From c50990c1c8830677b61f3a7f8e595d1f4decb3bc Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 19 Jan 2026 09:26:53 +0000 Subject: [PATCH 001/192] fix: ListTasks validation and serialization across all transports (#460) These fixes are needed for the TCK tests in https://github.com/a2aproject/a2a-tck/pull/93 - Fix pageSize=0 validation using hasPageSize() instead of zeroToNull - Add includingDefaultValueFields() for complete JSON responses - Validate enum UNRECOGNIZED, negative timestamps across transports - Support multiple timestamp/status formats in REST - Ensure consistent InvalidParamsError behavior across JSON-RPC, gRPC, REST --- .gitignore | 1 + .../database/jpa/JpaDatabaseTaskStore.java | 61 +++++++-------- .../a2a/server/tasks/InMemoryTaskStore.java | 33 +++++--- .../a2a/grpc/mapper/A2ACommonFieldMapper.java | 46 +++++++++-- .../grpc/mapper/ListTasksParamsMapper.java | 3 +- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 18 ++--- .../java/io/a2a/spec/ListTasksParams.java | 45 ++++++----- .../grpc/handler/GrpcHandlerTest.java | 49 ++++++++++++ .../jsonrpc/handler/JSONRPCHandlerTest.java | 28 +++++++ .../transport/rest/handler/RestHandler.java | 71 ++++++++++++----- .../rest/handler/RestHandlerTest.java | 78 +++++++++++++++++++ 11 files changed, 335 insertions(+), 98 deletions(-) diff --git a/.gitignore b/.gitignore index 82b1fecc1..c95331d77 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ pom.xml.releaseBackup pom.xml.versionsBackup release.properties .flattened-pom.xml +*.args # Eclipse .project 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 49dad1728..840773ea6 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 @@ -226,6 +226,25 @@ public ListTasksResult list(ListTasksParams params) { LOGGER.debug("Listing tasks with params: contextId={}, status={}, pageSize={}, pageToken={}", params.contextId(), params.status(), params.pageSize(), params.pageToken()); + // Parse pageToken once at the beginning + Instant tokenTimestamp = null; + String tokenId = null; + if (params.pageToken() != null && !params.pageToken().isEmpty()) { + String[] tokenParts = params.pageToken().split(":", 2); + if (tokenParts.length == 2) { + try { + long timestampMillis = Long.parseLong(tokenParts[0]); + tokenId = tokenParts[1]; + tokenTimestamp = Instant.ofEpochMilli(timestampMillis); + } catch (NumberFormatException e) { + throw new io.a2a.spec.InvalidParamsError(null, + "Invalid pageToken format: timestamp must be numeric milliseconds", null); + } + } else { + throw new io.a2a.spec.InvalidParamsError(null, "Invalid pageToken format: expected 'timestamp:id'", null); + } + } + // Build dynamic JPQL query with WHERE clauses for filtering StringBuilder queryBuilder = new StringBuilder("SELECT t FROM JpaTask t WHERE 1=1"); StringBuilder countQueryBuilder = new StringBuilder("SELECT COUNT(t) FROM JpaTask t WHERE 1=1"); @@ -249,18 +268,9 @@ public ListTasksResult list(ListTasksParams params) { } // Apply pagination cursor using keyset pagination for composite sort (timestamp DESC, id ASC) - // PageToken format: "timestamp_millis:taskId" (e.g., "1699999999000:task-123") - if (params.pageToken() != null && !params.pageToken().isEmpty()) { - String[] tokenParts = params.pageToken().split(":", 2); - if (tokenParts.length == 2) { - // Keyset pagination: get tasks where timestamp < tokenTimestamp OR (timestamp = tokenTimestamp AND id > tokenId) - // All tasks have timestamps (TaskStatus canonical constructor ensures this) - queryBuilder.append(" AND (t.statusTimestamp < :tokenTimestamp OR (t.statusTimestamp = :tokenTimestamp AND t.id > :tokenId))"); - } else { - // Legacy ID-only pageToken format is not supported with timestamp-based sorting - // Throw error to prevent incorrect pagination results - throw new io.a2a.spec.InvalidParamsError(null, "Invalid pageToken format: expected 'timestamp:id'", null); - } + if (tokenTimestamp != null) { + // Keyset pagination: get tasks where timestamp < tokenTimestamp OR (timestamp = tokenTimestamp AND id > tokenId) + queryBuilder.append(" AND (t.statusTimestamp < :tokenTimestamp OR (t.statusTimestamp = :tokenTimestamp AND t.id > :tokenId))"); } // Sort by status timestamp descending (most recent first), then by ID for stable ordering @@ -279,25 +289,9 @@ public ListTasksResult list(ListTasksParams params) { if (params.lastUpdatedAfter() != null) { query.setParameter("lastUpdatedAfter", params.lastUpdatedAfter()); } - if (params.pageToken() != null && !params.pageToken().isEmpty()) { - String[] tokenParts = params.pageToken().split(":", 2); - if (tokenParts.length == 2) { - // Parse keyset pagination parameters - try { - long timestampMillis = Long.parseLong(tokenParts[0]); - String tokenId = tokenParts[1]; - - // All tasks have timestamps (TaskStatus canonical constructor ensures this) - Instant tokenTimestamp = Instant.ofEpochMilli(timestampMillis); - query.setParameter("tokenTimestamp", tokenTimestamp); - query.setParameter("tokenId", tokenId); - } catch (NumberFormatException e) { - // Malformed timestamp in pageToken - throw new io.a2a.spec.InvalidParamsError(null, - "Invalid pageToken format: timestamp must be numeric milliseconds", null); - } - } - // Note: Legacy ID-only format already rejected in query building phase + if (tokenTimestamp != null) { + query.setParameter("tokenTimestamp", tokenTimestamp); + query.setParameter("tokenId", tokenId); } // Apply page size limit (+1 to check for next page) @@ -362,7 +356,10 @@ public ListTasksResult list(ListTasksParams params) { private Task transformTask(Task task, int historyLength, boolean includeArtifacts) { // Limit history if needed (keep most recent N messages) List history = task.history(); - if (historyLength > 0 && history != null && history.size() > historyLength) { + if (historyLength == 0) { + // When historyLength is 0, return empty history + history = List.of(); + } else if (historyLength > 0 && history != null && history.size() > historyLength) { history = history.subList(history.size() - historyLength, history.size()); } 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 d2d9362ca..f1243e272 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 @@ -90,18 +90,24 @@ public ListTasksResult list(ListTasksParams params) { int mid = left + (right - left) / 2; Task task = allFilteredTasks.get(mid); - // All tasks have timestamps (TaskStatus canonical constructor ensures this) - // Truncate to milliseconds for consistency with pageToken precision - java.time.Instant taskTimestamp = task.status().timestamp().toInstant() - .truncatedTo(java.time.temporal.ChronoUnit.MILLIS); - int timestampCompare = taskTimestamp.compareTo(tokenTimestamp); - - if (timestampCompare < 0 || (timestampCompare == 0 && task.id().compareTo(tokenId) > 0)) { - // This task is after the token, search left half - right = mid; - } else { - // This task is before or equal to token, search right half + java.time.Instant taskTimestamp = (task.status() != null && task.status().timestamp() != null) + ? task.status().timestamp().toInstant().truncatedTo(java.time.temporal.ChronoUnit.MILLIS) + : null; + + if (taskTimestamp == null) { + // Task with null timestamp is always "before" a token with a timestamp, as they are sorted last. + // So, we search in the right half. left = mid + 1; + } else { + int timestampCompare = taskTimestamp.compareTo(tokenTimestamp); + + if (timestampCompare < 0 || (timestampCompare == 0 && task.id().compareTo(tokenId) > 0)) { + // This task is after the token, search left half + right = mid; + } else { + // This task is before or equal to token, search right half + left = mid + 1; + } } } startIndex = left; @@ -144,7 +150,10 @@ public ListTasksResult list(ListTasksParams params) { private Task transformTask(Task task, int historyLength, boolean includeArtifacts) { // Limit history if needed (keep most recent N messages) List history = task.history(); - if (historyLength > 0 && history != null && history.size() > historyLength) { + if (historyLength == 0) { + // When historyLength is 0, return empty history + history = List.of(); + } else if (historyLength > 0 && history != null && history.size() > historyLength) { history = history.subList(history.size() - historyLength, history.size()); } 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 c3f031e97..723df2e53 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 @@ -285,7 +285,23 @@ default Map metadataFromProto(Struct struct) { */ @Named("zeroToNull") default Integer zeroToNull(int value) { - return value > 0 ? value : null; + return value != 0 ? value : null; + } + + /** + * Converts protobuf int to Integer, preserving all values including 0. + *

+ * Unlike zeroToNull, this method preserves 0 values, allowing compact constructor + * validation to catch invalid values (e.g., pageSize=0 must fail validation). + * For truly optional fields where 0 means "unset", use zeroToNull instead. + * Use this with {@code @Mapping(qualifiedByName = "intToIntegerOrNull")}. + * + * @param value the protobuf int value + * @return Integer (never null for primitive int input) + */ + @Named("intToIntegerOrNull") + default Integer intToIntegerOrNull(int value) { + return value; } /** @@ -337,13 +353,20 @@ default long instantToMillis(Instant instant) { * Converts protobuf milliseconds-since-epoch (int64) to domain Instant. *

* Returns null if input is 0 (protobuf default for unset field). + * Throws InvalidParamsError for negative values (invalid timestamps). * Use this with {@code @Mapping(qualifiedByName = "millisToInstant")}. * * @param millis milliseconds since epoch * @return domain Instant, or null if millis is 0 + * @throws InvalidParamsError if millis is negative */ @Named("millisToInstant") default Instant millisToInstant(long millis) { + if (millis < 0L) { + throw new InvalidParamsError(null, + "Timestamp must be a non-negative number of milliseconds since epoch, but got: " + millis, + null); + } return millis > 0L ? Instant.ofEpochMilli(millis) : null; } @@ -351,21 +374,32 @@ default Instant millisToInstant(long millis) { // Enum Conversions (handling UNSPECIFIED/UNKNOWN) // ======================================================================== /** - * Converts protobuf TaskState to domain TaskState, treating UNSPECIFIED/UNKNOWN as null. + * Converts protobuf TaskState to domain TaskState, treating UNSPECIFIED as null. *

- * Protobuf enums default to UNSPECIFIED (0 value) when unset. The domain may also have - * UNKNOWN for unparseable values. Both should map to null for optional fields. + * Protobuf enums default to UNSPECIFIED (0 value) when unset, which maps to null for optional fields. + * However, UNRECOGNIZED (invalid enum values from JSON) throws InvalidParamsError for proper validation. * Use this with {@code @Mapping(qualifiedByName = "taskStateOrNull")}. * * @param state the protobuf TaskState - * @return domain TaskState or null if UNSPECIFIED/UNKNOWN + * @return domain TaskState or null if UNSPECIFIED + * @throws InvalidParamsError if state is UNRECOGNIZED (invalid enum value) */ @Named("taskStateOrNull") default io.a2a.spec.TaskState taskStateOrNull(io.a2a.grpc.TaskState state) { if (state == null || state == io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED) { return null; } + // Reject invalid enum values (e.g., "INVALID_STATUS" from JSON) + if (state == io.a2a.grpc.TaskState.UNRECOGNIZED) { + String validStates = java.util.Arrays.stream(io.a2a.spec.TaskState.values()) + .filter(s -> s != io.a2a.spec.TaskState.UNKNOWN) + .map(Enum::name) + .collect(java.util.stream.Collectors.joining(", ")); + throw new InvalidParamsError(null, + "Invalid task state value. Must be one of: " + validStates, + null); + } io.a2a.spec.TaskState result = TaskStateMapper.INSTANCE.fromProto(state); - return result == io.a2a.spec.TaskState.UNKNOWN ? null : result; + return result; } } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java index 05d45d68a..3e666a8e5 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java @@ -38,7 +38,8 @@ public interface ListTasksParamsMapper { */ @Mapping(target = "contextId", source = "contextId", qualifiedByName = "emptyToNull") @Mapping(target = "status", source = "status", qualifiedByName = "taskStateOrNull") - @Mapping(target = "pageSize", source = "pageSize", qualifiedByName = "zeroToNull") + // pageSize: Check if field is set using hasPageSize() to distinguish unset (null) from explicit 0 (validation error) + @Mapping(target = "pageSize", expression = "java(request.hasPageSize() ? request.getPageSize() : null)") @Mapping(target = "pageToken", source = "pageToken", qualifiedByName = "emptyToNull") @Mapping(target = "historyLength", source = "historyLength", qualifiedByName = "zeroToNull") @Mapping(target = "lastUpdatedAfter", source = "lastUpdatedAfter", qualifiedByName = "millisToInstant") 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 ad46a8f38..c7d1df72f 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 @@ -458,14 +458,12 @@ private static JsonProcessingException convertProtoBufExceptionToJsonProcessingE return new JsonProcessingException(ERROR_MESSAGE.formatted("unknown parsing error")); } - // Extract field name if present in error message - String prefix = "Cannot find field: "; - if (message.contains(prefix)) { - return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(message.substring(message.indexOf(prefix) + prefix.length())), id); - } - prefix = "Invalid value for"; - if (message.contains(prefix)) { - return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(message.substring(message.indexOf(prefix) + prefix.length())), id); + // Extract field name if present in error message - check common prefixes + String[] prefixes = {"Cannot find field: ", "Invalid value for", "Invalid enum value:"}; + for (String prefix : prefixes) { + if (message.contains(prefix)) { + return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(message.substring(message.indexOf(prefix) + prefix.length())), id); + } } // Try to extract specific error details using regex patterns @@ -548,7 +546,7 @@ public static String toJsonRPCRequest(@Nullable String requestId, String method, output.name("method").value(method); } if (payload != null) { - String resultValue = JsonFormat.printer().omittingInsignificantWhitespace().print(payload); + String resultValue = JsonFormat.printer().includingDefaultValueFields().omittingInsignificantWhitespace().print(payload); output.name("params").jsonValue(resultValue); } output.endObject(); @@ -571,7 +569,7 @@ public static String toJsonRPCResultResponse(Object requestId, com.google.protob output.name("id").value(number.longValue()); } } - String resultValue = JsonFormat.printer().omittingInsignificantWhitespace().print(builder); + String resultValue = JsonFormat.printer().includingDefaultValueFields().omittingInsignificantWhitespace().print(builder); output.name("result").jsonValue(resultValue); output.endObject(); return result.toString(); diff --git a/spec/src/main/java/io/a2a/spec/ListTasksParams.java b/spec/src/main/java/io/a2a/spec/ListTasksParams.java index 6813dcf45..6fb9ff5d1 100644 --- a/spec/src/main/java/io/a2a/spec/ListTasksParams.java +++ b/spec/src/main/java/io/a2a/spec/ListTasksParams.java @@ -2,7 +2,6 @@ import java.time.Instant; -import io.a2a.util.Assert; import org.jspecify.annotations.Nullable; /** @@ -27,9 +26,12 @@ public record ListTasksParams( @Nullable Boolean includeArtifacts, String tenant ) { + private static final int MIN_PAGE_SIZE = 1; + private static final int MAX_PAGE_SIZE = 100; + private static final int DEFAULT_PAGE_SIZE = 50; /** * Compact constructor for validation. - * Validates that the tenant parameter is not null. + * Validates that the tenant parameter is not null and parameters are within valid ranges. * * @param contextId filter by context ID * @param status filter by task status @@ -39,9 +41,24 @@ public record ListTasksParams( * @param lastUpdatedAfter filter by last update timestamp * @param includeArtifacts whether to include artifacts * @param tenant the tenant identifier + * @throws InvalidParamsError if tenant is null or if pageSize or historyLength are out of valid range */ public ListTasksParams { - Assert.checkNotNullParam("tenant", tenant); + if (tenant == null) { + throw new InvalidParamsError(null, "Parameter 'tenant' may not be null", null); + } + + // Validate pageSize (1-100) + if (pageSize != null && (pageSize < MIN_PAGE_SIZE || pageSize > MAX_PAGE_SIZE)) { + throw new InvalidParamsError(null, + "pageSize must be between " + MIN_PAGE_SIZE + " and " + MAX_PAGE_SIZE + ", got: " + pageSize, null); + } + + // Validate historyLength (>= 0) + if (historyLength != null && historyLength < 0) { + throw new InvalidParamsError(null, + "historyLength must be non-negative, got: " + historyLength, null); + } } /** * Default constructor for listing all tasks. @@ -61,33 +78,23 @@ public ListTasksParams(Integer pageSize, String pageToken) { } /** - * Validates and returns the effective page size (between 1 and 100, defaults to 50). + * Returns the effective page size (defaults to 50 if not specified). + * Values are validated in the constructor to be within the range [1, 100]. * * @return the effective page size */ public int getEffectivePageSize() { - if (pageSize == null) { - return 50; - } - if (pageSize < 1) { - return 1; - } - if (pageSize > 100) { - return 100; - } - return pageSize; + return pageSize != null ? pageSize : DEFAULT_PAGE_SIZE; } /** - * Returns the effective history length (non-negative, defaults to 0). + * Returns the effective history length (defaults to 0 if not specified). + * Values are validated in the constructor to be non-negative. * * @return the effective history length */ public int getEffectiveHistoryLength() { - if (historyLength == null || historyLength < 0) { - return 0; - } - return historyLength; + return historyLength != null ? historyLength : 0; } /** 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 77a2c955f..a3ce7ca2a 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 @@ -21,6 +21,8 @@ import io.a2a.grpc.GetTaskRequest; import io.a2a.grpc.ListTaskPushNotificationConfigRequest; import io.a2a.grpc.ListTaskPushNotificationConfigResponse; +import io.a2a.grpc.ListTasksRequest; +import io.a2a.grpc.ListTasksResponse; import io.a2a.grpc.Message; import io.a2a.grpc.Part; import io.a2a.grpc.PushNotificationConfig; @@ -1209,6 +1211,53 @@ private void assertGrpcError(StreamRecorder streamRecorder, Status.Code e Assertions.assertTrue(streamRecorder.getValues().isEmpty()); } + @Test + public void testListTasksNegativeTimestampReturnsInvalidArgument() { + TestGrpcHandler handler = new TestGrpcHandler(CARD, requestHandler, internalExecutor); + StreamRecorder responseObserver = StreamRecorder.create(); + + // Negative timestamp should trigger validation error + ListTasksRequest request = ListTasksRequest.newBuilder() + .setLastUpdatedAfter(-1L) + .setTenant("") + .build(); + + handler.listTasks(request, responseObserver); + + // Should return error with INVALID_ARGUMENT status + Assertions.assertTrue(responseObserver.getError() != null); + StatusRuntimeException error = (StatusRuntimeException) responseObserver.getError(); + assertEquals(Status.INVALID_ARGUMENT.getCode(), error.getStatus().getCode()); + } + + @Test + public void testListTasksEmptyResultIncludesAllFields() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, requestHandler, internalExecutor); + StreamRecorder responseObserver = StreamRecorder.create(); + + // Query for a context that doesn't exist - should return empty result + ListTasksRequest request = ListTasksRequest.newBuilder() + .setContextId("nonexistent-context-id") + .setTenant("") + .build(); + + handler.listTasks(request, responseObserver); + + // Should succeed with empty result + Assertions.assertNull(responseObserver.getError()); + List responses = responseObserver.getValues(); + assertEquals(1, responses.size()); + + ListTasksResponse response = responses.get(0); + // Verify all fields are present (even if empty/default) + Assertions.assertNotNull(response.getTasksList(), "tasks field should not be null"); + assertEquals(0, response.getTasksList().size(), "tasks should be empty list"); + assertEquals(0, response.getTotalSize(), "totalSize should be 0"); + assertEquals(0, response.getPageSize(), "pageSize should be 0"); + // nextPageToken will be empty string for empty results (protobuf default) + Assertions.assertNotNull(response.getNextPageToken()); + } + private static class TestGrpcHandler extends GrpcHandler { private final AgentCard card; private final RequestHandler handler; 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 a55233adb..3436a34b1 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 @@ -30,12 +30,15 @@ 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.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.ListTasksRequest; +import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; @@ -56,7 +59,9 @@ import io.a2a.spec.Event; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InternalError; +import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; +import io.a2a.spec.ListTasksParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; @@ -1959,4 +1964,27 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { assertNull(response.getError()); Assertions.assertSame(message, response.getResult()); } + + @Test + public void testListTasksEmptyResultIncludesAllFields() { + JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); + + // Query for a context that doesn't exist - should return empty result + ListTasksParams params = ListTasksParams.builder() + .contextId("nonexistent-context-id") + .tenant("") + .build(); + ListTasksRequest request = new ListTasksRequest("1", params); + ListTasksResponse response = handler.onListTasks(request, callContext); + + // Should return success with all fields present (not null) + assertNull(response.getError()); + ListTasksResult result = response.getResult(); + Assertions.assertNotNull(result); + Assertions.assertNotNull(result.tasks(), "tasks field should not be null"); + assertEquals(0, result.tasks().size(), "tasks should be empty list"); + assertEquals(0, result.totalSize(), "totalSize should be 0"); + assertEquals(0, result.pageSize(), "pageSize should be 0"); + // nextPageToken can be null for empty results + } } 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 87e57f415..4d9a9667d 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 @@ -69,6 +69,7 @@ public class RestHandler { private static final Logger log = Logger.getLogger(RestHandler.class.getName()); + private static final String TASK_STATE_PREFIX = "TASK_STATE_"; // Fields set by constructor injection cannot be final. We need a noargs constructor for // Jakarta compatibility, and it seems that making fields set by constructor injection @@ -219,21 +220,41 @@ public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String s paramsBuilder.contextId(contextId); } if (status != null) { + TaskState taskState = null; + + // Try JSON format first (e.g., "working", "completed") try { - paramsBuilder.status(TaskState.fromString(status)); + taskState = TaskState.fromString(status); } catch (IllegalArgumentException e) { - try { - paramsBuilder.status(TaskState.valueOf(status)); - } catch (IllegalArgumentException valueOfError) { - String validStates = Arrays.stream(TaskState.values()) - .map(TaskState::asString) - .collect(Collectors.joining(", ")); - Map errorData = new HashMap<>(); - errorData.put("parameter", "status"); - errorData.put("reason", "Must be one of: " + validStates); - throw new InvalidParamsError(null, "Invalid params", errorData); + // Try protobuf enum format (e.g., "TASK_STATE_WORKING") + if (status.startsWith(TASK_STATE_PREFIX)) { + String enumName = status.substring(TASK_STATE_PREFIX.length()); + try { + taskState = TaskState.valueOf(enumName); + } catch (IllegalArgumentException protoError) { + // Fall through to error handling below + } + } else { + // Try enum constant name directly (e.g., "WORKING") + try { + taskState = TaskState.valueOf(status); + } catch (IllegalArgumentException valueOfError) { + // Fall through to error handling below + } } } + + if (taskState == null) { + String validStates = Arrays.stream(TaskState.values()) + .map(TaskState::asString) + .collect(Collectors.joining(", ")); + Map errorData = new HashMap<>(); + errorData.put("parameter", "status"); + errorData.put("reason", "Must be one of: " + validStates); + throw new InvalidParamsError(null, "Invalid params", errorData); + } + + paramsBuilder.status(taskState); } if (pageSize != null) { paramsBuilder.pageSize(pageSize); @@ -247,12 +268,25 @@ public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String s paramsBuilder.tenant(tenant); if (lastUpdatedAfter != null) { try { - paramsBuilder.lastUpdatedAfter(Instant.parse(lastUpdatedAfter)); - } catch (DateTimeParseException e) { - Map errorData = new HashMap<>(); - errorData.put("parameter", "lastUpdatedAfter"); - errorData.put("reason", "Must be valid ISO-8601 timestamp"); - throw new InvalidParamsError(null, "Invalid params", errorData); + // Try parsing as Unix milliseconds first (integer) + long millis = Long.parseLong(lastUpdatedAfter); + if (millis < 0L) { + Map errorData = new HashMap<>(); + errorData.put("parameter", "lastUpdatedAfter"); + errorData.put("reason", "Must be a non-negative timestamp value, got: " + millis); + throw new InvalidParamsError(null, "Invalid params", errorData); + } + paramsBuilder.lastUpdatedAfter(Instant.ofEpochMilli(millis)); + } catch (NumberFormatException nfe) { + // Fall back to ISO-8601 format + try { + paramsBuilder.lastUpdatedAfter(Instant.parse(lastUpdatedAfter)); + } catch (DateTimeParseException e) { + Map errorData = new HashMap<>(); + errorData.put("parameter", "lastUpdatedAfter"); + errorData.put("reason", "Must be valid Unix milliseconds or ISO-8601 timestamp"); + throw new InvalidParamsError(null, "Invalid params", errorData); + } } } if (includeArtifacts != null) { @@ -338,7 +372,8 @@ private void validate(String json) { private HTTPRestResponse createSuccessResponse(int statusCode, com.google.protobuf.Message.Builder builder) { try { - String jsonBody = JsonFormat.printer().print(builder); + // Include default value fields to ensure empty arrays, zeros, etc. are present in JSON + String jsonBody = JsonFormat.printer().includingDefaultValueFields().print(builder); return new HTTPRestResponse(statusCode, "application/json", jsonBody); } catch (InvalidProtocolBufferException e) { return createErrorResponse(new InternalError("Failed to serialize response: " + e.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 1ed1492e1..a2e6ef6e9 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 @@ -879,4 +879,82 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { Assertions.assertEquals("application/json", response.getContentType()); Assertions.assertNotNull(response.getBody()); } + + @Test + public void testListTasksNegativeTimestampReturns422() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + + // Negative timestamp should return 422 (Invalid params) + RestHandler.HTTPRestResponse response = handler.listTasks(null, null, null, null, + null, "-1", null, "", callContext); + + Assertions.assertEquals(422, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); + } + + @Test + public void testListTasksUnixMillisecondsTimestamp() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK); + + // Unix milliseconds timestamp should be accepted + String timestampMillis = String.valueOf(System.currentTimeMillis() - 10000); + RestHandler.HTTPRestResponse response = handler.listTasks(null, null, null, null, + null, timestampMillis, null, "", callContext); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains("tasks")); + } + + @Test + public void testListTasksProtobufEnumStatus() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK); + + // Protobuf enum format (TASK_STATE_SUBMITTED) should be accepted + RestHandler.HTTPRestResponse response = handler.listTasks(null, "TASK_STATE_SUBMITTED", null, null, + null, null, null, "", callContext); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); + } + + @Test + public void testListTasksEnumConstantStatus() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK); + + // Enum constant format (SUBMITTED) should be accepted + RestHandler.HTTPRestResponse response = handler.listTasks(null, "SUBMITTED", null, null, + null, null, null, "", callContext); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); + } + + @Test + public void testListTasksEmptyResultIncludesAllFields() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + + // Query for a context that doesn't exist - should return empty result with all fields + RestHandler.HTTPRestResponse response = handler.listTasks("nonexistent-context-id", null, null, null, + null, null, null, "", callContext); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + + String body = response.getBody(); + // Verify all required fields are present (not missing) + Assertions.assertTrue(body.contains("\"tasks\""), "Response should contain tasks field"); + Assertions.assertTrue(body.contains("\"totalSize\""), "Response should contain totalSize field"); + Assertions.assertTrue(body.contains("\"pageSize\""), "Response should contain pageSize field"); + Assertions.assertTrue(body.contains("\"nextPageToken\""), "Response should contain nextPageToken field"); + // Verify empty array, not null + Assertions.assertTrue(body.contains("\"tasks\":[]") || body.contains("\"tasks\": []"), + "tasks should be empty array"); + } } From 41247716ed9772af01d8dbf95584b54974246fb1 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 19 Jan 2026 13:29:08 +0000 Subject: [PATCH 002/192] fix: Make historyLength consistent with pageSize in mapper (#600) --- .../main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java index 3e666a8e5..cdb501d9a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java @@ -41,7 +41,8 @@ public interface ListTasksParamsMapper { // pageSize: Check if field is set using hasPageSize() to distinguish unset (null) from explicit 0 (validation error) @Mapping(target = "pageSize", expression = "java(request.hasPageSize() ? request.getPageSize() : null)") @Mapping(target = "pageToken", source = "pageToken", qualifiedByName = "emptyToNull") - @Mapping(target = "historyLength", source = "historyLength", qualifiedByName = "zeroToNull") + // historyLength: Check if field is set using hasHistoryLength() for consistency with pageSize + @Mapping(target = "historyLength", expression = "java(request.hasHistoryLength() ? request.getHistoryLength() : null)") @Mapping(target = "lastUpdatedAfter", source = "lastUpdatedAfter", qualifiedByName = "millisToInstant") @Mapping(target = "includeArtifacts", source = "includeArtifacts", qualifiedByName = "falseToNull") io.a2a.spec.ListTasksParams fromProto(ListTasksRequest request); From 434b1becdf8fefc562185ab915ed351a0c70a1b8 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 19 Jan 2026 16:29:03 +0000 Subject: [PATCH 003/192] chore: Prepare 1.0.0.Alpha1 release (#602) --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../java/io/a2a/examples/helloworld/HelloWorldRunner.java | 4 ++-- examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/push-notification-config-store-database-jpa/pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../queue-manager-replicated/replication-mp-reactive/pom.xml | 2 +- extras/queue-manager-replicated/tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- extras/queue-manager-replicated/tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 44 files changed, 45 insertions(+), 45 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 809a3a6a9..d1d84ddee 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 1c09486fe..8ad8d20ac 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index 37ecc9d25..421b622d2 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index dd95cd7e4..4d3adb723 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index bd16914a6..ae353f327 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 2c184a7fe..1487b94a3 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 0cbadd8ab..e6fa67b17 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index 2c682c888..ae0914821 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index ca1005e13..a32b8a516 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index f224e422f..7c7f20c2f 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-java-sdk-common diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index 4db8c96d8..f7fb0168f 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index 0ac460bc5..cf2925b0d 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java index 0c19ffad7..ad29c96e0 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java @@ -1,6 +1,6 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha1-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha1-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha1 +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha1 //SOURCES HelloWorldClient.java /** diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index ddb562e60..d7d9e6bcf 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 584690dce..00ce3e013 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index 29cedf9c5..13e298723 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 59bbf1141..071b1beb6 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 0258dccc8..f3e35c91e 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 47e8c8bc0..45c7542a8 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index ba7a95b1d..42d58a0c4 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 8a1c461c4..919bf7445 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index 52ff3c5cb..98255923c 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index b6caa6a08..6c043636a 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index 391dc16be..66f2d7e3d 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index 67e7ee470..fac72e33b 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index abd49a4c8..108d25f83 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index 72a4451ac..26775faf6 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index b0597ffa2..d8c0c1f49 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index e18e562a9..777c58210 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 62d7da6cd..42338fd1e 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index ea8e7bae0..e1e41c426 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index 9a712913a..5676f3c15 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index 3f3f26b7d..73b1c84a3 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index 0c131756e..654025911 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index d711c2773..206cf50a2 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index 6c45cb659..91df7052c 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index fb9a3fdfa..686a56325 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index 9270b2751..4a850fb31 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index 2f04f5c2a..e55d56f23 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-java-sdk-spec diff --git a/tck/pom.xml b/tck/pom.xml index 9b41e49e3..25ff2fdc6 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 a2a-tck-server diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index ff0298841..3529400f0 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index e1c7ccf05..52731b453 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index 59498d8d7..5b0b68616 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 685de4977..f6bda74b4 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1-SNAPSHOT + 1.0.0.Alpha1 ../../pom.xml a2a-java-sdk-transport-rest From 7059c125d11af8a2f1bcddda263e05e967c563d3 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 19 Jan 2026 17:04:20 +0000 Subject: [PATCH 004/192] chore: Next is 1.0.0.Alpha2 (#603) --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../java/io/a2a/examples/helloworld/HelloWorldRunner.java | 4 ++-- examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/push-notification-config-store-database-jpa/pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../queue-manager-replicated/replication-mp-reactive/pom.xml | 2 +- extras/queue-manager-replicated/tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- extras/queue-manager-replicated/tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 44 files changed, 45 insertions(+), 45 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index d1d84ddee..7cf7a54a8 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 8ad8d20ac..f25631bbd 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index 421b622d2..963dfc8b5 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 4d3adb723..1c241831d 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index ae353f327..ecbaaf454 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 1487b94a3..32e077cab 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index e6fa67b17..4437d4fe1 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index ae0914821..ad4a14d56 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index a32b8a516..abba14137 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index 7c7f20c2f..c83d33bf2 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-java-sdk-common diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index f7fb0168f..d71434b81 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index cf2925b0d..a9e0cf0d4 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java index ad29c96e0..138f7e4f7 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java @@ -1,6 +1,6 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha1 -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha1 +//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha2-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha2-SNAPSHOT //SOURCES HelloWorldClient.java /** diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index d7d9e6bcf..589e9c30d 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 00ce3e013..4b0ea1564 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index 13e298723..55bb98e71 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 071b1beb6..2bb4f1662 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index f3e35c91e..b944295b3 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 45c7542a8..91646ca0f 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 42d58a0c4..7ae399aff 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 919bf7445..72d284cba 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index 98255923c..31ea048fa 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index 6c043636a..5f7dc9812 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index 66f2d7e3d..40c45a964 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index fac72e33b..b45243e7f 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index 108d25f83..a269f6c48 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index 26775faf6..c01e2c51e 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index d8c0c1f49..b98aa7bf9 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index 777c58210..af4dcb855 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 42338fd1e..3b82074e1 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index e1e41c426..dbbbf42cf 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index 5676f3c15..adf31c903 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index 73b1c84a3..e05266922 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index 654025911..b12a68153 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 206cf50a2..37252458e 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index 91df7052c..318c85e6c 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index 686a56325..9c3d594fe 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index 4a850fb31..b602f7613 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index e55d56f23..d79c4fa07 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-java-sdk-spec diff --git a/tck/pom.xml b/tck/pom.xml index 25ff2fdc6..39c289c72 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT a2a-tck-server diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index 3529400f0..fc5bbe52a 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index 52731b453..0c652c1c3 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index 5b0b68616..bb551b930 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index f6bda74b4..3722ae44d 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha1 + 1.0.0.Alpha2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-rest From 99db49f22a9f4f8ecdd394e668c1d3a0fe63a144 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Fri, 23 Jan 2026 12:09:24 +0100 Subject: [PATCH 005/192] feat!: update a2a.proto 0572953 (#606) based on commit https://github.com/a2aproject/A2A/commit/057295311b8ddda63bdda56c82a694c76d307e37 spec-grpc module has been regenerated from the updated a2a.proto Key changes: * Agent card * extendedAgentCard is not specified by capabilities (instead of `supportsExtendedAgentCard` field) * protocolVersions is a list (instead of a single `protocolVersion`) * SendMessage * `msg` field is now named `message` * ListTask * timestamp is now named statusTimestampAfter instead of `lastUpdatedAfter` * OAuthFlows * `deviceCode` has been added, `implicit` & `password` have been removed * AuthorizationCodeOAuthFlow * new `pkce_required` boolean field --------- Signed-off-by: Jeff Mesnil --- .../java/io/a2a/client/AbstractClient.java | 18 +- .../src/main/java/io/a2a/client/Client.java | 15 +- .../AuthenticationAuthorizationTest.java | 2 +- .../java/io/a2a/client/ClientBuilderTest.java | 2 +- .../transport/grpc/EventStreamObserver.java | 4 +- .../transport/grpc/GrpcErrorMapper.java | 4 +- .../client/transport/grpc/GrpcTransport.java | 32 +- .../transport/grpc/GrpcErrorMapperTest.java | 12 +- .../transport/jsonrpc/JSONRPCTransport.java | 32 +- .../jsonrpc/JSONRPCTransportTest.java | 96 +- .../transport/jsonrpc/JsonMessages.java | 18 +- .../transport/rest/RestErrorMapper.java | 5 +- .../client/transport/rest/RestTransport.java | 22 +- .../rest/sse/RestSSEEventListener.java | 4 +- .../transport/rest/RestTransportTest.java | 2 +- .../client/transport/spi/ClientTransport.java | 6 +- .../cloud/CloudAgentCardProducer.java | 2 +- .../examples/cloud/A2ACloudExampleClient.java | 8 +- .../examples/helloworld/HelloWorldClient.java | 6 +- .../helloworld/AgentCardProducer.java | 2 +- .../MultiInstanceReplicationAgentCards.java | 2 +- .../ReplicationTestAgentCardProducer.java | 2 +- .../database/jpa/JpaDatabaseTaskStore.java | 16 +- .../java/io/a2a/client/http/JsonMessages.java | 3 +- .../jsonrpc/common/wrappers/A2AResponse.java | 2 +- ....java => GetExtendedAgentCardRequest.java} | 25 +- ...java => GetExtendedAgentCardResponse.java} | 16 +- .../wrappers/NonStreamingJSONRPCRequest.java | 2 +- .../json/SecuritySchemeSerializationTest.java | 65 - .../grpc/quarkus/QuarkusGrpcHandler.java | 20 + .../server/apps/quarkus/A2AServerRoutes.java | 13 +- .../apps/quarkus/A2AServerRoutesTest.java | 18 +- .../DefaultRequestHandler.java | 18 +- .../a2a/server/tasks/InMemoryTaskStore.java | 4 +- .../server/version/A2AVersionValidator.java | 40 +- .../AbstractA2ARequestHandlerTest.java | 2 +- .../version/A2AVersionValidatorTest.java | 28 +- spec-grpc/src/main/java/io/a2a/grpc/A2A.java | 466 ++--- .../java/io/a2a/grpc/AgentCapabilities.java | 113 + .../a2a/grpc/AgentCapabilitiesOrBuilder.java | 19 + .../src/main/java/io/a2a/grpc/AgentCard.java | 1856 +++++------------ .../java/io/a2a/grpc/AgentCardOrBuilder.java | 194 +- .../a2a/grpc/AuthorizationCodeOAuthFlow.java | 87 + .../AuthorizationCodeOAuthFlowOrBuilder.java | 11 + ...AuthFlow.java => DeviceCodeOAuthFlow.java} | 404 ++-- ...java => DeviceCodeOAuthFlowOrBuilder.java} | 42 +- .../main/java/io/a2a/grpc/GetTaskRequest.java | 30 +- .../io/a2a/grpc/GetTaskRequestOrBuilder.java | 10 +- .../java/io/a2a/grpc/ImplicitOAuthFlow.java | 1027 --------- .../a2a/grpc/ImplicitOAuthFlowOrBuilder.java | 106 - .../java/io/a2a/grpc/ListTasksRequest.java | 267 ++- .../a2a/grpc/ListTasksRequestOrBuilder.java | 29 +- .../src/main/java/io/a2a/grpc/Message.java | 26 +- .../src/main/java/io/a2a/grpc/OAuthFlows.java | 484 +---- .../java/io/a2a/grpc/OAuthFlowsOrBuilder.java | 49 +- .../io/a2a/grpc/SendMessageConfiguration.java | 30 +- .../SendMessageConfigurationOrBuilder.java | 10 +- .../java/io/a2a/grpc/SendMessageRequest.java | 168 +- .../a2a/grpc/SendMessageRequestOrBuilder.java | 16 +- .../java/io/a2a/grpc/SendMessageResponse.java | 120 +- .../grpc/SendMessageResponseOrBuilder.java | 16 +- .../main/java/io/a2a/grpc/StreamResponse.java | 120 +- .../io/a2a/grpc/StreamResponseOrBuilder.java | 16 +- .../a2a/grpc/mapper/A2ACommonFieldMapper.java | 38 + .../grpc/mapper/AgentCapabilitiesMapper.java | 1 + .../io/a2a/grpc/mapper/AgentCardMapper.java | 4 - .../AuthorizationCodeOAuthFlowMapper.java | 1 + .../grpc/mapper/ImplicitOAuthFlowMapper.java | 18 - .../grpc/mapper/ListTasksParamsMapper.java | 4 +- .../grpc/mapper/MessageSendParamsMapper.java | 6 +- .../io/a2a/grpc/mapper/OAuthFlowsMapper.java | 5 +- .../grpc/mapper/PasswordOAuthFlowMapper.java | 18 - .../a2a/grpc/mapper/StreamResponseMapper.java | 6 +- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 20 +- .../java/io/a2a/grpc/utils/ProtoUtils.java | 6 +- spec-grpc/src/main/proto/a2a.proto | 106 +- .../grpc/mapper/StreamResponseMapperTest.java | 10 +- .../java/io/a2a/grpc/utils/ToProtoTest.java | 11 +- .../main/java/io/a2a/spec/A2AErrorCodes.java | 4 +- .../java/io/a2a/spec/AgentCapabilities.java | 21 +- spec/src/main/java/io/a2a/spec/AgentCard.java | 46 +- .../a2a/spec/AuthorizationCodeOAuthFlow.java | 4 +- .../java/io/a2a/spec/DeviceCodeOAuthFlow.java | 37 + ... ExtendedAgentCardNotConfiguredError.java} | 12 +- .../java/io/a2a/spec/ImplicitOAuthFlow.java | 40 - .../java/io/a2a/spec/ListTasksParams.java | 18 +- .../src/main/java/io/a2a/spec/OAuthFlows.java | 28 +- .../java/io/a2a/spec/PasswordOAuthFlow.java | 40 - .../io/a2a/spec/VersionNotSupportedError.java | 2 +- .../io/a2a/tck/server/AgentCardProducer.java | 2 +- .../apps/common/AbstractA2AServerTest.java | 16 +- .../server/apps/common/AgentCardProducer.java | 11 +- .../transport/grpc/handler/GrpcHandler.java | 14 +- .../grpc/handler/GrpcHandlerTest.java | 56 +- .../jsonrpc/handler/JSONRPCHandler.java | 25 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 21 +- .../transport/rest/handler/RestHandler.java | 20 +- .../rest/handler/RestHandlerTest.java | 8 +- 98 files changed, 2486 insertions(+), 4477 deletions(-) rename jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/{GetAuthenticatedExtendedCardRequest.java => GetExtendedAgentCardRequest.java} (73%) rename jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/{GetAuthenticatedExtendedCardResponse.java => GetExtendedAgentCardResponse.java} (69%) rename spec-grpc/src/main/java/io/a2a/grpc/{PasswordOAuthFlow.java => DeviceCodeOAuthFlow.java} (69%) rename spec-grpc/src/main/java/io/a2a/grpc/{PasswordOAuthFlowOrBuilder.java => DeviceCodeOAuthFlowOrBuilder.java} (63%) delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/ImplicitOAuthFlowMapper.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/PasswordOAuthFlowMapper.java create mode 100644 spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java rename spec/src/main/java/io/a2a/spec/{ExtendedCardNotConfiguredError.java => ExtendedAgentCardNotConfiguredError.java} (78%) delete mode 100644 spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java delete mode 100644 spec/src/main/java/io/a2a/spec/PasswordOAuthFlow.java 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 75fe48956..5d2785386 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java @@ -384,23 +384,23 @@ public abstract void resubscribe(@NonNull TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException; /** - * Retrieve the AgentCard. + * Retrieve the extended AgentCard. * - * @return the AgentCard - * @throws A2AClientException if retrieving the agent card fails for any reason + * @return the extended AgentCard + * @throws A2AClientException if retrieving the extended agent card fails for any reason */ - public AgentCard getAgentCard() throws A2AClientException { - return getAgentCard(null); + public AgentCard getExtendedAgentCard() throws A2AClientException { + return getExtendedAgentCard(null); } /** - * Retrieve the AgentCard. + * Retrieve the extended AgentCard. * * @param context optional client call context for the request (may be {@code null}) - * @return the AgentCard - * @throws A2AClientException if retrieving the agent card fails for any reason + * @return the extended AgentCard + * @throws A2AClientException if retrieving the extended agent card fails for any reason */ - public abstract AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2AClientException; + public abstract AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException; /** * Close the transport and release any associated resources. 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 9976133e5..117351098 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -592,27 +592,28 @@ public void resubscribe(@NonNull TaskIdParams request, } /** - * Retrieve the agent's current agent card. + * Retrieve the agent's extended agent card. *

- * This method fetches the latest agent card from the agent. The card may have changed since + * This method fetches the extended agent card from the agent (if the extendedAgentCard capability is supported). + * The card may have changed since * client construction (e.g., new skills added, capabilities updated). The client's internal * reference is updated to the newly retrieved card. *

* Example: *

{@code
-     * AgentCard updatedCard = client.getAgentCard(null);
+     * AgentCard updatedCard = client.getExtendedAgentCard(null);
      * System.out.println("Agent version: " + updatedCard.version());
      * System.out.println("Skills: " + updatedCard.skills().size());
      * }
* * @param context custom call context for request interceptors (optional) - * @return the agent's current agent card - * @throws A2AClientException if the agent card cannot be retrieved + * @return the agent's extended agent card + * @throws A2AClientException if the extended agent card cannot be retrieved * @see AgentCard */ @Override - public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - agentCard = clientTransport.getAgentCard(context); + public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { + agentCard = clientTransport.getExtendedAgentCard(context); return agentCard; } diff --git a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java b/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java index 0294b3dc4..58b528881 100644 --- a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java +++ b/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java @@ -90,7 +90,7 @@ public void setUp() { .description("Test skill") .tags(Collections.singletonList("test")) .build())) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .supportedInterfaces(java.util.Arrays.asList( new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_URL), new AgentInterface(TransportProtocol.HTTP_JSON.asString(), AGENT_URL), diff --git a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java index 2c95c2619..56eb7560d 100644 --- a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java +++ b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java @@ -42,7 +42,7 @@ public class ClientBuilderTest { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .supportedInterfaces(List.of( new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))) .build(); 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 d77b81824..0c928bd75 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 @@ -25,8 +25,8 @@ public EventStreamObserver(Consumer eventHandler, Consumer interceptors; - private AgentCard agentCard; + private final AgentCard agentCard; private final String agentTenant; public GrpcTransport(Channel channel, AgentCard agentCard) { @@ -104,8 +106,8 @@ public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallCont try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); io.a2a.grpc.SendMessageResponse response = stubWithMetadata.sendMessage(sendMessageRequest); - if (response.hasMsg()) { - return FromProto.message(response.getMsg()); + if (response.hasMessage()) { + return FromProto.message(response.getMessage()); } else if (response.hasTask()) { return FromProto.task(response.getTask()); } else { @@ -195,8 +197,12 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo if (request.historyLength() != null) { requestBuilder.setHistoryLength(request.historyLength()); } - if (request.lastUpdatedAfter() != null) { - requestBuilder.setLastUpdatedAfter(request.lastUpdatedAfter().toEpochMilli()); + if (request.statusTimestampAfter() != null) { + requestBuilder.setStatusTimestampAfter( + com.google.protobuf.Timestamp.newBuilder() + .setSeconds(request.statusTimestampAfter().getEpochSecond()) + .setNanos(request.statusTimestampAfter().getNano()) + .build()); } if (request.includeArtifacts() != null) { requestBuilder.setIncludeArtifacts(request.includeArtifacts()); @@ -344,9 +350,19 @@ private MessageSendParams createRequestWithTenant(MessageSendParams request) { } @Override - public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - // TODO: Determine how to handle retrieving the authenticated extended agent card - return agentCard; + public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { + GetExtendedAgentCardRequest request = GetExtendedAgentCardRequest.newBuilder() + .build(); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, request, agentCard, context); + + try { + A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); + io.a2a.grpc.AgentCard response = stubWithMetadata.getExtendedAgentCard(request); + + return FromProto.agentCard(response); + } catch (StatusRuntimeException | StatusException e) { + throw GrpcErrorMapper.mapGrpcError(e, "Failed to get extended agent card: "); + } } @Override diff --git a/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java b/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java index b68f7c958..864e406d2 100644 --- a/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java +++ b/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java @@ -7,15 +7,9 @@ import io.a2a.spec.A2AClientException; import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedCardNotConfiguredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ExtensionSupportRequiredError; -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 io.a2a.spec.VersionNotSupportedError; @@ -85,9 +79,9 @@ public void testExtendedCardNotConfiguredErrorUnmarshalling() { // Verify the result assertNotNull(result); assertNotNull(result.getCause()); - assertInstanceOf(ExtendedCardNotConfiguredError.class, result.getCause()); + assertInstanceOf(ExtendedAgentCardNotConfiguredError.class, result.getCause()); - ExtendedCardNotConfiguredError extendedCardError = (ExtendedCardNotConfiguredError) result.getCause(); + ExtendedAgentCardNotConfiguredError extendedCardError = (ExtendedAgentCardNotConfiguredError) result.getCause(); assertNotNull(extendedCardError.getMessage()); assertTrue(extendedCardError.getMessage().contains("Extended card not configured")); } 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 8c948c4a8..e991eecb3 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 @@ -21,7 +21,7 @@ import java.util.function.Consumer; import com.google.protobuf.MessageOrBuilder; -import io.a2a.client.http.A2ACardResolver; + import io.a2a.client.http.A2AHttpClient; import io.a2a.client.http.A2AHttpClientFactory; import io.a2a.client.http.A2AHttpResponse; @@ -33,12 +33,10 @@ 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.GetExtendedAgentCardResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; @@ -71,8 +69,7 @@ public class JSONRPCTransport implements ClientTransport { private final A2AHttpClient httpClient; private final AgentInterface agentInterface; private final @Nullable List interceptors; - private @Nullable AgentCard agentCard; - private boolean needsExtendedCard = false; + private final @Nullable AgentCard agentCard; public JSONRPCTransport(String agentUrl) { this(null, null, new AgentInterface("JSONRPC", agentUrl), null); @@ -88,7 +85,6 @@ public JSONRPCTransport(@Nullable A2AHttpClient httpClient, @Nullable AgentCard this.agentCard = agentCard; this.agentInterface = agentInterface; this.interceptors = interceptors; - this.needsExtendedCard = agentCard == null || agentCard.supportsExtendedAgentCard(); } @Override @@ -288,31 +284,15 @@ public void resubscribe(TaskIdParams request, Consumer event } @Override - public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - A2ACardResolver resolver; + public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { try { - if (agentCard == null) { - resolver = new A2ACardResolver(httpClient, agentInterface.url(), agentInterface.tenant(), null, getHttpHeaders(context)); - agentCard = resolver.getAgentCard(); - needsExtendedCard = agentCard.supportsExtendedAgentCard(); - } - if (!needsExtendedCard) { - return agentCard; - } - - GetAuthenticatedExtendedCardRequest getExtendedAgentCardRequest = GetAuthenticatedExtendedCardRequest.builder() - .jsonrpc(A2AMessage.JSONRPC_VERSION) - .build(); // id will be randomly generated - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, ProtoUtils.ToProto.extendedAgentCard(), agentCard, context); try { 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; + GetExtendedAgentCardResponse response = unmarshalResponse(httpResponseBody, GET_EXTENDED_AGENT_CARD_METHOD); + return response.getResult(); } catch (IOException | InterruptedException | JsonProcessingException e) { throw new A2AClientException("Failed to get authenticated extended agent card: " + e, e); } diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 3344420a0..9b6f7f017 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -353,96 +353,8 @@ public void testA2AClientSetTaskPushNotificationConfig() throws Exception { assertEquals("jwt", authenticationInfo.schemes().get(0)); } - @Test - public void testA2AClientGetAgentCard() throws Exception { - this.server.when( - request() - .withMethod("GET") - .withPath("/.well-known/agent-card.json") - ) - .respond( - response() - .withStatusCode(200) - .withBody(AGENT_CARD) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - AgentCard agentCard = client.getAgentCard(null); - assertEquals("GeoSpatial Route Planner Agent", agentCard.name()); - assertEquals("Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", agentCard.description()); - assertEquals("https://georoute-agent.example.com/a2a/v1", Utils.getFavoriteInterface(agentCard).url()); - assertEquals("Example Geo Services Inc.", agentCard.provider().organization()); - assertEquals("https://www.examplegeoservices.com", agentCard.provider().url()); - assertEquals("1.2.0", agentCard.version()); - assertEquals("https://docs.examplegeoservices.com/georoute-agent/api", agentCard.documentationUrl()); - assertTrue(agentCard.capabilities().streaming()); - assertTrue(agentCard.capabilities().pushNotifications()); - assertFalse(agentCard.capabilities().stateTransitionHistory()); - Map securitySchemes = agentCard.securitySchemes(); - assertNotNull(securitySchemes); - OpenIdConnectSecurityScheme google = (OpenIdConnectSecurityScheme) securitySchemes.get("google"); - assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.openIdConnectUrl()); - List>> security = agentCard.security(); - assertEquals(1, security.size()); - Map> securityMap = security.get(0); - List scopes = securityMap.get("google"); - List expectedScopes = List.of("openid", "profile", "email"); - assertEquals(expectedScopes, scopes); - List defaultInputModes = List.of("application/json", "text/plain"); - assertEquals(defaultInputModes, agentCard.defaultInputModes()); - List defaultOutputModes = List.of("application/json", "image/png"); - assertEquals(defaultOutputModes, agentCard.defaultOutputModes()); - List skills = agentCard.skills(); - assertEquals("route-optimizer-traffic", skills.get(0).id()); - assertEquals("Traffic-Aware Route Optimizer", skills.get(0).name()); - assertEquals("Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", skills.get(0).description()); - List tags = List.of("maps", "routing", "navigation", "directions", "traffic"); - assertEquals(tags, skills.get(0).tags()); - List examples = List.of("Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}"); - assertEquals(examples, skills.get(0).examples()); - assertEquals(defaultInputModes, skills.get(0).inputModes()); - List outputModes = List.of("application/json", "application/vnd.geo+json", "text/html"); - assertEquals(outputModes, skills.get(0).outputModes()); - assertEquals("custom-map-generator", skills.get(1).id()); - assertEquals("Personalized Map Generator", skills.get(1).name()); - assertEquals("Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", skills.get(1).description()); - tags = List.of("maps", "customization", "visualization", "cartography"); - assertEquals(tags, skills.get(1).tags()); - examples = List.of("Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location."); - assertEquals(examples, skills.get(1).examples()); - List inputModes = List.of("application/json"); - assertEquals(inputModes, skills.get(1).inputModes()); - outputModes = List.of("image/png", "image/jpeg", "application/json", "text/html"); - assertEquals(outputModes, skills.get(1).outputModes()); - assertFalse(agentCard.supportsExtendedAgentCard()); - assertEquals("https://georoute-agent.example.com/icon.png", agentCard.iconUrl()); - assertEquals(CURRENT_PROTOCOL_VERSION, agentCard.protocolVersion()); - assertEquals("JSONRPC", agentCard.supportedInterfaces().get(0).protocolBinding()); - List additionalInterfaces = agentCard.supportedInterfaces(); - assertEquals(3, additionalInterfaces.size()); - AgentInterface jsonrpc = new AgentInterface(TransportProtocol.JSONRPC.asString(), "https://georoute-agent.example.com/a2a/v1"); - AgentInterface grpc = new AgentInterface(TransportProtocol.GRPC.asString(), "https://georoute-agent.example.com/a2a/grpc"); - AgentInterface httpJson = new AgentInterface(TransportProtocol.HTTP_JSON.asString(), "https://georoute-agent.example.com/a2a/json"); - assertEquals(jsonrpc, additionalInterfaces.get(0)); - assertEquals(grpc, additionalInterfaces.get(1)); - assertEquals(httpJson, additionalInterfaces.get(2)); - } - - @Test - public void testA2AClientGetAuthenticatedExtendedAgentCard() throws Exception { - this.server.when( - request() - .withMethod("GET") - .withPath("/.well-known/agent-card.json") - ) - .respond( - response() - .withStatusCode(200) - .withBody(AGENT_CARD_SUPPORTS_EXTENDED) - ); + public void testA2AClientGetExtendedAgentCard() throws Exception { this.server.when( request() .withMethod("POST") @@ -456,7 +368,7 @@ public void testA2AClientGetAuthenticatedExtendedAgentCard() throws Exception { ); JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - AgentCard agentCard = client.getAgentCard(null); + AgentCard agentCard = client.getExtendedAgentCard(null); assertEquals("GeoSpatial Route Planner Agent Extended", agentCard.name()); assertEquals("Extended description", agentCard.description()); assertEquals("https://georoute-agent.example.com/a2a/v1", Utils.getFavoriteInterface(agentCard).url()); @@ -467,6 +379,7 @@ public void testA2AClientGetAuthenticatedExtendedAgentCard() throws Exception { assertTrue(agentCard.capabilities().streaming()); assertTrue(agentCard.capabilities().pushNotifications()); assertFalse(agentCard.capabilities().stateTransitionHistory()); + assertTrue(agentCard.capabilities().extendedAgentCard()); Map securitySchemes = agentCard.securitySchemes(); assertNotNull(securitySchemes); OpenIdConnectSecurityScheme google = (OpenIdConnectSecurityScheme) securitySchemes.get("google"); @@ -509,9 +422,8 @@ public void testA2AClientGetAuthenticatedExtendedAgentCard() throws Exception { assertEquals("Extended Skill", skills.get(2).name()); assertEquals("This is an extended skill.", skills.get(2).description()); assertEquals(List.of("extended"), skills.get(2).tags()); - assertTrue(agentCard.supportsExtendedAgentCard()); assertEquals("https://georoute-agent.example.com/icon.png", agentCard.iconUrl()); - assertEquals(CURRENT_PROTOCOL_VERSION, agentCard.protocolVersion()); + assertEquals(CURRENT_PROTOCOL_VERSION, agentCard.protocolVersions().get(0)); } @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 27c27a7ab..dfdbb9741 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 @@ -10,7 +10,7 @@ public class JsonMessages { static final String AGENT_CARD = String.format(""" { - "protocolVersion": "%s", + "protocolVersions": ["%s"], "name": "GeoSpatial Route Planner Agent", "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", "supportedInterfaces" : [ @@ -28,7 +28,8 @@ public class JsonMessages { "capabilities": { "streaming": true, "pushNotifications": true, - "stateTransitionHistory": false + "stateTransitionHistory": false, + "extendedAgentCard": false }, "securitySchemes": { "google": { @@ -75,7 +76,6 @@ public class JsonMessages { ] } ], - "supportsExtendedAgentCard": false, "signatures": [ { "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", @@ -610,7 +610,8 @@ public class JsonMessages { "capabilities": { "streaming": true, "pushNotifications": true, - "stateTransitionHistory": false + "stateTransitionHistory": false, + "extendedAgentCard": true }, "securitySchemes": { "google": { @@ -663,8 +664,7 @@ public class JsonMessages { "tags": ["extended"] } ], - "supportsExtendedAgentCard": true, - "protocolVersion": "%s", + "protocolVersions": ["%s"], "signatures": [ { "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdUI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", @@ -691,7 +691,8 @@ public class JsonMessages { "capabilities": { "streaming": true, "pushNotifications": true, - "stateTransitionHistory": false + "stateTransitionHistory": false, + "extendedAgentCard": true }, "securitySchemes": { "google": { @@ -738,7 +739,6 @@ public class JsonMessages { ] } ], - "supportsExtendedAgentCard": true, - "protocolVersion": "%s" + "protocolVersions": ["%s"] }""", CURRENT_PROTOCOL_VERSION); } 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 76e6df404..92ce45416 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 @@ -8,7 +8,7 @@ import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.A2AClientException; -import io.a2a.spec.ExtendedCardNotConfiguredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.InternalError; @@ -50,8 +50,7 @@ public static A2AClientException mapRestError(String body, int code) { public static A2AClientException mapRestError(String className, String errorMessage, int code) { return switch (className) { case "io.a2a.spec.TaskNotFoundError" -> new A2AClientException(errorMessage, new TaskNotFoundError()); - case "io.a2a.spec.AuthenticatedExtendedCardNotConfiguredError", - "io.a2a.spec.ExtendedCardNotConfiguredError" -> new A2AClientException(errorMessage, new ExtendedCardNotConfiguredError(null, errorMessage, null)); + case "io.a2a.spec.ExtendedCardNotConfiguredError" -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, null)); case "io.a2a.spec.ContentTypeNotSupportedError" -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, null, errorMessage)); case "io.a2a.spec.InternalError" -> new A2AClientException(errorMessage, new InternalError(errorMessage)); case "io.a2a.spec.InvalidAgentResponseError" -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, null, errorMessage)); 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 d67972a07..6513086da 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 @@ -65,8 +65,7 @@ public class RestTransport implements ClientTransport { private final A2AHttpClient httpClient; private final AgentInterface agentInterface; private @Nullable final List interceptors; - private AgentCard agentCard; - private boolean needsExtendedCard = false; + private final AgentCard agentCard; public RestTransport(AgentCard agentCard) { this(null, agentCard, Utils.getFavoriteInterface(agentCard), null); @@ -89,8 +88,8 @@ public EventKind sendMessage(MessageSendParams messageSendParams, @Nullable Clie String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, messageSendParams.tenant()) + "/message:send", payloadAndHeaders); io.a2a.grpc.SendMessageResponse.Builder responseBuilder = io.a2a.grpc.SendMessageResponse.newBuilder(); JsonFormat.parser().merge(httpResponseBody, responseBuilder); - if (responseBuilder.hasMsg()) { - return ProtoUtils.FromProto.message(responseBuilder.getMsg()); + if (responseBuilder.hasMessage()) { + return ProtoUtils.FromProto.message(responseBuilder.getMessage()); } if (responseBuilder.hasTask()) { return ProtoUtils.FromProto.task(responseBuilder.getTask()); @@ -416,17 +415,8 @@ public void resubscribe(TaskIdParams request, Consumer event } @Override - public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - A2ACardResolver resolver; + public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { try { - if (agentCard == null) { - resolver = new A2ACardResolver(httpClient, agentInterface.url(), agentInterface.tenant(), null, getHttpHeaders(context)); - agentCard = resolver.getAgentCard(); - needsExtendedCard = agentCard.supportsExtendedAgentCard(); - } - if (!needsExtendedCard) { - return agentCard; - } PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, null, agentCard, context); String url = Utils.buildBaseUrl(agentInterface, "") + "/extendedAgentCard"; A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); @@ -440,9 +430,7 @@ public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2ACli throw RestErrorMapper.mapRestError(response); } String httpResponseBody = response.body(); - agentCard = JsonUtil.fromJson(httpResponseBody, AgentCard.class); - needsExtendedCard = false; - return agentCard; + return JsonUtil.fromJson(httpResponseBody, AgentCard.class); } catch (IOException | InterruptedException | JsonProcessingException e) { throw new A2AClientException("Failed to get authenticated extended agent card: " + e, e); } catch (A2AClientError e) { diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java index 58a1a57f0..ec74d2fbc 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java +++ b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java @@ -47,8 +47,8 @@ public void onError(Throwable throwable, @Nullable Future future) { private void handleMessage(StreamResponse response) { StreamingEventKind event; switch (response.getPayloadCase()) { - case MSG -> - event = ProtoUtils.FromProto.message(response.getMsg()); + case MESSAGE -> + event = ProtoUtils.FromProto.message(response.getMessage()); case TASK -> event = ProtoUtils.FromProto.task(response.getTask()); case STATUS_UPDATE -> diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index eda760130..879363d9c 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -91,7 +91,7 @@ public class RestTransportTest { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); @BeforeEach 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 e0f4b3a0c..df95e9ffd 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 @@ -137,13 +137,13 @@ void resubscribe(TaskIdParams request, Consumer eventConsume Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException; /** - * Retrieve the AgentCard. + * Retrieve the extended AgentCard. * * @param context optional client call context for the request (may be {@code null}) - * @return the AgentCard + * @return the extended agent card * @throws A2AClientException if retrieving the agent card fails for any reason */ - AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2AClientException; + AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException; /** * Close the transport and release any associated resources. diff --git a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java b/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java index 07c7aea04..39e968ccf 100644 --- a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java +++ b/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java @@ -58,7 +58,7 @@ public AgentCard agentCard() { )) .build() )) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } } diff --git a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java b/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java index 73d080c45..b29b0b55f 100644 --- a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java +++ b/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java @@ -68,6 +68,8 @@ public class A2ACloudExampleClient { private Client nonStreamingClient; private ClientConfig nonStreamingConfig; + private AgentCard agentCard; + public static void main(String[] args) throws Exception { new A2ACloudExampleClient().run(); } @@ -75,7 +77,7 @@ public static void main(String[] args) throws Exception { private void run() throws Exception { printHeader(); - AgentCard agentCard = fetchAndConfigureAgentCard(); + agentCard = fetchAndConfigureAgentCard(); String clientTaskId = generateClientTaskId(); createClients(agentCard); @@ -273,7 +275,7 @@ private void sendProcessMessages() throws InterruptedException { final int messageNum = messageCount; // Create a new client for each request to force new HTTP connection - Client freshClient = Client.builder(streamingClient.getAgentCard()) + Client freshClient = Client.builder(agentCard) .clientConfig(nonStreamingConfig) .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) .build(); @@ -318,7 +320,7 @@ private void sendCompleteMessage() { System.out.println(); System.out.println("Step 4: Sending 'complete' to finalize task..."); - Client completeClient = Client.builder(streamingClient.getAgentCard()) + Client completeClient = Client.builder(agentCard) .clientConfig(nonStreamingConfig) .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) .build(); 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 c3b1cb473..5b8a6d196 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 @@ -40,11 +40,11 @@ public static void main(String[] args) { System.out.println("Using public agent card for client initialization (default)."); finalAgentCard = publicAgentCard; - if (publicAgentCard.supportsExtendedAgentCard()) { - System.out.println("Public card supports authenticated extended card. Attempting to fetch from: " + SERVER_URL + "/agent/authenticatedExtendedCard"); + if (publicAgentCard.capabilities().extendedAgentCard()) { + System.out.println("Public card supports authenticated extended card. Attempting to fetch from: " + SERVER_URL + "/ExtendedAgentCard"); Map authHeaders = new HashMap<>(); authHeaders.put("Authorization", "Bearer dummy-token-for-extended-card"); - AgentCard extendedAgentCard = A2A.getAgentCard(SERVER_URL, "/agent/authenticatedExtendedCard", authHeaders); + AgentCard extendedAgentCard = A2A.getAgentCard(SERVER_URL, "/ExtendedAgentCard", authHeaders); System.out.println("Successfully fetched authenticated extended agent card:"); System.out.println(JsonUtil.toJson(extendedAgentCard)); System.out.println("Using AUTHENTICATED EXTENDED agent card for client initialization."); diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java index 66f1c7fc4..42f631924 100644 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java +++ b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java @@ -43,7 +43,7 @@ public AgentCard agentCard() { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } } diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java index 9936ea4df..f029fd120 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java @@ -48,7 +48,7 @@ public static AgentCard createAgentCard(int instanceNumber, int port) { .description("Fire-and-forget agent for testing replication") .tags(Collections.singletonList("test")) .build())) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } } diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java index 7a0e9280e..b476fc497 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java @@ -39,7 +39,7 @@ public AgentCard agentCard() { .skills(List.of()) .supportedInterfaces(List.of( new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:8081"))) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } } \ No newline at end of file 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 840773ea6..0db0e1548 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 @@ -261,10 +261,10 @@ public ListTasksResult list(ListTasksParams params) { countQueryBuilder.append(" AND t.state = :state"); } - // Apply lastUpdatedAfter filter using denormalized timestamp column - if (params.lastUpdatedAfter() != null) { - queryBuilder.append(" AND t.statusTimestamp > :lastUpdatedAfter"); - countQueryBuilder.append(" AND t.statusTimestamp > :lastUpdatedAfter"); + // Apply statusTimestampAfter filter using denormalized timestamp column + if (params.statusTimestampAfter() != null) { + queryBuilder.append(" AND t.statusTimestamp > :statusTimestampAfter"); + countQueryBuilder.append(" AND t.statusTimestamp > :statusTimestampAfter"); } // Apply pagination cursor using keyset pagination for composite sort (timestamp DESC, id ASC) @@ -286,8 +286,8 @@ public ListTasksResult list(ListTasksParams params) { if (params.status() != null) { query.setParameter("state", params.status().asString()); } - if (params.lastUpdatedAfter() != null) { - query.setParameter("lastUpdatedAfter", params.lastUpdatedAfter()); + if (params.statusTimestampAfter() != null) { + query.setParameter("statusTimestampAfter", params.statusTimestampAfter()); } if (tokenTimestamp != null) { query.setParameter("tokenTimestamp", tokenTimestamp); @@ -315,8 +315,8 @@ public ListTasksResult list(ListTasksParams params) { if (params.status() != null) { countQuery.setParameter("state", params.status().asString()); } - if (params.lastUpdatedAfter() != null) { - countQuery.setParameter("lastUpdatedAfter", params.lastUpdatedAfter()); + if (params.statusTimestampAfter() != null) { + countQuery.setParameter("statusTimestampAfter", params.statusTimestampAfter()); } int totalSize = countQuery.getSingleResult().intValue(); diff --git a/http-client/src/test/java/io/a2a/client/http/JsonMessages.java b/http-client/src/test/java/io/a2a/client/http/JsonMessages.java index d889b8e2c..794017432 100644 --- a/http-client/src/test/java/io/a2a/client/http/JsonMessages.java +++ b/http-client/src/test/java/io/a2a/client/http/JsonMessages.java @@ -8,7 +8,7 @@ public class JsonMessages { static final String AGENT_CARD = """ { - "protocolVersion": "0.2.9", + "protocolVersions": ["0.2.9"], "name": "GeoSpatial Route Planner Agent", "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", "supportedInterfaces" : [ @@ -73,7 +73,6 @@ public class JsonMessages { ] } ], - "supportsExtendedAgentCard": true, "signatures": [ { "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java index 73bb430eb..530f55e9f 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java @@ -10,7 +10,7 @@ * * @param the type of the result value returned in successful responses */ -public abstract sealed class A2AResponse implements A2AMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetAuthenticatedExtendedCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, A2AErrorResponse, ListTaskPushNotificationConfigResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, SetTaskPushNotificationConfigResponse { +public abstract sealed class A2AResponse implements A2AMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetExtendedAgentCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, A2AErrorResponse, ListTaskPushNotificationConfigResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, SetTaskPushNotificationConfigResponse { /** The JSON-RPC protocol version. */ protected String jsonrpc; diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java similarity index 73% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java index dec5ec257..89e893363 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java @@ -4,8 +4,9 @@ import java.util.UUID; +import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedCardNotConfiguredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; /** * JSON-RPC request to retrieve an agent's extended card with authenticated details. @@ -20,18 +21,18 @@ * *

* The agent must support authenticated extended cards (indicated by - * {@link AgentCard#supportsExtendedAgentCard()}) and the client must provide + * {@link AgentCapabilities#extendedAgentCard()} }) and the client must provide * valid authentication credentials for this request to succeed. *

- * This class implements the JSON-RPC {@code agent/getAuthenticatedExtendedCard} method + * This class implements the JSON-RPC {@code GetExtendedAgentCard} method * as specified in the A2A Protocol. * - * @see GetAuthenticatedExtendedCardResponse for the corresponding response + * @see GetExtendedAgentCardResponse for the corresponding response * @see AgentCard for the card structure - * @see ExtendedCardNotConfiguredError for the error when unsupported + * @see ExtendedAgentCardNotConfiguredError for the error when unsupported * @see A2A Protocol Specification */ -public final class GetAuthenticatedExtendedCardRequest extends NonStreamingJSONRPCRequest { +public final class GetExtendedAgentCardRequest extends NonStreamingJSONRPCRequest { /** * Constructs request with full parameters. @@ -39,7 +40,7 @@ public final class GetAuthenticatedExtendedCardRequest extends NonStreamingJSONR * @param jsonrpc the JSON-RPC version * @param id the request ID */ - public GetAuthenticatedExtendedCardRequest(String jsonrpc, Object id) { + public GetExtendedAgentCardRequest(String jsonrpc, Object id) { super(jsonrpc, GET_EXTENDED_AGENT_CARD_METHOD, id); } @@ -48,7 +49,7 @@ public GetAuthenticatedExtendedCardRequest(String jsonrpc, Object id) { * * @param id the request ID */ - public GetAuthenticatedExtendedCardRequest(String id) { + public GetExtendedAgentCardRequest(String id) { this(null, id); } @@ -80,7 +81,7 @@ private Builder() { * @param jsonrpc the JSON-RPC version * @return this builder for method chaining */ - public GetAuthenticatedExtendedCardRequest.Builder jsonrpc(String jsonrpc) { + public GetExtendedAgentCardRequest.Builder jsonrpc(String jsonrpc) { this.jsonrpc = jsonrpc; return this; } @@ -91,7 +92,7 @@ public GetAuthenticatedExtendedCardRequest.Builder jsonrpc(String jsonrpc) { * @param id the request ID * @return this builder for method chaining */ - public GetAuthenticatedExtendedCardRequest.Builder id(Object id) { + public GetExtendedAgentCardRequest.Builder id(Object id) { this.id = id; return this; } @@ -101,11 +102,11 @@ public GetAuthenticatedExtendedCardRequest.Builder id(Object id) { * * @return a new instance */ - public GetAuthenticatedExtendedCardRequest build() { + public GetExtendedAgentCardRequest build() { if (id == null) { id = UUID.randomUUID().toString(); } - return new GetAuthenticatedExtendedCardRequest(jsonrpc, id); + return new GetExtendedAgentCardRequest(jsonrpc, id); } } } diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java similarity index 69% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java index 63b4fd8eb..edf181dd6 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java @@ -2,7 +2,7 @@ import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedCardNotConfiguredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; /** * JSON-RPC response containing an agent's extended card with authenticated details. @@ -13,14 +13,14 @@ *

* If the agent doesn't support authenticated extended cards or authentication fails, * the error field will contain a {@link A2AError} such as - * {@link ExtendedCardNotConfiguredError}. + * {@link ExtendedAgentCardNotConfiguredError}. * - * @see GetAuthenticatedExtendedCardRequest for the corresponding request + * @see GetExtendedAgentCardRequest for the corresponding request * @see AgentCard for the card structure - * @see ExtendedCardNotConfiguredError for the error when unsupported + * @see ExtendedAgentCardNotConfiguredError for the error when unsupported * @see A2A Protocol Specification */ -public final class GetAuthenticatedExtendedCardResponse extends A2AResponse { +public final class GetExtendedAgentCardResponse extends A2AResponse { /** * Constructs response with full parameters. @@ -30,7 +30,7 @@ public final class GetAuthenticatedExtendedCardResponse extends A2AResponse extends A2ARequest permits GetTaskRequest, CancelTaskRequest, SetTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, SendMessageRequest, DeleteTaskPushNotificationConfigRequest, ListTaskPushNotificationConfigRequest, - GetAuthenticatedExtendedCardRequest, ListTasksRequest { + GetExtendedAgentCardRequest, ListTasksRequest { NonStreamingJSONRPCRequest(String jsonrpc, String method, Object id, T params) { validateAndSetJsonParameters(jsonrpc, method, id, params, true); diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java index bbc297baa..5a5f3d856 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java @@ -17,10 +17,7 @@ import io.a2a.spec.APIKeySecurityScheme; import io.a2a.spec.HTTPAuthSecurityScheme; import io.a2a.spec.MutualTLSSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OAuthFlows; import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.PasswordOAuthFlow; import io.a2a.spec.SecurityScheme; /** @@ -128,68 +125,6 @@ void testAPIKeySecuritySchemeWithDescriptionSerialization() throws JsonProcessin "description", "API key authentication via query parameter")); } - @Test - void testOAuth2SecuritySchemeSerialization() throws JsonProcessingException { - PasswordOAuthFlow passwordFlow = new PasswordOAuthFlow( - "https://example.com/oauth/refresh", - Map.of("read", "Read access", "write", "Write access"), - "https://example.com/oauth/token" - ); - - OAuthFlows flows = OAuthFlows.builder() - .password(passwordFlow) - .build(); - - SecurityScheme scheme = OAuth2SecurityScheme.builder() - .flows(flows) - .description("OAuth 2.0 password flow") - .oauth2MetadataUrl("https://example.com/.well-known/oauth-authorization-server") - .build(); - - // Verify serialization with nested OAuth flow fields - String json = JsonUtil.toJson(scheme); - assertNotNull(json); - assertTrue(json.contains(OAuth2SecurityScheme.TYPE)); - assertTrue(json.contains("\"description\":\"OAuth 2.0 password flow\"")); - assertTrue(json.contains("\"oauth2MetadataUrl\":\"https://example.com/.well-known/oauth-authorization-server\"")); - assertTrue(json.contains("\"tokenUrl\":\"https://example.com/oauth/token\"")); - assertTrue(json.contains("\"read\":\"Read access\"")); - - SecurityScheme deserialized = JsonUtil.fromJson(json, SecurityScheme.class); - assertEquals(scheme, deserialized); - } - - @Test - void testOAuth2SecuritySchemeDeserialization() throws JsonProcessingException { - String json = """ - { - "oauth2SecurityScheme" : { - "flows": { - "password": { - "tokenUrl": "https://example.com/oauth/token", - "refreshUrl": "https://example.com/oauth/refresh", - "scopes": { - "read": "Read access", - "write": "Write access" - } - } - }, - "description": "OAuth 2.0 authentication" - } - }"""; - - SecurityScheme securityScheme = JsonUtil.fromJson(json, SecurityScheme.class); - assertInstanceOf(OAuth2SecurityScheme.class, securityScheme); - OAuth2SecurityScheme scheme = (OAuth2SecurityScheme) securityScheme; - assertEquals("OAuth 2.0 authentication", scheme.description()); - assertNotNull(scheme.flows()); - assertNotNull(scheme.flows().password()); - assertEquals("https://example.com/oauth/token", scheme.flows().password().tokenUrl()); - assertEquals("https://example.com/oauth/refresh", scheme.flows().password().refreshUrl()); - assertEquals(2, scheme.flows().password().scopes().size()); - assertEquals("Read access", scheme.flows().password().scopes().get("read")); - } - @Test void testOpenIdConnectSecuritySchemeSerialization() throws JsonProcessingException { SecurityScheme scheme = OpenIdConnectSecurityScheme.builder() 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 edd346d50..e5f7a27c2 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 @@ -5,6 +5,7 @@ import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; +import io.a2a.server.ExtendedAgentCard; import io.a2a.server.PublicAgentCard; import io.a2a.server.requesthandlers.RequestHandler; import io.a2a.server.util.async.Internal; @@ -14,6 +15,7 @@ import io.quarkus.grpc.GrpcService; import io.quarkus.grpc.RegisterInterceptor; import io.quarkus.security.Authenticated; +import org.jspecify.annotations.Nullable; @GrpcService @RegisterInterceptor(A2AExtensionsInterceptor.class) @@ -21,16 +23,29 @@ public class QuarkusGrpcHandler extends GrpcHandler { private final AgentCard agentCard; + private final AgentCard extendedAgentCard; private final RequestHandler requestHandler; private final Instance callContextFactoryInstance; private final Executor executor; + /** + * No-args constructor for CDI proxy creation. + * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. + * All fields are initialized by the @Inject constructor during actual bean creation. + */ + @Inject public QuarkusGrpcHandler(@PublicAgentCard AgentCard agentCard, + @ExtendedAgentCard Instance extendedAgentCard, RequestHandler requestHandler, Instance callContextFactoryInstance, @Internal Executor executor) { this.agentCard = agentCard; + if (extendedAgentCard != null && extendedAgentCard.isResolvable()) { + this.extendedAgentCard = extendedAgentCard.get(); + } else { + this.extendedAgentCard = null; + } this.requestHandler = requestHandler; this.callContextFactoryInstance = callContextFactoryInstance; this.executor = executor; @@ -46,6 +61,11 @@ protected AgentCard getAgentCard() { return agentCard; } + @Override + protected AgentCard getExtendedAgentCard() { + return extendedAgentCard; + } + @Override protected CallContextFactory getCallContextFactory() { return callContextFactoryInstance.isUnsatisfied() ? null : callContextFactoryInstance.get(); 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 9f4b31d83..18e18a2f1 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 @@ -35,8 +35,8 @@ 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.GetExtendedAgentCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; @@ -59,7 +59,6 @@ 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.InternalError; import io.a2a.spec.JSONParseError; import io.a2a.spec.UnsupportedOperationError; @@ -186,8 +185,8 @@ private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest if (request instanceof DeleteTaskPushNotificationConfigRequest req) { return jsonRpcHandler.deletePushNotificationConfig(req, context); } - if (request instanceof GetAuthenticatedExtendedCardRequest req) { - return jsonRpcHandler.onGetAuthenticatedExtendedCardRequest(req, context); + if (request instanceof GetExtendedAgentCardRequest req) { + return jsonRpcHandler.onGetExtendedCardRequest(req, context); } return generateErrorResponse(request, new UnsupportedOperationError()); } @@ -287,8 +286,8 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -513,8 +513,8 @@ public void testGetAuthenticatedExtendedCard_MethodNameSetInContext() { routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); // Assert - verify(mockJsonRpcHandler).onGetAuthenticatedExtendedCardRequest( - any(GetAuthenticatedExtendedCardRequest.class), contextCaptor.capture()); + verify(mockJsonRpcHandler).onGetExtendedCardRequest( + any(GetExtendedAgentCardRequest.class), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(GET_EXTENDED_AGENT_CARD_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); 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 e19f7920d..002acbafd 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 @@ -312,19 +312,27 @@ private static Task limitTaskHistory(Task task, @Nullable Integer historyLength) @Override 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()); + LOGGER.debug("onListTasks with contextId={}, status={}, pageSize={}, pageToken={}, statusTimestampAfter={}", + params.contextId(), params.status(), params.pageSize(), params.pageToken(), params.statusTimestampAfter()); - // Validate lastUpdatedAfter timestamp if provided - if (params.lastUpdatedAfter() != null) { + // Validate statusTimestampAfter timestamp if provided + if (params.statusTimestampAfter() != null) { // Check if timestamp is in the future (optional validation per spec) Instant now = Instant.now(); - if (params.lastUpdatedAfter().isAfter(now)) { + if (params.statusTimestampAfter().isAfter(now)) { Map errorData = new HashMap<>(); errorData.put("parameter", "lastUpdatedAfter"); errorData.put("reason", "Timestamp cannot be in the future"); throw new InvalidParamsError(null, "Invalid params", errorData); } + // Check that timestamp is not negative + long millis = params.statusTimestampAfter().toEpochMilli(); + if (millis < 0L) { + Map errorData = new HashMap<>(); + errorData.put("parameter", "statusTimestampAfter"); + errorData.put("reason", "Must be a non-negative timestamp value, got: " + millis); + throw new InvalidParamsError(null, "Invalid params", errorData); + } } ListTasksResult result = taskStore.list(params); 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 f1243e272..8a3d72133 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 @@ -52,10 +52,10 @@ public ListTasksResult list(ListTasksParams params) { .filter(task -> params.contextId() == null || params.contextId().equals(task.contextId())) .filter(task -> params.status() == null || (task.status() != null && params.status().equals(task.status().state()))) - .filter(task -> params.lastUpdatedAfter() == null || + .filter(task -> params.statusTimestampAfter() == null || (task.status() != null && task.status().timestamp() != null && - task.status().timestamp().toInstant().isAfter(params.lastUpdatedAfter()))) + task.status().timestamp().toInstant().isAfter(params.statusTimestampAfter()))) .sorted(Comparator.comparing( (Task t) -> (t.status() != null && t.status().timestamp() != null) // Truncate to milliseconds for consistency with pageToken precision diff --git a/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java b/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java index 83a83122f..91159428a 100644 --- a/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java +++ b/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java @@ -1,5 +1,7 @@ package io.a2a.server.version; +import java.util.List; + import io.a2a.server.ServerCallContext; import io.a2a.spec.AgentCard; import io.a2a.spec.VersionNotSupportedError; @@ -35,13 +37,13 @@ public static void validateProtocolVersion(AgentCard agentCard, ServerCallContex requestedVersion = AgentCard.CURRENT_PROTOCOL_VERSION; } - String supportedVersion = agentCard.protocolVersion(); + List supportedVersions = agentCard.protocolVersions(); - if (!isVersionCompatible(supportedVersion, requestedVersion)) { + if (!isVersionCompatible(supportedVersions, requestedVersion)) { throw new VersionNotSupportedError( null, "Protocol version '" + requestedVersion + "' is not supported. " + - "Supported version: " + supportedVersion, + "Supported versions: " + supportedVersions, null); } } @@ -55,22 +57,30 @@ public static void validateProtocolVersion(AgentCard agentCard, ServerCallContex *

  • Minor versions are compatible (any x.Y works with x.Z)
  • * * - * @param supported the version supported by the agent (e.g., "1.0") - * @param requested the version requested by the client (e.g., "1.1") + * @param supportedVersions the version supported by the agent (e.g., ["1.0", "1.1"]) + * @param requestedVersion the version requested by the client (e.g., "1.1") * @return true if versions are compatible, false otherwise */ - static boolean isVersionCompatible(String supported, String requested) { - try { - VersionParts supportedParts = parseVersion(supported); - VersionParts requestedParts = parseVersion(requested); - - // Major versions must match exactly - return supportedParts.major == requestedParts.major; - // Minor versions are compatible - any 1.x can talk to any 1.y - } catch (IllegalArgumentException e) { - // If we can't parse the version, consider it incompatible + static boolean isVersionCompatible(List supportedVersions, String requestedVersion) { + if (supportedVersions == null) { return false; } + for (String supportedVersion : supportedVersions) { + try { + VersionParts supportedParts = parseVersion(supportedVersion); + VersionParts requestedParts = parseVersion(requestedVersion); + + // Major versions must match exactly + if (supportedParts.major == requestedParts.major) { + return true; + } + // Minor versions are compatible - any 1.x can talk to any 1.y + } catch (IllegalArgumentException e) { + // If we can't parse the version, consider it incompatible + return false; + } + } + return false; } /** 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 8038bc147..ea5bbe797 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 @@ -127,7 +127,7 @@ protected static AgentCard createAgentCard(boolean streaming, boolean pushNotifi .defaultInputModes(new ArrayList<>()) .defaultOutputModes(new ArrayList<>()) .skills(new ArrayList<>()) - .protocolVersion(CURRENT_PROTOCOL_VERSION); + .protocolVersions(CURRENT_PROTOCOL_VERSION); return builder.build(); } diff --git a/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java b/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java index 528017731..43e0f55dd 100644 --- a/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java +++ b/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java @@ -18,34 +18,34 @@ public class A2AVersionValidatorTest { @Test public void testIsVersionCompatible_SameMajorMinor() { - assertTrue(A2AVersionValidator.isVersionCompatible("1.0", "1.0")); + assertTrue(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "1.0")); } @Test public void testIsVersionCompatible_SameMajorDifferentMinor() { // Major versions match, minor versions can differ - assertTrue(A2AVersionValidator.isVersionCompatible("1.0", "1.1")); - assertTrue(A2AVersionValidator.isVersionCompatible("1.1", "1.0")); - assertTrue(A2AVersionValidator.isVersionCompatible("1.5", "1.9")); + assertTrue(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "1.1")); + assertTrue(A2AVersionValidator.isVersionCompatible(List.of("1.1"), "1.0")); + assertTrue(A2AVersionValidator.isVersionCompatible(List.of("1.5"), "1.9")); } @Test public void testIsVersionCompatible_DifferentMajor() { // Major versions must match exactly - assertFalse(A2AVersionValidator.isVersionCompatible("1.0", "2.0")); - assertFalse(A2AVersionValidator.isVersionCompatible("2.0", "1.0")); - assertFalse(A2AVersionValidator.isVersionCompatible("1.5", "2.5")); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "2.0")); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of("2.0"), "1.0")); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.5"), "2.5")); } @Test public void testIsVersionCompatible_InvalidFormat() { // Invalid version formats should return false - assertFalse(A2AVersionValidator.isVersionCompatible("1.0", "invalid")); - assertFalse(A2AVersionValidator.isVersionCompatible("invalid", "1.0")); - assertFalse(A2AVersionValidator.isVersionCompatible("1", "1.0")); - assertFalse(A2AVersionValidator.isVersionCompatible("1.0", "")); - assertFalse(A2AVersionValidator.isVersionCompatible("", "1.0")); - assertFalse(A2AVersionValidator.isVersionCompatible("1.0", null)); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "invalid")); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of("invalid"), "1.0")); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1"), "1.0")); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "")); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of(""), "1.0")); + assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.0"), null)); assertFalse(A2AVersionValidator.isVersionCompatible(null, "1.0")); } @@ -153,7 +153,7 @@ private AgentCard createAgentCard(String protocolVersion) { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(Collections.emptyList()) - .protocolVersion(protocolVersion) + .protocolVersions(protocolVersion) .build(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java index bc454f7e1..0fa06787b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java @@ -202,25 +202,15 @@ public static void registerAllExtensions( com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; static final com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable; + internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor; + internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor; static final com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_PasswordOAuthFlow_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable; + internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_a2a_v1_SendMessageRequest_descriptor; static final @@ -352,199 +342,191 @@ public static void registerAllExtensions( "\n\007schemes\030\001 \003(\tB\003\340A\002\022\023\n\013credentials\030\002 \001(" + "\t\"Q\n\016AgentInterface\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\035\n" + "\020protocol_binding\030\002 \001(\tB\003\340A\002\022\016\n\006tenant\030\003" + - " \001(\t\"\255\007\n\tAgentCard\022\"\n\020protocol_version\030\020" + - " \001(\tB\003\340A\002H\000\210\001\001\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\030\n\013des" + - "cription\030\002 \001(\tB\003\340A\002\0224\n\024supported_interfa" + - "ces\030\023 \003(\0132\026.a2a.v1.AgentInterface\022\024\n\003url" + - "\030\003 \001(\tB\002\030\001H\001\210\001\001\022$\n\023preferred_transport\030\016" + - " \001(\tB\002\030\001H\002\210\001\001\0229\n\025additional_interfaces\030\017" + - " \003(\0132\026.a2a.v1.AgentInterfaceB\002\030\001\022\'\n\010prov" + - "ider\030\004 \001(\0132\025.a2a.v1.AgentProvider\022\024\n\007ver" + - "sion\030\005 \001(\tB\003\340A\002\022\036\n\021documentation_url\030\006 \001" + - "(\tH\003\210\001\001\0224\n\014capabilities\030\007 \001(\0132\031.a2a.v1.A" + - "gentCapabilitiesB\003\340A\002\022@\n\020security_scheme" + - "s\030\010 \003(\0132&.a2a.v1.AgentCard.SecuritySchem" + - "esEntry\022\"\n\010security\030\t \003(\0132\020.a2a.v1.Secur" + - "ity\022 \n\023default_input_modes\030\n \003(\tB\003\340A\002\022!\n" + - "\024default_output_modes\030\013 \003(\tB\003\340A\002\022\'\n\006skil" + - "ls\030\014 \003(\0132\022.a2a.v1.AgentSkillB\003\340A\002\022)\n\034sup" + - "ports_extended_agent_card\030\r \001(\010H\004\210\001\001\022.\n\n" + - "signatures\030\021 \003(\0132\032.a2a.v1.AgentCardSigna" + - "ture\022\025\n\010icon_url\030\022 \001(\tH\005\210\001\001\032N\n\024SecurityS" + - "chemesEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132" + - "\026.a2a.v1.SecurityScheme:\0028\001B\023\n\021_protocol" + - "_versionB\006\n\004_urlB\026\n\024_preferred_transport" + - "B\024\n\022_documentation_urlB\037\n\035_supports_exte" + - "nded_agent_cardB\013\n\t_icon_url\"<\n\rAgentPro" + - "vider\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\031\n\014organization\030" + - "\002 \001(\tB\003\340A\002\"\341\001\n\021AgentCapabilities\022\026\n\tstre" + - "aming\030\001 \001(\010H\000\210\001\001\022\037\n\022push_notifications\030\002" + - " \001(\010H\001\210\001\001\022*\n\nextensions\030\003 \003(\0132\026.a2a.v1.A" + - "gentExtension\022%\n\030state_transition_histor" + - "y\030\004 \001(\010H\002\210\001\001B\014\n\n_streamingB\025\n\023_push_noti" + - "ficationsB\033\n\031_state_transition_history\"m" + - "\n\016AgentExtension\022\013\n\003uri\030\001 \001(\t\022\023\n\013descrip" + - "tion\030\002 \001(\t\022\020\n\010required\030\003 \001(\010\022\'\n\006params\030\004" + - " \001(\0132\027.google.protobuf.Struct\"\276\001\n\nAgentS" + - "kill\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\021\n\004name\030\002 \001(\tB\003\340A\002" + - "\022\030\n\013description\030\003 \001(\tB\003\340A\002\022\021\n\004tags\030\004 \003(\t" + - "B\003\340A\002\022\020\n\010examples\030\005 \003(\t\022\023\n\013input_modes\030\006" + - " \003(\t\022\024\n\014output_modes\030\007 \003(\t\022\"\n\010security\030\010" + - " \003(\0132\020.a2a.v1.Security\"m\n\022AgentCardSigna" + - "ture\022\026\n\tprotected\030\001 \001(\tB\003\340A\002\022\026\n\tsignatur" + - "e\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\0132\027.google.pr" + - "otobuf.Struct\"v\n\032TaskPushNotificationCon" + - "fig\022\021\n\004name\030\001 \001(\tB\003\340A\002\022E\n\030push_notificat" + - "ion_config\030\002 \001(\0132\036.a2a.v1.PushNotificati" + - "onConfigB\003\340A\002\"\032\n\nStringList\022\014\n\004list\030\001 \003(" + - "\t\"~\n\010Security\022.\n\007schemes\030\001 \003(\0132\035.a2a.v1." + - "Security.SchemesEntry\032B\n\014SchemesEntry\022\013\n" + - "\003key\030\001 \001(\t\022!\n\005value\030\002 \001(\0132\022.a2a.v1.Strin" + - "gList:\0028\001\"\361\002\n\016SecurityScheme\022?\n\027api_key_" + - "security_scheme\030\001 \001(\0132\034.a2a.v1.APIKeySec" + - "uritySchemeH\000\022C\n\031http_auth_security_sche" + - "me\030\002 \001(\0132\036.a2a.v1.HTTPAuthSecurityScheme" + - "H\000\022>\n\026oauth2_security_scheme\030\003 \001(\0132\034.a2a" + - ".v1.OAuth2SecuritySchemeH\000\022N\n\037open_id_co" + - "nnect_security_scheme\030\004 \001(\0132#.a2a.v1.Ope" + - "nIdConnectSecuritySchemeH\000\022?\n\024mtls_secur" + - "ity_scheme\030\005 \001(\0132\037.a2a.v1.MutualTlsSecur" + - "itySchemeH\000B\010\n\006scheme\"U\n\024APIKeySecurityS" + - "cheme\022\023\n\013description\030\001 \001(\t\022\025\n\010location\030\002" + - " \001(\tB\003\340A\002\022\021\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026HTTPAuth" + - "SecurityScheme\022\023\n\013description\030\001 \001(\t\022\023\n\006s" + - "cheme\030\002 \001(\tB\003\340A\002\022\025\n\rbearer_format\030\003 \001(\t\"" + - "p\n\024OAuth2SecurityScheme\022\023\n\013description\030\001" + - " \001(\t\022&\n\005flows\030\002 \001(\0132\022.a2a.v1.OAuthFlowsB" + - "\003\340A\002\022\033\n\023oauth2_metadata_url\030\003 \001(\t\"T\n\033Ope" + - "nIdConnectSecurityScheme\022\023\n\013description\030" + - "\001 \001(\t\022 \n\023open_id_connect_url\030\002 \001(\tB\003\340A\002\"" + - ".\n\027MutualTlsSecurityScheme\022\023\n\013descriptio" + - "n\030\001 \001(\t\"\366\001\n\nOAuthFlows\022@\n\022authorization_" + - "code\030\001 \001(\0132\".a2a.v1.AuthorizationCodeOAu" + - "thFlowH\000\022@\n\022client_credentials\030\002 \001(\0132\".a" + - "2a.v1.ClientCredentialsOAuthFlowH\000\022-\n\010im" + - "plicit\030\003 \001(\0132\031.a2a.v1.ImplicitOAuthFlowH" + - "\000\022-\n\010password\030\004 \001(\0132\031.a2a.v1.PasswordOAu" + - "thFlowH\000B\006\n\004flow\"\335\001\n\032AuthorizationCodeOA" + - "uthFlow\022\036\n\021authorization_url\030\001 \001(\tB\003\340A\002\022" + - "\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003" + - " \001(\t\022C\n\006scopes\030\004 \003(\0132..a2a.v1.Authorizat" + - "ionCodeOAuthFlow.ScopesEntryB\003\340A\002\032-\n\013Sco" + - "pesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001" + - "\"\275\001\n\032ClientCredentialsOAuthFlow\022\026\n\ttoken" + - "_url\030\001 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022C\n\006" + - "scopes\030\003 \003(\0132..a2a.v1.ClientCredentialsO" + - "AuthFlow.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry" + - "\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\263\001\n\021Imp" + - "licitOAuthFlow\022\036\n\021authorization_url\030\001 \001(" + - "\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022:\n\006scopes\030\003 " + - "\003(\0132%.a2a.v1.ImplicitOAuthFlow.ScopesEnt" + + " \001(\t\"\310\005\n\tAgentCard\022\036\n\021protocol_versions\030" + + "\020 \003(\tB\003\340A\002\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\030\n\013descrip" + + "tion\030\002 \001(\tB\003\340A\002\0229\n\024supported_interfaces\030" + + "\023 \003(\0132\026.a2a.v1.AgentInterfaceB\003\340A\002\022\'\n\010pr" + + "ovider\030\004 \001(\0132\025.a2a.v1.AgentProvider\022\024\n\007v" + + "ersion\030\005 \001(\tB\003\340A\002\022\036\n\021documentation_url\030\006" + + " \001(\tH\000\210\001\001\0224\n\014capabilities\030\007 \001(\0132\031.a2a.v1" + + ".AgentCapabilitiesB\003\340A\002\022@\n\020security_sche" + + "mes\030\010 \003(\0132&.a2a.v1.AgentCard.SecuritySch" + + "emesEntry\022\"\n\010security\030\t \003(\0132\020.a2a.v1.Sec" + + "urity\022 \n\023default_input_modes\030\n \003(\tB\003\340A\002\022" + + "!\n\024default_output_modes\030\013 \003(\tB\003\340A\002\022\'\n\006sk" + + "ills\030\014 \003(\0132\022.a2a.v1.AgentSkillB\003\340A\002\022.\n\ns" + + "ignatures\030\021 \003(\0132\032.a2a.v1.AgentCardSignat" + + "ure\022\025\n\010icon_url\030\022 \001(\tH\001\210\001\001\032N\n\024SecuritySc" + + "hemesEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026" + + ".a2a.v1.SecurityScheme:\0028\001B\024\n\022_documenta" + + "tion_urlB\013\n\t_icon_urlJ\004\010\003\020\004J\004\010\016\020\017J\004\010\017\020\020\"" + + "<\n\rAgentProvider\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\031\n\014or" + + "ganization\030\002 \001(\tB\003\340A\002\"\233\002\n\021AgentCapabilit" + + "ies\022\026\n\tstreaming\030\001 \001(\010H\000\210\001\001\022\037\n\022push_noti" + + "fications\030\002 \001(\010H\001\210\001\001\022*\n\nextensions\030\003 \003(\013" + + "2\026.a2a.v1.AgentExtension\022%\n\030state_transi" + + "tion_history\030\004 \001(\010H\002\210\001\001\022 \n\023extended_agen" + + "t_card\030\005 \001(\010H\003\210\001\001B\014\n\n_streamingB\025\n\023_push" + + "_notificationsB\033\n\031_state_transition_hist" + + "oryB\026\n\024_extended_agent_card\"m\n\016AgentExte" + + "nsion\022\013\n\003uri\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022" + + "\020\n\010required\030\003 \001(\010\022\'\n\006params\030\004 \001(\0132\027.goog" + + "le.protobuf.Struct\"\276\001\n\nAgentSkill\022\017\n\002id\030" + + "\001 \001(\tB\003\340A\002\022\021\n\004name\030\002 \001(\tB\003\340A\002\022\030\n\013descrip" + + "tion\030\003 \001(\tB\003\340A\002\022\021\n\004tags\030\004 \003(\tB\003\340A\002\022\020\n\010ex" + + "amples\030\005 \003(\t\022\023\n\013input_modes\030\006 \003(\t\022\024\n\014out" + + "put_modes\030\007 \003(\t\022\"\n\010security\030\010 \003(\0132\020.a2a." + + "v1.Security\"m\n\022AgentCardSignature\022\026\n\tpro" + + "tected\030\001 \001(\tB\003\340A\002\022\026\n\tsignature\030\002 \001(\tB\003\340A" + + "\002\022\'\n\006header\030\003 \001(\0132\027.google.protobuf.Stru" + + "ct\"v\n\032TaskPushNotificationConfig\022\021\n\004name" + + "\030\001 \001(\tB\003\340A\002\022E\n\030push_notification_config\030" + + "\002 \001(\0132\036.a2a.v1.PushNotificationConfigB\003\340" + + "A\002\"\032\n\nStringList\022\014\n\004list\030\001 \003(\t\"~\n\010Securi" + + "ty\022.\n\007schemes\030\001 \003(\0132\035.a2a.v1.Security.Sc" + + "hemesEntry\032B\n\014SchemesEntry\022\013\n\003key\030\001 \001(\t\022" + + "!\n\005value\030\002 \001(\0132\022.a2a.v1.StringList:\0028\001\"\361" + + "\002\n\016SecurityScheme\022?\n\027api_key_security_sc" + + "heme\030\001 \001(\0132\034.a2a.v1.APIKeySecurityScheme" + + "H\000\022C\n\031http_auth_security_scheme\030\002 \001(\0132\036." + + "a2a.v1.HTTPAuthSecuritySchemeH\000\022>\n\026oauth" + + "2_security_scheme\030\003 \001(\0132\034.a2a.v1.OAuth2S" + + "ecuritySchemeH\000\022N\n\037open_id_connect_secur" + + "ity_scheme\030\004 \001(\0132#.a2a.v1.OpenIdConnectS" + + "ecuritySchemeH\000\022?\n\024mtls_security_scheme\030" + + "\005 \001(\0132\037.a2a.v1.MutualTlsSecuritySchemeH\000" + + "B\010\n\006scheme\"U\n\024APIKeySecurityScheme\022\023\n\013de" + + "scription\030\001 \001(\t\022\025\n\010location\030\002 \001(\tB\003\340A\002\022\021" + + "\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026HTTPAuthSecuritySch" + + "eme\022\023\n\013description\030\001 \001(\t\022\023\n\006scheme\030\002 \001(\t" + + "B\003\340A\002\022\025\n\rbearer_format\030\003 \001(\t\"p\n\024OAuth2Se" + + "curityScheme\022\023\n\013description\030\001 \001(\t\022&\n\005flo" + + "ws\030\002 \001(\0132\022.a2a.v1.OAuthFlowsB\003\340A\002\022\033\n\023oau" + + "th2_metadata_url\030\003 \001(\t\"T\n\033OpenIdConnectS" + + "ecurityScheme\022\023\n\013description\030\001 \001(\t\022 \n\023op" + + "en_id_connect_url\030\002 \001(\tB\003\340A\002\".\n\027MutualTl" + + "sSecurityScheme\022\023\n\013description\030\001 \001(\t\"\330\001\n" + + "\nOAuthFlows\022@\n\022authorization_code\030\001 \001(\0132" + + "\".a2a.v1.AuthorizationCodeOAuthFlowH\000\022@\n" + + "\022client_credentials\030\002 \001(\0132\".a2a.v1.Clien" + + "tCredentialsOAuthFlowH\000\0222\n\013device_code\030\005" + + " \001(\0132\033.a2a.v1.DeviceCodeOAuthFlowH\000B\006\n\004f" + + "lowJ\004\010\003\020\004J\004\010\004\020\005\"\364\001\n\032AuthorizationCodeOAu" + + "thFlow\022\036\n\021authorization_url\030\001 \001(\tB\003\340A\002\022\026" + + "\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 " + + "\001(\t\022C\n\006scopes\030\004 \003(\0132..a2a.v1.Authorizati" + + "onCodeOAuthFlow.ScopesEntryB\003\340A\002\022\025\n\rpkce" + + "_required\030\005 \001(\010\032-\n\013ScopesEntry\022\013\n\003key\030\001 " + + "\001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\275\001\n\032ClientCredent" + + "ialsOAuthFlow\022\026\n\ttoken_url\030\001 \001(\tB\003\340A\002\022\023\n" + + "\013refresh_url\030\002 \001(\t\022C\n\006scopes\030\003 \003(\0132..a2a" + + ".v1.ClientCredentialsOAuthFlow.ScopesEnt" + "ryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005v" + - "alue\030\002 \001(\t:\0028\001\"\253\001\n\021PasswordOAuthFlow\022\026\n\t" + - "token_url\030\001 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(" + - "\t\022:\n\006scopes\030\003 \003(\0132%.a2a.v1.PasswordOAuth" + - "Flow.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003" + - "key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\270\001\n\022SendMes" + - "sageRequest\022\016\n\006tenant\030\004 \001(\t\022.\n\007request\030\001" + - " \001(\0132\017.a2a.v1.MessageB\003\340A\002R\007message\0227\n\rc" + - "onfiguration\030\002 \001(\0132 .a2a.v1.SendMessageC" + - "onfiguration\022)\n\010metadata\030\003 \001(\0132\027.google." + - "protobuf.Struct\"c\n\016GetTaskRequest\022\016\n\006ten" + - "ant\030\003 \001(\t\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\033\n\016history_" + - "length\030\002 \001(\005H\000\210\001\001B\021\n\017_history_length\"\225\002\n" + - "\020ListTasksRequest\022\016\n\006tenant\030\t \001(\t\022\022\n\ncon" + - "text_id\030\001 \001(\t\022!\n\006status\030\002 \001(\0162\021.a2a.v1.T" + - "askState\022\026\n\tpage_size\030\003 \001(\005H\000\210\001\001\022\022\n\npage" + - "_token\030\004 \001(\t\022\033\n\016history_length\030\005 \001(\005H\001\210\001" + - "\001\022\032\n\022last_updated_after\030\006 \001(\003\022\036\n\021include" + - "_artifacts\030\007 \001(\010H\002\210\001\001B\014\n\n_page_sizeB\021\n\017_" + - "history_lengthB\024\n\022_include_artifacts\"\204\001\n" + - "\021ListTasksResponse\022 \n\005tasks\030\001 \003(\0132\014.a2a." + - "v1.TaskB\003\340A\002\022\034\n\017next_page_token\030\002 \001(\tB\003\340" + - "A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022\027\n\ntotal_size" + - "\030\004 \001(\005B\003\340A\002\"1\n\021CancelTaskRequest\022\016\n\006tena" + - "nt\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"D\n$GetTaskPushNot" + - "ificationConfigRequest\022\016\n\006tenant\030\002 \001(\t\022\014" + - "\n\004name\030\001 \001(\t\"G\n\'DeleteTaskPushNotificati" + - "onConfigRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004name\030" + - "\001 \001(\t\"\234\001\n$SetTaskPushNotificationConfigR" + - "equest\022\016\n\006tenant\030\004 \001(\t\022\023\n\006parent\030\001 \001(\tB\003" + - "\340A\002\022\026\n\tconfig_id\030\002 \001(\tB\003\340A\002\0227\n\006config\030\003 " + - "\001(\0132\".a2a.v1.TaskPushNotificationConfigB" + - "\003\340A\002\"6\n\026SubscribeToTaskRequest\022\016\n\006tenant" + - "\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"n\n%ListTaskPushNoti" + - "ficationConfigRequest\022\016\n\006tenant\030\004 \001(\t\022\016\n" + - "\006parent\030\001 \001(\t\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npage" + - "_token\030\003 \001(\t\"-\n\033GetExtendedAgentCardRequ" + - "est\022\016\n\006tenant\030\001 \001(\t\"g\n\023SendMessageRespon" + - "se\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022\'\n\003msg\030" + - "\002 \001(\0132\017.a2a.v1.MessageH\000R\007messageB\t\n\007pay" + - "load\"\326\001\n\016StreamResponse\022\034\n\004task\030\001 \001(\0132\014." + - "a2a.v1.TaskH\000\022\'\n\003msg\030\002 \001(\0132\017.a2a.v1.Mess" + - "ageH\000R\007message\0226\n\rstatus_update\030\003 \001(\0132\035." + - "a2a.v1.TaskStatusUpdateEventH\000\022:\n\017artifa" + - "ct_update\030\004 \001(\0132\037.a2a.v1.TaskArtifactUpd" + - "ateEventH\000B\t\n\007payload\"v\n&ListTaskPushNot" + - "ificationConfigResponse\0223\n\007configs\030\001 \003(\013" + - "2\".a2a.v1.TaskPushNotificationConfig\022\027\n\017" + - "next_page_token\030\002 \001(\t*\372\001\n\tTaskState\022\032\n\026T" + - "ASK_STATE_UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SU" + - "BMITTED\020\001\022\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TAS" + - "K_STATE_COMPLETED\020\003\022\025\n\021TASK_STATE_FAILED" + - "\020\004\022\030\n\024TASK_STATE_CANCELLED\020\005\022\035\n\031TASK_STA" + - "TE_INPUT_REQUIRED\020\006\022\027\n\023TASK_STATE_REJECT" + - "ED\020\007\022\034\n\030TASK_STATE_AUTH_REQUIRED\020\010*;\n\004Ro" + - "le\022\024\n\020ROLE_UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022" + - "\016\n\nROLE_AGENT\020\0022\276\016\n\nA2AService\022}\n\013SendMe" + - "ssage\022\032.a2a.v1.SendMessageRequest\032\033.a2a." + - "v1.SendMessageResponse\"5\202\323\344\223\002/\"\r/message" + - ":send:\001*Z\033\"\026/{tenant}/message:send:\001*\022\207\001" + - "\n\024SendStreamingMessage\022\032.a2a.v1.SendMess" + - "ageRequest\032\026.a2a.v1.StreamResponse\"9\202\323\344\223" + - "\0023\"\017/message:stream:\001*Z\035\"\030/{tenant}/mess" + - "age:stream:\001*0\001\022k\n\007GetTask\022\026.a2a.v1.GetT" + - "askRequest\032\014.a2a.v1.Task\":\332A\004name\202\323\344\223\002-\022" + - "\017/{name=tasks/*}Z\032\022\030/{tenant}/{name=task" + - "s/*}\022c\n\tListTasks\022\030.a2a.v1.ListTasksRequ" + - "est\032\031.a2a.v1.ListTasksResponse\"!\202\323\344\223\002\033\022\006" + - "/tasksZ\021\022\017/{tenant}/tasks\022~\n\nCancelTask\022" + - "\031.a2a.v1.CancelTaskRequest\032\014.a2a.v1.Task" + - "\"G\202\323\344\223\002A\"\026/{name=tasks/*}:cancel:\001*Z$\"\037/" + - "{tenant}/{name=tasks/*}:cancel:\001*\022\224\001\n\017Su" + - "bscribeToTask\022\036.a2a.v1.SubscribeToTaskRe" + - "quest\032\026.a2a.v1.StreamResponse\"G\202\323\344\223\002A\022\031/" + - "{name=tasks/*}:subscribeZ$\022\"/{tenant}/{n" + - "ame=tasks/*}:subscribe0\001\022\373\001\n\035SetTaskPush" + - "NotificationConfig\022,.a2a.v1.SetTaskPushN" + - "otificationConfigRequest\032\".a2a.v1.TaskPu" + - "shNotificationConfig\"\207\001\332A\rparent,config\202" + - "\323\344\223\002q\")/{parent=tasks/*/pushNotification" + - "Configs}:\006configZ<\"2/{tenant}/{parent=ta" + - "sks/*/pushNotificationConfigs}:\006config\022\341" + - "\001\n\035GetTaskPushNotificationConfig\022,.a2a.v" + - "1.GetTaskPushNotificationConfigRequest\032\"" + - ".a2a.v1.TaskPushNotificationConfig\"n\332A\004n" + - "ame\202\323\344\223\002a\022)/{name=tasks/*/pushNotificati" + - "onConfigs/*}Z4\0222/{tenant}/{name=tasks/*/" + - "pushNotificationConfigs/*}\022\361\001\n\036ListTaskP" + - "ushNotificationConfig\022-.a2a.v1.ListTaskP" + - "ushNotificationConfigRequest\032..a2a.v1.Li" + - "stTaskPushNotificationConfigResponse\"p\332A" + - "\006parent\202\323\344\223\002a\022)/{parent=tasks/*}/pushNot" + - "ificationConfigsZ4\0222/{tenant}/{parent=ta" + - "sks/*}/pushNotificationConfigs\022\211\001\n\024GetEx" + - "tendedAgentCard\022#.a2a.v1.GetExtendedAgen" + - "tCardRequest\032\021.a2a.v1.AgentCard\"9\202\323\344\223\0023\022" + - "\022/extendedAgentCardZ\035\022\033/{tenant}/extende" + - "dAgentCard\022\333\001\n DeleteTaskPushNotificatio" + - "nConfig\022/.a2a.v1.DeleteTaskPushNotificat" + - "ionConfigRequest\032\026.google.protobuf.Empty" + - "\"n\332A\004name\202\323\344\223\002a*)/{name=tasks/*/pushNoti" + - "ficationConfigs/*}Z4*2/{tenant}/{name=ta" + - "sks/*/pushNotificationConfigs/*}B7\n\013io.a" + - "2a.grpcB\003A2AP\001Z\030google.golang.org/a2a/v1" + - "\252\002\006A2a.V1b\006proto3" + "alue\030\002 \001(\t:\0028\001\"\326\001\n\023DeviceCodeOAuthFlow\022%" + + "\n\030device_authorization_url\030\001 \001(\tB\003\340A\002\022\026\n" + + "\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001" + + "(\t\022<\n\006scopes\030\004 \003(\0132\'.a2a.v1.DeviceCodeOA" + + "uthFlow.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022" + + "\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\257\001\n\022Send" + + "MessageRequest\022\016\n\006tenant\030\004 \001(\t\022%\n\007messag" + + "e\030\001 \001(\0132\017.a2a.v1.MessageB\003\340A\002\0227\n\rconfigu" + + "ration\030\002 \001(\0132 .a2a.v1.SendMessageConfigu" + + "ration\022)\n\010metadata\030\003 \001(\0132\027.google.protob" + + "uf.Struct\"c\n\016GetTaskRequest\022\016\n\006tenant\030\003 " + + "\001(\t\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\033\n\016history_length" + + "\030\002 \001(\005H\000\210\001\001B\021\n\017_history_length\"\265\002\n\020ListT" + + "asksRequest\022\016\n\006tenant\030\t \001(\t\022\022\n\ncontext_i" + + "d\030\001 \001(\t\022!\n\006status\030\002 \001(\0162\021.a2a.v1.TaskSta" + + "te\022\026\n\tpage_size\030\003 \001(\005H\000\210\001\001\022\022\n\npage_token" + + "\030\004 \001(\t\022\033\n\016history_length\030\005 \001(\005H\001\210\001\001\022:\n\026s" + + "tatus_timestamp_after\030\006 \001(\0132\032.google.pro" + + "tobuf.Timestamp\022\036\n\021include_artifacts\030\007 \001" + + "(\010H\002\210\001\001B\014\n\n_page_sizeB\021\n\017_history_length" + + "B\024\n\022_include_artifacts\"\204\001\n\021ListTasksResp" + + "onse\022 \n\005tasks\030\001 \003(\0132\014.a2a.v1.TaskB\003\340A\002\022\034" + + "\n\017next_page_token\030\002 \001(\tB\003\340A\002\022\026\n\tpage_siz" + + "e\030\003 \001(\005B\003\340A\002\022\027\n\ntotal_size\030\004 \001(\005B\003\340A\002\"1\n" + + "\021CancelTaskRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004na" + + "me\030\001 \001(\t\"D\n$GetTaskPushNotificationConfi" + + "gRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"G" + + "\n\'DeleteTaskPushNotificationConfigReques" + + "t\022\016\n\006tenant\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"\234\001\n$SetT" + + "askPushNotificationConfigRequest\022\016\n\006tena" + + "nt\030\004 \001(\t\022\023\n\006parent\030\001 \001(\tB\003\340A\002\022\026\n\tconfig_" + + "id\030\002 \001(\tB\003\340A\002\0227\n\006config\030\003 \001(\0132\".a2a.v1.T" + + "askPushNotificationConfigB\003\340A\002\"6\n\026Subscr" + + "ibeToTaskRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004name" + + "\030\001 \001(\t\"n\n%ListTaskPushNotificationConfig" + + "Request\022\016\n\006tenant\030\004 \001(\t\022\016\n\006parent\030\001 \001(\t\022" + + "\021\n\tpage_size\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t\"-" + + "\n\033GetExtendedAgentCardRequest\022\016\n\006tenant\030" + + "\001 \001(\t\"b\n\023SendMessageResponse\022\034\n\004task\030\001 \001" + + "(\0132\014.a2a.v1.TaskH\000\022\"\n\007message\030\002 \001(\0132\017.a2" + + "a.v1.MessageH\000B\t\n\007payload\"\321\001\n\016StreamResp" + + "onse\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022\"\n\007me" + + "ssage\030\002 \001(\0132\017.a2a.v1.MessageH\000\0226\n\rstatus" + + "_update\030\003 \001(\0132\035.a2a.v1.TaskStatusUpdateE" + + "ventH\000\022:\n\017artifact_update\030\004 \001(\0132\037.a2a.v1" + + ".TaskArtifactUpdateEventH\000B\t\n\007payload\"v\n" + + "&ListTaskPushNotificationConfigResponse\022" + + "3\n\007configs\030\001 \003(\0132\".a2a.v1.TaskPushNotifi" + + "cationConfig\022\027\n\017next_page_token\030\002 \001(\t*\372\001" + + "\n\tTaskState\022\032\n\026TASK_STATE_UNSPECIFIED\020\000\022" + + "\030\n\024TASK_STATE_SUBMITTED\020\001\022\026\n\022TASK_STATE_" + + "WORKING\020\002\022\030\n\024TASK_STATE_COMPLETED\020\003\022\025\n\021T" + + "ASK_STATE_FAILED\020\004\022\030\n\024TASK_STATE_CANCELL" + + "ED\020\005\022\035\n\031TASK_STATE_INPUT_REQUIRED\020\006\022\027\n\023T" + + "ASK_STATE_REJECTED\020\007\022\034\n\030TASK_STATE_AUTH_" + + "REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE_UNSPECIFIED\020\000" + + "\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AGENT\020\0022\276\016\n\nA2AS" + + "ervice\022}\n\013SendMessage\022\032.a2a.v1.SendMessa" + + "geRequest\032\033.a2a.v1.SendMessageResponse\"5" + + "\202\323\344\223\002/\"\r/message:send:\001*Z\033\"\026/{tenant}/me" + + "ssage:send:\001*\022\207\001\n\024SendStreamingMessage\022\032" + + ".a2a.v1.SendMessageRequest\032\026.a2a.v1.Stre" + + "amResponse\"9\202\323\344\223\0023\"\017/message:stream:\001*Z\035" + + "\"\030/{tenant}/message:stream:\001*0\001\022k\n\007GetTa" + + "sk\022\026.a2a.v1.GetTaskRequest\032\014.a2a.v1.Task" + + "\":\332A\004name\202\323\344\223\002-\022\017/{name=tasks/*}Z\032\022\030/{te" + + "nant}/{name=tasks/*}\022c\n\tListTasks\022\030.a2a." + + "v1.ListTasksRequest\032\031.a2a.v1.ListTasksRe" + + "sponse\"!\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tenant}/task" + + "s\022~\n\nCancelTask\022\031.a2a.v1.CancelTaskReque" + + "st\032\014.a2a.v1.Task\"G\202\323\344\223\002A\"\026/{name=tasks/*" + + "}:cancel:\001*Z$\"\037/{tenant}/{name=tasks/*}:" + + "cancel:\001*\022\224\001\n\017SubscribeToTask\022\036.a2a.v1.S" + + "ubscribeToTaskRequest\032\026.a2a.v1.StreamRes" + + "ponse\"G\202\323\344\223\002A\022\031/{name=tasks/*}:subscribe" + + "Z$\022\"/{tenant}/{name=tasks/*}:subscribe0\001" + + "\022\373\001\n\035SetTaskPushNotificationConfig\022,.a2a" + + ".v1.SetTaskPushNotificationConfigRequest" + + "\032\".a2a.v1.TaskPushNotificationConfig\"\207\001\332" + + "A\rparent,config\202\323\344\223\002q\")/{parent=tasks/*/" + + "pushNotificationConfigs}:\006configZ<\"2/{te" + + "nant}/{parent=tasks/*/pushNotificationCo" + + "nfigs}:\006config\022\341\001\n\035GetTaskPushNotificati" + + "onConfig\022,.a2a.v1.GetTaskPushNotificatio" + + "nConfigRequest\032\".a2a.v1.TaskPushNotifica" + + "tionConfig\"n\332A\004name\202\323\344\223\002a\022)/{name=tasks/" + + "*/pushNotificationConfigs/*}Z4\0222/{tenant" + + "}/{name=tasks/*/pushNotificationConfigs/" + + "*}\022\361\001\n\036ListTaskPushNotificationConfig\022-." + + "a2a.v1.ListTaskPushNotificationConfigReq" + + "uest\032..a2a.v1.ListTaskPushNotificationCo" + + "nfigResponse\"p\332A\006parent\202\323\344\223\002a\022)/{parent=" + + "tasks/*}/pushNotificationConfigsZ4\0222/{te" + + "nant}/{parent=tasks/*}/pushNotificationC" + + "onfigs\022\211\001\n\024GetExtendedAgentCard\022#.a2a.v1" + + ".GetExtendedAgentCardRequest\032\021.a2a.v1.Ag" + + "entCard\"9\202\323\344\223\0023\022\022/extendedAgentCardZ\035\022\033/" + + "{tenant}/extendedAgentCard\022\333\001\n DeleteTas" + + "kPushNotificationConfig\022/.a2a.v1.DeleteT" + + "askPushNotificationConfigRequest\032\026.googl" + + "e.protobuf.Empty\"n\332A\004name\202\323\344\223\002a*)/{name=" + + "tasks/*/pushNotificationConfigs/*}Z4*2/{" + + "tenant}/{name=tasks/*/pushNotificationCo" + + "nfigs/*}B7\n\013io.a2a.grpcB\003A2AP\001Z\030google.g" + + "olang.org/a2a/v1\252\002\006A2a.V1b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -639,7 +621,7 @@ public static void registerAllExtensions( internal_static_a2a_v1_AgentCard_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentCard_descriptor, - new java.lang.String[] { "ProtocolVersion", "Name", "Description", "SupportedInterfaces", "Url", "PreferredTransport", "AdditionalInterfaces", "Provider", "Version", "DocumentationUrl", "Capabilities", "SecuritySchemes", "Security", "DefaultInputModes", "DefaultOutputModes", "Skills", "SupportsExtendedAgentCard", "Signatures", "IconUrl", }); + new java.lang.String[] { "ProtocolVersions", "Name", "Description", "SupportedInterfaces", "Provider", "Version", "DocumentationUrl", "Capabilities", "SecuritySchemes", "Security", "DefaultInputModes", "DefaultOutputModes", "Skills", "Signatures", "IconUrl", }); internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor = internal_static_a2a_v1_AgentCard_descriptor.getNestedType(0); internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_fieldAccessorTable = new @@ -657,7 +639,7 @@ public static void registerAllExtensions( internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentCapabilities_descriptor, - new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", "StateTransitionHistory", }); + new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", "StateTransitionHistory", "ExtendedAgentCard", }); internal_static_a2a_v1_AgentExtension_descriptor = getDescriptor().getMessageType(16); internal_static_a2a_v1_AgentExtension_fieldAccessorTable = new @@ -741,13 +723,13 @@ public static void registerAllExtensions( internal_static_a2a_v1_OAuthFlows_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_OAuthFlows_descriptor, - new java.lang.String[] { "AuthorizationCode", "ClientCredentials", "Implicit", "Password", "Flow", }); + new java.lang.String[] { "AuthorizationCode", "ClientCredentials", "DeviceCode", "Flow", }); internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor = getDescriptor().getMessageType(29); internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor, - new java.lang.String[] { "AuthorizationUrl", "TokenUrl", "RefreshUrl", "Scopes", }); + new java.lang.String[] { "AuthorizationUrl", "TokenUrl", "RefreshUrl", "Scopes", "PkceRequired", }); internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor = internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor.getNestedType(0); internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new @@ -766,110 +748,98 @@ public static void registerAllExtensions( com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor = + internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor = getDescriptor().getMessageType(31); - internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable = new + internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor, - new java.lang.String[] { "AuthorizationUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable = new + internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor, + new java.lang.String[] { "DeviceAuthorizationUrl", "TokenUrl", "RefreshUrl", "Scopes", }); + internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor = + internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor.getNestedType(0); + internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_PasswordOAuthFlow_descriptor = - getDescriptor().getMessageType(32); - internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_PasswordOAuthFlow_descriptor, - new java.lang.String[] { "TokenUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_PasswordOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, + internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_a2a_v1_SendMessageRequest_descriptor = - getDescriptor().getMessageType(33); + getDescriptor().getMessageType(32); internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_SendMessageRequest_descriptor, - new java.lang.String[] { "Tenant", "Request", "Configuration", "Metadata", }); + new java.lang.String[] { "Tenant", "Message", "Configuration", "Metadata", }); internal_static_a2a_v1_GetTaskRequest_descriptor = - getDescriptor().getMessageType(34); + getDescriptor().getMessageType(33); internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_GetTaskRequest_descriptor, new java.lang.String[] { "Tenant", "Name", "HistoryLength", }); internal_static_a2a_v1_ListTasksRequest_descriptor = - getDescriptor().getMessageType(35); + getDescriptor().getMessageType(34); internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_ListTasksRequest_descriptor, - new java.lang.String[] { "Tenant", "ContextId", "Status", "PageSize", "PageToken", "HistoryLength", "LastUpdatedAfter", "IncludeArtifacts", }); + new java.lang.String[] { "Tenant", "ContextId", "Status", "PageSize", "PageToken", "HistoryLength", "StatusTimestampAfter", "IncludeArtifacts", }); internal_static_a2a_v1_ListTasksResponse_descriptor = - getDescriptor().getMessageType(36); + getDescriptor().getMessageType(35); internal_static_a2a_v1_ListTasksResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_ListTasksResponse_descriptor, new java.lang.String[] { "Tasks", "NextPageToken", "PageSize", "TotalSize", }); internal_static_a2a_v1_CancelTaskRequest_descriptor = - getDescriptor().getMessageType(37); + getDescriptor().getMessageType(36); internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_CancelTaskRequest_descriptor, new java.lang.String[] { "Tenant", "Name", }); internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(38); + getDescriptor().getMessageType(37); internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "Name", }); internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(39); + getDescriptor().getMessageType(38); internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "Name", }); internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(40); + getDescriptor().getMessageType(39); internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "Parent", "ConfigId", "Config", }); internal_static_a2a_v1_SubscribeToTaskRequest_descriptor = - getDescriptor().getMessageType(41); + getDescriptor().getMessageType(40); internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_SubscribeToTaskRequest_descriptor, new java.lang.String[] { "Tenant", "Name", }); internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(42); + getDescriptor().getMessageType(41); internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "Parent", "PageSize", "PageToken", }); internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor = - getDescriptor().getMessageType(43); + getDescriptor().getMessageType(42); internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor, new java.lang.String[] { "Tenant", }); internal_static_a2a_v1_SendMessageResponse_descriptor = - getDescriptor().getMessageType(44); + getDescriptor().getMessageType(43); internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_SendMessageResponse_descriptor, - new java.lang.String[] { "Task", "Msg", "Payload", }); + new java.lang.String[] { "Task", "Message", "Payload", }); internal_static_a2a_v1_StreamResponse_descriptor = - getDescriptor().getMessageType(45); + getDescriptor().getMessageType(44); internal_static_a2a_v1_StreamResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_StreamResponse_descriptor, - new java.lang.String[] { "Task", "Msg", "StatusUpdate", "ArtifactUpdate", "Payload", }); + new java.lang.String[] { "Task", "Message", "StatusUpdate", "ArtifactUpdate", "Payload", }); internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor = - getDescriptor().getMessageType(46); + getDescriptor().getMessageType(45); internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor, diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java index 84ef70448..2e6c44ab8 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java @@ -192,6 +192,33 @@ public boolean getStateTransitionHistory() { return stateTransitionHistory_; } + public static final int EXTENDED_AGENT_CARD_FIELD_NUMBER = 5; + private boolean extendedAgentCard_ = false; + /** + *
    +   * Indicates if the agent supports providing an extended agent card when authenticated.
    +   * 
    + * + * optional bool extended_agent_card = 5; + * @return Whether the extendedAgentCard field is set. + */ + @java.lang.Override + public boolean hasExtendedAgentCard() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + *
    +   * Indicates if the agent supports providing an extended agent card when authenticated.
    +   * 
    + * + * optional bool extended_agent_card = 5; + * @return The extendedAgentCard. + */ + @java.lang.Override + public boolean getExtendedAgentCard() { + return extendedAgentCard_; + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -218,6 +245,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (((bitField0_ & 0x00000004) != 0)) { output.writeBool(4, stateTransitionHistory_); } + if (((bitField0_ & 0x00000008) != 0)) { + output.writeBool(5, extendedAgentCard_); + } getUnknownFields().writeTo(output); } @@ -243,6 +273,10 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeBoolSize(4, stateTransitionHistory_); } + if (((bitField0_ & 0x00000008) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(5, extendedAgentCard_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -275,6 +309,11 @@ public boolean equals(final java.lang.Object obj) { if (getStateTransitionHistory() != other.getStateTransitionHistory()) return false; } + if (hasExtendedAgentCard() != other.hasExtendedAgentCard()) return false; + if (hasExtendedAgentCard()) { + if (getExtendedAgentCard() + != other.getExtendedAgentCard()) return false; + } if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -305,6 +344,11 @@ public int hashCode() { hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( getStateTransitionHistory()); } + if (hasExtendedAgentCard()) { + hash = (37 * hash) + EXTENDED_AGENT_CARD_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getExtendedAgentCard()); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -451,6 +495,7 @@ public Builder clear() { } bitField0_ = (bitField0_ & ~0x00000004); stateTransitionHistory_ = false; + extendedAgentCard_ = false; return this; } @@ -510,6 +555,10 @@ private void buildPartial0(io.a2a.grpc.AgentCapabilities result) { result.stateTransitionHistory_ = stateTransitionHistory_; to_bitField0_ |= 0x00000004; } + if (((from_bitField0_ & 0x00000010) != 0)) { + result.extendedAgentCard_ = extendedAgentCard_; + to_bitField0_ |= 0x00000008; + } result.bitField0_ |= to_bitField0_; } @@ -560,6 +609,9 @@ public Builder mergeFrom(io.a2a.grpc.AgentCapabilities other) { if (other.hasStateTransitionHistory()) { setStateTransitionHistory(other.getStateTransitionHistory()); } + if (other.hasExtendedAgentCard()) { + setExtendedAgentCard(other.getExtendedAgentCard()); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -614,6 +666,11 @@ public Builder mergeFrom( bitField0_ |= 0x00000008; break; } // case 32 + case 40: { + extendedAgentCard_ = input.readBool(); + bitField0_ |= 0x00000010; + break; + } // case 40 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -1111,6 +1168,62 @@ public Builder clearStateTransitionHistory() { return this; } + private boolean extendedAgentCard_ ; + /** + *
    +     * Indicates if the agent supports providing an extended agent card when authenticated.
    +     * 
    + * + * optional bool extended_agent_card = 5; + * @return Whether the extendedAgentCard field is set. + */ + @java.lang.Override + public boolean hasExtendedAgentCard() { + return ((bitField0_ & 0x00000010) != 0); + } + /** + *
    +     * Indicates if the agent supports providing an extended agent card when authenticated.
    +     * 
    + * + * optional bool extended_agent_card = 5; + * @return The extendedAgentCard. + */ + @java.lang.Override + public boolean getExtendedAgentCard() { + return extendedAgentCard_; + } + /** + *
    +     * Indicates if the agent supports providing an extended agent card when authenticated.
    +     * 
    + * + * optional bool extended_agent_card = 5; + * @param value The extendedAgentCard to set. + * @return This builder for chaining. + */ + public Builder setExtendedAgentCard(boolean value) { + + extendedAgentCard_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
    +     * Indicates if the agent supports providing an extended agent card when authenticated.
    +     * 
    + * + * optional bool extended_agent_card = 5; + * @return This builder for chaining. + */ + public Builder clearExtendedAgentCard() { + bitField0_ = (bitField0_ & ~0x00000010); + extendedAgentCard_ = false; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCapabilities) } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java index df5d9277c..b084db7ee 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java @@ -110,4 +110,23 @@ io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( * @return The stateTransitionHistory. */ boolean getStateTransitionHistory(); + + /** + *
    +   * Indicates if the agent supports providing an extended agent card when authenticated.
    +   * 
    + * + * optional bool extended_agent_card = 5; + * @return Whether the extendedAgentCard field is set. + */ + boolean hasExtendedAgentCard(); + /** + *
    +   * Indicates if the agent supports providing an extended agent card when authenticated.
    +   * 
    + * + * optional bool extended_agent_card = 5; + * @return The extendedAgentCard. + */ + boolean getExtendedAgentCard(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java index b352e84f5..5111e4f12 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java @@ -36,13 +36,11 @@ private AgentCard(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); } private AgentCard() { - protocolVersion_ = ""; + protocolVersions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); name_ = ""; description_ = ""; supportedInterfaces_ = java.util.Collections.emptyList(); - url_ = ""; - preferredTransport_ = ""; - additionalInterfaces_ = java.util.Collections.emptyList(); version_ = ""; documentationUrl_ = ""; security_ = java.util.Collections.emptyList(); @@ -81,66 +79,69 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl } private int bitField0_; - public static final int PROTOCOL_VERSION_FIELD_NUMBER = 16; + public static final int PROTOCOL_VERSIONS_FIELD_NUMBER = 16; @SuppressWarnings("serial") - private volatile java.lang.Object protocolVersion_ = ""; + private com.google.protobuf.LazyStringArrayList protocolVersions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); /** *
    -   * The version of the A2A protocol this agent supports.
    -   * Default: "1.0"
    +   * The versions of the A2A protocol this agent supports.
    +   * For stable versions (1.x+), list only the latest supported minor version per major version.
    +   * For legacy experimental versions (0.x), explicitly list each supported version.
    +   * Default: ["1.0"]
        * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the protocolVersion field is set. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @return A list containing the protocolVersions. */ - @java.lang.Override - public boolean hasProtocolVersion() { - return ((bitField0_ & 0x00000001) != 0); + public com.google.protobuf.ProtocolStringList + getProtocolVersionsList() { + return protocolVersions_; } /** *
    -   * The version of the A2A protocol this agent supports.
    -   * Default: "1.0"
    +   * The versions of the A2A protocol this agent supports.
    +   * For stable versions (1.x+), list only the latest supported minor version per major version.
    +   * For legacy experimental versions (0.x), explicitly list each supported version.
    +   * Default: ["1.0"]
        * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolVersion. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @return The count of protocolVersions. */ - @java.lang.Override - public java.lang.String getProtocolVersion() { - java.lang.Object ref = protocolVersion_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - protocolVersion_ = s; - return s; - } + public int getProtocolVersionsCount() { + return protocolVersions_.size(); } /** *
    -   * The version of the A2A protocol this agent supports.
    -   * Default: "1.0"
    +   * The versions of the A2A protocol this agent supports.
    +   * For stable versions (1.x+), list only the latest supported minor version per major version.
    +   * For legacy experimental versions (0.x), explicitly list each supported version.
    +   * Default: ["1.0"]
        * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolVersion. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param index The index of the element to return. + * @return The protocolVersions at the given index. + */ + public java.lang.String getProtocolVersions(int index) { + return protocolVersions_.get(index); + } + /** + *
    +   * The versions of the A2A protocol this agent supports.
    +   * For stable versions (1.x+), list only the latest supported minor version per major version.
    +   * For legacy experimental versions (0.x), explicitly list each supported version.
    +   * Default: ["1.0"]
    +   * 
    + * + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param index The index of the value to return. + * @return The bytes of the protocolVersions at the given index. */ - @java.lang.Override public com.google.protobuf.ByteString - getProtocolVersionBytes() { - java.lang.Object ref = protocolVersion_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protocolVersion_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } + getProtocolVersionsBytes(int index) { + return protocolVersions_.getByteString(index); } public static final int NAME_FIELD_NUMBER = 1; @@ -251,7 +252,7 @@ public java.lang.String getDescription() { * Ordered list of supported interfaces. First entry is preferred. * * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List getSupportedInterfacesList() { @@ -262,7 +263,7 @@ public java.util.List getSupportedInterfacesList() { * Ordered list of supported interfaces. First entry is preferred. * * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List @@ -274,7 +275,7 @@ public java.util.List getSupportedInterfacesList() { * Ordered list of supported interfaces. First entry is preferred. * * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public int getSupportedInterfacesCount() { @@ -285,7 +286,7 @@ public int getSupportedInterfacesCount() { * Ordered list of supported interfaces. First entry is preferred. * * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { @@ -296,7 +297,7 @@ public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { * Ordered list of supported interfaces. First entry is preferred. * * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( @@ -304,197 +305,6 @@ public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( return supportedInterfaces_.get(index); } - public static final int URL_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object url_ = ""; - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return Whether the url field is set. - */ - @java.lang.Override - @java.lang.Deprecated public boolean hasUrl() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return The url. - */ - @java.lang.Override - @java.lang.Deprecated public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } - } - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return The bytes for url. - */ - @java.lang.Override - @java.lang.Deprecated public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PREFERRED_TRANSPORT_FIELD_NUMBER = 14; - @SuppressWarnings("serial") - private volatile java.lang.Object preferredTransport_ = ""; - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return Whether the preferredTransport field is set. - */ - @java.lang.Override - @java.lang.Deprecated public boolean hasPreferredTransport() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return The preferredTransport. - */ - @java.lang.Override - @java.lang.Deprecated public java.lang.String getPreferredTransport() { - java.lang.Object ref = preferredTransport_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - preferredTransport_ = s; - return s; - } - } - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return The bytes for preferredTransport. - */ - @java.lang.Override - @java.lang.Deprecated public com.google.protobuf.ByteString - getPreferredTransportBytes() { - java.lang.Object ref = preferredTransport_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - preferredTransport_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ADDITIONAL_INTERFACES_FIELD_NUMBER = 15; - @SuppressWarnings("serial") - private java.util.List additionalInterfaces_; - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public java.util.List getAdditionalInterfacesList() { - return additionalInterfaces_; - } - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public java.util.List - getAdditionalInterfacesOrBuilderList() { - return additionalInterfaces_; - } - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public int getAdditionalInterfacesCount() { - return additionalInterfaces_.size(); - } - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.AgentInterface getAdditionalInterfaces(int index) { - return additionalInterfaces_.get(index); - } - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.AgentInterfaceOrBuilder getAdditionalInterfacesOrBuilder( - int index) { - return additionalInterfaces_.get(index); - } - public static final int PROVIDER_FIELD_NUMBER = 4; private io.a2a.grpc.AgentProvider provider_; /** @@ -507,7 +317,7 @@ public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( */ @java.lang.Override public boolean hasProvider() { - return ((bitField0_ & 0x00000008) != 0); + return ((bitField0_ & 0x00000001) != 0); } /** *
    @@ -595,7 +405,7 @@ public java.lang.String getVersion() {
        */
       @java.lang.Override
       public boolean hasDocumentationUrl() {
    -    return ((bitField0_ & 0x00000010) != 0);
    +    return ((bitField0_ & 0x00000002) != 0);
       }
       /**
        * 
    @@ -653,7 +463,7 @@ public java.lang.String getDocumentationUrl() {
        */
       @java.lang.Override
       public boolean hasCapabilities() {
    -    return ((bitField0_ & 0x00000020) != 0);
    +    return ((bitField0_ & 0x00000004) != 0);
       }
       /**
        * 
    @@ -1025,33 +835,6 @@ public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
         return skills_.get(index);
       }
     
    -  public static final int SUPPORTS_EXTENDED_AGENT_CARD_FIELD_NUMBER = 13;
    -  private boolean supportsExtendedAgentCard_ = false;
    -  /**
    -   * 
    -   * Whether the agent supports providing an extended agent card when authenticated.
    -   * 
    - * - * optional bool supports_extended_agent_card = 13; - * @return Whether the supportsExtendedAgentCard field is set. - */ - @java.lang.Override - public boolean hasSupportsExtendedAgentCard() { - return ((bitField0_ & 0x00000040) != 0); - } - /** - *
    -   * Whether the agent supports providing an extended agent card when authenticated.
    -   * 
    - * - * optional bool supports_extended_agent_card = 13; - * @return The supportsExtendedAgentCard. - */ - @java.lang.Override - public boolean getSupportsExtendedAgentCard() { - return supportsExtendedAgentCard_; - } - public static final int SIGNATURES_FIELD_NUMBER = 17; @SuppressWarnings("serial") private java.util.List signatures_; @@ -1126,7 +909,7 @@ public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( */ @java.lang.Override public boolean hasIconUrl() { - return ((bitField0_ & 0x00000080) != 0); + return ((bitField0_ & 0x00000008) != 0); } /** *
    @@ -1192,19 +975,16 @@ public void writeTo(com.google.protobuf.CodedOutputStream output)
         if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) {
           com.google.protobuf.GeneratedMessage.writeString(output, 2, description_);
         }
    -    if (((bitField0_ & 0x00000002) != 0)) {
    -      com.google.protobuf.GeneratedMessage.writeString(output, 3, url_);
    -    }
    -    if (((bitField0_ & 0x00000008) != 0)) {
    +    if (((bitField0_ & 0x00000001) != 0)) {
           output.writeMessage(4, getProvider());
         }
         if (!com.google.protobuf.GeneratedMessage.isStringEmpty(version_)) {
           com.google.protobuf.GeneratedMessage.writeString(output, 5, version_);
         }
    -    if (((bitField0_ & 0x00000010) != 0)) {
    +    if (((bitField0_ & 0x00000002) != 0)) {
           com.google.protobuf.GeneratedMessage.writeString(output, 6, documentationUrl_);
         }
    -    if (((bitField0_ & 0x00000020) != 0)) {
    +    if (((bitField0_ & 0x00000004) != 0)) {
           output.writeMessage(7, getCapabilities());
         }
         com.google.protobuf.GeneratedMessage
    @@ -1225,22 +1005,13 @@ public void writeTo(com.google.protobuf.CodedOutputStream output)
         for (int i = 0; i < skills_.size(); i++) {
           output.writeMessage(12, skills_.get(i));
         }
    -    if (((bitField0_ & 0x00000040) != 0)) {
    -      output.writeBool(13, supportsExtendedAgentCard_);
    -    }
    -    if (((bitField0_ & 0x00000004) != 0)) {
    -      com.google.protobuf.GeneratedMessage.writeString(output, 14, preferredTransport_);
    -    }
    -    for (int i = 0; i < additionalInterfaces_.size(); i++) {
    -      output.writeMessage(15, additionalInterfaces_.get(i));
    -    }
    -    if (((bitField0_ & 0x00000001) != 0)) {
    -      com.google.protobuf.GeneratedMessage.writeString(output, 16, protocolVersion_);
    +    for (int i = 0; i < protocolVersions_.size(); i++) {
    +      com.google.protobuf.GeneratedMessage.writeString(output, 16, protocolVersions_.getRaw(i));
         }
         for (int i = 0; i < signatures_.size(); i++) {
           output.writeMessage(17, signatures_.get(i));
         }
    -    if (((bitField0_ & 0x00000080) != 0)) {
    +    if (((bitField0_ & 0x00000008) != 0)) {
           com.google.protobuf.GeneratedMessage.writeString(output, 18, iconUrl_);
         }
         for (int i = 0; i < supportedInterfaces_.size(); i++) {
    @@ -1261,20 +1032,17 @@ public int getSerializedSize() {
         if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) {
           size += com.google.protobuf.GeneratedMessage.computeStringSize(2, description_);
         }
    -    if (((bitField0_ & 0x00000002) != 0)) {
    -      size += com.google.protobuf.GeneratedMessage.computeStringSize(3, url_);
    -    }
    -    if (((bitField0_ & 0x00000008) != 0)) {
    +    if (((bitField0_ & 0x00000001) != 0)) {
           size += com.google.protobuf.CodedOutputStream
             .computeMessageSize(4, getProvider());
         }
         if (!com.google.protobuf.GeneratedMessage.isStringEmpty(version_)) {
           size += com.google.protobuf.GeneratedMessage.computeStringSize(5, version_);
         }
    -    if (((bitField0_ & 0x00000010) != 0)) {
    +    if (((bitField0_ & 0x00000002) != 0)) {
           size += com.google.protobuf.GeneratedMessage.computeStringSize(6, documentationUrl_);
         }
    -    if (((bitField0_ & 0x00000020) != 0)) {
    +    if (((bitField0_ & 0x00000004) != 0)) {
           size += com.google.protobuf.CodedOutputStream
             .computeMessageSize(7, getCapabilities());
         }
    @@ -1312,25 +1080,19 @@ public int getSerializedSize() {
           size += com.google.protobuf.CodedOutputStream
             .computeMessageSize(12, skills_.get(i));
         }
    -    if (((bitField0_ & 0x00000040) != 0)) {
    -      size += com.google.protobuf.CodedOutputStream
    -        .computeBoolSize(13, supportsExtendedAgentCard_);
    -    }
    -    if (((bitField0_ & 0x00000004) != 0)) {
    -      size += com.google.protobuf.GeneratedMessage.computeStringSize(14, preferredTransport_);
    -    }
    -    for (int i = 0; i < additionalInterfaces_.size(); i++) {
    -      size += com.google.protobuf.CodedOutputStream
    -        .computeMessageSize(15, additionalInterfaces_.get(i));
    -    }
    -    if (((bitField0_ & 0x00000001) != 0)) {
    -      size += com.google.protobuf.GeneratedMessage.computeStringSize(16, protocolVersion_);
    +    {
    +      int dataSize = 0;
    +      for (int i = 0; i < protocolVersions_.size(); i++) {
    +        dataSize += computeStringSizeNoTag(protocolVersions_.getRaw(i));
    +      }
    +      size += dataSize;
    +      size += 2 * getProtocolVersionsList().size();
         }
         for (int i = 0; i < signatures_.size(); i++) {
           size += com.google.protobuf.CodedOutputStream
             .computeMessageSize(17, signatures_.get(i));
         }
    -    if (((bitField0_ & 0x00000080) != 0)) {
    +    if (((bitField0_ & 0x00000008) != 0)) {
           size += com.google.protobuf.GeneratedMessage.computeStringSize(18, iconUrl_);
         }
         for (int i = 0; i < supportedInterfaces_.size(); i++) {
    @@ -1352,29 +1114,14 @@ public boolean equals(final java.lang.Object obj) {
         }
         io.a2a.grpc.AgentCard other = (io.a2a.grpc.AgentCard) obj;
     
    -    if (hasProtocolVersion() != other.hasProtocolVersion()) return false;
    -    if (hasProtocolVersion()) {
    -      if (!getProtocolVersion()
    -          .equals(other.getProtocolVersion())) return false;
    -    }
    +    if (!getProtocolVersionsList()
    +        .equals(other.getProtocolVersionsList())) return false;
         if (!getName()
             .equals(other.getName())) return false;
         if (!getDescription()
             .equals(other.getDescription())) return false;
         if (!getSupportedInterfacesList()
             .equals(other.getSupportedInterfacesList())) return false;
    -    if (hasUrl() != other.hasUrl()) return false;
    -    if (hasUrl()) {
    -      if (!getUrl()
    -          .equals(other.getUrl())) return false;
    -    }
    -    if (hasPreferredTransport() != other.hasPreferredTransport()) return false;
    -    if (hasPreferredTransport()) {
    -      if (!getPreferredTransport()
    -          .equals(other.getPreferredTransport())) return false;
    -    }
    -    if (!getAdditionalInterfacesList()
    -        .equals(other.getAdditionalInterfacesList())) return false;
         if (hasProvider() != other.hasProvider()) return false;
         if (hasProvider()) {
           if (!getProvider()
    @@ -1402,11 +1149,6 @@ public boolean equals(final java.lang.Object obj) {
             .equals(other.getDefaultOutputModesList())) return false;
         if (!getSkillsList()
             .equals(other.getSkillsList())) return false;
    -    if (hasSupportsExtendedAgentCard() != other.hasSupportsExtendedAgentCard()) return false;
    -    if (hasSupportsExtendedAgentCard()) {
    -      if (getSupportsExtendedAgentCard()
    -          != other.getSupportsExtendedAgentCard()) return false;
    -    }
         if (!getSignaturesList()
             .equals(other.getSignaturesList())) return false;
         if (hasIconUrl() != other.hasIconUrl()) return false;
    @@ -1425,9 +1167,9 @@ public int hashCode() {
         }
         int hash = 41;
         hash = (19 * hash) + getDescriptor().hashCode();
    -    if (hasProtocolVersion()) {
    -      hash = (37 * hash) + PROTOCOL_VERSION_FIELD_NUMBER;
    -      hash = (53 * hash) + getProtocolVersion().hashCode();
    +    if (getProtocolVersionsCount() > 0) {
    +      hash = (37 * hash) + PROTOCOL_VERSIONS_FIELD_NUMBER;
    +      hash = (53 * hash) + getProtocolVersionsList().hashCode();
         }
         hash = (37 * hash) + NAME_FIELD_NUMBER;
         hash = (53 * hash) + getName().hashCode();
    @@ -1437,18 +1179,6 @@ public int hashCode() {
           hash = (37 * hash) + SUPPORTED_INTERFACES_FIELD_NUMBER;
           hash = (53 * hash) + getSupportedInterfacesList().hashCode();
         }
    -    if (hasUrl()) {
    -      hash = (37 * hash) + URL_FIELD_NUMBER;
    -      hash = (53 * hash) + getUrl().hashCode();
    -    }
    -    if (hasPreferredTransport()) {
    -      hash = (37 * hash) + PREFERRED_TRANSPORT_FIELD_NUMBER;
    -      hash = (53 * hash) + getPreferredTransport().hashCode();
    -    }
    -    if (getAdditionalInterfacesCount() > 0) {
    -      hash = (37 * hash) + ADDITIONAL_INTERFACES_FIELD_NUMBER;
    -      hash = (53 * hash) + getAdditionalInterfacesList().hashCode();
    -    }
         if (hasProvider()) {
           hash = (37 * hash) + PROVIDER_FIELD_NUMBER;
           hash = (53 * hash) + getProvider().hashCode();
    @@ -1483,11 +1213,6 @@ public int hashCode() {
           hash = (37 * hash) + SKILLS_FIELD_NUMBER;
           hash = (53 * hash) + getSkillsList().hashCode();
         }
    -    if (hasSupportsExtendedAgentCard()) {
    -      hash = (37 * hash) + SUPPORTS_EXTENDED_AGENT_CARD_FIELD_NUMBER;
    -      hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
    -          getSupportsExtendedAgentCard());
    -    }
         if (getSignaturesCount() > 0) {
           hash = (37 * hash) + SIGNATURES_FIELD_NUMBER;
           hash = (53 * hash) + getSignaturesList().hashCode();
    @@ -1657,7 +1382,6 @@ private void maybeForceBuilderInitialization() {
           if (com.google.protobuf.GeneratedMessage
                   .alwaysUseFieldBuilders) {
             internalGetSupportedInterfacesFieldBuilder();
    -        internalGetAdditionalInterfacesFieldBuilder();
             internalGetProviderFieldBuilder();
             internalGetCapabilitiesFieldBuilder();
             internalGetSecurityFieldBuilder();
    @@ -1669,7 +1393,8 @@ private void maybeForceBuilderInitialization() {
         public Builder clear() {
           super.clear();
           bitField0_ = 0;
    -      protocolVersion_ = "";
    +      protocolVersions_ =
    +          com.google.protobuf.LazyStringArrayList.emptyList();
           name_ = "";
           description_ = "";
           if (supportedInterfacesBuilder_ == null) {
    @@ -1679,15 +1404,6 @@ public Builder clear() {
             supportedInterfacesBuilder_.clear();
           }
           bitField0_ = (bitField0_ & ~0x00000008);
    -      url_ = "";
    -      preferredTransport_ = "";
    -      if (additionalInterfacesBuilder_ == null) {
    -        additionalInterfaces_ = java.util.Collections.emptyList();
    -      } else {
    -        additionalInterfaces_ = null;
    -        additionalInterfacesBuilder_.clear();
    -      }
    -      bitField0_ = (bitField0_ & ~0x00000040);
           provider_ = null;
           if (providerBuilder_ != null) {
             providerBuilder_.dispose();
    @@ -1707,7 +1423,7 @@ public Builder clear() {
             security_ = null;
             securityBuilder_.clear();
           }
    -      bitField0_ = (bitField0_ & ~0x00001000);
    +      bitField0_ = (bitField0_ & ~0x00000200);
           defaultInputModes_ =
               com.google.protobuf.LazyStringArrayList.emptyList();
           defaultOutputModes_ =
    @@ -1718,15 +1434,14 @@ public Builder clear() {
             skills_ = null;
             skillsBuilder_.clear();
           }
    -      bitField0_ = (bitField0_ & ~0x00008000);
    -      supportsExtendedAgentCard_ = false;
    +      bitField0_ = (bitField0_ & ~0x00001000);
           if (signaturesBuilder_ == null) {
             signatures_ = java.util.Collections.emptyList();
           } else {
             signatures_ = null;
             signaturesBuilder_.clear();
           }
    -      bitField0_ = (bitField0_ & ~0x00020000);
    +      bitField0_ = (bitField0_ & ~0x00002000);
           iconUrl_ = "";
           return this;
         }
    @@ -1770,37 +1485,28 @@ private void buildPartialRepeatedFields(io.a2a.grpc.AgentCard result) {
           } else {
             result.supportedInterfaces_ = supportedInterfacesBuilder_.build();
           }
    -      if (additionalInterfacesBuilder_ == null) {
    -        if (((bitField0_ & 0x00000040) != 0)) {
    -          additionalInterfaces_ = java.util.Collections.unmodifiableList(additionalInterfaces_);
    -          bitField0_ = (bitField0_ & ~0x00000040);
    -        }
    -        result.additionalInterfaces_ = additionalInterfaces_;
    -      } else {
    -        result.additionalInterfaces_ = additionalInterfacesBuilder_.build();
    -      }
           if (securityBuilder_ == null) {
    -        if (((bitField0_ & 0x00001000) != 0)) {
    +        if (((bitField0_ & 0x00000200) != 0)) {
               security_ = java.util.Collections.unmodifiableList(security_);
    -          bitField0_ = (bitField0_ & ~0x00001000);
    +          bitField0_ = (bitField0_ & ~0x00000200);
             }
             result.security_ = security_;
           } else {
             result.security_ = securityBuilder_.build();
           }
           if (skillsBuilder_ == null) {
    -        if (((bitField0_ & 0x00008000) != 0)) {
    +        if (((bitField0_ & 0x00001000) != 0)) {
               skills_ = java.util.Collections.unmodifiableList(skills_);
    -          bitField0_ = (bitField0_ & ~0x00008000);
    +          bitField0_ = (bitField0_ & ~0x00001000);
             }
             result.skills_ = skills_;
           } else {
             result.skills_ = skillsBuilder_.build();
           }
           if (signaturesBuilder_ == null) {
    -        if (((bitField0_ & 0x00020000) != 0)) {
    +        if (((bitField0_ & 0x00002000) != 0)) {
               signatures_ = java.util.Collections.unmodifiableList(signatures_);
    -          bitField0_ = (bitField0_ & ~0x00020000);
    +          bitField0_ = (bitField0_ & ~0x00002000);
             }
             result.signatures_ = signatures_;
           } else {
    @@ -1810,10 +1516,9 @@ private void buildPartialRepeatedFields(io.a2a.grpc.AgentCard result) {
     
         private void buildPartial0(io.a2a.grpc.AgentCard result) {
           int from_bitField0_ = bitField0_;
    -      int to_bitField0_ = 0;
           if (((from_bitField0_ & 0x00000001) != 0)) {
    -        result.protocolVersion_ = protocolVersion_;
    -        to_bitField0_ |= 0x00000001;
    +        protocolVersions_.makeImmutable();
    +        result.protocolVersions_ = protocolVersions_;
           }
           if (((from_bitField0_ & 0x00000002) != 0)) {
             result.name_ = name_;
    @@ -1821,51 +1526,40 @@ private void buildPartial0(io.a2a.grpc.AgentCard result) {
           if (((from_bitField0_ & 0x00000004) != 0)) {
             result.description_ = description_;
           }
    +      int to_bitField0_ = 0;
           if (((from_bitField0_ & 0x00000010) != 0)) {
    -        result.url_ = url_;
    -        to_bitField0_ |= 0x00000002;
    -      }
    -      if (((from_bitField0_ & 0x00000020) != 0)) {
    -        result.preferredTransport_ = preferredTransport_;
    -        to_bitField0_ |= 0x00000004;
    -      }
    -      if (((from_bitField0_ & 0x00000080) != 0)) {
             result.provider_ = providerBuilder_ == null
                 ? provider_
                 : providerBuilder_.build();
    -        to_bitField0_ |= 0x00000008;
    +        to_bitField0_ |= 0x00000001;
           }
    -      if (((from_bitField0_ & 0x00000100) != 0)) {
    +      if (((from_bitField0_ & 0x00000020) != 0)) {
             result.version_ = version_;
           }
    -      if (((from_bitField0_ & 0x00000200) != 0)) {
    +      if (((from_bitField0_ & 0x00000040) != 0)) {
             result.documentationUrl_ = documentationUrl_;
    -        to_bitField0_ |= 0x00000010;
    +        to_bitField0_ |= 0x00000002;
           }
    -      if (((from_bitField0_ & 0x00000400) != 0)) {
    +      if (((from_bitField0_ & 0x00000080) != 0)) {
             result.capabilities_ = capabilitiesBuilder_ == null
                 ? capabilities_
                 : capabilitiesBuilder_.build();
    -        to_bitField0_ |= 0x00000020;
    +        to_bitField0_ |= 0x00000004;
           }
    -      if (((from_bitField0_ & 0x00000800) != 0)) {
    +      if (((from_bitField0_ & 0x00000100) != 0)) {
             result.securitySchemes_ = internalGetSecuritySchemes().build(SecuritySchemesDefaultEntryHolder.defaultEntry);
           }
    -      if (((from_bitField0_ & 0x00002000) != 0)) {
    +      if (((from_bitField0_ & 0x00000400) != 0)) {
             defaultInputModes_.makeImmutable();
             result.defaultInputModes_ = defaultInputModes_;
           }
    -      if (((from_bitField0_ & 0x00004000) != 0)) {
    +      if (((from_bitField0_ & 0x00000800) != 0)) {
             defaultOutputModes_.makeImmutable();
             result.defaultOutputModes_ = defaultOutputModes_;
           }
    -      if (((from_bitField0_ & 0x00010000) != 0)) {
    -        result.supportsExtendedAgentCard_ = supportsExtendedAgentCard_;
    -        to_bitField0_ |= 0x00000040;
    -      }
    -      if (((from_bitField0_ & 0x00040000) != 0)) {
    +      if (((from_bitField0_ & 0x00004000) != 0)) {
             result.iconUrl_ = iconUrl_;
    -        to_bitField0_ |= 0x00000080;
    +        to_bitField0_ |= 0x00000008;
           }
           result.bitField0_ |= to_bitField0_;
         }
    @@ -1882,9 +1576,14 @@ public Builder mergeFrom(com.google.protobuf.Message other) {
     
         public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
           if (other == io.a2a.grpc.AgentCard.getDefaultInstance()) return this;
    -      if (other.hasProtocolVersion()) {
    -        protocolVersion_ = other.protocolVersion_;
    -        bitField0_ |= 0x00000001;
    +      if (!other.protocolVersions_.isEmpty()) {
    +        if (protocolVersions_.isEmpty()) {
    +          protocolVersions_ = other.protocolVersions_;
    +          bitField0_ |= 0x00000001;
    +        } else {
    +          ensureProtocolVersionsIsMutable();
    +          protocolVersions_.addAll(other.protocolVersions_);
    +        }
             onChanged();
           }
           if (!other.getName().isEmpty()) {
    @@ -1923,53 +1622,17 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
               }
             }
           }
    -      if (other.hasUrl()) {
    -        url_ = other.url_;
    -        bitField0_ |= 0x00000010;
    -        onChanged();
    +      if (other.hasProvider()) {
    +        mergeProvider(other.getProvider());
           }
    -      if (other.hasPreferredTransport()) {
    -        preferredTransport_ = other.preferredTransport_;
    +      if (!other.getVersion().isEmpty()) {
    +        version_ = other.version_;
             bitField0_ |= 0x00000020;
             onChanged();
           }
    -      if (additionalInterfacesBuilder_ == null) {
    -        if (!other.additionalInterfaces_.isEmpty()) {
    -          if (additionalInterfaces_.isEmpty()) {
    -            additionalInterfaces_ = other.additionalInterfaces_;
    -            bitField0_ = (bitField0_ & ~0x00000040);
    -          } else {
    -            ensureAdditionalInterfacesIsMutable();
    -            additionalInterfaces_.addAll(other.additionalInterfaces_);
    -          }
    -          onChanged();
    -        }
    -      } else {
    -        if (!other.additionalInterfaces_.isEmpty()) {
    -          if (additionalInterfacesBuilder_.isEmpty()) {
    -            additionalInterfacesBuilder_.dispose();
    -            additionalInterfacesBuilder_ = null;
    -            additionalInterfaces_ = other.additionalInterfaces_;
    -            bitField0_ = (bitField0_ & ~0x00000040);
    -            additionalInterfacesBuilder_ = 
    -              com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
    -                 internalGetAdditionalInterfacesFieldBuilder() : null;
    -          } else {
    -            additionalInterfacesBuilder_.addAllMessages(other.additionalInterfaces_);
    -          }
    -        }
    -      }
    -      if (other.hasProvider()) {
    -        mergeProvider(other.getProvider());
    -      }
    -      if (!other.getVersion().isEmpty()) {
    -        version_ = other.version_;
    -        bitField0_ |= 0x00000100;
    -        onChanged();
    -      }
           if (other.hasDocumentationUrl()) {
             documentationUrl_ = other.documentationUrl_;
    -        bitField0_ |= 0x00000200;
    +        bitField0_ |= 0x00000040;
             onChanged();
           }
           if (other.hasCapabilities()) {
    @@ -1977,12 +1640,12 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
           }
           internalGetMutableSecuritySchemes().mergeFrom(
               other.internalGetSecuritySchemes());
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000100;
           if (securityBuilder_ == null) {
             if (!other.security_.isEmpty()) {
               if (security_.isEmpty()) {
                 security_ = other.security_;
    -            bitField0_ = (bitField0_ & ~0x00001000);
    +            bitField0_ = (bitField0_ & ~0x00000200);
               } else {
                 ensureSecurityIsMutable();
                 security_.addAll(other.security_);
    @@ -1995,7 +1658,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
                 securityBuilder_.dispose();
                 securityBuilder_ = null;
                 security_ = other.security_;
    -            bitField0_ = (bitField0_ & ~0x00001000);
    +            bitField0_ = (bitField0_ & ~0x00000200);
                 securityBuilder_ = 
                   com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                      internalGetSecurityFieldBuilder() : null;
    @@ -2007,7 +1670,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
           if (!other.defaultInputModes_.isEmpty()) {
             if (defaultInputModes_.isEmpty()) {
               defaultInputModes_ = other.defaultInputModes_;
    -          bitField0_ |= 0x00002000;
    +          bitField0_ |= 0x00000400;
             } else {
               ensureDefaultInputModesIsMutable();
               defaultInputModes_.addAll(other.defaultInputModes_);
    @@ -2017,7 +1680,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
           if (!other.defaultOutputModes_.isEmpty()) {
             if (defaultOutputModes_.isEmpty()) {
               defaultOutputModes_ = other.defaultOutputModes_;
    -          bitField0_ |= 0x00004000;
    +          bitField0_ |= 0x00000800;
             } else {
               ensureDefaultOutputModesIsMutable();
               defaultOutputModes_.addAll(other.defaultOutputModes_);
    @@ -2028,7 +1691,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
             if (!other.skills_.isEmpty()) {
               if (skills_.isEmpty()) {
                 skills_ = other.skills_;
    -            bitField0_ = (bitField0_ & ~0x00008000);
    +            bitField0_ = (bitField0_ & ~0x00001000);
               } else {
                 ensureSkillsIsMutable();
                 skills_.addAll(other.skills_);
    @@ -2041,7 +1704,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
                 skillsBuilder_.dispose();
                 skillsBuilder_ = null;
                 skills_ = other.skills_;
    -            bitField0_ = (bitField0_ & ~0x00008000);
    +            bitField0_ = (bitField0_ & ~0x00001000);
                 skillsBuilder_ = 
                   com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                      internalGetSkillsFieldBuilder() : null;
    @@ -2050,14 +1713,11 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
               }
             }
           }
    -      if (other.hasSupportsExtendedAgentCard()) {
    -        setSupportsExtendedAgentCard(other.getSupportsExtendedAgentCard());
    -      }
           if (signaturesBuilder_ == null) {
             if (!other.signatures_.isEmpty()) {
               if (signatures_.isEmpty()) {
                 signatures_ = other.signatures_;
    -            bitField0_ = (bitField0_ & ~0x00020000);
    +            bitField0_ = (bitField0_ & ~0x00002000);
               } else {
                 ensureSignaturesIsMutable();
                 signatures_.addAll(other.signatures_);
    @@ -2070,7 +1730,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
                 signaturesBuilder_.dispose();
                 signaturesBuilder_ = null;
                 signatures_ = other.signatures_;
    -            bitField0_ = (bitField0_ & ~0x00020000);
    +            bitField0_ = (bitField0_ & ~0x00002000);
                 signaturesBuilder_ = 
                   com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                      internalGetSignaturesFieldBuilder() : null;
    @@ -2081,7 +1741,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
           }
           if (other.hasIconUrl()) {
             iconUrl_ = other.iconUrl_;
    -        bitField0_ |= 0x00040000;
    +        bitField0_ |= 0x00004000;
             onChanged();
           }
           this.mergeUnknownFields(other.getUnknownFields());
    @@ -2120,33 +1780,28 @@ public Builder mergeFrom(
                   bitField0_ |= 0x00000004;
                   break;
                 } // case 18
    -            case 26: {
    -              url_ = input.readStringRequireUtf8();
    -              bitField0_ |= 0x00000010;
    -              break;
    -            } // case 26
                 case 34: {
                   input.readMessage(
                       internalGetProviderFieldBuilder().getBuilder(),
                       extensionRegistry);
    -              bitField0_ |= 0x00000080;
    +              bitField0_ |= 0x00000010;
                   break;
                 } // case 34
                 case 42: {
                   version_ = input.readStringRequireUtf8();
    -              bitField0_ |= 0x00000100;
    +              bitField0_ |= 0x00000020;
                   break;
                 } // case 42
                 case 50: {
                   documentationUrl_ = input.readStringRequireUtf8();
    -              bitField0_ |= 0x00000200;
    +              bitField0_ |= 0x00000040;
                   break;
                 } // case 50
                 case 58: {
                   input.readMessage(
                       internalGetCapabilitiesFieldBuilder().getBuilder(),
                       extensionRegistry);
    -              bitField0_ |= 0x00000400;
    +              bitField0_ |= 0x00000080;
                   break;
                 } // case 58
                 case 66: {
    @@ -2155,7 +1810,7 @@ public Builder mergeFrom(
                       SecuritySchemesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
                   internalGetMutableSecuritySchemes().ensureBuilderMap().put(
                       securitySchemes__.getKey(), securitySchemes__.getValue());
    -              bitField0_ |= 0x00000800;
    +              bitField0_ |= 0x00000100;
                   break;
                 } // case 66
                 case 74: {
    @@ -2196,32 +1851,10 @@ public Builder mergeFrom(
                   }
                   break;
                 } // case 98
    -            case 104: {
    -              supportsExtendedAgentCard_ = input.readBool();
    -              bitField0_ |= 0x00010000;
    -              break;
    -            } // case 104
    -            case 114: {
    -              preferredTransport_ = input.readStringRequireUtf8();
    -              bitField0_ |= 0x00000020;
    -              break;
    -            } // case 114
    -            case 122: {
    -              io.a2a.grpc.AgentInterface m =
    -                  input.readMessage(
    -                      io.a2a.grpc.AgentInterface.parser(),
    -                      extensionRegistry);
    -              if (additionalInterfacesBuilder_ == null) {
    -                ensureAdditionalInterfacesIsMutable();
    -                additionalInterfaces_.add(m);
    -              } else {
    -                additionalInterfacesBuilder_.addMessage(m);
    -              }
    -              break;
    -            } // case 122
                 case 130: {
    -              protocolVersion_ = input.readStringRequireUtf8();
    -              bitField0_ |= 0x00000001;
    +              java.lang.String s = input.readStringRequireUtf8();
    +              ensureProtocolVersionsIsMutable();
    +              protocolVersions_.add(s);
                   break;
                 } // case 130
                 case 138: {
    @@ -2239,7 +1872,7 @@ public Builder mergeFrom(
                 } // case 138
                 case 146: {
                   iconUrl_ = input.readStringRequireUtf8();
    -              bitField0_ |= 0x00040000;
    +              bitField0_ |= 0x00004000;
                   break;
                 } // case 146
                 case 154: {
    @@ -2272,110 +1905,175 @@ public Builder mergeFrom(
         }
         private int bitField0_;
     
    -    private java.lang.Object protocolVersion_ = "";
    +    private com.google.protobuf.LazyStringArrayList protocolVersions_ =
    +        com.google.protobuf.LazyStringArrayList.emptyList();
    +    private void ensureProtocolVersionsIsMutable() {
    +      if (!protocolVersions_.isModifiable()) {
    +        protocolVersions_ = new com.google.protobuf.LazyStringArrayList(protocolVersions_);
    +      }
    +      bitField0_ |= 0x00000001;
    +    }
         /**
          * 
    -     * The version of the A2A protocol this agent supports.
    -     * Default: "1.0"
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
          * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the protocolVersion field is set. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @return A list containing the protocolVersions. */ - public boolean hasProtocolVersion() { - return ((bitField0_ & 0x00000001) != 0); + public com.google.protobuf.ProtocolStringList + getProtocolVersionsList() { + protocolVersions_.makeImmutable(); + return protocolVersions_; } /** *
    -     * The version of the A2A protocol this agent supports.
    -     * Default: "1.0"
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
          * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolVersion. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @return The count of protocolVersions. */ - public java.lang.String getProtocolVersion() { - java.lang.Object ref = protocolVersion_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - protocolVersion_ = s; - return s; - } else { - return (java.lang.String) ref; - } + public int getProtocolVersionsCount() { + return protocolVersions_.size(); + } + /** + *
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
    +     * 
    + * + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param index The index of the element to return. + * @return The protocolVersions at the given index. + */ + public java.lang.String getProtocolVersions(int index) { + return protocolVersions_.get(index); } /** *
    -     * The version of the A2A protocol this agent supports.
    -     * Default: "1.0"
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
          * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolVersion. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param index The index of the value to return. + * @return The bytes of the protocolVersions at the given index. */ public com.google.protobuf.ByteString - getProtocolVersionBytes() { - java.lang.Object ref = protocolVersion_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protocolVersion_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } + getProtocolVersionsBytes(int index) { + return protocolVersions_.getByteString(index); + } + /** + *
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
    +     * 
    + * + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param index The index to set the value at. + * @param value The protocolVersions to set. + * @return This builder for chaining. + */ + public Builder setProtocolVersions( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureProtocolVersionsIsMutable(); + protocolVersions_.set(index, value); + bitField0_ |= 0x00000001; + onChanged(); + return this; } /** *
    -     * The version of the A2A protocol this agent supports.
    -     * Default: "1.0"
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
          * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param value The protocolVersion to set. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param value The protocolVersions to add. * @return This builder for chaining. */ - public Builder setProtocolVersion( + public Builder addProtocolVersions( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - protocolVersion_ = value; + ensureProtocolVersionsIsMutable(); + protocolVersions_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
    +     * 
    + * + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param values The protocolVersions to add. + * @return This builder for chaining. + */ + public Builder addAllProtocolVersions( + java.lang.Iterable values) { + ensureProtocolVersionsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, protocolVersions_); bitField0_ |= 0x00000001; onChanged(); return this; } /** *
    -     * The version of the A2A protocol this agent supports.
    -     * Default: "1.0"
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
          * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearProtocolVersion() { - protocolVersion_ = getDefaultInstance().getProtocolVersion(); - bitField0_ = (bitField0_ & ~0x00000001); + public Builder clearProtocolVersions() { + protocolVersions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001);; onChanged(); return this; } /** *
    -     * The version of the A2A protocol this agent supports.
    -     * Default: "1.0"
    +     * The versions of the A2A protocol this agent supports.
    +     * For stable versions (1.x+), list only the latest supported minor version per major version.
    +     * For legacy experimental versions (0.x), explicitly list each supported version.
    +     * Default: ["1.0"]
          * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for protocolVersion to set. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes of the protocolVersions to add. * @return This builder for chaining. */ - public Builder setProtocolVersionBytes( + public Builder addProtocolVersionsBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - protocolVersion_ = value; + ensureProtocolVersionsIsMutable(); + protocolVersions_.add(value); bitField0_ |= 0x00000001; onChanged(); return this; @@ -2472,572 +2170,30 @@ public Builder setNameBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - name_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object description_ = ""; - /** - *
    -     * A human-readable description of the agent, assisting users and other agents
    -     * in understanding its purpose.
    -     * Example: "Agent that helps users with recipes and cooking."
    -     * 
    - * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
    -     * A human-readable description of the agent, assisting users and other agents
    -     * in understanding its purpose.
    -     * Example: "Agent that helps users with recipes and cooking."
    -     * 
    - * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
    -     * A human-readable description of the agent, assisting users and other agents
    -     * in understanding its purpose.
    -     * Example: "Agent that helps users with recipes and cooking."
    -     * 
    - * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
    -     * A human-readable description of the agent, assisting users and other agents
    -     * in understanding its purpose.
    -     * Example: "Agent that helps users with recipes and cooking."
    -     * 
    - * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
    -     * A human-readable description of the agent, assisting users and other agents
    -     * in understanding its purpose.
    -     * Example: "Agent that helps users with recipes and cooking."
    -     * 
    - * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private java.util.List supportedInterfaces_ = - java.util.Collections.emptyList(); - private void ensureSupportedInterfacesIsMutable() { - if (!((bitField0_ & 0x00000008) != 0)) { - supportedInterfaces_ = new java.util.ArrayList(supportedInterfaces_); - bitField0_ |= 0x00000008; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> supportedInterfacesBuilder_; - - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public java.util.List getSupportedInterfacesList() { - if (supportedInterfacesBuilder_ == null) { - return java.util.Collections.unmodifiableList(supportedInterfaces_); - } else { - return supportedInterfacesBuilder_.getMessageList(); - } - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public int getSupportedInterfacesCount() { - if (supportedInterfacesBuilder_ == null) { - return supportedInterfaces_.size(); - } else { - return supportedInterfacesBuilder_.getCount(); - } - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { - if (supportedInterfacesBuilder_ == null) { - return supportedInterfaces_.get(index); - } else { - return supportedInterfacesBuilder_.getMessage(index); - } - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder setSupportedInterfaces( - int index, io.a2a.grpc.AgentInterface value) { - if (supportedInterfacesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.set(index, value); - onChanged(); - } else { - supportedInterfacesBuilder_.setMessage(index, value); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder setSupportedInterfaces( - int index, io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.set(index, builderForValue.build()); - onChanged(); - } else { - supportedInterfacesBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder addSupportedInterfaces(io.a2a.grpc.AgentInterface value) { - if (supportedInterfacesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(value); - onChanged(); - } else { - supportedInterfacesBuilder_.addMessage(value); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder addSupportedInterfaces( - int index, io.a2a.grpc.AgentInterface value) { - if (supportedInterfacesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(index, value); - onChanged(); - } else { - supportedInterfacesBuilder_.addMessage(index, value); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder addSupportedInterfaces( - io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(builderForValue.build()); - onChanged(); - } else { - supportedInterfacesBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder addSupportedInterfaces( - int index, io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(index, builderForValue.build()); - onChanged(); - } else { - supportedInterfacesBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder addAllSupportedInterfaces( - java.lang.Iterable values) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, supportedInterfaces_); - onChanged(); - } else { - supportedInterfacesBuilder_.addAllMessages(values); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder clearSupportedInterfaces() { - if (supportedInterfacesBuilder_ == null) { - supportedInterfaces_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); - onChanged(); - } else { - supportedInterfacesBuilder_.clear(); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public Builder removeSupportedInterfaces(int index) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.remove(index); - onChanged(); - } else { - supportedInterfacesBuilder_.remove(index); - } - return this; - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public io.a2a.grpc.AgentInterface.Builder getSupportedInterfacesBuilder( - int index) { - return internalGetSupportedInterfacesFieldBuilder().getBuilder(index); - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( - int index) { - if (supportedInterfacesBuilder_ == null) { - return supportedInterfaces_.get(index); } else { - return supportedInterfacesBuilder_.getMessageOrBuilder(index); - } - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public java.util.List - getSupportedInterfacesOrBuilderList() { - if (supportedInterfacesBuilder_ != null) { - return supportedInterfacesBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(supportedInterfaces_); - } - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder() { - return internalGetSupportedInterfacesFieldBuilder().addBuilder( - io.a2a.grpc.AgentInterface.getDefaultInstance()); - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder( - int index) { - return internalGetSupportedInterfacesFieldBuilder().addBuilder( - index, io.a2a.grpc.AgentInterface.getDefaultInstance()); - } - /** - *
    -     * Ordered list of supported interfaces. First entry is preferred.
    -     * 
    - * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; - */ - public java.util.List - getSupportedInterfacesBuilderList() { - return internalGetSupportedInterfacesFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> - internalGetSupportedInterfacesFieldBuilder() { - if (supportedInterfacesBuilder_ == null) { - supportedInterfacesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder>( - supportedInterfaces_, - ((bitField0_ & 0x00000008) != 0), - getParentForChildren(), - isClean()); - supportedInterfaces_ = null; - } - return supportedInterfacesBuilder_; - } - - private java.lang.Object url_ = ""; - /** - *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    -     * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return Whether the url field is set. - */ - @java.lang.Deprecated public boolean hasUrl() { - return ((bitField0_ & 0x00000010) != 0); - } - /** - *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    -     * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return The url. - */ - @java.lang.Deprecated public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    -     * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return The bytes for url. - */ - @java.lang.Deprecated public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    -     * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @param value The url to set. - * @return This builder for chaining. - */ - @java.lang.Deprecated public Builder setUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - url_ = value; - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    -     * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return This builder for chaining. - */ - @java.lang.Deprecated public Builder clearUrl() { - url_ = getDefaultInstance().getUrl(); - bitField0_ = (bitField0_ & ~0x00000010); - onChanged(); - return this; - } - /** - *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    -     * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @param value The bytes for url to set. - * @return This builder for chaining. - */ - @java.lang.Deprecated public Builder setUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - url_ = value; - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - - private java.lang.Object preferredTransport_ = ""; - /** - *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    -     * 
    - * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return Whether the preferredTransport field is set. - */ - @java.lang.Deprecated public boolean hasPreferredTransport() { - return ((bitField0_ & 0x00000020) != 0); + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; } + + private java.lang.Object description_ = ""; /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * A human-readable description of the agent, assisting users and other agents
    +     * in understanding its purpose.
    +     * Example: "Agent that helps users with recipes and cooking."
          * 
    * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return The preferredTransport. + * string description = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The description. */ - @java.lang.Deprecated public java.lang.String getPreferredTransport() { - java.lang.Object ref = preferredTransport_; + public java.lang.String getDescription() { + java.lang.Object ref = description_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - preferredTransport_ = s; + description_ = s; return s; } else { return (java.lang.String) ref; @@ -3045,22 +2201,22 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder( } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * A human-readable description of the agent, assisting users and other agents
    +     * in understanding its purpose.
    +     * Example: "Agent that helps users with recipes and cooking."
          * 
    * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return The bytes for preferredTransport. + * string description = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for description. */ - @java.lang.Deprecated public com.google.protobuf.ByteString - getPreferredTransportBytes() { - java.lang.Object ref = preferredTransport_; + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - preferredTransport_ = b; + description_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -3068,370 +2224,370 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder( } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * A human-readable description of the agent, assisting users and other agents
    +     * in understanding its purpose.
    +     * Example: "Agent that helps users with recipes and cooking."
          * 
    * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @param value The preferredTransport to set. + * string description = 2 [(.google.api.field_behavior) = REQUIRED]; + * @param value The description to set. * @return This builder for chaining. */ - @java.lang.Deprecated public Builder setPreferredTransport( + public Builder setDescription( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - preferredTransport_ = value; - bitField0_ |= 0x00000020; + description_ = value; + bitField0_ |= 0x00000004; onChanged(); return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * A human-readable description of the agent, assisting users and other agents
    +     * in understanding its purpose.
    +     * Example: "Agent that helps users with recipes and cooking."
          * 
    * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 + * string description = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - @java.lang.Deprecated public Builder clearPreferredTransport() { - preferredTransport_ = getDefaultInstance().getPreferredTransport(); - bitField0_ = (bitField0_ & ~0x00000020); + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000004); onChanged(); return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * A human-readable description of the agent, assisting users and other agents
    +     * in understanding its purpose.
    +     * Example: "Agent that helps users with recipes and cooking."
          * 
    * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @param value The bytes for preferredTransport to set. + * string description = 2 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for description to set. * @return This builder for chaining. */ - @java.lang.Deprecated public Builder setPreferredTransportBytes( + public Builder setDescriptionBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - preferredTransport_ = value; - bitField0_ |= 0x00000020; + description_ = value; + bitField0_ |= 0x00000004; onChanged(); return this; } - private java.util.List additionalInterfaces_ = + private java.util.List supportedInterfaces_ = java.util.Collections.emptyList(); - private void ensureAdditionalInterfacesIsMutable() { - if (!((bitField0_ & 0x00000040) != 0)) { - additionalInterfaces_ = new java.util.ArrayList(additionalInterfaces_); - bitField0_ |= 0x00000040; + private void ensureSupportedInterfacesIsMutable() { + if (!((bitField0_ & 0x00000008) != 0)) { + supportedInterfaces_ = new java.util.ArrayList(supportedInterfaces_); + bitField0_ |= 0x00000008; } } private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> additionalInterfacesBuilder_; + io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> supportedInterfacesBuilder_; /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public java.util.List getAdditionalInterfacesList() { - if (additionalInterfacesBuilder_ == null) { - return java.util.Collections.unmodifiableList(additionalInterfaces_); + public java.util.List getSupportedInterfacesList() { + if (supportedInterfacesBuilder_ == null) { + return java.util.Collections.unmodifiableList(supportedInterfaces_); } else { - return additionalInterfacesBuilder_.getMessageList(); + return supportedInterfacesBuilder_.getMessageList(); } } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public int getAdditionalInterfacesCount() { - if (additionalInterfacesBuilder_ == null) { - return additionalInterfaces_.size(); + public int getSupportedInterfacesCount() { + if (supportedInterfacesBuilder_ == null) { + return supportedInterfaces_.size(); } else { - return additionalInterfacesBuilder_.getCount(); + return supportedInterfacesBuilder_.getCount(); } } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public io.a2a.grpc.AgentInterface getAdditionalInterfaces(int index) { - if (additionalInterfacesBuilder_ == null) { - return additionalInterfaces_.get(index); + public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { + if (supportedInterfacesBuilder_ == null) { + return supportedInterfaces_.get(index); } else { - return additionalInterfacesBuilder_.getMessage(index); + return supportedInterfacesBuilder_.getMessage(index); } } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder setAdditionalInterfaces( + public Builder setSupportedInterfaces( int index, io.a2a.grpc.AgentInterface value) { - if (additionalInterfacesBuilder_ == null) { + if (supportedInterfacesBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureAdditionalInterfacesIsMutable(); - additionalInterfaces_.set(index, value); + ensureSupportedInterfacesIsMutable(); + supportedInterfaces_.set(index, value); onChanged(); } else { - additionalInterfacesBuilder_.setMessage(index, value); + supportedInterfacesBuilder_.setMessage(index, value); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder setAdditionalInterfaces( + public Builder setSupportedInterfaces( int index, io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (additionalInterfacesBuilder_ == null) { - ensureAdditionalInterfacesIsMutable(); - additionalInterfaces_.set(index, builderForValue.build()); + if (supportedInterfacesBuilder_ == null) { + ensureSupportedInterfacesIsMutable(); + supportedInterfaces_.set(index, builderForValue.build()); onChanged(); } else { - additionalInterfacesBuilder_.setMessage(index, builderForValue.build()); + supportedInterfacesBuilder_.setMessage(index, builderForValue.build()); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder addAdditionalInterfaces(io.a2a.grpc.AgentInterface value) { - if (additionalInterfacesBuilder_ == null) { + public Builder addSupportedInterfaces(io.a2a.grpc.AgentInterface value) { + if (supportedInterfacesBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureAdditionalInterfacesIsMutable(); - additionalInterfaces_.add(value); + ensureSupportedInterfacesIsMutable(); + supportedInterfaces_.add(value); onChanged(); } else { - additionalInterfacesBuilder_.addMessage(value); + supportedInterfacesBuilder_.addMessage(value); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder addAdditionalInterfaces( + public Builder addSupportedInterfaces( int index, io.a2a.grpc.AgentInterface value) { - if (additionalInterfacesBuilder_ == null) { + if (supportedInterfacesBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureAdditionalInterfacesIsMutable(); - additionalInterfaces_.add(index, value); + ensureSupportedInterfacesIsMutable(); + supportedInterfaces_.add(index, value); onChanged(); } else { - additionalInterfacesBuilder_.addMessage(index, value); + supportedInterfacesBuilder_.addMessage(index, value); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder addAdditionalInterfaces( + public Builder addSupportedInterfaces( io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (additionalInterfacesBuilder_ == null) { - ensureAdditionalInterfacesIsMutable(); - additionalInterfaces_.add(builderForValue.build()); + if (supportedInterfacesBuilder_ == null) { + ensureSupportedInterfacesIsMutable(); + supportedInterfaces_.add(builderForValue.build()); onChanged(); } else { - additionalInterfacesBuilder_.addMessage(builderForValue.build()); + supportedInterfacesBuilder_.addMessage(builderForValue.build()); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder addAdditionalInterfaces( + public Builder addSupportedInterfaces( int index, io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (additionalInterfacesBuilder_ == null) { - ensureAdditionalInterfacesIsMutable(); - additionalInterfaces_.add(index, builderForValue.build()); + if (supportedInterfacesBuilder_ == null) { + ensureSupportedInterfacesIsMutable(); + supportedInterfaces_.add(index, builderForValue.build()); onChanged(); } else { - additionalInterfacesBuilder_.addMessage(index, builderForValue.build()); + supportedInterfacesBuilder_.addMessage(index, builderForValue.build()); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder addAllAdditionalInterfaces( + public Builder addAllSupportedInterfaces( java.lang.Iterable values) { - if (additionalInterfacesBuilder_ == null) { - ensureAdditionalInterfacesIsMutable(); + if (supportedInterfacesBuilder_ == null) { + ensureSupportedInterfacesIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, additionalInterfaces_); + values, supportedInterfaces_); onChanged(); } else { - additionalInterfacesBuilder_.addAllMessages(values); + supportedInterfacesBuilder_.addAllMessages(values); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder clearAdditionalInterfaces() { - if (additionalInterfacesBuilder_ == null) { - additionalInterfaces_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000040); + public Builder clearSupportedInterfaces() { + if (supportedInterfacesBuilder_ == null) { + supportedInterfaces_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); onChanged(); } else { - additionalInterfacesBuilder_.clear(); + supportedInterfacesBuilder_.clear(); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public Builder removeAdditionalInterfaces(int index) { - if (additionalInterfacesBuilder_ == null) { - ensureAdditionalInterfacesIsMutable(); - additionalInterfaces_.remove(index); + public Builder removeSupportedInterfaces(int index) { + if (supportedInterfacesBuilder_ == null) { + ensureSupportedInterfacesIsMutable(); + supportedInterfaces_.remove(index); onChanged(); } else { - additionalInterfacesBuilder_.remove(index); + supportedInterfacesBuilder_.remove(index); } return this; } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public io.a2a.grpc.AgentInterface.Builder getAdditionalInterfacesBuilder( + public io.a2a.grpc.AgentInterface.Builder getSupportedInterfacesBuilder( int index) { - return internalGetAdditionalInterfacesFieldBuilder().getBuilder(index); + return internalGetSupportedInterfacesFieldBuilder().getBuilder(index); } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public io.a2a.grpc.AgentInterfaceOrBuilder getAdditionalInterfacesOrBuilder( + public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( int index) { - if (additionalInterfacesBuilder_ == null) { - return additionalInterfaces_.get(index); } else { - return additionalInterfacesBuilder_.getMessageOrBuilder(index); + if (supportedInterfacesBuilder_ == null) { + return supportedInterfaces_.get(index); } else { + return supportedInterfacesBuilder_.getMessageOrBuilder(index); } } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public java.util.List - getAdditionalInterfacesOrBuilderList() { - if (additionalInterfacesBuilder_ != null) { - return additionalInterfacesBuilder_.getMessageOrBuilderList(); + public java.util.List + getSupportedInterfacesOrBuilderList() { + if (supportedInterfacesBuilder_ != null) { + return supportedInterfacesBuilder_.getMessageOrBuilderList(); } else { - return java.util.Collections.unmodifiableList(additionalInterfaces_); + return java.util.Collections.unmodifiableList(supportedInterfaces_); } } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public io.a2a.grpc.AgentInterface.Builder addAdditionalInterfacesBuilder() { - return internalGetAdditionalInterfacesFieldBuilder().addBuilder( + public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder() { + return internalGetSupportedInterfacesFieldBuilder().addBuilder( io.a2a.grpc.AgentInterface.getDefaultInstance()); } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public io.a2a.grpc.AgentInterface.Builder addAdditionalInterfacesBuilder( + public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder( int index) { - return internalGetAdditionalInterfacesFieldBuilder().addBuilder( + return internalGetSupportedInterfacesFieldBuilder().addBuilder( index, io.a2a.grpc.AgentInterface.getDefaultInstance()); } /** *
    -     * DEPRECATED: Use 'supported_interfaces' instead.
    +     * Ordered list of supported interfaces. First entry is preferred.
          * 
    * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ - @java.lang.Deprecated public java.util.List - getAdditionalInterfacesBuilderList() { - return internalGetAdditionalInterfacesFieldBuilder().getBuilderList(); + public java.util.List + getSupportedInterfacesBuilderList() { + return internalGetSupportedInterfacesFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilder< io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> - internalGetAdditionalInterfacesFieldBuilder() { - if (additionalInterfacesBuilder_ == null) { - additionalInterfacesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + internalGetSupportedInterfacesFieldBuilder() { + if (supportedInterfacesBuilder_ == null) { + supportedInterfacesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder>( - additionalInterfaces_, - ((bitField0_ & 0x00000040) != 0), + supportedInterfaces_, + ((bitField0_ & 0x00000008) != 0), getParentForChildren(), isClean()); - additionalInterfaces_ = null; + supportedInterfaces_ = null; } - return additionalInterfacesBuilder_; + return supportedInterfacesBuilder_; } private io.a2a.grpc.AgentProvider provider_; @@ -3446,7 +2602,7 @@ private void ensureAdditionalInterfacesIsMutable() { * @return Whether the provider field is set. */ public boolean hasProvider() { - return ((bitField0_ & 0x00000080) != 0); + return ((bitField0_ & 0x00000010) != 0); } /** *
    @@ -3479,7 +2635,7 @@ public Builder setProvider(io.a2a.grpc.AgentProvider value) {
           } else {
             providerBuilder_.setMessage(value);
           }
    -      bitField0_ |= 0x00000080;
    +      bitField0_ |= 0x00000010;
           onChanged();
           return this;
         }
    @@ -3497,7 +2653,7 @@ public Builder setProvider(
           } else {
             providerBuilder_.setMessage(builderForValue.build());
           }
    -      bitField0_ |= 0x00000080;
    +      bitField0_ |= 0x00000010;
           onChanged();
           return this;
         }
    @@ -3510,7 +2666,7 @@ public Builder setProvider(
          */
         public Builder mergeProvider(io.a2a.grpc.AgentProvider value) {
           if (providerBuilder_ == null) {
    -        if (((bitField0_ & 0x00000080) != 0) &&
    +        if (((bitField0_ & 0x00000010) != 0) &&
               provider_ != null &&
               provider_ != io.a2a.grpc.AgentProvider.getDefaultInstance()) {
               getProviderBuilder().mergeFrom(value);
    @@ -3521,7 +2677,7 @@ public Builder mergeProvider(io.a2a.grpc.AgentProvider value) {
             providerBuilder_.mergeFrom(value);
           }
           if (provider_ != null) {
    -        bitField0_ |= 0x00000080;
    +        bitField0_ |= 0x00000010;
             onChanged();
           }
           return this;
    @@ -3534,7 +2690,7 @@ public Builder mergeProvider(io.a2a.grpc.AgentProvider value) {
          * .a2a.v1.AgentProvider provider = 4;
          */
         public Builder clearProvider() {
    -      bitField0_ = (bitField0_ & ~0x00000080);
    +      bitField0_ = (bitField0_ & ~0x00000010);
           provider_ = null;
           if (providerBuilder_ != null) {
             providerBuilder_.dispose();
    @@ -3551,7 +2707,7 @@ public Builder clearProvider() {
          * .a2a.v1.AgentProvider provider = 4;
          */
         public io.a2a.grpc.AgentProvider.Builder getProviderBuilder() {
    -      bitField0_ |= 0x00000080;
    +      bitField0_ |= 0x00000010;
           onChanged();
           return internalGetProviderFieldBuilder().getBuilder();
         }
    @@ -3649,7 +2805,7 @@ public Builder setVersion(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
           version_ = value;
    -      bitField0_ |= 0x00000100;
    +      bitField0_ |= 0x00000020;
           onChanged();
           return this;
         }
    @@ -3664,7 +2820,7 @@ public Builder setVersion(
          */
         public Builder clearVersion() {
           version_ = getDefaultInstance().getVersion();
    -      bitField0_ = (bitField0_ & ~0x00000100);
    +      bitField0_ = (bitField0_ & ~0x00000020);
           onChanged();
           return this;
         }
    @@ -3683,7 +2839,7 @@ public Builder setVersionBytes(
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
           version_ = value;
    -      bitField0_ |= 0x00000100;
    +      bitField0_ |= 0x00000020;
           onChanged();
           return this;
         }
    @@ -3698,7 +2854,7 @@ public Builder setVersionBytes(
          * @return Whether the documentationUrl field is set.
          */
         public boolean hasDocumentationUrl() {
    -      return ((bitField0_ & 0x00000200) != 0);
    +      return ((bitField0_ & 0x00000040) != 0);
         }
         /**
          * 
    @@ -3754,7 +2910,7 @@ public Builder setDocumentationUrl(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
           documentationUrl_ = value;
    -      bitField0_ |= 0x00000200;
    +      bitField0_ |= 0x00000040;
           onChanged();
           return this;
         }
    @@ -3768,7 +2924,7 @@ public Builder setDocumentationUrl(
          */
         public Builder clearDocumentationUrl() {
           documentationUrl_ = getDefaultInstance().getDocumentationUrl();
    -      bitField0_ = (bitField0_ & ~0x00000200);
    +      bitField0_ = (bitField0_ & ~0x00000040);
           onChanged();
           return this;
         }
    @@ -3786,7 +2942,7 @@ public Builder setDocumentationUrlBytes(
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
           documentationUrl_ = value;
    -      bitField0_ |= 0x00000200;
    +      bitField0_ |= 0x00000040;
           onChanged();
           return this;
         }
    @@ -3803,7 +2959,7 @@ public Builder setDocumentationUrlBytes(
          * @return Whether the capabilities field is set.
          */
         public boolean hasCapabilities() {
    -      return ((bitField0_ & 0x00000400) != 0);
    +      return ((bitField0_ & 0x00000080) != 0);
         }
         /**
          * 
    @@ -3836,7 +2992,7 @@ public Builder setCapabilities(io.a2a.grpc.AgentCapabilities value) {
           } else {
             capabilitiesBuilder_.setMessage(value);
           }
    -      bitField0_ |= 0x00000400;
    +      bitField0_ |= 0x00000080;
           onChanged();
           return this;
         }
    @@ -3854,7 +3010,7 @@ public Builder setCapabilities(
           } else {
             capabilitiesBuilder_.setMessage(builderForValue.build());
           }
    -      bitField0_ |= 0x00000400;
    +      bitField0_ |= 0x00000080;
           onChanged();
           return this;
         }
    @@ -3867,7 +3023,7 @@ public Builder setCapabilities(
          */
         public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) {
           if (capabilitiesBuilder_ == null) {
    -        if (((bitField0_ & 0x00000400) != 0) &&
    +        if (((bitField0_ & 0x00000080) != 0) &&
               capabilities_ != null &&
               capabilities_ != io.a2a.grpc.AgentCapabilities.getDefaultInstance()) {
               getCapabilitiesBuilder().mergeFrom(value);
    @@ -3878,7 +3034,7 @@ public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) {
             capabilitiesBuilder_.mergeFrom(value);
           }
           if (capabilities_ != null) {
    -        bitField0_ |= 0x00000400;
    +        bitField0_ |= 0x00000080;
             onChanged();
           }
           return this;
    @@ -3891,7 +3047,7 @@ public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) {
          * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
          */
         public Builder clearCapabilities() {
    -      bitField0_ = (bitField0_ & ~0x00000400);
    +      bitField0_ = (bitField0_ & ~0x00000080);
           capabilities_ = null;
           if (capabilitiesBuilder_ != null) {
             capabilitiesBuilder_.dispose();
    @@ -3908,7 +3064,7 @@ public Builder clearCapabilities() {
          * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
          */
         public io.a2a.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() {
    -      bitField0_ |= 0x00000400;
    +      bitField0_ |= 0x00000080;
           onChanged();
           return internalGetCapabilitiesFieldBuilder().getBuilder();
         }
    @@ -3976,7 +3132,7 @@ public com.google.protobuf.MapEntry(securitySchemesConverter);
           }
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000100;
           onChanged();
           return securitySchemes_;
         }
    @@ -4050,7 +3206,7 @@ public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
           return securitySchemesConverter.build(map.get(key));
         }
         public Builder clearSecuritySchemes() {
    -      bitField0_ = (bitField0_ & ~0x00000800);
    +      bitField0_ = (bitField0_ & ~0x00000100);
           internalGetMutableSecuritySchemes().clear();
           return this;
         }
    @@ -4074,7 +3230,7 @@ public Builder removeSecuritySchemes(
         @java.lang.Deprecated
         public java.util.Map
             getMutableSecuritySchemes() {
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000100;
           return internalGetMutableSecuritySchemes().ensureMessageMap();
         }
         /**
    @@ -4091,7 +3247,7 @@ public Builder putSecuritySchemes(
           if (value == null) { throw new NullPointerException("map value"); }
           internalGetMutableSecuritySchemes().ensureBuilderMap()
               .put(key, value);
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000100;
           return this;
         }
         /**
    @@ -4110,7 +3266,7 @@ public Builder putAllSecuritySchemes(
           }
           internalGetMutableSecuritySchemes().ensureBuilderMap()
               .putAll(values);
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000100;
           return this;
         }
         /**
    @@ -4138,9 +3294,9 @@ public io.a2a.grpc.SecurityScheme.Builder putSecuritySchemesBuilderIfAbsent(
         private java.util.List security_ =
           java.util.Collections.emptyList();
         private void ensureSecurityIsMutable() {
    -      if (!((bitField0_ & 0x00001000) != 0)) {
    +      if (!((bitField0_ & 0x00000200) != 0)) {
             security_ = new java.util.ArrayList(security_);
    -        bitField0_ |= 0x00001000;
    +        bitField0_ |= 0x00000200;
            }
         }
     
    @@ -4345,7 +3501,7 @@ public Builder addAllSecurity(
         public Builder clearSecurity() {
           if (securityBuilder_ == null) {
             security_ = java.util.Collections.emptyList();
    -        bitField0_ = (bitField0_ & ~0x00001000);
    +        bitField0_ = (bitField0_ & ~0x00000200);
             onChanged();
           } else {
             securityBuilder_.clear();
    @@ -4457,7 +3613,7 @@ public io.a2a.grpc.Security.Builder addSecurityBuilder(
             securityBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                 io.a2a.grpc.Security, io.a2a.grpc.Security.Builder, io.a2a.grpc.SecurityOrBuilder>(
                     security_,
    -                ((bitField0_ & 0x00001000) != 0),
    +                ((bitField0_ & 0x00000200) != 0),
                     getParentForChildren(),
                     isClean());
             security_ = null;
    @@ -4471,7 +3627,7 @@ private void ensureDefaultInputModesIsMutable() {
           if (!defaultInputModes_.isModifiable()) {
             defaultInputModes_ = new com.google.protobuf.LazyStringArrayList(defaultInputModes_);
           }
    -      bitField0_ |= 0x00002000;
    +      bitField0_ |= 0x00000400;
         }
         /**
          * 
    @@ -4547,7 +3703,7 @@ public Builder setDefaultInputModes(
           if (value == null) { throw new NullPointerException(); }
           ensureDefaultInputModesIsMutable();
           defaultInputModes_.set(index, value);
    -      bitField0_ |= 0x00002000;
    +      bitField0_ |= 0x00000400;
           onChanged();
           return this;
         }
    @@ -4567,7 +3723,7 @@ public Builder addDefaultInputModes(
           if (value == null) { throw new NullPointerException(); }
           ensureDefaultInputModesIsMutable();
           defaultInputModes_.add(value);
    -      bitField0_ |= 0x00002000;
    +      bitField0_ |= 0x00000400;
           onChanged();
           return this;
         }
    @@ -4587,7 +3743,7 @@ public Builder addAllDefaultInputModes(
           ensureDefaultInputModesIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
               values, defaultInputModes_);
    -      bitField0_ |= 0x00002000;
    +      bitField0_ |= 0x00000400;
           onChanged();
           return this;
         }
    @@ -4604,7 +3760,7 @@ public Builder addAllDefaultInputModes(
         public Builder clearDefaultInputModes() {
           defaultInputModes_ =
             com.google.protobuf.LazyStringArrayList.emptyList();
    -      bitField0_ = (bitField0_ & ~0x00002000);;
    +      bitField0_ = (bitField0_ & ~0x00000400);;
           onChanged();
           return this;
         }
    @@ -4625,7 +3781,7 @@ public Builder addDefaultInputModesBytes(
           checkByteStringIsUtf8(value);
           ensureDefaultInputModesIsMutable();
           defaultInputModes_.add(value);
    -      bitField0_ |= 0x00002000;
    +      bitField0_ |= 0x00000400;
           onChanged();
           return this;
         }
    @@ -4636,7 +3792,7 @@ private void ensureDefaultOutputModesIsMutable() {
           if (!defaultOutputModes_.isModifiable()) {
             defaultOutputModes_ = new com.google.protobuf.LazyStringArrayList(defaultOutputModes_);
           }
    -      bitField0_ |= 0x00004000;
    +      bitField0_ |= 0x00000800;
         }
         /**
          * 
    @@ -4702,7 +3858,7 @@ public Builder setDefaultOutputModes(
           if (value == null) { throw new NullPointerException(); }
           ensureDefaultOutputModesIsMutable();
           defaultOutputModes_.set(index, value);
    -      bitField0_ |= 0x00004000;
    +      bitField0_ |= 0x00000800;
           onChanged();
           return this;
         }
    @@ -4720,7 +3876,7 @@ public Builder addDefaultOutputModes(
           if (value == null) { throw new NullPointerException(); }
           ensureDefaultOutputModesIsMutable();
           defaultOutputModes_.add(value);
    -      bitField0_ |= 0x00004000;
    +      bitField0_ |= 0x00000800;
           onChanged();
           return this;
         }
    @@ -4738,7 +3894,7 @@ public Builder addAllDefaultOutputModes(
           ensureDefaultOutputModesIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
               values, defaultOutputModes_);
    -      bitField0_ |= 0x00004000;
    +      bitField0_ |= 0x00000800;
           onChanged();
           return this;
         }
    @@ -4753,7 +3909,7 @@ public Builder addAllDefaultOutputModes(
         public Builder clearDefaultOutputModes() {
           defaultOutputModes_ =
             com.google.protobuf.LazyStringArrayList.emptyList();
    -      bitField0_ = (bitField0_ & ~0x00004000);;
    +      bitField0_ = (bitField0_ & ~0x00000800);;
           onChanged();
           return this;
         }
    @@ -4772,7 +3928,7 @@ public Builder addDefaultOutputModesBytes(
           checkByteStringIsUtf8(value);
           ensureDefaultOutputModesIsMutable();
           defaultOutputModes_.add(value);
    -      bitField0_ |= 0x00004000;
    +      bitField0_ |= 0x00000800;
           onChanged();
           return this;
         }
    @@ -4780,9 +3936,9 @@ public Builder addDefaultOutputModesBytes(
         private java.util.List skills_ =
           java.util.Collections.emptyList();
         private void ensureSkillsIsMutable() {
    -      if (!((bitField0_ & 0x00008000) != 0)) {
    +      if (!((bitField0_ & 0x00001000) != 0)) {
             skills_ = new java.util.ArrayList(skills_);
    -        bitField0_ |= 0x00008000;
    +        bitField0_ |= 0x00001000;
            }
         }
     
    @@ -4998,7 +4154,7 @@ public Builder addAllSkills(
         public Builder clearSkills() {
           if (skillsBuilder_ == null) {
             skills_ = java.util.Collections.emptyList();
    -        bitField0_ = (bitField0_ & ~0x00008000);
    +        bitField0_ = (bitField0_ & ~0x00001000);
             onChanged();
           } else {
             skillsBuilder_.clear();
    @@ -5117,7 +4273,7 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder(
             skillsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                 io.a2a.grpc.AgentSkill, io.a2a.grpc.AgentSkill.Builder, io.a2a.grpc.AgentSkillOrBuilder>(
                     skills_,
    -                ((bitField0_ & 0x00008000) != 0),
    +                ((bitField0_ & 0x00001000) != 0),
                     getParentForChildren(),
                     isClean());
             skills_ = null;
    @@ -5125,68 +4281,12 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder(
           return skillsBuilder_;
         }
     
    -    private boolean supportsExtendedAgentCard_ ;
    -    /**
    -     * 
    -     * Whether the agent supports providing an extended agent card when authenticated.
    -     * 
    - * - * optional bool supports_extended_agent_card = 13; - * @return Whether the supportsExtendedAgentCard field is set. - */ - @java.lang.Override - public boolean hasSupportsExtendedAgentCard() { - return ((bitField0_ & 0x00010000) != 0); - } - /** - *
    -     * Whether the agent supports providing an extended agent card when authenticated.
    -     * 
    - * - * optional bool supports_extended_agent_card = 13; - * @return The supportsExtendedAgentCard. - */ - @java.lang.Override - public boolean getSupportsExtendedAgentCard() { - return supportsExtendedAgentCard_; - } - /** - *
    -     * Whether the agent supports providing an extended agent card when authenticated.
    -     * 
    - * - * optional bool supports_extended_agent_card = 13; - * @param value The supportsExtendedAgentCard to set. - * @return This builder for chaining. - */ - public Builder setSupportsExtendedAgentCard(boolean value) { - - supportsExtendedAgentCard_ = value; - bitField0_ |= 0x00010000; - onChanged(); - return this; - } - /** - *
    -     * Whether the agent supports providing an extended agent card when authenticated.
    -     * 
    - * - * optional bool supports_extended_agent_card = 13; - * @return This builder for chaining. - */ - public Builder clearSupportsExtendedAgentCard() { - bitField0_ = (bitField0_ & ~0x00010000); - supportsExtendedAgentCard_ = false; - onChanged(); - return this; - } - private java.util.List signatures_ = java.util.Collections.emptyList(); private void ensureSignaturesIsMutable() { - if (!((bitField0_ & 0x00020000) != 0)) { + if (!((bitField0_ & 0x00002000) != 0)) { signatures_ = new java.util.ArrayList(signatures_); - bitField0_ |= 0x00020000; + bitField0_ |= 0x00002000; } } @@ -5380,7 +4480,7 @@ public Builder addAllSignatures( public Builder clearSignatures() { if (signaturesBuilder_ == null) { signatures_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00020000); + bitField0_ = (bitField0_ & ~0x00002000); onChanged(); } else { signaturesBuilder_.clear(); @@ -5485,7 +4585,7 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder( signaturesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< io.a2a.grpc.AgentCardSignature, io.a2a.grpc.AgentCardSignature.Builder, io.a2a.grpc.AgentCardSignatureOrBuilder>( signatures_, - ((bitField0_ & 0x00020000) != 0), + ((bitField0_ & 0x00002000) != 0), getParentForChildren(), isClean()); signatures_ = null; @@ -5503,7 +4603,7 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder( * @return Whether the iconUrl field is set. */ public boolean hasIconUrl() { - return ((bitField0_ & 0x00040000) != 0); + return ((bitField0_ & 0x00004000) != 0); } /** *
    @@ -5559,7 +4659,7 @@ public Builder setIconUrl(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
           iconUrl_ = value;
    -      bitField0_ |= 0x00040000;
    +      bitField0_ |= 0x00004000;
           onChanged();
           return this;
         }
    @@ -5573,7 +4673,7 @@ public Builder setIconUrl(
          */
         public Builder clearIconUrl() {
           iconUrl_ = getDefaultInstance().getIconUrl();
    -      bitField0_ = (bitField0_ & ~0x00040000);
    +      bitField0_ = (bitField0_ & ~0x00004000);
           onChanged();
           return this;
         }
    @@ -5591,7 +4691,7 @@ public Builder setIconUrlBytes(
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
           iconUrl_ = value;
    -      bitField0_ |= 0x00040000;
    +      bitField0_ |= 0x00004000;
           onChanged();
           return this;
         }
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java
    index 91ad7f3b4..8c31e3053 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java
    @@ -12,35 +12,56 @@ public interface AgentCardOrBuilder extends
     
       /**
        * 
    -   * The version of the A2A protocol this agent supports.
    -   * Default: "1.0"
    +   * The versions of the A2A protocol this agent supports.
    +   * For stable versions (1.x+), list only the latest supported minor version per major version.
    +   * For legacy experimental versions (0.x), explicitly list each supported version.
    +   * Default: ["1.0"]
        * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the protocolVersion field is set. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @return A list containing the protocolVersions. */ - boolean hasProtocolVersion(); + java.util.List + getProtocolVersionsList(); + /** + *
    +   * The versions of the A2A protocol this agent supports.
    +   * For stable versions (1.x+), list only the latest supported minor version per major version.
    +   * For legacy experimental versions (0.x), explicitly list each supported version.
    +   * Default: ["1.0"]
    +   * 
    + * + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @return The count of protocolVersions. + */ + int getProtocolVersionsCount(); /** *
    -   * The version of the A2A protocol this agent supports.
    -   * Default: "1.0"
    +   * The versions of the A2A protocol this agent supports.
    +   * For stable versions (1.x+), list only the latest supported minor version per major version.
    +   * For legacy experimental versions (0.x), explicitly list each supported version.
    +   * Default: ["1.0"]
        * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolVersion. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param index The index of the element to return. + * @return The protocolVersions at the given index. */ - java.lang.String getProtocolVersion(); + java.lang.String getProtocolVersions(int index); /** *
    -   * The version of the A2A protocol this agent supports.
    -   * Default: "1.0"
    +   * The versions of the A2A protocol this agent supports.
    +   * For stable versions (1.x+), list only the latest supported minor version per major version.
    +   * For legacy experimental versions (0.x), explicitly list each supported version.
    +   * Default: ["1.0"]
        * 
    * - * optional string protocol_version = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolVersion. + * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; + * @param index The index of the value to return. + * @return The bytes of the protocolVersions at the given index. */ com.google.protobuf.ByteString - getProtocolVersionBytes(); + getProtocolVersionsBytes(int index); /** *
    @@ -93,7 +114,7 @@ public interface AgentCardOrBuilder extends
        * Ordered list of supported interfaces. First entry is preferred.
        * 
    * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getSupportedInterfacesList(); @@ -102,7 +123,7 @@ public interface AgentCardOrBuilder extends * Ordered list of supported interfaces. First entry is preferred. *
    * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.AgentInterface getSupportedInterfaces(int index); /** @@ -110,7 +131,7 @@ public interface AgentCardOrBuilder extends * Ordered list of supported interfaces. First entry is preferred. *
    * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ int getSupportedInterfacesCount(); /** @@ -118,7 +139,7 @@ public interface AgentCardOrBuilder extends * Ordered list of supported interfaces. First entry is preferred. *
    * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getSupportedInterfacesOrBuilderList(); @@ -127,125 +148,11 @@ public interface AgentCardOrBuilder extends * Ordered list of supported interfaces. First entry is preferred. *
    * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19; + * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( int index); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return Whether the url field is set. - */ - @java.lang.Deprecated boolean hasUrl(); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return The url. - */ - @java.lang.Deprecated java.lang.String getUrl(); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string url = 3 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.url is deprecated. - * See a2a.proto;l=426 - * @return The bytes for url. - */ - @java.lang.Deprecated com.google.protobuf.ByteString - getUrlBytes(); - - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return Whether the preferredTransport field is set. - */ - @java.lang.Deprecated boolean hasPreferredTransport(); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return The preferredTransport. - */ - @java.lang.Deprecated java.lang.String getPreferredTransport(); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * optional string preferred_transport = 14 [deprecated = true]; - * @deprecated a2a.v1.AgentCard.preferred_transport is deprecated. - * See a2a.proto;l=428 - * @return The bytes for preferredTransport. - */ - @java.lang.Deprecated com.google.protobuf.ByteString - getPreferredTransportBytes(); - - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Deprecated java.util.List - getAdditionalInterfacesList(); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Deprecated io.a2a.grpc.AgentInterface getAdditionalInterfaces(int index); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Deprecated int getAdditionalInterfacesCount(); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Deprecated java.util.List - getAdditionalInterfacesOrBuilderList(); - /** - *
    -   * DEPRECATED: Use 'supported_interfaces' instead.
    -   * 
    - * - * repeated .a2a.v1.AgentInterface additional_interfaces = 15 [deprecated = true]; - */ - @java.lang.Deprecated io.a2a.grpc.AgentInterfaceOrBuilder getAdditionalInterfacesOrBuilder( - int index); - /** *
        * The service provider of the agent.
    @@ -598,25 +505,6 @@ io.a2a.grpc.SecurityOrBuilder getSecurityOrBuilder(
       io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
           int index);
     
    -  /**
    -   * 
    -   * Whether the agent supports providing an extended agent card when authenticated.
    -   * 
    - * - * optional bool supports_extended_agent_card = 13; - * @return Whether the supportsExtendedAgentCard field is set. - */ - boolean hasSupportsExtendedAgentCard(); - /** - *
    -   * Whether the agent supports providing an extended agent card when authenticated.
    -   * 
    - * - * optional bool supports_extended_agent_card = 13; - * @return The supportsExtendedAgentCard. - */ - boolean getSupportsExtendedAgentCard(); - /** *
        * JSON Web Signatures computed for this AgentCard.
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java
    index 9bbc4a253..06b7b8f41 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java
    @@ -299,6 +299,22 @@ public java.lang.String getScopesOrThrow(
         return map.get(key);
       }
     
    +  public static final int PKCE_REQUIRED_FIELD_NUMBER = 5;
    +  private boolean pkceRequired_ = false;
    +  /**
    +   * 
    +   * Indicates if PKCE (RFC 7636) is required for this flow.
    +   * PKCE should always be used for public clients and is recommended for all clients.
    +   * 
    + * + * bool pkce_required = 5; + * @return The pkceRequired. + */ + @java.lang.Override + public boolean getPkceRequired() { + return pkceRequired_; + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -328,6 +344,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) internalGetScopes(), ScopesDefaultEntryHolder.defaultEntry, 4); + if (pkceRequired_ != false) { + output.writeBool(5, pkceRequired_); + } getUnknownFields().writeTo(output); } @@ -356,6 +375,10 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(4, scopes__); } + if (pkceRequired_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(5, pkceRequired_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -379,6 +402,8 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getRefreshUrl())) return false; if (!internalGetScopes().equals( other.internalGetScopes())) return false; + if (getPkceRequired() + != other.getPkceRequired()) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -400,6 +425,9 @@ public int hashCode() { hash = (37 * hash) + SCOPES_FIELD_NUMBER; hash = (53 * hash) + internalGetScopes().hashCode(); } + hash = (37 * hash) + PKCE_REQUIRED_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getPkceRequired()); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -562,6 +590,7 @@ public Builder clear() { tokenUrl_ = ""; refreshUrl_ = ""; internalGetMutableScopes().clear(); + pkceRequired_ = false; return this; } @@ -608,6 +637,9 @@ private void buildPartial0(io.a2a.grpc.AuthorizationCodeOAuthFlow result) { result.scopes_ = internalGetScopes(); result.scopes_.makeImmutable(); } + if (((from_bitField0_ & 0x00000010) != 0)) { + result.pkceRequired_ = pkceRequired_; + } } @java.lang.Override @@ -640,6 +672,9 @@ public Builder mergeFrom(io.a2a.grpc.AuthorizationCodeOAuthFlow other) { internalGetMutableScopes().mergeFrom( other.internalGetScopes()); bitField0_ |= 0x00000008; + if (other.getPkceRequired() != false) { + setPkceRequired(other.getPkceRequired()); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -690,6 +725,11 @@ public Builder mergeFrom( bitField0_ |= 0x00000008; break; } // case 34 + case 40: { + pkceRequired_ = input.readBool(); + bitField0_ |= 0x00000010; + break; + } // case 40 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -1138,6 +1178,53 @@ public Builder putAllScopes( return this; } + private boolean pkceRequired_ ; + /** + *
    +     * Indicates if PKCE (RFC 7636) is required for this flow.
    +     * PKCE should always be used for public clients and is recommended for all clients.
    +     * 
    + * + * bool pkce_required = 5; + * @return The pkceRequired. + */ + @java.lang.Override + public boolean getPkceRequired() { + return pkceRequired_; + } + /** + *
    +     * Indicates if PKCE (RFC 7636) is required for this flow.
    +     * PKCE should always be used for public clients and is recommended for all clients.
    +     * 
    + * + * bool pkce_required = 5; + * @param value The pkceRequired to set. + * @return This builder for chaining. + */ + public Builder setPkceRequired(boolean value) { + + pkceRequired_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
    +     * Indicates if PKCE (RFC 7636) is required for this flow.
    +     * PKCE should always be used for public clients and is recommended for all clients.
    +     * 
    + * + * bool pkce_required = 5; + * @return This builder for chaining. + */ + public Builder clearPkceRequired() { + bitField0_ = (bitField0_ & ~0x00000010); + pkceRequired_ = false; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:a2a.v1.AuthorizationCodeOAuthFlow) } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java index b50acbd01..5dd2d393d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java @@ -123,4 +123,15 @@ java.lang.String getScopesOrDefault( */ java.lang.String getScopesOrThrow( java.lang.String key); + + /** + *
    +   * Indicates if PKCE (RFC 7636) is required for this flow.
    +   * PKCE should always be used for public clients and is recommended for all clients.
    +   * 
    + * + * bool pkce_required = 5; + * @return The pkceRequired. + */ + boolean getPkceRequired(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java similarity index 69% rename from spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java rename to spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java index 2f21f9789..701371c2b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java @@ -7,17 +7,19 @@ /** *
    - * --8<-- [start:PasswordOAuthFlow]
    - * Defines configuration details for the OAuth 2.0 Resource Owner Password flow.
    + * --8<-- [start:DeviceCodeOAuthFlow]
    + * Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628).
    + * This flow is designed for input-constrained devices such as IoT devices,
    + * and CLI tools where the user authenticates on a separate device.
      * 
    * - * Protobuf type {@code a2a.v1.PasswordOAuthFlow} + * Protobuf type {@code a2a.v1.DeviceCodeOAuthFlow} */ @com.google.protobuf.Generated -public final class PasswordOAuthFlow extends +public final class DeviceCodeOAuthFlow extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.PasswordOAuthFlow) - PasswordOAuthFlowOrBuilder { + // @@protoc_insertion_point(message_implements:a2a.v1.DeviceCodeOAuthFlow) + DeviceCodeOAuthFlowOrBuilder { private static final long serialVersionUID = 0L; static { com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( @@ -26,20 +28,21 @@ public final class PasswordOAuthFlow extends /* minor= */ 33, /* patch= */ 1, /* suffix= */ "", - "PasswordOAuthFlow"); + "DeviceCodeOAuthFlow"); } - // Use PasswordOAuthFlow.newBuilder() to construct. - private PasswordOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { + // Use DeviceCodeOAuthFlow.newBuilder() to construct. + private DeviceCodeOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); } - private PasswordOAuthFlow() { + private DeviceCodeOAuthFlow() { + deviceAuthorizationUrl_ = ""; tokenUrl_ = ""; refreshUrl_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -47,7 +50,7 @@ private PasswordOAuthFlow() { protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( int number) { switch (number) { - case 3: + case 4: return internalGetScopes(); default: throw new RuntimeException( @@ -57,12 +60,59 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class); + io.a2a.grpc.DeviceCodeOAuthFlow.class, io.a2a.grpc.DeviceCodeOAuthFlow.Builder.class); } - public static final int TOKEN_URL_FIELD_NUMBER = 1; + public static final int DEVICE_AUTHORIZATION_URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object deviceAuthorizationUrl_ = ""; + /** + *
    +   * The device authorization endpoint URL.
    +   * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The deviceAuthorizationUrl. + */ + @java.lang.Override + public java.lang.String getDeviceAuthorizationUrl() { + java.lang.Object ref = deviceAuthorizationUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + deviceAuthorizationUrl_ = s; + return s; + } + } + /** + *
    +   * The device authorization endpoint URL.
    +   * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for deviceAuthorizationUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDeviceAuthorizationUrlBytes() { + java.lang.Object ref = deviceAuthorizationUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + deviceAuthorizationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TOKEN_URL_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object tokenUrl_ = ""; /** @@ -70,7 +120,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl * The token URL to be used for this flow. *
    * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The tokenUrl. */ @java.lang.Override @@ -91,7 +141,7 @@ public java.lang.String getTokenUrl() { * The token URL to be used for this flow. *
    * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for tokenUrl. */ @java.lang.Override @@ -109,7 +159,7 @@ public java.lang.String getTokenUrl() { } } - public static final int REFRESH_URL_FIELD_NUMBER = 2; + public static final int REFRESH_URL_FIELD_NUMBER = 3; @SuppressWarnings("serial") private volatile java.lang.Object refreshUrl_ = ""; /** @@ -117,7 +167,7 @@ public java.lang.String getTokenUrl() { * The URL to be used for obtaining refresh tokens. *
    * - * string refresh_url = 2; + * string refresh_url = 3; * @return The refreshUrl. */ @java.lang.Override @@ -138,7 +188,7 @@ public java.lang.String getRefreshUrl() { * The URL to be used for obtaining refresh tokens. *
    * - * string refresh_url = 2; + * string refresh_url = 3; * @return The bytes for refreshUrl. */ @java.lang.Override @@ -156,13 +206,13 @@ public java.lang.String getRefreshUrl() { } } - public static final int SCOPES_FIELD_NUMBER = 3; + public static final int SCOPES_FIELD_NUMBER = 4; private static final class ScopesDefaultEntryHolder { static final com.google.protobuf.MapEntry< java.lang.String, java.lang.String> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.STRING, @@ -187,7 +237,7 @@ public int getScopesCount() { * The available scopes for the OAuth2 security scheme. *
    * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public boolean containsScopes( @@ -208,7 +258,7 @@ public java.util.Map getScopes() { * The available scopes for the OAuth2 security scheme. *
    * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.Map getScopesMap() { @@ -219,7 +269,7 @@ public java.util.Map getScopesMap() { * The available scopes for the OAuth2 security scheme. *
    * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public /* nullable */ @@ -237,7 +287,7 @@ java.lang.String getScopesOrDefault( * The available scopes for the OAuth2 security scheme. *
    * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.lang.String getScopesOrThrow( @@ -265,18 +315,21 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(deviceAuthorizationUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, deviceAuthorizationUrl_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, tokenUrl_); + com.google.protobuf.GeneratedMessage.writeString(output, 2, tokenUrl_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); + com.google.protobuf.GeneratedMessage.writeString(output, 3, refreshUrl_); } com.google.protobuf.GeneratedMessage .serializeStringMapTo( output, internalGetScopes(), ScopesDefaultEntryHolder.defaultEntry, - 3); + 4); getUnknownFields().writeTo(output); } @@ -286,11 +339,14 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(deviceAuthorizationUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, deviceAuthorizationUrl_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tokenUrl_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tokenUrl_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, refreshUrl_); } for (java.util.Map.Entry entry : internalGetScopes().getMap().entrySet()) { @@ -300,7 +356,7 @@ public int getSerializedSize() { .setValue(entry.getValue()) .build(); size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, scopes__); + .computeMessageSize(4, scopes__); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -312,11 +368,13 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.a2a.grpc.PasswordOAuthFlow)) { + if (!(obj instanceof io.a2a.grpc.DeviceCodeOAuthFlow)) { return super.equals(obj); } - io.a2a.grpc.PasswordOAuthFlow other = (io.a2a.grpc.PasswordOAuthFlow) obj; + io.a2a.grpc.DeviceCodeOAuthFlow other = (io.a2a.grpc.DeviceCodeOAuthFlow) obj; + if (!getDeviceAuthorizationUrl() + .equals(other.getDeviceAuthorizationUrl())) return false; if (!getTokenUrl() .equals(other.getTokenUrl())) return false; if (!getRefreshUrl() @@ -334,6 +392,8 @@ public int hashCode() { } int hash = 41; hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + DEVICE_AUTHORIZATION_URL_FIELD_NUMBER; + hash = (53 * hash) + getDeviceAuthorizationUrl().hashCode(); hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; hash = (53 * hash) + getTokenUrl().hashCode(); hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; @@ -347,44 +407,44 @@ public int hashCode() { return hash; } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom(byte[] data) + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom(java.io.InputStream input) + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -392,26 +452,26 @@ public static io.a2a.grpc.PasswordOAuthFlow parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.PasswordOAuthFlow parseDelimitedFrom(java.io.InputStream input) + public static io.a2a.grpc.DeviceCodeOAuthFlow parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.a2a.grpc.PasswordOAuthFlow parseDelimitedFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -424,7 +484,7 @@ public static io.a2a.grpc.PasswordOAuthFlow parseFrom( public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.a2a.grpc.PasswordOAuthFlow prototype) { + public static Builder newBuilder(io.a2a.grpc.DeviceCodeOAuthFlow prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -441,26 +501,28 @@ protected Builder newBuilderForType( } /** *
    -   * --8<-- [start:PasswordOAuthFlow]
    -   * Defines configuration details for the OAuth 2.0 Resource Owner Password flow.
    +   * --8<-- [start:DeviceCodeOAuthFlow]
    +   * Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628).
    +   * This flow is designed for input-constrained devices such as IoT devices,
    +   * and CLI tools where the user authenticates on a separate device.
        * 
    * - * Protobuf type {@code a2a.v1.PasswordOAuthFlow} + * Protobuf type {@code a2a.v1.DeviceCodeOAuthFlow} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.PasswordOAuthFlow) - io.a2a.grpc.PasswordOAuthFlowOrBuilder { + // @@protoc_insertion_point(builder_implements:a2a.v1.DeviceCodeOAuthFlow) + io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( int number) { switch (number) { - case 3: + case 4: return internalGetScopes(); default: throw new RuntimeException( @@ -471,7 +533,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( int number) { switch (number) { - case 3: + case 4: return internalGetMutableScopes(); default: throw new RuntimeException( @@ -481,12 +543,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class); + io.a2a.grpc.DeviceCodeOAuthFlow.class, io.a2a.grpc.DeviceCodeOAuthFlow.Builder.class); } - // Construct using io.a2a.grpc.PasswordOAuthFlow.newBuilder() + // Construct using io.a2a.grpc.DeviceCodeOAuthFlow.newBuilder() private Builder() { } @@ -500,6 +562,7 @@ private Builder( public Builder clear() { super.clear(); bitField0_ = 0; + deviceAuthorizationUrl_ = ""; tokenUrl_ = ""; refreshUrl_ = ""; internalGetMutableScopes().clear(); @@ -509,17 +572,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; } @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow getDefaultInstanceForType() { - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); + public io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstanceForType() { + return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); } @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow build() { - io.a2a.grpc.PasswordOAuthFlow result = buildPartial(); + public io.a2a.grpc.DeviceCodeOAuthFlow build() { + io.a2a.grpc.DeviceCodeOAuthFlow result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -527,22 +590,25 @@ public io.a2a.grpc.PasswordOAuthFlow build() { } @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow buildPartial() { - io.a2a.grpc.PasswordOAuthFlow result = new io.a2a.grpc.PasswordOAuthFlow(this); + public io.a2a.grpc.DeviceCodeOAuthFlow buildPartial() { + io.a2a.grpc.DeviceCodeOAuthFlow result = new io.a2a.grpc.DeviceCodeOAuthFlow(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.a2a.grpc.PasswordOAuthFlow result) { + private void buildPartial0(io.a2a.grpc.DeviceCodeOAuthFlow result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { - result.tokenUrl_ = tokenUrl_; + result.deviceAuthorizationUrl_ = deviceAuthorizationUrl_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.refreshUrl_ = refreshUrl_; + result.tokenUrl_ = tokenUrl_; } if (((from_bitField0_ & 0x00000004) != 0)) { + result.refreshUrl_ = refreshUrl_; + } + if (((from_bitField0_ & 0x00000008) != 0)) { result.scopes_ = internalGetScopes(); result.scopes_.makeImmutable(); } @@ -550,29 +616,34 @@ private void buildPartial0(io.a2a.grpc.PasswordOAuthFlow result) { @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.PasswordOAuthFlow) { - return mergeFrom((io.a2a.grpc.PasswordOAuthFlow)other); + if (other instanceof io.a2a.grpc.DeviceCodeOAuthFlow) { + return mergeFrom((io.a2a.grpc.DeviceCodeOAuthFlow)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.a2a.grpc.PasswordOAuthFlow other) { - if (other == io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance()) return this; + public Builder mergeFrom(io.a2a.grpc.DeviceCodeOAuthFlow other) { + if (other == io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance()) return this; + if (!other.getDeviceAuthorizationUrl().isEmpty()) { + deviceAuthorizationUrl_ = other.deviceAuthorizationUrl_; + bitField0_ |= 0x00000001; + onChanged(); + } if (!other.getTokenUrl().isEmpty()) { tokenUrl_ = other.tokenUrl_; - bitField0_ |= 0x00000001; + bitField0_ |= 0x00000002; onChanged(); } if (!other.getRefreshUrl().isEmpty()) { refreshUrl_ = other.refreshUrl_; - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000004; onChanged(); } internalGetMutableScopes().mergeFrom( other.internalGetScopes()); - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -600,24 +671,29 @@ public Builder mergeFrom( done = true; break; case 10: { - tokenUrl_ = input.readStringRequireUtf8(); + deviceAuthorizationUrl_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000001; break; } // case 10 case 18: { - refreshUrl_ = input.readStringRequireUtf8(); + tokenUrl_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; } // case 18 case 26: { + refreshUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 34: { com.google.protobuf.MapEntry scopes__ = input.readMessage( ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); internalGetMutableScopes().getMutableMap().put( scopes__.getKey(), scopes__.getValue()); - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; break; - } // case 26 + } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -635,13 +711,105 @@ public Builder mergeFrom( } private int bitField0_; + private java.lang.Object deviceAuthorizationUrl_ = ""; + /** + *
    +     * The device authorization endpoint URL.
    +     * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The deviceAuthorizationUrl. + */ + public java.lang.String getDeviceAuthorizationUrl() { + java.lang.Object ref = deviceAuthorizationUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + deviceAuthorizationUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The device authorization endpoint URL.
    +     * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for deviceAuthorizationUrl. + */ + public com.google.protobuf.ByteString + getDeviceAuthorizationUrlBytes() { + java.lang.Object ref = deviceAuthorizationUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + deviceAuthorizationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The device authorization endpoint URL.
    +     * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The deviceAuthorizationUrl to set. + * @return This builder for chaining. + */ + public Builder setDeviceAuthorizationUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + deviceAuthorizationUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
    +     * The device authorization endpoint URL.
    +     * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearDeviceAuthorizationUrl() { + deviceAuthorizationUrl_ = getDefaultInstance().getDeviceAuthorizationUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
    +     * The device authorization endpoint URL.
    +     * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for deviceAuthorizationUrl to set. + * @return This builder for chaining. + */ + public Builder setDeviceAuthorizationUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + deviceAuthorizationUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + private java.lang.Object tokenUrl_ = ""; /** *
          * The token URL to be used for this flow.
          * 
    * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The tokenUrl. */ public java.lang.String getTokenUrl() { @@ -661,7 +829,7 @@ public java.lang.String getTokenUrl() { * The token URL to be used for this flow. * * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for tokenUrl. */ public com.google.protobuf.ByteString @@ -682,7 +850,7 @@ public java.lang.String getTokenUrl() { * The token URL to be used for this flow. * * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The tokenUrl to set. * @return This builder for chaining. */ @@ -690,7 +858,7 @@ public Builder setTokenUrl( java.lang.String value) { if (value == null) { throw new NullPointerException(); } tokenUrl_ = value; - bitField0_ |= 0x00000001; + bitField0_ |= 0x00000002; onChanged(); return this; } @@ -699,12 +867,12 @@ public Builder setTokenUrl( * The token URL to be used for this flow. * * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearTokenUrl() { tokenUrl_ = getDefaultInstance().getTokenUrl(); - bitField0_ = (bitField0_ & ~0x00000001); + bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } @@ -713,7 +881,7 @@ public Builder clearTokenUrl() { * The token URL to be used for this flow. * * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for tokenUrl to set. * @return This builder for chaining. */ @@ -722,7 +890,7 @@ public Builder setTokenUrlBytes( if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); tokenUrl_ = value; - bitField0_ |= 0x00000001; + bitField0_ |= 0x00000002; onChanged(); return this; } @@ -733,7 +901,7 @@ public Builder setTokenUrlBytes( * The URL to be used for obtaining refresh tokens. * * - * string refresh_url = 2; + * string refresh_url = 3; * @return The refreshUrl. */ public java.lang.String getRefreshUrl() { @@ -753,7 +921,7 @@ public java.lang.String getRefreshUrl() { * The URL to be used for obtaining refresh tokens. * * - * string refresh_url = 2; + * string refresh_url = 3; * @return The bytes for refreshUrl. */ public com.google.protobuf.ByteString @@ -774,7 +942,7 @@ public java.lang.String getRefreshUrl() { * The URL to be used for obtaining refresh tokens. * * - * string refresh_url = 2; + * string refresh_url = 3; * @param value The refreshUrl to set. * @return This builder for chaining. */ @@ -782,7 +950,7 @@ public Builder setRefreshUrl( java.lang.String value) { if (value == null) { throw new NullPointerException(); } refreshUrl_ = value; - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000004; onChanged(); return this; } @@ -791,12 +959,12 @@ public Builder setRefreshUrl( * The URL to be used for obtaining refresh tokens. * * - * string refresh_url = 2; + * string refresh_url = 3; * @return This builder for chaining. */ public Builder clearRefreshUrl() { refreshUrl_ = getDefaultInstance().getRefreshUrl(); - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000004); onChanged(); return this; } @@ -805,7 +973,7 @@ public Builder clearRefreshUrl() { * The URL to be used for obtaining refresh tokens. * * - * string refresh_url = 2; + * string refresh_url = 3; * @param value The bytes for refreshUrl to set. * @return This builder for chaining. */ @@ -814,7 +982,7 @@ public Builder setRefreshUrlBytes( if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); refreshUrl_ = value; - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000004; onChanged(); return this; } @@ -838,7 +1006,7 @@ public Builder setRefreshUrlBytes( if (!scopes_.isMutable()) { scopes_ = scopes_.copy(); } - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; onChanged(); return scopes_; } @@ -850,7 +1018,7 @@ public int getScopesCount() { * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public boolean containsScopes( @@ -871,7 +1039,7 @@ public java.util.Map getScopes() { * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.Map getScopesMap() { @@ -882,7 +1050,7 @@ public java.util.Map getScopesMap() { * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public /* nullable */ @@ -900,7 +1068,7 @@ java.lang.String getScopesOrDefault( * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.lang.String getScopesOrThrow( @@ -914,7 +1082,7 @@ public java.lang.String getScopesOrThrow( return map.get(key); } public Builder clearScopes() { - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000008); internalGetMutableScopes().getMutableMap() .clear(); return this; @@ -924,7 +1092,7 @@ public Builder clearScopes() { * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder removeScopes( java.lang.String key) { @@ -939,7 +1107,7 @@ public Builder removeScopes( @java.lang.Deprecated public java.util.Map getMutableScopes() { - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; return internalGetMutableScopes().getMutableMap(); } /** @@ -947,7 +1115,7 @@ public Builder removeScopes( * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder putScopes( java.lang.String key, @@ -956,7 +1124,7 @@ public Builder putScopes( if (value == null) { throw new NullPointerException("map value"); } internalGetMutableScopes().getMutableMap() .put(key, value); - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; return this; } /** @@ -964,33 +1132,33 @@ public Builder putScopes( * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder putAllScopes( java.util.Map values) { internalGetMutableScopes().getMutableMap() .putAll(values); - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.PasswordOAuthFlow) + // @@protoc_insertion_point(builder_scope:a2a.v1.DeviceCodeOAuthFlow) } - // @@protoc_insertion_point(class_scope:a2a.v1.PasswordOAuthFlow) - private static final io.a2a.grpc.PasswordOAuthFlow DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:a2a.v1.DeviceCodeOAuthFlow) + private static final io.a2a.grpc.DeviceCodeOAuthFlow DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.a2a.grpc.PasswordOAuthFlow(); + DEFAULT_INSTANCE = new io.a2a.grpc.DeviceCodeOAuthFlow(); } - public static io.a2a.grpc.PasswordOAuthFlow getDefaultInstance() { + public static io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { @java.lang.Override - public PasswordOAuthFlow parsePartialFrom( + public DeviceCodeOAuthFlow parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { @@ -1009,17 +1177,17 @@ public PasswordOAuthFlow parsePartialFrom( } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } @java.lang.Override - public com.google.protobuf.Parser getParserForType() { + public com.google.protobuf.Parser getParserForType() { return PARSER; } @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow getDefaultInstanceForType() { + public io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstanceForType() { return DEFAULT_INSTANCE; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java similarity index 63% rename from spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java rename to spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java index 1b0aeeac0..761e2a6db 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java @@ -6,16 +6,36 @@ package io.a2a.grpc; @com.google.protobuf.Generated -public interface PasswordOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.PasswordOAuthFlow) +public interface DeviceCodeOAuthFlowOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.DeviceCodeOAuthFlow) com.google.protobuf.MessageOrBuilder { + /** + *
    +   * The device authorization endpoint URL.
    +   * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The deviceAuthorizationUrl. + */ + java.lang.String getDeviceAuthorizationUrl(); + /** + *
    +   * The device authorization endpoint URL.
    +   * 
    + * + * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for deviceAuthorizationUrl. + */ + com.google.protobuf.ByteString + getDeviceAuthorizationUrlBytes(); + /** *
        * The token URL to be used for this flow.
        * 
    * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The tokenUrl. */ java.lang.String getTokenUrl(); @@ -24,7 +44,7 @@ public interface PasswordOAuthFlowOrBuilder extends * The token URL to be used for this flow. * * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; + * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for tokenUrl. */ com.google.protobuf.ByteString @@ -35,7 +55,7 @@ public interface PasswordOAuthFlowOrBuilder extends * The URL to be used for obtaining refresh tokens. * * - * string refresh_url = 2; + * string refresh_url = 3; * @return The refreshUrl. */ java.lang.String getRefreshUrl(); @@ -44,7 +64,7 @@ public interface PasswordOAuthFlowOrBuilder extends * The URL to be used for obtaining refresh tokens. * * - * string refresh_url = 2; + * string refresh_url = 3; * @return The bytes for refreshUrl. */ com.google.protobuf.ByteString @@ -55,7 +75,7 @@ public interface PasswordOAuthFlowOrBuilder extends * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ int getScopesCount(); /** @@ -63,7 +83,7 @@ public interface PasswordOAuthFlowOrBuilder extends * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ boolean containsScopes( java.lang.String key); @@ -78,7 +98,7 @@ boolean containsScopes( * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ java.util.Map getScopesMap(); @@ -87,7 +107,7 @@ boolean containsScopes( * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ /* nullable */ java.lang.String getScopesOrDefault( @@ -99,7 +119,7 @@ java.lang.String getScopesOrDefault( * The available scopes for the OAuth2 security scheme. * * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; + * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; */ java.lang.String getScopesOrThrow( java.lang.String key); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java index 2322a9f8b..33395ab8d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java @@ -151,7 +151,10 @@ public java.lang.String getName() { private int historyLength_ = 0; /** *
    -   * The maximum number of messages to include in the history.
    +   * The maximum number of most recent messages from the task's history to retrieve. An
    +   * unset value means the client does not impose any limit. A value of zero is
    +   * a request to not include any messages. The server MUST NOT return more
    +   * messages than the provided value, but MAY apply a lower limit.
        * 
    * * optional int32 history_length = 2; @@ -163,7 +166,10 @@ public boolean hasHistoryLength() { } /** *
    -   * The maximum number of messages to include in the history.
    +   * The maximum number of most recent messages from the task's history to retrieve. An
    +   * unset value means the client does not impose any limit. A value of zero is
    +   * a request to not include any messages. The server MUST NOT return more
    +   * messages than the provided value, but MAY apply a lower limit.
        * 
    * * optional int32 history_length = 2; @@ -720,7 +726,10 @@ public Builder setNameBytes( private int historyLength_ ; /** *
    -     * The maximum number of messages to include in the history.
    +     * The maximum number of most recent messages from the task's history to retrieve. An
    +     * unset value means the client does not impose any limit. A value of zero is
    +     * a request to not include any messages. The server MUST NOT return more
    +     * messages than the provided value, but MAY apply a lower limit.
          * 
    * * optional int32 history_length = 2; @@ -732,7 +741,10 @@ public boolean hasHistoryLength() { } /** *
    -     * The maximum number of messages to include in the history.
    +     * The maximum number of most recent messages from the task's history to retrieve. An
    +     * unset value means the client does not impose any limit. A value of zero is
    +     * a request to not include any messages. The server MUST NOT return more
    +     * messages than the provided value, but MAY apply a lower limit.
          * 
    * * optional int32 history_length = 2; @@ -744,7 +756,10 @@ public int getHistoryLength() { } /** *
    -     * The maximum number of messages to include in the history.
    +     * The maximum number of most recent messages from the task's history to retrieve. An
    +     * unset value means the client does not impose any limit. A value of zero is
    +     * a request to not include any messages. The server MUST NOT return more
    +     * messages than the provided value, but MAY apply a lower limit.
          * 
    * * optional int32 history_length = 2; @@ -760,7 +775,10 @@ public Builder setHistoryLength(int value) { } /** *
    -     * The maximum number of messages to include in the history.
    +     * The maximum number of most recent messages from the task's history to retrieve. An
    +     * unset value means the client does not impose any limit. A value of zero is
    +     * a request to not include any messages. The server MUST NOT return more
    +     * messages than the provided value, but MAY apply a lower limit.
          * 
    * * optional int32 history_length = 2; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java index a17389884..1ef78600d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java @@ -54,7 +54,10 @@ public interface GetTaskRequestOrBuilder extends /** *
    -   * The maximum number of messages to include in the history.
    +   * The maximum number of most recent messages from the task's history to retrieve. An
    +   * unset value means the client does not impose any limit. A value of zero is
    +   * a request to not include any messages. The server MUST NOT return more
    +   * messages than the provided value, but MAY apply a lower limit.
        * 
    * * optional int32 history_length = 2; @@ -63,7 +66,10 @@ public interface GetTaskRequestOrBuilder extends boolean hasHistoryLength(); /** *
    -   * The maximum number of messages to include in the history.
    +   * The maximum number of most recent messages from the task's history to retrieve. An
    +   * unset value means the client does not impose any limit. A value of zero is
    +   * a request to not include any messages. The server MUST NOT return more
    +   * messages than the provided value, but MAY apply a lower limit.
        * 
    * * optional int32 history_length = 2; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java deleted file mode 100644 index a7f186016..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java +++ /dev/null @@ -1,1027 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
    - * --8<-- [start:ImplicitOAuthFlow]
    - * Defines configuration details for the OAuth 2.0 Implicit flow.
    - * 
    - * - * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} - */ -@com.google.protobuf.Generated -public final class ImplicitOAuthFlow extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ImplicitOAuthFlow) - ImplicitOAuthFlowOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "ImplicitOAuthFlow"); - } - // Use ImplicitOAuthFlow.newBuilder() to construct. - private ImplicitOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private ImplicitOAuthFlow() { - authorizationUrl_ = ""; - refreshUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class); - } - - public static final int AUTHORIZATION_URL_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object authorizationUrl_ = ""; - /** - *
    -   * The authorization URL to be used for this flow.
    -   * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The authorizationUrl. - */ - @java.lang.Override - public java.lang.String getAuthorizationUrl() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - authorizationUrl_ = s; - return s; - } - } - /** - *
    -   * The authorization URL to be used for this flow.
    -   * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for authorizationUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getAuthorizationUrlBytes() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - authorizationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int REFRESH_URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object refreshUrl_ = ""; - /** - *
    -   * The URL to be used for obtaining refresh tokens.
    -   * 
    - * - * string refresh_url = 2; - * @return The refreshUrl. - */ - @java.lang.Override - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } - } - /** - *
    -   * The URL to be used for obtaining refresh tokens.
    -   * 
    - * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SCOPES_FIELD_NUMBER = 3; - private static final class ScopesDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, java.lang.String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - @SuppressWarnings("serial") - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, authorizationUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); - } - com.google.protobuf.GeneratedMessage - .serializeStringMapTo( - output, - internalGetScopes(), - ScopesDefaultEntryHolder.defaultEntry, - 3); - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, authorizationUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); - } - for (java.util.Map.Entry entry - : internalGetScopes().getMap().entrySet()) { - com.google.protobuf.MapEntry - scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, scopes__); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.ImplicitOAuthFlow)) { - return super.equals(obj); - } - io.a2a.grpc.ImplicitOAuthFlow other = (io.a2a.grpc.ImplicitOAuthFlow) obj; - - if (!getAuthorizationUrl() - .equals(other.getAuthorizationUrl())) return false; - if (!getRefreshUrl() - .equals(other.getRefreshUrl())) return false; - if (!internalGetScopes().equals( - other.internalGetScopes())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + AUTHORIZATION_URL_FIELD_NUMBER; - hash = (53 * hash) + getAuthorizationUrl().hashCode(); - hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; - hash = (53 * hash) + getRefreshUrl().hashCode(); - if (!internalGetScopes().getMap().isEmpty()) { - hash = (37 * hash) + SCOPES_FIELD_NUMBER; - hash = (53 * hash) + internalGetScopes().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.ImplicitOAuthFlow parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.ImplicitOAuthFlow parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.ImplicitOAuthFlow prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
    -   * --8<-- [start:ImplicitOAuthFlow]
    -   * Defines configuration details for the OAuth 2.0 Implicit flow.
    -   * 
    - * - * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ImplicitOAuthFlow) - io.a2a.grpc.ImplicitOAuthFlowOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetMutableScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class); - } - - // Construct using io.a2a.grpc.ImplicitOAuthFlow.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - authorizationUrl_ = ""; - refreshUrl_ = ""; - internalGetMutableScopes().clear(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow getDefaultInstanceForType() { - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow build() { - io.a2a.grpc.ImplicitOAuthFlow result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow buildPartial() { - io.a2a.grpc.ImplicitOAuthFlow result = new io.a2a.grpc.ImplicitOAuthFlow(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.ImplicitOAuthFlow result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.authorizationUrl_ = authorizationUrl_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.refreshUrl_ = refreshUrl_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.scopes_ = internalGetScopes(); - result.scopes_.makeImmutable(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ImplicitOAuthFlow) { - return mergeFrom((io.a2a.grpc.ImplicitOAuthFlow)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.ImplicitOAuthFlow other) { - if (other == io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance()) return this; - if (!other.getAuthorizationUrl().isEmpty()) { - authorizationUrl_ = other.authorizationUrl_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getRefreshUrl().isEmpty()) { - refreshUrl_ = other.refreshUrl_; - bitField0_ |= 0x00000002; - onChanged(); - } - internalGetMutableScopes().mergeFrom( - other.internalGetScopes()); - bitField0_ |= 0x00000004; - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - authorizationUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - refreshUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - com.google.protobuf.MapEntry - scopes__ = input.readMessage( - ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - internalGetMutableScopes().getMutableMap().put( - scopes__.getKey(), scopes__.getValue()); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object authorizationUrl_ = ""; - /** - *
    -     * The authorization URL to be used for this flow.
    -     * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The authorizationUrl. - */ - public java.lang.String getAuthorizationUrl() { - java.lang.Object ref = authorizationUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - authorizationUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
    -     * The authorization URL to be used for this flow.
    -     * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for authorizationUrl. - */ - public com.google.protobuf.ByteString - getAuthorizationUrlBytes() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - authorizationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
    -     * The authorization URL to be used for this flow.
    -     * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The authorizationUrl to set. - * @return This builder for chaining. - */ - public Builder setAuthorizationUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - authorizationUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
    -     * The authorization URL to be used for this flow.
    -     * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearAuthorizationUrl() { - authorizationUrl_ = getDefaultInstance().getAuthorizationUrl(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
    -     * The authorization URL to be used for this flow.
    -     * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for authorizationUrl to set. - * @return This builder for chaining. - */ - public Builder setAuthorizationUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - authorizationUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object refreshUrl_ = ""; - /** - *
    -     * The URL to be used for obtaining refresh tokens.
    -     * 
    - * - * string refresh_url = 2; - * @return The refreshUrl. - */ - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
    -     * The URL to be used for obtaining refresh tokens.
    -     * 
    - * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
    -     * The URL to be used for obtaining refresh tokens.
    -     * 
    - * - * string refresh_url = 2; - * @param value The refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - refreshUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
    -     * The URL to be used for obtaining refresh tokens.
    -     * 
    - * - * string refresh_url = 2; - * @return This builder for chaining. - */ - public Builder clearRefreshUrl() { - refreshUrl_ = getDefaultInstance().getRefreshUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
    -     * The URL to be used for obtaining refresh tokens.
    -     * 
    - * - * string refresh_url = 2; - * @param value The bytes for refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - refreshUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - private com.google.protobuf.MapField - internalGetMutableScopes() { - if (scopes_ == null) { - scopes_ = com.google.protobuf.MapField.newMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - if (!scopes_.isMutable()) { - scopes_ = scopes_.copy(); - } - bitField0_ |= 0x00000004; - onChanged(); - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
    -     * The available scopes for the OAuth2 security scheme.
    -     * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
    -     * The available scopes for the OAuth2 security scheme.
    -     * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
    -     * The available scopes for the OAuth2 security scheme.
    -     * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
    -     * The available scopes for the OAuth2 security scheme.
    -     * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - public Builder clearScopes() { - bitField0_ = (bitField0_ & ~0x00000004); - internalGetMutableScopes().getMutableMap() - .clear(); - return this; - } - /** - *
    -     * The available scopes for the OAuth2 security scheme.
    -     * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - internalGetMutableScopes().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableScopes() { - bitField0_ |= 0x00000004; - return internalGetMutableScopes().getMutableMap(); - } - /** - *
    -     * The available scopes for the OAuth2 security scheme.
    -     * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder putScopes( - java.lang.String key, - java.lang.String value) { - if (key == null) { throw new NullPointerException("map key"); } - if (value == null) { throw new NullPointerException("map value"); } - internalGetMutableScopes().getMutableMap() - .put(key, value); - bitField0_ |= 0x00000004; - return this; - } - /** - *
    -     * The available scopes for the OAuth2 security scheme.
    -     * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder putAllScopes( - java.util.Map values) { - internalGetMutableScopes().getMutableMap() - .putAll(values); - bitField0_ |= 0x00000004; - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.ImplicitOAuthFlow) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.ImplicitOAuthFlow) - private static final io.a2a.grpc.ImplicitOAuthFlow DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.ImplicitOAuthFlow(); - } - - public static io.a2a.grpc.ImplicitOAuthFlow getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ImplicitOAuthFlow parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java deleted file mode 100644 index e59040641..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java +++ /dev/null @@ -1,106 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface ImplicitOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ImplicitOAuthFlow) - com.google.protobuf.MessageOrBuilder { - - /** - *
    -   * The authorization URL to be used for this flow.
    -   * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The authorizationUrl. - */ - java.lang.String getAuthorizationUrl(); - /** - *
    -   * The authorization URL to be used for this flow.
    -   * 
    - * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for authorizationUrl. - */ - com.google.protobuf.ByteString - getAuthorizationUrlBytes(); - - /** - *
    -   * The URL to be used for obtaining refresh tokens.
    -   * 
    - * - * string refresh_url = 2; - * @return The refreshUrl. - */ - java.lang.String getRefreshUrl(); - /** - *
    -   * The URL to be used for obtaining refresh tokens.
    -   * 
    - * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - com.google.protobuf.ByteString - getRefreshUrlBytes(); - - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - int getScopesCount(); - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - boolean containsScopes( - java.lang.String key); - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getScopes(); - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.Map - getScopesMap(); - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue); - /** - *
    -   * The available scopes for the OAuth2 security scheme.
    -   * 
    - * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - java.lang.String getScopesOrThrow( - java.lang.String key); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java index 93d5a8bc9..c2645afcc 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java @@ -276,20 +276,45 @@ public int getHistoryLength() { return historyLength_; } - public static final int LAST_UPDATED_AFTER_FIELD_NUMBER = 6; - private long lastUpdatedAfter_ = 0L; + public static final int STATUS_TIMESTAMP_AFTER_FIELD_NUMBER = 6; + private com.google.protobuf.Timestamp statusTimestampAfter_; /** *
    -   * Filter tasks updated after this timestamp (milliseconds since epoch).
    -   * Only tasks with a last updated time greater than or equal to this value will be returned.
    +   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
        * 
    * - * int64 last_updated_after = 6; - * @return The lastUpdatedAfter. + * .google.protobuf.Timestamp status_timestamp_after = 6; + * @return Whether the statusTimestampAfter field is set. */ @java.lang.Override - public long getLastUpdatedAfter() { - return lastUpdatedAfter_; + public boolean hasStatusTimestampAfter() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
    +   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +   * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + * @return The statusTimestampAfter. + */ + @java.lang.Override + public com.google.protobuf.Timestamp getStatusTimestampAfter() { + return statusTimestampAfter_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; + } + /** + *
    +   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +   * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + */ + @java.lang.Override + public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder() { + return statusTimestampAfter_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; } public static final int INCLUDE_ARTIFACTS_FIELD_NUMBER = 7; @@ -305,7 +330,7 @@ public long getLastUpdatedAfter() { */ @java.lang.Override public boolean hasIncludeArtifacts() { - return ((bitField0_ & 0x00000004) != 0); + return ((bitField0_ & 0x00000008) != 0); } /** *
    @@ -350,10 +375,10 @@ public void writeTo(com.google.protobuf.CodedOutputStream output)
         if (((bitField0_ & 0x00000002) != 0)) {
           output.writeInt32(5, historyLength_);
         }
    -    if (lastUpdatedAfter_ != 0L) {
    -      output.writeInt64(6, lastUpdatedAfter_);
    -    }
         if (((bitField0_ & 0x00000004) != 0)) {
    +      output.writeMessage(6, getStatusTimestampAfter());
    +    }
    +    if (((bitField0_ & 0x00000008) != 0)) {
           output.writeBool(7, includeArtifacts_);
         }
         if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) {
    @@ -386,11 +411,11 @@ public int getSerializedSize() {
           size += com.google.protobuf.CodedOutputStream
             .computeInt32Size(5, historyLength_);
         }
    -    if (lastUpdatedAfter_ != 0L) {
    +    if (((bitField0_ & 0x00000004) != 0)) {
           size += com.google.protobuf.CodedOutputStream
    -        .computeInt64Size(6, lastUpdatedAfter_);
    +        .computeMessageSize(6, getStatusTimestampAfter());
         }
    -    if (((bitField0_ & 0x00000004) != 0)) {
    +    if (((bitField0_ & 0x00000008) != 0)) {
           size += com.google.protobuf.CodedOutputStream
             .computeBoolSize(7, includeArtifacts_);
         }
    @@ -429,8 +454,11 @@ public boolean equals(final java.lang.Object obj) {
           if (getHistoryLength()
               != other.getHistoryLength()) return false;
         }
    -    if (getLastUpdatedAfter()
    -        != other.getLastUpdatedAfter()) return false;
    +    if (hasStatusTimestampAfter() != other.hasStatusTimestampAfter()) return false;
    +    if (hasStatusTimestampAfter()) {
    +      if (!getStatusTimestampAfter()
    +          .equals(other.getStatusTimestampAfter())) return false;
    +    }
         if (hasIncludeArtifacts() != other.hasIncludeArtifacts()) return false;
         if (hasIncludeArtifacts()) {
           if (getIncludeArtifacts()
    @@ -463,9 +491,10 @@ public int hashCode() {
           hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER;
           hash = (53 * hash) + getHistoryLength();
         }
    -    hash = (37 * hash) + LAST_UPDATED_AFTER_FIELD_NUMBER;
    -    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
    -        getLastUpdatedAfter());
    +    if (hasStatusTimestampAfter()) {
    +      hash = (37 * hash) + STATUS_TIMESTAMP_AFTER_FIELD_NUMBER;
    +      hash = (53 * hash) + getStatusTimestampAfter().hashCode();
    +    }
         if (hasIncludeArtifacts()) {
           hash = (37 * hash) + INCLUDE_ARTIFACTS_FIELD_NUMBER;
           hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
    @@ -595,13 +624,19 @@ public static final class Builder extends
     
         // Construct using io.a2a.grpc.ListTasksRequest.newBuilder()
         private Builder() {
    -
    +      maybeForceBuilderInitialization();
         }
     
         private Builder(
             com.google.protobuf.GeneratedMessage.BuilderParent parent) {
           super(parent);
    -
    +      maybeForceBuilderInitialization();
    +    }
    +    private void maybeForceBuilderInitialization() {
    +      if (com.google.protobuf.GeneratedMessage
    +              .alwaysUseFieldBuilders) {
    +        internalGetStatusTimestampAfterFieldBuilder();
    +      }
         }
         @java.lang.Override
         public Builder clear() {
    @@ -613,7 +648,11 @@ public Builder clear() {
           pageSize_ = 0;
           pageToken_ = "";
           historyLength_ = 0;
    -      lastUpdatedAfter_ = 0L;
    +      statusTimestampAfter_ = null;
    +      if (statusTimestampAfterBuilder_ != null) {
    +        statusTimestampAfterBuilder_.dispose();
    +        statusTimestampAfterBuilder_ = null;
    +      }
           includeArtifacts_ = false;
           return this;
         }
    @@ -670,11 +709,14 @@ private void buildPartial0(io.a2a.grpc.ListTasksRequest result) {
             to_bitField0_ |= 0x00000002;
           }
           if (((from_bitField0_ & 0x00000040) != 0)) {
    -        result.lastUpdatedAfter_ = lastUpdatedAfter_;
    +        result.statusTimestampAfter_ = statusTimestampAfterBuilder_ == null
    +            ? statusTimestampAfter_
    +            : statusTimestampAfterBuilder_.build();
    +        to_bitField0_ |= 0x00000004;
           }
           if (((from_bitField0_ & 0x00000080) != 0)) {
             result.includeArtifacts_ = includeArtifacts_;
    -        to_bitField0_ |= 0x00000004;
    +        to_bitField0_ |= 0x00000008;
           }
           result.bitField0_ |= to_bitField0_;
         }
    @@ -715,8 +757,8 @@ public Builder mergeFrom(io.a2a.grpc.ListTasksRequest other) {
           if (other.hasHistoryLength()) {
             setHistoryLength(other.getHistoryLength());
           }
    -      if (other.getLastUpdatedAfter() != 0L) {
    -        setLastUpdatedAfter(other.getLastUpdatedAfter());
    +      if (other.hasStatusTimestampAfter()) {
    +        mergeStatusTimestampAfter(other.getStatusTimestampAfter());
           }
           if (other.hasIncludeArtifacts()) {
             setIncludeArtifacts(other.getIncludeArtifacts());
    @@ -772,11 +814,13 @@ public Builder mergeFrom(
                   bitField0_ |= 0x00000020;
                   break;
                 } // case 40
    -            case 48: {
    -              lastUpdatedAfter_ = input.readInt64();
    +            case 50: {
    +              input.readMessage(
    +                  internalGetStatusTimestampAfterFieldBuilder().getBuilder(),
    +                  extensionRegistry);
                   bitField0_ |= 0x00000040;
                   break;
    -            } // case 48
    +            } // case 50
                 case 56: {
                   includeArtifacts_ = input.readBool();
                   bitField0_ |= 0x00000080;
    @@ -1267,52 +1311,171 @@ public Builder clearHistoryLength() {
           return this;
         }
     
    -    private long lastUpdatedAfter_ ;
    +    private com.google.protobuf.Timestamp statusTimestampAfter_;
    +    private com.google.protobuf.SingleFieldBuilder<
    +        com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> statusTimestampAfterBuilder_;
         /**
          * 
    -     * Filter tasks updated after this timestamp (milliseconds since epoch).
    -     * Only tasks with a last updated time greater than or equal to this value will be returned.
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
          * 
    * - * int64 last_updated_after = 6; - * @return The lastUpdatedAfter. + * .google.protobuf.Timestamp status_timestamp_after = 6; + * @return Whether the statusTimestampAfter field is set. */ - @java.lang.Override - public long getLastUpdatedAfter() { - return lastUpdatedAfter_; + public boolean hasStatusTimestampAfter() { + return ((bitField0_ & 0x00000040) != 0); } /** *
    -     * Filter tasks updated after this timestamp (milliseconds since epoch).
    -     * Only tasks with a last updated time greater than or equal to this value will be returned.
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
          * 
    * - * int64 last_updated_after = 6; - * @param value The lastUpdatedAfter to set. - * @return This builder for chaining. + * .google.protobuf.Timestamp status_timestamp_after = 6; + * @return The statusTimestampAfter. */ - public Builder setLastUpdatedAfter(long value) { - - lastUpdatedAfter_ = value; + public com.google.protobuf.Timestamp getStatusTimestampAfter() { + if (statusTimestampAfterBuilder_ == null) { + return statusTimestampAfter_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; + } else { + return statusTimestampAfterBuilder_.getMessage(); + } + } + /** + *
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +     * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + */ + public Builder setStatusTimestampAfter(com.google.protobuf.Timestamp value) { + if (statusTimestampAfterBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + statusTimestampAfter_ = value; + } else { + statusTimestampAfterBuilder_.setMessage(value); + } bitField0_ |= 0x00000040; onChanged(); return this; } /** *
    -     * Filter tasks updated after this timestamp (milliseconds since epoch).
    -     * Only tasks with a last updated time greater than or equal to this value will be returned.
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
          * 
    * - * int64 last_updated_after = 6; - * @return This builder for chaining. + * .google.protobuf.Timestamp status_timestamp_after = 6; */ - public Builder clearLastUpdatedAfter() { + public Builder setStatusTimestampAfter( + com.google.protobuf.Timestamp.Builder builderForValue) { + if (statusTimestampAfterBuilder_ == null) { + statusTimestampAfter_ = builderForValue.build(); + } else { + statusTimestampAfterBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +     * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + */ + public Builder mergeStatusTimestampAfter(com.google.protobuf.Timestamp value) { + if (statusTimestampAfterBuilder_ == null) { + if (((bitField0_ & 0x00000040) != 0) && + statusTimestampAfter_ != null && + statusTimestampAfter_ != com.google.protobuf.Timestamp.getDefaultInstance()) { + getStatusTimestampAfterBuilder().mergeFrom(value); + } else { + statusTimestampAfter_ = value; + } + } else { + statusTimestampAfterBuilder_.mergeFrom(value); + } + if (statusTimestampAfter_ != null) { + bitField0_ |= 0x00000040; + onChanged(); + } + return this; + } + /** + *
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +     * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + */ + public Builder clearStatusTimestampAfter() { bitField0_ = (bitField0_ & ~0x00000040); - lastUpdatedAfter_ = 0L; + statusTimestampAfter_ = null; + if (statusTimestampAfterBuilder_ != null) { + statusTimestampAfterBuilder_.dispose(); + statusTimestampAfterBuilder_ = null; + } onChanged(); return this; } + /** + *
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +     * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + */ + public com.google.protobuf.Timestamp.Builder getStatusTimestampAfterBuilder() { + bitField0_ |= 0x00000040; + onChanged(); + return internalGetStatusTimestampAfterFieldBuilder().getBuilder(); + } + /** + *
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +     * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + */ + public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder() { + if (statusTimestampAfterBuilder_ != null) { + return statusTimestampAfterBuilder_.getMessageOrBuilder(); + } else { + return statusTimestampAfter_ == null ? + com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; + } + } + /** + *
    +     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +     * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> + internalGetStatusTimestampAfterFieldBuilder() { + if (statusTimestampAfterBuilder_ == null) { + statusTimestampAfterBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>( + getStatusTimestampAfter(), + getParentForChildren(), + isClean()); + statusTimestampAfter_ = null; + } + return statusTimestampAfterBuilder_; + } private boolean includeArtifacts_ ; /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java index 6b832c0d1..410485d50 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java @@ -131,14 +131,33 @@ public interface ListTasksRequestOrBuilder extends /** *
    -   * Filter tasks updated after this timestamp (milliseconds since epoch).
    -   * Only tasks with a last updated time greater than or equal to this value will be returned.
    +   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
        * 
    * - * int64 last_updated_after = 6; - * @return The lastUpdatedAfter. + * .google.protobuf.Timestamp status_timestamp_after = 6; + * @return Whether the statusTimestampAfter field is set. */ - long getLastUpdatedAfter(); + boolean hasStatusTimestampAfter(); + /** + *
    +   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +   * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + * @return The statusTimestampAfter. + */ + com.google.protobuf.Timestamp getStatusTimestampAfter(); + /** + *
    +   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
    +   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
    +   * 
    + * + * .google.protobuf.Timestamp status_timestamp_after = 6; + */ + com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder(); /** *
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Message.java b/spec-grpc/src/main/java/io/a2a/grpc/Message.java
    index 8ff6a60f6..e8f296411 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/Message.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/Message.java
    @@ -8,13 +8,12 @@
     /**
      * 
      * --8<-- [start:Message]
    - * Message is one unit of communication between client and server. It is
    - * associated with a context and optionally a task. Since the server is
    - * responsible for the context definition, it must always provide a context_id
    - * in its messages. The client can optionally provide the context_id if it
    - * knows the context to associate the message to. Similarly for task_id,
    - * except the server decides if a task is created and whether to include the
    - * task_id.
    + * Message is one unit of communication between client and server. It can be
    + * associated with a context and/or a task. For server messages, context_id must
    + * be provided, and task_id only if a task was created. For client messages, both
    + * fields are optional, with the caveat that if both are provided, they have to
    + * match (the context_id has to be the one that is set on the task). If only
    + * task_id is provided, the server will infer context_id from it.
      * 
    * * Protobuf type {@code a2a.v1.Message} @@ -702,13 +701,12 @@ protected Builder newBuilderForType( /** *
        * --8<-- [start:Message]
    -   * Message is one unit of communication between client and server. It is
    -   * associated with a context and optionally a task. Since the server is
    -   * responsible for the context definition, it must always provide a context_id
    -   * in its messages. The client can optionally provide the context_id if it
    -   * knows the context to associate the message to. Similarly for task_id,
    -   * except the server decides if a task is created and whether to include the
    -   * task_id.
    +   * Message is one unit of communication between client and server. It can be
    +   * associated with a context and/or a task. For server messages, context_id must
    +   * be provided, and task_id only if a task was created. For client messages, both
    +   * fields are optional, with the caveat that if both are provided, they have to
    +   * match (the context_id has to be the one that is set on the task). If only
    +   * task_id is provided, the server will infer context_id from it.
        * 
    * * Protobuf type {@code a2a.v1.Message} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java index f2da009e6..e4fd7c957 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java @@ -56,8 +56,7 @@ public enum FlowCase com.google.protobuf.AbstractMessage.InternalOneOfEnum { AUTHORIZATION_CODE(1), CLIENT_CREDENTIALS(2), - IMPLICIT(3), - PASSWORD(4), + DEVICE_CODE(5), FLOW_NOT_SET(0); private final int value; private FlowCase(int value) { @@ -77,8 +76,7 @@ public static FlowCase forNumber(int value) { switch (value) { case 1: return AUTHORIZATION_CODE; case 2: return CLIENT_CREDENTIALS; - case 3: return IMPLICIT; - case 4: return PASSWORD; + case 5: return DEVICE_CODE; case 0: return FLOW_NOT_SET; default: return null; } @@ -180,90 +178,47 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); } - public static final int IMPLICIT_FIELD_NUMBER = 3; + public static final int DEVICE_CODE_FIELD_NUMBER = 5; /** *
    -   * Configuration for the OAuth Implicit flow.
    +   * Configuration for the OAuth Device Code flow.
        * 
    * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - * @return Whether the implicit field is set. + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * @return Whether the deviceCode field is set. */ @java.lang.Override - public boolean hasImplicit() { - return flowCase_ == 3; + public boolean hasDeviceCode() { + return flowCase_ == 5; } /** *
    -   * Configuration for the OAuth Implicit flow.
    +   * Configuration for the OAuth Device Code flow.
        * 
    * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - * @return The implicit. + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * @return The deviceCode. */ @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow getImplicit() { - if (flowCase_ == 3) { - return (io.a2a.grpc.ImplicitOAuthFlow) flow_; + public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() { + if (flowCase_ == 5) { + return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_; } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); + return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); } /** *
    -   * Configuration for the OAuth Implicit flow.
    +   * Configuration for the OAuth Device Code flow.
        * 
    * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() { - if (flowCase_ == 3) { - return (io.a2a.grpc.ImplicitOAuthFlow) flow_; + public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() { + if (flowCase_ == 5) { + return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_; } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - - public static final int PASSWORD_FIELD_NUMBER = 4; - /** - *
    -   * Configuration for the OAuth Resource Owner Password flow.
    -   * 
    - * - * .a2a.v1.PasswordOAuthFlow password = 4; - * @return Whether the password field is set. - */ - @java.lang.Override - public boolean hasPassword() { - return flowCase_ == 4; - } - /** - *
    -   * Configuration for the OAuth Resource Owner Password flow.
    -   * 
    - * - * .a2a.v1.PasswordOAuthFlow password = 4; - * @return The password. - */ - @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow getPassword() { - if (flowCase_ == 4) { - return (io.a2a.grpc.PasswordOAuthFlow) flow_; - } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); - } - /** - *
    -   * Configuration for the OAuth Resource Owner Password flow.
    -   * 
    - * - * .a2a.v1.PasswordOAuthFlow password = 4; - */ - @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() { - if (flowCase_ == 4) { - return (io.a2a.grpc.PasswordOAuthFlow) flow_; - } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); + return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); } private byte memoizedIsInitialized = -1; @@ -286,11 +241,8 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (flowCase_ == 2) { output.writeMessage(2, (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_); } - if (flowCase_ == 3) { - output.writeMessage(3, (io.a2a.grpc.ImplicitOAuthFlow) flow_); - } - if (flowCase_ == 4) { - output.writeMessage(4, (io.a2a.grpc.PasswordOAuthFlow) flow_); + if (flowCase_ == 5) { + output.writeMessage(5, (io.a2a.grpc.DeviceCodeOAuthFlow) flow_); } getUnknownFields().writeTo(output); } @@ -309,13 +261,9 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(2, (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_); } - if (flowCase_ == 3) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, (io.a2a.grpc.ImplicitOAuthFlow) flow_); - } - if (flowCase_ == 4) { + if (flowCase_ == 5) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, (io.a2a.grpc.PasswordOAuthFlow) flow_); + .computeMessageSize(5, (io.a2a.grpc.DeviceCodeOAuthFlow) flow_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -342,13 +290,9 @@ public boolean equals(final java.lang.Object obj) { if (!getClientCredentials() .equals(other.getClientCredentials())) return false; break; - case 3: - if (!getImplicit() - .equals(other.getImplicit())) return false; - break; - case 4: - if (!getPassword() - .equals(other.getPassword())) return false; + case 5: + if (!getDeviceCode() + .equals(other.getDeviceCode())) return false; break; case 0: default: @@ -373,13 +317,9 @@ public int hashCode() { hash = (37 * hash) + CLIENT_CREDENTIALS_FIELD_NUMBER; hash = (53 * hash) + getClientCredentials().hashCode(); break; - case 3: - hash = (37 * hash) + IMPLICIT_FIELD_NUMBER; - hash = (53 * hash) + getImplicit().hashCode(); - break; - case 4: - hash = (37 * hash) + PASSWORD_FIELD_NUMBER; - hash = (53 * hash) + getPassword().hashCode(); + case 5: + hash = (37 * hash) + DEVICE_CODE_FIELD_NUMBER; + hash = (53 * hash) + getDeviceCode().hashCode(); break; case 0: default: @@ -526,11 +466,8 @@ public Builder clear() { if (clientCredentialsBuilder_ != null) { clientCredentialsBuilder_.clear(); } - if (implicitBuilder_ != null) { - implicitBuilder_.clear(); - } - if (passwordBuilder_ != null) { - passwordBuilder_.clear(); + if (deviceCodeBuilder_ != null) { + deviceCodeBuilder_.clear(); } flowCase_ = 0; flow_ = null; @@ -581,13 +518,9 @@ private void buildPartialOneofs(io.a2a.grpc.OAuthFlows result) { clientCredentialsBuilder_ != null) { result.flow_ = clientCredentialsBuilder_.build(); } - if (flowCase_ == 3 && - implicitBuilder_ != null) { - result.flow_ = implicitBuilder_.build(); - } - if (flowCase_ == 4 && - passwordBuilder_ != null) { - result.flow_ = passwordBuilder_.build(); + if (flowCase_ == 5 && + deviceCodeBuilder_ != null) { + result.flow_ = deviceCodeBuilder_.build(); } } @@ -612,12 +545,8 @@ public Builder mergeFrom(io.a2a.grpc.OAuthFlows other) { mergeClientCredentials(other.getClientCredentials()); break; } - case IMPLICIT: { - mergeImplicit(other.getImplicit()); - break; - } - case PASSWORD: { - mergePassword(other.getPassword()); + case DEVICE_CODE: { + mergeDeviceCode(other.getDeviceCode()); break; } case FLOW_NOT_SET: { @@ -664,20 +593,13 @@ public Builder mergeFrom( flowCase_ = 2; break; } // case 18 - case 26: { - input.readMessage( - internalGetImplicitFieldBuilder().getBuilder(), - extensionRegistry); - flowCase_ = 3; - break; - } // case 26 - case 34: { + case 42: { input.readMessage( - internalGetPasswordFieldBuilder().getBuilder(), + internalGetDeviceCodeFieldBuilder().getBuilder(), extensionRegistry); - flowCase_ = 4; + flowCase_ = 5; break; - } // case 34 + } // case 42 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -1067,359 +989,181 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui } private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> implicitBuilder_; - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - * @return Whether the implicit field is set. - */ - @java.lang.Override - public boolean hasImplicit() { - return flowCase_ == 3; - } - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - * @return The implicit. - */ - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow getImplicit() { - if (implicitBuilder_ == null) { - if (flowCase_ == 3) { - return (io.a2a.grpc.ImplicitOAuthFlow) flow_; - } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } else { - if (flowCase_ == 3) { - return implicitBuilder_.getMessage(); - } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - } - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - */ - public Builder setImplicit(io.a2a.grpc.ImplicitOAuthFlow value) { - if (implicitBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - flow_ = value; - onChanged(); - } else { - implicitBuilder_.setMessage(value); - } - flowCase_ = 3; - return this; - } - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - */ - public Builder setImplicit( - io.a2a.grpc.ImplicitOAuthFlow.Builder builderForValue) { - if (implicitBuilder_ == null) { - flow_ = builderForValue.build(); - onChanged(); - } else { - implicitBuilder_.setMessage(builderForValue.build()); - } - flowCase_ = 3; - return this; - } - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - */ - public Builder mergeImplicit(io.a2a.grpc.ImplicitOAuthFlow value) { - if (implicitBuilder_ == null) { - if (flowCase_ == 3 && - flow_ != io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance()) { - flow_ = io.a2a.grpc.ImplicitOAuthFlow.newBuilder((io.a2a.grpc.ImplicitOAuthFlow) flow_) - .mergeFrom(value).buildPartial(); - } else { - flow_ = value; - } - onChanged(); - } else { - if (flowCase_ == 3) { - implicitBuilder_.mergeFrom(value); - } else { - implicitBuilder_.setMessage(value); - } - } - flowCase_ = 3; - return this; - } - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - */ - public Builder clearImplicit() { - if (implicitBuilder_ == null) { - if (flowCase_ == 3) { - flowCase_ = 0; - flow_ = null; - onChanged(); - } - } else { - if (flowCase_ == 3) { - flowCase_ = 0; - flow_ = null; - } - implicitBuilder_.clear(); - } - return this; - } - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - */ - public io.a2a.grpc.ImplicitOAuthFlow.Builder getImplicitBuilder() { - return internalGetImplicitFieldBuilder().getBuilder(); - } - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - */ - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() { - if ((flowCase_ == 3) && (implicitBuilder_ != null)) { - return implicitBuilder_.getMessageOrBuilder(); - } else { - if (flowCase_ == 3) { - return (io.a2a.grpc.ImplicitOAuthFlow) flow_; - } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - } - /** - *
    -     * Configuration for the OAuth Implicit flow.
    -     * 
    - * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> - internalGetImplicitFieldBuilder() { - if (implicitBuilder_ == null) { - if (!(flowCase_ == 3)) { - flow_ = io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - implicitBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder>( - (io.a2a.grpc.ImplicitOAuthFlow) flow_, - getParentForChildren(), - isClean()); - flow_ = null; - } - flowCase_ = 3; - onChanged(); - return implicitBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> passwordBuilder_; + io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder> deviceCodeBuilder_; /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; - * @return Whether the password field is set. + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * @return Whether the deviceCode field is set. */ @java.lang.Override - public boolean hasPassword() { - return flowCase_ == 4; + public boolean hasDeviceCode() { + return flowCase_ == 5; } /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; - * @return The password. + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * @return The deviceCode. */ @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow getPassword() { - if (passwordBuilder_ == null) { - if (flowCase_ == 4) { - return (io.a2a.grpc.PasswordOAuthFlow) flow_; + public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() { + if (deviceCodeBuilder_ == null) { + if (flowCase_ == 5) { + return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_; } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); + return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); } else { - if (flowCase_ == 4) { - return passwordBuilder_.getMessage(); + if (flowCase_ == 5) { + return deviceCodeBuilder_.getMessage(); } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); + return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); } } /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ - public Builder setPassword(io.a2a.grpc.PasswordOAuthFlow value) { - if (passwordBuilder_ == null) { + public Builder setDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) { + if (deviceCodeBuilder_ == null) { if (value == null) { throw new NullPointerException(); } flow_ = value; onChanged(); } else { - passwordBuilder_.setMessage(value); + deviceCodeBuilder_.setMessage(value); } - flowCase_ = 4; + flowCase_ = 5; return this; } /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ - public Builder setPassword( - io.a2a.grpc.PasswordOAuthFlow.Builder builderForValue) { - if (passwordBuilder_ == null) { + public Builder setDeviceCode( + io.a2a.grpc.DeviceCodeOAuthFlow.Builder builderForValue) { + if (deviceCodeBuilder_ == null) { flow_ = builderForValue.build(); onChanged(); } else { - passwordBuilder_.setMessage(builderForValue.build()); + deviceCodeBuilder_.setMessage(builderForValue.build()); } - flowCase_ = 4; + flowCase_ = 5; return this; } /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ - public Builder mergePassword(io.a2a.grpc.PasswordOAuthFlow value) { - if (passwordBuilder_ == null) { - if (flowCase_ == 4 && - flow_ != io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance()) { - flow_ = io.a2a.grpc.PasswordOAuthFlow.newBuilder((io.a2a.grpc.PasswordOAuthFlow) flow_) + public Builder mergeDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) { + if (deviceCodeBuilder_ == null) { + if (flowCase_ == 5 && + flow_ != io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance()) { + flow_ = io.a2a.grpc.DeviceCodeOAuthFlow.newBuilder((io.a2a.grpc.DeviceCodeOAuthFlow) flow_) .mergeFrom(value).buildPartial(); } else { flow_ = value; } onChanged(); } else { - if (flowCase_ == 4) { - passwordBuilder_.mergeFrom(value); + if (flowCase_ == 5) { + deviceCodeBuilder_.mergeFrom(value); } else { - passwordBuilder_.setMessage(value); + deviceCodeBuilder_.setMessage(value); } } - flowCase_ = 4; + flowCase_ = 5; return this; } /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ - public Builder clearPassword() { - if (passwordBuilder_ == null) { - if (flowCase_ == 4) { + public Builder clearDeviceCode() { + if (deviceCodeBuilder_ == null) { + if (flowCase_ == 5) { flowCase_ = 0; flow_ = null; onChanged(); } } else { - if (flowCase_ == 4) { + if (flowCase_ == 5) { flowCase_ = 0; flow_ = null; } - passwordBuilder_.clear(); + deviceCodeBuilder_.clear(); } return this; } /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ - public io.a2a.grpc.PasswordOAuthFlow.Builder getPasswordBuilder() { - return internalGetPasswordFieldBuilder().getBuilder(); + public io.a2a.grpc.DeviceCodeOAuthFlow.Builder getDeviceCodeBuilder() { + return internalGetDeviceCodeFieldBuilder().getBuilder(); } /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() { - if ((flowCase_ == 4) && (passwordBuilder_ != null)) { - return passwordBuilder_.getMessageOrBuilder(); + public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() { + if ((flowCase_ == 5) && (deviceCodeBuilder_ != null)) { + return deviceCodeBuilder_.getMessageOrBuilder(); } else { - if (flowCase_ == 4) { - return (io.a2a.grpc.PasswordOAuthFlow) flow_; + if (flowCase_ == 5) { + return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_; } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); + return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); } } /** *
    -     * Configuration for the OAuth Resource Owner Password flow.
    +     * Configuration for the OAuth Device Code flow.
          * 
    * - * .a2a.v1.PasswordOAuthFlow password = 4; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> - internalGetPasswordFieldBuilder() { - if (passwordBuilder_ == null) { - if (!(flowCase_ == 4)) { - flow_ = io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); + io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder> + internalGetDeviceCodeFieldBuilder() { + if (deviceCodeBuilder_ == null) { + if (!(flowCase_ == 5)) { + flow_ = io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); } - passwordBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder>( - (io.a2a.grpc.PasswordOAuthFlow) flow_, + deviceCodeBuilder_ = new com.google.protobuf.SingleFieldBuilder< + io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder>( + (io.a2a.grpc.DeviceCodeOAuthFlow) flow_, getParentForChildren(), isClean()); flow_ = null; } - flowCase_ = 4; + flowCase_ = 5; onChanged(); - return passwordBuilder_; + return deviceCodeBuilder_; } // @@protoc_insertion_point(builder_scope:a2a.v1.OAuthFlows) diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java index 1bdc0f5e0..cb84fa83e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java @@ -66,57 +66,30 @@ public interface OAuthFlowsOrBuilder extends /** *
    -   * Configuration for the OAuth Implicit flow.
    +   * Configuration for the OAuth Device Code flow.
        * 
    * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - * @return Whether the implicit field is set. + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * @return Whether the deviceCode field is set. */ - boolean hasImplicit(); + boolean hasDeviceCode(); /** *
    -   * Configuration for the OAuth Implicit flow.
    +   * Configuration for the OAuth Device Code flow.
        * 
    * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; - * @return The implicit. + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * @return The deviceCode. */ - io.a2a.grpc.ImplicitOAuthFlow getImplicit(); + io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode(); /** *
    -   * Configuration for the OAuth Implicit flow.
    +   * Configuration for the OAuth Device Code flow.
        * 
    * - * .a2a.v1.ImplicitOAuthFlow implicit = 3; + * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ - io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder(); - - /** - *
    -   * Configuration for the OAuth Resource Owner Password flow.
    -   * 
    - * - * .a2a.v1.PasswordOAuthFlow password = 4; - * @return Whether the password field is set. - */ - boolean hasPassword(); - /** - *
    -   * Configuration for the OAuth Resource Owner Password flow.
    -   * 
    - * - * .a2a.v1.PasswordOAuthFlow password = 4; - * @return The password. - */ - io.a2a.grpc.PasswordOAuthFlow getPassword(); - /** - *
    -   * Configuration for the OAuth Resource Owner Password flow.
    -   * 
    - * - * .a2a.v1.PasswordOAuthFlow password = 4; - */ - io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder(); + io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder(); io.a2a.grpc.OAuthFlows.FlowCase getFlowCase(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java index 457c55b1f..6bec1fb51 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java @@ -146,7 +146,10 @@ public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBu private int historyLength_ = 0; /** *
    -   * The maximum number of messages to include in the history.
    +   * The maximum number of most recent messages from the task's history to retrieve in
    +   * the response. An unset value means the client does not impose any limit. A
    +   * value of zero is a request to not include any messages. The server MUST NOT
    +   * return more messages than the provided value, but MAY apply a lower limit.
        * 
    * * optional int32 history_length = 3; @@ -158,7 +161,10 @@ public boolean hasHistoryLength() { } /** *
    -   * The maximum number of messages to include in the history.
    +   * The maximum number of most recent messages from the task's history to retrieve in
    +   * the response. An unset value means the client does not impose any limit. A
    +   * value of zero is a request to not include any messages. The server MUST NOT
    +   * return more messages than the provided value, but MAY apply a lower limit.
        * 
    * * optional int32 history_length = 3; @@ -903,7 +909,10 @@ public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBu private int historyLength_ ; /** *
    -     * The maximum number of messages to include in the history.
    +     * The maximum number of most recent messages from the task's history to retrieve in
    +     * the response. An unset value means the client does not impose any limit. A
    +     * value of zero is a request to not include any messages. The server MUST NOT
    +     * return more messages than the provided value, but MAY apply a lower limit.
          * 
    * * optional int32 history_length = 3; @@ -915,7 +924,10 @@ public boolean hasHistoryLength() { } /** *
    -     * The maximum number of messages to include in the history.
    +     * The maximum number of most recent messages from the task's history to retrieve in
    +     * the response. An unset value means the client does not impose any limit. A
    +     * value of zero is a request to not include any messages. The server MUST NOT
    +     * return more messages than the provided value, but MAY apply a lower limit.
          * 
    * * optional int32 history_length = 3; @@ -927,7 +939,10 @@ public int getHistoryLength() { } /** *
    -     * The maximum number of messages to include in the history.
    +     * The maximum number of most recent messages from the task's history to retrieve in
    +     * the response. An unset value means the client does not impose any limit. A
    +     * value of zero is a request to not include any messages. The server MUST NOT
    +     * return more messages than the provided value, but MAY apply a lower limit.
          * 
    * * optional int32 history_length = 3; @@ -943,7 +958,10 @@ public Builder setHistoryLength(int value) { } /** *
    -     * The maximum number of messages to include in the history.
    +     * The maximum number of most recent messages from the task's history to retrieve in
    +     * the response. An unset value means the client does not impose any limit. A
    +     * value of zero is a request to not include any messages. The server MUST NOT
    +     * return more messages than the provided value, but MAY apply a lower limit.
          * 
    * * optional int32 history_length = 3; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java index cfbab940c..2fed6a6af 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java @@ -80,7 +80,10 @@ public interface SendMessageConfigurationOrBuilder extends /** *
    -   * The maximum number of messages to include in the history.
    +   * The maximum number of most recent messages from the task's history to retrieve in
    +   * the response. An unset value means the client does not impose any limit. A
    +   * value of zero is a request to not include any messages. The server MUST NOT
    +   * return more messages than the provided value, but MAY apply a lower limit.
        * 
    * * optional int32 history_length = 3; @@ -89,7 +92,10 @@ public interface SendMessageConfigurationOrBuilder extends boolean hasHistoryLength(); /** *
    -   * The maximum number of messages to include in the history.
    +   * The maximum number of most recent messages from the task's history to retrieve in
    +   * the response. An unset value means the client does not impose any limit. A
    +   * value of zero is a request to not include any messages. The server MUST NOT
    +   * return more messages than the provided value, but MAY apply a lower limit.
        * 
    * * optional int32 history_length = 3; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java index 41ba38002..caaf9740e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java @@ -98,18 +98,18 @@ public java.lang.String getTenant() { } } - public static final int REQUEST_FIELD_NUMBER = 1; - private io.a2a.grpc.Message request_; + public static final int MESSAGE_FIELD_NUMBER = 1; + private io.a2a.grpc.Message message_; /** *
        * The message to send to the agent.
        * 
    * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; - * @return Whether the request field is set. + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return Whether the message field is set. */ @java.lang.Override - public boolean hasRequest() { + public boolean hasMessage() { return ((bitField0_ & 0x00000001) != 0); } /** @@ -117,23 +117,23 @@ public boolean hasRequest() { * The message to send to the agent. *
    * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; - * @return The request. + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The message. */ @java.lang.Override - public io.a2a.grpc.Message getRequest() { - return request_ == null ? io.a2a.grpc.Message.getDefaultInstance() : request_; + public io.a2a.grpc.Message getMessage() { + return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; } /** *
        * The message to send to the agent.
        * 
    * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getRequestOrBuilder() { - return request_ == null ? io.a2a.grpc.Message.getDefaultInstance() : request_; + public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { + return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; } public static final int CONFIGURATION_FIELD_NUMBER = 2; @@ -227,7 +227,7 @@ public final boolean isInitialized() { public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(1, getRequest()); + output.writeMessage(1, getMessage()); } if (((bitField0_ & 0x00000002) != 0)) { output.writeMessage(2, getConfiguration()); @@ -249,7 +249,7 @@ public int getSerializedSize() { size = 0; if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, getRequest()); + .computeMessageSize(1, getMessage()); } if (((bitField0_ & 0x00000002) != 0)) { size += com.google.protobuf.CodedOutputStream @@ -279,10 +279,10 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (hasRequest() != other.hasRequest()) return false; - if (hasRequest()) { - if (!getRequest() - .equals(other.getRequest())) return false; + if (hasMessage() != other.hasMessage()) return false; + if (hasMessage()) { + if (!getMessage() + .equals(other.getMessage())) return false; } if (hasConfiguration() != other.hasConfiguration()) return false; if (hasConfiguration()) { @@ -307,9 +307,9 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - if (hasRequest()) { - hash = (37 * hash) + REQUEST_FIELD_NUMBER; - hash = (53 * hash) + getRequest().hashCode(); + if (hasMessage()) { + hash = (37 * hash) + MESSAGE_FIELD_NUMBER; + hash = (53 * hash) + getMessage().hashCode(); } if (hasConfiguration()) { hash = (37 * hash) + CONFIGURATION_FIELD_NUMBER; @@ -455,7 +455,7 @@ private Builder( private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessage .alwaysUseFieldBuilders) { - internalGetRequestFieldBuilder(); + internalGetMessageFieldBuilder(); internalGetConfigurationFieldBuilder(); internalGetMetadataFieldBuilder(); } @@ -465,10 +465,10 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - request_ = null; - if (requestBuilder_ != null) { - requestBuilder_.dispose(); - requestBuilder_ = null; + message_ = null; + if (messageBuilder_ != null) { + messageBuilder_.dispose(); + messageBuilder_ = null; } configuration_ = null; if (configurationBuilder_ != null) { @@ -518,9 +518,9 @@ private void buildPartial0(io.a2a.grpc.SendMessageRequest result) { } int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000002) != 0)) { - result.request_ = requestBuilder_ == null - ? request_ - : requestBuilder_.build(); + result.message_ = messageBuilder_ == null + ? message_ + : messageBuilder_.build(); to_bitField0_ |= 0x00000001; } if (((from_bitField0_ & 0x00000004) != 0)) { @@ -555,8 +555,8 @@ public Builder mergeFrom(io.a2a.grpc.SendMessageRequest other) { bitField0_ |= 0x00000001; onChanged(); } - if (other.hasRequest()) { - mergeRequest(other.getRequest()); + if (other.hasMessage()) { + mergeMessage(other.getMessage()); } if (other.hasConfiguration()) { mergeConfiguration(other.getConfiguration()); @@ -592,7 +592,7 @@ public Builder mergeFrom( break; case 10: { input.readMessage( - internalGetRequestFieldBuilder().getBuilder(), + internalGetMessageFieldBuilder().getBuilder(), extensionRegistry); bitField0_ |= 0x00000002; break; @@ -725,18 +725,18 @@ public Builder setTenantBytes( return this; } - private io.a2a.grpc.Message request_; + private io.a2a.grpc.Message message_; private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> requestBuilder_; + io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_; /** *
          * The message to send to the agent.
          * 
    * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; - * @return Whether the request field is set. + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return Whether the message field is set. */ - public boolean hasRequest() { + public boolean hasMessage() { return ((bitField0_ & 0x00000002) != 0); } /** @@ -744,14 +744,14 @@ public boolean hasRequest() { * The message to send to the agent. *
    * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; - * @return The request. + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The message. */ - public io.a2a.grpc.Message getRequest() { - if (requestBuilder_ == null) { - return request_ == null ? io.a2a.grpc.Message.getDefaultInstance() : request_; + public io.a2a.grpc.Message getMessage() { + if (messageBuilder_ == null) { + return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; } else { - return requestBuilder_.getMessage(); + return messageBuilder_.getMessage(); } } /** @@ -759,16 +759,16 @@ public io.a2a.grpc.Message getRequest() { * The message to send to the agent. * * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ - public Builder setRequest(io.a2a.grpc.Message value) { - if (requestBuilder_ == null) { + public Builder setMessage(io.a2a.grpc.Message value) { + if (messageBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - request_ = value; + message_ = value; } else { - requestBuilder_.setMessage(value); + messageBuilder_.setMessage(value); } bitField0_ |= 0x00000002; onChanged(); @@ -779,14 +779,14 @@ public Builder setRequest(io.a2a.grpc.Message value) { * The message to send to the agent. * * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ - public Builder setRequest( + public Builder setMessage( io.a2a.grpc.Message.Builder builderForValue) { - if (requestBuilder_ == null) { - request_ = builderForValue.build(); + if (messageBuilder_ == null) { + message_ = builderForValue.build(); } else { - requestBuilder_.setMessage(builderForValue.build()); + messageBuilder_.setMessage(builderForValue.build()); } bitField0_ |= 0x00000002; onChanged(); @@ -797,21 +797,21 @@ public Builder setRequest( * The message to send to the agent. * * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ - public Builder mergeRequest(io.a2a.grpc.Message value) { - if (requestBuilder_ == null) { + public Builder mergeMessage(io.a2a.grpc.Message value) { + if (messageBuilder_ == null) { if (((bitField0_ & 0x00000002) != 0) && - request_ != null && - request_ != io.a2a.grpc.Message.getDefaultInstance()) { - getRequestBuilder().mergeFrom(value); + message_ != null && + message_ != io.a2a.grpc.Message.getDefaultInstance()) { + getMessageBuilder().mergeFrom(value); } else { - request_ = value; + message_ = value; } } else { - requestBuilder_.mergeFrom(value); + messageBuilder_.mergeFrom(value); } - if (request_ != null) { + if (message_ != null) { bitField0_ |= 0x00000002; onChanged(); } @@ -822,14 +822,14 @@ public Builder mergeRequest(io.a2a.grpc.Message value) { * The message to send to the agent. * * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ - public Builder clearRequest() { + public Builder clearMessage() { bitField0_ = (bitField0_ & ~0x00000002); - request_ = null; - if (requestBuilder_ != null) { - requestBuilder_.dispose(); - requestBuilder_ = null; + message_ = null; + if (messageBuilder_ != null) { + messageBuilder_.dispose(); + messageBuilder_ = null; } onChanged(); return this; @@ -839,26 +839,26 @@ public Builder clearRequest() { * The message to send to the agent. * * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ - public io.a2a.grpc.Message.Builder getRequestBuilder() { + public io.a2a.grpc.Message.Builder getMessageBuilder() { bitField0_ |= 0x00000002; onChanged(); - return internalGetRequestFieldBuilder().getBuilder(); + return internalGetMessageFieldBuilder().getBuilder(); } /** *
          * The message to send to the agent.
          * 
    * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ - public io.a2a.grpc.MessageOrBuilder getRequestOrBuilder() { - if (requestBuilder_ != null) { - return requestBuilder_.getMessageOrBuilder(); + public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { + if (messageBuilder_ != null) { + return messageBuilder_.getMessageOrBuilder(); } else { - return request_ == null ? - io.a2a.grpc.Message.getDefaultInstance() : request_; + return message_ == null ? + io.a2a.grpc.Message.getDefaultInstance() : message_; } } /** @@ -866,20 +866,20 @@ public io.a2a.grpc.MessageOrBuilder getRequestOrBuilder() { * The message to send to the agent. * * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> - internalGetRequestFieldBuilder() { - if (requestBuilder_ == null) { - requestBuilder_ = new com.google.protobuf.SingleFieldBuilder< + internalGetMessageFieldBuilder() { + if (messageBuilder_ == null) { + messageBuilder_ = new com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>( - getRequest(), + getMessage(), getParentForChildren(), isClean()); - request_ = null; + message_ = null; } - return requestBuilder_; + return messageBuilder_; } private io.a2a.grpc.SendMessageConfiguration configuration_; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java index 5040d6562..de2e6cc12 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java @@ -35,27 +35,27 @@ public interface SendMessageRequestOrBuilder extends * The message to send to the agent. * * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; - * @return Whether the request field is set. + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return Whether the message field is set. */ - boolean hasRequest(); + boolean hasMessage(); /** *
        * The message to send to the agent.
        * 
    * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; - * @return The request. + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The message. */ - io.a2a.grpc.Message getRequest(); + io.a2a.grpc.Message getMessage(); /** *
        * The message to send to the agent.
        * 
    * - * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; */ - io.a2a.grpc.MessageOrBuilder getRequestOrBuilder(); + io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); /** *
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java
    index 0fe457f59..466f2206a 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java
    @@ -55,7 +55,7 @@ public enum PayloadCase
           implements com.google.protobuf.Internal.EnumLite,
               com.google.protobuf.AbstractMessage.InternalOneOfEnum {
         TASK(1),
    -    MSG(2),
    +    MESSAGE(2),
         PAYLOAD_NOT_SET(0);
         private final int value;
         private PayloadCase(int value) {
    @@ -74,7 +74,7 @@ public static PayloadCase valueOf(int value) {
         public static PayloadCase forNumber(int value) {
           switch (value) {
             case 1: return TASK;
    -        case 2: return MSG;
    +        case 2: return MESSAGE;
             case 0: return PAYLOAD_NOT_SET;
             default: return null;
           }
    @@ -121,31 +121,31 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
         return io.a2a.grpc.Task.getDefaultInstance();
       }
     
    -  public static final int MSG_FIELD_NUMBER = 2;
    +  public static final int MESSAGE_FIELD_NUMBER = 2;
       /**
    -   * .a2a.v1.Message msg = 2 [json_name = "message"];
    -   * @return Whether the msg field is set.
    +   * .a2a.v1.Message message = 2;
    +   * @return Whether the message field is set.
        */
       @java.lang.Override
    -  public boolean hasMsg() {
    +  public boolean hasMessage() {
         return payloadCase_ == 2;
       }
       /**
    -   * .a2a.v1.Message msg = 2 [json_name = "message"];
    -   * @return The msg.
    +   * .a2a.v1.Message message = 2;
    +   * @return The message.
        */
       @java.lang.Override
    -  public io.a2a.grpc.Message getMsg() {
    +  public io.a2a.grpc.Message getMessage() {
         if (payloadCase_ == 2) {
            return (io.a2a.grpc.Message) payload_;
         }
         return io.a2a.grpc.Message.getDefaultInstance();
       }
       /**
    -   * .a2a.v1.Message msg = 2 [json_name = "message"];
    +   * .a2a.v1.Message message = 2;
        */
       @java.lang.Override
    -  public io.a2a.grpc.MessageOrBuilder getMsgOrBuilder() {
    +  public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
         if (payloadCase_ == 2) {
            return (io.a2a.grpc.Message) payload_;
         }
    @@ -211,8 +211,8 @@ public boolean equals(final java.lang.Object obj) {
                 .equals(other.getTask())) return false;
             break;
           case 2:
    -        if (!getMsg()
    -            .equals(other.getMsg())) return false;
    +        if (!getMessage()
    +            .equals(other.getMessage())) return false;
             break;
           case 0:
           default:
    @@ -234,8 +234,8 @@ public int hashCode() {
             hash = (53 * hash) + getTask().hashCode();
             break;
           case 2:
    -        hash = (37 * hash) + MSG_FIELD_NUMBER;
    -        hash = (53 * hash) + getMsg().hashCode();
    +        hash = (37 * hash) + MESSAGE_FIELD_NUMBER;
    +        hash = (53 * hash) + getMessage().hashCode();
             break;
           case 0:
           default:
    @@ -379,8 +379,8 @@ public Builder clear() {
           if (taskBuilder_ != null) {
             taskBuilder_.clear();
           }
    -      if (msgBuilder_ != null) {
    -        msgBuilder_.clear();
    +      if (messageBuilder_ != null) {
    +        messageBuilder_.clear();
           }
           payloadCase_ = 0;
           payload_ = null;
    @@ -428,8 +428,8 @@ private void buildPartialOneofs(io.a2a.grpc.SendMessageResponse result) {
             result.payload_ = taskBuilder_.build();
           }
           if (payloadCase_ == 2 &&
    -          msgBuilder_ != null) {
    -        result.payload_ = msgBuilder_.build();
    +          messageBuilder_ != null) {
    +        result.payload_ = messageBuilder_.build();
           }
         }
     
    @@ -450,8 +450,8 @@ public Builder mergeFrom(io.a2a.grpc.SendMessageResponse other) {
               mergeTask(other.getTask());
               break;
             }
    -        case MSG: {
    -          mergeMsg(other.getMsg());
    +        case MESSAGE: {
    +          mergeMessage(other.getMessage());
               break;
             }
             case PAYLOAD_NOT_SET: {
    @@ -493,7 +493,7 @@ public Builder mergeFrom(
                 } // case 10
                 case 18: {
                   input.readMessage(
    -                  internalGetMsgFieldBuilder().getBuilder(),
    +                  internalGetMessageFieldBuilder().getBuilder(),
                       extensionRegistry);
                   payloadCase_ = 2;
                   break;
    @@ -673,68 +673,68 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
         }
     
         private com.google.protobuf.SingleFieldBuilder<
    -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> msgBuilder_;
    +        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_;
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    -     * @return Whether the msg field is set.
    +     * .a2a.v1.Message message = 2;
    +     * @return Whether the message field is set.
          */
         @java.lang.Override
    -    public boolean hasMsg() {
    +    public boolean hasMessage() {
           return payloadCase_ == 2;
         }
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    -     * @return The msg.
    +     * .a2a.v1.Message message = 2;
    +     * @return The message.
          */
         @java.lang.Override
    -    public io.a2a.grpc.Message getMsg() {
    -      if (msgBuilder_ == null) {
    +    public io.a2a.grpc.Message getMessage() {
    +      if (messageBuilder_ == null) {
             if (payloadCase_ == 2) {
               return (io.a2a.grpc.Message) payload_;
             }
             return io.a2a.grpc.Message.getDefaultInstance();
           } else {
             if (payloadCase_ == 2) {
    -          return msgBuilder_.getMessage();
    +          return messageBuilder_.getMessage();
             }
             return io.a2a.grpc.Message.getDefaultInstance();
           }
         }
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    +     * .a2a.v1.Message message = 2;
          */
    -    public Builder setMsg(io.a2a.grpc.Message value) {
    -      if (msgBuilder_ == null) {
    +    public Builder setMessage(io.a2a.grpc.Message value) {
    +      if (messageBuilder_ == null) {
             if (value == null) {
               throw new NullPointerException();
             }
             payload_ = value;
             onChanged();
           } else {
    -        msgBuilder_.setMessage(value);
    +        messageBuilder_.setMessage(value);
           }
           payloadCase_ = 2;
           return this;
         }
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    +     * .a2a.v1.Message message = 2;
          */
    -    public Builder setMsg(
    +    public Builder setMessage(
             io.a2a.grpc.Message.Builder builderForValue) {
    -      if (msgBuilder_ == null) {
    +      if (messageBuilder_ == null) {
             payload_ = builderForValue.build();
             onChanged();
           } else {
    -        msgBuilder_.setMessage(builderForValue.build());
    +        messageBuilder_.setMessage(builderForValue.build());
           }
           payloadCase_ = 2;
           return this;
         }
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    +     * .a2a.v1.Message message = 2;
          */
    -    public Builder mergeMsg(io.a2a.grpc.Message value) {
    -      if (msgBuilder_ == null) {
    +    public Builder mergeMessage(io.a2a.grpc.Message value) {
    +      if (messageBuilder_ == null) {
             if (payloadCase_ == 2 &&
                 payload_ != io.a2a.grpc.Message.getDefaultInstance()) {
               payload_ = io.a2a.grpc.Message.newBuilder((io.a2a.grpc.Message) payload_)
    @@ -745,19 +745,19 @@ public Builder mergeMsg(io.a2a.grpc.Message value) {
             onChanged();
           } else {
             if (payloadCase_ == 2) {
    -          msgBuilder_.mergeFrom(value);
    +          messageBuilder_.mergeFrom(value);
             } else {
    -          msgBuilder_.setMessage(value);
    +          messageBuilder_.setMessage(value);
             }
           }
           payloadCase_ = 2;
           return this;
         }
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    +     * .a2a.v1.Message message = 2;
          */
    -    public Builder clearMsg() {
    -      if (msgBuilder_ == null) {
    +    public Builder clearMessage() {
    +      if (messageBuilder_ == null) {
             if (payloadCase_ == 2) {
               payloadCase_ = 0;
               payload_ = null;
    @@ -768,23 +768,23 @@ public Builder clearMsg() {
               payloadCase_ = 0;
               payload_ = null;
             }
    -        msgBuilder_.clear();
    +        messageBuilder_.clear();
           }
           return this;
         }
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    +     * .a2a.v1.Message message = 2;
          */
    -    public io.a2a.grpc.Message.Builder getMsgBuilder() {
    -      return internalGetMsgFieldBuilder().getBuilder();
    +    public io.a2a.grpc.Message.Builder getMessageBuilder() {
    +      return internalGetMessageFieldBuilder().getBuilder();
         }
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    +     * .a2a.v1.Message message = 2;
          */
         @java.lang.Override
    -    public io.a2a.grpc.MessageOrBuilder getMsgOrBuilder() {
    -      if ((payloadCase_ == 2) && (msgBuilder_ != null)) {
    -        return msgBuilder_.getMessageOrBuilder();
    +    public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
    +      if ((payloadCase_ == 2) && (messageBuilder_ != null)) {
    +        return messageBuilder_.getMessageOrBuilder();
           } else {
             if (payloadCase_ == 2) {
               return (io.a2a.grpc.Message) payload_;
    @@ -793,16 +793,16 @@ public io.a2a.grpc.MessageOrBuilder getMsgOrBuilder() {
           }
         }
         /**
    -     * .a2a.v1.Message msg = 2 [json_name = "message"];
    +     * .a2a.v1.Message message = 2;
          */
         private com.google.protobuf.SingleFieldBuilder<
             io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> 
    -        internalGetMsgFieldBuilder() {
    -      if (msgBuilder_ == null) {
    +        internalGetMessageFieldBuilder() {
    +      if (messageBuilder_ == null) {
             if (!(payloadCase_ == 2)) {
               payload_ = io.a2a.grpc.Message.getDefaultInstance();
             }
    -        msgBuilder_ = new com.google.protobuf.SingleFieldBuilder<
    +        messageBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                 io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>(
                     (io.a2a.grpc.Message) payload_,
                     getParentForChildren(),
    @@ -811,7 +811,7 @@ public io.a2a.grpc.MessageOrBuilder getMsgOrBuilder() {
           }
           payloadCase_ = 2;
           onChanged();
    -      return msgBuilder_;
    +      return messageBuilder_;
         }
     
         // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageResponse)
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java
    index 40a838920..355131b71 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java
    @@ -26,19 +26,19 @@ public interface SendMessageResponseOrBuilder extends
       io.a2a.grpc.TaskOrBuilder getTaskOrBuilder();
     
       /**
    -   * .a2a.v1.Message msg = 2 [json_name = "message"];
    -   * @return Whether the msg field is set.
    +   * .a2a.v1.Message message = 2;
    +   * @return Whether the message field is set.
        */
    -  boolean hasMsg();
    +  boolean hasMessage();
       /**
    -   * .a2a.v1.Message msg = 2 [json_name = "message"];
    -   * @return The msg.
    +   * .a2a.v1.Message message = 2;
    +   * @return The message.
        */
    -  io.a2a.grpc.Message getMsg();
    +  io.a2a.grpc.Message getMessage();
       /**
    -   * .a2a.v1.Message msg = 2 [json_name = "message"];
    +   * .a2a.v1.Message message = 2;
        */
    -  io.a2a.grpc.MessageOrBuilder getMsgOrBuilder();
    +  io.a2a.grpc.MessageOrBuilder getMessageOrBuilder();
     
       io.a2a.grpc.SendMessageResponse.PayloadCase getPayloadCase();
     }
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java
    index 139650483..3d27db5ef 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java
    @@ -55,7 +55,7 @@ public enum PayloadCase
           implements com.google.protobuf.Internal.EnumLite,
               com.google.protobuf.AbstractMessage.InternalOneOfEnum {
         TASK(1),
    -    MSG(2),
    +    MESSAGE(2),
         STATUS_UPDATE(3),
         ARTIFACT_UPDATE(4),
         PAYLOAD_NOT_SET(0);
    @@ -76,7 +76,7 @@ public static PayloadCase valueOf(int value) {
         public static PayloadCase forNumber(int value) {
           switch (value) {
             case 1: return TASK;
    -        case 2: return MSG;
    +        case 2: return MESSAGE;
             case 3: return STATUS_UPDATE;
             case 4: return ARTIFACT_UPDATE;
             case 0: return PAYLOAD_NOT_SET;
    @@ -137,17 +137,17 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
         return io.a2a.grpc.Task.getDefaultInstance();
       }
     
    -  public static final int MSG_FIELD_NUMBER = 2;
    +  public static final int MESSAGE_FIELD_NUMBER = 2;
       /**
        * 
        * A Message object containing a message from the agent.
        * 
    * - * .a2a.v1.Message msg = 2 [json_name = "message"]; - * @return Whether the msg field is set. + * .a2a.v1.Message message = 2; + * @return Whether the message field is set. */ @java.lang.Override - public boolean hasMsg() { + public boolean hasMessage() { return payloadCase_ == 2; } /** @@ -155,11 +155,11 @@ public boolean hasMsg() { * A Message object containing a message from the agent. *
    * - * .a2a.v1.Message msg = 2 [json_name = "message"]; - * @return The msg. + * .a2a.v1.Message message = 2; + * @return The message. */ @java.lang.Override - public io.a2a.grpc.Message getMsg() { + public io.a2a.grpc.Message getMessage() { if (payloadCase_ == 2) { return (io.a2a.grpc.Message) payload_; } @@ -170,10 +170,10 @@ public io.a2a.grpc.Message getMsg() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getMsgOrBuilder() { + public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { if (payloadCase_ == 2) { return (io.a2a.grpc.Message) payload_; } @@ -339,8 +339,8 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getTask())) return false; break; case 2: - if (!getMsg() - .equals(other.getMsg())) return false; + if (!getMessage() + .equals(other.getMessage())) return false; break; case 3: if (!getStatusUpdate() @@ -370,8 +370,8 @@ public int hashCode() { hash = (53 * hash) + getTask().hashCode(); break; case 2: - hash = (37 * hash) + MSG_FIELD_NUMBER; - hash = (53 * hash) + getMsg().hashCode(); + hash = (37 * hash) + MESSAGE_FIELD_NUMBER; + hash = (53 * hash) + getMessage().hashCode(); break; case 3: hash = (37 * hash) + STATUS_UPDATE_FIELD_NUMBER; @@ -523,8 +523,8 @@ public Builder clear() { if (taskBuilder_ != null) { taskBuilder_.clear(); } - if (msgBuilder_ != null) { - msgBuilder_.clear(); + if (messageBuilder_ != null) { + messageBuilder_.clear(); } if (statusUpdateBuilder_ != null) { statusUpdateBuilder_.clear(); @@ -578,8 +578,8 @@ private void buildPartialOneofs(io.a2a.grpc.StreamResponse result) { result.payload_ = taskBuilder_.build(); } if (payloadCase_ == 2 && - msgBuilder_ != null) { - result.payload_ = msgBuilder_.build(); + messageBuilder_ != null) { + result.payload_ = messageBuilder_.build(); } if (payloadCase_ == 3 && statusUpdateBuilder_ != null) { @@ -608,8 +608,8 @@ public Builder mergeFrom(io.a2a.grpc.StreamResponse other) { mergeTask(other.getTask()); break; } - case MSG: { - mergeMsg(other.getMsg()); + case MESSAGE: { + mergeMessage(other.getMessage()); break; } case STATUS_UPDATE: { @@ -659,7 +659,7 @@ public Builder mergeFrom( } // case 10 case 18: { input.readMessage( - internalGetMsgFieldBuilder().getBuilder(), + internalGetMessageFieldBuilder().getBuilder(), extensionRegistry); payloadCase_ = 2; break; @@ -889,17 +889,17 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { } private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> msgBuilder_; + io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_; /** *
          * A Message object containing a message from the agent.
          * 
    * - * .a2a.v1.Message msg = 2 [json_name = "message"]; - * @return Whether the msg field is set. + * .a2a.v1.Message message = 2; + * @return Whether the message field is set. */ @java.lang.Override - public boolean hasMsg() { + public boolean hasMessage() { return payloadCase_ == 2; } /** @@ -907,19 +907,19 @@ public boolean hasMsg() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; - * @return The msg. + * .a2a.v1.Message message = 2; + * @return The message. */ @java.lang.Override - public io.a2a.grpc.Message getMsg() { - if (msgBuilder_ == null) { + public io.a2a.grpc.Message getMessage() { + if (messageBuilder_ == null) { if (payloadCase_ == 2) { return (io.a2a.grpc.Message) payload_; } return io.a2a.grpc.Message.getDefaultInstance(); } else { if (payloadCase_ == 2) { - return msgBuilder_.getMessage(); + return messageBuilder_.getMessage(); } return io.a2a.grpc.Message.getDefaultInstance(); } @@ -929,17 +929,17 @@ public io.a2a.grpc.Message getMsg() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ - public Builder setMsg(io.a2a.grpc.Message value) { - if (msgBuilder_ == null) { + public Builder setMessage(io.a2a.grpc.Message value) { + if (messageBuilder_ == null) { if (value == null) { throw new NullPointerException(); } payload_ = value; onChanged(); } else { - msgBuilder_.setMessage(value); + messageBuilder_.setMessage(value); } payloadCase_ = 2; return this; @@ -949,15 +949,15 @@ public Builder setMsg(io.a2a.grpc.Message value) { * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ - public Builder setMsg( + public Builder setMessage( io.a2a.grpc.Message.Builder builderForValue) { - if (msgBuilder_ == null) { + if (messageBuilder_ == null) { payload_ = builderForValue.build(); onChanged(); } else { - msgBuilder_.setMessage(builderForValue.build()); + messageBuilder_.setMessage(builderForValue.build()); } payloadCase_ = 2; return this; @@ -967,10 +967,10 @@ public Builder setMsg( * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ - public Builder mergeMsg(io.a2a.grpc.Message value) { - if (msgBuilder_ == null) { + public Builder mergeMessage(io.a2a.grpc.Message value) { + if (messageBuilder_ == null) { if (payloadCase_ == 2 && payload_ != io.a2a.grpc.Message.getDefaultInstance()) { payload_ = io.a2a.grpc.Message.newBuilder((io.a2a.grpc.Message) payload_) @@ -981,9 +981,9 @@ public Builder mergeMsg(io.a2a.grpc.Message value) { onChanged(); } else { if (payloadCase_ == 2) { - msgBuilder_.mergeFrom(value); + messageBuilder_.mergeFrom(value); } else { - msgBuilder_.setMessage(value); + messageBuilder_.setMessage(value); } } payloadCase_ = 2; @@ -994,10 +994,10 @@ public Builder mergeMsg(io.a2a.grpc.Message value) { * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ - public Builder clearMsg() { - if (msgBuilder_ == null) { + public Builder clearMessage() { + if (messageBuilder_ == null) { if (payloadCase_ == 2) { payloadCase_ = 0; payload_ = null; @@ -1008,7 +1008,7 @@ public Builder clearMsg() { payloadCase_ = 0; payload_ = null; } - msgBuilder_.clear(); + messageBuilder_.clear(); } return this; } @@ -1017,22 +1017,22 @@ public Builder clearMsg() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ - public io.a2a.grpc.Message.Builder getMsgBuilder() { - return internalGetMsgFieldBuilder().getBuilder(); + public io.a2a.grpc.Message.Builder getMessageBuilder() { + return internalGetMessageFieldBuilder().getBuilder(); } /** *
          * A Message object containing a message from the agent.
          * 
    * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getMsgOrBuilder() { - if ((payloadCase_ == 2) && (msgBuilder_ != null)) { - return msgBuilder_.getMessageOrBuilder(); + public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { + if ((payloadCase_ == 2) && (messageBuilder_ != null)) { + return messageBuilder_.getMessageOrBuilder(); } else { if (payloadCase_ == 2) { return (io.a2a.grpc.Message) payload_; @@ -1045,16 +1045,16 @@ public io.a2a.grpc.MessageOrBuilder getMsgOrBuilder() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> - internalGetMsgFieldBuilder() { - if (msgBuilder_ == null) { + internalGetMessageFieldBuilder() { + if (messageBuilder_ == null) { if (!(payloadCase_ == 2)) { payload_ = io.a2a.grpc.Message.getDefaultInstance(); } - msgBuilder_ = new com.google.protobuf.SingleFieldBuilder< + messageBuilder_ = new com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>( (io.a2a.grpc.Message) payload_, getParentForChildren(), @@ -1063,7 +1063,7 @@ public io.a2a.grpc.MessageOrBuilder getMsgOrBuilder() { } payloadCase_ = 2; onChanged(); - return msgBuilder_; + return messageBuilder_; } private com.google.protobuf.SingleFieldBuilder< diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java index d6596f26d..5688ed06b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java @@ -42,27 +42,27 @@ public interface StreamResponseOrBuilder extends * A Message object containing a message from the agent. * * - * .a2a.v1.Message msg = 2 [json_name = "message"]; - * @return Whether the msg field is set. + * .a2a.v1.Message message = 2; + * @return Whether the message field is set. */ - boolean hasMsg(); + boolean hasMessage(); /** *
        * A Message object containing a message from the agent.
        * 
    * - * .a2a.v1.Message msg = 2 [json_name = "message"]; - * @return The msg. + * .a2a.v1.Message message = 2; + * @return The message. */ - io.a2a.grpc.Message getMsg(); + io.a2a.grpc.Message getMessage(); /** *
        * A Message object containing a message from the agent.
        * 
    * - * .a2a.v1.Message msg = 2 [json_name = "message"]; + * .a2a.v1.Message message = 2; */ - io.a2a.grpc.MessageOrBuilder getMsgOrBuilder(); + io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); /** *
    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 723df2e53..0acdc5d3e 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
    @@ -370,6 +370,44 @@ default Instant millisToInstant(long millis) {
             return millis > 0L ? Instant.ofEpochMilli(millis) : null;
         }
     
    +    // ========================================================================
    +    // Instant ↔ Timestamp Conversions (for Timestamp timestamp fields)
    +    // ========================================================================
    +    /**
    +     * Converts domain Instant to protobuf Timestamp.
    +     * 

    + * Use this with {@code @Mapping(qualifiedByName = "instantToProtoTimestamp")}. + * + * @param instant the domain Instant + * @return protobuf Timestamp, or default instance if input is null + */ + @Named("instantToProtoTimestamp") + default Timestamp instantToProtoTimestamp(Instant instant) { + if (instant == null) { + return Timestamp.getDefaultInstance(); + } + return Timestamp.newBuilder() + .setSeconds(instant.getEpochSecond()) + .setNanos(instant.getNano()) + .build(); + } + + /** + * Converts protobuf Timestamp to domain Instant. + *

    + * Use this with {@code @Mapping(qualifiedByName = "protoTimestampToInstant")}. + * + * @param timestamp the protobuf Timestamp + * @return Instant, or null if input is null/default + */ + @Named("protoTimestampToInstant") + default Instant protoTimestampToInstant(Timestamp timestamp) { + if (timestamp == null || timestamp.equals(Timestamp.getDefaultInstance())) { + return null; + } + return Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()); + } + // ======================================================================== // Enum Conversions (handling UNSPECIFIED/UNKNOWN) // ======================================================================== diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java index a8216fec8..337ea8de6 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java @@ -2,6 +2,7 @@ import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; /** * Mapper between {@link io.a2a.spec.AgentCapabilities} and {@link io.a2a.grpc.AgentCapabilities}. diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java index 7a27cb57d..97b9ed0a1 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java @@ -22,10 +22,6 @@ public interface AgentCardMapper { AgentCardMapper INSTANCE = A2AMappers.getMapper(AgentCardMapper.class); - // Deprecated proto fields - not present in spec API (removed in 1.0.0) - @Mapping(target = "url", ignore = true) - @Mapping(target = "preferredTransport", ignore = true) - @Mapping(target = "additionalInterfaces", ignore = true) @Mapping(target = "provider", source = "provider", conditionExpression = "java(domain.provider() != null)") @Mapping(target = "documentationUrl", source = "documentationUrl", conditionExpression = "java(domain.documentationUrl() != null)") @Mapping(target = "iconUrl", source = "iconUrl", conditionExpression = "java(domain.iconUrl() != null)") diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java index 09fdc3184..d59a3e10a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java @@ -2,6 +2,7 @@ import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; /** * Mapper between {@link io.a2a.spec.AuthorizationCodeOAuthFlow} and {@link io.a2a.grpc.AuthorizationCodeOAuthFlow}. diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ImplicitOAuthFlowMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ImplicitOAuthFlowMapper.java deleted file mode 100644 index 99f0b7854..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ImplicitOAuthFlowMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.ImplicitOAuthFlow} and {@link io.a2a.grpc.ImplicitOAuthFlow}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface ImplicitOAuthFlowMapper { - - ImplicitOAuthFlowMapper INSTANCE = A2AMappers.getMapper(ImplicitOAuthFlowMapper.class); - - io.a2a.grpc.ImplicitOAuthFlow toProto(io.a2a.spec.ImplicitOAuthFlow domain); - - io.a2a.spec.ImplicitOAuthFlow fromProto(io.a2a.grpc.ImplicitOAuthFlow proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java index cdb501d9a..06d4c2dd4 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java @@ -26,7 +26,7 @@ public interface ListTasksParamsMapper { @Mapping(target = "pageSize", source = "pageSize", conditionExpression = "java(params.pageSize() != null)") @Mapping(target = "pageToken", source = "pageToken", conditionExpression = "java(params.pageToken() != null)") @Mapping(target = "historyLength", source = "historyLength", conditionExpression = "java(params.historyLength() != null)") - @Mapping(target = "lastUpdatedAfter", source = "lastUpdatedAfter", qualifiedByName = "instantToMillis") + @Mapping(target = "statusTimestampAfter", source = "statusTimestampAfter", qualifiedByName = "instantToProtoTimestamp") @Mapping(target = "includeArtifacts", source = "includeArtifacts", conditionExpression = "java(params.includeArtifacts() != null)") ListTasksRequest toProto(io.a2a.spec.ListTasksParams params); @@ -43,7 +43,7 @@ public interface ListTasksParamsMapper { @Mapping(target = "pageToken", source = "pageToken", qualifiedByName = "emptyToNull") // historyLength: Check if field is set using hasHistoryLength() for consistency with pageSize @Mapping(target = "historyLength", expression = "java(request.hasHistoryLength() ? request.getHistoryLength() : null)") - @Mapping(target = "lastUpdatedAfter", source = "lastUpdatedAfter", qualifiedByName = "millisToInstant") + @Mapping(target = "statusTimestampAfter", source = "statusTimestampAfter", qualifiedByName = "protoTimestampToInstant") @Mapping(target = "includeArtifacts", source = "includeArtifacts", qualifiedByName = "falseToNull") io.a2a.spec.ListTasksParams fromProto(ListTasksRequest request); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java index 759fc0fef..11885ac11 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java @@ -18,20 +18,18 @@ public interface MessageSendParamsMapper { /** * Converts domain MessageSendParams to proto SendMessageRequest. - * Maps domain "message" field to proto "request" field. + * Maps domain "message" field to proto "message" field. */ - @Mapping(target = "request", source = "message") @Mapping(target = "configuration", source = "configuration", conditionExpression = "java(domain.configuration() != null)") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") io.a2a.grpc.SendMessageRequest toProto(MessageSendParams domain); /** * Converts proto SendMessageRequest to domain MessageSendParams. - * Maps proto "request" field to domain "message" field. + * Maps proto "message" field to domain "message" field. * Uses Builder pattern for record construction. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "message", source = "request") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") MessageSendParams fromProto(io.a2a.grpc.SendMessageRequest proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java index 6af0e28ce..e919b50d6 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java @@ -2,6 +2,7 @@ import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; /** * Mapper between {@link io.a2a.spec.OAuthFlows} and {@link io.a2a.grpc.OAuthFlows}. @@ -10,9 +11,7 @@ collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, uses = { AuthorizationCodeOAuthFlowMapper.class, - ClientCredentialsOAuthFlowMapper.class, - ImplicitOAuthFlowMapper.class, - PasswordOAuthFlowMapper.class + ClientCredentialsOAuthFlowMapper.class }) public interface OAuthFlowsMapper { diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PasswordOAuthFlowMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PasswordOAuthFlowMapper.java deleted file mode 100644 index 84b6e1bdf..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PasswordOAuthFlowMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.PasswordOAuthFlow} and {@link io.a2a.grpc.PasswordOAuthFlow}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface PasswordOAuthFlowMapper { - - PasswordOAuthFlowMapper INSTANCE = A2AMappers.getMapper(PasswordOAuthFlowMapper.class); - - io.a2a.grpc.PasswordOAuthFlow toProto(io.a2a.spec.PasswordOAuthFlow domain); - - io.a2a.spec.PasswordOAuthFlow fromProto(io.a2a.grpc.PasswordOAuthFlow proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java index 2b91beff0..07eacb148 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java @@ -45,7 +45,7 @@ default io.a2a.grpc.StreamResponse toProto(StreamingEventKind domain) { .setTask(TaskMapper.INSTANCE.toProto((Task) domain)) .build(); case Message.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setMsg(MessageMapper.INSTANCE.toProto((Message) domain)) + .setMessage(MessageMapper.INSTANCE.toProto((Message) domain)) .build(); case TaskStatusUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() .setStatusUpdate(TaskStatusUpdateEventMapper.INSTANCE.toProto((TaskStatusUpdateEvent) domain)) @@ -74,8 +74,8 @@ default StreamingEventKind fromProto(io.a2a.grpc.StreamResponse proto) { return switch (proto.getPayloadCase()) { case TASK -> TaskMapper.INSTANCE.fromProto(proto.getTask()); - case MSG -> - MessageMapper.INSTANCE.fromProto(proto.getMsg()); + case MESSAGE -> + MessageMapper.INSTANCE.fromProto(proto.getMessage()); case STATUS_UPDATE -> TaskStatusUpdateEventMapper.INSTANCE.fromProto(proto.getStatusUpdate()); case ARTIFACT_UPDATE -> 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 c7d1df72f..1692ae3a5 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,7 +1,7 @@ package io.a2a.grpc.utils; import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.EXTENDED_CARD_NOT_CONFIGURED_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED_ERROR; import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; @@ -48,8 +48,8 @@ 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.GetExtendedAgentCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; @@ -66,7 +66,7 @@ import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.spec.A2AError; import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedCardNotConfiguredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.InvalidAgentResponseError; import io.a2a.spec.InvalidParamsError; @@ -245,7 +245,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new DeleteTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.deleteTaskPushNotificationConfigParams(builder)); } case GET_EXTENDED_AGENT_CARD_METHOD -> { - return new GetAuthenticatedExtendedCardRequest(version, id); + return new GetExtendedAgentCardRequest(version, id); } case SEND_STREAMING_MESSAGE_METHOD -> { io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); @@ -314,8 +314,8 @@ public static A2AResponse parseResponseBody(String body, String method) throw case SEND_MESSAGE_METHOD -> { io.a2a.grpc.SendMessageResponse.Builder builder = io.a2a.grpc.SendMessageResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); - if (builder.hasMsg()) { - return new SendMessageResponse(id, ProtoUtils.FromProto.message(builder.getMsg())); + if (builder.hasMessage()) { + return new SendMessageResponse(id, ProtoUtils.FromProto.message(builder.getMessage())); } return new SendMessageResponse(id, ProtoUtils.FromProto.task(builder.getTask())); } @@ -330,7 +330,7 @@ public static A2AResponse parseResponseBody(String body, String method) throw 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)); + return new GetExtendedAgentCardResponse(id, ProtoUtils.FromProto.agentCard(builder)); } default -> throw new MethodNotFoundJsonMappingException("Unsupported JSON-RPC method: '" + method + "' in response parsing.", getIdIfPossible(jsonRpc)); @@ -393,8 +393,8 @@ private static A2AError processError(JsonObject error) { return new ContentTypeNotSupportedError(code, message, data); case INVALID_AGENT_RESPONSE_ERROR_CODE: return new InvalidAgentResponseError(code, message, data); - case EXTENDED_CARD_NOT_CONFIGURED_ERROR_CODE: - return new ExtendedCardNotConfiguredError(code, message, data); + case EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE: + return new ExtendedAgentCardNotConfiguredError(code, message, data); case EXTENSION_SUPPORT_REQUIRED_ERROR: return new ExtensionSupportRequiredError(code, message, data); case VERSION_NOT_SUPPORTED_ERROR_CODE: 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 b4e9a1755..b2941dc98 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 @@ -149,7 +149,7 @@ public static io.a2a.grpc.SendMessageResponse taskOrMessage(EventKind eventKind) .setTask(task((Task) eventKind)) .build(); case Message.STREAMING_EVENT_ID -> io.a2a.grpc.SendMessageResponse.newBuilder() - .setMsg(message((Message) eventKind)) + .setMessage(message((Message) eventKind)) .build(); default -> throw new IllegalArgumentException("Unsupported event type: " + eventKind); }; @@ -161,7 +161,7 @@ public static io.a2a.grpc.StreamResponse taskOrMessageStream(StreamingEventKind .setTask(task((Task) eventKind)) .build(); case Message.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setMsg(message((Message) eventKind)) + .setMessage(message((Message) eventKind)) .build(); case TaskStatusUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() .setStatusUpdate(taskStatusUpdateEvent((TaskStatusUpdateEvent) eventKind)) @@ -181,7 +181,7 @@ public static io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConf return taskPushNotificationConfig(config); } - public static io.a2a.grpc.AgentCard getAuthenticatedExtendedCardResponse(AgentCard card) { + public static io.a2a.grpc.AgentCard getExtendedCardResponse(AgentCard card) { return agentCard(card); } } diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto index 888fd18b8..ccf37e6ab 100644 --- a/spec-grpc/src/main/proto/a2a.proto +++ b/spec-grpc/src/main/proto/a2a.proto @@ -9,8 +9,6 @@ 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; @@ -145,7 +143,10 @@ message SendMessageConfiguration { repeated string accepted_output_modes = 1; // Configuration for the agent to send push notifications for task updates. PushNotificationConfig push_notification_config = 2; - // The maximum number of messages to include in the history. + // The maximum number of most recent messages from the task's history to retrieve in + // the response. An unset value means the client does not impose any limit. A + // value of zero is a request to not include any messages. The server MUST NOT + // return more messages than the provided value, but MAY apply a lower limit. optional int32 history_length = 3; // If true, the operation waits until the task reaches a terminal state before returning. Default is false. bool blocking = 4; @@ -277,13 +278,12 @@ enum Role { // --8<-- [end:Role] // --8<-- [start:Message] -// Message is one unit of communication between client and server. It is -// associated with a context and optionally a task. Since the server is -// responsible for the context definition, it must always provide a context_id -// in its messages. The client can optionally provide the context_id if it -// knows the context to associate the message to. Similarly for task_id, -// except the server decides if a task is created and whether to include the -// task_id. +// Message is one unit of communication between client and server. It can be +// associated with a context and/or a task. For server messages, context_id must +// be provided, and task_id only if a task was created. For client messages, both +// fields are optional, with the caveat that if both are provided, they have to +// match (the context_id has to be the one that is set on the task). If only +// task_id is provided, the server will infer context_id from it. message Message { // The unique identifier (e.g. UUID) of the message. This is required and // created by the message creator. @@ -411,9 +411,14 @@ message AgentInterface { // communication methods, and security requirements. // Next ID: 20 message AgentCard { - // The version of the A2A protocol this agent supports. - // Default: "1.0" - optional string protocol_version = 16 [(google.api.field_behavior) = REQUIRED]; + // The versions of the A2A protocol this agent supports. + // For stable versions (1.x+), list only the latest supported minor version per major version. + // For legacy experimental versions (0.x), explicitly list each supported version. + // Default: ["1.0"] + repeated string protocol_versions = 16 [(google.api.field_behavior) = REQUIRED]; + // Reserve these field numbers as they were previously used by removed + // fields. + reserved 3, 14, 15; // A human readable name for the agent. // Example: "Recipe Agent" string name = 1 [(google.api.field_behavior) = REQUIRED]; @@ -422,13 +427,7 @@ message AgentCard { // Example: "Agent that helps users with recipes and cooking." string description = 2 [(google.api.field_behavior) = REQUIRED]; // Ordered list of supported interfaces. First entry is preferred. - repeated AgentInterface supported_interfaces = 19; - // DEPRECATED: Use 'supported_interfaces' instead. - optional string url = 3 [deprecated = true]; - // DEPRECATED: Use 'supported_interfaces' instead. - optional string preferred_transport = 14 [deprecated = true]; - // DEPRECATED: Use 'supported_interfaces' instead. - repeated AgentInterface additional_interfaces = 15 [deprecated = true]; + repeated AgentInterface supported_interfaces = 19 [(google.api.field_behavior) = REQUIRED]; // The service provider of the agent. AgentProvider provider = 4; // The version of the agent. @@ -453,8 +452,6 @@ message AgentCard { // a descriptive concept but represents a more focused set of behaviors that the // agent is likely to succeed at. repeated AgentSkill skills = 12 [(google.api.field_behavior) = REQUIRED]; - // Whether the agent supports providing an extended agent card when authenticated. - optional bool supports_extended_agent_card = 13; // JSON Web Signatures computed for this AgentCard. repeated AgentCardSignature signatures = 17; // An optional URL to an icon for the agent. @@ -485,6 +482,8 @@ message AgentCapabilities { repeated AgentExtension extensions = 3; // Indicates if the agent provides a history of state transitions for a task. optional bool state_transition_history = 4; + // Indicates if the agent supports providing an extended agent card when authenticated. + optional bool extended_agent_card = 5; } // --8<-- [end:AgentCapabilities] @@ -644,15 +643,15 @@ message MutualTlsSecurityScheme { // --8<-- [start:OAuthFlows] // Defines the configuration for the supported OAuth 2.0 flows. message OAuthFlows { + // Tags 3 and 4 were previously used by deprecated OAuth flows. + reserved 3, 4; oneof flow { // Configuration for the OAuth Authorization Code flow. AuthorizationCodeOAuthFlow authorization_code = 1; // Configuration for the OAuth Client Credentials flow. ClientCredentialsOAuthFlow client_credentials = 2; - // Configuration for the OAuth Implicit flow. - ImplicitOAuthFlow implicit = 3; - // Configuration for the OAuth Resource Owner Password flow. - PasswordOAuthFlow password = 4; + // Configuration for the OAuth Device Code flow. + DeviceCodeOAuthFlow device_code = 5; } } // --8<-- [end:OAuthFlows] @@ -668,6 +667,9 @@ message AuthorizationCodeOAuthFlow { string refresh_url = 3; // The available scopes for the OAuth2 security scheme. map scopes = 4 [(google.api.field_behavior) = REQUIRED]; + // Indicates if PKCE (RFC 7636) is required for this flow. + // PKCE should always be used for public clients and is recommended for all clients. + bool pkce_required = 5; } // --8<-- [end:AuthorizationCodeOAuthFlow] @@ -683,29 +685,21 @@ message ClientCredentialsOAuthFlow { } // --8<-- [end:ClientCredentialsOAuthFlow] -// --8<-- [start:ImplicitOAuthFlow] -// Defines configuration details for the OAuth 2.0 Implicit flow. -message ImplicitOAuthFlow { - // The authorization URL to be used for this flow. - string authorization_url = 1 [(google.api.field_behavior) = REQUIRED]; - // The URL to be used for obtaining refresh tokens. - string refresh_url = 2; - // The available scopes for the OAuth2 security scheme. - map scopes = 3 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:ImplicitOAuthFlow] - -// --8<-- [start:PasswordOAuthFlow] -// Defines configuration details for the OAuth 2.0 Resource Owner Password flow. -message PasswordOAuthFlow { +// --8<-- [start:DeviceCodeOAuthFlow] +// Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628). +// This flow is designed for input-constrained devices such as IoT devices, +// and CLI tools where the user authenticates on a separate device. +message DeviceCodeOAuthFlow { + // The device authorization endpoint URL. + string device_authorization_url = 1 [(google.api.field_behavior) = REQUIRED]; // The token URL to be used for this flow. - string token_url = 1 [(google.api.field_behavior) = REQUIRED]; + string token_url = 2 [(google.api.field_behavior) = REQUIRED]; // The URL to be used for obtaining refresh tokens. - string refresh_url = 2; + string refresh_url = 3; // The available scopes for the OAuth2 security scheme. - map scopes = 3 [(google.api.field_behavior) = REQUIRED]; + map scopes = 4 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:PasswordOAuthFlow] +// --8<-- [end:DeviceCodeOAuthFlow] ///////////// Request Messages /////////// // --8<-- [start:SendMessageRequest] @@ -714,10 +708,7 @@ message SendMessageRequest { // Optional tenant, provided as a path parameter. string tenant = 4; // The message to send to the agent. - Message request = 1 [ - (google.api.field_behavior) = REQUIRED, - json_name = "message" - ]; + Message message = 1 [(google.api.field_behavior) = REQUIRED]; // Configuration for the send request. SendMessageConfiguration configuration = 2; // A flexible key-value map for passing additional context or parameters. @@ -733,7 +724,10 @@ message GetTaskRequest { // The resource name of the task. // Format: tasks/{task_id} string name = 1 [(google.api.field_behavior) = REQUIRED]; - // The maximum number of messages to include in the history. + // The maximum number of most recent messages from the task's history to retrieve. An + // unset value means the client does not impose any limit. A value of zero is + // a request to not include any messages. The server MUST NOT return more + // messages than the provided value, but MAY apply a lower limit. optional int32 history_length = 2; } // --8<-- [end:GetTaskRequest] @@ -754,9 +748,9 @@ message ListTasksRequest { string page_token = 4; // The maximum number of messages to include in each task's history. optional int32 history_length = 5; - // Filter tasks updated after this timestamp (milliseconds since epoch). - // Only tasks with a last updated time greater than or equal to this value will be returned. - int64 last_updated_after = 6; + // Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z"). + // Only tasks with a status timestamp time greater than or equal to this value will be returned. + google.protobuf.Timestamp status_timestamp_after = 6; // Whether to include artifacts in the returned tasks. // Defaults to false to reduce payload size. optional bool include_artifacts = 7; @@ -861,7 +855,7 @@ message GetExtendedAgentCardRequest { message SendMessageResponse { oneof payload { Task task = 1; - Message msg = 2 [json_name = "message"]; + Message message = 2; } } // --8<-- [end:SendMessageResponse] @@ -873,7 +867,7 @@ message StreamResponse { // A Task object containing the current state of the task. Task task = 1; // A Message object containing a message from the agent. - Message msg = 2 [json_name = "message"]; + Message message = 2; // An event indicating a task status update. TaskStatusUpdateEvent status_update = 3; // An event indicating a task artifact update. @@ -892,4 +886,4 @@ message ListTaskPushNotificationConfigResponse { // If this field is omitted, there are no subsequent pages. string next_page_token = 2; } -// --8<-- [end:ListTaskPushNotificationConfigResponse] +// --8<-- [end:ListTaskPushNotificationConfigResponse] \ No newline at end of file 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 0619af352..bd007d61f 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 @@ -80,17 +80,17 @@ void testConvertMessage_ToProto() { // Assert assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.MSG, result.getPayloadCase()); - assertEquals("msg-123", result.getMsg().getMessageId()); - assertEquals("context-456", result.getMsg().getContextId()); - assertEquals(io.a2a.grpc.Role.ROLE_USER, result.getMsg().getRole()); + assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.MESSAGE, result.getPayloadCase()); + assertEquals("msg-123", result.getMessage().getMessageId()); + assertEquals("context-456", result.getMessage().getContextId()); + assertEquals(io.a2a.grpc.Role.ROLE_USER, result.getMessage().getRole()); } @Test void testConvertMessage_FromProto() { // Arrange io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setMsg(io.a2a.grpc.Message.newBuilder() + .setMessage(io.a2a.grpc.Message.newBuilder() .setMessageId("msg-123") .setContextId("context-456") .setRole(io.a2a.grpc.Role.ROLE_USER) diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index ec6d1cd86..e0a67c9c8 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -6,6 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.OffsetDateTime; import java.util.Collections; @@ -65,7 +66,7 @@ public void convertAgentCard() { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersion("123") // Weird protool version on purpose to make sure non-default takes effect + .protocolVersions("123") // Weird protool version on purpose to make sure non-default takes effect .build(); io.a2a.grpc.AgentCard result = ProtoUtils.ToProto.agentCard(agentCard); assertEquals("Hello World Agent", result.getName()); @@ -79,7 +80,8 @@ public void convertAgentCard() { assertEquals("text", result.getDefaultInputModes(0)); assertEquals(1, result.getDefaultOutputModesCount()); assertEquals("text", result.getDefaultOutputModes(0)); - assertEquals("123", result.getProtocolVersion()); + // protocolVersions is now a repeated field, checking if the list contains the value + assertTrue(result.getProtocolVersionsList().contains("123")); agentCard = AgentCard.builder() .name("Hello World Agent") .description("Just a hello world agent") @@ -103,7 +105,7 @@ public void convertAgentCard() { // .iconUrl("http://example.com/icon.svg") .securitySchemes(Map.of("basic", HTTPAuthSecurityScheme.builder().scheme("basic").description("Basic Auth").build())) .security(List.of(Map.of("oauth", List.of("read")))) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); result = ProtoUtils.ToProto.agentCard(agentCard); assertEquals("Hello World Agent", result.getName()); @@ -117,7 +119,8 @@ public void convertAgentCard() { assertEquals("text", result.getDefaultInputModes(0)); assertEquals(1, result.getDefaultOutputModesCount()); assertEquals("text", result.getDefaultOutputModes(0)); - assertEquals(CURRENT_PROTOCOL_VERSION, result.getProtocolVersion()); + // protocolVersions is now a repeated field, checking if the list contains the value + assertTrue(result.getProtocolVersionsList().contains(CURRENT_PROTOCOL_VERSION)); assertEquals(1, result.getSecurityCount()); assertEquals(1, result.getSecurity(0).getSchemesMap().size()); assertEquals(true, result.getSecurity(0).getSchemesMap().containsKey("oauth")); diff --git a/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java b/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java index 9c1b4c88a..8eb4c6584 100644 --- a/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java +++ b/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java @@ -23,8 +23,8 @@ public interface A2AErrorCodes { /** Error code indicating the agent returned an invalid response (-32006). */ int INVALID_AGENT_RESPONSE_ERROR_CODE = -32006; - /** Error code indicating extended card is not configured (-32007). */ - int EXTENDED_CARD_NOT_CONFIGURED_ERROR_CODE = -32007; + /** Error code indicating extended agent card is not configured (-32007). */ + int EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE = -32007; /** Error code indicating client requested use of an extension marked as required: true in the Agent Card * but the client did not declare support for it in the request (-32008). */ diff --git a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java index 2913a2b97..ae8fb6f01 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java +++ b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java @@ -26,12 +26,16 @@ * @param streaming whether the agent supports streaming responses with incremental artifacts * @param pushNotifications whether the agent supports push notifications for state changes * @param stateTransitionHistory whether the agent maintains state transition history + * @param extendedAgentCard whether the agent supports an extended agent card * @param extensions list of custom extensions supported by the agent (optional) * @see AgentCard * @see AgentExtension * @see A2A Protocol Specification */ -public record AgentCapabilities(boolean streaming, boolean pushNotifications, boolean stateTransitionHistory, +public record AgentCapabilities(boolean streaming, + boolean pushNotifications, + boolean stateTransitionHistory, + boolean extendedAgentCard, List extensions) { /** @@ -62,6 +66,7 @@ public static class Builder { private boolean streaming; private boolean pushNotifications; private boolean stateTransitionHistory; + private boolean extendedAgentCard; private List extensions; /** @@ -112,6 +117,18 @@ public Builder stateTransitionHistory(boolean stateTransitionHistory) { return this; } + /** + * Sets whether the agent supports an extended agent card. + * state transition history. + * + * @param extendedAgentCard true if an extended agent card is supported, false otherwise + * @return this builder for method chaining + */ + public Builder extendedAgentCard(boolean extendedAgentCard) { + this.extendedAgentCard = extendedAgentCard; + return this; + } + /** * Sets the list of custom extensions supported by the agent. *

    @@ -133,7 +150,7 @@ public Builder extensions(List extensions) { * @return a new AgentCapabilities instance */ public AgentCapabilities build() { - return new AgentCapabilities(streaming, pushNotifications, stateTransitionHistory, extensions); + return new AgentCapabilities(streaming, pushNotifications, stateTransitionHistory, extendedAgentCard, extensions); } } } diff --git a/spec/src/main/java/io/a2a/spec/AgentCard.java b/spec/src/main/java/io/a2a/spec/AgentCard.java index d8ed1231a..f5a642509 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCard.java +++ b/spec/src/main/java/io/a2a/spec/AgentCard.java @@ -32,12 +32,11 @@ * @param defaultInputModes list of supported input modes, e.g., "text", "audio" (required) * @param defaultOutputModes list of supported output modes, e.g., "text", "audio" (required) * @param skills list of skills that this agent can perform (required) - * @param supportsExtendedAgentCard whether the agent supports authenticated extended card retrieval (optional, defaults to false) * @param securitySchemes map of security scheme names to their definitions (optional) * @param security list of security requirements for accessing the agent (optional) * @param iconUrl URL to an icon representing the agent (optional) * @param supportedInterfaces ordered list of protocol+URL interface combinations; first entry is preferred (required) - * @param protocolVersion the version of the A2A Protocol this agent implements (defaults to {@link #CURRENT_PROTOCOL_VERSION}) + * @param protocolVersions the versions of the A2A Protocol this agent implements (defaults to a singleton list of {@link #CURRENT_PROTOCOL_VERSION}) * @param signatures digital signatures verifying the authenticity of the agent card (optional) * @see AgentInterface * @see A2A Protocol Specification @@ -52,12 +51,11 @@ public record AgentCard( List defaultInputModes, List defaultOutputModes, List skills, - boolean supportsExtendedAgentCard, Map securitySchemes, List>> security, String iconUrl, List supportedInterfaces, - String protocolVersion, + List protocolVersions, List signatures) { /** The default A2A Protocol version used when not explicitly specified. */ @@ -75,12 +73,11 @@ public record AgentCard( * @param defaultInputModes the defaultInputModes parameter (see class-level JavaDoc) * @param defaultOutputModes the defaultOutputModes parameter (see class-level JavaDoc) * @param skills the skills parameter (see class-level JavaDoc) - * @param supportsExtendedAgentCard the supportsExtendedAgentCard parameter (see class-level JavaDoc) * @param securitySchemes the securitySchemes parameter (see class-level JavaDoc) * @param security the security parameter (see class-level JavaDoc) * @param iconUrl the iconUrl parameter (see class-level JavaDoc) * @param supportedInterfaces the supportedInterfaces parameter (see class-level JavaDoc) - * @param protocolVersion the protocolVersion parameter (see class-level JavaDoc) + * @param protocolVersions the protocolVersions parameter (see class-level JavaDoc) * @param signatures the signatures parameter (see class-level JavaDoc) * @throws IllegalArgumentException if any required field is null */ @@ -94,8 +91,8 @@ public record AgentCard( Assert.checkNotNullParam("supportedInterfaces", supportedInterfaces); Assert.checkNotNullParam("version", version); - if (protocolVersion == null) { - protocolVersion = CURRENT_PROTOCOL_VERSION; + if (protocolVersions == null || protocolVersions.isEmpty()) { + protocolVersions = List.of(CURRENT_PROTOCOL_VERSION); } } @@ -162,12 +159,11 @@ public static class Builder { private List defaultInputModes; private List defaultOutputModes; private List skills; - private boolean supportsExtendedAgentCard = false; private Map securitySchemes; private List>> security; private String iconUrl; private List supportedInterfaces; - private String protocolVersion; + private List protocolVersions; private List signatures; /** @@ -195,12 +191,11 @@ private Builder(AgentCard card) { this.defaultInputModes = card.defaultInputModes != null ? new ArrayList<>(card.defaultInputModes) : null; this.defaultOutputModes = card.defaultOutputModes != null ? new ArrayList<>(card.defaultOutputModes) : null; this.skills = card.skills != null ? new ArrayList<>(card.skills) : null; - this.supportsExtendedAgentCard = card.supportsExtendedAgentCard; this.securitySchemes = card.securitySchemes != null ? Map.copyOf(card.securitySchemes) : null; this.security = card.security != null ? new ArrayList<>(card.security) : null; this.iconUrl = card.iconUrl; this.supportedInterfaces = card.supportedInterfaces != null ? new ArrayList<>(card.supportedInterfaces) : null; - this.protocolVersion = card.protocolVersion; + this.protocolVersions = card.protocolVersions; this.signatures = card.signatures != null ? new ArrayList<>(card.signatures) : null; } @@ -316,21 +311,6 @@ public Builder skills(List skills) { return this; } - /** - * Sets whether the agent supports extended card retrieval. - *

    - * When true, the agent can provide additional information through the - * {@code GetAuthenticatedExtendedCard} method, which may include private - * or user-specific details not in the public card. - * - * @param supportsExtendedAgentCard true if supported, false otherwise - * @return this builder for method chaining - */ - public Builder supportsExtendedAgentCard(boolean supportsExtendedAgentCard) { - this.supportsExtendedAgentCard = supportsExtendedAgentCard; - return this; - } - /** * Sets the map of security scheme definitions. *

    @@ -398,13 +378,13 @@ public Builder supportedInterfaces(List supportedInterfaces) { /** * Sets the version of the A2A Protocol this agent implements. *

    - * If not set, defaults to {@link AgentCard#CURRENT_PROTOCOL_VERSION}. + * If not set, defaults to a single list of {@link AgentCard#CURRENT_PROTOCOL_VERSION}. * - * @param protocolVersion the protocol version string + * @param protocolVersions the protocol versions * @return this builder for method chaining */ - public Builder protocolVersion(String protocolVersion) { - this.protocolVersion = protocolVersion; + public Builder protocolVersions(String... protocolVersions) { + this.protocolVersions = List.of(protocolVersions); return this; } @@ -434,8 +414,8 @@ public Builder signatures(List signatures) { public AgentCard build() { return new AgentCard(name, description, provider, version, documentationUrl, capabilities, defaultInputModes, defaultOutputModes, skills, - supportsExtendedAgentCard, securitySchemes, security, iconUrl, - supportedInterfaces, protocolVersion, signatures); + securitySchemes, security, iconUrl, + supportedInterfaces, protocolVersions, signatures); } } } diff --git a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java b/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java index c4db756a4..d3d399057 100644 --- a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java +++ b/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java @@ -19,13 +19,14 @@ * @param refreshUrl URL for obtaining refresh tokens (optional) * @param scopes map of available OAuth scopes to their descriptions (required) * @param tokenUrl URL for the token endpoint where codes are exchanged for tokens (required) + * @param pkceRequired Indicates if PKCE (RFC 7636) is required for this flow. (required) * @see OAuthFlows for the container of all supported OAuth flows * @see OAuth2SecurityScheme for the security scheme using these flows * @see RFC 6749 - Authorization Code Grant * @see A2A Protocol Specification */ public record AuthorizationCodeOAuthFlow(String authorizationUrl, String refreshUrl, Map scopes, - String tokenUrl) { + String tokenUrl, boolean pkceRequired) { /** * Compact constructor that validates required fields. @@ -34,6 +35,7 @@ public record AuthorizationCodeOAuthFlow(String authorizationUrl, String refresh * @param refreshUrl the refreshUrl parameter (see class-level JavaDoc) * @param scopes the scopes parameter (see class-level JavaDoc) * @param tokenUrl the tokenUrl parameter (see class-level JavaDoc) + * @param pkceRequired Indicates if PKCE (RFC 7636) is required for this flow. (required) * @throws IllegalArgumentException if authorizationUrl, scopes, or tokenUrl is null */ public AuthorizationCodeOAuthFlow { diff --git a/spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java b/spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java new file mode 100644 index 000000000..d2d25c047 --- /dev/null +++ b/spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java @@ -0,0 +1,37 @@ +package io.a2a.spec; + +import java.util.Map; + +import io.a2a.util.Assert; + +/** + * Configuration details for the OAuth 2.0 Device Code flow (RFC 8628). + *

    + * This flow is designed for input-constrained devices such as IoT devices, + * and CLI tools where the user authenticates on a separate device. + * + * @param deviceAuthorizationUrl the device authorization endpoint URL (required) + * @param tokenUrl URL for the token endpoint where credentials are exchanged for tokens (required) + * @param refreshUrl URL for obtaining refresh tokens (optional) + * @param scopes map of available OAuth scopes to their descriptions (required) + * @see OAuthFlows for the container of all supported OAuth flows + * @see OAuth2SecurityScheme for the security scheme using these flows + * @see A2A Protocol Specification + */ +public record DeviceCodeOAuthFlow(String deviceAuthorizationUrl, String tokenUrl, String refreshUrl, Map scopes) { + + /** + * Compact constructor that validates required fields. + * + * @param deviceAuthorizationUrl the device authorization endpoint URL (required) + * @param tokenUrl URL for the token endpoint where credentials are exchanged for tokens (required) + * @param refreshUrl URL for obtaining refresh tokens (optional) + * @param scopes map of available OAuth scopes to their descriptions (required) + * @throws IllegalArgumentException if authorizationUrl, scopes, or tokenUrl is null + */ + public DeviceCodeOAuthFlow { + Assert.checkNotNullParam("deviceAuthorizationUrl", deviceAuthorizationUrl); + Assert.checkNotNullParam("tokenUrl", tokenUrl); + Assert.checkNotNullParam("scopes", scopes); + } +} diff --git a/spec/src/main/java/io/a2a/spec/ExtendedCardNotConfiguredError.java b/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java similarity index 78% rename from spec/src/main/java/io/a2a/spec/ExtendedCardNotConfiguredError.java rename to spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java index 3403b3ffd..c8998fe04 100644 --- a/spec/src/main/java/io/a2a/spec/ExtendedCardNotConfiguredError.java +++ b/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java @@ -1,6 +1,6 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.EXTENDED_CARD_NOT_CONFIGURED_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; @@ -19,15 +19,15 @@ * Usage example: *

    {@code
      * // In agent implementation
    - * if (authenticatedExtendedCard == null) {
    - *     throw new AuthenticatedExtendedCardNotConfiguredError();
    + * if (extendedAgentCard == null) {
    + *     throw new ExtendedAgentCardNotConfiguredError();
      * }
      * }
    * * @see AgentCard for the base agent card structure * @see A2A Protocol Specification */ -public class ExtendedCardNotConfiguredError extends A2AProtocolError { +public class ExtendedAgentCardNotConfiguredError extends A2AProtocolError { /** * Constructs an error for agents that don't support authenticated extended card retrieval. @@ -36,12 +36,12 @@ public class ExtendedCardNotConfiguredError extends A2AProtocolError { * @param message the error message * @param data additional error data */ - public ExtendedCardNotConfiguredError( + public ExtendedAgentCardNotConfiguredError( Integer code, String message, Object data) { super( - defaultIfNull(code, EXTENDED_CARD_NOT_CONFIGURED_ERROR_CODE), + defaultIfNull(code, EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE), defaultIfNull(message, "Extended Card not configured"), data, "https://a2a-protocol.org/errors/extended-agent-card-not-configured"); diff --git a/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java b/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java deleted file mode 100644 index 06341ab2b..000000000 --- a/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.a2a.spec; - -import java.util.Map; - -import io.a2a.util.Assert; - -/** - * Configuration for the OAuth 2.0 Implicit flow. - *

    - * The implicit flow is designed for browser-based applications where the client - * cannot securely store credentials. The access token is returned directly from - * the authorization endpoint without an intermediate authorization code. - *

    - * Note: The implicit flow is considered less secure than the - * authorization code flow and is deprecated in OAuth 2.1. It should only be used - * for legacy applications or when the authorization code flow with PKCE is not feasible. - * - * @param authorizationUrl URL for the authorization endpoint where users authenticate (required) - * @param refreshUrl URL for obtaining refresh tokens (optional, rarely used in implicit flow) - * @param scopes map of available OAuth scopes to their descriptions (required) - * @see OAuthFlows for the container of all supported OAuth flows - * @see OAuth2SecurityScheme for the security scheme using these flows - * @see RFC 6749 - Implicit Grant - * @see A2A Protocol Specification - */ -public record ImplicitOAuthFlow(String authorizationUrl, String refreshUrl, Map scopes) { - - /** - * Compact constructor that validates required fields. - * - * @param authorizationUrl the authorizationUrl parameter (see class-level JavaDoc) - * @param refreshUrl the refreshUrl parameter (see class-level JavaDoc) - * @param scopes the scopes parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if authorizationUrl or scopes is null - */ - public ImplicitOAuthFlow { - Assert.checkNotNullParam("authorizationUrl", authorizationUrl); - Assert.checkNotNullParam("scopes", scopes); - } -} diff --git a/spec/src/main/java/io/a2a/spec/ListTasksParams.java b/spec/src/main/java/io/a2a/spec/ListTasksParams.java index 6fb9ff5d1..d99d25bcf 100644 --- a/spec/src/main/java/io/a2a/spec/ListTasksParams.java +++ b/spec/src/main/java/io/a2a/spec/ListTasksParams.java @@ -12,7 +12,7 @@ * @param pageSize Maximum number of tasks to return (1-100, defaults to 50) * @param pageToken Token for pagination from a previous ListTasksResult * @param historyLength Number of recent messages to include in each task's history (defaults to 0) - * @param lastUpdatedAfter Filter tasks updated after this timestamp + * @param statusTimestampAfter Filter tasks updated after this timestamp * @param includeArtifacts Whether to include artifacts in the returned tasks (defaults to false) * @param tenant optional tenant, provided as a path parameter. */ @@ -22,7 +22,7 @@ public record ListTasksParams( @Nullable Integer pageSize, @Nullable String pageToken, @Nullable Integer historyLength, - @Nullable Instant lastUpdatedAfter, + @Nullable Instant statusTimestampAfter, @Nullable Boolean includeArtifacts, String tenant ) { @@ -38,7 +38,7 @@ public record ListTasksParams( * @param pageSize maximum number of results per page * @param pageToken pagination token * @param historyLength number of history items to include - * @param lastUpdatedAfter filter by last update timestamp + * @param statusTimestampAfter filter by status timestamp * @param includeArtifacts whether to include artifacts * @param tenant the tenant identifier * @throws InvalidParamsError if tenant is null or if pageSize or historyLength are out of valid range @@ -124,7 +124,7 @@ public static class Builder { private Integer pageSize; private String pageToken; private Integer historyLength; - private Instant lastUpdatedAfter; + private Instant statusTimestampAfter; private Boolean includeArtifacts; private String tenant; @@ -190,13 +190,13 @@ public Builder historyLength(Integer historyLength) { } /** - * Sets the lastUpdatedAfter. + * Sets the statusTimestampAfter. * - * @param lastUpdatedAfter the lastUpdatedAfter + * @param statusTimestampAfter the statusTimestampAfter * @return this builder for method chaining */ - public Builder lastUpdatedAfter(Instant lastUpdatedAfter) { - this.lastUpdatedAfter = lastUpdatedAfter; + public Builder statusTimestampAfter(Instant statusTimestampAfter) { + this.statusTimestampAfter = statusTimestampAfter; return this; } @@ -229,7 +229,7 @@ public Builder tenant(String tenant) { */ public ListTasksParams build() { return new ListTasksParams(contextId, status, pageSize, pageToken, historyLength, - lastUpdatedAfter, includeArtifacts, tenant); + statusTimestampAfter, includeArtifacts, tenant); } } } diff --git a/spec/src/main/java/io/a2a/spec/OAuthFlows.java b/spec/src/main/java/io/a2a/spec/OAuthFlows.java index bcddf7f43..5cabfcccd 100644 --- a/spec/src/main/java/io/a2a/spec/OAuthFlows.java +++ b/spec/src/main/java/io/a2a/spec/OAuthFlows.java @@ -10,14 +10,13 @@ * * @param authorizationCode OAuth 2.0 authorization code flow configuration * @param clientCredentials OAuth 2.0 client credentials flow configuration - * @param implicit OAuth 2.0 implicit flow configuration - * @param password OAuth 2.0 resource owner password credentials flow configuration + * @param deviceCode OAuth 2.0 device code flow configuration * @see OAuth2SecurityScheme for the security scheme using these flows * @see OpenAPI OAuth Flows Object * @see A2A Protocol Specification */ public record OAuthFlows(AuthorizationCodeOAuthFlow authorizationCode, ClientCredentialsOAuthFlow clientCredentials, - ImplicitOAuthFlow implicit, PasswordOAuthFlow password) { + DeviceCodeOAuthFlow deviceCode) { /** * Create a new Builder @@ -34,8 +33,7 @@ public static Builder builder() { public static class Builder { private AuthorizationCodeOAuthFlow authorizationCode; private ClientCredentialsOAuthFlow clientCredentials; - private ImplicitOAuthFlow implicit; - private PasswordOAuthFlow password; + private DeviceCodeOAuthFlow deviceCode; /** * Creates a new Builder with all fields unset. @@ -66,26 +64,16 @@ public Builder clientCredentials(ClientCredentialsOAuthFlow clientCredentials) { } /** - * Sets the implicit flow configuration. + * Sets the device code flow configuration. * - * @param implicit the implicit flow (optional) + * @param deviceCode the device code flow (optional) * @return this builder for method chaining */ - public Builder implicit(ImplicitOAuthFlow implicit) { - this.implicit = implicit; + public Builder deviceCode(DeviceCodeOAuthFlow deviceCode) { + this.deviceCode = deviceCode; return this; } - /** - * Sets the password flow configuration. - * - * @param password the password flow (optional) - * @return this builder for method chaining - */ - public Builder password(PasswordOAuthFlow password) { - this.password = password; - return this; - } /** * Builds a new immutable OAuthFlows instance. @@ -93,7 +81,7 @@ public Builder password(PasswordOAuthFlow password) { * @return a new OAuthFlows instance */ public OAuthFlows build() { - return new OAuthFlows(authorizationCode, clientCredentials, implicit, password); + return new OAuthFlows(authorizationCode, clientCredentials, deviceCode); } } } diff --git a/spec/src/main/java/io/a2a/spec/PasswordOAuthFlow.java b/spec/src/main/java/io/a2a/spec/PasswordOAuthFlow.java deleted file mode 100644 index a6a3a8803..000000000 --- a/spec/src/main/java/io/a2a/spec/PasswordOAuthFlow.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.a2a.spec; - -import java.util.Map; - -import io.a2a.util.Assert; - -/** - * Configuration for the OAuth 2.0 Resource Owner Password Credentials flow. - *

    - * The password flow allows the client to exchange a user's credentials (username and password) - * directly for an access token. This flow should only be used when there is a high degree of - * trust between the user and the client application. - *

    - * Note: This flow is generally discouraged and deprecated in OAuth 2.1 - * because it exposes user credentials to the client. Use the authorization code flow - * with PKCE instead whenever possible. - * - * @param refreshUrl URL for obtaining refresh tokens (optional) - * @param scopes map of available OAuth scopes to their descriptions (required) - * @param tokenUrl URL for the token endpoint where credentials are exchanged for tokens (required) - * @see OAuthFlows for the container of all supported OAuth flows - * @see OAuth2SecurityScheme for the security scheme using these flows - * @see RFC 6749 - Resource Owner Password Credentials Grant - * @see A2A Protocol Specification - */ -public record PasswordOAuthFlow(String refreshUrl, Map scopes, String tokenUrl) { - - /** - * Compact constructor that validates required fields. - * - * @param refreshUrl the refreshUrl parameter (see class-level JavaDoc) - * @param scopes the scopes parameter (see class-level JavaDoc) - * @param tokenUrl the tokenUrl parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if scopes or tokenUrl is null - */ - public PasswordOAuthFlow { - Assert.checkNotNullParam("scopes", scopes); - Assert.checkNotNullParam("tokenUrl", tokenUrl); - } -} diff --git a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java index 50c8f3a45..955709986 100644 --- a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java @@ -23,7 +23,7 @@ * } * }

    * - * @see AgentCard#protocolVersion() for supported version declaration + * @see AgentCard#protocolVersions() for supported version declaration * @see A2A Protocol Specification */ public class VersionNotSupportedError extends A2AProtocolError { diff --git a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java index d5b5d6ffd..526b81ce5 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java @@ -50,7 +50,7 @@ public AgentCard agentCard() { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } 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 5fab9d8d7..d8a871e04 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 @@ -19,6 +19,7 @@ import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; @@ -606,21 +607,26 @@ public void testError() throws A2AClientException { } @Test - public void testGetAgentCard() throws A2AClientException { - AgentCard agentCard = getClient().getAgentCard(); + public void testGetExtendedAgentCard() throws A2AClientException { + AgentCard agentCard = getClient().getExtendedAgentCard(); assertNotNull(agentCard); assertEquals("test-card", agentCard.name()); assertEquals("A test agent card", agentCard.description()); assertNotNull(agentCard.supportedInterfaces()); assertFalse(agentCard.supportedInterfaces().isEmpty()); - assertEquals(getTransportUrl(), Utils.getFavoriteInterface(agentCard).url()); + Optional transportInterface = agentCard.supportedInterfaces().stream() + .filter(i -> getTransportProtocol().equals(i.protocolBinding())) + .findFirst(); + assertTrue(transportInterface.isPresent()); + System.out.println("transportInterface = " + transportInterface); + assertEquals(getTransportUrl(),transportInterface.get().url()); assertEquals("1.0", agentCard.version()); assertEquals("http://example.com/docs", agentCard.documentationUrl()); assertTrue(agentCard.capabilities().pushNotifications()); assertTrue(agentCard.capabilities().streaming()); assertTrue(agentCard.capabilities().stateTransitionHistory()); + assertTrue(agentCard.capabilities().extendedAgentCard()); assertTrue(agentCard.skills().isEmpty()); - assertFalse(agentCard.supportsExtendedAgentCard()); } @Test @@ -1994,7 +2000,7 @@ private AgentCard createTestAgentCard() { .defaultOutputModes(List.of("text")) .skills(List.of()) .supportedInterfaces(List.of(new AgentInterface(getTransportProtocol(), getTransportUrl()))) - .protocolVersion(CURRENT_PROTOCOL_VERSION) + .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java index b8b9b376f..03ec3481b 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java @@ -1,6 +1,7 @@ package io.a2a.server.apps.common; import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; +import static io.a2a.spec.TransportProtocol.GRPC; import java.io.IOException; import java.io.InputStream; @@ -12,10 +13,13 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; +import io.a2a.server.ExtendedAgentCard; import io.a2a.server.PublicAgentCard; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; +import io.a2a.spec.TransportProtocol; + import io.quarkus.arc.profile.IfBuildProfile; import org.junit.jupiter.api.Assertions; @@ -28,9 +32,11 @@ public class AgentCardProducer { @Produces @PublicAgentCard + @ExtendedAgentCard public AgentCard agentCard() { String port = System.getProperty("test.agent.card.port", "8081"); String preferredTransport = loadPreferredTransportFromProperties(); + String transportUrl = GRPC.toString().equals(preferredTransport) ? "localhost:" + port : "http://localhost:" + port; AgentCard.Builder builder = AgentCard.builder() .name("test-card") @@ -41,12 +47,13 @@ public AgentCard agentCard() { .streaming(true) .pushNotifications(true) .stateTransitionHistory(true) + .extendedAgentCard(true) .build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) .skills(new ArrayList<>()) - .protocolVersion(CURRENT_PROTOCOL_VERSION) - .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, "http://localhost:" + port))); + .protocolVersions(CURRENT_PROTOCOL_VERSION) + .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, transportUrl))); return builder.build(); } 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 2998965ea..408205aa2 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 @@ -33,7 +33,7 @@ import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; -import io.a2a.spec.ExtendedCardNotConfiguredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InternalError; @@ -325,8 +325,11 @@ public void onComplete() { public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, StreamObserver responseObserver) { try { - responseObserver.onNext(ToProto.agentCard(getAgentCardInternal())); - responseObserver.onCompleted(); + AgentCard extendedAgentCard = getExtendedAgentCard(); + if (extendedAgentCard != null) { + responseObserver.onNext(ToProto.agentCard(extendedAgentCard)); + responseObserver.onCompleted(); + } } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -452,7 +455,7 @@ private void handleError(StreamObserver responseObserver, A2AError error) } else if (error instanceof InvalidAgentResponseError) { status = Status.INTERNAL; description = "InvalidAgentResponseError: " + error.getMessage(); - } else if (error instanceof ExtendedCardNotConfiguredError) { + } else if (error instanceof ExtendedAgentCardNotConfiguredError) { status = Status.FAILED_PRECONDITION; description = "ExtendedCardNotConfiguredError: " + error.getMessage(); } else if (error instanceof ExtensionSupportRequiredError) { @@ -498,6 +501,7 @@ private void handleInternalError(StreamObserver responseObserver, Throwab handleError(responseObserver, new InternalError(t.getMessage())); } + private AgentCard getAgentCardInternal() { AgentCard agentCard = getAgentCard(); if (initialised.compareAndSet(false, true)) { @@ -538,6 +542,8 @@ public static void setStreamingSubscribedRunnable(Runnable runnable) { protected abstract AgentCard getAgentCard(); + protected abstract AgentCard getExtendedAgentCard(); + protected abstract CallContextFactory getCallContextFactory(); protected abstract Executor getExecutor(); 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 a3ce7ca2a..690d69a87 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 @@ -12,6 +12,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import jakarta.enterprise.inject.Instance; + import com.google.protobuf.Empty; import com.google.protobuf.Struct; import io.a2a.grpc.AuthenticationInfo; @@ -49,16 +51,13 @@ import io.a2a.spec.AgentInterface; import io.a2a.spec.Artifact; import io.a2a.spec.Event; -import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.InternalError; -import io.a2a.spec.VersionNotSupportedError; import io.a2a.spec.MessageSendParams; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; -import io.a2a.transport.grpc.context.GrpcContextKeys; -import io.grpc.Context; + import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.internal.testing.StreamRecorder; @@ -194,7 +193,7 @@ public void testOnMessageNewMessageSuccess() throws Exception { Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); SendMessageResponse response = result.get(0); - assertEquals(GRPC_MESSAGE, response.getMsg()); + assertEquals(GRPC_MESSAGE, response.getMessage()); } @Test @@ -210,7 +209,7 @@ public void testOnMessageNewMessageWithExistingTaskSuccess() throws Exception { Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); SendMessageResponse response = result.get(0); - assertEquals(GRPC_MESSAGE, response.getMsg()); + assertEquals(GRPC_MESSAGE, response.getMessage()); } @Test @@ -316,8 +315,8 @@ public void testOnMessageStreamNewMessageSuccess() throws Exception { Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); StreamResponse response = result.get(0); - Assertions.assertTrue(response.hasMsg()); - Message message = response.getMsg(); + Assertions.assertTrue(response.hasMessage()); + Message message = response.getMessage(); Assertions.assertEquals(GRPC_MESSAGE, message); } @@ -533,7 +532,7 @@ public void testOnResubscribeExistingTaskSuccess() throws Exception { // We need to send some events in order for those to end up in the queue SendMessageRequest sendMessageRequest = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder messageRecorder = StreamRecorder.create(); handler.sendStreamingMessage(sendMessageRequest, messageRecorder); @@ -545,8 +544,8 @@ public void testOnResubscribeExistingTaskSuccess() throws Exception { Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); StreamResponse response = result.get(0); - Assertions.assertTrue(response.hasMsg()); - assertEquals(GRPC_MESSAGE, response.getMsg()); + Assertions.assertTrue(response.hasMessage()); + assertEquals(GRPC_MESSAGE, response.getMessage()); Assertions.assertNull(streamRecorder.getError()); } @@ -755,7 +754,7 @@ public void testDeletePushNotificationConfigNoPushConfigStore() { } @Disabled - public void testOnGetAuthenticatedExtendedAgentCard() throws Exception { + public void testOnGetExtendedAgentCard() throws Exception { // TODO - getting the authenticated extended agent card isn't supported for gRPC right now } @@ -843,13 +842,13 @@ public void testExtensionSupportRequiredErrorOnSendMessage() throws Exception { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); GrpcHandler handler = new TestGrpcHandler(cardWithExtension, requestHandler, internalExecutor); SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendMessage(request, streamRecorder); @@ -879,13 +878,13 @@ public void testExtensionSupportRequiredErrorOnSendStreamingMessage() throws Exc .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); GrpcHandler handler = new TestGrpcHandler(cardWithExtension, requestHandler, internalExecutor); SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendStreamingMessage(request, streamRecorder); @@ -915,7 +914,7 @@ public void testRequiredExtensionProvidedSuccess() throws Exception { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); // Create a TestGrpcHandler that provides the required extension in the context @@ -942,7 +941,7 @@ public ServerCallContext create(StreamObserver streamObserver) { }; SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendMessage(request, streamRecorder); @@ -989,7 +988,7 @@ public ServerCallContext create(StreamObserver streamObserver) { }; SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendMessage(request, streamRecorder); @@ -1034,7 +1033,7 @@ public ServerCallContext create(StreamObserver streamObserver) { }; SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendStreamingMessage(request, streamRecorder); @@ -1083,7 +1082,7 @@ public ServerCallContext create(StreamObserver streamObserver) { }; SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendMessage(request, streamRecorder); @@ -1134,7 +1133,7 @@ public ServerCallContext create(StreamObserver streamObserver) { }; SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendMessage(request, streamRecorder); @@ -1147,7 +1146,7 @@ public ServerCallContext create(StreamObserver streamObserver) { private StreamRecorder sendMessageRequest(GrpcHandler handler) throws Exception { SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendMessage(request, streamRecorder); @@ -1189,7 +1188,7 @@ private StreamRecorder getTaskPushNotificationConfig private StreamRecorder sendStreamingMessageRequest(GrpcHandler handler) throws Exception { SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.sendStreamingMessage(request, streamRecorder); @@ -1199,7 +1198,7 @@ private StreamRecorder sendStreamingMessageRequest(GrpcHandler h private void sendStreamingMessageRequest(GrpcHandler handler, StreamObserver streamObserver) throws Exception { SendMessageRequest request = SendMessageRequest.newBuilder() - .setRequest(GRPC_MESSAGE) + .setMessage(GRPC_MESSAGE) .build(); handler.sendStreamingMessage(request, streamObserver); } @@ -1218,7 +1217,7 @@ public void testListTasksNegativeTimestampReturnsInvalidArgument() { // Negative timestamp should trigger validation error ListTasksRequest request = ListTasksRequest.newBuilder() - .setLastUpdatedAfter(-1L) + .setStatusTimestampAfter(com.google.protobuf.Timestamp.newBuilder().setSeconds(-1L).build()) .setTenant("") .build(); @@ -1279,6 +1278,11 @@ protected AgentCard getAgentCard() { return card; } + @Override + protected AgentCard getExtendedAgentCard() { + return card; + } + @Override protected CallContextFactory getCallContextFactory() { return null; 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 ca8149099..2e1a1fdf0 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 @@ -14,8 +14,8 @@ 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.GetExtendedAgentCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; @@ -42,8 +42,7 @@ import io.a2a.server.version.A2AVersionValidator; import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.EventKind; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidRequestError; @@ -53,7 +52,7 @@ import io.a2a.spec.Task; import io.a2a.spec.TaskNotFoundError; import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.VersionNotSupportedError; + import mutiny.zero.ZeroPublisher; import org.jspecify.annotations.Nullable; @@ -262,18 +261,18 @@ public DeleteTaskPushNotificationConfigResponse deletePushNotificationConfig( } // TODO: Add authentication (https://github.com/a2aproject/a2a-java/issues/77) - public GetAuthenticatedExtendedCardResponse onGetAuthenticatedExtendedCardRequest( - GetAuthenticatedExtendedCardRequest request, ServerCallContext context) { - if (!agentCard.supportsExtendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { - return new GetAuthenticatedExtendedCardResponse(request.getId(), - new ExtendedCardNotConfiguredError(null, "Extended Card not configured", null)); + public GetExtendedAgentCardResponse onGetExtendedCardRequest( + GetExtendedAgentCardRequest request, ServerCallContext context) { + if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { + return new GetExtendedAgentCardResponse(request.getId(), + new ExtendedAgentCardNotConfiguredError(null, "Extended Card not configured", null)); } try { - return new GetAuthenticatedExtendedCardResponse(request.getId(), extendedAgentCard.get()); + return new GetExtendedAgentCardResponse(request.getId(), extendedAgentCard.get()); } catch (A2AError e) { - return new GetAuthenticatedExtendedCardResponse(request.getId(), e); + return new GetExtendedAgentCardResponse(request.getId(), e); } catch (Throwable t) { - return new GetAuthenticatedExtendedCardResponse(request.getId(), new InternalError(t.getMessage())); + return new GetExtendedAgentCardResponse(request.getId(), new InternalError(t.getMessage())); } } 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 3436a34b1..b43c28029 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 @@ -22,8 +22,8 @@ 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.GetExtendedAgentCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; @@ -52,14 +52,13 @@ import io.a2a.spec.AgentExtension; import io.a2a.spec.AgentInterface; import io.a2a.spec.Artifact; -import io.a2a.spec.ExtendedCardNotConfiguredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.VersionNotSupportedError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.Event; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.ListTasksParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; @@ -1525,12 +1524,12 @@ public void testDeletePushNotificationConfigNoPushConfigStore() { } @Test - public void testOnGetAuthenticatedExtendedAgentCard() throws Exception { + public void testOnGetExtendedAgentCard() throws Exception { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - GetAuthenticatedExtendedCardRequest request = new GetAuthenticatedExtendedCardRequest("1"); - GetAuthenticatedExtendedCardResponse response = handler.onGetAuthenticatedExtendedCardRequest(request, callContext); + GetExtendedAgentCardRequest request = new GetExtendedAgentCardRequest("1"); + GetExtendedAgentCardResponse response = handler.onGetExtendedCardRequest(request, callContext); assertEquals(request.getId(), response.getId()); - assertInstanceOf(ExtendedCardNotConfiguredError.class, response.getError()); + assertInstanceOf(ExtendedAgentCardNotConfiguredError.class, response.getError()); assertNull(response.getResult()); } @@ -1633,7 +1632,7 @@ public void testExtensionSupportRequiredErrorOnMessageSend() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); @@ -1672,7 +1671,7 @@ public void testExtensionSupportRequiredErrorOnMessageSendStream() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); @@ -1741,7 +1740,7 @@ public void testRequiredExtensionProvidedSuccess() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); 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 4d9a9667d..3ffb56c5f 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 @@ -36,7 +36,7 @@ import io.a2a.server.util.async.Internal; import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedCardNotConfiguredError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; @@ -210,7 +210,7 @@ public HTTPRestResponse getTask(String taskId, @Nullable Integer historyLength, public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String status, @Nullable Integer pageSize, @Nullable String pageToken, - @Nullable Integer historyLength, @Nullable String lastUpdatedAfter, + @Nullable Integer historyLength, @Nullable String statusTimestampAfter, @Nullable Boolean includeArtifacts, String tenant, ServerCallContext context) { try { @@ -266,21 +266,21 @@ public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String s paramsBuilder.historyLength(historyLength); } paramsBuilder.tenant(tenant); - if (lastUpdatedAfter != null) { + if (statusTimestampAfter != null) { try { // Try parsing as Unix milliseconds first (integer) - long millis = Long.parseLong(lastUpdatedAfter); + long millis = Long.parseLong(statusTimestampAfter); if (millis < 0L) { Map errorData = new HashMap<>(); - errorData.put("parameter", "lastUpdatedAfter"); + errorData.put("parameter", "statusTimestampAfter"); errorData.put("reason", "Must be a non-negative timestamp value, got: " + millis); throw new InvalidParamsError(null, "Invalid params", errorData); } - paramsBuilder.lastUpdatedAfter(Instant.ofEpochMilli(millis)); + paramsBuilder.statusTimestampAfter(Instant.ofEpochMilli(millis)); } catch (NumberFormatException nfe) { // Fall back to ISO-8601 format try { - paramsBuilder.lastUpdatedAfter(Instant.parse(lastUpdatedAfter)); + paramsBuilder.statusTimestampAfter(Instant.parse(statusTimestampAfter)); } catch (DateTimeParseException e) { Map errorData = new HashMap<>(); errorData.put("parameter", "lastUpdatedAfter"); @@ -466,7 +466,7 @@ private int mapErrorToHttpStatus(A2AError error) { if (error instanceof InvalidAgentResponseError) { return 502; } - if (error instanceof ExtendedCardNotConfiguredError + if (error instanceof ExtendedAgentCardNotConfiguredError || error instanceof ExtensionSupportRequiredError) { return 400; } @@ -478,8 +478,8 @@ private int mapErrorToHttpStatus(A2AError error) { public HTTPRestResponse getExtendedAgentCard(String tenant) { try { - if (!agentCard.supportsExtendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { - throw new ExtendedCardNotConfiguredError(null, "Extended Card not configured", null); + if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { + throw new ExtendedAgentCardNotConfiguredError(null, "Extended Card not configured", null); } return new HTTPRestResponse(200, "application/json", JsonUtil.toJson(extendedAgentCard.get())); } catch (A2AError e) { 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 a2e6ef6e9..7d930415b 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 @@ -19,8 +19,6 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.AgentExtension; import io.a2a.spec.AgentInterface; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.VersionNotSupportedError; import io.a2a.spec.Task; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -458,7 +456,7 @@ public void testExtensionSupportRequiredErrorOnSendMessage() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); @@ -508,7 +506,7 @@ public void testExtensionSupportRequiredErrorOnSendStreamingMessage() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); @@ -596,7 +594,7 @@ public void testRequiredExtensionProvidedSuccess() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersion(AgentCard.CURRENT_PROTOCOL_VERSION) + .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); From d3e5b28d7258250013da788af26f71a0e15e57a7 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Fri, 23 Jan 2026 16:04:10 +0100 Subject: [PATCH 006/192] test: Add input-required workflow coverage (#609) Add test for input-required task state transitions: create task, receive input-required status, send input, and complete task. Signed-off-by: Emmanuel Hugonnet --- .../apps/common/AbstractA2AServerTest.java | 62 +++++++++++++++++++ .../apps/common/AgentExecutorProducer.java | 42 +++++++++++++ 2 files changed, 104 insertions(+) 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 d8a871e04..724b58613 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 @@ -1424,6 +1424,68 @@ public void testNonBlockingWithMultipleMessages() throws Exception { } } + @Test + @Timeout(value = 1, unit = TimeUnit.MINUTES) + public void testInputRequiredWorkflow() throws Exception { + String inputRequiredTaskId = "input-required-test-" + java.util.UUID.randomUUID(); + try { + // 1. Send initial message - AgentExecutor will transition task to INPUT_REQUIRED + Message initialMessage = Message.builder(MESSAGE) + .taskId(inputRequiredTaskId) + .contextId("test-context") + .parts(new TextPart("Initial request")) + .build(); + + CountDownLatch initialLatch = new CountDownLatch(1); + AtomicReference initialState = new AtomicReference<>(); + AtomicBoolean initialUnexpectedEvent = new AtomicBoolean(false); + + BiConsumer initialConsumer = (event, agentCard) -> { + if (event instanceof TaskEvent te) { + initialState.set(te.getTask().status().state()); + initialLatch.countDown(); + } else { + initialUnexpectedEvent.set(true); + } + }; + + // Send initial message - task will go to INPUT_REQUIRED state + getNonStreamingClient().sendMessage(initialMessage, List.of(initialConsumer), null); + assertTrue(initialLatch.await(10, TimeUnit.SECONDS)); + assertFalse(initialUnexpectedEvent.get()); + assertEquals(TaskState.INPUT_REQUIRED, initialState.get()); + + // 2. Send input message - AgentExecutor will complete the task + Message inputMessage = Message.builder(MESSAGE) + .taskId(inputRequiredTaskId) + .contextId("test-context") + .parts(new TextPart("User input")) + .build(); + + CountDownLatch completionLatch = new CountDownLatch(1); + AtomicReference completedState = new AtomicReference<>(); + AtomicBoolean completionUnexpectedEvent = new AtomicBoolean(false); + + BiConsumer completionConsumer = (event, agentCard) -> { + if (event instanceof TaskEvent te) { + completedState.set(te.getTask().status().state()); + completionLatch.countDown(); + } else { + completionUnexpectedEvent.set(true); + } + }; + + // Send input - task will be completed + getNonStreamingClient().sendMessage(inputMessage, List.of(completionConsumer), null); + assertTrue(completionLatch.await(10, TimeUnit.SECONDS)); + assertFalse(completionUnexpectedEvent.get()); + assertEquals(TaskState.COMPLETED, completedState.get()); + + } finally { + deleteTaskInTaskStore(inputRequiredTaskId); + } + } + @Test public void testMalformedJSONRPCRequest() { // skip this test for non-JSONRPC transports 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 8b03a68f4..364d2275f 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 @@ -10,6 +10,9 @@ import io.a2a.server.events.EventQueue; import io.a2a.server.tasks.TaskUpdater; import io.a2a.spec.A2AError; +import io.a2a.spec.InvalidParamsError; +import io.a2a.spec.Message; +import io.a2a.spec.Part; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; import io.quarkus.arc.profile.IfBuildProfile; @@ -43,6 +46,28 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr } } + // Special handling for input-required test + if (taskId != null && taskId.startsWith("input-required-test")) { + // First call: context.getTask() == null (new task) + if (context.getTask() == null) { + updater.startWork(); + updater.requiresInput(updater.newAgentMessage( + List.of(new TextPart("Please provide additional information")), + context.getMessage().metadata())); + // Return immediately - queue stays open because task is in INPUT_REQUIRED state + return; + } else { + String input = extractTextFromMessage(context.getMessage()); + if(! "User input".equals(input)) { + throw new InvalidParamsError("We didn't get the expected input"); + } + // Second call: context.getTask() != null (input provided) + updater.startWork(); + updater.complete(); + return; + } + } + if (context.getTaskId().equals("task-not-supported-123")) { eventQueue.enqueueEvent(new UnsupportedOperationError()); } @@ -60,4 +85,21 @@ public void cancel(RequestContext context, EventQueue eventQueue) throws A2AErro } }; } + + /** + * Extract the content of TextPart in a message to create a single String. + * @param message the message containing the TextPart. + * @return a String aggreagating all the TextPart contents of the message. + */ + private String extractTextFromMessage(final Message message) { + final StringBuilder textBuilder = new StringBuilder(); + if (message.parts() != null) { + for (final Part part : message.parts()) { + if (part instanceof TextPart textPart) { + textBuilder.append(textPart.text()); + } + } + } + return textBuilder.toString(); + } } From ae3e01b69f2c446919f47e611fa02b421ddd9b98 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 26 Jan 2026 08:02:08 +0000 Subject: [PATCH 007/192] chore: Centralise PageToken parsing (#601) fixes: #597 --------- Signed-off-by: Emmanuel Hugonnet Co-authored-by: Emmanuel Hugonnet --- ...paDatabasePushNotificationConfigStore.java | 33 ++-- ...otificationConfigStoreIntegrationTest.java | 16 +- .../database/jpa/JpaDatabaseTaskStore.java | 25 +-- .../a2a/server/tasks/InMemoryTaskStore.java | 82 ++++----- spec/src/main/java/io/a2a/util/PageToken.java | 68 ++++++++ .../test/java/io/a2a/util/PageTokenTest.java | 161 ++++++++++++++++++ 6 files changed, 285 insertions(+), 100 deletions(-) create mode 100644 spec/src/main/java/io/a2a/util/PageToken.java create mode 100644 spec/src/test/java/io/a2a/util/PageTokenTest.java 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 1df8b57f3..36245e277 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 @@ -15,6 +15,7 @@ import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.util.PageToken; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; import java.util.stream.Collectors; @@ -79,18 +80,17 @@ public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConf String taskId = params.id(); LOGGER.debug("Retrieving PushNotificationConfigs for Task '{}' with params: pageSize={}, pageToken={}", taskId, params.pageSize(), params.pageToken()); + + // Parse pageToken once at the beginning + PageToken pageToken = PageToken.fromString(params.pageToken()); + try { StringBuilder queryBuilder = new StringBuilder("SELECT c FROM JpaPushNotificationConfig c WHERE c.id.taskId = :taskId"); - if (params.pageToken() != null && !params.pageToken().isEmpty()) { - String[] tokenParts = params.pageToken().split(":", 2); - if (tokenParts.length == 2) { + if (pageToken != null) { // Keyset pagination: get tasks where timestamp < tokenTimestamp OR (timestamp = tokenTimestamp AND id > tokenId) // All tasks have timestamps (TaskStatus canonical constructor ensures this) queryBuilder.append(" AND (COALESCE(c.createdAt, :nullSentinel) < :tokenTimestamp OR (COALESCE(c.createdAt, :nullSentinel) = :tokenTimestamp AND c.id.configId > :tokenId))"); - } else { - // Based on the comments in the test case, if the pageToken is invalid start from the beginning. - } } queryBuilder.append(" ORDER BY COALESCE(c.createdAt, :nullSentinel) DESC, c.id.configId ASC"); @@ -99,22 +99,9 @@ public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConf query.setParameter("taskId", taskId); query.setParameter("nullSentinel", NULL_TIMESTAMP_SENTINEL); - if (params.pageToken() != null && !params.pageToken().isEmpty()) { - String[] tokenParts = params.pageToken().split(":", 2); - if (tokenParts.length == 2) { - try { - long timestampMillis = Long.parseLong(tokenParts[0]); - String tokenId = tokenParts[1]; - - Instant tokenTimestamp = Instant.ofEpochMilli(timestampMillis); - query.setParameter("tokenTimestamp", tokenTimestamp); - query.setParameter("tokenId", tokenId); - } catch (NumberFormatException e) { - // Malformed timestamp in pageToken - throw new io.a2a.spec.InvalidParamsError(null, - "Invalid pageToken format: timestamp must be numeric milliseconds", null); - } - } + if (pageToken != null) { + query.setParameter("tokenTimestamp", pageToken.timestamp()); + query.setParameter("tokenId", pageToken.id()); } int pageSize = params.getEffectivePageSize(); @@ -128,7 +115,7 @@ public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConf jpaConfigsPage = jpaConfigsPage.subList(0, pageSize); JpaPushNotificationConfig lastConfig = jpaConfigsPage.get(jpaConfigsPage.size() - 1); Instant timestamp = lastConfig.getCreatedAt() != null ? lastConfig.getCreatedAt() : NULL_TIMESTAMP_SENTINEL; - nextPageToken = timestamp.toEpochMilli() + ":" + lastConfig.getId().getConfigId(); + nextPageToken = new PageToken(timestamp, lastConfig.getId().getConfigId()).toString(); } List configs = jpaConfigsPage.stream() 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 a31beb631..cca31e536 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 @@ -352,15 +352,12 @@ public void testPaginationWithInvalidToken() { // Create 5 configs createSamples(taskId, 5); - // Request with invalid pageToken - JPA implementation behavior is to start from beginning + // Request with invalid pageToken - should throw InvalidParamsError for invalid format ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams( taskId, 2, "invalid_token_that_does_not_exist", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - assertNotNull(result); - // When token is not found, implementation starts from beginning - assertEquals(2, result.configs().size(), "Should return first page when token is not found"); - assertNotNull(result.nextPageToken(), "Should have nextPageToken since more items exist"); + assertThrows(io.a2a.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), + "Should throw InvalidParamsError for invalid pageToken format (missing colon)"); } @Test @@ -428,12 +425,9 @@ public void testPageTokenWithMissingColon() { ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 2, "123456789cfg1", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - assertNotNull(result); - assertEquals(2, result.configs().size(), - "Should return first page when pageToken format is invalid (missing colon)"); - assertNotNull(result.nextPageToken(), "Should have nextPageToken since more items exist"); + assertThrows(io.a2a.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), + "Should throw InvalidParamsError for invalid pageToken format (missing colon)"); } @Test 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 0db0e1548..b65b71650 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 @@ -25,6 +25,7 @@ import io.a2a.spec.Artifact; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; +import io.a2a.util.PageToken; import io.a2a.spec.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -227,23 +228,9 @@ public ListTasksResult list(ListTasksParams params) { params.contextId(), params.status(), params.pageSize(), params.pageToken()); // Parse pageToken once at the beginning - Instant tokenTimestamp = null; - String tokenId = null; - if (params.pageToken() != null && !params.pageToken().isEmpty()) { - String[] tokenParts = params.pageToken().split(":", 2); - if (tokenParts.length == 2) { - try { - long timestampMillis = Long.parseLong(tokenParts[0]); - tokenId = tokenParts[1]; - tokenTimestamp = Instant.ofEpochMilli(timestampMillis); - } catch (NumberFormatException e) { - throw new io.a2a.spec.InvalidParamsError(null, - "Invalid pageToken format: timestamp must be numeric milliseconds", null); - } - } else { - throw new io.a2a.spec.InvalidParamsError(null, "Invalid pageToken format: expected 'timestamp:id'", null); - } - } + PageToken pageToken = PageToken.fromString(params.pageToken()); + Instant tokenTimestamp = pageToken != null ? pageToken.timestamp() : null; + String tokenId = pageToken != null ? pageToken.id() : null; // Build dynamic JPQL query with WHERE clauses for filtering StringBuilder queryBuilder = new StringBuilder("SELECT t FROM JpaTask t WHERE 1=1"); @@ -337,8 +324,8 @@ public ListTasksResult list(ListTasksParams params) { if (hasMore && !tasks.isEmpty()) { Task lastTask = tasks.get(tasks.size() - 1); // All tasks have timestamps (TaskStatus canonical constructor ensures this) - long timestampMillis = lastTask.status().timestamp().toInstant().toEpochMilli(); - nextPageToken = timestampMillis + ":" + lastTask.id(); + Instant timestamp = lastTask.status().timestamp().toInstant(); + nextPageToken = new PageToken(timestamp, lastTask.id()).toString(); } // Apply post-processing transformations (history limiting, artifact removal) 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 8a3d72133..1e3ae1206 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 @@ -11,6 +11,7 @@ import io.a2a.spec.Artifact; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; +import io.a2a.util.PageToken; import io.a2a.spec.Task; import org.jspecify.annotations.Nullable; @@ -73,54 +74,41 @@ public ListTasksResult list(ListTasksParams params) { // Handle page token using keyset pagination (format: "timestamp_millis:taskId") // Use binary search to efficiently find the first task after the pageToken position (O(log N)) - if (params.pageToken() != null && !params.pageToken().isEmpty()) { - String[] tokenParts = params.pageToken().split(":", 2); - if (tokenParts.length == 2) { - try { - long tokenTimestampMillis = Long.parseLong(tokenParts[0]); - java.time.Instant tokenTimestamp = java.time.Instant.ofEpochMilli(tokenTimestampMillis); - String tokenId = tokenParts[1]; - - // Binary search for first task where: timestamp < tokenTimestamp OR (timestamp == tokenTimestamp AND id > tokenId) - // Since list is sorted (timestamp DESC, id ASC), we search for the insertion point - int left = 0; - int right = allFilteredTasks.size(); - - while (left < right) { - int mid = left + (right - left) / 2; - Task task = allFilteredTasks.get(mid); - - java.time.Instant taskTimestamp = (task.status() != null && task.status().timestamp() != null) - ? task.status().timestamp().toInstant().truncatedTo(java.time.temporal.ChronoUnit.MILLIS) - : null; - - if (taskTimestamp == null) { - // Task with null timestamp is always "before" a token with a timestamp, as they are sorted last. - // So, we search in the right half. - left = mid + 1; - } else { - int timestampCompare = taskTimestamp.compareTo(tokenTimestamp); - - if (timestampCompare < 0 || (timestampCompare == 0 && task.id().compareTo(tokenId) > 0)) { - // This task is after the token, search left half - right = mid; - } else { - // This task is before or equal to token, search right half - left = mid + 1; - } - } + PageToken pageToken = PageToken.fromString(params.pageToken()); + if (pageToken != null) { + java.time.Instant tokenTimestamp = pageToken.timestamp(); + String tokenId = pageToken.id(); + + // Binary search for first task where: timestamp < tokenTimestamp OR (timestamp == tokenTimestamp AND id > tokenId) + // Since list is sorted (timestamp DESC, id ASC), we search for the insertion point + int left = 0; + int right = allFilteredTasks.size(); + + while (left < right) { + int mid = left + (right - left) / 2; + Task task = allFilteredTasks.get(mid); + + java.time.Instant taskTimestamp = (task.status() != null && task.status().timestamp() != null) + ? task.status().timestamp().toInstant().truncatedTo(java.time.temporal.ChronoUnit.MILLIS) + : null; + + if (taskTimestamp == null) { + // Task with null timestamp is always "before" a token with a timestamp, as they are sorted last. + // So, we search in the right half. + left = mid + 1; + } else { + int timestampCompare = taskTimestamp.compareTo(tokenTimestamp); + + if (timestampCompare < 0 || (timestampCompare == 0 && task.id().compareTo(tokenId) > 0)) { + // This task is after the token, search left half + right = mid; + } else { + // This task is before or equal to token, search right half + left = mid + 1; } - startIndex = left; - } catch (NumberFormatException e) { - // Malformed timestamp in pageToken - throw new io.a2a.spec.InvalidParamsError(null, - "Invalid pageToken format: timestamp must be numeric milliseconds", null); } - } else { - // Legacy ID-only pageToken format is not supported with timestamp-based sorting - // Throw error to prevent incorrect pagination results - throw new io.a2a.spec.InvalidParamsError(null, "Invalid pageToken format: expected 'timestamp:id'", null); } + startIndex = left; } // Get the page of tasks @@ -132,8 +120,8 @@ public ListTasksResult list(ListTasksParams params) { if (endIndex < allFilteredTasks.size()) { Task lastTask = allFilteredTasks.get(endIndex - 1); // All tasks have timestamps (TaskStatus canonical constructor ensures this) - long timestampMillis = lastTask.status().timestamp().toInstant().toEpochMilli(); - nextPageToken = timestampMillis + ":" + lastTask.id(); + java.time.Instant timestamp = lastTask.status().timestamp().toInstant(); + nextPageToken = new PageToken(timestamp, lastTask.id()).toString(); } // Transform tasks: limit history and optionally remove artifacts diff --git a/spec/src/main/java/io/a2a/util/PageToken.java b/spec/src/main/java/io/a2a/util/PageToken.java new file mode 100644 index 000000000..c703a903a --- /dev/null +++ b/spec/src/main/java/io/a2a/util/PageToken.java @@ -0,0 +1,68 @@ +package io.a2a.util; + +import java.time.Instant; + +import io.a2a.spec.InvalidParamsError; +import org.jspecify.annotations.Nullable; + +/** + * Represents a pagination token for keyset-based pagination. + *

    + * PageTokens use the format {@code "timestamp_millis:id"} where: + *

      + *
    • {@code timestamp_millis} - Unix timestamp in milliseconds (numeric)
    • + *
    • {@code id} - The entity identifier (String)
    • + *
    + * This format enables efficient keyset pagination by allowing queries to resume + * at a specific point in a timestamp-sorted, ID-secondary-sorted result set. + * + * @param timestamp The timestamp component of the page token + * @param id The identifier component of the page token + */ +public record PageToken(Instant timestamp, String id) { + + /** + * Parses a pageToken string into a PageToken record. + *

    + * Expected format: {@code "timestamp_millis:id"} + * + * @param tokenStr The pageToken string to parse, may be null or empty + * @return A PageToken instance, or null if tokenStr is null or empty + * @throws InvalidParamsError if the token format is invalid or timestamp is not numeric + */ + public static @Nullable PageToken fromString(@Nullable String tokenStr) { + if (tokenStr == null || tokenStr.isEmpty()) { + return null; + } + + String[] tokenParts = tokenStr.split(":", 2); + if (tokenParts.length != 2) { + throw new InvalidParamsError(null, + "Invalid pageToken format: expected 'timestamp:id'", null); + } + + try { + long timestampMillis = Long.parseLong(tokenParts[0]); + String id = tokenParts[1]; + if (id.isEmpty()) { + throw new InvalidParamsError(null, "Invalid pageToken format: id part cannot be empty", null); + } + return new PageToken(Instant.ofEpochMilli(timestampMillis), id); + } catch (NumberFormatException e) { + throw new InvalidParamsError(null, + "Invalid pageToken format: timestamp must be numeric milliseconds", null); + } + } + + /** + * Converts this PageToken to its string representation. + *

    + * Format: {@code "timestamp_millis:id"} + * + * @return The pageToken string + */ + @Override + public String toString() { + return timestamp.toEpochMilli() + ":" + id; + } +} diff --git a/spec/src/test/java/io/a2a/util/PageTokenTest.java b/spec/src/test/java/io/a2a/util/PageTokenTest.java new file mode 100644 index 000000000..aef9c8192 --- /dev/null +++ b/spec/src/test/java/io/a2a/util/PageTokenTest.java @@ -0,0 +1,161 @@ +package io.a2a.util; + +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 static org.junit.jupiter.api.Assertions.assertThrows; + +import java.time.Instant; +import java.util.stream.Stream; + +import io.a2a.spec.InvalidParamsError; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; + +/** + * Unit tests for {@link PageToken}. + */ +class PageTokenTest { + + // ========== Valid Token Parsing Tests ========== + + /** + * Provides test data for valid token parsing tests. + * Format: tokenString, expectedTimestampMillis, expectedId + */ + static Stream validTokens() { + return Stream.of( + Arguments.of("1640000000000:user123", 1640000000000L, "user123"), + Arguments.of("1640000000000:user:123:extra", 1640000000000L, "user:123:extra"), + Arguments.of("0:user123", 0L, "user123"), + Arguments.of("-1000:user123", -1000L, "user123"), + Arguments.of(Long.MAX_VALUE + ":user123", Long.MAX_VALUE, "user123"), + Arguments.of(Long.MIN_VALUE + ":user123", Long.MIN_VALUE, "user123"), + Arguments.of("1640000000000:" + "a".repeat(1000), 1640000000000L, "a".repeat(1000)), + Arguments.of("1640000000000:user-123_test@example.com", 1640000000000L, "user-123_test@example.com") + ); + } + + /** + * Verifies that various valid pageToken strings are correctly parsed into PageToken objects. + */ + @ParameterizedTest + @MethodSource("validTokens") + void testFromString_validTokens_parseCorrectly(String tokenStr, long expectedTimestampMillis, String expectedId) { + PageToken token = PageToken.fromString(tokenStr); + + assertNotNull(token); + assertEquals(Instant.ofEpochMilli(expectedTimestampMillis), token.timestamp()); + assertEquals(expectedId, token.id()); + } + + // ========== Null and Empty Input Tests ========== + + /** + * Verifies that null or empty strings return null instead of throwing an exception. + */ + @ParameterizedTest + @NullAndEmptySource + void testFromString_nullOrEmpty_returnsNull(String tokenStr) { + PageToken token = PageToken.fromString(tokenStr); + assertNull(token); + } + + // ========== Invalid Format Tests ========== + + /** + * Provides test data for invalid token format tests. + * Format: tokenString, expectedErrorMessage + */ + static Stream invalidTokenFormats() { + return Stream.of( + Arguments.of("1640000000000user123", "Invalid pageToken format: expected 'timestamp:id'"), + Arguments.of("1640000000000", "Invalid pageToken format: expected 'timestamp:id'"), + Arguments.of("1640000000000:", "Invalid pageToken format: id part cannot be empty"), + Arguments.of(":", "Invalid pageToken format: timestamp must be numeric milliseconds"), + Arguments.of("notanumber:user123", "Invalid pageToken format: timestamp must be numeric milliseconds"), + Arguments.of("1640000000.123:user123", "Invalid pageToken format: timestamp must be numeric milliseconds"), + Arguments.of("1640 000 000:user123", "Invalid pageToken format: timestamp must be numeric milliseconds") + ); + } + + /** + * Verifies that various invalid token formats throw InvalidParamsError with appropriate messages. + */ + @ParameterizedTest + @MethodSource("invalidTokenFormats") + void testFromString_invalidFormats_throwsInvalidParamsError(String tokenStr, String expectedErrorMessage) { + InvalidParamsError ex = assertThrows(InvalidParamsError.class, () -> { + PageToken.fromString(tokenStr); + }); + assertNotNull(ex.getMessage()); + assertEquals(expectedErrorMessage, ex.getMessage()); + } + + // ========== toString Tests ========== + + /** + * Provides test data for toString tests. + * Format: timestampMillis, id, expectedString + */ + static Stream toStringTestData() { + return Stream.of( + Arguments.of(1640000000000L, "user123", "1640000000000:user123"), + Arguments.of(1640000000000L, "user:123", "1640000000000:user:123"), + Arguments.of(0L, "user123", "0:user123"), + Arguments.of(-1000L, "user123", "-1000:user123") + ); + } + + /** + * Verifies that toString formats PageTokens correctly as "timestamp_millis:id". + */ + @ParameterizedTest + @MethodSource("toStringTestData") + void testToString_formatsCorrectly(long timestampMillis, String id, String expectedString) { + PageToken token = new PageToken(Instant.ofEpochMilli(timestampMillis), id); + String result = token.toString(); + assertEquals(expectedString, result); + } + + // ========== Round-Trip Conversion Tests ========== + + /** + * Provides test data for round-trip conversion tests. + */ + static Stream roundTripTokens() { + return Stream.of( + "1640000000000:user123", + "1640000000000:user:123:extra", + "0:user123", + "-1000:user123" + ); + } + + /** + * Verifies that converting from string to PageToken and back to string preserves the original value. + */ + @ParameterizedTest + @MethodSource("roundTripTokens") + void testRoundTrip_fromStringToString_preservesValue(String original) { + PageToken token = PageToken.fromString(original); + String result = token.toString(); + assertEquals(original, result); + } + + /** + * Verifies that converting from PageToken to string and back to PageToken preserves the original value. + */ + @Test + void testRoundTrip_toStringFromString_preservesValue() { + PageToken original = new PageToken(Instant.ofEpochMilli(1640000000000L), "user123"); + String tokenStr = original.toString(); + PageToken result = PageToken.fromString(tokenStr); + + assertEquals(original.timestamp(), result.timestamp()); + assertEquals(original.id(), result.id()); + } +} From 659df81b28f49218df55d766c87cc37a4c72bc94 Mon Sep 17 00:00:00 2001 From: Harsha Ramesh Date: Mon, 26 Jan 2026 02:56:28 -0800 Subject: [PATCH 008/192] fix: add missing META-INF/beans.xml to microprofile-config integration (#589) The microprofile-config integration was missing the beans.xml marker file, which prevented the configuration from being loaded as an alternative bean in Quarkus applications. This file is required for CDI bean discovery. Fixes #587 --- .../src/main/resources/META-INF/beans.xml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 integrations/microprofile-config/src/main/resources/META-INF/beans.xml diff --git a/integrations/microprofile-config/src/main/resources/META-INF/beans.xml b/integrations/microprofile-config/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..ffc8abb42 --- /dev/null +++ b/integrations/microprofile-config/src/main/resources/META-INF/beans.xml @@ -0,0 +1,6 @@ + + + From 21c15d647156d14481be538517df21a7a1d78a48 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 4 Feb 2026 17:30:25 +0000 Subject: [PATCH 009/192] feat: Implement MainEventBus architecture for event queue processing (#611) Introduces centralized event processing with single background thread to guarantee event persistence before client visibility and eliminate race conditions in concurrent task updates. Key Changes: - MainEventBus: Central LinkedBlockingDeque for all events - MainEventBusProcessor: Single background thread ensuring serial processing (TaskStore.save() -> PushNotificationSender.send() -> distributeToChildren()) - Two-level queue cleanup protection via TaskStateProvider.isTaskFinalized() to prevent premature cleanup for fire-and-forget tasks - Deterministic blocking calls: waitForTaskFinalization() ensures TaskStore persistence completes before returning to client - Streaming closure: agentCompleted flag via EnhancedRunnable.DoneCallback for graceful drain when agent completes - SseFormatter utility: Framework-agnostic SSE formatting in server-common - Executor pool improvements: Bounded EventConsumerExecutor pool (size 15) prevents exhaustion during high concurrency Null TaskId Support: - QueueManager.switchKey(): Atomic key switching from temp to real task ID - Non-streaming path now handles null taskId like streaming (generates temp UUID) - Cloud deployment test reverted to use A2A.toUserMessage() (valid null taskId case) - No duplicate queue map entries, clean queue lifecycle management Additional Fixes: - Blocking calls always wait for task finalization (not just final events) - RequestContext uses message.taskId() for new tasks when task is null - PostgreSQL pod deployment: Wait loop for pod creation before readiness check - Javadoc: Remove invalid

    tags around

     blocks
    - ServerCallContext: EventConsumer cancellation via closeHandler for
    graceful disconnect
    - Gemini feedback improvements
    
    Architecture Impact:
    - All events flow through MainEventBus before distribution to
    ChildQueues
    - Clients never see unpersisted events (persistence-before-distribution)
    - Fire-and-forget tasks supported: queues stay open for non-final states
    - Late resubscription enabled: queues persist until task finalization
    - Null taskId messages supported: temp IDs transition to real IDs via
    switchKey
    - Test synchronization: MainEventBusProcessorCallback for deterministic
    testing
    
    ---------
    
    Signed-off-by: Emmanuel Hugonnet 
    Co-authored-by: Emmanuel Hugonnet 
    ---
     .../jsonrpc/sse/SSEEventListener.java         |   20 +-
     .../rest/sse/RestSSEEventListener.java        |   24 +-
     examples/cloud-deployment/scripts/deploy.sh   |   16 +
     .../common/events/TaskFinalizedEvent.java     |   14 +-
     ...paDatabasePushNotificationConfigStore.java |    1 +
     .../core/ReplicatedEventQueueItem.java        |   10 +
     .../core/ReplicatedQueueManager.java          |  103 +-
     .../core/ReplicatedQueueManagerTest.java      |  345 ++++--
     .../io/a2a/server/events/EventQueueUtil.java  |   11 +
     .../src/main/resources/application.properties |    2 +
     .../src/main/resources/application.properties |    2 +
     .../MultiInstanceReplicationTest.java         |   97 +-
     .../KafkaReplicationIntegrationTest.java      |   12 +
     .../database/jpa/JpaDatabaseTaskStore.java    |   16 +-
     .../jpa/JpaDatabaseTaskStoreTest.java         |   64 +-
     .../server/apps/quarkus/A2AServerRoutes.java  |  120 +-
     .../src/test/resources/application.properties |    5 +
     .../server/rest/quarkus/A2AServerRoutes.java  |  144 ++-
     .../java/io/a2a/server/ServerCallContext.java |   61 +
     .../io/a2a/server/events/EventConsumer.java   |   80 ++
     .../java/io/a2a/server/events/EventQueue.java |  427 ++++---
     .../server/events/InMemoryQueueManager.java   |   32 +-
     .../io/a2a/server/events/MainEventBus.java    |   42 +
     .../server/events/MainEventBusContext.java    |   11 +
     .../server/events/MainEventBusProcessor.java  |  386 +++++++
     .../events/MainEventBusProcessorCallback.java |   66 ++
     .../MainEventBusProcessorInitializer.java     |   43 +
     .../io/a2a/server/events/QueueManager.java    |   26 +-
     .../DefaultRequestHandler.java                |  515 +++++----
     .../a2a/server/tasks/InMemoryTaskStore.java   |    3 +-
     .../io/a2a/server/tasks/ResultAggregator.java |  128 ++-
     .../java/io/a2a/server/tasks/TaskManager.java |   38 +-
     .../java/io/a2a/server/tasks/TaskStore.java   |    5 +-
     .../util/async/AsyncExecutorProducer.java     |   57 +-
     .../async/EventConsumerExecutorProducer.java  |   93 ++
     .../io/a2a/server/util/sse/SseFormatter.java  |  136 +++
     .../io/a2a/server/util/sse/package-info.java  |   11 +
     .../META-INF/a2a-defaults.properties          |    4 +
     .../a2a/server/events/EventConsumerTest.java  |  100 +-
     .../io/a2a/server/events/EventQueueTest.java  |  227 ++--
     .../io/a2a/server/events/EventQueueUtil.java  |   37 +-
     .../events/InMemoryQueueManagerTest.java      |   34 +-
     .../AbstractA2ARequestHandlerTest.java        |   23 +-
     .../DefaultRequestHandlerTest.java            | 1001 -----------------
     .../server/tasks/InMemoryTaskStoreTest.java   |   49 -
     .../server/tasks/ResultAggregatorTest.java    |   81 +-
     .../io/a2a/server/tasks/TaskManagerTest.java  |   91 +-
     .../io/a2a/server/tasks/TaskUpdaterTest.java  |   58 +-
     tck/src/main/resources/application.properties |    1 +
     .../apps/common/AbstractA2AServerTest.java    |   63 ++
     .../a2a/server/apps/common/TestUtilsBean.java |    2 +-
     .../transport/grpc/handler/GrpcHandler.java   |   24 +-
     .../grpc/handler/GrpcHandlerTest.java         |   83 +-
     .../jsonrpc/handler/JSONRPCHandlerTest.java   |  416 ++++---
     .../transport/rest/handler/RestHandler.java   |   15 +
     .../rest/handler/RestHandlerTest.java         |   20 +-
     56 files changed, 3284 insertions(+), 2211 deletions(-)
     create mode 100644 extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java
     create mode 100644 server-common/src/main/java/io/a2a/server/events/MainEventBus.java
     create mode 100644 server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java
     create mode 100644 server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java
     create mode 100644 server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java
     create mode 100644 server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java
     create mode 100644 server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java
     create mode 100644 server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java
     create mode 100644 server-common/src/main/java/io/a2a/server/util/sse/package-info.java
    
    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 33025ed5e..3a24f5145 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
    @@ -10,6 +10,8 @@
     import io.a2a.jsonrpc.common.json.JsonProcessingException;
     import io.a2a.spec.A2AError;
     import io.a2a.spec.StreamingEventKind;
    +import io.a2a.spec.Task;
    +import io.a2a.spec.TaskState;
     import io.a2a.spec.TaskStatusUpdateEvent;
     import org.jspecify.annotations.Nullable;
     
    @@ -64,11 +66,23 @@ private void handleMessage(String message, @Nullable Future future) {
     
                 StreamingEventKind event = ProtoUtils.FromProto.streamingEventKind(response);
                 eventHandler.accept(event);
    -            if (event instanceof TaskStatusUpdateEvent && ((TaskStatusUpdateEvent) event).isFinal()) {
    -                if (future != null) {
    -                    future.cancel(true); // close SSE channel
    +
    +            // Client-side auto-close on final events to prevent connection leaks
    +            // Handles both TaskStatusUpdateEvent and Task objects with final states
    +            // This covers late subscriptions to completed tasks and ensures no connection leaks
    +            boolean shouldClose = false;
    +            if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) {
    +                shouldClose = true;
    +            } else if (event instanceof Task task) {
    +                TaskState state = task.status().state();
    +                if (state.isFinal()) {
    +                    shouldClose = true;
                     }
                 }
    +
    +            if (shouldClose && future != null) {
    +                future.cancel(true); // close SSE channel
    +            }
             } catch (A2AError error) {
                 if (errorHandler != null) {
                     errorHandler.accept(error);
    diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java
    index ec74d2fbc..85e604da3 100644
    --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java
    +++ b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java
    @@ -10,6 +10,9 @@
     import io.a2a.grpc.StreamResponse;
     import io.a2a.grpc.utils.ProtoUtils;
     import io.a2a.spec.StreamingEventKind;
    +import io.a2a.spec.Task;
    +import io.a2a.spec.TaskState;
    +import io.a2a.spec.TaskStatusUpdateEvent;
     import org.jspecify.annotations.Nullable;
     
     public class RestSSEEventListener {
    @@ -29,7 +32,7 @@ public void onMessage(String message, @Nullable Future completableFuture)
                 log.fine("Streaming message received: " + message);
                 io.a2a.grpc.StreamResponse.Builder builder = io.a2a.grpc.StreamResponse.newBuilder();
                 JsonFormat.parser().merge(message, builder);
    -            handleMessage(builder.build());
    +            handleMessage(builder.build(), completableFuture);
             } catch (InvalidProtocolBufferException e) {
                 errorHandler.accept(RestErrorMapper.mapRestError(message, 500));
             }
    @@ -44,7 +47,7 @@ public void onError(Throwable throwable, @Nullable Future future) {
             }
         }
     
    -    private void handleMessage(StreamResponse response) {
    +    private void handleMessage(StreamResponse response, @Nullable Future future) {
             StreamingEventKind event;
             switch (response.getPayloadCase()) {
                 case MESSAGE ->
    @@ -62,6 +65,23 @@ private void handleMessage(StreamResponse response) {
                 }
             }
             eventHandler.accept(event);
    +
    +        // Client-side auto-close on final events to prevent connection leaks
    +        // Handles both TaskStatusUpdateEvent and Task objects with final states
    +        // This covers late subscriptions to completed tasks and ensures no connection leaks
    +        boolean shouldClose = false;
    +        if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) {
    +            shouldClose = true;
    +        } else if (event instanceof Task task) {
    +            TaskState state = task.status().state();
    +            if (state.isFinal()) {
    +                shouldClose = true;
    +            }
    +        }
    +
    +        if (shouldClose && future != null) {
    +            future.cancel(true); // close SSE channel
    +        }
         }
     
     }
    diff --git a/examples/cloud-deployment/scripts/deploy.sh b/examples/cloud-deployment/scripts/deploy.sh
    index e267f3302..fff2a6061 100755
    --- a/examples/cloud-deployment/scripts/deploy.sh
    +++ b/examples/cloud-deployment/scripts/deploy.sh
    @@ -212,6 +212,22 @@ echo ""
     echo "Deploying PostgreSQL..."
     kubectl apply -f ../k8s/01-postgres.yaml
     echo "Waiting for PostgreSQL to be ready..."
    +
    +# Wait for pod to be created (StatefulSet takes time to create pod)
    +for i in {1..30}; do
    +    if kubectl get pod -l app=postgres -n a2a-demo 2>/dev/null | grep -q postgres; then
    +        echo "PostgreSQL pod found, waiting for ready state..."
    +        break
    +    fi
    +    if [ $i -eq 30 ]; then
    +        echo -e "${RED}ERROR: PostgreSQL pod not created after 30 seconds${NC}"
    +        kubectl get statefulset -n a2a-demo
    +        exit 1
    +    fi
    +    sleep 1
    +done
    +
    +# Now wait for pod to be ready
     kubectl wait --for=condition=Ready pod -l app=postgres -n a2a-demo --timeout=120s
     echo -e "${GREEN}✓ PostgreSQL deployed${NC}"
     
    diff --git a/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java b/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java
    index 8c5f59348..0c35bad7a 100644
    --- a/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java
    +++ b/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java
    @@ -5,22 +5,28 @@
      * This event is fired AFTER the database transaction commits, making it safe for downstream
      * components to assume the task is durably stored.
      *
    - * 

    Used by the replicated queue manager to send poison pill events after ensuring - * the final task state is committed to the database, eliminating race conditions. + *

    Used by the replicated queue manager to send the final task state before the poison pill, + * ensuring correct event ordering across instances and eliminating race conditions. */ public class TaskFinalizedEvent { private final String taskId; + private final Object task; // Task type from io.a2a.spec - using Object to avoid dependency - public TaskFinalizedEvent(String taskId) { + public TaskFinalizedEvent(String taskId, Object task) { this.taskId = taskId; + this.task = task; } public String getTaskId() { return taskId; } + public Object getTask() { + return task; + } + @Override public String toString() { - return "TaskFinalizedEvent{taskId='" + taskId + "'}"; + return "TaskFinalizedEvent{taskId='" + taskId + "', task=" + task + "}"; } } 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 36245e277..5049bc9a4 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 @@ -164,4 +164,5 @@ public void deleteInfo(String taskId, String configId) { taskId, configId); } } + } 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 87c10fb4e..206e07f03 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 @@ -149,6 +149,16 @@ public void setClosedEvent(boolean closedEvent) { } } + /** + * Check if this event is a Task event. + * Task events should always be processed even for inactive tasks, + * as they carry the final task state. + * @return true if this is a Task event + */ + public boolean isTaskEvent() { + return event instanceof io.a2a.spec.Task; + } + @Override public String toString() { return "ReplicatedEventQueueItem{" + 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 586ab11a7..44dfbe427 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 @@ -13,8 +13,10 @@ import io.a2a.server.events.EventQueueFactory; import io.a2a.server.events.EventQueueItem; import io.a2a.server.events.InMemoryQueueManager; +import io.a2a.server.events.MainEventBus; import io.a2a.server.events.QueueManager; import io.a2a.server.tasks.TaskStateProvider; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,10 +47,12 @@ protected ReplicatedQueueManager() { } @Inject - public ReplicatedQueueManager(ReplicationStrategy replicationStrategy, TaskStateProvider taskStateProvider) { + public ReplicatedQueueManager(ReplicationStrategy replicationStrategy, + TaskStateProvider taskStateProvider, + MainEventBus mainEventBus) { this.replicationStrategy = replicationStrategy; this.taskStateProvider = taskStateProvider; - this.delegate = new InMemoryQueueManager(new ReplicatingEventQueueFactory(), taskStateProvider); + this.delegate = new InMemoryQueueManager(new ReplicatingEventQueueFactory(), taskStateProvider, mainEventBus); } @@ -77,8 +81,7 @@ public void close(String taskId) { @Override public EventQueue createOrTap(String taskId) { - EventQueue queue = delegate.createOrTap(taskId); - return queue; + return delegate.createOrTap(taskId); } @Override @@ -87,9 +90,11 @@ public void awaitQueuePollerStart(EventQueue eventQueue) throws InterruptedExcep } public void onReplicatedEvent(@Observes ReplicatedEventQueueItem replicatedEvent) { - // Check if task is still active before processing replicated event (unless it's a QueueClosedEvent) - // QueueClosedEvent should always be processed to terminate streams, even for inactive tasks + // Check if task is still active before processing replicated event + // Always allow QueueClosedEvent and Task events (they carry final state) + // Skip other event types for inactive tasks to prevent queue creation for expired tasks if (!replicatedEvent.isClosedEvent() + && !replicatedEvent.isTaskEvent() && !taskStateProvider.isTaskActive(replicatedEvent.getTaskId())) { // Task is no longer active - skip processing this replicated event // This prevents creating queues for tasks that have been finalized beyond the grace period @@ -97,38 +102,81 @@ public void onReplicatedEvent(@Observes ReplicatedEventQueueItem replicatedEvent return; } - // Get or create a ChildQueue for this task (creates MainQueue if it doesn't exist) - EventQueue childQueue = delegate.createOrTap(replicatedEvent.getTaskId()); - + // Get the MainQueue to enqueue the replicated event item + // We must use enqueueItem (not enqueueEvent) to preserve the isReplicated() flag + // and avoid triggering the replication hook again (which would cause a replication loop) + // + // IMPORTANT: We must NOT create a ChildQueue here! Creating and immediately closing + // a ChildQueue means there are zero children when MainEventBusProcessor distributes + // the event. Existing ChildQueues (from active client subscriptions) will receive + // the event when MainEventBusProcessor distributes it to all children. + // + // If MainQueue doesn't exist, create it. This handles late-arriving replicated events + // for tasks that were created on another instance. + EventQueue childQueue = null; // Track ChildQueue we might create + EventQueue mainQueue = delegate.get(replicatedEvent.getTaskId()); try { - // Get the MainQueue to enqueue the replicated event item - // We must use enqueueItem (not enqueueEvent) to preserve the isReplicated() flag - // and avoid triggering the replication hook again (which would cause a replication loop) - EventQueue mainQueue = delegate.get(replicatedEvent.getTaskId()); + if (mainQueue == null) { + LOGGER.debug("Creating MainQueue for replicated event on task {}", replicatedEvent.getTaskId()); + childQueue = delegate.createOrTap(replicatedEvent.getTaskId()); // Creates MainQueue + returns ChildQueue + mainQueue = delegate.get(replicatedEvent.getTaskId()); // Get MainQueue from map + } + if (mainQueue != null) { mainQueue.enqueueItem(replicatedEvent); } else { - LOGGER.warn("MainQueue not found for task {}, cannot enqueue replicated event. This may happen if the queue was already cleaned up.", - replicatedEvent.getTaskId()); + LOGGER.warn( + "MainQueue not found for task {}, cannot enqueue replicated event. This may happen if the queue was already cleaned up.", + replicatedEvent.getTaskId()); } } finally { - // Close the temporary ChildQueue to prevent leaks - // The MainQueue remains open for other consumers - childQueue.close(); + if (childQueue != null) { + try { + childQueue.close(); // Close the ChildQueue we created (not MainQueue!) + } catch (Exception ignore) { + // The close is safe, but print a stacktrace just in case + if (LOGGER.isDebugEnabled()) { + ignore.printStackTrace(); + } + } + } } } /** * Observes task finalization events fired AFTER database transaction commits. - * This guarantees the task's final state is durably stored before sending the poison pill. + * This guarantees the task's final state is durably stored before replication. * - * @param event the task finalized event containing the task ID + * Sends TaskStatusUpdateEvent (not full Task) FIRST, then the poison pill (QueueClosedEvent), + * ensuring correct event ordering across instances and eliminating race conditions where + * the poison pill arrives before the final task state. + * + * IMPORTANT: We send TaskStatusUpdateEvent instead of full Task to maintain consistency + * with local event distribution. Clients expect TaskStatusUpdateEvent for status changes, + * and sending the full Task causes issues in remote instances where clients don't handle + * bare Task objects the same way they handle TaskStatusUpdateEvent. + * + * @param event the task finalized event containing the task ID and final Task */ public void onTaskFinalized(@Observes(during = TransactionPhase.AFTER_SUCCESS) TaskFinalizedEvent event) { String taskId = event.getTaskId(); - LOGGER.debug("Task {} finalized - sending poison pill (QueueClosedEvent) after transaction commit", taskId); + io.a2a.spec.Task finalTask = (io.a2a.spec.Task) event.getTask(); // Cast from Object + + LOGGER.debug("Task {} finalized - sending TaskStatusUpdateEvent then poison pill (QueueClosedEvent) after transaction commit", taskId); + + // Convert final Task to TaskStatusUpdateEvent to match local event distribution + // This ensures remote instances receive the same event type as local instances + io.a2a.spec.TaskStatusUpdateEvent finalStatusEvent = io.a2a.spec.TaskStatusUpdateEvent.builder() + .taskId(taskId) + .contextId(finalTask.contextId()) + .status(finalTask.status()) + .isFinal(true) + .build(); + + // Send TaskStatusUpdateEvent FIRST to ensure it arrives before poison pill + replicationStrategy.send(taskId, finalStatusEvent); - // Send poison pill directly via replication strategy + // Then send poison pill // The transaction has committed, so the final state is guaranteed to be in the database io.a2a.server.events.QueueClosedEvent closedEvent = new io.a2a.server.events.QueueClosedEvent(taskId); replicationStrategy.send(taskId, closedEvent); @@ -152,12 +200,11 @@ public EventQueue.EventQueueBuilder builder(String taskId) { // which sends the QueueClosedEvent after the database transaction commits. // This ensures proper ordering and transactional guarantees. - // Return the builder with callbacks - return delegate.getEventQueueBuilder(taskId) - .taskId(taskId) - .hook(new ReplicationHook(taskId)) - .addOnCloseCallback(delegate.getCleanupCallback(taskId)) - .taskStateProvider(taskStateProvider); + // Call createBaseEventQueueBuilder() directly to avoid infinite recursion + // (getEventQueueBuilder() would delegate back to this factory, creating a loop) + // The base builder already includes: taskId, cleanup callback, taskStateProvider, mainEventBus + return delegate.createBaseEventQueueBuilder(taskId) + .hook(new ReplicationHook(taskId)); } } 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 43571cd30..14b4c1f51 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 @@ -22,12 +22,19 @@ import io.a2a.server.events.EventQueueClosedException; import io.a2a.server.events.EventQueueItem; import io.a2a.server.events.EventQueueTestHelper; +import io.a2a.server.events.EventQueueUtil; +import io.a2a.server.events.MainEventBus; +import io.a2a.server.events.MainEventBusProcessor; import io.a2a.server.events.QueueClosedEvent; +import io.a2a.server.tasks.InMemoryTaskStore; +import io.a2a.server.tasks.PushNotificationSender; import io.a2a.spec.Event; import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.Task; import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -35,10 +42,27 @@ class ReplicatedQueueManagerTest { private ReplicatedQueueManager queueManager; private StreamingEventKind testEvent; + private MainEventBus mainEventBus; + private MainEventBusProcessor mainEventBusProcessor; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; @BeforeEach void setUp() { - queueManager = new ReplicatedQueueManager(new NoOpReplicationStrategy(), new MockTaskStateProvider(true)); + // Create MainEventBus first + InMemoryTaskStore taskStore = new InMemoryTaskStore(); + mainEventBus = new MainEventBus(); + + // Create QueueManager before MainEventBusProcessor (processor needs it as parameter) + queueManager = new ReplicatedQueueManager( + new NoOpReplicationStrategy(), + new MockTaskStateProvider(true), + mainEventBus + ); + + // Create MainEventBusProcessor with QueueManager + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); + EventQueueUtil.start(mainEventBusProcessor); + testEvent = TaskStatusUpdateEvent.builder() .taskId("test-task") .contextId("test-context") @@ -47,25 +71,82 @@ void setUp() { .build(); } + /** + * Helper to create a test event with the specified taskId. + * This ensures taskId consistency between queue creation and event creation. + */ + private TaskStatusUpdateEvent createEventForTask(String taskId) { + return TaskStatusUpdateEvent.builder() + .taskId(taskId) + .contextId("test-context") + .status(new TaskStatus(TaskState.SUBMITTED)) + .isFinal(false) + .build(); + } + + @AfterEach + void tearDown() { + if (mainEventBusProcessor != null) { + mainEventBusProcessor.setCallback(null); // Clear any test callbacks + EventQueueUtil.stop(mainEventBusProcessor); + } + mainEventBusProcessor = null; + mainEventBus = null; + queueManager = null; + } + + /** + * Helper to wait for MainEventBusProcessor to process an event. + * Replaces polling patterns with deterministic callback-based waiting. + * + * @param action the action that triggers event processing + * @throws InterruptedException if waiting is interrupted + * @throws AssertionError if processing doesn't complete within timeout + */ + private void waitForEventProcessing(Runnable action) throws InterruptedException { + CountDownLatch processingLatch = new CountDownLatch(1); + mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { + @Override + public void onEventProcessed(String taskId, io.a2a.spec.Event event) { + processingLatch.countDown(); + } + + @Override + public void onTaskFinalized(String taskId) { + // Not needed for basic event processing wait + } + }); + + try { + action.run(); + assertTrue(processingLatch.await(5, TimeUnit.SECONDS), + "MainEventBusProcessor should have processed the event within timeout"); + } finally { + mainEventBusProcessor.setCallback(null); + } + } + @Test void testReplicationStrategyTriggeredOnNormalEnqueue() throws InterruptedException { CountingReplicationStrategy strategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true)); + queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true), mainEventBus); String taskId = "test-task-1"; EventQueue queue = queueManager.createOrTap(taskId); + TaskStatusUpdateEvent event = createEventForTask(taskId); - queue.enqueueEvent(testEvent); + // Wait for MainEventBusProcessor to process the event and trigger replication + waitForEventProcessing(() -> queue.enqueueEvent(event)); assertEquals(1, strategy.getCallCount()); assertEquals(taskId, strategy.getLastTaskId()); - assertEquals(testEvent, strategy.getLastEvent()); + assertEquals(event, strategy.getLastEvent()); } @Test void testReplicationStrategyNotTriggeredOnReplicatedEvent() throws InterruptedException { CountingReplicationStrategy strategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true)); + queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true), mainEventBus); String taskId = "test-task-2"; EventQueue queue = queueManager.createOrTap(taskId); @@ -79,17 +160,19 @@ void testReplicationStrategyNotTriggeredOnReplicatedEvent() throws InterruptedEx @Test void testReplicationStrategyWithCountingImplementation() throws InterruptedException { CountingReplicationStrategy countingStrategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(countingStrategy, new MockTaskStateProvider(true)); + queueManager = new ReplicatedQueueManager(countingStrategy, new MockTaskStateProvider(true), mainEventBus); String taskId = "test-task-3"; EventQueue queue = queueManager.createOrTap(taskId); + TaskStatusUpdateEvent event = createEventForTask(taskId); - queue.enqueueEvent(testEvent); - queue.enqueueEvent(testEvent); + // Wait for MainEventBusProcessor to process each event + waitForEventProcessing(() -> queue.enqueueEvent(event)); + waitForEventProcessing(() -> queue.enqueueEvent(event)); assertEquals(2, countingStrategy.getCallCount()); assertEquals(taskId, countingStrategy.getLastTaskId()); - assertEquals(testEvent, countingStrategy.getLastEvent()); + assertEquals(event, countingStrategy.getLastEvent()); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, testEvent); queueManager.onReplicatedEvent(replicatedEvent); @@ -100,46 +183,45 @@ void testReplicationStrategyWithCountingImplementation() throws InterruptedExcep @Test void testReplicatedEventDeliveredToCorrectQueue() throws InterruptedException { String taskId = "test-task-4"; + TaskStatusUpdateEvent eventForTask = createEventForTask(taskId); // Use matching taskId EventQueue queue = queueManager.createOrTap(taskId); - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, testEvent); - queueManager.onReplicatedEvent(replicatedEvent); + ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, eventForTask); - Event dequeuedEvent; - try { - dequeuedEvent = queue.dequeueEventItem(100).getEvent(); - } catch (EventQueueClosedException e) { - fail("Queue should not be closed"); - return; - } - assertEquals(testEvent, dequeuedEvent); + // Use callback to wait for event processing + EventQueueItem item = dequeueEventWithRetry(queue, () -> queueManager.onReplicatedEvent(replicatedEvent)); + assertNotNull(item, "Event should be available in queue"); + Event dequeuedEvent = item.getEvent(); + assertEquals(eventForTask, dequeuedEvent); } @Test void testReplicatedEventCreatesQueueIfNeeded() throws InterruptedException { String taskId = "non-existent-task"; + TaskStatusUpdateEvent eventForTask = createEventForTask(taskId); // Use matching taskId // Verify no queue exists initially assertNull(queueManager.get(taskId)); - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, testEvent); - - // Process the replicated event - assertDoesNotThrow(() -> queueManager.onReplicatedEvent(replicatedEvent)); - - // Verify that a queue was created and the event was enqueued - EventQueue queue = queueManager.get(taskId); - assertNotNull(queue, "Queue should be created when processing replicated event for non-existent task"); - - // Verify the event was enqueued by dequeuing it - Event dequeuedEvent; - try { - dequeuedEvent = queue.dequeueEventItem(100).getEvent(); - } catch (EventQueueClosedException e) { - fail("Queue should not be closed"); - return; - } - assertEquals(testEvent, dequeuedEvent, "The replicated event should be enqueued in the newly created queue"); + // Create a ChildQueue BEFORE processing the replicated event + // This ensures the ChildQueue exists when MainEventBusProcessor distributes the event + EventQueue childQueue = queueManager.createOrTap(taskId); + assertNotNull(childQueue, "ChildQueue should be created"); + + // Verify MainQueue was created + EventQueue mainQueue = queueManager.get(taskId); + assertNotNull(mainQueue, "MainQueue should exist after createOrTap"); + + ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, eventForTask); + + // Process the replicated event and wait for distribution + // Use callback to wait for event processing + EventQueueItem item = dequeueEventWithRetry(childQueue, () -> { + assertDoesNotThrow(() -> queueManager.onReplicatedEvent(replicatedEvent)); + }); + assertNotNull(item, "Event should be available in queue"); + Event dequeuedEvent = item.getEvent(); + assertEquals(eventForTask, dequeuedEvent, "The replicated event should be enqueued in the newly created queue"); } @Test @@ -170,17 +252,18 @@ void testBasicQueueManagerFunctionality() throws InterruptedException { void testQueueToTaskIdMappingMaintained() throws InterruptedException { String taskId = "test-task-6"; CountingReplicationStrategy countingStrategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(countingStrategy, new MockTaskStateProvider(true)); + queueManager = new ReplicatedQueueManager(countingStrategy, new MockTaskStateProvider(true), mainEventBus); + TaskStatusUpdateEvent event = createEventForTask(taskId); EventQueue queue = queueManager.createOrTap(taskId); - queue.enqueueEvent(testEvent); + waitForEventProcessing(() -> queue.enqueueEvent(event)); assertEquals(taskId, countingStrategy.getLastTaskId()); queueManager.close(taskId); // Task is active, so NO poison pill is sent EventQueue newQueue = queueManager.createOrTap(taskId); - newQueue.enqueueEvent(testEvent); + waitForEventProcessing(() -> newQueue.enqueueEvent(event)); assertEquals(taskId, countingStrategy.getLastTaskId()); // 2 replication calls: 1 testEvent, 1 testEvent (no QueueClosedEvent because task is active) @@ -217,16 +300,43 @@ void testReplicatedEventJsonSerialization() throws Exception { @Test void testParallelReplicationBehavior() throws InterruptedException { CountingReplicationStrategy strategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true)); + queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true), mainEventBus); String taskId = "parallel-test-task"; EventQueue queue = queueManager.createOrTap(taskId); int numThreads = 10; int eventsPerThread = 5; + int expectedEventCount = (numThreads / 2) * eventsPerThread; // Only normal enqueues + int totalEventCount = numThreads * eventsPerThread; // All events (normal + replicated) ExecutorService executor = Executors.newFixedThreadPool(numThreads); CountDownLatch startLatch = new CountDownLatch(1); CountDownLatch doneLatch = new CountDownLatch(numThreads); + + // Use CyclicBarrier for better thread synchronization + // This ensures all threads start their work at approximately the same time + java.util.concurrent.CyclicBarrier barrier = new java.util.concurrent.CyclicBarrier(numThreads); + + // Track processed events for better diagnostics on failure + java.util.concurrent.CopyOnWriteArrayList processedEvents = + new java.util.concurrent.CopyOnWriteArrayList<>(); + + // Set up callback to wait for ALL events to be processed by MainEventBusProcessor + // Must wait for all 50 events (25 normal + 25 replicated) to ensure all normal events + // have triggered replication before we check the count + CountDownLatch processingLatch = new CountDownLatch(totalEventCount); + mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { + @Override + public void onEventProcessed(String tid, io.a2a.spec.Event event) { + processedEvents.add(event); + processingLatch.countDown(); + } + + @Override + public void onTaskFinalized(String tid) { + // Not needed for this test + } + }); // Launch threads that will enqueue events normally (should trigger replication) for (int i = 0; i < numThreads / 2; i++) { @@ -234,18 +344,20 @@ void testParallelReplicationBehavior() throws InterruptedException { executor.submit(() -> { try { startLatch.await(); + barrier.await(); // Synchronize thread starts for better interleaving for (int j = 0; j < eventsPerThread; j++) { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("normal-" + threadId + "-" + j) + .taskId(taskId) // Use same taskId as queue .contextId("test-context") .status(new TaskStatus(TaskState.WORKING)) .isFinal(false) .build(); queue.enqueueEvent(event); - Thread.sleep(1); // Small delay to interleave operations } } catch (InterruptedException e) { Thread.currentThread().interrupt(); + } catch (java.util.concurrent.BrokenBarrierException e) { + throw new RuntimeException("Barrier broken", e); } finally { doneLatch.countDown(); } @@ -258,19 +370,21 @@ void testParallelReplicationBehavior() throws InterruptedException { executor.submit(() -> { try { startLatch.await(); + barrier.await(); // Synchronize thread starts for better interleaving for (int j = 0; j < eventsPerThread; j++) { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("replicated-" + threadId + "-" + j) + .taskId(taskId) // Use same taskId as queue .contextId("test-context") .status(new TaskStatus(TaskState.COMPLETED)) .isFinal(true) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, event); queueManager.onReplicatedEvent(replicatedEvent); - Thread.sleep(1); // Small delay to interleave operations } } catch (InterruptedException e) { Thread.currentThread().interrupt(); + } catch (java.util.concurrent.BrokenBarrierException e) { + throw new RuntimeException("Barrier broken", e); } finally { doneLatch.countDown(); } @@ -280,24 +394,43 @@ void testParallelReplicationBehavior() throws InterruptedException { // Start all threads simultaneously startLatch.countDown(); - // Wait for all threads to complete - assertTrue(doneLatch.await(10, TimeUnit.SECONDS), "All threads should complete within 10 seconds"); + // Wait for all threads to complete with explicit timeout + assertTrue(doneLatch.await(10, TimeUnit.SECONDS), + "All " + numThreads + " threads should complete within 10 seconds"); executor.shutdown(); - assertTrue(executor.awaitTermination(5, TimeUnit.SECONDS), "Executor should shutdown within 5 seconds"); + assertTrue(executor.awaitTermination(5, TimeUnit.SECONDS), + "Executor should shutdown within 5 seconds"); + + // Wait for MainEventBusProcessor to process all events + try { + boolean allProcessed = processingLatch.await(10, TimeUnit.SECONDS); + assertTrue(allProcessed, + String.format("MainEventBusProcessor should have processed all %d events within timeout. " + + "Processed: %d, Remaining: %d", + totalEventCount, processedEvents.size(), processingLatch.getCount())); + } finally { + mainEventBusProcessor.setCallback(null); + queue.close(true, true); + } + + // Verify we processed the expected number of events + assertEquals(totalEventCount, processedEvents.size(), + "Should have processed exactly " + totalEventCount + " events (normal + replicated)"); // Only the normal enqueue operations should have triggered replication // numThreads/2 threads * eventsPerThread events each = total expected replication calls int expectedReplicationCalls = (numThreads / 2) * eventsPerThread; assertEquals(expectedReplicationCalls, strategy.getCallCount(), - "Only normal enqueue operations should trigger replication, not replicated events"); + String.format("Only normal enqueue operations should trigger replication, not replicated events. " + + "Expected: %d, Actual: %d", expectedReplicationCalls, strategy.getCallCount())); } @Test void testReplicatedEventSkippedWhenTaskInactive() throws InterruptedException { // Create a task state provider that returns false (task is inactive) MockTaskStateProvider stateProvider = new MockTaskStateProvider(false); - queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider); + queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider, mainEventBus); String taskId = "inactive-task"; @@ -316,30 +449,32 @@ void testReplicatedEventSkippedWhenTaskInactive() throws InterruptedException { void testReplicatedEventProcessedWhenTaskActive() throws InterruptedException { // Create a task state provider that returns true (task is active) MockTaskStateProvider stateProvider = new MockTaskStateProvider(true); - queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider); + queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider, mainEventBus); String taskId = "active-task"; + TaskStatusUpdateEvent eventForTask = createEventForTask(taskId); // Use matching taskId // Verify no queue exists initially assertNull(queueManager.get(taskId)); - // Process a replicated event for an active task - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, testEvent); - queueManager.onReplicatedEvent(replicatedEvent); + // Create a ChildQueue BEFORE processing the replicated event + // This ensures the ChildQueue exists when MainEventBusProcessor distributes the event + EventQueue childQueue = queueManager.createOrTap(taskId); + assertNotNull(childQueue, "ChildQueue should be created"); - // Queue should be created and event should be enqueued - EventQueue queue = queueManager.get(taskId); - assertNotNull(queue, "Queue should be created for active task"); + // Verify MainQueue was created + EventQueue mainQueue = queueManager.get(taskId); + assertNotNull(mainQueue, "MainQueue should exist after createOrTap"); - // Verify the event was enqueued - Event dequeuedEvent; - try { - dequeuedEvent = queue.dequeueEventItem(100).getEvent(); - } catch (EventQueueClosedException e) { - fail("Queue should not be closed"); - return; - } - assertEquals(testEvent, dequeuedEvent, "Event should be enqueued for active task"); + // Process a replicated event for an active task + ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, eventForTask); + + // Verify the event was enqueued and distributed to our ChildQueue + // Use callback to wait for event processing + EventQueueItem item = dequeueEventWithRetry(childQueue, () -> queueManager.onReplicatedEvent(replicatedEvent)); + assertNotNull(item, "Event should be available in queue"); + Event dequeuedEvent = item.getEvent(); + assertEquals(eventForTask, dequeuedEvent, "Event should be enqueued for active task"); } @@ -347,7 +482,7 @@ void testReplicatedEventProcessedWhenTaskActive() throws InterruptedException { void testReplicatedEventToExistingQueueWhenTaskBecomesInactive() throws InterruptedException { // Create a task state provider that returns true initially MockTaskStateProvider stateProvider = new MockTaskStateProvider(true); - queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider); + queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider, mainEventBus); String taskId = "task-becomes-inactive"; @@ -387,30 +522,38 @@ void testReplicatedEventToExistingQueueWhenTaskBecomesInactive() throws Interrup @Test void testPoisonPillSentViaTransactionAwareEvent() throws InterruptedException { CountingReplicationStrategy strategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true)); + queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true), mainEventBus); String taskId = "poison-pill-test"; EventQueue queue = queueManager.createOrTap(taskId); + TaskStatusUpdateEvent event = createEventForTask(taskId); - // Enqueue a normal event first - queue.enqueueEvent(testEvent); + // Enqueue a normal event first and wait for processing + waitForEventProcessing(() -> queue.enqueueEvent(event)); // In the new architecture, QueueClosedEvent (poison pill) is sent via CDI events // when JpaDatabaseTaskStore.save() persists a final task and the transaction commits // ReplicatedQueueManager.onTaskFinalized() observes AFTER_SUCCESS and sends the poison pill // Simulate the CDI event observer being called (what happens in real execution) - TaskFinalizedEvent taskFinalizedEvent = new TaskFinalizedEvent(taskId); + // Create a final task for the event + Task finalTask = Task.builder() + .id(taskId) + .contextId("test-context") + .status(new TaskStatus(TaskState.COMPLETED)) + .build(); + TaskFinalizedEvent taskFinalizedEvent = new TaskFinalizedEvent(taskId, finalTask); // Call the observer method directly (simulating CDI event delivery) queueManager.onTaskFinalized(taskFinalizedEvent); - // Verify that QueueClosedEvent was replicated - // strategy.getCallCount() should be 2: one for testEvent, one for QueueClosedEvent - assertEquals(2, strategy.getCallCount(), "Should have replicated both normal event and QueueClosedEvent"); + // Verify that final Task and QueueClosedEvent were replicated + // strategy.getCallCount() should be 3: testEvent, final Task, then QueueClosedEvent (poison pill) + assertEquals(3, strategy.getCallCount(), "Should have replicated testEvent, final Task, and QueueClosedEvent"); + // Verify the last event is QueueClosedEvent (poison pill) Event lastEvent = strategy.getLastEvent(); - assertTrue(lastEvent instanceof QueueClosedEvent, "Last replicated event should be QueueClosedEvent"); + assertTrue(lastEvent instanceof QueueClosedEvent, "Last replicated event should be QueueClosedEvent (poison pill)"); assertEquals(taskId, ((QueueClosedEvent) lastEvent).getTaskId()); } @@ -451,36 +594,21 @@ void testQueueClosedEventJsonSerialization() throws Exception { @Test void testReplicatedQueueClosedEventTerminatesConsumer() throws InterruptedException { String taskId = "remote-close-test"; + TaskStatusUpdateEvent eventForTask = createEventForTask(taskId); // Use matching taskId EventQueue queue = queueManager.createOrTap(taskId); - // Enqueue a normal event - queue.enqueueEvent(testEvent); - // Simulate receiving QueueClosedEvent from remote node QueueClosedEvent closedEvent = new QueueClosedEvent(taskId); ReplicatedEventQueueItem replicatedClosedEvent = new ReplicatedEventQueueItem(taskId, closedEvent); - queueManager.onReplicatedEvent(replicatedClosedEvent); - // Dequeue the normal event first - EventQueueItem item1; - try { - item1 = queue.dequeueEventItem(100); - } catch (EventQueueClosedException e) { - fail("Should not throw on first dequeue"); - return; - } - assertNotNull(item1); - assertEquals(testEvent, item1.getEvent()); + // Dequeue the normal event first (use callback to wait for async processing) + EventQueueItem item1 = dequeueEventWithRetry(queue, () -> queue.enqueueEvent(eventForTask)); + assertNotNull(item1, "First event should be available"); + assertEquals(eventForTask, item1.getEvent()); - // Next dequeue should get the QueueClosedEvent - EventQueueItem item2; - try { - item2 = queue.dequeueEventItem(100); - } catch (EventQueueClosedException e) { - fail("Should not throw on second dequeue, should return the event"); - return; - } - assertNotNull(item2); + // Next dequeue should get the QueueClosedEvent (use callback to wait for async processing) + EventQueueItem item2 = dequeueEventWithRetry(queue, () -> queueManager.onReplicatedEvent(replicatedClosedEvent)); + assertNotNull(item2, "QueueClosedEvent should be available"); assertTrue(item2.getEvent() instanceof QueueClosedEvent, "Second event should be QueueClosedEvent"); } @@ -539,4 +667,25 @@ public void setActive(boolean active) { this.active = active; } } + + /** + * Helper method to dequeue an event after waiting for MainEventBusProcessor distribution. + * Uses callback-based waiting instead of polling for deterministic synchronization. + * + * @param queue the queue to dequeue from + * @param enqueueAction the action that enqueues the event (triggers event processing) + * @return the dequeued EventQueueItem, or null if queue is closed + */ + private EventQueueItem dequeueEventWithRetry(EventQueue queue, Runnable enqueueAction) throws InterruptedException { + // Wait for event to be processed and distributed + waitForEventProcessing(enqueueAction); + + // Event is now available, dequeue directly + try { + return queue.dequeueEventItem(100); + } catch (EventQueueClosedException e) { + // Queue closed, return null + return null; + } + } } \ No newline at end of file diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java b/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java new file mode 100644 index 000000000..a91575aaa --- /dev/null +++ b/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java @@ -0,0 +1,11 @@ +package io.a2a.server.events; + +public class EventQueueUtil { + public static void start(MainEventBusProcessor processor) { + processor.start(); + } + + public static void stop(MainEventBusProcessor processor) { + processor.stop(); + } +} diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties index d0692ca53..ea64096cb 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties @@ -34,5 +34,7 @@ quarkus.messaging.kafka.health.timeout=5s # Enable debug logging quarkus.log.category."io.a2a.server.events".level=DEBUG quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG +quarkus.log.category."io.a2a.server.tasks".level=DEBUG quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG +quarkus.log.category."io.a2a.extras.taskstore.database.jpa".level=DEBUG quarkus.log.category."io.a2a.client".level=DEBUG diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties index 0b647f3a5..d9a495e8f 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties @@ -34,5 +34,7 @@ quarkus.messaging.kafka.health.timeout=5s # Enable debug logging quarkus.log.category."io.a2a.server.events".level=DEBUG quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG +quarkus.log.category."io.a2a.server.tasks".level=DEBUG quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG +quarkus.log.category."io.a2a.extras.taskstore.database.jpa".level=DEBUG quarkus.log.category."io.a2a.client".level=DEBUG diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java index 93093388d..b98f0e87d 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java @@ -10,6 +10,7 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; @@ -254,9 +255,11 @@ public void testMultiInstanceEventReplication() throws Exception { final String taskId = "replication-test-task-" + System.currentTimeMillis(); final String contextId = "replication-test-context"; - // Step 1: Send initial message NON-streaming to create task - Message initialMessage = Message.builder(A2A.toUserMessage("Initial test message")) - .taskId(taskId) + Throwable testFailure = null; + try { + // Step 1: Send initial message NON-streaming to create task + Message initialMessage = Message.builder(A2A.toUserMessage("Initial test message")) + .taskId(taskId) .contextId(contextId) .build(); @@ -308,11 +311,33 @@ public void testMultiInstanceEventReplication() throws Exception { AtomicReference app1Error = new AtomicReference<>(); AtomicReference app2Error = new AtomicReference<>(); + AtomicBoolean app1ReceivedInitialTask = new AtomicBoolean(false); + AtomicBoolean app2ReceivedInitialTask = new AtomicBoolean(false); // App1 subscriber BiConsumer app1Subscriber = (event, card) -> { + String eventDetail = event.getClass().getSimpleName(); + if (event instanceof io.a2a.client.TaskUpdateEvent tue) { + eventDetail += " [" + tue.getUpdateEvent().getClass().getSimpleName(); + if (tue.getUpdateEvent() instanceof io.a2a.spec.TaskStatusUpdateEvent statusEvent) { + eventDetail += ", state=" + (statusEvent.status() != null ? statusEvent.status().state() : "null"); + } + eventDetail += "]"; + } else if (event instanceof io.a2a.client.TaskEvent te) { + eventDetail += " [state=" + (te.getTask().status() != null ? te.getTask().status().state() : "null") + "]"; + } + System.out.println("APP1 received event: " + eventDetail); + + // Per A2A spec 3.1.6: Handle initial TaskEvent on resubscribe + if (!app1ReceivedInitialTask.get() && event instanceof io.a2a.client.TaskEvent) { + app1ReceivedInitialTask.set(true); + System.out.println("APP1 filtered initial TaskEvent"); + // Don't count initial TaskEvent toward expected artifact/status events + return; + } app1Events.add(event); - app1EventCount.incrementAndGet(); + int count = app1EventCount.incrementAndGet(); + System.out.println("APP1 event count now: " + count + ", event: " + eventDetail); }; Consumer app1ErrorHandler = error -> { @@ -323,8 +348,28 @@ public void testMultiInstanceEventReplication() throws Exception { // App2 subscriber BiConsumer app2Subscriber = (event, card) -> { + String eventDetail = event.getClass().getSimpleName(); + if (event instanceof io.a2a.client.TaskUpdateEvent tue) { + eventDetail += " [" + tue.getUpdateEvent().getClass().getSimpleName(); + if (tue.getUpdateEvent() instanceof io.a2a.spec.TaskStatusUpdateEvent statusEvent) { + eventDetail += ", state=" + (statusEvent.status() != null ? statusEvent.status().state() : "null"); + } + eventDetail += "]"; + } else if (event instanceof io.a2a.client.TaskEvent te) { + eventDetail += " [state=" + (te.getTask().status() != null ? te.getTask().status().state() : "null") + "]"; + } + System.out.println("APP2 received event: " + eventDetail); + + // Per A2A spec 3.1.6: Handle initial TaskEvent on resubscribe + if (!app2ReceivedInitialTask.get() && event instanceof io.a2a.client.TaskEvent) { + app2ReceivedInitialTask.set(true); + System.out.println("APP2 filtered initial TaskEvent"); + // Don't count initial TaskEvent toward expected artifact/status events + return; + } app2Events.add(event); - app2EventCount.incrementAndGet(); + int count = app2EventCount.incrementAndGet(); + System.out.println("APP2 event count now: " + count + ", event: " + eventDetail); }; Consumer app2ErrorHandler = error -> { @@ -409,9 +454,45 @@ public void testMultiInstanceEventReplication() throws Exception { throw new AssertionError("App2 subscriber error", app2Error.get()); } - // Verify both received at least 3 events (could be more due to initial state events) - assertTrue(app1Events.size() >= 3, "App1 should receive at least 3 events, got: " + app1Events.size()); - assertTrue(app2Events.size() >= 3, "App2 should receive at least 3 events, got: " + app2Events.size()); + // Verify both received at least 3 events (could be more due to initial state events) + assertTrue(app1Events.size() >= 3, "App1 should receive at least 3 events, got: " + app1Events.size()); + assertTrue(app2Events.size() >= 3, "App2 should receive at least 3 events, got: " + app2Events.size()); + } catch (Throwable t) { + testFailure = t; + throw t; + } finally { + // Output container logs if test failed + if (testFailure != null) { + System.err.println("\n========================================"); + System.err.println("TEST FAILED - Dumping container logs"); + System.err.println("========================================\n"); + + dumpContainerLogs("KAFKA", kafka, 100); + dumpContainerLogs("APP1", app1, 200); + dumpContainerLogs("APP2", app2, 200); + + System.err.println("\n========================================"); + System.err.println("END OF CONTAINER LOGS"); + System.err.println("========================================\n"); + } + } + } + + /** + * Dumps the last N lines of logs from a container to stderr. + */ + private void dumpContainerLogs(String containerName, org.testcontainers.containers.ContainerState container, int lastLines) { + System.err.println("\n--- " + containerName + " LOGS (last " + lastLines + " lines) ---"); + try { + String logs = container.getLogs(); + String[] lines = logs.split("\n"); + int start = Math.max(0, lines.length - lastLines); + for (int i = start; i < lines.length; i++) { + System.err.println(lines[i]); + } + } catch (Exception e) { + System.err.println("Failed to retrieve " + containerName + " logs: " + e.getMessage()); + } } /** 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 3825f3bad..c4b23fb0d 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 @@ -222,9 +222,21 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { AtomicReference receivedCompletedEvent = new AtomicReference<>(); AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); AtomicReference errorRef = new AtomicReference<>(); + AtomicBoolean receivedInitialTask = new AtomicBoolean(false); // Create consumer to handle resubscribed events BiConsumer consumer = (event, agentCard) -> { + // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent + if (!receivedInitialTask.get()) { + if (event instanceof TaskEvent) { + receivedInitialTask.set(true); + return; + } else { + throw new AssertionError("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + } + } + + // Process subsequent events if (event instanceof TaskUpdateEvent taskUpdateEvent) { if (taskUpdateEvent.getUpdateEvent() instanceof TaskStatusUpdateEvent statusEvent) { if (statusEvent.status().state() == TaskState.COMPLETED) { 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 b65b71650..a4afa8588 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 @@ -65,19 +65,23 @@ void initConfig() { @Transactional @Override - public void save(Task task) { - LOGGER.debug("Saving task with ID: {}", task.id()); + public void save(Task task, boolean isReplicated) { + LOGGER.debug("Saving task with ID: {} (replicated: {})", task.id(), isReplicated); try { JpaTask jpaTask = JpaTask.createFromTask(task); em.merge(jpaTask); LOGGER.debug("Persisted/updated task with ID: {}", task.id()); - if (task.status() != null && task.status().state() != null && task.status().state().isFinal()) { + // Only fire TaskFinalizedEvent for locally-generated final states, NOT for replicated events + // This prevents feedback loops where receiving a replicated final task triggers another replication + if (!isReplicated && task.status() != null && task.status().state() != null && task.status().state().isFinal()) { // Fire CDI event if task reached final state // IMPORTANT: The event will be delivered AFTER transaction commits (AFTER_SUCCESS observers) - // This ensures the task's final state is durably stored before the QueueClosedEvent poison pill is sent - LOGGER.debug("Task {} is in final state, firing TaskFinalizedEvent", task.id()); - taskFinalizedEvent.fire(new TaskFinalizedEvent(task.id())); + // This ensures the task's final state is durably stored before the final task and poison pill are sent + LOGGER.debug("Task {} is in final state, firing TaskFinalizedEvent with full Task", task.id()); + taskFinalizedEvent.fire(new TaskFinalizedEvent(task.id(), task)); + } else if (isReplicated && task.status() != null && task.status().state() != null && task.status().state().isFinal()) { + LOGGER.debug("Task {} is in final state but from replication - NOT firing TaskFinalizedEvent (prevents feedback loop)", task.id()); } } catch (JsonProcessingException e) { LOGGER.error("Failed to serialize task with ID: {}", task.id(), e); 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 ea77f73c7..15c01a626 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 @@ -54,7 +54,7 @@ public void testSaveAndRetrieveTask() { .build(); // Save the task - taskStore.save(task); + taskStore.save(task, false); // Retrieve the task Task retrieved = taskStore.get("test-task-1"); @@ -84,7 +84,7 @@ public void testSaveAndRetrieveTaskWithHistory() { .build(); // Save the task - taskStore.save(task); + taskStore.save(task, false); // Retrieve the task Task retrieved = taskStore.get("test-task-2"); @@ -108,7 +108,7 @@ public void testUpdateExistingTask() { .status(new TaskStatus(TaskState.SUBMITTED)) .build(); - taskStore.save(initialTask); + taskStore.save(initialTask, false); // Update the task Task updatedTask = Task.builder() @@ -117,7 +117,7 @@ public void testUpdateExistingTask() { .status(new TaskStatus(TaskState.COMPLETED)) .build(); - taskStore.save(updatedTask); + taskStore.save(updatedTask, false); // Retrieve and verify the update Task retrieved = taskStore.get("test-task-3"); @@ -144,7 +144,7 @@ public void testDeleteTask() { .status(new TaskStatus(TaskState.SUBMITTED)) .build(); - taskStore.save(task); + taskStore.save(task, false); // Verify it exists assertNotNull(taskStore.get("test-task-4")); @@ -180,7 +180,7 @@ public void testTaskWithComplexMetadata() { .build(); // Save and retrieve - taskStore.save(task); + taskStore.save(task, false); Task retrieved = taskStore.get("test-task-5"); assertNotNull(retrieved); @@ -201,7 +201,7 @@ public void testIsTaskActiveForNonFinalTask() { .status(new TaskStatus(TaskState.WORKING)) .build(); - taskStore.save(task); + taskStore.save(task, false); // Task should be active (not in final state) JpaDatabaseTaskStore jpaDatabaseTaskStore = (JpaDatabaseTaskStore) taskStore; @@ -220,7 +220,7 @@ public void testIsTaskActiveForFinalTaskWithinGracePeriod() { .status(new TaskStatus(TaskState.WORKING)) .build(); - taskStore.save(task); + taskStore.save(task, false); // Update to final state Task finalTask = Task.builder() @@ -229,7 +229,7 @@ public void testIsTaskActiveForFinalTaskWithinGracePeriod() { .status(new TaskStatus(TaskState.COMPLETED)) .build(); - taskStore.save(finalTask); + taskStore.save(finalTask, false); // Task should be active (within grace period - default 15 seconds) JpaDatabaseTaskStore jpaDatabaseTaskStore = (JpaDatabaseTaskStore) taskStore; @@ -248,7 +248,7 @@ public void testIsTaskActiveForFinalTaskBeyondGracePeriod() { .status(new TaskStatus(TaskState.COMPLETED)) .build(); - taskStore.save(task); + taskStore.save(task, false); // Directly update the finalizedAt timestamp to 20 seconds in the past // (beyond the default 15-second grace period) @@ -322,9 +322,9 @@ public void testListTasksFilterByContextId() { .status(new TaskStatus(TaskState.COMPLETED)) .build(); - taskStore.save(task1); - taskStore.save(task2); - taskStore.save(task3); + taskStore.save(task1, false); + taskStore.save(task2, false); + taskStore.save(task3, false); // List tasks for context-A ListTasksParams params = ListTasksParams.builder() @@ -361,9 +361,9 @@ public void testListTasksFilterByStatus() { .status(new TaskStatus(TaskState.COMPLETED)) .build(); - taskStore.save(task1); - taskStore.save(task2); - taskStore.save(task3); + taskStore.save(task1, false); + taskStore.save(task2, false); + taskStore.save(task3, false); // List only WORKING tasks in this context ListTasksParams params = ListTasksParams.builder() @@ -401,9 +401,9 @@ public void testListTasksCombinedFilters() { .status(new TaskStatus(TaskState.WORKING)) .build(); - taskStore.save(task1); - taskStore.save(task2); - taskStore.save(task3); + taskStore.save(task1, false); + taskStore.save(task2, false); + taskStore.save(task3, false); // List WORKING tasks in context-X ListTasksParams params = ListTasksParams.builder() @@ -432,7 +432,7 @@ public void testListTasksPagination() { .contextId("context-pagination") .status(new TaskStatus(TaskState.SUBMITTED, null, sameTimestamp)) .build(); - taskStore.save(task); + taskStore.save(task, false); } // First page: pageSize=2 @@ -488,7 +488,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { .contextId("context-diff-timestamps") .status(new TaskStatus(TaskState.WORKING, null, now.minusMinutes(10))) .build(); - taskStore.save(task1); + taskStore.save(task1, false); // Task 2: 5 minutes ago, ID="task-diff-b" Task task2 = Task.builder() @@ -496,7 +496,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { .contextId("context-diff-timestamps") .status(new TaskStatus(TaskState.WORKING, null, now.minusMinutes(5))) .build(); - taskStore.save(task2); + taskStore.save(task2, false); // Task 3: 5 minutes ago, ID="task-diff-c" (same timestamp as task2, tests ID tie-breaker) Task task3 = Task.builder() @@ -504,7 +504,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { .contextId("context-diff-timestamps") .status(new TaskStatus(TaskState.WORKING, null, now.minusMinutes(5))) .build(); - taskStore.save(task3); + taskStore.save(task3, false); // Task 4: Now, ID="task-diff-d" Task task4 = Task.builder() @@ -512,7 +512,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { .contextId("context-diff-timestamps") .status(new TaskStatus(TaskState.WORKING, null, now)) .build(); - taskStore.save(task4); + taskStore.save(task4, false); // Task 5: 1 minute ago, ID="task-diff-e" Task task5 = Task.builder() @@ -520,7 +520,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { .contextId("context-diff-timestamps") .status(new TaskStatus(TaskState.WORKING, null, now.minusMinutes(1))) .build(); - taskStore.save(task5); + taskStore.save(task5, false); // Expected order (timestamp DESC, id ASC): // 1. task-diff-d (now) @@ -616,7 +616,7 @@ public void testListTasksHistoryLimiting() { .history(longHistory) .build(); - taskStore.save(task); + taskStore.save(task, false); // List with historyLength=3 (should keep only last 3 messages) - filter by unique context ListTasksParams params = ListTasksParams.builder() @@ -654,7 +654,7 @@ public void testListTasksArtifactInclusion() { .artifacts(artifacts) .build(); - taskStore.save(task); + taskStore.save(task, false); // List without artifacts (default) - filter by unique context ListTasksParams paramsWithoutArtifacts = ListTasksParams.builder() @@ -691,7 +691,7 @@ public void testListTasksDefaultPageSize() { .contextId("context-default-pagesize") .status(new TaskStatus(TaskState.SUBMITTED)) .build(); - taskStore.save(task); + taskStore.save(task, false); } // List without specifying pageSize (should use default of 50) @@ -715,7 +715,7 @@ public void testListTasksInvalidPageTokenFormat() { .contextId("context-invalid-token") .status(new TaskStatus(TaskState.WORKING)) .build(); - taskStore.save(task); + taskStore.save(task, false); // Test 1: Legacy ID-only pageToken should throw InvalidParamsError ListTasksParams params1 = ListTasksParams.builder() @@ -777,9 +777,9 @@ public void testListTasksOrderingById() { .build(); // Save in reverse order - taskStore.save(task3); - taskStore.save(task1); - taskStore.save(task2); + taskStore.save(task3, false); + taskStore.save(task1, false); + taskStore.save(task2, false); // List should return sorted by timestamp DESC (all same), then by ID ASC ListTasksParams params = ListTasksParams.builder() 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 18e18a2f1..cb5bdb25b 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 @@ -13,7 +13,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Function; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; @@ -21,6 +20,7 @@ import com.google.gson.JsonSyntaxException; import io.a2a.common.A2AHeaders; +import io.a2a.server.util.sse.SseFormatter; import io.a2a.grpc.utils.JSONRPCUtils; import io.a2a.jsonrpc.common.json.IdJsonMappingException; import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; @@ -65,7 +65,6 @@ import io.a2a.transport.jsonrpc.handler.JSONRPCHandler; import io.quarkus.security.Authenticated; import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.ReactiveRoutes; import io.quarkus.vertx.web.Route; import io.smallrye.mutiny.Multi; import io.vertx.core.AsyncResult; @@ -74,6 +73,8 @@ import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.RoutingContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @Singleton public class A2AServerRoutes { @@ -135,8 +136,12 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { } else if (streaming) { final Multi> finalStreamingResponse = streamingResponse; executor.execute(() -> { - MultiSseSupport.subscribeObject( - finalStreamingResponse.map(i -> (Object) i), rc); + // Convert Multi to Multi with SSE formatting + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = finalStreamingResponse + .map(response -> SseFormatter.formatResponseAsSSE(response, eventIdCounter.getAndIncrement())); + // Write SSE-formatted strings to HTTP response + MultiSseSupport.writeSseStrings(sseEvents, rc, context); }); } else { @@ -295,34 +300,30 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse + * This class only handles HTTP-specific concerns (writing to response, backpressure, disconnect). + * SSE formatting and JSON serialization are handled by {@link SseFormatter}. + */ private static class MultiSseSupport { + private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); private MultiSseSupport() { // Avoid direct instantiation. } - private static void initialize(HttpServerResponse response) { - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - response.setChunked(true); - } - } - - private static void onWriteDone(Flow.Subscription subscription, AsyncResult ar, RoutingContext rc) { - if (ar.failed()) { - rc.fail(ar.cause()); - } else { - subscription.request(1); - } - } - - public static void write(Multi multi, RoutingContext rc) { + /** + * Write SSE-formatted strings to HTTP response. + * + * @param sseStrings Multi stream of SSE-formatted strings (from SseFormatter) + * @param rc Vert.x routing context + * @param context A2A server call context (for EventConsumer cancellation) + */ + public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { HttpServerResponse response = rc.response(); - multi.subscribe().withSubscriber(new Flow.Subscriber() { + + sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { Flow.Subscription upstream; @Override @@ -330,6 +331,13 @@ public void onSubscribe(Flow.Subscription subscription) { this.upstream = subscription; this.upstream.request(1); + // Detect client disconnect and call EventConsumer.cancel() directly + response.closeHandler(v -> { + logger.info("SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); + context.invokeEventConsumerCancelCallback(); + subscription.cancel(); + }); + // Notify tests that we are subscribed Runnable runnable = streamingMultiSseSupportSubscribedRunnable; if (runnable != null) { @@ -338,54 +346,50 @@ public void onSubscribe(Flow.Subscription subscription) { } @Override - public void onNext(Buffer item) { - initialize(response); - response.write(item, new Handler>() { + public void onNext(String sseEvent) { + // Set SSE headers on first event + if (response.bytesWritten() == 0) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + response.setChunked(true); + } + + // Write SSE-formatted string to response + response.write(Buffer.buffer(sseEvent), new Handler>() { @Override public void handle(AsyncResult ar) { - onWriteDone(upstream, ar, rc); + if (ar.failed()) { + // Client disconnected or write failed - cancel upstream to stop EventConsumer + upstream.cancel(); + rc.fail(ar.cause()); + } else { + upstream.request(1); + } } }); } @Override public void onError(Throwable throwable) { + // Cancel upstream to stop EventConsumer when error occurs + upstream.cancel(); rc.fail(throwable); } @Override public void onComplete() { - endOfStream(response); - } - }); - } - - public static void subscribeObject(Multi multi, RoutingContext rc) { - AtomicLong count = new AtomicLong(); - write(multi.map(new Function() { - @Override - public Buffer apply(Object o) { - if (o instanceof ReactiveRoutes.ServerSentEvent) { - 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((A2AResponse) ev.data()); - return Buffer.buffer(e + "data: " + data + "\nid: " + id + "\n\n"); + if (response.bytesWritten() == 0) { + // No events written - still set SSE content type + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } } - String data = serializeResponse((A2AResponse) o); - return Buffer.buffer("data: " + data + "\nid: " + count.getAndIncrement() + "\n\n"); - } - }), rc); - } - - private static void endOfStream(HttpServerResponse response) { - if (response.bytesWritten() == 0) { // No item - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + response.end(); } - } - response.end(); + }); } } } diff --git a/reference/jsonrpc/src/test/resources/application.properties b/reference/jsonrpc/src/test/resources/application.properties index 7b9cea9cc..e612925d4 100644 --- a/reference/jsonrpc/src/test/resources/application.properties +++ b/reference/jsonrpc/src/test/resources/application.properties @@ -1 +1,6 @@ quarkus.arc.selected-alternatives=io.a2a.server.apps.common.TestHttpClient + +# Debug logging for event processing and request handling +quarkus.log.category."io.a2a.server.events".level=DEBUG +quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG +quarkus.log.category."io.a2a.server.tasks".level=DEBUG 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 46d0d38e6..7a50f0afb 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 @@ -15,7 +15,8 @@ import java.util.concurrent.Executor; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Function; + +import io.a2a.server.util.sse.SseFormatter; import jakarta.annotation.security.PermitAll; import jakarta.enterprise.inject.Instance; @@ -38,7 +39,6 @@ import io.a2a.util.Utils; import io.quarkus.security.Authenticated; import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.ReactiveRoutes; import io.quarkus.vertx.web.Route; import io.smallrye.mutiny.Multi; import io.vertx.core.AsyncResult; @@ -110,10 +110,14 @@ public void sendMessageStreaming(@Body String body, RoutingContext rc) { if (error != null) { sendResponse(rc, error); } else if (streamingResponse != null) { - Multi events = Multi.createFrom().publisher(streamingResponse.getPublisher()); + final HTTPRestStreamingResponse finalStreamingResponse = streamingResponse; executor.execute(() -> { - MultiSseSupport.subscribeObject( - events.map(i -> (Object) i), rc); + // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = Multi.createFrom().publisher(finalStreamingResponse.getPublisher()) + .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); + // Write SSE-formatted strings to HTTP response + MultiSseSupport.writeSseStrings(sseEvents, rc, context); }); } } @@ -243,10 +247,14 @@ public void subscribeToTask(RoutingContext rc) { if (error != null) { sendResponse(rc, error); } else if (streamingResponse != null) { - Multi events = Multi.createFrom().publisher(streamingResponse.getPublisher()); + final HTTPRestStreamingResponse finalStreamingResponse = streamingResponse; executor.execute(() -> { - MultiSseSupport.subscribeObject( - events.map(i -> (Object) i), rc); + // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = Multi.createFrom().publisher(finalStreamingResponse.getPublisher()) + .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); + // Write SSE-formatted strings to HTTP response + MultiSseSupport.writeSseStrings(sseEvents, rc, context); }); } } @@ -450,34 +458,30 @@ public String getUsername() { } } - // Port of import io.quarkus.vertx.web.runtime.MultiSseSupport, which is considered internal API + /** + * Simplified SSE support for Vert.x/Quarkus. + *

    + * This class only handles HTTP-specific concerns (writing to response, backpressure, disconnect). + * SSE formatting and JSON serialization are handled by {@link SseFormatter}. + */ private static class MultiSseSupport { + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MultiSseSupport.class); private MultiSseSupport() { // Avoid direct instantiation. } - private static void initialize(HttpServerResponse response) { - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - response.setChunked(true); - } - } - - private static void onWriteDone(Flow.@Nullable Subscription subscription, AsyncResult ar, RoutingContext rc) { - if (ar.failed()) { - rc.fail(ar.cause()); - } else if (subscription != null) { - subscription.request(1); - } - } - - private static void write(Multi multi, RoutingContext rc) { + /** + * Write SSE-formatted strings to HTTP response. + * + * @param sseStrings Multi stream of SSE-formatted strings (from SseFormatter) + * @param rc Vert.x routing context + * @param context A2A server call context (for EventConsumer cancellation) + */ + public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { HttpServerResponse response = rc.response(); - multi.subscribe().withSubscriber(new Flow.Subscriber() { + + sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { Flow.@Nullable Subscription upstream; @Override @@ -485,6 +489,13 @@ public void onSubscribe(Flow.Subscription subscription) { this.upstream = subscription; this.upstream.request(1); + // Detect client disconnect and call EventConsumer.cancel() directly + response.closeHandler(v -> { + logger.debug("REST SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); + context.invokeEventConsumerCancelCallback(); + subscription.cancel(); + }); + // Notify tests that we are subscribed Runnable runnable = streamingMultiSseSupportSubscribedRunnable; if (runnable != null) { @@ -493,53 +504,64 @@ public void onSubscribe(Flow.Subscription subscription) { } @Override - public void onNext(Buffer item) { - initialize(response); - response.write(item, new Handler>() { + public void onNext(String sseEvent) { + // Set SSE headers on first event + if (response.bytesWritten() == 0) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + // Additional SSE headers to prevent buffering + headers.set("Cache-Control", "no-cache"); + headers.set("X-Accel-Buffering", "no"); // Disable nginx buffering + response.setChunked(true); + + // CRITICAL: Disable write queue max size to prevent buffering + // Vert.x buffers writes by default - we need immediate flushing for SSE + response.setWriteQueueMaxSize(1); // Force immediate flush + + // Send initial SSE comment to kickstart the stream + // This forces Vert.x to send headers and start the stream immediately + response.write(": SSE stream started\n\n"); + } + + // Write SSE-formatted string to response + response.write(Buffer.buffer(sseEvent), new Handler>() { @Override public void handle(AsyncResult ar) { - onWriteDone(upstream, ar, rc); + if (ar.failed()) { + // Client disconnected or write failed - cancel upstream to stop EventConsumer + // NullAway: upstream is guaranteed non-null after onSubscribe + java.util.Objects.requireNonNull(upstream).cancel(); + rc.fail(ar.cause()); + } else { + // NullAway: upstream is guaranteed non-null after onSubscribe + java.util.Objects.requireNonNull(upstream).request(1); + } } }); } @Override public void onError(Throwable throwable) { + // Cancel upstream to stop EventConsumer when error occurs + // NullAway: upstream is guaranteed non-null after onSubscribe + java.util.Objects.requireNonNull(upstream).cancel(); rc.fail(throwable); } @Override public void onComplete() { - endOfStream(response); - } - }); - } - - private static void subscribeObject(Multi multi, RoutingContext rc) { - AtomicLong count = new AtomicLong(); - write(multi.map(new Function() { - @Override - public Buffer apply(Object o) { - if (o instanceof ReactiveRoutes.ServerSentEvent) { - ReactiveRoutes.ServerSentEvent ev = (ReactiveRoutes.ServerSentEvent) o; - long id = ev.id() != -1 ? ev.id() : count.getAndIncrement(); - String e = ev.event() == null ? "" : "event: " + ev.event() + "\n"; - return Buffer.buffer(e + "data: " + ev.data() + "\nid: " + id + "\n\n"); - } else { - return Buffer.buffer("data: " + o + "\nid: " + count.getAndIncrement() + "\n\n"); + if (response.bytesWritten() == 0) { + // No events written - still set SSE content type + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } } + response.end(); } - }), rc); - } - - private static void endOfStream(HttpServerResponse response) { - if (response.bytesWritten() == 0) { // No item - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); + }); } } diff --git a/server-common/src/main/java/io/a2a/server/ServerCallContext.java b/server-common/src/main/java/io/a2a/server/ServerCallContext.java index ba5c20b95..c12c60c21 100644 --- a/server-common/src/main/java/io/a2a/server/ServerCallContext.java +++ b/server-common/src/main/java/io/a2a/server/ServerCallContext.java @@ -16,6 +16,7 @@ public class ServerCallContext { private final Set requestedExtensions; private final Set activatedExtensions; private final @Nullable String requestedProtocolVersion; + private volatile @Nullable Runnable eventConsumerCancelCallback; public ServerCallContext(User user, Map state, Set requestedExtensions) { this(user, state, requestedExtensions, null); @@ -64,4 +65,64 @@ public boolean isExtensionRequested(String extensionUri) { public @Nullable String getRequestedProtocolVersion() { return requestedProtocolVersion; } + + /** + * Sets the callback to be invoked when the client disconnects or the call is cancelled. + *

    + * This callback is typically used to stop the EventConsumer polling loop when a client + * disconnects from a streaming endpoint. The callback is invoked by transport layers + * (JSON-RPC over HTTP/SSE, REST over HTTP/SSE, gRPC streaming) when they detect that + * the client has closed the connection. + *

    + *

    + * Thread Safety: The callback may be invoked from any thread, depending + * on the transport implementation. Implementations should be thread-safe. + *

    + * Example Usage: + *
    {@code
    +     * EventConsumer consumer = new EventConsumer(queue);
    +     * context.setEventConsumerCancelCallback(consumer::cancel);
    +     * }
    + * + * @param callback the callback to invoke on client disconnect, or null to clear any existing callback + * @see #invokeEventConsumerCancelCallback() + */ + public void setEventConsumerCancelCallback(@Nullable Runnable callback) { + this.eventConsumerCancelCallback = callback; + } + + /** + * Invokes the EventConsumer cancel callback if one has been set. + *

    + * This method is called by transport layers when a client disconnects or cancels a + * streaming request. It triggers the callback registered via + * {@link #setEventConsumerCancelCallback(Runnable)}, which typically stops the + * EventConsumer polling loop. + *

    + *

    + * Transport-Specific Behavior: + *

    + *
      + *
    • JSON-RPC/REST over HTTP/SSE: Called from Vert.x + * {@code HttpServerResponse.closeHandler()} when the SSE connection is closed
    • + *
    • gRPC streaming: Called from gRPC + * {@code Context.CancellationListener.cancelled()} when the call is cancelled
    • + *
    + *

    + * Thread Safety: This method is thread-safe. The callback is stored + * in a volatile field and null-checked before invocation to prevent race conditions. + *

    + *

    + * If no callback has been set, this method does nothing (no-op). + *

    + * + * @see #setEventConsumerCancelCallback(Runnable) + * @see io.a2a.server.events.EventConsumer#cancel() + */ + public void invokeEventConsumerCancelCallback() { + Runnable callback = this.eventConsumerCancelCallback; + if (callback != null) { + callback.run(); + } + } } 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 d4fe5b395..7c7b28452 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 @@ -19,10 +19,17 @@ public class EventConsumer { private static final Logger LOGGER = LoggerFactory.getLogger(EventConsumer.class); private final EventQueue queue; private volatile @Nullable Throwable error; + private volatile boolean cancelled = false; + private volatile boolean agentCompleted = false; + private volatile int pollTimeoutsAfterAgentCompleted = 0; private static final String ERROR_MSG = "Agent did not return any response"; private static final int NO_WAIT = -1; private static final int QUEUE_WAIT_MILLISECONDS = 500; + // In replicated scenarios, events can arrive hundreds of milliseconds after local agent completes + // Grace period allows Kafka replication to deliver late-arriving events + // 3 timeouts * 500ms = 1500ms grace period for replication delays + private static final int MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED = 3; public EventConsumer(EventQueue queue) { this.queue = queue; @@ -45,6 +52,14 @@ public Flow.Publisher consumeAll() { boolean completed = false; try { while (true) { + // Check if cancelled by client disconnect + if (cancelled) { + LOGGER.debug("EventConsumer detected cancellation, exiting polling loop for queue {}", System.identityHashCode(queue)); + completed = true; + tube.complete(); + return; + } + if (error != null) { completed = true; tube.fail(error); @@ -60,13 +75,49 @@ public Flow.Publisher consumeAll() { EventQueueItem item; Event event; try { + LOGGER.debug("EventConsumer polling queue {} (error={}, agentCompleted={})", + System.identityHashCode(queue), error, agentCompleted); item = queue.dequeueEventItem(QUEUE_WAIT_MILLISECONDS); if (item == null) { + int queueSize = queue.size(); + LOGGER.debug("EventConsumer poll timeout (null item), agentCompleted={}, queue.size()={}, timeoutCount={}", + agentCompleted, queueSize, pollTimeoutsAfterAgentCompleted); + // If agent completed, a poll timeout means no more events are coming + // MainEventBusProcessor has 500ms to distribute events from MainEventBus + // If we timeout with agentCompleted=true, all events have been distributed + // + // IMPORTANT: In replicated scenarios, remote events may arrive AFTER local agent completes! + // Use grace period to allow for Kafka replication delays (can be 400-500ms) + if (agentCompleted && queueSize == 0) { + pollTimeoutsAfterAgentCompleted++; + if (pollTimeoutsAfterAgentCompleted >= MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED) { + LOGGER.debug("Agent completed with {} consecutive poll timeouts and empty queue, closing for graceful completion (queue={})", + pollTimeoutsAfterAgentCompleted, System.identityHashCode(queue)); + queue.close(); + completed = true; + tube.complete(); + return; + } else { + LOGGER.debug("Agent completed but grace period active ({}/{} timeouts), continuing to poll (queue={})", + pollTimeoutsAfterAgentCompleted, MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED, System.identityHashCode(queue)); + } + } else if (agentCompleted && queueSize > 0) { + LOGGER.debug("Agent completed but queue has {} pending events, resetting timeout counter and continuing to poll (queue={})", + queueSize, System.identityHashCode(queue)); + pollTimeoutsAfterAgentCompleted = 0; // Reset counter when events arrive + } continue; } + // Event received - reset timeout counter + pollTimeoutsAfterAgentCompleted = 0; event = item.getEvent(); + LOGGER.debug("EventConsumer received event: {} (queue={})", + event.getClass().getSimpleName(), System.identityHashCode(queue)); + // Defensive logging for error handling if (event instanceof Throwable thr) { + LOGGER.debug("EventConsumer detected Throwable event: {} - triggering tube.fail()", + thr.getClass().getSimpleName()); tube.fail(thr); return; } @@ -90,14 +141,30 @@ public Flow.Publisher consumeAll() { // Only send event if it's not a QueueClosedEvent // QueueClosedEvent is an internal coordination event used for replication // and should not be exposed to API consumers + boolean isFinalSent = false; if (!(event instanceof QueueClosedEvent)) { tube.send(item); + isFinalSent = isFinalEvent; } if (isFinalEvent) { LOGGER.debug("Final or interrupted event detected, closing queue and breaking loop for queue {}", System.identityHashCode(queue)); queue.close(); LOGGER.debug("Queue closed, breaking loop for queue {}", System.identityHashCode(queue)); + + // CRITICAL: Allow tube buffer to flush before calling tube.complete() + // tube.send() buffers events asynchronously. If we call tube.complete() immediately, + // the stream-end signal can reach the client BEFORE the buffered final event, + // causing the client to close the connection and never receive the final event. + // This is especially important in replicated scenarios where events arrive via Kafka + // and timing is less deterministic. A small delay ensures the buffer flushes. + if (isFinalSent) { + try { + Thread.sleep(50); // 50ms to allow SSE buffer flush + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } break; } } catch (EventQueueClosedException e) { @@ -138,12 +205,25 @@ private boolean isStreamTerminatingTask(Task task) { public EnhancedRunnable.DoneCallback createAgentRunnableDoneCallback() { return agentRunnable -> { + LOGGER.debug("EventConsumer: Agent done callback invoked (hasError={}, queue={})", + agentRunnable.getError() != null, System.identityHashCode(queue)); if (agentRunnable.getError() != null) { error = agentRunnable.getError(); + LOGGER.debug("EventConsumer: Set error field from agent callback"); + } else { + agentCompleted = true; + LOGGER.debug("EventConsumer: Agent completed successfully, set agentCompleted=true, will close queue after draining"); } }; } + public void cancel() { + // Set cancellation flag to stop polling loop + // Called when client disconnects without completing stream + LOGGER.debug("EventConsumer cancelled (client disconnect), stopping polling for queue {}", System.identityHashCode(queue)); + cancelled = true; + } + public void close() { // Close the queue to stop the polling loop in consumeAll() // This will cause EventQueueClosedException and exit the while(true) loop 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 a08f63084..99f8bc2dc 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 @@ -1,6 +1,7 @@ package io.a2a.server.events; import java.util.List; +import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; @@ -11,6 +12,8 @@ import io.a2a.server.tasks.TaskStateProvider; import io.a2a.spec.Event; +import io.a2a.spec.Task; +import io.a2a.spec.TaskStatusUpdateEvent; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,7 +26,7 @@ * and hierarchical queue structures via MainQueue and ChildQueue implementations. *

    *

    - * Use {@link #builder()} to create configured instances or extend MainQueue/ChildQueue directly. + * Use {@link #builder(MainEventBus)} to create configured instances or extend MainQueue/ChildQueue directly. *

    */ public abstract class EventQueue implements AutoCloseable { @@ -36,14 +39,6 @@ public abstract class EventQueue implements AutoCloseable { public static final int DEFAULT_QUEUE_SIZE = 1000; private final int queueSize; - /** - * Internal blocking queue for storing event queue items. - */ - protected final BlockingQueue queue = new LinkedBlockingDeque<>(); - /** - * Semaphore for backpressure control, limiting the number of pending events. - */ - protected final Semaphore semaphore; private volatile boolean closed = false; /** @@ -64,7 +59,6 @@ protected EventQueue(int queueSize) { throw new IllegalArgumentException("Queue size must be greater than 0"); } this.queueSize = queueSize; - this.semaphore = new Semaphore(queueSize, true); LOGGER.trace("Creating {} with queue size: {}", this, queueSize); } @@ -78,8 +72,8 @@ protected EventQueue(EventQueue parent) { LOGGER.trace("Creating {}, parent: {}", this, parent); } - static EventQueueBuilder builder() { - return new EventQueueBuilder(); + static EventQueueBuilder builder(MainEventBus mainEventBus) { + return new EventQueueBuilder().mainEventBus(mainEventBus); } /** @@ -95,6 +89,7 @@ public static class EventQueueBuilder { private @Nullable String taskId; private List onCloseCallbacks = new java.util.ArrayList<>(); private @Nullable TaskStateProvider taskStateProvider; + private @Nullable MainEventBus mainEventBus; /** * Sets the maximum queue size. @@ -153,17 +148,31 @@ public EventQueueBuilder taskStateProvider(TaskStateProvider taskStateProvider) return this; } + /** + * Sets the main event bus + * + * @param mainEventBus the main event bus + * @return this builder + */ + public EventQueueBuilder mainEventBus(MainEventBus mainEventBus) { + this.mainEventBus = mainEventBus; + return this; + } + /** * Builds and returns the configured EventQueue. * * @return a new MainQueue instance */ public EventQueue build() { - if (hook != null || !onCloseCallbacks.isEmpty() || taskStateProvider != null) { - return new MainQueue(queueSize, hook, taskId, onCloseCallbacks, taskStateProvider); - } else { - return new MainQueue(queueSize); + // MainEventBus is REQUIRED - enforce single architectural path + if (mainEventBus == null) { + throw new IllegalStateException("MainEventBus is required for EventQueue creation"); } + if (taskId == null) { + throw new IllegalStateException("taskId is required for EventQueue creation"); + } + return new MainQueue(queueSize, hook, taskId, onCloseCallbacks, taskStateProvider, mainEventBus); } } @@ -209,21 +218,39 @@ public void enqueueEvent(Event event) { * @param item the event queue item to enqueue * @throws RuntimeException if interrupted while waiting to acquire the semaphore */ - public void enqueueItem(EventQueueItem item) { - Event event = item.getEvent(); - if (closed) { - LOGGER.warn("Queue is closed. Event will not be enqueued. {} {}", this, event); - return; - } - // Call toString() since for errors we don't really want the full stacktrace - try { - semaphore.acquire(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Unable to acquire the semaphore to enqueue the event", e); - } - queue.add(item); - LOGGER.debug("Enqueued event {} {}", event instanceof Throwable ? event.toString() : event, this); + public abstract void enqueueItem(EventQueueItem item); + + /** + * Enqueues an event directly to this specific queue only, bypassing the MainEventBus. + *

    + * This method is used for enqueuing already-persisted events (e.g., current task state + * on resubscribe) that should only be sent to this specific subscriber, not distributed + * to all children or sent through MainEventBusProcessor. + *

    + *

    + * Default implementation throws UnsupportedOperationException. Only ChildQueue supports this. + *

    + * + * @param item the event queue item to enqueue directly + * @throws UnsupportedOperationException if called on MainQueue or other queue types + */ + public void enqueueLocalOnly(EventQueueItem item) { + throw new UnsupportedOperationException( + "enqueueLocalOnly is only supported on ChildQueue for resubscribe scenarios"); + } + + /** + * Enqueues an event directly to this specific queue only, bypassing the MainEventBus. + *

    + * Convenience method that wraps the event in a LocalEventQueueItem before calling + * {@link #enqueueLocalOnly(EventQueueItem)}. + *

    + * + * @param event the event to enqueue directly + * @throws UnsupportedOperationException if called on MainQueue or other queue types + */ + public void enqueueEventLocalOnly(Event event) { + enqueueLocalOnly(new LocalEventQueueItem(event)); } /** @@ -244,48 +271,17 @@ public void enqueueItem(EventQueueItem item) { * This method returns the full EventQueueItem wrapper, allowing callers to check * metadata like whether the event is replicated via {@link EventQueueItem#isReplicated()}. *

    + *

    + * Note: MainQueue does not support dequeue operations - only ChildQueues can be consumed. + *

    * * @param waitMilliSeconds the maximum time to wait in milliseconds * @return the EventQueueItem, or null if timeout occurs * @throws EventQueueClosedException if the queue is closed and empty + * @throws UnsupportedOperationException if called on MainQueue */ - public @Nullable EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueClosedException { - if (closed && queue.isEmpty()) { - LOGGER.debug("Queue is closed, and empty. Sending termination message. {}", this); - throw new EventQueueClosedException(); - } - try { - if (waitMilliSeconds <= 0) { - EventQueueItem item = queue.poll(); - if (item != null) { - Event event = item.getEvent(); - // Call toString() since for errors we don't really want the full stacktrace - LOGGER.debug("Dequeued event item (no wait) {} {}", this, event instanceof Throwable ? event.toString() : event); - semaphore.release(); - } - return item; - } - try { - LOGGER.trace("Polling queue {} (wait={}ms)", System.identityHashCode(this), waitMilliSeconds); - EventQueueItem item = queue.poll(waitMilliSeconds, TimeUnit.MILLISECONDS); - if (item != null) { - Event event = item.getEvent(); - // Call toString() since for errors we don't really want the full stacktrace - LOGGER.debug("Dequeued event item (waiting) {} {}", this, event instanceof Throwable ? event.toString() : event); - semaphore.release(); - } else { - LOGGER.trace("Dequeue timeout (null) from queue {}", System.identityHashCode(this)); - } - return item; - } catch (InterruptedException e) { - LOGGER.debug("Interrupted dequeue (waiting) {}", this); - Thread.currentThread().interrupt(); - return null; - } - } finally { - signalQueuePollerStarted(); - } - } + @Nullable + public abstract EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueClosedException; /** * Placeholder method for task completion notification. @@ -295,6 +291,18 @@ public void taskDone() { // TODO Not sure if needed yet. BlockingQueue.poll()/.take() remove the events. } + /** + * Returns the current size of the queue. + *

    + * For MainQueue: returns the number of events in-flight (in MainEventBus queue + currently being processed). + * This reflects actual capacity usage tracked by the semaphore. + * For ChildQueue: returns the size of the local consumption queue. + *

    + * + * @return the number of events currently in the queue + */ + public abstract int size(); + /** * Closes this event queue gracefully, allowing pending events to be consumed. */ @@ -348,72 +356,71 @@ protected void doClose(boolean immediate) { LOGGER.debug("Closing {} (immediate={})", this, immediate); closed = true; } - - if (immediate) { - // Immediate close: clear pending events - queue.clear(); - LOGGER.debug("Cleared queue for immediate close: {}", this); - } - // For graceful close, let the queue drain naturally through normal consumption + // Subclasses handle immediate close logic (e.g., ChildQueue clears its local queue) } static class MainQueue extends EventQueue { private final List children = new CopyOnWriteArrayList<>(); + protected final Semaphore semaphore; private final CountDownLatch pollingStartedLatch = new CountDownLatch(1); private final AtomicBoolean pollingStarted = new AtomicBoolean(false); private final @Nullable EventEnqueueHook enqueueHook; - private final @Nullable String taskId; + private final String taskId; private final List onCloseCallbacks; private final @Nullable TaskStateProvider taskStateProvider; - - MainQueue() { - super(); - this.enqueueHook = null; - this.taskId = null; - this.onCloseCallbacks = List.of(); - this.taskStateProvider = null; - } - - MainQueue(int queueSize) { - super(queueSize); - this.enqueueHook = null; - this.taskId = null; - this.onCloseCallbacks = List.of(); - this.taskStateProvider = null; - } - - MainQueue(EventEnqueueHook hook) { - super(); - this.enqueueHook = hook; - this.taskId = null; - this.onCloseCallbacks = List.of(); - this.taskStateProvider = null; - } - - MainQueue(int queueSize, EventEnqueueHook hook) { - super(queueSize); - this.enqueueHook = hook; - this.taskId = null; - this.onCloseCallbacks = List.of(); - this.taskStateProvider = null; - } - - MainQueue(int queueSize, @Nullable EventEnqueueHook hook, @Nullable String taskId, List onCloseCallbacks, @Nullable TaskStateProvider taskStateProvider) { + private final MainEventBus mainEventBus; + + MainQueue(int queueSize, + @Nullable EventEnqueueHook hook, + String taskId, + List onCloseCallbacks, + @Nullable TaskStateProvider taskStateProvider, + @Nullable MainEventBus mainEventBus) { super(queueSize); + this.semaphore = new Semaphore(queueSize, true); this.enqueueHook = hook; this.taskId = taskId; this.onCloseCallbacks = List.copyOf(onCloseCallbacks); // Defensive copy this.taskStateProvider = taskStateProvider; - LOGGER.debug("Created MainQueue for task {} with {} onClose callbacks and TaskStateProvider: {}", + this.mainEventBus = Objects.requireNonNull(mainEventBus, "MainEventBus is required"); + LOGGER.debug("Created MainQueue for task {} with {} onClose callbacks, TaskStateProvider: {}, MainEventBus configured", taskId, onCloseCallbacks.size(), taskStateProvider != null); } + public EventQueue tap() { ChildQueue child = new ChildQueue(this); children.add(child); return child; } + /** + * Returns the current number of child queues. + * Useful for debugging and logging event distribution. + */ + public int getChildCount() { + return children.size(); + } + + /** + * Returns the enqueue hook for replication (package-protected for MainEventBusProcessor). + */ + @Nullable EventEnqueueHook getEnqueueHook() { + return enqueueHook; + } + + @Override + public EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueClosedException { + throw new UnsupportedOperationException("MainQueue cannot be consumed directly - use tap() to create a ChildQueue for consumption"); + } + + @Override + public int size() { + // Return total in-flight events (in MainEventBus + being processed) + // This aligns with semaphore's capacity tracking + return getQueueSize() - semaphore.availablePermits(); + } + @Override public void enqueueItem(EventQueueItem item) { // MainQueue must accept events even when closed to support: @@ -424,6 +431,15 @@ public void enqueueItem(EventQueueItem item) { // We bypass the parent's closed check and enqueue directly Event event = item.getEvent(); + // Check if this is a final event BEFORE submitting to MainEventBus + // If it is, notify all children to expect it (so they wait for MainEventBusProcessor) + if (isFinalEvent(event)) { + LOGGER.debug("Final event detected, notifying {} children to expect it", children.size()); + for (ChildQueue child : children) { + child.expectFinalEvent(); + } + } + // Acquire semaphore for backpressure try { semaphore.acquire(); @@ -432,17 +448,27 @@ public void enqueueItem(EventQueueItem item) { throw new RuntimeException("Unable to acquire the semaphore to enqueue the event", e); } - // Add to this MainQueue's internal queue - queue.add(item); LOGGER.debug("Enqueued event {} {}", event instanceof Throwable ? event.toString() : event, this); - // Distribute to all ChildQueues (they will receive the event even if MainQueue is closed) - children.forEach(eq -> eq.internalEnqueueItem(item)); + // Submit to MainEventBus for centralized persistence + distribution + // MainEventBus is guaranteed non-null by constructor requirement + // Note: Replication now happens in MainEventBusProcessor AFTER persistence - // Trigger replication hook if configured - if (enqueueHook != null) { - enqueueHook.onEnqueue(item); + // Submit event to MainEventBus with our taskId + mainEventBus.submit(taskId, this, item); + } + + /** + * Checks if an event represents a final task state. + */ + private boolean isFinalEvent(Event event) { + if (event instanceof Task task) { + return task.status() != null && task.status().state() != null + && task.status().state().isFinal(); + } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { + return statusUpdate.isFinal(); } + return false; } @Override @@ -465,20 +491,15 @@ public void signalQueuePollerStarted() { void childClosing(ChildQueue child, boolean immediate) { children.remove(child); // Remove the closing child - // Close immediately if requested - if (immediate) { - LOGGER.debug("MainQueue closing immediately (immediate=true)"); - this.doClose(immediate); - return; - } - // If there are still children, keep queue open if (!children.isEmpty()) { LOGGER.debug("MainQueue staying open: {} children remaining", children.size()); return; } - // No children left - check if task is finalized before auto-closing + // No children left - check if task is finalized before closing + // IMPORTANT: This check must happen BEFORE the immediate flag check + // to prevent closing queues for non-final tasks (fire-and-forget, resubscription support) if (taskStateProvider != null && taskId != null) { boolean isFinalized = taskStateProvider.isTaskFinalized(taskId); if (!isFinalized) { @@ -493,6 +514,36 @@ void childClosing(ChildQueue child, boolean immediate) { this.doClose(immediate); } + /** + * Distribute event to all ChildQueues. + * Called by MainEventBusProcessor after TaskStore persistence. + */ + void distributeToChildren(EventQueueItem item) { + int childCount = children.size(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("MainQueue[{}]: Distributing event {} to {} children", + taskId, item.getEvent().getClass().getSimpleName(), childCount); + } + children.forEach(child -> { + LOGGER.debug("MainQueue[{}]: Enqueueing event {} to child queue", + taskId, item.getEvent().getClass().getSimpleName()); + child.internalEnqueueItem(item); + }); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("MainQueue[{}]: Completed distribution of {} to {} children", + taskId, item.getEvent().getClass().getSimpleName(), childCount); + } + } + + /** + * Release the semaphore after event processing is complete. + * Called by MainEventBusProcessor in finally block to ensure release even on exceptions. + * Balances the acquire() in enqueueEvent() - protects MainEventBus throughput. + */ + void releaseSemaphore() { + semaphore.release(); + } + /** * Get the count of active child queues. * Used for testing to verify reference counting mechanism. @@ -539,10 +590,17 @@ public void close(boolean immediate) { public void close(boolean immediate, boolean notifyParent) { throw new UnsupportedOperationException("MainQueue does not support notifyParent parameter - use close(boolean) instead"); } + + String getTaskId() { + return taskId; + } } static class ChildQueue extends EventQueue { private final MainQueue parent; + private final BlockingQueue queue = new LinkedBlockingDeque<>(); + private volatile boolean immediateClose = false; + private volatile boolean awaitingFinalEvent = false; public ChildQueue(MainQueue parent) { this.parent = parent; @@ -553,8 +611,94 @@ public void enqueueEvent(Event event) { parent.enqueueEvent(event); } + @Override + public void enqueueItem(EventQueueItem item) { + // ChildQueue delegates writes to parent MainQueue + parent.enqueueItem(item); + } + private void internalEnqueueItem(EventQueueItem item) { - super.enqueueItem(item); + // Internal method called by MainEventBusProcessor to add to local queue + // Note: Semaphore is managed by parent MainQueue (acquire/release), not ChildQueue + Event event = item.getEvent(); + // For graceful close: still accept events so they can be drained by EventConsumer + // For immediate close: reject events to stop distribution quickly + if (isClosed() && immediateClose) { + LOGGER.warn("ChildQueue is immediately closed. Event will not be enqueued. {} {}", this, event); + return; + } + if (!queue.offer(item)) { + LOGGER.warn("ChildQueue {} is full. Closing immediately.", this); + close(true); // immediate close + } else { + LOGGER.debug("Enqueued event {} {}", event instanceof Throwable ? event.toString() : event, this); + + // If we were awaiting a final event and this is it, clear the flag + if (awaitingFinalEvent && isFinalEvent(event)) { + awaitingFinalEvent = false; + LOGGER.debug("ChildQueue {} received awaited final event", System.identityHashCode(this)); + } + } + } + + /** + * Checks if an event represents a final task state. + */ + private boolean isFinalEvent(Event event) { + if (event instanceof Task task) { + return task.status() != null && task.status().state() != null + && task.status().state().isFinal(); + } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { + return statusUpdate.isFinal(); + } + return false; + } + + @Override + public void enqueueLocalOnly(EventQueueItem item) { + internalEnqueueItem(item); + } + + @Override + @Nullable + public EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueClosedException { + // For immediate close: exit immediately even if queue is not empty (race with MainEventBusProcessor) + // For graceful close: only exit when queue is empty (wait for all events to be consumed) + // BUT: if awaiting final event, keep polling even if closed and empty + if (isClosed() && (queue.isEmpty() || immediateClose) && !awaitingFinalEvent) { + LOGGER.debug("ChildQueue is closed{}, sending termination message. {} (queueSize={})", + immediateClose ? " (immediate)" : " and empty", + this, + queue.size()); + throw new EventQueueClosedException(); + } + try { + if (waitMilliSeconds <= 0) { + EventQueueItem item = queue.poll(); + if (item != null) { + Event event = item.getEvent(); + LOGGER.debug("Dequeued event item (no wait) {} {}", this, event instanceof Throwable ? event.toString() : event); + } + return item; + } + try { + LOGGER.trace("Polling ChildQueue {} (wait={}ms)", System.identityHashCode(this), waitMilliSeconds); + EventQueueItem item = queue.poll(waitMilliSeconds, TimeUnit.MILLISECONDS); + if (item != null) { + Event event = item.getEvent(); + LOGGER.debug("Dequeued event item (waiting) {} {}", this, event instanceof Throwable ? event.toString() : event); + } else { + LOGGER.trace("Dequeue timeout (null) from ChildQueue {}", System.identityHashCode(this)); + } + return item; + } catch (InterruptedException e) { + LOGGER.debug("Interrupted dequeue (waiting) {}", this); + Thread.currentThread().interrupt(); + return null; + } + } finally { + signalQueuePollerStarted(); + } } @Override @@ -562,6 +706,12 @@ public EventQueue tap() { throw new IllegalStateException("Can only tap the main queue"); } + @Override + public int size() { + // Return size of local consumption queue + return queue.size(); + } + @Override public void awaitQueuePollerStart() throws InterruptedException { parent.awaitQueuePollerStart(); @@ -572,6 +722,29 @@ public void signalQueuePollerStarted() { parent.signalQueuePollerStarted(); } + @Override + protected void doClose(boolean immediate) { + super.doClose(immediate); // Sets closed flag + if (immediate) { + // Immediate close: clear pending events from local queue + this.immediateClose = true; + int clearedCount = queue.size(); + queue.clear(); + LOGGER.debug("Cleared {} events from ChildQueue for immediate close: {}", clearedCount, this); + } + // For graceful close, let the queue drain naturally through normal consumption + } + + /** + * Notifies this ChildQueue to expect a final event. + * Called by MainQueue when it enqueues a final event, BEFORE submitting to MainEventBus. + * This ensures the ChildQueue keeps polling until the final event arrives (after MainEventBusProcessor). + */ + void expectFinalEvent() { + awaitingFinalEvent = true; + LOGGER.debug("ChildQueue {} now awaiting final event", System.identityHashCode(this)); + } + @Override public void close() { close(false); 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 e5a17e0e7..53a089e4c 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 @@ -34,16 +34,20 @@ protected InMemoryQueueManager() { this.taskStateProvider = null; } + MainEventBus mainEventBus; + @Inject - public InMemoryQueueManager(TaskStateProvider taskStateProvider) { + public InMemoryQueueManager(TaskStateProvider taskStateProvider, MainEventBus mainEventBus) { + this.mainEventBus = mainEventBus; this.factory = new DefaultEventQueueFactory(); this.taskStateProvider = taskStateProvider; } - // For testing with custom factory - public InMemoryQueueManager(EventQueueFactory factory, TaskStateProvider taskStateProvider) { + // For testing/extensions with custom factory and MainEventBus + public InMemoryQueueManager(EventQueueFactory factory, TaskStateProvider taskStateProvider, MainEventBus mainEventBus) { this.factory = factory; this.taskStateProvider = taskStateProvider; + this.mainEventBus = mainEventBus; } @Override @@ -101,7 +105,6 @@ public EventQueue createOrTap(String taskId) { EventQueue newQueue = null; if (existing == null) { // Use builder pattern for cleaner queue creation - // Use the new taskId-aware builder method if available newQueue = factory.builder(taskId).build(); // Make sure an existing queue has not been added in the meantime existing = queues.putIfAbsent(taskId, newQueue); @@ -128,6 +131,12 @@ public void awaitQueuePollerStart(EventQueue eventQueue) throws InterruptedExcep eventQueue.awaitQueuePollerStart(); } + @Override + public EventQueue.EventQueueBuilder getEventQueueBuilder(String taskId) { + // Use the factory to ensure proper configuration (MainEventBus, callbacks, etc.) + return factory.builder(taskId); + } + @Override public int getActiveChildQueueCount(String taskId) { EventQueue queue = queues.get(taskId); @@ -142,6 +151,14 @@ public int getActiveChildQueueCount(String taskId) { return -1; } + @Override + public EventQueue.EventQueueBuilder createBaseEventQueueBuilder(String taskId) { + return EventQueue.builder(mainEventBus) + .taskId(taskId) + .addOnCloseCallback(getCleanupCallback(taskId)) + .taskStateProvider(taskStateProvider); + } + /** * Get the cleanup callback that removes a queue from the map when it closes. * This is exposed so that subclasses (like ReplicatedQueueManager) can reuse @@ -181,11 +198,8 @@ public Runnable getCleanupCallback(String taskId) { private class DefaultEventQueueFactory implements EventQueueFactory { @Override public EventQueue.EventQueueBuilder builder(String taskId) { - // Return builder with callback that removes queue from map when closed - return EventQueue.builder() - .taskId(taskId) - .addOnCloseCallback(getCleanupCallback(taskId)) - .taskStateProvider(taskStateProvider); + // Delegate to the base builder creation method + return createBaseEventQueueBuilder(taskId); } } } diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBus.java b/server-common/src/main/java/io/a2a/server/events/MainEventBus.java new file mode 100644 index 000000000..90080b1e2 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBus.java @@ -0,0 +1,42 @@ +package io.a2a.server.events; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class MainEventBus { + private static final Logger LOGGER = LoggerFactory.getLogger(MainEventBus.class); + private final BlockingQueue queue; + + public MainEventBus() { + this.queue = new LinkedBlockingDeque<>(); + } + + void submit(String taskId, EventQueue.MainQueue mainQueue, EventQueueItem item) { + try { + queue.put(new MainEventBusContext(taskId, mainQueue, item)); + LOGGER.debug("Submitted event for task {} to MainEventBus (queue size: {})", + taskId, queue.size()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted submitting to MainEventBus", e); + } + } + + MainEventBusContext take() throws InterruptedException { + LOGGER.debug("MainEventBus: Waiting to take event (current queue size: {})...", queue.size()); + MainEventBusContext context = queue.take(); + LOGGER.debug("MainEventBus: Took event for task {} (remaining queue size: {})", + context.taskId(), queue.size()); + return context; + } + + public int size() { + return queue.size(); + } +} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java new file mode 100644 index 000000000..292a60f21 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java @@ -0,0 +1,11 @@ +package io.a2a.server.events; + +import java.util.Objects; + +record MainEventBusContext(String taskId, EventQueue.MainQueue eventQueue, EventQueueItem eventQueueItem) { + MainEventBusContext { + Objects.requireNonNull(taskId, "taskId cannot be null"); + Objects.requireNonNull(eventQueue, "eventQueue cannot be null"); + Objects.requireNonNull(eventQueueItem, "eventQueueItem cannot be null"); + } +} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java new file mode 100644 index 000000000..8b3dc6fa3 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java @@ -0,0 +1,386 @@ +package io.a2a.server.events; + +import java.util.concurrent.CompletableFuture; + +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import io.a2a.server.tasks.PushNotificationSender; +import io.a2a.server.tasks.TaskManager; +import io.a2a.server.tasks.TaskStore; +import io.a2a.spec.A2AServerException; +import io.a2a.spec.Event; +import io.a2a.spec.InternalError; +import io.a2a.spec.Message; +import io.a2a.spec.Task; +import io.a2a.spec.TaskArtifactUpdateEvent; +import io.a2a.spec.TaskStatusUpdateEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Background processor for the MainEventBus. + *

    + * This processor runs in a dedicated background thread, consuming events from the MainEventBus + * and performing two critical operations in order: + *

    + *
      + *
    1. Update TaskStore with event data (persistence FIRST)
    2. + *
    3. Distribute event to ChildQueues (clients see it AFTER persistence)
    4. + *
    + *

    + * This architecture ensures clients never receive events before they're persisted, + * eliminating race conditions and enabling reliable event replay. + *

    + *

    + * Note: This bean is eagerly initialized by {@link MainEventBusProcessorInitializer} + * to ensure the background thread starts automatically when the application starts. + *

    + */ +@ApplicationScoped +public class MainEventBusProcessor implements Runnable { + private static final Logger LOGGER = LoggerFactory.getLogger(MainEventBusProcessor.class); + + /** + * Callback for testing synchronization with async event processing. + * Default is NOOP to avoid null checks in production code. + * Tests can inject their own callback via setCallback(). + */ + private volatile MainEventBusProcessorCallback callback = MainEventBusProcessorCallback.NOOP; + + /** + * Optional executor for push notifications. + * If null, uses default ForkJoinPool (async). + * Tests can inject a synchronous executor to ensure deterministic ordering. + */ + private volatile @Nullable java.util.concurrent.Executor pushNotificationExecutor = null; + + private final MainEventBus eventBus; + + private final TaskStore taskStore; + + private final PushNotificationSender pushSender; + + private final QueueManager queueManager; + + private volatile boolean running = true; + private @Nullable Thread processorThread; + + @Inject + public MainEventBusProcessor(MainEventBus eventBus, TaskStore taskStore, PushNotificationSender pushSender, QueueManager queueManager) { + this.eventBus = eventBus; + this.taskStore = taskStore; + this.pushSender = pushSender; + this.queueManager = queueManager; + } + + /** + * Set a callback for testing synchronization with async event processing. + *

    + * This is primarily intended for tests that need to wait for event processing to complete. + * Pass null to reset to the default NOOP callback. + *

    + * + * @param callback the callback to invoke during event processing, or null for NOOP + */ + public void setCallback(MainEventBusProcessorCallback callback) { + this.callback = callback != null ? callback : MainEventBusProcessorCallback.NOOP; + } + + /** + * Set a custom executor for push notifications (primarily for testing). + *

    + * By default, push notifications are sent asynchronously using CompletableFuture.runAsync() + * with the default ForkJoinPool. For tests that need deterministic ordering of push + * notifications, inject a synchronous executor that runs tasks immediately on the calling thread. + *

    + * Example synchronous executor for tests: + *
    {@code
    +     * Executor syncExecutor = Runnable::run;
    +     * mainEventBusProcessor.setPushNotificationExecutor(syncExecutor);
    +     * }
    + * + * @param executor the executor to use for push notifications, or null to use default ForkJoinPool + */ + public void setPushNotificationExecutor(java.util.concurrent.Executor executor) { + this.pushNotificationExecutor = executor; + } + + @PostConstruct + void start() { + processorThread = new Thread(this, "MainEventBusProcessor"); + processorThread.setDaemon(true); // Allow JVM to exit even if this thread is running + processorThread.start(); + LOGGER.info("MainEventBusProcessor started"); + } + + /** + * No-op method to force CDI proxy resolution and ensure @PostConstruct has been called. + * Called by MainEventBusProcessorInitializer during application startup. + */ + public void ensureStarted() { + // Method intentionally empty - just forces proxy resolution + } + + @PreDestroy + void stop() { + LOGGER.info("MainEventBusProcessor stopping..."); + running = false; + if (processorThread != null) { + processorThread.interrupt(); + try { + long start = System.currentTimeMillis(); + processorThread.join(5000); // Wait up to 5 seconds + long elapsed = System.currentTimeMillis() - start; + LOGGER.info("MainEventBusProcessor thread stopped in {}ms", elapsed); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + LOGGER.warn("Interrupted while waiting for MainEventBusProcessor thread to stop"); + } + } + LOGGER.info("MainEventBusProcessor stopped"); + } + + @Override + public void run() { + LOGGER.info("MainEventBusProcessor processing loop started"); + while (running) { + try { + LOGGER.debug("MainEventBusProcessor: Waiting for event from MainEventBus..."); + MainEventBusContext context = eventBus.take(); + LOGGER.debug("MainEventBusProcessor: Retrieved event for task {} from MainEventBus", + context.taskId()); + processEvent(context); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + LOGGER.info("MainEventBusProcessor interrupted, shutting down"); + break; + } catch (Exception e) { + LOGGER.error("Error processing event from MainEventBus", e); + // Continue processing despite errors + } + } + LOGGER.info("MainEventBusProcessor processing loop ended"); + } + + private void processEvent(MainEventBusContext context) { + String taskId = context.taskId(); + Event event = context.eventQueueItem().getEvent(); + // MainEventBus.submit() guarantees this is always a MainQueue + EventQueue.MainQueue mainQueue = (EventQueue.MainQueue) context.eventQueue(); + + LOGGER.debug("MainEventBusProcessor: Processing event for task {}: {}", + taskId, event.getClass().getSimpleName()); + + Event eventToDistribute = null; + boolean isReplicated = context.eventQueueItem().isReplicated(); + try { + // Step 1: Update TaskStore FIRST (persistence before clients see it) + // If this throws, we distribute an error to ensure "persist before client visibility" + + try { + boolean isFinal = updateTaskStore(taskId, event, isReplicated); + + eventToDistribute = event; // Success - distribute original event + + // Trigger replication AFTER successful persistence + // SKIP replication if task is final - ReplicatedQueueManager handles this via TaskFinalizedEvent + // to ensure final Task is sent before poison pill (QueueClosedEvent) + if (!isFinal) { + EventEnqueueHook hook = mainQueue.getEnqueueHook(); + if (hook != null) { + LOGGER.debug("Triggering replication hook for task {} after successful persistence", taskId); + hook.onEnqueue(context.eventQueueItem()); + } + } else { + LOGGER.debug("Task {} is final - skipping replication hook (handled by ReplicatedQueueManager)", taskId); + } + } catch (InternalError e) { + // Persistence failed - create error event to distribute instead + LOGGER.error("Failed to persist event for task {}, distributing error to clients", taskId, e); + String errorMessage = "Failed to persist event: " + e.getMessage(); + eventToDistribute = e; + } catch (Exception e) { + LOGGER.error("Failed to persist event for task {}, distributing error to clients", taskId, e); + String errorMessage = "Failed to persist event: " + e.getMessage(); + eventToDistribute = new InternalError(errorMessage); + } + + // Step 2: Send push notification AFTER successful persistence (only from active node) + // Skip push notifications for replicated events to avoid duplicate notifications in multi-instance deployments + if (eventToDistribute == event && !isReplicated) { + // Capture task state immediately after persistence, before going async + // This ensures we send the task as it existed when THIS event was processed, + // not whatever state might exist later when the async callback executes + Task taskSnapshot = taskStore.get(taskId); + if (taskSnapshot != null) { + sendPushNotification(taskId, taskSnapshot); + } else { + LOGGER.warn("Task {} not found in TaskStore after successful persistence, skipping push notification", taskId); + } + } + + // Step 3: Then distribute to ChildQueues (clients see either event or error AFTER persistence attempt) + if (eventToDistribute == null) { + LOGGER.error("MainEventBusProcessor: eventToDistribute is NULL for task {} - this should never happen!", taskId); + eventToDistribute = new InternalError("Internal error: event processing failed"); + } + + int childCount = mainQueue.getChildCount(); + LOGGER.debug("MainEventBusProcessor: Distributing {} to {} children for task {}", + eventToDistribute.getClass().getSimpleName(), childCount, taskId); + // Create new EventQueueItem with the event to distribute (original or error) + EventQueueItem itemToDistribute = new LocalEventQueueItem(eventToDistribute); + mainQueue.distributeToChildren(itemToDistribute); + LOGGER.debug("MainEventBusProcessor: Distributed {} to {} children for task {}", + eventToDistribute.getClass().getSimpleName(), childCount, taskId); + + LOGGER.debug("MainEventBusProcessor: Completed processing event for task {}", taskId); + + } finally { + try { + // Step 4: Notify callback after all processing is complete + // Call callback with the distributed event (original or error) + if (eventToDistribute != null) { + callback.onEventProcessed(taskId, eventToDistribute); + + // Step 5: If this is a final event, notify task finalization + // Only for successful persistence (not for errors) + if (eventToDistribute == event && isFinalEvent(event)) { + callback.onTaskFinalized(taskId); + } + } + } finally { + // ALWAYS release semaphore, even if processing fails + // Balances the acquire() in MainQueue.enqueueEvent() + mainQueue.releaseSemaphore(); + } + } + } + + /** + * Updates TaskStore using TaskManager.process(). + *

    + * Creates a temporary TaskManager instance for this event and delegates to its process() method, + * which handles all event types (Task, TaskStatusUpdateEvent, TaskArtifactUpdateEvent). + * This leverages existing TaskManager logic for status updates, artifact appending, message history, etc. + *

    + *

    + * If persistence fails, the exception is propagated to processEvent() which distributes an + * InternalError to clients instead of the original event, ensuring "persist before visibility". + * See Gemini's comment: https://github.com/a2aproject/a2a-java/pull/515#discussion_r2604621833 + *

    + * + * @param taskId the task ID + * @param event the event to persist + * @return true if the task reached a final state, false otherwise + * @throws InternalError if persistence fails + */ + private boolean updateTaskStore(String taskId, Event event, boolean isReplicated) throws InternalError { + try { + // Extract contextId from event (all relevant events have it) + String contextId = extractContextId(event); + + // Create temporary TaskManager instance for this event + TaskManager taskManager = new TaskManager(taskId, contextId, taskStore, null); + + // Use TaskManager.process() - handles all event types with existing logic + boolean isFinal = taskManager.process(event, isReplicated); + LOGGER.debug("TaskStore updated via TaskManager.process() for task {}: {} (final: {}, replicated: {})", + taskId, event.getClass().getSimpleName(), isFinal, isReplicated); + return isFinal; + } catch (InternalError e) { + LOGGER.error("Error updating TaskStore via TaskManager for task {}", taskId, e); + // Rethrow to prevent distributing unpersisted event to clients + throw e; + } catch (Exception e) { + LOGGER.error("Unexpected error updating TaskStore for task {}", taskId, e); + // Rethrow to prevent distributing unpersisted event to clients + throw new InternalError("TaskStore persistence failed: " + e.getMessage()); + } + } + + /** + * Sends push notification for the task AFTER persistence. + *

    + * This is called after updateTaskStore() to ensure the notification contains + * the latest persisted state, avoiding race conditions. + *

    + *

    + * CRITICAL: Push notifications are sent asynchronously in the background + * to avoid blocking event distribution to ChildQueues. The 83ms overhead from + * PushNotificationSender.sendNotification() was causing streaming delays. + *

    + *

    + * IMPORTANT: The task parameter is a snapshot captured immediately after + * persistence. This ensures we send the task state as it existed when THIS event + * was processed, not whatever state might exist in TaskStore when the async + * callback executes (subsequent events may have already updated the store). + *

    + *

    + * NOTE: Tests can inject a synchronous executor via setPushNotificationExecutor() + * to ensure deterministic ordering of push notifications in the test environment. + *

    + * + * @param taskId the task ID + * @param task the task snapshot to send (captured immediately after persistence) + */ + private void sendPushNotification(String taskId, Task task) { + Runnable pushTask = () -> { + try { + if (task != null) { + LOGGER.debug("Sending push notification for task {}", taskId); + pushSender.sendNotification(task); + } else { + LOGGER.debug("Skipping push notification - task snapshot is null for task {}", taskId); + } + } catch (Exception e) { + LOGGER.error("Error sending push notification for task {}", taskId, e); + // Don't rethrow - push notifications are best-effort + } + }; + + // Use custom executor if set (for tests), otherwise use default ForkJoinPool (async) + if (pushNotificationExecutor != null) { + pushNotificationExecutor.execute(pushTask); + } else { + CompletableFuture.runAsync(pushTask); + } + } + + /** + * Extracts contextId from an event. + * Returns null if the event type doesn't have a contextId (e.g., Message). + */ + @Nullable + private String extractContextId(Event event) { + if (event instanceof Task task) { + return task.contextId(); + } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { + return statusUpdate.contextId(); + } else if (event instanceof TaskArtifactUpdateEvent artifactUpdate) { + return artifactUpdate.contextId(); + } + // Message and other events don't have contextId + return null; + } + + /** + * Checks if an event represents a final task state. + * + * @param event the event to check + * @return true if the event represents a final state (COMPLETED, FAILED, CANCELED, REJECTED, UNKNOWN) + */ + private boolean isFinalEvent(Event event) { + if (event instanceof Task task) { + return task.status() != null && task.status().state() != null + && task.status().state().isFinal(); + } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { + return statusUpdate.isFinal(); + } + return false; + } +} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java new file mode 100644 index 000000000..b0a9adbce --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java @@ -0,0 +1,66 @@ +package io.a2a.server.events; + +import io.a2a.spec.Event; + +/** + * Callback interface for MainEventBusProcessor events. + *

    + * This interface is primarily intended for testing, allowing tests to synchronize + * with the asynchronous MainEventBusProcessor. Production code should not rely on this. + *

    + * Usage in tests: + *
    + * {@code
    + * @Inject
    + * MainEventBusProcessor processor;
    + *
    + * @BeforeEach
    + * void setUp() {
    + *     CountDownLatch latch = new CountDownLatch(3);
    + *     processor.setCallback(new MainEventBusProcessorCallback() {
    + *         public void onEventProcessed(String taskId, Event event) {
    + *             latch.countDown();
    + *         }
    + *     });
    + * }
    + *
    + * @AfterEach
    + * void tearDown() {
    + *     processor.setCallback(null); // Reset to NOOP
    + * }
    + * }
    + * 
    + */ +public interface MainEventBusProcessorCallback { + + /** + * Called after an event has been fully processed (persisted, notification sent, distributed to children). + * + * @param taskId the task ID + * @param event the event that was processed + */ + void onEventProcessed(String taskId, Event event); + + /** + * Called when a task reaches a final state (COMPLETED, FAILED, CANCELED, REJECTED). + * + * @param taskId the task ID that was finalized + */ + void onTaskFinalized(String taskId); + + /** + * No-op implementation that does nothing. + * Used as the default callback to avoid null checks. + */ + MainEventBusProcessorCallback NOOP = new MainEventBusProcessorCallback() { + @Override + public void onEventProcessed(String taskId, Event event) { + // No-op + } + + @Override + public void onTaskFinalized(String taskId) { + // No-op + } + }; +} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java new file mode 100644 index 000000000..ba4b300be --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java @@ -0,0 +1,43 @@ +package io.a2a.server.events; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Initialized; +import jakarta.enterprise.event.Observes; +import jakarta.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Portable CDI initializer for MainEventBusProcessor. + *

    + * This bean observes the ApplicationScoped initialization event and injects + * MainEventBusProcessor, which triggers its eager creation and starts the background thread. + *

    + *

    + * This approach is portable across all Jakarta CDI implementations (Weld, OpenWebBeans, Quarkus, etc.) + * and ensures MainEventBusProcessor starts automatically when the application starts. + *

    + */ +@ApplicationScoped +public class MainEventBusProcessorInitializer { + private static final Logger LOGGER = LoggerFactory.getLogger(MainEventBusProcessorInitializer.class); + + @Inject + MainEventBusProcessor processor; + + /** + * Observes ApplicationScoped initialization to force eager creation of MainEventBusProcessor. + * The injection of MainEventBusProcessor in this bean triggers its creation, and calling + * ensureStarted() forces the CDI proxy to be resolved, which ensures @PostConstruct has been + * called and the background thread is running. + */ + void onStart(@Observes @Initialized(ApplicationScoped.class) Object event) { + if (processor != null) { + // Force proxy resolution to ensure @PostConstruct has been called + processor.ensureStarted(); + LOGGER.info("MainEventBusProcessor initialized and started"); + } else { + LOGGER.error("MainEventBusProcessor is null - initialization failed!"); + } + } +} diff --git a/server-common/src/main/java/io/a2a/server/events/QueueManager.java b/server-common/src/main/java/io/a2a/server/events/QueueManager.java index 01e754fcb..4ad30f0cb 100644 --- a/server-common/src/main/java/io/a2a/server/events/QueueManager.java +++ b/server-common/src/main/java/io/a2a/server/events/QueueManager.java @@ -177,7 +177,31 @@ public interface QueueManager { * @return a builder for creating event queues */ default EventQueue.EventQueueBuilder getEventQueueBuilder(String taskId) { - return EventQueue.builder(); + throw new UnsupportedOperationException( + "QueueManager implementations must override getEventQueueBuilder() to provide MainEventBus" + ); + } + + /** + * Creates a base EventQueueBuilder with standard configuration for this QueueManager. + * This method provides the foundation for creating event queues with proper configuration + * (MainEventBus, TaskStateProvider, cleanup callbacks, etc.). + *

    + * QueueManager implementations that use custom factories can call this method directly + * to get the base builder without going through the factory (which could cause infinite + * recursion if the factory delegates back to getEventQueueBuilder()). + *

    + *

    + * Callers can then add additional configuration (hooks, callbacks) before building the queue. + *

    + * + * @param taskId the task ID for the queue + * @return a builder with base configuration specific to this QueueManager implementation + */ + default EventQueue.EventQueueBuilder createBaseEventQueueBuilder(String taskId) { + throw new UnsupportedOperationException( + "QueueManager implementations must override createBaseEventQueueBuilder() to provide MainEventBus" + ); } /** 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 002acbafd..c476c8741 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 @@ -11,13 +11,13 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; @@ -35,13 +35,15 @@ import io.a2a.server.events.EventConsumer; import io.a2a.server.events.EventQueue; import io.a2a.server.events.EventQueueItem; +import io.a2a.server.events.MainEventBusProcessor; +import io.a2a.server.events.MainEventBusProcessorCallback; import io.a2a.server.events.QueueManager; -import io.a2a.server.events.TaskQueueExistsException; import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.server.tasks.PushNotificationSender; import io.a2a.server.tasks.ResultAggregator; import io.a2a.server.tasks.TaskManager; import io.a2a.server.tasks.TaskStore; +import io.a2a.server.util.async.EventConsumerExecutorProducer.EventConsumerExecutor; import io.a2a.server.util.async.Internal; import io.a2a.spec.A2AError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; @@ -64,6 +66,7 @@ import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.UnsupportedOperationError; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; @@ -122,7 +125,6 @@ *
  • {@link EventConsumer} polls and processes events on Vert.x worker thread
  • *
  • Queue closes automatically on final event (COMPLETED/FAILED/CANCELED)
  • *
  • Cleanup waits for both agent execution AND event consumption to complete
  • - *
  • Background tasks tracked via {@link #trackBackgroundTask(CompletableFuture)}
  • * * *

    Threading Model

    @@ -179,6 +181,13 @@ public class DefaultRequestHandler implements RequestHandler { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultRequestHandler.class); + /** + * Separate logger for thread statistics diagnostic logging. + * This allows independent control of verbose thread pool monitoring without affecting + * general request handler logging. Enable with: logging.level.io.a2a.server.diagnostics.ThreadStats=DEBUG + */ + private static final Logger THREAD_STATS_LOGGER = LoggerFactory.getLogger("io.a2a.server.diagnostics.ThreadStats"); + private static final String A2A_BLOCKING_AGENT_TIMEOUT_SECONDS = "a2a.blocking.agent.timeout.seconds"; private static final String A2A_BLOCKING_CONSUMPTION_TIMEOUT_SECONDS = "a2a.blocking.consumption.timeout.seconds"; @@ -214,13 +223,14 @@ public class DefaultRequestHandler implements RequestHandler { private TaskStore taskStore; private QueueManager queueManager; private PushNotificationConfigStore pushConfigStore; - private PushNotificationSender pushSender; + private MainEventBusProcessor mainEventBusProcessor; private Supplier requestContextBuilder; private final ConcurrentMap> runningAgents = new ConcurrentHashMap<>(); - private final Set> backgroundTasks = ConcurrentHashMap.newKeySet(); + private Executor executor; + private Executor eventConsumerExecutor; /** * No-args constructor for CDI proxy creation. @@ -234,21 +244,25 @@ protected DefaultRequestHandler() { this.taskStore = null; this.queueManager = null; this.pushConfigStore = null; - this.pushSender = null; + this.mainEventBusProcessor = null; this.requestContextBuilder = null; this.executor = null; + this.eventConsumerExecutor = null; } @Inject public DefaultRequestHandler(AgentExecutor agentExecutor, TaskStore taskStore, QueueManager queueManager, PushNotificationConfigStore pushConfigStore, - PushNotificationSender pushSender, @Internal Executor executor) { + MainEventBusProcessor mainEventBusProcessor, + @Internal Executor executor, + @EventConsumerExecutor Executor eventConsumerExecutor) { this.agentExecutor = agentExecutor; this.taskStore = taskStore; this.queueManager = queueManager; this.pushConfigStore = pushConfigStore; - this.pushSender = pushSender; + this.mainEventBusProcessor = mainEventBusProcessor; this.executor = executor; + this.eventConsumerExecutor = eventConsumerExecutor; // TODO In Python this is also a constructor parameter defaulting to this SimpleRequestContextBuilder // implementation if the parameter is null. Skip that for now, since otherwise I get CDI errors, and // I am unsure about the correct scope. @@ -264,16 +278,20 @@ void initConfig() { configProvider.getValue(A2A_BLOCKING_CONSUMPTION_TIMEOUT_SECONDS)); } + /** * For testing */ public static DefaultRequestHandler create(AgentExecutor agentExecutor, TaskStore taskStore, QueueManager queueManager, PushNotificationConfigStore pushConfigStore, - PushNotificationSender pushSender, Executor executor) { + MainEventBusProcessor mainEventBusProcessor, + Executor executor, Executor eventConsumerExecutor) { DefaultRequestHandler handler = - new DefaultRequestHandler(agentExecutor, taskStore, queueManager, pushConfigStore, pushSender, executor); + new DefaultRequestHandler(agentExecutor, taskStore, queueManager, pushConfigStore, + mainEventBusProcessor, executor, eventConsumerExecutor); handler.agentCompletionTimeoutSeconds = 5; handler.consumptionCompletionTimeoutSeconds = 2; + return handler; } @@ -359,12 +377,9 @@ public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws taskStore, null); - ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor); + ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor, eventConsumerExecutor); - EventQueue queue = queueManager.tap(task.id()); - if (queue == null) { - queue = queueManager.getEventQueueBuilder(task.id()).build(); - } + EventQueue queue = queueManager.createOrTap(task.id()); agentExecutor.cancel( requestContextBuilder.get() .setTaskId(task.id()) @@ -395,28 +410,41 @@ public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws @Override public EventKind onMessageSend(MessageSendParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onMessageSend - task: {}; context {}", params.message().taskId(), params.message().contextId()); + + // Build MessageSendSetup which creates RequestContext with real taskId (auto-generated if needed) MessageSendSetup mss = initMessageSend(params, context); - String taskId = mss.requestContext.getTaskId(); - LOGGER.debug("Request context taskId: {}", taskId); + // Use the taskId from RequestContext for queue management (no temp ID needed!) + // RequestContext.build() guarantees taskId is non-null via checkOrGenerateTaskId() + String queueTaskId = java.util.Objects.requireNonNull( + mss.requestContext.getTaskId(), "TaskId must be non-null after RequestContext.build()"); + LOGGER.debug("Queue taskId: {}", queueTaskId); - if (taskId == null) { - throw new io.a2a.spec.InternalError("Task ID is null in onMessageSend"); - } - EventQueue queue = queueManager.createOrTap(taskId); - ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor); + // Create queue with real taskId (no tempId parameter needed) + EventQueue queue = queueManager.createOrTap(queueTaskId); + final java.util.concurrent.atomic.AtomicReference<@NonNull String> taskId = new java.util.concurrent.atomic.AtomicReference<>(queueTaskId); + ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); + // Default to blocking=false per A2A spec (return after task creation) boolean blocking = params.configuration() != null && Boolean.TRUE.equals(params.configuration().blocking()); + // Log blocking behavior from client request + if (params.configuration() != null && params.configuration().blocking() != null) { + LOGGER.debug("DefaultRequestHandler: Client requested blocking={} for task {}", + params.configuration().blocking(), taskId.get()); + } else if (params.configuration() != null) { + LOGGER.debug("DefaultRequestHandler: Client sent configuration but blocking=null, using default blocking={} for task {}", blocking, taskId.get()); + } else { + LOGGER.debug("DefaultRequestHandler: Client sent no configuration, using default blocking={} for task {}", blocking, taskId.get()); + } + LOGGER.debug("DefaultRequestHandler: Final blocking decision: {} for task {}", blocking, taskId.get()); + boolean interruptedOrNonBlocking = false; - EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(taskId, mss.requestContext, queue); + EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue); ResultAggregator.EventTypeAndInterrupt etai = null; EventKind kind = null; // Declare outside try block so it's in scope for return try { - // Create callback for push notifications during background event processing - Runnable pushNotificationCallback = () -> sendPushNotification(taskId, resultAggregator); - EventConsumer consumer = new EventConsumer(queue); // This callback must be added before we start consuming. Otherwise, @@ -424,7 +452,7 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte producerRunnable.addDoneCallback(consumer.createAgentRunnableDoneCallback()); // Get agent future before consuming (for blocking calls to wait for agent completion) - CompletableFuture agentFuture = runningAgents.get(taskId); + CompletableFuture agentFuture = runningAgents.get(queueTaskId); etai = resultAggregator.consumeAndBreakOnInterrupt(consumer, blocking); if (etai == null) { @@ -432,7 +460,8 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte throw new InternalError("No result"); } interruptedOrNonBlocking = etai.interrupted(); - LOGGER.debug("Was interrupted or non-blocking: {}", interruptedOrNonBlocking); + LOGGER.debug("DefaultRequestHandler: interruptedOrNonBlocking={} (blocking={}, eventType={})", + interruptedOrNonBlocking, blocking, kind != null ? kind.getClass().getSimpleName() : null); // For blocking calls that were interrupted (returned on first event), // wait for agent execution and event processing BEFORE returning to client. @@ -441,30 +470,36 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte // during the consumption loop itself. kind = etai.eventType(); + // No ID switching needed - agent uses context.getTaskId() which is the same as queue key + // Store push notification config for newly created tasks (mirrors streaming logic) // Only for NEW tasks - existing tasks are handled by initMessageSend() if (mss.task() == null && kind instanceof Task createdTask && shouldAddPushInfo(params)) { - LOGGER.debug("Storing push notification config for new task {}", createdTask.id()); + LOGGER.debug("Storing push notification config for new task {} (original taskId from params: {})", + createdTask.id(), params.message().taskId()); pushConfigStore.setInfo(createdTask.id(), params.configuration().pushNotificationConfig()); } if (blocking && interruptedOrNonBlocking) { - // For blocking calls: ensure all events are processed before returning - // Order of operations is critical to avoid circular dependency: - // 1. Wait for agent to finish enqueueing events + // For blocking calls: ensure all consumed events are persisted to TaskStore before returning + // Order of operations is critical to avoid circular dependency and race conditions: + // 1. Wait for agent to finish enqueueing events (or timeout) // 2. Close the queue to signal consumption can complete // 3. Wait for consumption to finish processing events - // 4. Fetch final task state from TaskStore + // 4. (Implicit) MainEventBusProcessor persistence guarantee via consumption completion + // 5. Fetch current task state from TaskStore (includes all consumed & persisted events) + LOGGER.debug("DefaultRequestHandler: Entering blocking fire-and-forget handling for task {}", taskId.get()); try { // Step 1: Wait for agent to finish (with configurable timeout) if (agentFuture != null) { try { agentFuture.get(agentCompletionTimeoutSeconds, SECONDS); - LOGGER.debug("Agent completed for task {}", taskId); + LOGGER.debug("DefaultRequestHandler: Step 1 - Agent completed for task {}", taskId.get()); } catch (java.util.concurrent.TimeoutException e) { // Agent still running after timeout - that's fine, events already being processed - LOGGER.debug("Agent still running for task {} after {}s", taskId, agentCompletionTimeoutSeconds); + LOGGER.debug("DefaultRequestHandler: Step 1 - Agent still running for task {} after {}s timeout", + taskId.get(), agentCompletionTimeoutSeconds); } } @@ -472,55 +507,84 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte // For fire-and-forget tasks, there's no final event, so we need to close the queue // This allows EventConsumer.consumeAll() to exit queue.close(false, false); // graceful close, don't notify parent yet - LOGGER.debug("Closed queue for task {} to allow consumption completion", taskId); + LOGGER.debug("DefaultRequestHandler: Step 2 - Closed queue for task {} to allow consumption completion", taskId.get()); // Step 3: Wait for consumption to complete (now that queue is closed) if (etai.consumptionFuture() != null) { etai.consumptionFuture().get(consumptionCompletionTimeoutSeconds, SECONDS); - LOGGER.debug("Consumption completed for task {}", taskId); + LOGGER.debug("DefaultRequestHandler: Step 3 - Consumption completed for task {}", taskId.get()); } + + // Step 4: Implicit guarantee of persistence via consumption completion + // We do NOT add an explicit wait for MainEventBusProcessor here because: + // 1. MainEventBusProcessor persists BEFORE distributing to ChildQueues + // 2. Step 3 (consumption completion) already guarantees all consumed events are persisted + // 3. Adding another explicit synchronization point would require exposing + // MainEventBusProcessor internals and blocking event loop threads + // + // Note: For fire-and-forget tasks, if the agent is still running after Step 1 timeout, + // it may enqueue additional events. These will be persisted asynchronously but won't + // be included in the task state returned to the client (already consumed in Step 3). + } catch (InterruptedException e) { Thread.currentThread().interrupt(); - String msg = String.format("Error waiting for task %s completion", taskId); + String msg = String.format("Error waiting for task %s completion", taskId.get()); LOGGER.warn(msg, e); throw new InternalError(msg); } catch (java.util.concurrent.ExecutionException e) { - String msg = String.format("Error during task %s execution", taskId); + String msg = String.format("Error during task %s execution", taskId.get()); LOGGER.warn(msg, e.getCause()); throw new InternalError(msg); - } catch (java.util.concurrent.TimeoutException e) { - String msg = String.format("Timeout waiting for consumption to complete for task %s", taskId); - LOGGER.warn(msg, taskId); + } catch (TimeoutException e) { + // Timeout from consumption future.get() - different from finalization timeout + String msg = String.format("Timeout waiting for task %s consumption", taskId.get()); + LOGGER.warn(msg, e); throw new InternalError(msg); } - // Step 4: Fetch the final task state from TaskStore (all events have been processed) - // taskId is guaranteed non-null here (checked earlier) - String nonNullTaskId = taskId; + // Step 5: Fetch the current task state from TaskStore + // All events consumed in Step 3 are guaranteed persisted (MainEventBusProcessor + // ordering: persist → distribute → consume). This returns the persisted state + // including all consumed events and artifacts. + String nonNullTaskId = Objects.requireNonNull(taskId.get(), "taskId cannot be null"); Task updatedTask = taskStore.get(nonNullTaskId); if (updatedTask != null) { kind = updatedTask; - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Fetched final task for {} with state {} and {} artifacts", - nonNullTaskId, updatedTask.status().state(), - updatedTask.artifacts().size()); - } + LOGGER.debug("DefaultRequestHandler: Step 5 - Fetched current task for {} with state {} and {} artifacts", + taskId.get(), updatedTask.status().state(), + updatedTask.artifacts().size()); + } else { + LOGGER.warn("DefaultRequestHandler: Step 5 - Task {} not found in TaskStore!", taskId.get()); } } - if (kind instanceof Task taskResult && !taskId.equals(taskResult.id())) { + String finalTaskId = Objects.requireNonNull(taskId.get(), "taskId cannot be null"); + if (kind instanceof Task taskResult && !finalTaskId.equals(taskResult.id())) { throw new InternalError("Task ID mismatch in agent response"); } - - // Send push notification after initial return (for both blocking and non-blocking) - pushNotificationCallback.run(); } finally { + // For non-blocking calls: close ChildQueue IMMEDIATELY to free EventConsumer thread + // CRITICAL: Must use immediate=true to clear the local queue, otherwise EventConsumer + // continues polling until queue drains naturally, holding executor thread. + // Immediate close clears pending events and triggers EventQueueClosedException on next poll. + // Events continue flowing through MainQueue → MainEventBus → TaskStore. + if (!blocking && etai != null && etai.interrupted()) { + LOGGER.debug("DefaultRequestHandler: Non-blocking call in finally - closing ChildQueue IMMEDIATELY for task {} to free EventConsumer", taskId.get()); + queue.close(true); // immediate=true: clear queue and free EventConsumer + } + // Remove agent from map immediately to prevent accumulation - CompletableFuture agentFuture = runningAgents.remove(taskId); - LOGGER.debug("Removed agent for task {} from runningAgents in finally block, size after: {}", taskId, runningAgents.size()); + CompletableFuture agentFuture = runningAgents.remove(queueTaskId); + String cleanupTaskId = Objects.requireNonNull(taskId.get(), "taskId cannot be null"); + LOGGER.debug("Removed agent for task {} from runningAgents in finally block, size after: {}", cleanupTaskId, runningAgents.size()); - // Track cleanup as background task to avoid blocking Vert.x threads + // Cleanup as background task to avoid blocking Vert.x threads // Pass the consumption future to ensure cleanup waits for background consumption to complete - trackBackgroundTask(cleanupProducer(agentFuture, etai != null ? etai.consumptionFuture() : null, taskId, queue, false)); + cleanupProducer(agentFuture, etai != null ? etai.consumptionFuture() : null, cleanupTaskId, queue, false) + .whenComplete((res, err) -> { + if (err != null) { + LOGGER.error("Error during async cleanup for task {}", taskId.get(), err); + } + }); } LOGGER.debug("Returning: {}", kind); @@ -530,29 +594,44 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte @Override public Flow.Publisher onMessageSendStream( MessageSendParams params, ServerCallContext context) throws A2AError { - LOGGER.debug("onMessageSendStream START - task: {}; context: {}; runningAgents: {}; backgroundTasks: {}", - params.message().taskId(), params.message().contextId(), runningAgents.size(), backgroundTasks.size()); + LOGGER.debug("onMessageSendStream START - task: {}; context: {}; runningAgents: {}", + params.message().taskId(), params.message().contextId(), runningAgents.size()); + + // Build MessageSendSetup which creates RequestContext with real taskId (auto-generated if needed) MessageSendSetup mss = initMessageSend(params, context); - @Nullable String initialTaskId = mss.requestContext.getTaskId(); - // For streaming, taskId can be null initially (will be set when Task event arrives) - // Use a temporary ID for queue creation if needed - String queueTaskId = initialTaskId != null ? initialTaskId : "temp-" + java.util.UUID.randomUUID(); + // Use the taskId from RequestContext for queue management (no temp ID needed!) + // RequestContext.build() guarantees taskId is non-null via checkOrGenerateTaskId() + String queueTaskId = java.util.Objects.requireNonNull( + mss.requestContext.getTaskId(), "TaskId must be non-null after RequestContext.build()"); + final AtomicReference<@NonNull String> taskId = new AtomicReference<>(queueTaskId); - AtomicReference<@NonNull String> taskId = new AtomicReference<>(queueTaskId); - @SuppressWarnings("NullAway") - EventQueue queue = queueManager.createOrTap(taskId.get()); + // Create queue with real taskId (no tempId parameter needed) + EventQueue queue = queueManager.createOrTap(queueTaskId); LOGGER.debug("Created/tapped queue for task {}: {}", taskId.get(), queue); - ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor); + + // Store push notification config SYNCHRONOUSLY for new tasks before agent starts + // This ensures config is available when MainEventBusProcessor sends push notifications + // For existing tasks, config is stored in initMessageSend() + if (mss.task() == null && shouldAddPushInfo(params)) { + // Satisfy Nullaway + Objects.requireNonNull(taskId.get(), "taskId was null"); + LOGGER.debug("Storing push notification config for new streaming task {} EARLY (original taskId from params: {})", + taskId.get(), params.message().taskId()); + pushConfigStore.setInfo(taskId.get(), params.configuration().pushNotificationConfig()); + } + + ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue); // Move consumer creation and callback registration outside try block - // so consumer is available for background consumption on client disconnect EventConsumer consumer = new EventConsumer(queue); producerRunnable.addDoneCallback(consumer.createAgentRunnableDoneCallback()); - AtomicBoolean backgroundConsumeStarted = new AtomicBoolean(false); + // Store cancel callback in context for closeHandler to access + // When client disconnects, closeHandler can call this to stop EventConsumer polling loop + context.setEventConsumerCancelCallback(consumer::cancel); try { Flow.Publisher results = resultAggregator.consumeAndEmit(consumer); @@ -562,36 +641,13 @@ public Flow.Publisher onMessageSendStream( processor(createTubeConfig(), results, ((errorConsumer, item) -> { Event event = item.getEvent(); if (event instanceof Task createdTask) { - if (!Objects.equals(taskId.get(), createdTask.id())) { - errorConsumer.accept(new InternalError("Task ID mismatch in agent response")); - } - - // TODO the Python implementation no longer has the following block but removing it causes - // failures here - try { - queueManager.add(createdTask.id(), queue); - taskId.set(createdTask.id()); - } catch (TaskQueueExistsException e) { - // TODO Log - } - if (pushConfigStore != null && - params.configuration() != null && - params.configuration().pushNotificationConfig() != null) { - - pushConfigStore.setInfo( - createdTask.id(), - params.configuration().pushNotificationConfig()); - } - - } - String currentTaskId = taskId.get(); - if (pushSender != null && currentTaskId != null) { - EventKind latest = resultAggregator.getCurrentResult(); - if (latest instanceof Task latestTask) { - pushSender.sendNotification(latestTask); + // Verify task ID matches (should always match now - agent uses context.getTaskId()) + String currentId = Objects.requireNonNull(taskId.get(), "taskId cannot be null"); + if (!currentId.equals(createdTask.id())) { + errorConsumer.accept(new InternalError("Task ID mismatch: expected " + currentId + + " but got " + createdTask.id())); } } - return true; })); @@ -600,7 +656,8 @@ public Flow.Publisher onMessageSendStream( Flow.Publisher finalPublisher = convertingProcessor(eventPublisher, event -> (StreamingEventKind) event); - // Wrap publisher to detect client disconnect and continue background consumption + // Wrap publisher to detect client disconnect and immediately close ChildQueue + // This prevents ChildQueue backpressure from blocking MainEventBusProcessor return subscriber -> { String currentTaskId = taskId.get(); LOGGER.debug("Creating subscription wrapper for task {}", currentTaskId); @@ -621,8 +678,10 @@ public void request(long n) { @Override public void cancel() { - LOGGER.debug("Client cancelled subscription for task {}, starting background consumption", taskId.get()); - startBackgroundConsumption(); + LOGGER.debug("Client cancelled subscription for task {}, closing ChildQueue immediately", taskId.get()); + // Close ChildQueue immediately to prevent backpressure + // (clears queue and releases semaphore permits) + queue.close(true); // immediate=true subscription.cancel(); } }); @@ -647,8 +706,8 @@ public void onComplete() { subscriber.onComplete(); } catch (IllegalStateException e) { // Client already disconnected and response closed - this is expected - // for streaming responses where client disconnect triggers background - // consumption. Log and ignore. + // for streaming responses where client disconnect closes ChildQueue. + // Log and ignore. if (e.getMessage() != null && e.getMessage().contains("Response has already been written")) { LOGGER.debug("Client disconnected before onComplete, response already closed for task {}", taskId.get()); } else { @@ -656,36 +715,26 @@ public void onComplete() { } } } - - private void startBackgroundConsumption() { - if (backgroundConsumeStarted.compareAndSet(false, true)) { - LOGGER.debug("Starting background consumption for task {}", taskId.get()); - // Client disconnected: continue consuming and persisting events in background - CompletableFuture bgTask = CompletableFuture.runAsync(() -> { - try { - LOGGER.debug("Background consumption thread started for task {}", taskId.get()); - resultAggregator.consumeAll(consumer); - LOGGER.debug("Background consumption completed for task {}", taskId.get()); - } catch (Exception e) { - LOGGER.error("Error during background consumption for task {}", taskId.get(), e); - } - }, executor); - trackBackgroundTask(bgTask); - } else { - LOGGER.debug("Background consumption already started for task {}", taskId.get()); - } - } }); }; } finally { - LOGGER.debug("onMessageSendStream FINALLY - task: {}; runningAgents: {}; backgroundTasks: {}", - taskId.get(), runningAgents.size(), backgroundTasks.size()); - - // Remove agent from map immediately to prevent accumulation - CompletableFuture agentFuture = runningAgents.remove(taskId.get()); - LOGGER.debug("Removed agent for task {} from runningAgents in finally block, size after: {}", taskId.get(), runningAgents.size()); - - trackBackgroundTask(cleanupProducer(agentFuture, null, Objects.requireNonNull(taskId.get()), queue, true)); + // Needed to satisfy Nullaway + String idOfTask = taskId.get(); + if (idOfTask != null) { + LOGGER.debug("onMessageSendStream FINALLY - task: {}; runningAgents: {}", + idOfTask, runningAgents.size()); + + // Remove agent from map immediately to prevent accumulation + CompletableFuture agentFuture = runningAgents.remove(idOfTask); + LOGGER.debug("Removed agent for task {} from runningAgents in finally block, size after: {}", taskId.get(), runningAgents.size()); + + cleanupProducer(agentFuture, null, idOfTask, queue, true) + .whenComplete((res, err) -> { + if (err != null) { + LOGGER.error("Error during async cleanup for streaming task {}", taskId.get(), err); + } + }); + } } } @@ -746,7 +795,7 @@ public Flow.Publisher onResubscribeToTask( } TaskManager taskManager = new TaskManager(task.id(), task.contextId(), taskStore, null); - ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor); + ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor, eventConsumerExecutor); EventQueue queue = queueManager.tap(task.id()); LOGGER.debug("onResubscribeToTask - tapped queue: {}", queue != null ? System.identityHashCode(queue) : "null"); @@ -761,6 +810,13 @@ public Flow.Publisher onResubscribeToTask( queue = queueManager.createOrTap(task.id()); } + // Per A2A Protocol Spec 3.1.6 (Subscribe to Task): + // "The operation MUST return a Task object as the first event in the stream, + // representing the current state of the task at the time of subscription." + // Enqueue the current task state directly to this ChildQueue only (already persisted, no need for MainEventBus) + queue.enqueueEventLocalOnly(task); + LOGGER.debug("onResubscribeToTask - enqueued current task state as first event for taskId: {}", params.id()); + EventConsumer consumer = new EventConsumer(queue); Flow.Publisher results = resultAggregator.consumeAndEmit(consumer); LOGGER.debug("onResubscribeToTask - returning publisher for taskId: {}", params.id()); @@ -819,8 +875,7 @@ public void run() { LOGGER.debug("Agent execution starting for task {}", taskId); agentExecutor.execute(requestContext, queue); LOGGER.debug("Agent execution completed for task {}", taskId); - // No longer wait for queue poller to start - the consumer (which is guaranteed - // to be running on the Vert.x worker thread) will handle queue lifecycle. + // The consumer (running on the Vert.x worker thread) handles queue lifecycle. // This avoids blocking agent-executor threads waiting for worker threads. } }; @@ -833,8 +888,8 @@ public void run() { // Don't close queue here - let the consumer handle it via error callback // This ensures the consumer (which may not have started polling yet) gets the error } - // Queue lifecycle is now managed entirely by EventConsumer.consumeAll() - // which closes the queue on final events. No need to close here. + // Queue lifecycle is managed by EventConsumer.consumeAll() + // which closes the queue on final events. logThreadStats("AGENT COMPLETE END"); runnable.invokeDoneCallbacks(); }); @@ -843,47 +898,6 @@ public void run() { return runnable; } - private void trackBackgroundTask(CompletableFuture task) { - backgroundTasks.add(task); - LOGGER.debug("Tracking background task (total: {}): {}", backgroundTasks.size(), task); - - task.whenComplete((result, throwable) -> { - try { - if (throwable != null) { - // Unwrap CompletionException to check for CancellationException - Throwable cause = throwable; - if (throwable instanceof java.util.concurrent.CompletionException && throwable.getCause() != null) { - cause = throwable.getCause(); - } - - if (cause instanceof java.util.concurrent.CancellationException) { - LOGGER.debug("Background task cancelled: {}", task); - } else { - LOGGER.error("Background task failed", throwable); - } - } - } finally { - backgroundTasks.remove(task); - LOGGER.debug("Removed background task (remaining: {}): {}", backgroundTasks.size(), task); - } - }); - } - - /** - * Wait for all background tasks to complete. - * Useful for testing to ensure cleanup completes before assertions. - * - * @return CompletableFuture that completes when all background tasks finish - */ - public CompletableFuture waitForBackgroundTasks() { - CompletableFuture[] tasks = backgroundTasks.toArray(new CompletableFuture[0]); - if (tasks.length == 0) { - return CompletableFuture.completedFuture(null); - } - LOGGER.debug("Waiting for {} background tasks to complete", tasks.length); - return CompletableFuture.allOf(tasks); - } - private CompletableFuture cleanupProducer(@Nullable CompletableFuture agentFuture, @Nullable CompletableFuture consumptionFuture, String taskId, EventQueue queue, boolean isStreaming) { LOGGER.debug("Starting cleanup for task {} (streaming={})", taskId, isStreaming); logThreadStats("CLEANUP START"); @@ -908,14 +922,20 @@ private CompletableFuture cleanupProducer(@Nullable CompletableFuture cleanupProducer(@Nullable CompletableFuture + * Enable independently with: {@code logging.level.io.a2a.server.diagnostics.ThreadStats=DEBUG} + *

    */ @SuppressWarnings("unused") // Used for debugging private void logThreadStats(String label) { // Early return if debug logging is not enabled to avoid overhead - if (!LOGGER.isDebugEnabled()) { + if (!THREAD_STATS_LOGGER.isDebugEnabled()) { return; } @@ -982,28 +1036,57 @@ private void logThreadStats(String label) { } int activeThreads = rootGroup.activeCount(); - LOGGER.debug("=== THREAD STATS: {} ===", label); - LOGGER.debug("Active threads: {}", activeThreads); - LOGGER.debug("Running agents: {}", runningAgents.size()); - LOGGER.debug("Background tasks: {}", backgroundTasks.size()); - LOGGER.debug("Queue manager active queues: {}", queueManager.getClass().getSimpleName()); + // Count specific thread types + Thread[] threads = new Thread[activeThreads * 2]; + int count = rootGroup.enumerate(threads); + int eventConsumerThreads = 0; + int agentExecutorThreads = 0; + for (int i = 0; i < count; i++) { + if (threads[i] != null) { + String name = threads[i].getName(); + if (name.startsWith("a2a-event-consumer-")) { + eventConsumerThreads++; + } else if (name.startsWith("a2a-agent-executor-")) { + agentExecutorThreads++; + } + } + } + + THREAD_STATS_LOGGER.debug("=== THREAD STATS: {} ===", label); + THREAD_STATS_LOGGER.debug("Total active threads: {}", activeThreads); + THREAD_STATS_LOGGER.debug("EventConsumer threads: {}", eventConsumerThreads); + THREAD_STATS_LOGGER.debug("AgentExecutor threads: {}", agentExecutorThreads); + THREAD_STATS_LOGGER.debug("Running agents: {}", runningAgents.size()); + THREAD_STATS_LOGGER.debug("Queue manager active queues: {}", queueManager.getClass().getSimpleName()); // List running agents if (!runningAgents.isEmpty()) { - LOGGER.debug("Running agent tasks:"); + THREAD_STATS_LOGGER.debug("Running agent tasks:"); runningAgents.forEach((taskId, future) -> - LOGGER.debug(" - Task {}: {}", taskId, future.isDone() ? "DONE" : "RUNNING") + THREAD_STATS_LOGGER.debug(" - Task {}: {}", taskId, future.isDone() ? "DONE" : "RUNNING") ); } - // List background tasks - if (!backgroundTasks.isEmpty()) { - LOGGER.debug("Background tasks:"); - backgroundTasks.forEach(task -> - LOGGER.debug(" - {}: {}", task, task.isDone() ? "DONE" : "RUNNING") - ); + THREAD_STATS_LOGGER.debug("=== END THREAD STATS ==="); + } + + /** + * Check if an event represents a final task state. + * + * @param eventKind the event to check + * @return true if the event represents a final state (COMPLETED, FAILED, CANCELED, REJECTED, UNKNOWN) + */ + private boolean isFinalEvent(EventKind eventKind) { + if (!(eventKind instanceof Event event)) { + return false; + } + if (event instanceof Task task) { + return task.status() != null && task.status().state() != null + && task.status().state().isFinal(); + } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { + return statusUpdate.isFinal(); } - LOGGER.debug("=== END THREAD STATS ==="); + return false; } private record MessageSendSetup(TaskManager taskManager, @Nullable Task task, RequestContext requestContext) {} 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 1e3ae1206..15f94d7e8 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 @@ -32,8 +32,9 @@ public class InMemoryTaskStore implements TaskStore, TaskStateProvider { private final ConcurrentMap tasks = new ConcurrentHashMap<>(); @Override - public void save(Task task) { + public void save(Task task, boolean isReplicated) { tasks.put(task.id(), task); + // InMemoryTaskStore doesn't fire TaskFinalizedEvent, so isReplicated is unused here } @Override 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 95684e199..506b3f3b6 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 @@ -14,9 +14,9 @@ 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.InternalError; import io.a2a.spec.Message; import io.a2a.spec.Task; import io.a2a.spec.TaskState; @@ -31,12 +31,14 @@ public class ResultAggregator { private final TaskManager taskManager; private final Executor executor; + private final Executor eventConsumerExecutor; private volatile @Nullable Message message; - public ResultAggregator(TaskManager taskManager, @Nullable Message message, Executor executor) { + public ResultAggregator(TaskManager taskManager, @Nullable Message message, Executor executor, Executor eventConsumerExecutor) { this.taskManager = taskManager; this.message = message; this.executor = executor; + this.eventConsumerExecutor = eventConsumerExecutor; } public @Nullable EventKind getCurrentResult() { @@ -49,20 +51,23 @@ public ResultAggregator(TaskManager taskManager, @Nullable Message message, Exec public Flow.Publisher consumeAndEmit(EventConsumer consumer) { Flow.Publisher allItems = consumer.consumeAll(); - // Process items conditionally - only save non-replicated events to database - return processor(createTubeConfig(), allItems, (errorConsumer, item) -> { - // Only process non-replicated events to avoid duplicate database writes - if (!item.isReplicated()) { - try { - callTaskManagerProcess(item.getEvent()); - } catch (A2AServerException e) { - errorConsumer.accept(e); - return false; - } - } - // Continue processing and emit (both replicated and non-replicated) + // Just stream events - no persistence needed + // TaskStore update moved to MainEventBusProcessor + Flow.Publisher processed = processor(createTubeConfig(), allItems, (errorConsumer, item) -> { + // Continue processing and emit all events return true; }); + + // Wrap the publisher to ensure subscription happens on eventConsumerExecutor + // This prevents EventConsumer polling loop from running on AgentExecutor threads + // which caused thread accumulation when those threads didn't timeout + return new Flow.Publisher() { + @Override + public void subscribe(Flow.Subscriber subscriber) { + // Submit subscription to eventConsumerExecutor to isolate polling work + eventConsumerExecutor.execute(() -> processed.subscribe(subscriber)); + } + }; } public EventKind consumeAll(EventConsumer consumer) throws A2AError { @@ -81,15 +86,7 @@ public EventKind consumeAll(EventConsumer consumer) throws A2AError { return false; } } - // Only process non-replicated events to avoid duplicate database writes - if (!item.isReplicated()) { - try { - callTaskManagerProcess(event); - } catch (A2AServerException e) { - error.set(e); - return false; - } - } + // TaskStore update moved to MainEventBusProcessor return true; }, error::set); @@ -113,18 +110,24 @@ public EventKind consumeAll(EventConsumer consumer) throws A2AError { public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, boolean blocking) throws A2AError { Flow.Publisher allItems = consumer.consumeAll(); AtomicReference message = new AtomicReference<>(); + AtomicReference capturedTask = new AtomicReference<>(); // Capture Task events AtomicBoolean interrupted = new AtomicBoolean(false); AtomicReference errorRef = new AtomicReference<>(); CompletableFuture completionFuture = new CompletableFuture<>(); // Separate future for tracking background consumption completion CompletableFuture consumptionCompletionFuture = new CompletableFuture<>(); + // Latch to ensure EventConsumer starts polling before we wait on completionFuture + java.util.concurrent.CountDownLatch pollingStarted = new java.util.concurrent.CountDownLatch(1); // CRITICAL: The subscription itself must run on a background thread to avoid blocking // the Vert.x worker thread. EventConsumer.consumeAll() starts a polling loop that // blocks in dequeueEventItem(), so we must subscribe from a background thread. - // Use the @Internal executor (not ForkJoinPool.commonPool) to avoid saturation - // during concurrent request bursts. + // Use the dedicated @EventConsumerExecutor (cached thread pool) which creates threads + // on demand for I/O-bound polling. Using the @Internal executor caused deadlock when + // pool exhausted (100+ concurrent queues but maxPoolSize=50). CompletableFuture.runAsync(() -> { + // Signal that polling is about to start + pollingStarted.countDown(); consumer( createTubeConfig(), allItems, @@ -146,25 +149,30 @@ public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, return false; } - // Process event through TaskManager - only for non-replicated events - if (!item.isReplicated()) { - try { - callTaskManagerProcess(event); - } catch (A2AServerException e) { - errorRef.set(e); - completionFuture.completeExceptionally(e); - return false; + // Capture Task events (especially for new tasks where taskManager.getTask() would return null) + // We capture the LATEST task to ensure we get the most up-to-date state + if (event instanceof Task t) { + Task previousTask = capturedTask.get(); + capturedTask.set(t); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Captured Task event: id={}, state={} (previous: {})", + t.id(), t.status().state(), + previousTask != null ? previousTask.id() + "/" + previousTask.status().state() : "none"); } } + // TaskStore update moved to MainEventBusProcessor + // Determine interrupt behavior boolean shouldInterrupt = false; - boolean continueInBackground = false; boolean isFinalEvent = (event instanceof Task task && task.status().state().isFinal()) || (event instanceof TaskStatusUpdateEvent tsue && tsue.isFinal()); boolean isAuthRequired = (event instanceof Task task && task.status().state() == TaskState.AUTH_REQUIRED) || (event instanceof TaskStatusUpdateEvent tsue && tsue.status().state() == TaskState.AUTH_REQUIRED); + LOGGER.debug("ResultAggregator: Evaluating interrupt (blocking={}, isFinal={}, isAuth={}, eventType={})", + blocking, isFinalEvent, isAuthRequired, event.getClass().getSimpleName()); + // Always interrupt on auth_required, as it needs external action. if (isAuthRequired) { // auth-required is a special state: the message should be @@ -174,20 +182,19 @@ public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, // new request is expected in order for the agent to make progress, // so the agent should exit. shouldInterrupt = true; - continueInBackground = true; + LOGGER.debug("ResultAggregator: Setting shouldInterrupt=true (AUTH_REQUIRED)"); } else if (!blocking) { // For non-blocking calls, interrupt as soon as a task is available. shouldInterrupt = true; - continueInBackground = true; + LOGGER.debug("ResultAggregator: Setting shouldInterrupt=true (non-blocking)"); } else if (blocking) { // For blocking calls: Interrupt to free Vert.x thread, but continue in background // Python's async consumption doesn't block threads, but Java's does // So we interrupt to return quickly, then rely on background consumption - // DefaultRequestHandler will fetch the final state from TaskStore shouldInterrupt = true; - continueInBackground = true; + LOGGER.debug("ResultAggregator: Setting shouldInterrupt=true (blocking, isFinal={})", isFinalEvent); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Blocking call for task {}: {} event, returning with background consumption", taskIdForLogging(), isFinalEvent ? "final" : "non-final"); @@ -195,14 +202,14 @@ else if (blocking) { } if (shouldInterrupt) { + LOGGER.debug("ResultAggregator: Interrupting consumption (setting interrupted=true)"); // Complete the future to unblock the main thread interrupted.set(true); completionFuture.complete(null); // For blocking calls, DON'T complete consumptionCompletionFuture here. // Let it complete naturally when subscription finishes (onComplete callback below). - // This ensures all events are processed and persisted to TaskStore before - // DefaultRequestHandler.cleanupProducer() proceeds with cleanup. + // This ensures all events are fully processed before cleanup. // // For non-blocking and auth-required calls, complete immediately to allow // cleanup to proceed while consumption continues in background. @@ -237,7 +244,16 @@ else if (blocking) { } } ); - }, executor); + }, eventConsumerExecutor); + + // Wait for EventConsumer to start polling before we wait for events + // This prevents race where agent enqueues events before EventConsumer starts + try { + pollingStarted.await(5, java.util.concurrent.TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new io.a2a.spec.InternalError("Interrupted waiting for EventConsumer to start"); + } // Wait for completion or interruption try { @@ -261,28 +277,30 @@ else if (blocking) { Utils.rethrow(error); } - EventKind eventType; - Message msg = message.get(); - if (msg != null) { - eventType = msg; - } else { - Task task = taskManager.getTask(); - if (task == null) { - throw new io.a2a.spec.InternalError("No task or message available after consuming events"); + // Return Message if captured, otherwise Task if captured, otherwise fetch from TaskStore + EventKind eventKind = message.get(); + if (eventKind == null) { + eventKind = capturedTask.get(); + if (LOGGER.isDebugEnabled() && eventKind instanceof Task t) { + LOGGER.debug("Returning capturedTask: id={}, state={}", t.id(), t.status().state()); } - eventType = task; + } + if (eventKind == null) { + eventKind = taskManager.getTask(); + if (LOGGER.isDebugEnabled() && eventKind instanceof Task t) { + LOGGER.debug("Returning task from TaskStore: id={}, state={}", t.id(), t.status().state()); + } + } + if (eventKind == null) { + throw new InternalError("Could not find a Task/Message for " + taskManager.getTaskId()); } return new EventTypeAndInterrupt( - eventType, + eventKind, interrupted.get(), consumptionCompletionFuture); } - private void callTaskManagerProcess(Event event) throws A2AServerException { - taskManager.process(event); - } - private String taskIdForLogging() { Task task = taskManager.getTask(); return task != null ? task.id() : "unknown"; 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 fd3696a60..948ec596c 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 @@ -12,7 +12,7 @@ import io.a2a.spec.A2AServerException; import io.a2a.spec.Event; -import io.a2a.spec.InvalidParamsError; +import io.a2a.spec.InternalError; import io.a2a.spec.Message; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; @@ -59,12 +59,13 @@ public TaskManager(@Nullable String taskId, @Nullable String contextId, TaskStor return currentTask; } - Task saveTaskEvent(Task task) throws A2AServerException { + boolean saveTaskEvent(Task task, boolean isReplicated) throws A2AServerException { checkIdsAndUpdateIfNecessary(task.id(), task.contextId()); - return saveTask(task); + Task savedTask = saveTask(task, isReplicated); + return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); } - Task saveTaskEvent(TaskStatusUpdateEvent event) throws A2AServerException { + boolean saveTaskEvent(TaskStatusUpdateEvent event, boolean isReplicated) throws A2AServerException { checkIdsAndUpdateIfNecessary(event.taskId(), event.contextId()); Task task = ensureTask(event.taskId(), event.contextId()); @@ -86,10 +87,11 @@ Task saveTaskEvent(TaskStatusUpdateEvent event) throws A2AServerException { } task = builder.build(); - return saveTask(task); + Task savedTask = saveTask(task, isReplicated); + return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); } - Task saveTaskEvent(TaskArtifactUpdateEvent event) throws A2AServerException { + boolean saveTaskEvent(TaskArtifactUpdateEvent event, boolean isReplicated) throws A2AServerException { checkIdsAndUpdateIfNecessary(event.taskId(), event.contextId()); Task task = ensureTask(event.taskId(), event.contextId()); // taskId is guaranteed to be non-null after checkIdsAndUpdateIfNecessary @@ -98,18 +100,20 @@ Task saveTaskEvent(TaskArtifactUpdateEvent event) throws A2AServerException { throw new IllegalStateException("taskId should not be null after checkIdsAndUpdateIfNecessary"); } task = appendArtifactToTask(task, event, nonNullTaskId); - return saveTask(task); + Task savedTask = saveTask(task, isReplicated); + return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); } - public Event process(Event event) throws A2AServerException { + public boolean process(Event event, boolean isReplicated) throws A2AServerException { + boolean isFinal = false; if (event instanceof Task task) { - saveTaskEvent(task); + isFinal = saveTaskEvent(task, isReplicated); } else if (event instanceof TaskStatusUpdateEvent taskStatusUpdateEvent) { - saveTaskEvent(taskStatusUpdateEvent); + isFinal = saveTaskEvent(taskStatusUpdateEvent, isReplicated); } else if (event instanceof TaskArtifactUpdateEvent taskArtifactUpdateEvent) { - saveTaskEvent(taskArtifactUpdateEvent); + isFinal = saveTaskEvent(taskArtifactUpdateEvent, isReplicated); } - return event; + return isFinal; } public Task updateWithMessage(Message message, Task task) { @@ -125,7 +129,7 @@ public Task updateWithMessage(Message message, Task task) { .status(status) .history(history) .build(); - saveTask(task); + saveTask(task, false); // Local operation, not replicated return task; } @@ -133,7 +137,7 @@ private void checkIdsAndUpdateIfNecessary(String eventTaskId, String eventContex if (taskId != null && !eventTaskId.equals(taskId)) { throw new A2AServerException( "Invalid task id", - new InvalidParamsError(String.format("Task in event doesn't match TaskManager "))); + new InternalError(String.format("Task event has taskId %s but TaskManager has %s", eventTaskId, taskId))); } if (taskId == null) { taskId = eventTaskId; @@ -155,7 +159,7 @@ private Task ensureTask(String eventTaskId, String eventContextId) { } if (task == null) { task = createTask(eventTaskId, eventContextId); - saveTask(task); + saveTask(task, false); // Local operation, not replicated } return task; } @@ -170,8 +174,8 @@ private Task createTask(String taskId, String contextId) { .build(); } - private Task saveTask(Task task) { - taskStore.save(task); + private Task saveTask(Task task, boolean isReplicated) { + taskStore.save(task, isReplicated); if (taskId == null) { taskId = task.id(); contextId = task.contextId(); 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 18707fba2..3df903f77 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 @@ -100,8 +100,11 @@ public interface TaskStore { * Saves or updates a task. * * @param task the task to save + * @param isReplicated true if this task update came from a replicated event, + * false if it originated locally. Used to prevent feedback loops + * in replicated scenarios (e.g., don't fire TaskFinalizedEvent for replicated updates) */ - void save(Task task); + void save(Task task, boolean isReplicated); /** * Retrieves a task by its ID. 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 e26dd55fb..eee254ba3 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 @@ -1,8 +1,8 @@ package io.a2a.server.util.async; +import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -26,6 +26,7 @@ public class AsyncExecutorProducer { private static final String A2A_EXECUTOR_CORE_POOL_SIZE = "a2a.executor.core-pool-size"; private static final String A2A_EXECUTOR_MAX_POOL_SIZE = "a2a.executor.max-pool-size"; private static final String A2A_EXECUTOR_KEEP_ALIVE_SECONDS = "a2a.executor.keep-alive-seconds"; + private static final String A2A_EXECUTOR_QUEUE_CAPACITY = "a2a.executor.queue-capacity"; @Inject A2AConfigProvider configProvider; @@ -57,6 +58,16 @@ public class AsyncExecutorProducer { */ long keepAliveSeconds; + /** + * Queue capacity for pending tasks. + *

    + * Property: {@code a2a.executor.queue-capacity}
    + * Default: 100
    + * Note: Must be bounded to allow pool growth to maxPoolSize. + * When queue is full, new threads are created up to maxPoolSize. + */ + int queueCapacity; + private @Nullable ExecutorService executor; @PostConstruct @@ -64,18 +75,34 @@ public void init() { corePoolSize = Integer.parseInt(configProvider.getValue(A2A_EXECUTOR_CORE_POOL_SIZE)); maxPoolSize = Integer.parseInt(configProvider.getValue(A2A_EXECUTOR_MAX_POOL_SIZE)); keepAliveSeconds = Long.parseLong(configProvider.getValue(A2A_EXECUTOR_KEEP_ALIVE_SECONDS)); - - LOGGER.info("Initializing async executor: corePoolSize={}, maxPoolSize={}, keepAliveSeconds={}", - corePoolSize, maxPoolSize, keepAliveSeconds); - - executor = new ThreadPoolExecutor( + queueCapacity = Integer.parseInt(configProvider.getValue(A2A_EXECUTOR_QUEUE_CAPACITY)); + + LOGGER.info("Initializing async executor: corePoolSize={}, maxPoolSize={}, keepAliveSeconds={}, queueCapacity={}", + corePoolSize, maxPoolSize, keepAliveSeconds, queueCapacity); + + // CRITICAL: Use ArrayBlockingQueue (bounded) instead of LinkedBlockingQueue (unbounded). + // With unbounded queue, ThreadPoolExecutor NEVER grows beyond corePoolSize because the + // queue never fills. This causes executor pool exhaustion during concurrent requests when + // EventConsumer polling threads hold all core threads and agent tasks queue indefinitely. + // Bounded queue enables pool growth: when queue is full, new threads are created up to + // maxPoolSize, preventing agent execution starvation. + ThreadPoolExecutor tpe = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveSeconds, TimeUnit.SECONDS, - new LinkedBlockingQueue<>(), + new ArrayBlockingQueue<>(queueCapacity), new A2AThreadFactory() ); + + // CRITICAL: Allow core threads to timeout after keepAliveSeconds when idle. + // By default, ThreadPoolExecutor only times out threads above corePoolSize. + // Without this, core threads accumulate during testing and never clean up. + // This is essential for streaming scenarios where many short-lived tasks create threads + // for agent execution and cleanup callbacks, but those threads remain idle afterward. + tpe.allowCoreThreadTimeOut(true); + + executor = tpe; } @PreDestroy @@ -106,6 +133,22 @@ public Executor produce() { return executor; } + /** + * Log current executor pool statistics for diagnostics. + * Useful for debugging pool exhaustion or sizing issues. + */ + public void logPoolStats() { + if (executor instanceof ThreadPoolExecutor tpe) { + LOGGER.info("Executor pool stats: active={}/{}, queued={}/{}, completed={}, total={}", + tpe.getActiveCount(), + tpe.getPoolSize(), + tpe.getQueue().size(), + queueCapacity, + tpe.getCompletedTaskCount(), + tpe.getTaskCount()); + } + } + private static class A2AThreadFactory implements ThreadFactory { private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix = "a2a-agent-executor-"; diff --git a/server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java b/server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java new file mode 100644 index 000000000..24ff7f5d1 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java @@ -0,0 +1,93 @@ +package io.a2a.server.util.async; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Qualifier; + +import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Produces a dedicated executor for EventConsumer polling threads. + *

    + * CRITICAL: EventConsumer polling must use a separate executor from AgentExecutor because: + *

      + *
    • EventConsumer threads are I/O-bound (blocking on queue.poll()), not CPU-bound
    • + *
    • One EventConsumer thread needed per active queue (can be 100+ concurrent)
    • + *
    • Threads are mostly idle, waiting for events
    • + *
    • Using the same bounded pool as AgentExecutor causes deadlock when pool exhausted
    • + *
    + *

    + * Uses a cached thread pool (unbounded) with automatic thread reclamation: + *

      + *
    • Creates threads on demand as EventConsumers start
    • + *
    • Idle threads automatically terminated after 10 seconds
    • + *
    • No queue saturation since threads are created as needed
    • + *
    + */ +@ApplicationScoped +public class EventConsumerExecutorProducer { + private static final Logger LOGGER = LoggerFactory.getLogger(EventConsumerExecutorProducer.class); + + /** + * Qualifier annotation for EventConsumer executor injection. + */ + @Retention(RUNTIME) + @Target({METHOD, FIELD, PARAMETER, TYPE}) + @Qualifier + public @interface EventConsumerExecutor { + } + + /** + * Thread factory for EventConsumer threads. + */ + private static class EventConsumerThreadFactory implements ThreadFactory { + private final AtomicInteger threadNumber = new AtomicInteger(1); + + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r, "a2a-event-consumer-" + threadNumber.getAndIncrement()); + thread.setDaemon(true); + return thread; + } + } + + private @Nullable ExecutorService executor; + + @Produces + @EventConsumerExecutor + @ApplicationScoped + public Executor eventConsumerExecutor() { + // Cached thread pool with 10s idle timeout (reduced from default 60s): + // - Creates threads on demand as EventConsumers start + // - Reclaims idle threads after 10s to prevent accumulation during fast test execution + // - Perfect for I/O-bound EventConsumer polling which blocks on queue.poll() + // - 10s timeout balances thread reuse (production) vs cleanup (testing) + executor = new ThreadPoolExecutor( + 0, // corePoolSize - no core threads + Integer.MAX_VALUE, // maxPoolSize - unbounded + 10, TimeUnit.SECONDS, // keepAliveTime - 10s idle timeout + new SynchronousQueue<>(), // queue - same as cached pool + new EventConsumerThreadFactory() + ); + + LOGGER.info("Initialized EventConsumer executor: cached thread pool (unbounded, 10s idle timeout)"); + + return executor; + } +} diff --git a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java new file mode 100644 index 000000000..737fbac23 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java @@ -0,0 +1,136 @@ +package io.a2a.server.util.sse; + +import io.a2a.grpc.utils.JSONRPCUtils; +import io.a2a.jsonrpc.common.wrappers.A2AErrorResponse; +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.GetExtendedAgentCardResponse; +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.SendMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; + +/** + * Framework-agnostic utility for formatting A2A responses as Server-Sent Events (SSE). + *

    + * Provides static methods to serialize A2A responses to JSON and format them as SSE events. + * This allows HTTP server frameworks (Vert.x, Jakarta/WildFly, etc.) to use their own + * reactive libraries for publisher mapping while sharing the serialization logic. + *

    + * Example usage (Quarkus/Vert.x with Mutiny): + *

    {@code
    + * Flow.Publisher> responses = handler.onMessageSendStream(request, context);
    + * AtomicLong eventId = new AtomicLong(0);
    + *
    + * Multi sseEvents = Multi.createFrom().publisher(responses)
    + *     .map(response -> SseFormatter.formatResponseAsSSE(response, eventId.getAndIncrement()));
    + *
    + * sseEvents.subscribe().with(sseEvent -> httpResponse.write(Buffer.buffer(sseEvent)));
    + * }
    + *

    + * Example usage (Jakarta/WildFly with custom reactive library): + *

    {@code
    + * Flow.Publisher jsonStrings = restHandler.getJsonPublisher();
    + * AtomicLong eventId = new AtomicLong(0);
    + *
    + * Flow.Publisher sseEvents = mapPublisher(jsonStrings,
    + *     json -> SseFormatter.formatJsonAsSSE(json, eventId.getAndIncrement()));
    + * }
    + */ +public class SseFormatter { + + private SseFormatter() { + // Utility class - prevent instantiation + } + + /** + * Format an A2A response as an SSE event. + *

    + * Serializes the response to JSON and formats as: + *

    +     * data: {"jsonrpc":"2.0","result":{...},"id":123}
    +     * id: 0
    +     *
    +     * 
    + * + * @param response the A2A response to format + * @param eventId the SSE event ID + * @return SSE-formatted string (ready to write to HTTP response) + */ + public static String formatResponseAsSSE(A2AResponse response, long eventId) { + String jsonData = serializeResponse(response); + return "data: " + jsonData + "\nid: " + eventId + "\n\n"; + } + + /** + * Format a pre-serialized JSON string as an SSE event. + *

    + * Wraps the JSON in SSE format as: + *

    +     * data: {"jsonrpc":"2.0","result":{...},"id":123}
    +     * id: 0
    +     *
    +     * 
    + *

    + * Use this when you already have JSON strings (e.g., from REST transport) + * and just need to add SSE formatting. + * + * @param jsonString the JSON string to wrap + * @param eventId the SSE event ID + * @return SSE-formatted string (ready to write to HTTP response) + */ + public static String formatJsonAsSSE(String jsonString, long eventId) { + return "data: " + jsonString + "\nid: " + eventId + "\n\n"; + } + + /** + * Serialize an A2AResponse to JSON string. + */ + private static String serializeResponse(A2AResponse response) { + // For error responses, use standard JSON-RPC error format + if (response instanceof A2AErrorResponse error) { + return JSONRPCUtils.toJsonRPCErrorResponse(error.getId(), error.getError()); + } + if (response.getError() != null) { + return JSONRPCUtils.toJsonRPCErrorResponse(response.getId(), response.getError()); + } + + // Convert domain response to protobuf message and serialize + com.google.protobuf.MessageOrBuilder protoMessage = convertToProto(response); + return JSONRPCUtils.toJsonRPCResultResponse(response.getId(), protoMessage); + } + + /** + * Convert A2AResponse to protobuf message for serialization. + */ + 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) { + return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); + } else if (response instanceof SendMessageResponse r) { + return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessage(r.getResult()); + } else if (response instanceof ListTasksResponse r) { + return io.a2a.grpc.utils.ProtoUtils.ToProto.listTasksResult(r.getResult()); + } else if (response instanceof SetTaskPushNotificationConfigResponse r) { + return io.a2a.grpc.utils.ProtoUtils.ToProto.setTaskPushNotificationConfigResponse(r.getResult()); + } else if (response instanceof GetTaskPushNotificationConfigResponse r) { + return io.a2a.grpc.utils.ProtoUtils.ToProto.getTaskPushNotificationConfigResponse(r.getResult()); + } else if (response instanceof ListTaskPushNotificationConfigResponse r) { + return io.a2a.grpc.utils.ProtoUtils.ToProto.listTaskPushNotificationConfigResponse(r.getResult()); + } else if (response instanceof DeleteTaskPushNotificationConfigResponse) { + // DeleteTaskPushNotificationConfig has no result body, just return empty message + return com.google.protobuf.Empty.getDefaultInstance(); + } else if (response instanceof GetExtendedAgentCardResponse r) { + return io.a2a.grpc.utils.ProtoUtils.ToProto.getExtendedCardResponse(r.getResult()); + } else if (response instanceof SendStreamingMessageResponse r) { + return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessageStream(r.getResult()); + } else { + throw new IllegalArgumentException("Unknown response type: " + response.getClass().getName()); + } + } +} diff --git a/server-common/src/main/java/io/a2a/server/util/sse/package-info.java b/server-common/src/main/java/io/a2a/server/util/sse/package-info.java new file mode 100644 index 000000000..7e668b632 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/util/sse/package-info.java @@ -0,0 +1,11 @@ +/** + * Server-Sent Events (SSE) formatting utilities for A2A streaming responses. + *

    + * Provides framework-agnostic conversion of {@code Flow.Publisher>} to + * {@code Flow.Publisher} with SSE formatting, enabling easy integration with + * any HTTP server framework (Vert.x, Jakarta Servlet, etc.). + */ +@NullMarked +package io.a2a.server.util.sse; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/resources/META-INF/a2a-defaults.properties b/server-common/src/main/resources/META-INF/a2a-defaults.properties index 280fd943b..719be9e7a 100644 --- a/server-common/src/main/resources/META-INF/a2a-defaults.properties +++ b/server-common/src/main/resources/META-INF/a2a-defaults.properties @@ -19,3 +19,7 @@ a2a.executor.max-pool-size=50 # Keep-alive time for idle threads (seconds) a2a.executor.keep-alive-seconds=60 + +# Queue capacity for pending tasks (must be bounded to enable pool growth) +# When queue is full, new threads are created up to max-pool-size +a2a.executor.queue-capacity=100 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 4354f1639..146bfb10a 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 @@ -16,6 +16,8 @@ import java.util.concurrent.atomic.AtomicReference; import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.server.tasks.InMemoryTaskStore; +import io.a2a.server.tasks.PushNotificationSender; import io.a2a.spec.A2AError; import io.a2a.spec.A2AServerException; import io.a2a.spec.Artifact; @@ -27,14 +29,19 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class EventConsumerTest { + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final String TASK_ID = "123"; // Must match MINIMAL_TASK id + private EventQueue eventQueue; private EventConsumer eventConsumer; - + private MainEventBus mainEventBus; + private MainEventBusProcessor mainEventBusProcessor; private static final String MINIMAL_TASK = """ { @@ -54,10 +61,59 @@ public class EventConsumerTest { @BeforeEach public void init() { - eventQueue = EventQueue.builder().build(); + // Set up MainEventBus and processor for production-like test environment + InMemoryTaskStore taskStore = new InMemoryTaskStore(); + mainEventBus = new MainEventBus(); + InMemoryQueueManager queueManager = new InMemoryQueueManager(taskStore, mainEventBus); + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); + EventQueueUtil.start(mainEventBusProcessor); + + eventQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .taskId(TASK_ID) + .mainEventBus(mainEventBus) + .build().tap(); eventConsumer = new EventConsumer(eventQueue); } + @AfterEach + public void cleanup() { + if (mainEventBusProcessor != null) { + mainEventBusProcessor.setCallback(null); // Clear any test callbacks + EventQueueUtil.stop(mainEventBusProcessor); + } + } + + /** + * Helper to wait for MainEventBusProcessor to process an event. + * Replaces polling patterns with deterministic callback-based waiting. + * + * @param action the action that triggers event processing + * @throws InterruptedException if waiting is interrupted + * @throws AssertionError if processing doesn't complete within timeout + */ + private void waitForEventProcessing(Runnable action) throws InterruptedException { + CountDownLatch processingLatch = new CountDownLatch(1); + mainEventBusProcessor.setCallback(new MainEventBusProcessorCallback() { + @Override + public void onEventProcessed(String taskId, Event event) { + processingLatch.countDown(); + } + + @Override + public void onTaskFinalized(String taskId) { + // Not needed for basic event processing wait + } + }); + + try { + action.run(); + assertTrue(processingLatch.await(5, TimeUnit.SECONDS), + "MainEventBusProcessor should have processed the event within timeout"); + } finally { + mainEventBusProcessor.setCallback(null); + } + } + @Test public void testConsumeOneTaskEvent() throws Exception { Task event = fromJson(MINIMAL_TASK, Task.class); @@ -92,7 +148,7 @@ public void testConsumeAllMultipleEvents() throws JsonProcessingException { List events = List.of( fromJson(MINIMAL_TASK, Task.class), TaskArtifactUpdateEvent.builder() - .taskId("task-123") + .taskId(TASK_ID) .contextId("session-xyz") .artifact(Artifact.builder() .artifactId("11") @@ -100,7 +156,7 @@ public void testConsumeAllMultipleEvents() throws JsonProcessingException { .build()) .build(), TaskStatusUpdateEvent.builder() - .taskId("task-123") + .taskId(TASK_ID) .contextId("session-xyz") .status(new TaskStatus(TaskState.WORKING)) .isFinal(true) @@ -128,7 +184,7 @@ public void testConsumeUntilMessage() throws Exception { List events = List.of( fromJson(MINIMAL_TASK, Task.class), TaskArtifactUpdateEvent.builder() - .taskId("task-123") + .taskId(TASK_ID) .contextId("session-xyz") .artifact(Artifact.builder() .artifactId("11") @@ -136,7 +192,7 @@ public void testConsumeUntilMessage() throws Exception { .build()) .build(), TaskStatusUpdateEvent.builder() - .taskId("task-123") + .taskId(TASK_ID) .contextId("session-xyz") .status(new TaskStatus(TaskState.WORKING)) .isFinal(true) @@ -185,14 +241,14 @@ public void testConsumeMessageEvents() throws Exception { @Test public void testConsumeTaskInputRequired() { Task task = Task.builder() - .id("task-id") - .contextId("task-context") + .id(TASK_ID) + .contextId("session-xyz") .status(new TaskStatus(TaskState.INPUT_REQUIRED)) .build(); List events = List.of( task, TaskArtifactUpdateEvent.builder() - .taskId("task-123") + .taskId(TASK_ID) .contextId("session-xyz") .artifact(Artifact.builder() .artifactId("11") @@ -200,7 +256,7 @@ public void testConsumeTaskInputRequired() { .build()) .build(), TaskStatusUpdateEvent.builder() - .taskId("task-123") + .taskId(TASK_ID) .contextId("session-xyz") .status(new TaskStatus(TaskState.WORKING)) .isFinal(true) @@ -332,7 +388,9 @@ public void onComplete() { @Test public void testConsumeAllStopsOnQueueClosed() throws Exception { - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .mainEventBus(mainEventBus) + .build().tap(); EventConsumer consumer = new EventConsumer(queue); // Close the queue immediately @@ -378,12 +436,16 @@ public void onComplete() { @Test public void testConsumeAllHandlesQueueClosedException() throws Exception { - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .mainEventBus(mainEventBus) + .build().tap(); EventConsumer consumer = new EventConsumer(queue); // Add a message event (which will complete the stream) Event message = fromJson(MESSAGE_PAYLOAD, Message.class); - queue.enqueueEvent(message); + + // Use callback to wait for event processing + waitForEventProcessing(() -> queue.enqueueEvent(message)); // Close the queue before consuming queue.close(); @@ -428,11 +490,13 @@ public void onComplete() { @Test public void testConsumeAllTerminatesOnQueueClosedEvent() throws Exception { - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .mainEventBus(mainEventBus) + .build().tap(); EventConsumer consumer = new EventConsumer(queue); // Enqueue a QueueClosedEvent (poison pill) - QueueClosedEvent queueClosedEvent = new QueueClosedEvent("task-123"); + QueueClosedEvent queueClosedEvent = new QueueClosedEvent(TASK_ID); queue.enqueueEvent(queueClosedEvent); Flow.Publisher publisher = consumer.consumeAll(); @@ -477,8 +541,12 @@ public void onComplete() { } private void enqueueAndConsumeOneEvent(Event event) throws Exception { - eventQueue.enqueueEvent(event); + // Use callback to wait for event processing + waitForEventProcessing(() -> eventQueue.enqueueEvent(event)); + + // Event is now available, consume it directly Event result = eventConsumer.consumeOne(); + assertNotNull(result, "Event should be available"); assertSame(event, result); } 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 a3dc7d916..2499a8173 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 @@ -11,7 +11,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import io.a2a.server.tasks.InMemoryTaskStore; +import io.a2a.server.tasks.PushNotificationSender; import io.a2a.spec.A2AError; import io.a2a.spec.Artifact; import io.a2a.spec.Event; @@ -23,12 +27,17 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class EventQueueTest { private EventQueue eventQueue; + private MainEventBus mainEventBus; + private MainEventBusProcessor mainEventBusProcessor; + + private static final String TASK_ID = "123"; // Must match MINIMAL_TASK id private static final String MINIMAL_TASK = """ { @@ -46,38 +55,96 @@ public class EventQueueTest { } """; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; @BeforeEach public void init() { - eventQueue = EventQueue.builder().build(); + // Set up MainEventBus and processor for production-like test environment + InMemoryTaskStore taskStore = new InMemoryTaskStore(); + mainEventBus = new MainEventBus(); + InMemoryQueueManager queueManager = new InMemoryQueueManager(taskStore, mainEventBus); + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); + EventQueueUtil.start(mainEventBusProcessor); + + eventQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .taskId(TASK_ID) + .mainEventBus(mainEventBus) + .build().tap(); + } + + @AfterEach + public void cleanup() { + if (mainEventBusProcessor != null) { + mainEventBusProcessor.setCallback(null); // Clear any test callbacks + EventQueueUtil.stop(mainEventBusProcessor); + } + } + /** + * Helper to create a queue with MainEventBus configured (for tests that need event distribution). + */ + private EventQueue createQueueWithEventBus(String taskId) { + return EventQueueUtil.getEventQueueBuilder(mainEventBus) + .taskId(taskId) + .build(); + } + + /** + * Helper to wait for MainEventBusProcessor to process an event. + * Replaces polling patterns with deterministic callback-based waiting. + * + * @param action the action that triggers event processing + * @throws InterruptedException if waiting is interrupted + * @throws AssertionError if processing doesn't complete within timeout + */ + private void waitForEventProcessing(Runnable action) throws InterruptedException { + CountDownLatch processingLatch = new CountDownLatch(1); + mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { + @Override + public void onEventProcessed(String taskId, io.a2a.spec.Event event) { + processingLatch.countDown(); + } + + @Override + public void onTaskFinalized(String taskId) { + // Not needed for basic event processing wait + } + }); + + try { + action.run(); + assertTrue(processingLatch.await(5, TimeUnit.SECONDS), + "MainEventBusProcessor should have processed the event within timeout"); + } finally { + mainEventBusProcessor.setCallback(null); + } } @Test public void testConstructorDefaultQueueSize() { - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); assertEquals(EventQueue.DEFAULT_QUEUE_SIZE, queue.getQueueSize()); } @Test public void testConstructorCustomQueueSize() { int customSize = 500; - EventQueue queue = EventQueue.builder().queueSize(customSize).build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).queueSize(customSize).build(); assertEquals(customSize, queue.getQueueSize()); } @Test public void testConstructorInvalidQueueSize() { // Test zero queue size - assertThrows(IllegalArgumentException.class, () -> EventQueue.builder().queueSize(0).build()); + assertThrows(IllegalArgumentException.class, () -> EventQueueUtil.getEventQueueBuilder(mainEventBus).queueSize(0).build()); // Test negative queue size - assertThrows(IllegalArgumentException.class, () -> EventQueue.builder().queueSize(-10).build()); + assertThrows(IllegalArgumentException.class, () -> EventQueueUtil.getEventQueueBuilder(mainEventBus).queueSize(-10).build()); } @Test public void testTapCreatesChildQueue() { - EventQueue parentQueue = EventQueue.builder().build(); + EventQueue parentQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); EventQueue childQueue = parentQueue.tap(); assertNotNull(childQueue); @@ -87,7 +154,7 @@ public void testTapCreatesChildQueue() { @Test public void testTapOnChildQueueThrowsException() { - EventQueue parentQueue = EventQueue.builder().build(); + EventQueue parentQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); EventQueue childQueue = parentQueue.tap(); assertThrows(IllegalStateException.class, () -> childQueue.tap()); @@ -95,69 +162,74 @@ public void testTapOnChildQueueThrowsException() { @Test public void testEnqueueEventPropagagesToChildren() throws Exception { - EventQueue parentQueue = EventQueue.builder().build(); - EventQueue childQueue = parentQueue.tap(); + EventQueue mainQueue = createQueueWithEventBus(TASK_ID); + EventQueue childQueue1 = mainQueue.tap(); + EventQueue childQueue2 = mainQueue.tap(); Event event = fromJson(MINIMAL_TASK, Task.class); - parentQueue.enqueueEvent(event); + mainQueue.enqueueEvent(event); - // Event should be available in both parent and child queues - Event parentEvent = parentQueue.dequeueEventItem(-1).getEvent(); - Event childEvent = childQueue.dequeueEventItem(-1).getEvent(); + // Event should be available in all child queues + // Note: MainEventBusProcessor runs async, so we use dequeueEventItem with timeout + Event child1Event = childQueue1.dequeueEventItem(5000).getEvent(); + Event child2Event = childQueue2.dequeueEventItem(5000).getEvent(); - assertSame(event, parentEvent); - assertSame(event, childEvent); + assertSame(event, child1Event); + assertSame(event, child2Event); } @Test public void testMultipleChildQueuesReceiveEvents() throws Exception { - EventQueue parentQueue = EventQueue.builder().build(); - EventQueue childQueue1 = parentQueue.tap(); - EventQueue childQueue2 = parentQueue.tap(); + EventQueue mainQueue = createQueueWithEventBus(TASK_ID); + EventQueue childQueue1 = mainQueue.tap(); + EventQueue childQueue2 = mainQueue.tap(); + EventQueue childQueue3 = mainQueue.tap(); Event event1 = fromJson(MINIMAL_TASK, Task.class); Event event2 = fromJson(MESSAGE_PAYLOAD, Message.class); - parentQueue.enqueueEvent(event1); - parentQueue.enqueueEvent(event2); + mainQueue.enqueueEvent(event1); + mainQueue.enqueueEvent(event2); - // All queues should receive both events - assertSame(event1, parentQueue.dequeueEventItem(-1).getEvent()); - assertSame(event2, parentQueue.dequeueEventItem(-1).getEvent()); + // All child queues should receive both events + // Note: Use timeout for async processing + assertSame(event1, childQueue1.dequeueEventItem(5000).getEvent()); + assertSame(event2, childQueue1.dequeueEventItem(5000).getEvent()); - assertSame(event1, childQueue1.dequeueEventItem(-1).getEvent()); - assertSame(event2, childQueue1.dequeueEventItem(-1).getEvent()); + assertSame(event1, childQueue2.dequeueEventItem(5000).getEvent()); + assertSame(event2, childQueue2.dequeueEventItem(5000).getEvent()); - assertSame(event1, childQueue2.dequeueEventItem(-1).getEvent()); - assertSame(event2, childQueue2.dequeueEventItem(-1).getEvent()); + assertSame(event1, childQueue3.dequeueEventItem(5000).getEvent()); + assertSame(event2, childQueue3.dequeueEventItem(5000).getEvent()); } @Test public void testChildQueueDequeueIndependently() throws Exception { - EventQueue parentQueue = EventQueue.builder().build(); - EventQueue childQueue1 = parentQueue.tap(); - EventQueue childQueue2 = parentQueue.tap(); + EventQueue mainQueue = createQueueWithEventBus(TASK_ID); + EventQueue childQueue1 = mainQueue.tap(); + EventQueue childQueue2 = mainQueue.tap(); + EventQueue childQueue3 = mainQueue.tap(); Event event = fromJson(MINIMAL_TASK, Task.class); - parentQueue.enqueueEvent(event); + mainQueue.enqueueEvent(event); - // Dequeue from child1 first - Event child1Event = childQueue1.dequeueEventItem(-1).getEvent(); + // Dequeue from child1 first (use timeout for async processing) + Event child1Event = childQueue1.dequeueEventItem(5000).getEvent(); assertSame(event, child1Event); // child2 should still have the event available - Event child2Event = childQueue2.dequeueEventItem(-1).getEvent(); + Event child2Event = childQueue2.dequeueEventItem(5000).getEvent(); assertSame(event, child2Event); - // Parent should still have the event available - Event parentEvent = parentQueue.dequeueEventItem(-1).getEvent(); - assertSame(event, parentEvent); + // child3 should still have the event available + Event child3Event = childQueue3.dequeueEventItem(5000).getEvent(); + assertSame(event, child3Event); } @Test public void testCloseImmediatePropagationToChildren() throws Exception { - EventQueue parentQueue = EventQueue.builder().build(); + EventQueue parentQueue = createQueueWithEventBus(TASK_ID); EventQueue childQueue = parentQueue.tap(); // Add events to both parent and child @@ -166,7 +238,7 @@ public void testCloseImmediatePropagationToChildren() throws Exception { assertFalse(childQueue.isClosed()); try { - assertNotNull(childQueue.dequeueEventItem(-1)); // Child has the event + assertNotNull(childQueue.dequeueEventItem(5000)); // Child has the event (use timeout) } catch (EventQueueClosedException e) { // This is fine if queue closed before dequeue } @@ -187,27 +259,37 @@ public void testCloseImmediatePropagationToChildren() throws Exception { @Test public void testEnqueueEventWhenClosed() throws Exception { - EventQueue queue = EventQueue.builder().build(); + EventQueue mainQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .taskId(TASK_ID) + .build(); + EventQueue childQueue = mainQueue.tap(); Event event = fromJson(MINIMAL_TASK, Task.class); - queue.close(); // Close the queue first - assertTrue(queue.isClosed()); + childQueue.close(); // Close the child queue first (removes from children list) + assertTrue(childQueue.isClosed()); + + // Create a new child queue BEFORE enqueuing (ensures it's in children list for distribution) + EventQueue newChildQueue = mainQueue.tap(); // MainQueue accepts events even when closed (for replication support) // This ensures late-arriving replicated events can be enqueued to closed queues - queue.enqueueEvent(event); + // Note: MainEventBusProcessor runs asynchronously, so we use dequeueEventItem with timeout + mainQueue.enqueueEvent(event); - // Event should be available for dequeuing - Event dequeuedEvent = queue.dequeueEventItem(-1).getEvent(); + // New child queue should receive the event (old closed child was removed from children list) + EventQueueItem item = newChildQueue.dequeueEventItem(5000); + assertNotNull(item); + Event dequeuedEvent = item.getEvent(); assertSame(event, dequeuedEvent); - // Now queue is closed and empty, should throw exception - assertThrows(EventQueueClosedException.class, () -> queue.dequeueEventItem(-1)); + // Now new child queue is closed and empty, should throw exception + newChildQueue.close(); + assertThrows(EventQueueClosedException.class, () -> newChildQueue.dequeueEventItem(-1)); } @Test public void testDequeueEventWhenClosedAndEmpty() throws Exception { - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build().tap(); queue.close(); assertTrue(queue.isClosed()); @@ -217,19 +299,27 @@ public void testDequeueEventWhenClosedAndEmpty() throws Exception { @Test public void testDequeueEventWhenClosedButHasEvents() throws Exception { - EventQueue queue = EventQueue.builder().build(); + EventQueue mainQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .taskId(TASK_ID) + .build(); + EventQueue childQueue = mainQueue.tap(); Event event = fromJson(MINIMAL_TASK, Task.class); - queue.enqueueEvent(event); - queue.close(); // Graceful close - events should remain - assertTrue(queue.isClosed()); + // Use callback to wait for event processing instead of polling + waitForEventProcessing(() -> mainQueue.enqueueEvent(event)); - // Should still be able to dequeue existing events - Event dequeuedEvent = queue.dequeueEventItem(-1).getEvent(); + // At this point, event has been processed and distributed to childQueue + childQueue.close(); // Graceful close - events should remain + assertTrue(childQueue.isClosed()); + + // Should still be able to dequeue existing events from closed queue + EventQueueItem item = childQueue.dequeueEventItem(5000); + assertNotNull(item); + Event dequeuedEvent = item.getEvent(); assertSame(event, dequeuedEvent); // Now queue is closed and empty, should throw exception - assertThrows(EventQueueClosedException.class, () -> queue.dequeueEventItem(-1)); + assertThrows(EventQueueClosedException.class, () -> childQueue.dequeueEventItem(-1)); } @Test @@ -244,7 +334,9 @@ public void testEnqueueAndDequeueEvent() throws Exception { public void testDequeueEventNoWait() throws Exception { Event event = fromJson(MINIMAL_TASK, Task.class); eventQueue.enqueueEvent(event); - Event dequeuedEvent = eventQueue.dequeueEventItem(-1).getEvent(); + EventQueueItem item = eventQueue.dequeueEventItem(5000); + assertNotNull(item); + Event dequeuedEvent = item.getEvent(); assertSame(event, dequeuedEvent); } @@ -257,7 +349,7 @@ public void testDequeueEventEmptyQueueNoWait() throws Exception { @Test public void testDequeueEventWait() throws Exception { Event event = TaskStatusUpdateEvent.builder() - .taskId("task-123") + .taskId(TASK_ID) .contextId("session-xyz") .status(new TaskStatus(TaskState.WORKING)) .isFinal(true) @@ -271,7 +363,7 @@ public void testDequeueEventWait() throws Exception { @Test public void testTaskDone() throws Exception { Event event = TaskArtifactUpdateEvent.builder() - .taskId("task-123") + .taskId(TASK_ID) .contextId("session-xyz") .artifact(Artifact.builder() .artifactId("11") @@ -347,7 +439,7 @@ public void testCloseIdempotent() throws Exception { assertTrue(eventQueue.isClosed()); // Test with immediate close as well - EventQueue eventQueue2 = EventQueue.builder().build(); + EventQueue eventQueue2 = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); eventQueue2.close(true); assertTrue(eventQueue2.isClosed()); @@ -361,19 +453,20 @@ public void testCloseIdempotent() throws Exception { */ @Test public void testCloseChildQueues() throws Exception { - EventQueue childQueue = eventQueue.tap(); + EventQueue mainQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); + EventQueue childQueue = mainQueue.tap(); assertTrue(childQueue != null); // Graceful close - parent closes but children remain open - eventQueue.close(); - assertTrue(eventQueue.isClosed()); + mainQueue.close(); + assertTrue(mainQueue.isClosed()); assertFalse(childQueue.isClosed()); // Child NOT closed on graceful parent close // Immediate close - parent force-closes all children - EventQueue parentQueue2 = EventQueue.builder().build(); - EventQueue childQueue2 = parentQueue2.tap(); - parentQueue2.close(true); // immediate=true - assertTrue(parentQueue2.isClosed()); + EventQueue mainQueue2 = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); + EventQueue childQueue2 = mainQueue2.tap(); + mainQueue2.close(true); // immediate=true + assertTrue(mainQueue2.isClosed()); assertTrue(childQueue2.isClosed()); // Child IS closed on immediate parent close } @@ -383,7 +476,7 @@ public void testCloseChildQueues() throws Exception { */ @Test public void testMainQueueReferenceCountingStaysOpenWithActiveChildren() throws Exception { - EventQueue mainQueue = EventQueue.builder().build(); + EventQueue mainQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); EventQueue child1 = mainQueue.tap(); EventQueue child2 = mainQueue.tap(); diff --git a/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java b/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java index 39201c1f6..6c9ed4a17 100644 --- a/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java +++ b/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java @@ -1,8 +1,39 @@ package io.a2a.server.events; +import java.util.concurrent.atomic.AtomicInteger; + public class EventQueueUtil { - // Since EventQueue.builder() is package protected, add a method to expose it - public static EventQueue.EventQueueBuilder getEventQueueBuilder() { - return EventQueue.builder(); + // Counter for generating unique test taskIds + private static final AtomicInteger TASK_ID_COUNTER = new AtomicInteger(0); + + /** + * Get an EventQueue builder pre-configured with the shared test MainEventBus and a unique taskId. + *

    + * Note: Returns MainQueue - tests should call .tap() if they need to consume events. + *

    + * + * @return builder with TEST_EVENT_BUS and unique taskId already set + */ + public static EventQueue.EventQueueBuilder getEventQueueBuilder(MainEventBus eventBus) { + return EventQueue.builder(eventBus) + .taskId("test-task-" + TASK_ID_COUNTER.incrementAndGet()); + } + + /** + * Start a MainEventBusProcessor instance. + * + * @param processor the processor to start + */ + public static void start(MainEventBusProcessor processor) { + processor.start(); + } + + /** + * Stop a MainEventBusProcessor instance. + * + * @param processor the processor to stop + */ + public static void stop(MainEventBusProcessor processor) { + processor.stop(); } } diff --git a/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java b/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java index 1eca1b739..3e09ff2af 100644 --- a/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java +++ b/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java @@ -14,7 +14,10 @@ import java.util.concurrent.ExecutionException; import java.util.stream.IntStream; +import io.a2a.server.tasks.InMemoryTaskStore; import io.a2a.server.tasks.MockTaskStateProvider; +import io.a2a.server.tasks.PushNotificationSender; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -22,17 +25,30 @@ public class InMemoryQueueManagerTest { private InMemoryQueueManager queueManager; private MockTaskStateProvider taskStateProvider; + private InMemoryTaskStore taskStore; + private MainEventBus mainEventBus; + private MainEventBusProcessor mainEventBusProcessor; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; @BeforeEach public void setUp() { taskStateProvider = new MockTaskStateProvider(); - queueManager = new InMemoryQueueManager(taskStateProvider); + taskStore = new InMemoryTaskStore(); + mainEventBus = new MainEventBus(); + queueManager = new InMemoryQueueManager(taskStateProvider, mainEventBus); + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); + EventQueueUtil.start(mainEventBusProcessor); + } + + @AfterEach + public void tearDown() { + EventQueueUtil.stop(mainEventBusProcessor); } @Test public void testAddNewQueue() { String taskId = "test_task_id"; - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); queueManager.add(taskId, queue); @@ -43,8 +59,8 @@ public void testAddNewQueue() { @Test public void testAddExistingQueueThrowsException() { String taskId = "test_task_id"; - EventQueue queue1 = EventQueue.builder().build(); - EventQueue queue2 = EventQueue.builder().build(); + EventQueue queue1 = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); + EventQueue queue2 = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); queueManager.add(taskId, queue1); @@ -56,7 +72,7 @@ public void testAddExistingQueueThrowsException() { @Test public void testGetExistingQueue() { String taskId = "test_task_id"; - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); queueManager.add(taskId, queue); EventQueue result = queueManager.get(taskId); @@ -73,7 +89,7 @@ public void testGetNonexistentQueue() { @Test public void testTapExistingQueue() { String taskId = "test_task_id"; - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); queueManager.add(taskId, queue); EventQueue tappedQueue = queueManager.tap(taskId); @@ -94,7 +110,7 @@ public void testTapNonexistentQueue() { @Test public void testCloseExistingQueue() { String taskId = "test_task_id"; - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); queueManager.add(taskId, queue); queueManager.close(taskId); @@ -129,7 +145,7 @@ public void testCreateOrTapNewQueue() { @Test public void testCreateOrTapExistingQueue() { String taskId = "test_task_id"; - EventQueue originalQueue = EventQueue.builder().build(); + EventQueue originalQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); queueManager.add(taskId, originalQueue); EventQueue result = queueManager.createOrTap(taskId); @@ -151,7 +167,7 @@ public void testConcurrentOperations() throws InterruptedException, ExecutionExc // Add tasks concurrently List> addFutures = taskIds.stream() .map(taskId -> CompletableFuture.supplyAsync(() -> { - EventQueue queue = EventQueue.builder().build(); + EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); queueManager.add(taskId, queue); return taskId; })) 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 ea5bbe797..9c64f03f9 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 @@ -26,7 +26,10 @@ import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; import io.a2a.server.events.EventQueueItem; +import io.a2a.server.events.EventQueueUtil; import io.a2a.server.events.InMemoryQueueManager; +import io.a2a.server.events.MainEventBus; +import io.a2a.server.events.MainEventBusProcessor; import io.a2a.server.tasks.BasePushNotificationSender; import io.a2a.server.tasks.InMemoryPushNotificationConfigStore; import io.a2a.server.tasks.InMemoryTaskStore; @@ -66,6 +69,8 @@ public class AbstractA2ARequestHandlerTest { private static final String PREFERRED_TRANSPORT = "preferred-transport"; private static final String A2A_REQUESTHANDLER_TEST_PROPERTIES = "/a2a-requesthandler-test.properties"; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + protected AgentExecutor executor; protected TaskStore taskStore; protected RequestHandler requestHandler; @@ -73,6 +78,8 @@ public class AbstractA2ARequestHandlerTest { protected AgentExecutorMethod agentExecutorCancel; protected InMemoryQueueManager queueManager; protected TestHttpClient httpClient; + protected MainEventBus mainEventBus; + protected MainEventBusProcessor mainEventBusProcessor; protected final Executor internalExecutor = Executors.newCachedThreadPool(); @@ -96,19 +103,31 @@ public void cancel(RequestContext context, EventQueue eventQueue) throws A2AErro InMemoryTaskStore inMemoryTaskStore = new InMemoryTaskStore(); taskStore = inMemoryTaskStore; - queueManager = new InMemoryQueueManager(inMemoryTaskStore); + + // Create push notification components BEFORE MainEventBusProcessor httpClient = new TestHttpClient(); PushNotificationConfigStore pushConfigStore = new InMemoryPushNotificationConfigStore(); PushNotificationSender pushSender = new BasePushNotificationSender(pushConfigStore, httpClient); + // Create MainEventBus and MainEventBusProcessor (production code path) + mainEventBus = new MainEventBus(); + queueManager = new InMemoryQueueManager(inMemoryTaskStore, mainEventBus); + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, pushSender, queueManager); + EventQueueUtil.start(mainEventBusProcessor); + requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, pushConfigStore, pushSender, internalExecutor); + executor, taskStore, queueManager, pushConfigStore, mainEventBusProcessor, internalExecutor, internalExecutor); } @AfterEach public void cleanup() { agentExecutorExecute = null; agentExecutorCancel = null; + + // Stop MainEventBusProcessor background thread + if (mainEventBusProcessor != null) { + EventQueueUtil.stop(mainEventBusProcessor); + } } protected static AgentCard createAgentCard(boolean streaming, boolean pushNotifications, boolean stateTransitionHistory) { 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 293babe4e..e69de29bb 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 @@ -1,1001 +0,0 @@ -package io.a2a.server.requesthandlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import io.a2a.server.ServerCallContext; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.tasks.InMemoryPushNotificationConfigStore; -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.TaskUpdater; -import io.a2a.spec.A2AError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; -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.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; - -/** - * Comprehensive tests for DefaultRequestHandler, backported from Python's - * test_default_request_handler.py. These tests cover core functionality that - * is transport-agnostic and should work across JSON-RPC, gRPC, and REST. - * - * Background cleanup and task tracking tests are from Python PR #440 and #472. - */ -public class DefaultRequestHandlerTest { - - private DefaultRequestHandler requestHandler; - private InMemoryTaskStore taskStore; - private InMemoryQueueManager queueManager; - private TestAgentExecutor agentExecutor; - private ServerCallContext serverCallContext; - - @BeforeEach - void setUp() { - taskStore = new InMemoryTaskStore(); - // Pass taskStore as TaskStateProvider to queueManager for task-aware queue management - queueManager = new InMemoryQueueManager(taskStore); - agentExecutor = new TestAgentExecutor(); - - requestHandler = DefaultRequestHandler.create( - agentExecutor, - taskStore, - queueManager, - null, // pushConfigStore - null, // pushSender - Executors.newCachedThreadPool() - ); - - serverCallContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of(), Set.of()); - } - - /** - * Test that multiple blocking messages to the same task work correctly - * when agent doesn't emit final events (fire-and-forget pattern). - * This replicates TCK test: test_message_send_continue_task - */ - @Test - @Timeout(10) - void testBlockingMessageContinueTask() throws Exception { - String taskId = "continue-task-1"; - String contextId = "continue-ctx-1"; - - // Configure agent to NOT complete tasks (like TCK fire-and-forget agent) - agentExecutor.setExecuteCallback((context, queue) -> { - Task task = context.getTask(); - if (task == null) { - // First message: create SUBMITTED task - task = Task.builder() - .id(context.getTaskId()) - .contextId(context.getContextId()) - .status(new TaskStatus(TaskState.SUBMITTED)) - .build(); - } else { - // Subsequent messages: emit WORKING task (non-final) - task = Task.builder() - .id(context.getTaskId()) - .contextId(context.getContextId()) - .status(new TaskStatus(TaskState.WORKING)) - .build(); - } - queue.enqueueEvent(task); - // Don't complete - just return (fire-and-forget) - }); - - // First blocking message - should return SUBMITTED task - Message message1 = Message.builder() - .messageId("msg-1") - .role(Message.Role.USER) - .parts(new TextPart("first message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendParams params1 = new MessageSendParams(message1, null, null, ""); - Object result1 = requestHandler.onMessageSend(params1, serverCallContext); - - assertTrue(result1 instanceof Task); - Task task1 = (Task) result1; - assertTrue(task1.id().equals(taskId)); - assertTrue(task1.status().state() == TaskState.SUBMITTED); - - // Second blocking message to SAME taskId - should not hang - Message message2 = Message.builder() - .messageId("msg-2") - .role(Message.Role.USER) - .parts(new TextPart("second message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendParams params2 = new MessageSendParams(message2, null, null, ""); - Object result2 = requestHandler.onMessageSend(params2, serverCallContext); - - // Should complete successfully (not timeout) - assertTrue(result2 instanceof Task); - } - - /** - * Test that background cleanup tasks are properly tracked and cleared. - * Backported from Python test: test_background_cleanup_task_is_tracked_and_cleared - */ - @Test - @Timeout(10) - void testBackgroundCleanupTaskIsTrackedAndCleared() throws Exception { - String taskId = "track-task-1"; - String contextId = "track-ctx-1"; - - // Create a task that will trigger background cleanup - Task task = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.SUBMITTED)) - .build(); - - taskStore.save(task); - - Message message = Message.builder() - .messageId("msg-track") - .role(Message.Role.USER) - .parts(new TextPart("test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendParams params = new MessageSendParams(message, null, null, ""); - - // Set up agent to finish quickly so cleanup runs - CountDownLatch agentStarted = new CountDownLatch(1); - CountDownLatch allowAgentFinish = new CountDownLatch(1); - - agentExecutor.setExecuteCallback((context, queue) -> { - agentStarted.countDown(); - try { - allowAgentFinish.await(5, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - }); - - // Start streaming (this will create background tasks) - var streamingResult = requestHandler.onMessageSendStream(params, serverCallContext); - - // Wait for agent to start - assertTrue(agentStarted.await(5, TimeUnit.SECONDS), "Agent should start"); - - // Allow agent to finish, which should trigger cleanup - allowAgentFinish.countDown(); - - // Give some time for background tasks to be tracked and cleaned up - Thread.sleep(1000); - - // Background tasks should eventually be cleared - // Note: We can't directly access the backgroundTasks field without reflection, - // but the test verifies the mechanism doesn't hang or leak tasks - assertTrue(true, "Background cleanup completed without hanging"); - } - - /** - * Test that client disconnect triggers background cleanup and producer continues. - * Backported from Python test: test_on_message_send_stream_client_disconnect_triggers_background_cleanup_and_producer_continues - */ - @Test - @Timeout(10) - void testStreamingClientDisconnectTriggersBackgroundCleanup() throws Exception { - String taskId = "disc-task-1"; - String contextId = "disc-ctx-1"; - - Message message = Message.builder() - .messageId("mid") - .role(Message.Role.USER) - .parts(new TextPart("test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendParams params = new MessageSendParams(message, null, null, ""); - - // Agent should start and then wait - CountDownLatch agentStarted = new CountDownLatch(1); - CountDownLatch allowAgentFinish = new CountDownLatch(1); - AtomicBoolean agentCompleted = new AtomicBoolean(false); - - agentExecutor.setExecuteCallback((context, queue) -> { - agentStarted.countDown(); - try { - allowAgentFinish.await(10, TimeUnit.SECONDS); - agentCompleted.set(true); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - }); - - // Start streaming - var streamingResult = requestHandler.onMessageSendStream(params, serverCallContext); - - // Wait for agent to start - assertTrue(agentStarted.await(5, TimeUnit.SECONDS), "Agent should start executing"); - - // Simulate client disconnect by not consuming the stream - // In real scenarios, the client would close the connection - - // Agent should still be running (not finished immediately on "disconnect") - Thread.sleep(500); - assertTrue(agentExecutor.isExecuting(), "Producer should still be running after simulated disconnect"); - - // Allow agent to finish - allowAgentFinish.countDown(); - - // Wait a bit for completion - Thread.sleep(1000); - - assertTrue(agentCompleted.get(), "Agent should have completed execution"); - } - - /** - * Test that resubscription works after client disconnect. - * Backported from Python test: test_stream_disconnect_then_resubscribe_receives_future_events - */ - @Test - @Timeout(15) - void testStreamDisconnectThenResubscribeReceivesFutureEvents() throws Exception { - String taskId = "reconn-task-1"; - String contextId = "reconn-ctx-1"; - - // Create initial task - Task initialTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) - .build(); - - taskStore.save(initialTask); - - Message message = Message.builder() - .messageId("msg-reconn") - .role(Message.Role.USER) - .parts(new TextPart("test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendParams params = new MessageSendParams(message, null, null, ""); - - // Set up agent to emit events with controlled timing - CountDownLatch agentStarted = new CountDownLatch(1); - CountDownLatch allowSecondEvent = new CountDownLatch(1); - CountDownLatch allowFinish = new CountDownLatch(1); - - agentExecutor.setExecuteCallback((context, queue) -> { - agentStarted.countDown(); - - // Emit first event - Task firstEvent = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) - .build(); - queue.enqueueEvent(firstEvent); - - // Wait for permission to emit second event - try { - allowSecondEvent.await(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return; - } - - // Emit second event - Task secondEvent = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.COMPLETED)) - .build(); - queue.enqueueEvent(secondEvent); - - try { - allowFinish.await(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - }); - - // Start streaming and simulate getting first event then disconnecting - var streamingResult = requestHandler.onMessageSendStream(params, serverCallContext); - - // Wait for agent to start and emit first event - assertTrue(agentStarted.await(5, TimeUnit.SECONDS), "Agent should start"); - - // Simulate client disconnect (in real scenario, client would close connection) - // The background cleanup should keep the producer running - - // Now try to resubscribe to the task - io.a2a.spec.TaskIdParams resubParams = new io.a2a.spec.TaskIdParams(taskId); - - // Allow agent to emit second event - allowSecondEvent.countDown(); - - // Try resubscription - this should work because queue is still alive - var resubResult = requestHandler.onResubscribeToTask(resubParams, serverCallContext); - // If we get here without exception, resubscription worked - assertTrue(true, "Resubscription succeeded"); - - // Clean up - allowFinish.countDown(); - } - - /** - * Test that task state is persisted to task store after client disconnect. - * Backported from Python test: test_disconnect_persists_final_task_to_store - */ - @Test - @Timeout(15) - void testDisconnectPersistsFinalTaskToStore() throws Exception { - String taskId = "persist-task-1"; - String contextId = "persist-ctx-1"; - - Message message = Message.builder() - .messageId("msg-persist") - .role(Message.Role.USER) - .parts(new TextPart("test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendParams params = new MessageSendParams(message, null, null, ""); - - // Agent that completes after some delay - CountDownLatch agentStarted = new CountDownLatch(1); - CountDownLatch allowCompletion = new CountDownLatch(1); - - agentExecutor.setExecuteCallback((context, queue) -> { - agentStarted.countDown(); - - // Emit working status - Task workingTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) - .build(); - queue.enqueueEvent(workingTask); - - try { - allowCompletion.await(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return; - } - - // Emit final completed status - Task completedTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.COMPLETED)) - .build(); - queue.enqueueEvent(completedTask); - }); - - // Start streaming and simulate client disconnect - var streamingResult = requestHandler.onMessageSendStream(params, serverCallContext); - - // Wait for agent to start - assertTrue(agentStarted.await(5, TimeUnit.SECONDS), "Agent should start"); - - // Simulate client disconnect by not consuming the stream further - // In real scenarios, the reactive stream would be cancelled - - // Allow agent to complete in background - allowCompletion.countDown(); - - // Give time for background processing to persist the final state - Thread.sleep(2000); - - // Verify the final task state was persisted despite client disconnect - Task persistedTask = taskStore.get(taskId); - if (persistedTask != null) { - // If task was persisted, it should have the final state - assertTrue( - persistedTask.status().state() == TaskState.COMPLETED || - persistedTask.status().state() == TaskState.WORKING, - "Task should be persisted with working or completed state, got: " + persistedTask.status().state() - ); - } - // Note: In some architectures, the task might not be persisted if the - // background consumption isn't implemented. This test documents the expected behavior. - } - - /** - * Test that blocking message call waits for agent to finish and returns complete Task - * even when agent does fire-and-forget (emits non-final state and returns). - * - * Expected behavior: - * 1. Agent emits WORKING state with artifacts - * 2. Agent's execute() method returns WITHOUT emitting final state - * 3. Blocking onMessageSend() should wait for agent execution to complete - * 4. Blocking onMessageSend() should wait for all queued events to be processed - * 5. Returned Task should have WORKING state with all artifacts included - * - * This tests fire-and-forget pattern with blocking calls. - */ - @Test - @Timeout(15) - void testBlockingFireAndForgetReturnsNonFinalTask() throws Exception { - String taskId = "blocking-fire-forget-task"; - String contextId = "blocking-fire-forget-ctx"; - - Message message = Message.builder() - .messageId("msg-blocking-fire-forget") - .role(Message.Role.USER) - .parts(new TextPart("test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendConfiguration config = MessageSendConfiguration.builder() - .blocking(true) - .build(); - - MessageSendParams params = new MessageSendParams(message, config, null, ""); - - // Agent that does fire-and-forget: emits WORKING with artifact but never completes - agentExecutor.setExecuteCallback((context, queue) -> { - TaskUpdater updater = new TaskUpdater(context, queue); - - // Start work (WORKING state) - updater.startWork(); - - // Add artifact - updater.addArtifact( - List.of(new TextPart("Fire and forget artifact")), - "artifact-1", "FireForget", null); - - // Agent returns WITHOUT calling updater.complete() - // Task stays in WORKING state (non-final) - }); - - // Call blocking onMessageSend - should wait for agent to finish - Object result = requestHandler.onMessageSend(params, serverCallContext); - - // The returned result should be a Task in WORKING state with artifact - assertTrue(result instanceof Task, "Result should be a Task"); - Task returnedTask = (Task) result; - - // Verify task is in WORKING state (non-final, fire-and-forget) - assertEquals(TaskState.WORKING, returnedTask.status().state(), - "Returned task should be WORKING (fire-and-forget), got: " + returnedTask.status().state()); - - // Verify artifacts are included in the returned task - assertNotNull(returnedTask.artifacts(), - "Returned task should have artifacts"); - assertTrue(returnedTask.artifacts().size() >= 1, - "Returned task should have at least 1 artifact, got: " + - returnedTask.artifacts().size()); - } - - /** - * Test that non-blocking message call returns immediately and persists all events in background. - * - * Expected behavior: - * 1. Non-blocking call returns immediately with first event (WORKING state) - * 2. Agent continues running in background and produces more events - * 3. Background consumption continues and persists all events to TaskStore - * 4. Final task state (COMPLETED) is persisted in background - */ - @Test - @Timeout(15) - void testNonBlockingMessagePersistsAllEventsInBackground() throws Exception { - String taskId = "blocking-persist-task"; - String contextId = "blocking-persist-ctx"; - - Message message = Message.builder() - .messageId("msg-nonblocking-persist") - .role(Message.Role.USER) - .parts(new TextPart("test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - // Use default non-blocking behavior - MessageSendConfiguration config = MessageSendConfiguration.builder() - .build(); - - MessageSendParams params = new MessageSendParams(message, config, null, ""); - - // Agent that produces multiple events with delays - CountDownLatch agentStarted = new CountDownLatch(1); - CountDownLatch firstEventEmitted = new CountDownLatch(1); - CountDownLatch allowCompletion = new CountDownLatch(1); - - agentExecutor.setExecuteCallback((context, queue) -> { - agentStarted.countDown(); - - // Emit first event (WORKING state) - Task workingTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) - .build(); - queue.enqueueEvent(workingTask); - firstEventEmitted.countDown(); - - // Sleep to ensure the non-blocking call has returned before we emit more events - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return; - } - - // Wait for permission to complete - try { - allowCompletion.await(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return; - } - - // Emit final event (COMPLETED state) - // This event should be persisted to TaskStore in background - Task completedTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.COMPLETED)) - .build(); - queue.enqueueEvent(completedTask); - }); - - // Call non-blocking onMessageSend - Object result = requestHandler.onMessageSend(params, serverCallContext); - - // Assertion 1: The immediate result should be the first event (WORKING) - assertTrue(result instanceof Task, "Result should be a Task"); - Task immediateTask = (Task) result; - assertEquals(TaskState.WORKING, immediateTask.status().state(), - "Non-blocking should return immediately with WORKING state, got: " + immediateTask.status().state()); - - // At this point, the non-blocking call has returned, but the agent is still running - - // Allow the agent to emit the final COMPLETED event - allowCompletion.countDown(); - - // Assertion 2: Poll for the final task state to be persisted in background - // Use polling loop instead of fixed sleep for faster and more reliable test - long timeoutMs = 5000; - long startTime = System.currentTimeMillis(); - Task persistedTask = null; - boolean completedStateFound = false; - - while (System.currentTimeMillis() - startTime < timeoutMs) { - persistedTask = taskStore.get(taskId); - if (persistedTask != null && persistedTask.status().state() == TaskState.COMPLETED) { - completedStateFound = true; - break; - } - Thread.sleep(100); // Poll every 100ms - } - - assertTrue(persistedTask != null, "Task should be persisted to store"); - assertTrue( - completedStateFound, - "Final task state should be COMPLETED (background consumption should have processed it), got: " + - (persistedTask != null ? persistedTask.status().state() : "null") + - " after " + (System.currentTimeMillis() - startTime) + "ms" - ); - } - - /** - * Test the BIG idea: MainQueue stays open for non-final tasks even when all children close. - * This enables fire-and-forget tasks and late resubscriptions. - */ - @Test - @Timeout(15) - void testMainQueueStaysOpenForNonFinalTasks() throws Exception { - String taskId = "fire-and-forget-task"; - String contextId = "fire-ctx"; - - // Create initial task in WORKING state (non-final) - Task initialTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) - .build(); - taskStore.save(initialTask); - - Message message = Message.builder() - .messageId("msg-fire") - .role(Message.Role.USER) - .parts(new TextPart("fire and forget")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendParams params = new MessageSendParams(message, null, null, ""); - - // Agent that emits WORKING status but never completes (fire-and-forget pattern) - CountDownLatch agentStarted = new CountDownLatch(1); - CountDownLatch allowAgentFinish = new CountDownLatch(1); - - agentExecutor.setExecuteCallback((context, queue) -> { - agentStarted.countDown(); - - // Emit WORKING status (non-final) - Task workingTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) - .build(); - queue.enqueueEvent(workingTask); - - // Don't emit final state - just wait and finish - try { - allowAgentFinish.await(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - // Agent finishes WITHOUT emitting final task state - }); - - // Start streaming - var streamingResult = requestHandler.onMessageSendStream(params, serverCallContext); - - // Wait for agent to start and emit WORKING event - assertTrue(agentStarted.await(5, TimeUnit.SECONDS), "Agent should start"); - - // Give time for WORKING event to be processed - Thread.sleep(500); - - // Simulate client disconnect - this closes the ChildQueue - // but MainQueue should stay open because task is non-final - - // Allow agent to finish - allowAgentFinish.countDown(); - - // Give time for agent to finish and cleanup to run - Thread.sleep(2000); - - // THE BIG IDEA TEST: Resubscription should work because MainQueue is still open - // Even though: - // 1. The original ChildQueue closed (client disconnected) - // 2. The agent finished executing - // 3. Task is still in non-final WORKING state - // Therefore: MainQueue should still be open for resubscriptions - - io.a2a.spec.TaskIdParams resubParams = new io.a2a.spec.TaskIdParams(taskId); - var resubResult = requestHandler.onResubscribeToTask(resubParams, serverCallContext); - - // If we get here without exception, the BIG idea works! - assertTrue(true, "Resubscription succeeded - MainQueue stayed open for non-final task"); - } - - /** - * Test that MainQueue DOES close when task is finalized. - * This ensures Level 2 protection doesn't prevent cleanup of completed tasks. - */ - @Test - @Timeout(15) - void testMainQueueClosesForFinalizedTasks() throws Exception { - String taskId = "completed-task"; - String contextId = "completed-ctx"; - - // Create initial task in COMPLETED state (already finalized) - Task completedTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.COMPLETED)) - .build(); - taskStore.save(completedTask); - - // Create a queue for this task - EventQueue mainQueue = queueManager.createOrTap(taskId); - assertTrue(mainQueue != null, "Queue should be created"); - - // Close the child queue (simulating client disconnect) - mainQueue.close(); - - // Give time for cleanup callback to run - Thread.sleep(1000); - - // Since the task is finalized (COMPLETED), the MainQueue should be removed from the map - // This tests that Level 2 protection (childClosing check) allows cleanup for finalized tasks - EventQueue queue = queueManager.get(taskId); - assertTrue(queue == null || queue.isClosed(), - "Queue for finalized task should be null or closed"); - } - - /** - * Test that blocking message call returns a Task with ALL artifacts included. - * This reproduces the reported bug: blocking call returns before artifacts are processed. - * - * Expected behavior: - * 1. Agent emits multiple artifacts via TaskUpdater - * 2. Blocking onMessageSend() should wait for ALL events to be processed - * 3. Returned Task should have all artifacts included in COMPLETED state - * - * Bug manifestation: - * - onMessageSend() returns after first event - * - Artifacts are still being processed in background - * - Returned Task is incomplete - */ - @Test - @Timeout(15) - void testBlockingCallReturnsCompleteTaskWithArtifacts() throws Exception { - String taskId = "blocking-artifacts-task"; - String contextId = "blocking-artifacts-ctx"; - - Message message = Message.builder() - .messageId("msg-blocking-artifacts") - .role(Message.Role.USER) - .parts(new TextPart("test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendConfiguration config = MessageSendConfiguration.builder() - .blocking(true) - .build(); - - MessageSendParams params = new MessageSendParams(message, config, null, ""); - - // Agent that uses TaskUpdater to emit multiple artifacts (like real agents do) - agentExecutor.setExecuteCallback((context, queue) -> { - TaskUpdater updater = new TaskUpdater(context, queue); - - // Start work (WORKING state) - updater.startWork(); - - // Add first artifact - updater.addArtifact( - List.of(new TextPart("First artifact")), - "artifact-1", "First", null); - - // Add second artifact - updater.addArtifact( - List.of(new TextPart("Second artifact")), - "artifact-2", "Second", null); - - // Complete the task - updater.complete(); - }); - - // Call blocking onMessageSend - should wait for ALL events - Object result = requestHandler.onMessageSend(params, serverCallContext); - - // The returned result should be a Task with ALL artifacts - assertTrue(result instanceof Task, "Result should be a Task"); - Task returnedTask = (Task) result; - - // Verify task is completed - assertEquals(TaskState.COMPLETED, returnedTask.status().state(), - "Returned task should be COMPLETED"); - - // Verify artifacts are included in the returned task - assertNotNull(returnedTask.artifacts(), - "Returned task should have artifacts"); - assertTrue(returnedTask.artifacts().size() >= 2, - "Returned task should have at least 2 artifacts, got: " + - returnedTask.artifacts().size()); - } - - /** - * Test that pushNotificationConfig from SendMessageConfiguration is stored for NEW tasks - * in non-streaming (blocking) mode. This reproduces the bug from issue #84. - * - * Expected behavior: - * 1. Client sends message with pushNotificationConfig in SendMessageConfiguration - * 2. Agent creates a new task - * 3. pushNotificationConfig should be stored in PushNotificationConfigStore - * 4. Config should be retrievable via getInfo() - */ - @Test - @Timeout(10) - void testBlockingMessageStoresPushNotificationConfigForNewTask() throws Exception { - String taskId = "push-config-blocking-new-task"; - String contextId = "push-config-ctx"; - - // Create test config store - InMemoryPushNotificationConfigStore pushConfigStore = new InMemoryPushNotificationConfigStore(); - - // Re-create request handler with pushConfigStore - requestHandler = DefaultRequestHandler.create( - agentExecutor, - taskStore, - queueManager, - pushConfigStore, // Add push config store - null, // pushSender - Executors.newCachedThreadPool() - ); - - // Create push notification config - PushNotificationConfig pushConfig = PushNotificationConfig.builder() - .id("config-1") - .url("https://example.com/webhook") - .token("test-token-123") - .build(); - - // Create message with pushNotificationConfig - Message message = Message.builder() - .messageId("msg-push-config") - .role(Message.Role.USER) - .parts(new TextPart("test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendConfiguration config = MessageSendConfiguration.builder() - .blocking(true) - .pushNotificationConfig(pushConfig) - .build(); - - MessageSendParams params = new MessageSendParams(message, config, null, ""); - - // Agent creates a new task - agentExecutor.setExecuteCallback((context, queue) -> { - TaskUpdater updater = new TaskUpdater(context, queue); - updater.submit(); // Creates new task in SUBMITTED state - updater.complete(); - }); - - // Call blocking onMessageSend - Object result = requestHandler.onMessageSend(params, serverCallContext); - - // Verify result is a task - assertTrue(result instanceof Task, "Result should be a Task"); - Task returnedTask = (Task) result; - assertEquals(taskId, returnedTask.id()); - - // THE KEY ASSERTION: Verify pushNotificationConfig was stored - ListTaskPushNotificationConfigResult storedConfigs = pushConfigStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(storedConfigs, "Push notification config should be stored for new task"); - assertEquals(1, storedConfigs.size(), - "Should have exactly 1 push config stored"); - PushNotificationConfig storedConfig = storedConfigs.configs().get(0).pushNotificationConfig(); - assertEquals("config-1", storedConfig.id()); - assertEquals("https://example.com/webhook", storedConfig.url()); - } - - /** - * Test that pushNotificationConfig is stored for EXISTING tasks. - * This verifies the initMessageSend logic works correctly. - */ - @Test - @Timeout(10) - void testBlockingMessageStoresPushNotificationConfigForExistingTask() throws Exception { - String taskId = "push-config-existing-task"; - String contextId = "push-config-existing-ctx"; - - // Create test config store - InMemoryPushNotificationConfigStore pushConfigStore = new InMemoryPushNotificationConfigStore(); - - // Re-create request handler with pushConfigStore - requestHandler = DefaultRequestHandler.create( - agentExecutor, - taskStore, - queueManager, - pushConfigStore, // Add push config store - null, // pushSender - Executors.newCachedThreadPool() - ); - - // Create EXISTING task in store - Task existingTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) - .build(); - taskStore.save(existingTask); - - // Create push notification config - PushNotificationConfig pushConfig = PushNotificationConfig.builder() - .id("config-existing-1") - .url("https://example.com/existing-webhook") - .token("existing-token-789") - .build(); - - Message message = Message.builder() - .messageId("msg-push-existing") - .role(Message.Role.USER) - .parts(new TextPart("update existing task")) - .taskId(taskId) - .contextId(contextId) - .build(); - - MessageSendConfiguration config = MessageSendConfiguration.builder() - .blocking(true) - .pushNotificationConfig(pushConfig) - .build(); - - MessageSendParams params = new MessageSendParams(message, config, null, ""); - - // Agent updates the existing task - agentExecutor.setExecuteCallback((context, queue) -> { - TaskUpdater updater = new TaskUpdater(context, queue); - updater.addArtifact( - List.of(new TextPart("update artifact")), - "artifact-1", "Update", null); - updater.complete(); - }); - - // Call blocking onMessageSend - Object result = requestHandler.onMessageSend(params, serverCallContext); - - // Verify result - assertTrue(result instanceof Task, "Result should be a Task"); - - // Verify pushNotificationConfig was stored (initMessageSend path) - ListTaskPushNotificationConfigResult storedConfigs = pushConfigStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(storedConfigs,"Push notification config should be stored for existing task"); - assertEquals(1, storedConfigs.size(),"Should have exactly 1 push config stored"); - PushNotificationConfig storedConfig = storedConfigs.configs().get(0).pushNotificationConfig(); - assertEquals("config-existing-1", storedConfig.id()); - assertEquals("https://example.com/existing-webhook", storedConfig.url()); - } - - /** - * Simple test agent executor that allows controlling execution timing - */ - private static class TestAgentExecutor implements AgentExecutor { - private ExecuteCallback executeCallback; - private volatile boolean executing = false; - - interface ExecuteCallback { - void call(RequestContext context, EventQueue queue) throws A2AError; - } - - void setExecuteCallback(ExecuteCallback callback) { - this.executeCallback = callback; - } - - boolean isExecuting() { - return executing; - } - - @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { - executing = true; - try { - if (executeCallback != null) { - // Custom callback is responsible for emitting events - executeCallback.call(context, eventQueue); - } else { - // No custom callback - emit default completion event - Task completedTask = Task.builder() - .id(context.getTaskId()) - .contextId(context.getContextId()) - .status(new TaskStatus(TaskState.COMPLETED)) - .build(); - eventQueue.enqueueEvent(completedTask); - } - - } finally { - executing = false; - } - } - - @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { - // Simple cancel implementation - executing = false; - } - } -} \ No newline at end of file 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 e814c1c15..e69de29bb 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,49 +0,0 @@ -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 org.junit.jupiter.api.Test; - -public class InMemoryTaskStoreTest { - private static final String TASK_JSON = """ - { - "id": "task-abc", - "contextId" : "session-xyz", - "status": {"state": "submitted"} - }"""; - - @Test - public void testSaveAndGet() throws Exception { - InMemoryTaskStore store = new InMemoryTaskStore(); - Task task = fromJson(TASK_JSON, Task.class); - store.save(task); - Task retrieved = store.get(task.id()); - assertSame(task, retrieved); - } - - @Test - public void testGetNonExistent() throws Exception { - InMemoryTaskStore store = new InMemoryTaskStore(); - Task retrieved = store.get("nonexistent"); - assertNull(retrieved); - } - - @Test - public void testDelete() throws Exception { - InMemoryTaskStore store = new InMemoryTaskStore(); - Task task = fromJson(TASK_JSON, Task.class); - store.save(task); - store.delete(task.id()); - Task retrieved = store.get(task.id()); - assertNull(retrieved); - } - - @Test - public void testDeleteNonExistent() throws Exception { - InMemoryTaskStore store = new InMemoryTaskStore(); - store.delete("non-existent"); - } -} diff --git a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java index d64729077..0e25e9aad 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java @@ -11,18 +11,25 @@ import static org.mockito.Mockito.when; import java.util.Collections; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import io.a2a.server.events.EventConsumer; import io.a2a.server.events.EventQueue; +import io.a2a.server.events.EventQueueUtil; import io.a2a.server.events.InMemoryQueueManager; +import io.a2a.server.events.MainEventBus; +import io.a2a.server.events.MainEventBusProcessor; +import io.a2a.spec.Event; import io.a2a.spec.EventKind; import io.a2a.spec.Message; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; @@ -49,7 +56,7 @@ public class ResultAggregatorTest { @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); - aggregator = new ResultAggregator(mockTaskManager, null, testExecutor); + aggregator = new ResultAggregator(mockTaskManager, null, testExecutor, testExecutor); } // Helper methods for creating sample data @@ -69,13 +76,45 @@ private Task createSampleTask(String taskId, TaskState statusState, String conte .build(); } + /** + * Helper to wait for MainEventBusProcessor to process an event. + * Replaces polling patterns with deterministic callback-based waiting. + * + * @param processor the processor to set callback on + * @param action the action that triggers event processing + * @throws InterruptedException if waiting is interrupted + * @throws AssertionError if processing doesn't complete within timeout + */ + private void waitForEventProcessing(MainEventBusProcessor processor, Runnable action) throws InterruptedException { + CountDownLatch processingLatch = new CountDownLatch(1); + processor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { + @Override + public void onEventProcessed(String taskId, Event event) { + processingLatch.countDown(); + } + + @Override + public void onTaskFinalized(String taskId) { + // Not needed for basic event processing wait + } + }); + + try { + action.run(); + assertTrue(processingLatch.await(5, TimeUnit.SECONDS), + "MainEventBusProcessor should have processed the event within timeout"); + } finally { + processor.setCallback(null); + } + } + // Basic functionality tests @Test void testConstructorWithMessage() { Message initialMessage = createSampleMessage("initial", "msg1", Message.Role.USER); - ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, initialMessage, testExecutor); + ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, initialMessage, testExecutor, testExecutor); // Test that the message is properly stored by checking getCurrentResult assertEquals(initialMessage, aggregatorWithMessage.getCurrentResult()); @@ -86,7 +125,7 @@ void testConstructorWithMessage() { @Test void testGetCurrentResultWithMessageSet() { Message sampleMessage = createSampleMessage("hola", "msg1", Message.Role.USER); - ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, sampleMessage, testExecutor); + ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, sampleMessage, testExecutor, testExecutor); EventKind result = aggregatorWithMessage.getCurrentResult(); @@ -121,7 +160,7 @@ void testConstructorStoresTaskManagerCorrectly() { @Test void testConstructorWithNullMessage() { - ResultAggregator aggregatorWithNullMessage = new ResultAggregator(mockTaskManager, null, testExecutor); + ResultAggregator aggregatorWithNullMessage = new ResultAggregator(mockTaskManager, null, testExecutor, testExecutor); Task expectedTask = createSampleTask("null_msg_task", TaskState.WORKING, "ctx1"); when(mockTaskManager.getTask()).thenReturn(expectedTask); @@ -181,7 +220,7 @@ void testMultipleGetCurrentResultCalls() { void testGetCurrentResultWithMessageTakesPrecedence() { // Test that when both message and task are available, message takes precedence Message message = createSampleMessage("priority message", "pri1", Message.Role.USER); - ResultAggregator messageAggregator = new ResultAggregator(mockTaskManager, message, testExecutor); + ResultAggregator messageAggregator = new ResultAggregator(mockTaskManager, message, testExecutor, testExecutor); // Even if we set up the task manager to return something, message should take precedence Task task = createSampleTask("should_not_be_returned", TaskState.WORKING, "ctx1"); @@ -197,17 +236,24 @@ void testGetCurrentResultWithMessageTakesPrecedence() { @Test void testConsumeAndBreakNonBlocking() throws Exception { // Test that with blocking=false, the method returns after the first event - Task firstEvent = createSampleTask("non_blocking_task", TaskState.WORKING, "ctx1"); + String taskId = "test-task"; + Task firstEvent = createSampleTask(taskId, TaskState.WORKING, "ctx1"); // After processing firstEvent, the current result will be that task when(mockTaskManager.getTask()).thenReturn(firstEvent); // Create an event queue using QueueManager (which has access to builder) + MainEventBus mainEventBus = new MainEventBus(); + InMemoryTaskStore taskStore = new InMemoryTaskStore(); InMemoryQueueManager queueManager = - new InMemoryQueueManager(new MockTaskStateProvider()); + new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + EventQueueUtil.start(processor); + + EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); - EventQueue queue = queueManager.getEventQueueBuilder("test-task").build(); - queue.enqueueEvent(firstEvent); + // Use callback to wait for event processing (replaces polling) + waitForEventProcessing(processor, () -> queue.enqueueEvent(firstEvent)); // Create real EventConsumer with the queue EventConsumer eventConsumer = @@ -221,11 +267,16 @@ void testConsumeAndBreakNonBlocking() throws Exception { assertEquals(firstEvent, result.eventType()); assertTrue(result.interrupted()); - verify(mockTaskManager).process(firstEvent); - // getTask() is called at least once for the return value (line 255) - // May be called once more if debug logging executes in time (line 209) - // The async consumer may or may not execute before verification, so we accept 1-2 calls - verify(mockTaskManager, atLeast(1)).getTask(); - verify(mockTaskManager, atMost(2)).getTask(); + // NOTE: ResultAggregator no longer calls taskManager.process() + // That responsibility has moved to MainEventBusProcessor for centralized persistence + // + // NOTE: Since firstEvent is a Task, ResultAggregator captures it directly from the queue + // (capturedTask.get() at line 283 in ResultAggregator). Therefore, taskManager.getTask() + // is only called for debug logging in taskIdForLogging() (line 305), which may or may not + // execute depending on timing and log level. We expect 0-1 calls, not 1-2. + verify(mockTaskManager, atMost(1)).getTask(); + + // Cleanup: stop the processor + EventQueueUtil.stop(processor); } } 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 f14ebc0fe..91010e52e 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 @@ -48,7 +48,7 @@ public void init() throws Exception { @Test public void testGetTaskExisting() { Task expectedTask = minimalTask; - taskStore.save(expectedTask); + taskStore.save(expectedTask, false); Task retrieved = taskManager.getTask(); assertSame(expectedTask, retrieved); } @@ -61,16 +61,16 @@ public void testGetTaskNonExistent() { @Test public void testSaveTaskEventNewTask() throws A2AServerException { - Task saved = taskManager.saveTaskEvent(minimalTask); + taskManager.saveTaskEvent(minimalTask, false); + Task saved = taskManager.getTask(); Task retrieved = taskManager.getTask(); assertSame(minimalTask, retrieved); - assertSame(retrieved, saved); } @Test public void testSaveTaskEventStatusUpdate() throws A2AServerException { Task initialTask = minimalTask; - taskStore.save(initialTask); + taskStore.save(initialTask, false); TaskStatus newStatus = new TaskStatus( TaskState.WORKING, @@ -88,11 +88,11 @@ public void testSaveTaskEventStatusUpdate() throws A2AServerException { new HashMap<>()); - Task saved = taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); + Task saved = taskManager.getTask(); Task updated = taskManager.getTask(); assertNotSame(initialTask, updated); - assertSame(updated, saved); assertEquals(initialTask.id(), updated.id()); assertEquals(initialTask.contextId(), updated.contextId()); @@ -114,10 +114,10 @@ public void testSaveTaskEventArtifactUpdate() throws A2AServerException { .contextId(minimalTask.contextId()) .artifact(newArtifact) .build(); - Task saved = taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); + Task saved = taskManager.getTask(); Task updatedTask = taskManager.getTask(); - assertSame(updatedTask, saved); assertNotSame(initialTask, updatedTask); assertEquals(initialTask.id(), updatedTask.id()); @@ -144,7 +144,8 @@ public void testEnsureTaskNonExistentForStatusUpdate() throws A2AServerException .isFinal(false) .build(); - Task task = taskManagerWithoutId.saveTaskEvent(event); + taskManagerWithoutId.saveTaskEvent(event, false); + Task task = taskManagerWithoutId.getTask(); assertEquals(event.taskId(), taskManagerWithoutId.getTaskId()); assertEquals(event.contextId(), taskManagerWithoutId.getContextId()); @@ -164,13 +165,13 @@ public void testSaveTaskEventNewTaskNoTaskId() throws A2AServerException { .status(new TaskStatus(TaskState.WORKING)) .build(); - Task saved = taskManagerWithoutId.saveTaskEvent(task); + taskManagerWithoutId.saveTaskEvent(task, false); + Task saved = taskManager.getTask(); assertEquals(task.id(), taskManagerWithoutId.getTaskId()); assertEquals(task.contextId(), taskManagerWithoutId.getContextId()); Task retrieved = taskManagerWithoutId.getTask(); assertSame(task, retrieved); - assertSame(retrieved, saved); } @Test @@ -194,7 +195,7 @@ public void testTaskArtifactUpdateEventAppendTrueWithExistingArtifact() throws A Task taskWithArtifact = Task.builder(initialTask) .artifacts(Collections.singletonList(existingArtifact)) .build(); - taskStore.save(taskWithArtifact); + taskStore.save(taskWithArtifact, false); // Test: Append new parts to existing artifact Artifact newArtifact = Artifact.builder() @@ -209,7 +210,8 @@ public void testTaskArtifactUpdateEventAppendTrueWithExistingArtifact() throws A .append(true) .build(); - Task updatedTask = taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); + Task updatedTask = taskManager.getTask(); assertEquals(1, updatedTask.artifacts().size()); Artifact updatedArtifact = updatedTask.artifacts().get(0); @@ -223,7 +225,7 @@ public void testTaskArtifactUpdateEventAppendTrueWithExistingArtifact() throws A public void testTaskArtifactUpdateEventAppendTrueWithoutExistingArtifact() throws A2AServerException { // Setup: Create a task without artifacts Task initialTask = minimalTask; - taskStore.save(initialTask); + taskStore.save(initialTask, false); // Test: Try to append to non-existent artifact (should be ignored) Artifact newArtifact = Artifact.builder() @@ -238,7 +240,8 @@ public void testTaskArtifactUpdateEventAppendTrueWithoutExistingArtifact() throw .append(true) .build(); - Task saved = taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); + Task saved = taskManager.getTask(); Task updatedTask = taskManager.getTask(); // Should have no artifacts since append was ignored @@ -257,7 +260,7 @@ public void testTaskArtifactUpdateEventAppendFalseWithExistingArtifact() throws Task taskWithArtifact = Task.builder(initialTask) .artifacts(Collections.singletonList(existingArtifact)) .build(); - taskStore.save(taskWithArtifact); + taskStore.save(taskWithArtifact, false); // Test: Replace existing artifact (append=false) Artifact newArtifact = Artifact.builder() @@ -272,7 +275,8 @@ public void testTaskArtifactUpdateEventAppendFalseWithExistingArtifact() throws .append(false) .build(); - Task saved = taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); + Task saved = taskManager.getTask(); Task updatedTask = taskManager.getTask(); assertEquals(1, updatedTask.artifacts().size()); @@ -294,7 +298,7 @@ public void testTaskArtifactUpdateEventAppendNullWithExistingArtifact() throws A Task taskWithArtifact = Task.builder(initialTask) .artifacts(Collections.singletonList(existingArtifact)) .build(); - taskStore.save(taskWithArtifact); + taskStore.save(taskWithArtifact, false); // Test: Replace existing artifact (append=null, defaults to false) Artifact newArtifact = Artifact.builder() @@ -308,7 +312,8 @@ public void testTaskArtifactUpdateEventAppendNullWithExistingArtifact() throws A .artifact(newArtifact) .build(); // append is null - Task saved = taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); + Task saved = taskManager.getTask(); Task updatedTask = taskManager.getTask(); assertEquals(1, updatedTask.artifacts().size()); @@ -330,7 +335,7 @@ public void testAddingTaskWithDifferentIdFails() { .build(); assertThrows(A2AServerException.class, () -> { - taskManagerWithId.saveTaskEvent(differentTask); + taskManagerWithId.saveTaskEvent(differentTask, false); }); } @@ -347,7 +352,7 @@ public void testAddingTaskWithDifferentIdViaStatusUpdateFails() { .build(); assertThrows(A2AServerException.class, () -> { - taskManagerWithId.saveTaskEvent(event); + taskManagerWithId.saveTaskEvent(event, false); }); } @@ -368,7 +373,7 @@ public void testAddingTaskWithDifferentIdViaArtifactUpdateFails() { .build(); assertThrows(A2AServerException.class, () -> { - taskManagerWithId.saveTaskEvent(event); + taskManagerWithId.saveTaskEvent(event, false); }); } @@ -392,7 +397,8 @@ public void testTaskWithNoMessageUsesInitialMessage() throws A2AServerException .isFinal(false) .build(); - Task saved = taskManagerWithInitialMessage.saveTaskEvent(event); + taskManagerWithInitialMessage.saveTaskEvent(event, false); + Task saved = taskManager.getTask(); Task retrieved = taskManagerWithInitialMessage.getTask(); // Check that the task has the initial message in its history @@ -429,7 +435,8 @@ public void testTaskWithMessageDoesNotUseInitialMessage() throws A2AServerExcept .isFinal(false) .build(); - Task saved = taskManagerWithInitialMessage.saveTaskEvent(event); + taskManagerWithInitialMessage.saveTaskEvent(event, false); + Task saved = taskManager.getTask(); Task retrieved = taskManagerWithInitialMessage.getTask(); // There should now be a history containing the initialMessage @@ -447,7 +454,7 @@ public void testTaskWithMessageDoesNotUseInitialMessage() throws A2AServerExcept public void testMultipleArtifactsWithSameArtifactId() throws A2AServerException { // Test handling of multiple artifacts with the same artifactId Task initialTask = minimalTask; - taskStore.save(initialTask); + taskStore.save(initialTask, false); // Add first artifact Artifact artifact1 = Artifact.builder() @@ -460,7 +467,7 @@ public void testMultipleArtifactsWithSameArtifactId() throws A2AServerException .contextId(minimalTask.contextId()) .artifact(artifact1) .build(); - taskManager.saveTaskEvent(event1); + taskManager.saveTaskEvent(event1, false); // Add second artifact with same artifactId (should replace the first) Artifact artifact2 = Artifact.builder() @@ -473,7 +480,7 @@ public void testMultipleArtifactsWithSameArtifactId() throws A2AServerException .contextId(minimalTask.contextId()) .artifact(artifact2) .build(); - taskManager.saveTaskEvent(event2); + taskManager.saveTaskEvent(event2, false); Task updatedTask = taskManager.getTask(); assertEquals(1, updatedTask.artifacts().size()); @@ -487,7 +494,7 @@ public void testMultipleArtifactsWithSameArtifactId() throws A2AServerException public void testMultipleArtifactsWithDifferentArtifactIds() throws A2AServerException { // Test handling of multiple artifacts with different artifactIds Task initialTask = minimalTask; - taskStore.save(initialTask); + taskStore.save(initialTask, false); // Add first artifact Artifact artifact1 = Artifact.builder() @@ -500,7 +507,7 @@ public void testMultipleArtifactsWithDifferentArtifactIds() throws A2AServerExce .contextId(minimalTask.contextId()) .artifact(artifact1) .build(); - taskManager.saveTaskEvent(event1); + taskManager.saveTaskEvent(event1, false); // Add second artifact with different artifactId (should be added) Artifact artifact2 = Artifact.builder() @@ -513,7 +520,7 @@ public void testMultipleArtifactsWithDifferentArtifactIds() throws A2AServerExce .contextId(minimalTask.contextId()) .artifact(artifact2) .build(); - taskManager.saveTaskEvent(event2); + taskManager.saveTaskEvent(event2, false); Task updatedTask = taskManager.getTask(); assertEquals(2, updatedTask.artifacts().size()); @@ -545,7 +552,7 @@ public void testInvalidTaskIdValidation() { public void testSaveTaskEventMetadataUpdate() throws A2AServerException { // Test that metadata from TaskStatusUpdateEvent gets saved to the task Task initialTask = minimalTask; - taskStore.save(initialTask); + taskStore.save(initialTask, false); Map newMetadata = new HashMap<>(); newMetadata.put("meta_key_test", "meta_value_test"); @@ -558,7 +565,7 @@ public void testSaveTaskEventMetadataUpdate() throws A2AServerException { .metadata(newMetadata) .build(); - taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); Task updatedTask = taskManager.getTask(); assertEquals(newMetadata, updatedTask.metadata()); @@ -568,7 +575,7 @@ public void testSaveTaskEventMetadataUpdate() throws A2AServerException { public void testSaveTaskEventMetadataUpdateNull() throws A2AServerException { // Test that null metadata in TaskStatusUpdateEvent doesn't affect task Task initialTask = minimalTask; - taskStore.save(initialTask); + taskStore.save(initialTask, false); TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId(minimalTask.id()) @@ -578,7 +585,7 @@ public void testSaveTaskEventMetadataUpdateNull() throws A2AServerException { .metadata(null) .build(); - taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); Task updatedTask = taskManager.getTask(); // Should preserve original task's metadata (which is likely null for minimal task) @@ -594,7 +601,7 @@ public void testSaveTaskEventMetadataMergeExisting() throws A2AServerException { Task taskWithMetadata = Task.builder(minimalTask) .metadata(originalMetadata) .build(); - taskStore.save(taskWithMetadata); + taskStore.save(taskWithMetadata, false); Map newMetadata = new HashMap<>(); newMetadata.put("new_key", "new_value"); @@ -607,7 +614,7 @@ public void testSaveTaskEventMetadataMergeExisting() throws A2AServerException { .metadata(newMetadata) .build(); - taskManager.saveTaskEvent(event); + taskManager.saveTaskEvent(event, false); Task updatedTask = taskManager.getTask(); @@ -634,7 +641,8 @@ public void testCreateTaskWithInitialMessage() throws A2AServerException { .isFinal(false) .build(); - Task savedTask = taskManagerWithMessage.saveTaskEvent(event); + taskManagerWithMessage.saveTaskEvent(event, false); + Task savedTask = taskManagerWithMessage.getTask(); // Verify task was created properly assertNotNull(savedTask); @@ -662,7 +670,8 @@ public void testCreateTaskWithoutInitialMessage() throws A2AServerException { .isFinal(false) .build(); - Task savedTask = taskManagerWithoutMessage.saveTaskEvent(event); + taskManagerWithoutMessage.saveTaskEvent(event, false); + Task savedTask = taskManagerWithoutMessage.getTask(); // Verify task was created properly assertNotNull(savedTask); @@ -685,7 +694,8 @@ public void testSaveTaskInternal() throws A2AServerException { .status(new TaskStatus(TaskState.WORKING)) .build(); - Task savedTask = taskManagerWithoutId.saveTaskEvent(newTask); + taskManagerWithoutId.saveTaskEvent(newTask, false); + Task savedTask = taskManagerWithoutId.getTask(); // Verify internal state was updated assertEquals("test-task-id", taskManagerWithoutId.getTaskId()); @@ -716,7 +726,8 @@ public void testUpdateWithMessage() throws A2AServerException { .isFinal(false) .build(); - Task saved = taskManagerWithInitialMessage.saveTaskEvent(event); + taskManagerWithInitialMessage.saveTaskEvent(event, false); + Task saved = taskManagerWithInitialMessage.getTask(); Message updateMessage = Message.builder() .role(Message.Role.USER) diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java b/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java index 40f763569..73da17824 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java @@ -14,7 +14,11 @@ import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; +import io.a2a.server.events.EventQueueItem; import io.a2a.server.events.EventQueueUtil; +import io.a2a.server.events.InMemoryQueueManager; +import io.a2a.server.events.MainEventBus; +import io.a2a.server.events.MainEventBusProcessor; import io.a2a.spec.Event; import io.a2a.spec.Message; import io.a2a.spec.Part; @@ -22,6 +26,7 @@ import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -38,14 +43,28 @@ public class TaskUpdaterTest { private static final List> SAMPLE_PARTS = List.of(new TextPart("Test message")); + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + EventQueue eventQueue; + private MainEventBus mainEventBus; + private MainEventBusProcessor mainEventBusProcessor; private TaskUpdater taskUpdater; @BeforeEach public void init() { - eventQueue = EventQueueUtil.getEventQueueBuilder().build(); + // Set up MainEventBus and processor for production-like test environment + InMemoryTaskStore taskStore = new InMemoryTaskStore(); + mainEventBus = new MainEventBus(); + InMemoryQueueManager queueManager = new InMemoryQueueManager(taskStore, mainEventBus); + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); + EventQueueUtil.start(mainEventBusProcessor); + + eventQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .taskId(TEST_TASK_ID) + .mainEventBus(mainEventBus) + .build().tap(); RequestContext context = new RequestContext.Builder() .setTaskId(TEST_TASK_ID) .setContextId(TEST_TASK_CONTEXT_ID) @@ -53,10 +72,19 @@ public void init() { taskUpdater = new TaskUpdater(context, eventQueue); } + @AfterEach + public void cleanup() { + if (mainEventBusProcessor != null) { + EventQueueUtil.stop(mainEventBusProcessor); + } + } + @Test public void testAddArtifactWithCustomIdAndName() throws Exception { taskUpdater.addArtifact(SAMPLE_PARTS, "custom-artifact-id", "Custom Artifact", null); - Event event = eventQueue.dequeueEventItem(0).getEvent(); + EventQueueItem item = eventQueue.dequeueEventItem(5000); + assertNotNull(item); + Event event = item.getEvent(); assertNotNull(event); assertInstanceOf(TaskArtifactUpdateEvent.class, event); @@ -239,7 +267,9 @@ public void testNewAgentMessageWithMetadata() throws Exception { @Test public void testAddArtifactWithAppendTrue() throws Exception { taskUpdater.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, true, null); - Event event = eventQueue.dequeueEventItem(0).getEvent(); + EventQueueItem item = eventQueue.dequeueEventItem(5000); + assertNotNull(item); + Event event = item.getEvent(); assertNotNull(event); assertInstanceOf(TaskArtifactUpdateEvent.class, event); @@ -258,7 +288,9 @@ public void testAddArtifactWithAppendTrue() throws Exception { @Test public void testAddArtifactWithLastChunkTrue() throws Exception { taskUpdater.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, null, true); - Event event = eventQueue.dequeueEventItem(0).getEvent(); + EventQueueItem item = eventQueue.dequeueEventItem(5000); + assertNotNull(item); + Event event = item.getEvent(); assertNotNull(event); assertInstanceOf(TaskArtifactUpdateEvent.class, event); @@ -273,7 +305,9 @@ public void testAddArtifactWithLastChunkTrue() throws Exception { @Test public void testAddArtifactWithAppendAndLastChunk() throws Exception { taskUpdater.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, true, false); - Event event = eventQueue.dequeueEventItem(0).getEvent(); + EventQueueItem item = eventQueue.dequeueEventItem(5000); + assertNotNull(item); + Event event = item.getEvent(); assertNotNull(event); assertInstanceOf(TaskArtifactUpdateEvent.class, event); @@ -287,7 +321,9 @@ public void testAddArtifactWithAppendAndLastChunk() throws Exception { @Test public void testAddArtifactGeneratesIdWhenNull() throws Exception { taskUpdater.addArtifact(SAMPLE_PARTS, null, "Test Artifact", null); - Event event = eventQueue.dequeueEventItem(0).getEvent(); + EventQueueItem item = eventQueue.dequeueEventItem(5000); + assertNotNull(item); + Event event = item.getEvent(); assertNotNull(event); assertInstanceOf(TaskArtifactUpdateEvent.class, event); @@ -383,7 +419,9 @@ public void testConcurrentCompletionAttempts() throws Exception { thread2.join(); // Exactly one event should have been queued - Event event = eventQueue.dequeueEventItem(0).getEvent(); + EventQueueItem item = eventQueue.dequeueEventItem(5000); + assertNotNull(item); + Event event = item.getEvent(); assertNotNull(event); assertInstanceOf(TaskStatusUpdateEvent.class, event); @@ -396,7 +434,10 @@ public void testConcurrentCompletionAttempts() throws Exception { } private TaskStatusUpdateEvent checkTaskStatusUpdateEventOnQueue(boolean isFinal, TaskState state, Message statusMessage) throws Exception { - Event event = eventQueue.dequeueEventItem(0).getEvent(); + // Wait up to 5 seconds for event (async MainEventBusProcessor needs time to distribute) + EventQueueItem item = eventQueue.dequeueEventItem(5000); + assertNotNull(item); + Event event = item.getEvent(); assertNotNull(event); assertInstanceOf(TaskStatusUpdateEvent.class, event); @@ -408,6 +449,7 @@ private TaskStatusUpdateEvent checkTaskStatusUpdateEventOnQueue(boolean isFinal, assertEquals(state, tsue.status().state()); assertEquals(statusMessage, tsue.status().message()); + // Check no additional events (still use 0 timeout for this check) assertNull(eventQueue.dequeueEventItem(0)); return tsue; diff --git a/tck/src/main/resources/application.properties b/tck/src/main/resources/application.properties index c68793be4..b23747b00 100644 --- a/tck/src/main/resources/application.properties +++ b/tck/src/main/resources/application.properties @@ -12,6 +12,7 @@ a2a.executor.keep-alive-seconds=60 quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG quarkus.log.category."io.a2a.server.events".level=DEBUG quarkus.log.category."io.a2a.server.tasks".level=DEBUG +io.a2a.server.diagnostics.ThreadStats.level=DEBUG # Log to file for analysis quarkus.log.file.enable=true 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 724b58613..62acc506e 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 @@ -656,7 +656,20 @@ public void testResubscribeExistingTaskSuccess() throws Exception { AtomicReference errorRef = new AtomicReference<>(); // Create consumer to handle resubscribed events + AtomicBoolean receivedInitialTask = new AtomicBoolean(false); BiConsumer consumer = (event, agentCard) -> { + // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent + if (!receivedInitialTask.get()) { + if (event instanceof TaskEvent) { + receivedInitialTask.set(true); + // Don't count down latch for initial Task + return; + } else { + fail("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + } + } + + // Process subsequent events if (event instanceof TaskUpdateEvent taskUpdateEvent) { if (taskUpdateEvent.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifactEvent) { artifactUpdateEvent.set(artifactEvent); @@ -755,12 +768,25 @@ public void testResubscribeExistingTaskSuccessWithClientConsumers() throws Excep AtomicReference errorRef = new AtomicReference<>(); // Create consumer to handle resubscribed events + AtomicBoolean receivedInitialTask = new AtomicBoolean(false); AgentCard agentCard = createTestAgentCard(); ClientConfig clientConfig = createClientConfig(true); ClientBuilder clientBuilder = Client .builder(agentCard) .addConsumer((evt, agentCard1) -> { + // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent + if (!receivedInitialTask.get()) { + if (evt instanceof TaskEvent) { + receivedInitialTask.set(true); + // Don't count down latch for initial Task + return; + } else { + fail("First event on resubscribe MUST be TaskEvent, but was: " + evt.getClass().getSimpleName()); + } + } + + // Process subsequent events if (evt instanceof TaskUpdateEvent taskUpdateEvent) { if (taskUpdateEvent.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifactEvent) { artifactUpdateEvent.set(artifactEvent); @@ -918,8 +944,20 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti AtomicReference firstConsumerEvent = new AtomicReference<>(); AtomicBoolean firstUnexpectedEvent = new AtomicBoolean(false); AtomicReference firstErrorRef = new AtomicReference<>(); + AtomicBoolean firstReceivedInitialTask = new AtomicBoolean(false); BiConsumer firstConsumer = (event, agentCard) -> { + // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent + if (!firstReceivedInitialTask.get()) { + if (event instanceof TaskEvent) { + firstReceivedInitialTask.set(true); + return; + } else { + fail("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + } + } + + // Process subsequent events if (event instanceof TaskUpdateEvent tue && tue.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifact) { firstConsumerEvent.set(artifact); firstConsumerLatch.countDown(); @@ -975,8 +1013,20 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti AtomicReference secondConsumerEvent = new AtomicReference<>(); AtomicBoolean secondUnexpectedEvent = new AtomicBoolean(false); AtomicReference secondErrorRef = new AtomicReference<>(); + AtomicBoolean secondReceivedInitialTask = new AtomicBoolean(false); BiConsumer secondConsumer = (event, agentCard) -> { + // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent + if (!secondReceivedInitialTask.get()) { + if (event instanceof TaskEvent) { + secondReceivedInitialTask.set(true); + return; + } else { + fail("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + } + } + + // Process subsequent events if (event instanceof TaskUpdateEvent tue && tue.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifact) { secondConsumerEvent.set(artifact); secondConsumerLatch.countDown(); @@ -1316,8 +1366,20 @@ public void testNonBlockingWithMultipleMessages() throws Exception { List resubReceivedEvents = new CopyOnWriteArrayList<>(); AtomicBoolean resubUnexpectedEvent = new AtomicBoolean(false); AtomicReference resubErrorRef = new AtomicReference<>(); + AtomicBoolean resubReceivedInitialTask = new AtomicBoolean(false); BiConsumer resubConsumer = (event, agentCard) -> { + // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent + if (!resubReceivedInitialTask.get()) { + if (event instanceof TaskEvent) { + resubReceivedInitialTask.set(true); + return; + } else { + fail("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + } + } + + // Process subsequent events if (event instanceof TaskUpdateEvent tue) { resubReceivedEvents.add(tue.getUpdateEvent()); resubEventLatch.countDown(); @@ -1355,6 +1417,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { AtomicBoolean streamUnexpectedEvent = new AtomicBoolean(false); BiConsumer streamConsumer = (event, agentCard) -> { + // This consumer is for sendMessage() (not resubscribe), so it doesn't get initial TaskEvent if (event instanceof TaskUpdateEvent tue) { streamReceivedEvents.add(tue.getUpdateEvent()); streamEventLatch.countDown(); diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java index 9df23c565..45483f214 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java @@ -31,7 +31,7 @@ public class TestUtilsBean { PushNotificationConfigStore pushNotificationConfigStore; public void saveTask(Task task) { - taskStore.save(task); + taskStore.save(task, false); } public Task getTask(String taskId) { 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 408205aa2..439d97497 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 @@ -242,7 +242,7 @@ public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context); MessageSendParams params = FromProto.messageSendParams(request); Flow.Publisher publisher = getRequestHandler().onMessageSendStream(params, context); - convertToStreamResponse(publisher, responseObserver); + convertToStreamResponse(publisher, responseObserver, context); } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { @@ -264,7 +264,7 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, ServerCallContext context = createCallContext(responseObserver); TaskIdParams params = FromProto.taskIdParams(request); Flow.Publisher publisher = getRequestHandler().onResubscribeToTask(params, context); - convertToStreamResponse(publisher, responseObserver); + convertToStreamResponse(publisher, responseObserver, context); } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { @@ -275,7 +275,8 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, } private void convertToStreamResponse(Flow.Publisher publisher, - StreamObserver responseObserver) { + StreamObserver responseObserver, + ServerCallContext context) { CompletableFuture.runAsync(() -> { publisher.subscribe(new Flow.Subscriber() { private Flow.Subscription subscription; @@ -285,6 +286,18 @@ public void onSubscribe(Flow.Subscription subscription) { this.subscription = subscription; subscription.request(1); + // Detect gRPC client disconnect and call EventConsumer.cancel() directly + // This stops the polling loop without relying on subscription cancellation propagation + Context grpcContext = Context.current(); + grpcContext.addListener(new Context.CancellationListener() { + @Override + public void cancelled(Context ctx) { + LOGGER.fine(() -> "gRPC call cancelled by client, calling EventConsumer.cancel() to stop polling loop"); + context.invokeEventConsumerCancelCallback(); + subscription.cancel(); + } + }, getExecutor()); + // Notify tests that we are subscribed Runnable runnable = streamingSubscribedRunnable; if (runnable != null) { @@ -305,6 +318,8 @@ public void onNext(StreamingEventKind event) { @Override public void onError(Throwable throwable) { + // Cancel upstream to stop EventConsumer when error occurs + subscription.cancel(); if (throwable instanceof A2AError jsonrpcError) { handleError(responseObserver, jsonrpcError); } else { @@ -329,6 +344,9 @@ public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request if (extendedAgentCard != null) { responseObserver.onNext(ToProto.agentCard(extendedAgentCard)); responseObserver.onCompleted(); + } else { + // Extended agent card not configured - return error instead of hanging + handleError(responseObserver, new ExtendedAgentCardNotConfiguredError(null, "Extended agent card not configured", null)); } } catch (Throwable t) { handleInternalError(responseObserver, t); 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 690d69a87..afed1329f 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 @@ -84,7 +84,7 @@ public class GrpcHandlerTest extends AbstractA2ARequestHandlerTest { @Test public void testOnGetTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); GetTaskRequest request = GetTaskRequest.newBuilder() .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); @@ -120,7 +120,7 @@ public void testOnGetTaskNotFound() throws Exception { @Test public void testOnCancelTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorCancel = (context, eventQueue) -> { // We need to cancel the task or the EventConsumer never finds a 'final' event. @@ -151,7 +151,7 @@ public void testOnCancelTaskSuccess() throws Exception { @Test public void testOnCancelTaskNotSupported() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorCancel = (context, eventQueue) -> { throw new UnsupportedOperationError(); @@ -199,7 +199,7 @@ public void testOnMessageNewMessageSuccess() throws Exception { @Test public void testOnMessageNewMessageWithExistingTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getMessage()); }; @@ -281,8 +281,7 @@ public void testPushNotificationsNotSupportedError() throws Exception { @Test public void testOnGetPushNotificationNoPushNotifierConfig() throws Exception { // Create request handler without a push notifier - DefaultRequestHandler requestHandler = - new DefaultRequestHandler(executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true, false); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); @@ -293,8 +292,7 @@ public void testOnGetPushNotificationNoPushNotifierConfig() throws Exception { @Test public void testOnSetPushNotificationNoPushNotifierConfig() throws Exception { // Create request handler without a push notifier - DefaultRequestHandler requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true, false); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); @@ -330,7 +328,7 @@ public void testOnMessageStreamNewMessageExistingTaskSuccess() throws Exception io.a2a.spec.Task task = io.a2a.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) .history(new ArrayList<>()) .build(); - taskStore.save(task); + taskStore.save(task, false); List results = new ArrayList<>(); List errors = new ArrayList<>(); @@ -379,7 +377,7 @@ public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() throws Excep io.a2a.spec.Task task = io.a2a.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) .history(new ArrayList<>()) .build(); - taskStore.save(task); + taskStore.save(task, false); // This is used to send events from a mock List events = List.of( @@ -424,9 +422,14 @@ public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() throws Excep @Test public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - List events = List.of( - AbstractA2ARequestHandlerTest.MINIMAL_TASK, + // Use synchronous executor for push notifications to ensure deterministic ordering + // Without this, async push notifications can execute out of order, causing test flakiness + mainEventBusProcessor.setPushNotificationExecutor(Runnable::run); + + try { + GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); + List events = List.of( + AbstractA2ARequestHandlerTest.MINIMAL_TASK, TaskArtifactUpdateEvent.builder() .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) @@ -493,13 +496,16 @@ public void onCompleted() { Assertions.assertEquals(1, curr.artifacts().get(0).parts().size()); Assertions.assertEquals("text", ((TextPart)curr.artifacts().get(0).parts().get(0)).text()); - curr = httpClient.tasks.get(2); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); - Assertions.assertEquals(io.a2a.spec.TaskState.COMPLETED, curr.status().state()); - Assertions.assertEquals(1, curr.artifacts().size()); - Assertions.assertEquals(1, curr.artifacts().get(0).parts().size()); - Assertions.assertEquals("text", ((TextPart)curr.artifacts().get(0).parts().get(0)).text()); + curr = httpClient.tasks.get(2); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); + Assertions.assertEquals(io.a2a.spec.TaskState.COMPLETED, curr.status().state()); + Assertions.assertEquals(1, curr.artifacts().size()); + Assertions.assertEquals(1, curr.artifacts().get(0).parts().size()); + Assertions.assertEquals("text", ((TextPart)curr.artifacts().get(0).parts().get(0)).text()); + } finally { + mainEventBusProcessor.setPushNotificationExecutor(null); + } } @Test @@ -517,7 +523,7 @@ public void testOnResubscribeNoExistingTaskError() throws Exception { @Test public void testOnResubscribeExistingTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); queueManager.createOrTap(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); agentExecutorExecute = (context, eventQueue) -> { @@ -542,9 +548,18 @@ public void testOnResubscribeExistingTaskSuccess() throws Exception { streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); List result = streamRecorder.getValues(); Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - StreamResponse response = result.get(0); - Assertions.assertTrue(response.hasMessage()); + // Per A2A Protocol Spec 3.1.6, resubscribe sends current Task as first event, + // followed by the Message from the agent executor + Assertions.assertEquals(2, result.size()); + + // ENFORCE that first event is Task + Assertions.assertTrue(result.get(0).hasTask(), + "First event on resubscribe MUST be Task (current state)"); + + // Second event should be Message from agent executor + StreamResponse response = result.get(1); + Assertions.assertTrue(response.hasMessage(), + "Expected Message after initial Task"); assertEquals(GRPC_MESSAGE, response.getMessage()); Assertions.assertNull(streamRecorder.getError()); } @@ -552,7 +567,7 @@ public void testOnResubscribeExistingTaskSuccess() throws Exception { @Test public void testOnResubscribeExistingTaskSuccessMocks() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); queueManager.createOrTap(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); List events = List.of( @@ -627,7 +642,7 @@ public void testOnMessageStreamInternalError() throws Exception { @Test public void testListPushNotificationConfig() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -653,7 +668,7 @@ public void testListPushNotificationConfig() throws Exception { public void testListPushNotificationConfigNotSupported() throws Exception { AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -668,10 +683,9 @@ public void testListPushNotificationConfigNotSupported() throws Exception { @Test public void testListPushNotificationConfigNoPushConfigStore() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -702,7 +716,7 @@ public void testListPushNotificationConfigTaskNotFound() { @Test public void testDeletePushNotificationConfig() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -725,7 +739,7 @@ public void testDeletePushNotificationConfig() throws Exception { public void testDeletePushNotificationConfigNotSupported() throws Exception { AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -741,8 +755,7 @@ public void testDeletePushNotificationConfigNotSupported() throws Exception { @Test public void testDeletePushNotificationConfigNoPushConfigStore() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); DeleteTaskPushNotificationConfigRequest request = DeleteTaskPushNotificationConfigRequest.newBuilder() @@ -1155,7 +1168,7 @@ private StreamRecorder sendMessageRequest(GrpcHandler handl } private StreamRecorder createTaskPushNotificationConfigRequest(GrpcHandler handler, String name) throws Exception { - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); PushNotificationConfig config = PushNotificationConfig.newBuilder() .setUrl("http://example.com") .setId("config456") 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 b43c28029..4dc151626 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 @@ -3,6 +3,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.util.ArrayList; import java.util.Collections; @@ -30,6 +32,8 @@ 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; @@ -37,12 +41,11 @@ 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.ListTasksRequest; -import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.events.EventConsumer; +import io.a2a.server.events.MainEventBusProcessorCallback; import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; import io.a2a.server.requesthandlers.DefaultRequestHandler; import io.a2a.server.tasks.ResultAggregator; @@ -52,16 +55,15 @@ import io.a2a.spec.AgentExtension; import io.a2a.spec.AgentInterface; import io.a2a.spec.Artifact; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.VersionNotSupportedError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.Event; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; +import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.ListTasksParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; +import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; import io.a2a.spec.PushNotificationConfig; @@ -78,6 +80,7 @@ import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; +import io.a2a.spec.VersionNotSupportedError; import mutiny.zero.ZeroPublisher; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; @@ -92,7 +95,7 @@ public class JSONRPCHandlerTest extends AbstractA2ARequestHandlerTest { @Test public void testOnGetTaskSuccess() throws Exception { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); GetTaskRequest request = new GetTaskRequest("1", new TaskQueryParams(MINIMAL_TASK.id())); GetTaskResponse response = handler.onGetTask(request, callContext); assertEquals(request.getId(), response.getId()); @@ -113,7 +116,7 @@ public void testOnGetTaskNotFound() throws Exception { @Test public void testOnCancelTaskSuccess() throws Exception { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorCancel = (context, eventQueue) -> { // We need to cancel the task or the EventConsumer never finds a 'final' event. @@ -138,7 +141,7 @@ public void testOnCancelTaskSuccess() throws Exception { @Test public void testOnCancelTaskNotSupported() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorCancel = (context, eventQueue) -> { throw new UnsupportedOperationError(); @@ -174,42 +177,13 @@ public void testOnMessageNewMessageSuccess() { SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); SendMessageResponse response = handler.onMessageSend(request, callContext); assertNull(response.getError()); - // The Python implementation returns a Task here, but then again they are using hardcoded mocks and - // bypassing the whole EventQueue. - // If we were to send a Task in agentExecutorExecute EventConsumer.consumeAll() would not exit due to - // the Task not having a 'final' state - // - // See testOnMessageNewMessageSuccessMocks() for a test more similar to the Python implementation Assertions.assertSame(message, response.getResult()); } - @Test - public void testOnMessageNewMessageSuccessMocks() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response; - try (MockedConstruction mocked = Mockito.mockConstruction( - EventConsumer.class, - (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromItems(wrapEvent(MINIMAL_TASK))).when(mock).consumeAll(); - Mockito.doCallRealMethod().when(mock).createAgentRunnableDoneCallback(); - })) { - response = handler.onMessageSend(request, callContext); - } - assertNull(response.getError()); - Assertions.assertSame(MINIMAL_TASK, response.getResult()); - } - @Test public void testOnMessageNewMessageWithExistingTaskSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getMessage()); }; @@ -220,38 +194,9 @@ public void testOnMessageNewMessageWithExistingTaskSuccess() { SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); SendMessageResponse response = handler.onMessageSend(request, callContext); assertNull(response.getError()); - // The Python implementation returns a Task here, but then again they are using hardcoded mocks and - // bypassing the whole EventQueue. - // If we were to send a Task in agentExecutorExecute EventConsumer.consumeAll() would not exit due to - // the Task not having a 'final' state - // - // See testOnMessageNewMessageWithExistingTaskSuccessMocks() for a test more similar to the Python implementation Assertions.assertSame(message, response.getResult()); } - @Test - public void testOnMessageNewMessageWithExistingTaskSuccessMocks() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response; - try (MockedConstruction mocked = Mockito.mockConstruction( - EventConsumer.class, - (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromItems(wrapEvent(MINIMAL_TASK))).when(mock).consumeAll(); - })) { - response = handler.onMessageSend(request, callContext); - } - assertNull(response.getError()); - Assertions.assertSame(MINIMAL_TASK, response.getResult()); - - } - @Test public void testOnMessageError() { // See testMessageOnErrorMocks() for a test more similar to the Python implementation, using mocks for @@ -352,9 +297,11 @@ public void onComplete() { @Test public void testOnMessageStreamNewMessageMultipleEventsSuccess() throws InterruptedException { + // Note: Do NOT set callback - DefaultRequestHandler has a permanent callback + // We'll verify persistence by checking TaskStore after streaming completes JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - // Create multiple events to be sent during streaming + // Create multiple events to be sent during streaming Task taskEvent = Task.builder(MINIMAL_TASK) .status(new TaskStatus(TaskState.WORKING)) .build(); @@ -429,8 +376,8 @@ public void onComplete() { } }); - // Wait for all events to be received - Assertions.assertTrue(latch.await(2, TimeUnit.SECONDS), + // Wait for all events to be received (increased timeout for async processing) + assertTrue(latch.await(10, TimeUnit.SECONDS), "Expected to receive 3 events within timeout"); // Assert no error occurred during streaming @@ -456,6 +403,17 @@ public void onComplete() { "Third event should be a TaskStatusUpdateEvent"); assertEquals(MINIMAL_TASK.id(), receivedStatus.taskId()); assertEquals(TaskState.COMPLETED, receivedStatus.status().state()); + + // Verify events were persisted to TaskStore (poll for final state) + for (int i = 0; i < 50; i++) { + Task storedTask = taskStore.get(MINIMAL_TASK.id()); + if (storedTask != null && storedTask.status() != null + && TaskState.COMPLETED.equals(storedTask.status().state())) { + return; // Success - task finalized in TaskStore + } + Thread.sleep(100); + } + fail("Task should have been finalized in TaskStore within timeout"); } @Test @@ -538,7 +496,7 @@ public void testOnMessageStreamNewMessageExistingTaskSuccess() throws Exception Task task = Task.builder(MINIMAL_TASK) .history(new ArrayList<>()) .build(); - taskStore.save(task); + taskStore.save(task, false); Message message = Message.builder(MESSAGE) .taskId(task.id()) @@ -583,7 +541,7 @@ public void onComplete() { }); }); - Assertions.assertTrue(latch.await(1, TimeUnit.SECONDS)); + assertTrue(latch.await(1, TimeUnit.SECONDS)); subscriptionRef.get().cancel(); // The Python implementation has several events emitted since it uses mocks. // @@ -608,7 +566,7 @@ public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() { Task task = Task.builder(MINIMAL_TASK) .history(new ArrayList<>()) .build(); - taskStore.save(task); + taskStore.save(task, false); // This is used to send events from a mock List events = List.of( @@ -682,7 +640,7 @@ public void onComplete() { @Test public void testSetPushNotificationConfigSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); TaskPushNotificationConfig taskPushConfig = new TaskPushNotificationConfig( @@ -704,7 +662,7 @@ public void testSetPushNotificationConfigSuccess() { @Test public void testGetPushNotificationConfigSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -729,112 +687,124 @@ public void testGetPushNotificationConfigSuccess() { @Test public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Exception { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); - - List events = List.of( - MINIMAL_TASK, - TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.COMPLETED)) - .build()); - - agentExecutorExecute = (context, eventQueue) -> { - // Hardcode the events to send here - for (Event event : events) { - eventQueue.enqueueEvent(event); - } - }; - - TaskPushNotificationConfig config = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), "tenant"); - - SetTaskPushNotificationConfigRequest stpnRequest = new SetTaskPushNotificationConfigRequest("1", config); - SetTaskPushNotificationConfigResponse stpnResponse = handler.setPushNotificationConfig(stpnRequest, callContext); - assertNull(stpnResponse.getError()); - - Message msg = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .build(); - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(msg, null, null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - final List results = Collections.synchronizedList(new ArrayList<>()); - final AtomicReference subscriptionRef = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(6); - httpClient.latch = latch; - - Executors.newSingleThreadExecutor().execute(() -> { - response.subscribe(new Flow.Subscriber<>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscriptionRef.set(subscription); - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - System.out.println("-> " + item.getResult()); - results.add(item.getResult()); - System.out.println(results); - subscriptionRef.get().request(1); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscriptionRef.get().cancel(); - } - - @Override - public void onComplete() { - subscriptionRef.get().cancel(); + // Note: Do NOT set callback - DefaultRequestHandler has a permanent callback + + // Use synchronous executor for push notifications to ensure deterministic ordering + // Without this, async push notifications can execute out of order, causing test flakiness + mainEventBusProcessor.setPushNotificationExecutor(Runnable::run); + + try { + JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); + + List events = List.of( + MINIMAL_TASK, + TaskArtifactUpdateEvent.builder() + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) + .artifact(Artifact.builder() + .artifactId("11") + .parts(new TextPart("text")) + .build()) + .build(), + TaskStatusUpdateEvent.builder() + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) + .status(new TaskStatus(TaskState.COMPLETED)) + .build()); + + + agentExecutorExecute = (context, eventQueue) -> { + // Hardcode the events to send here + for (Event event : events) { + eventQueue.enqueueEvent(event); } + }; + + TaskPushNotificationConfig config = new TaskPushNotificationConfig( + MINIMAL_TASK.id(), + PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), "tenant"); + + SetTaskPushNotificationConfigRequest stpnRequest = new SetTaskPushNotificationConfigRequest("1", config); + SetTaskPushNotificationConfigResponse stpnResponse = handler.setPushNotificationConfig(stpnRequest, callContext); + assertNull(stpnResponse.getError()); + + Message msg = Message.builder(MESSAGE) + .taskId(MINIMAL_TASK.id()) + .build(); + SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(msg, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); + + final List results = Collections.synchronizedList(new ArrayList<>()); + final AtomicReference subscriptionRef = new AtomicReference<>(); + final CountDownLatch latch = new CountDownLatch(6); + httpClient.latch = latch; + + Executors.newSingleThreadExecutor().execute(() -> { + response.subscribe(new Flow.Subscriber<>() { + @Override + public void onSubscribe(Flow.Subscription subscription) { + subscriptionRef.set(subscription); + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse item) { + System.out.println("-> " + item.getResult()); + results.add(item.getResult()); + System.out.println(results); + subscriptionRef.get().request(1); + latch.countDown(); + } + + @Override + public void onError(Throwable throwable) { + subscriptionRef.get().cancel(); + } + + @Override + public void onComplete() { + subscriptionRef.get().cancel(); + } + }); }); - }); - Assertions.assertTrue(latch.await(5, TimeUnit.SECONDS)); - subscriptionRef.get().cancel(); - assertEquals(3, results.size()); - assertEquals(3, httpClient.tasks.size()); - - Task curr = httpClient.tasks.get(0); - assertEquals(MINIMAL_TASK.id(), curr.id()); - assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); - assertEquals(MINIMAL_TASK.status().state(), curr.status().state()); - assertEquals(0, curr.artifacts() == null ? 0 : curr.artifacts().size()); - - curr = httpClient.tasks.get(1); - assertEquals(MINIMAL_TASK.id(), curr.id()); - assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); - assertEquals(MINIMAL_TASK.status().state(), curr.status().state()); - assertEquals(1, curr.artifacts().size()); - assertEquals(1, curr.artifacts().get(0).parts().size()); - assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); - - curr = httpClient.tasks.get(2); - assertEquals(MINIMAL_TASK.id(), curr.id()); - assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); - assertEquals(TaskState.COMPLETED, curr.status().state()); - assertEquals(1, curr.artifacts().size()); - assertEquals(1, curr.artifacts().get(0).parts().size()); - assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); + assertTrue(latch.await(5, TimeUnit.SECONDS)); + + subscriptionRef.get().cancel(); + assertEquals(3, results.size()); + assertEquals(3, httpClient.tasks.size()); + + Task curr = httpClient.tasks.get(0); + assertEquals(MINIMAL_TASK.id(), curr.id()); + assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); + assertEquals(MINIMAL_TASK.status().state(), curr.status().state()); + assertEquals(0, curr.artifacts() == null ? 0 : curr.artifacts().size()); + + curr = httpClient.tasks.get(1); + assertEquals(MINIMAL_TASK.id(), curr.id()); + assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); + assertEquals(MINIMAL_TASK.status().state(), curr.status().state()); + assertEquals(1, curr.artifacts().size()); + assertEquals(1, curr.artifacts().get(0).parts().size()); + assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); + + curr = httpClient.tasks.get(2); + assertEquals(MINIMAL_TASK.id(), curr.id()); + assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); + assertEquals(TaskState.COMPLETED, curr.status().state()); + assertEquals(1, curr.artifacts().size()); + assertEquals(1, curr.artifacts().get(0).parts().size()); + assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); + } finally { + mainEventBusProcessor.setPushNotificationExecutor(null); + } } @Test public void testOnResubscribeExistingTaskSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); queueManager.createOrTap(MINIMAL_TASK.id()); agentExecutorExecute = (context, eventQueue) -> { @@ -861,6 +831,7 @@ public void testOnResubscribeExistingTaskSuccess() { CompletableFuture future = new CompletableFuture<>(); List results = new ArrayList<>(); + AtomicBoolean receivedInitialTask = new AtomicBoolean(false); response.subscribe(new Flow.Subscriber<>() { private Flow.Subscription subscription; @@ -873,7 +844,20 @@ public void onSubscribe(Flow.Subscription subscription) { @Override public void onNext(SendStreamingMessageResponse item) { - results.add(item.getResult()); + StreamingEventKind event = item.getResult(); + results.add(event); + + // Per A2A Protocol Spec 3.1.6: ENFORCE that first event is Task + if (!receivedInitialTask.get()) { + assertTrue(event instanceof Task, + "First event on resubscribe MUST be Task (current state), but was: " + event.getClass().getSimpleName()); + receivedInitialTask.set(true); + } else { + // Subsequent events should be the expected type (Message in this case) + assertTrue(event instanceof Message, + "Expected Message after initial Task, but was: " + event.getClass().getSimpleName()); + } + subscription.request(1); } @@ -892,16 +876,15 @@ public void onComplete() { future.join(); - // The Python implementation has several events emitted since it uses mocks. - // - // See testOnMessageStreamNewMessageExistingTaskSuccessMocks() for a test more similar to the Python implementation - assertEquals(1, results.size()); + // Verify we received exactly 2 events and the initial Task was received + assertEquals(2, results.size()); + assertTrue(receivedInitialTask.get(), "Should have received initial Task event"); } @Test public void testOnResubscribeExistingTaskSuccessMocks() throws Exception { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); queueManager.createOrTap(MINIMAL_TASK.id()); List events = List.of( @@ -1060,7 +1043,7 @@ public void onComplete() { if (results.get(0).getError() != null && results.get(0).getError() instanceof InvalidRequestError ire) { assertEquals("Streaming is not supported by the agent", ire.getMessage()); } else { - Assertions.fail("Expected a response containing an error"); + fail("Expected a response containing an error"); } } @@ -1107,7 +1090,7 @@ public void onComplete() { if (results.get(0).getError() != null && results.get(0).getError() instanceof InvalidRequestError ire) { assertEquals("Streaming is not supported by the agent", ire.getMessage()); } else { - Assertions.fail("Expected a response containing an error"); + fail("Expected a response containing an error"); } } @@ -1115,7 +1098,7 @@ public void onComplete() { public void testPushNotificationsNotSupportedError() { AgentCard card = createAgentCard(true, false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); TaskPushNotificationConfig config = new TaskPushNotificationConfig( @@ -1135,12 +1118,11 @@ public void testPushNotificationsNotSupportedError() { @Test public void testOnGetPushNotificationNoPushNotifierConfig() { // Create request handler without a push notifier - DefaultRequestHandler requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); AgentCard card = createAgentCard(false, true, false); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); GetTaskPushNotificationConfigRequest request = new GetTaskPushNotificationConfigRequest("id", new GetTaskPushNotificationConfigParams(MINIMAL_TASK.id())); @@ -1154,12 +1136,11 @@ public void testOnGetPushNotificationNoPushNotifierConfig() { @Test public void testOnSetPushNotificationNoPushNotifierConfig() { // Create request handler without a push notifier - DefaultRequestHandler requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); AgentCard card = createAgentCard(false, true, false); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); TaskPushNotificationConfig config = new TaskPushNotificationConfig( @@ -1246,12 +1227,11 @@ public void testDefaultRequestHandlerWithCustomComponents() { @Test public void testOnMessageSendErrorHandling() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); AgentCard card = createAgentCard(false, true, false); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); Message message = Message.builder(MESSAGE) .taskId(MINIMAL_TASK.id()) @@ -1280,7 +1260,7 @@ public void testOnMessageSendErrorHandling() { @Test public void testOnMessageSendTaskIdMismatch() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = ((context, eventQueue) -> { eventQueue.enqueueEvent(MINIMAL_TASK); @@ -1293,16 +1273,17 @@ public void testOnMessageSendTaskIdMismatch() { } @Test - public void testOnMessageStreamTaskIdMismatch() { + public void testOnMessageStreamTaskIdMismatch() throws InterruptedException { + // Note: Do NOT set callback - DefaultRequestHandler has a permanent callback JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = ((context, eventQueue) -> { - eventQueue.enqueueEvent(MINIMAL_TASK); - }); + agentExecutorExecute = ((context, eventQueue) -> { + eventQueue.enqueueEvent(MINIMAL_TASK); + }); - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, null, null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); + SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); CompletableFuture future = new CompletableFuture<>(); List results = new ArrayList<>(); @@ -1347,7 +1328,7 @@ public void onComplete() { @Test public void testListPushNotificationConfig() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -1378,7 +1359,7 @@ public void testListPushNotificationConfig() { public void testListPushNotificationConfigNotSupported() { AgentCard card = createAgentCard(true, false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -1404,10 +1385,9 @@ public void testListPushNotificationConfigNotSupported() { @Test public void testListPushNotificationConfigNoPushConfigStore() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -1442,7 +1422,7 @@ public void testListPushNotificationConfigTaskNotFound() { @Test public void testDeletePushNotificationConfig() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -1470,7 +1450,7 @@ public void testDeletePushNotificationConfig() { public void testDeletePushNotificationConfigNotSupported() { AgentCard card = createAgentCard(true, false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -1496,10 +1476,10 @@ public void testDeletePushNotificationConfigNotSupported() { @Test public void testDeletePushNotificationConfigNoPushConfigStore() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, null, null, internalExecutor); + DefaultRequestHandler requestHandler = + DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; @@ -1593,7 +1573,7 @@ public void onComplete() { }); // The main thread should not be blocked - we should be able to continue immediately - Assertions.assertTrue(streamStarted.await(100, TimeUnit.MILLISECONDS), + assertTrue(streamStarted.await(100, TimeUnit.MILLISECONDS), "Streaming subscription should start quickly without blocking main thread"); // This proves the main thread is not blocked - we can do other work @@ -1603,11 +1583,11 @@ public void onComplete() { mainThreadBlocked.set(false); // If we get here, main thread was not blocked // Wait for the actual event processing to complete - Assertions.assertTrue(eventProcessed.await(2, TimeUnit.SECONDS), + assertTrue(eventProcessed.await(2, TimeUnit.SECONDS), "Event should be processed within reasonable time"); // Verify we received the event and main thread was not blocked - Assertions.assertTrue(eventReceived.get(), "Should have received streaming event"); + assertTrue(eventReceived.get(), "Should have received streaming event"); Assertions.assertFalse(mainThreadBlocked.get(), "Main thread should not have been blocked"); } @@ -1646,7 +1626,7 @@ public void testExtensionSupportRequiredErrorOnMessageSend() { SendMessageResponse response = handler.onMessageSend(request, callContext); assertInstanceOf(ExtensionSupportRequiredError.class, response.getError()); - Assertions.assertTrue(response.getError().getMessage().contains("https://example.com/test-extension")); + assertTrue(response.getError().getMessage().contains("https://example.com/test-extension")); assertNull(response.getResult()); } @@ -1715,7 +1695,7 @@ public void onComplete() { assertEquals(1, results.size()); assertInstanceOf(ExtensionSupportRequiredError.class, results.get(0).getError()); - Assertions.assertTrue(results.get(0).getError().getMessage().contains("https://example.com/streaming-extension")); + assertTrue(results.get(0).getError().getMessage().contains("https://example.com/streaming-extension")); assertNull(results.get(0).getResult()); } @@ -1805,7 +1785,7 @@ public void testVersionNotSupportedErrorOnMessageSend() { SendMessageResponse response = handler.onMessageSend(request, contextWithVersion); assertInstanceOf(VersionNotSupportedError.class, response.getError()); - Assertions.assertTrue(response.getError().getMessage().contains("2.0")); + assertTrue(response.getError().getMessage().contains("2.0")); assertNull(response.getResult()); } @@ -1876,12 +1856,12 @@ public void onComplete() { }); // Wait for async processing - Assertions.assertTrue(latch.await(2, TimeUnit.SECONDS), "Expected to receive error event within timeout"); + assertTrue(latch.await(2, TimeUnit.SECONDS), "Expected to receive error event within timeout"); assertEquals(1, results.size()); SendStreamingMessageResponse result = results.get(0); assertInstanceOf(VersionNotSupportedError.class, result.getError()); - Assertions.assertTrue(result.getError().getMessage().contains("2.0")); + assertTrue(result.getError().getMessage().contains("2.0")); assertNull(result.getResult()); } 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 3ffb56c5f..3273d6119 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 @@ -399,32 +399,46 @@ private Flow.Publisher convertToSendStreamingMessageResponse( Flow.Publisher publisher) { // We can't use the normal convertingProcessor since that propagates any errors as an error handled // via Subscriber.onError() rather than as part of the SendStreamingResponse payload + log.log(Level.FINE, "REST: convertToSendStreamingMessageResponse called, creating ZeroPublisher"); return ZeroPublisher.create(createTubeConfig(), tube -> { + log.log(Level.FINE, "REST: ZeroPublisher tube created, starting CompletableFuture.runAsync"); CompletableFuture.runAsync(() -> { + log.log(Level.FINE, "REST: Inside CompletableFuture, subscribing to EventKind publisher"); publisher.subscribe(new Flow.Subscriber() { Flow.@Nullable Subscription subscription; @Override public void onSubscribe(Flow.Subscription subscription) { + log.log(Level.FINE, "REST: onSubscribe called, storing subscription and requesting first event"); this.subscription = subscription; subscription.request(1); } @Override public void onNext(StreamingEventKind item) { + log.log(Level.FINE, "REST: onNext called with event: {0}", item.getClass().getSimpleName()); try { String payload = JsonFormat.printer().omittingInsignificantWhitespace().print(ProtoUtils.ToProto.taskOrMessageStream(item)); + log.log(Level.FINE, "REST: Converted to JSON, sending via tube: {0}", payload.substring(0, Math.min(100, payload.length()))); tube.send(payload); + log.log(Level.FINE, "REST: tube.send() completed, requesting next event from EventConsumer"); + // Request next event from EventConsumer (Chain 1: EventConsumer → RestHandler) + // This is safe because ZeroPublisher buffers items + // Chain 2 (ZeroPublisher → MultiSseSupport) controls actual delivery via request(1) in onWriteDone() if (subscription != null) { subscription.request(1); + } else { + log.log(Level.WARNING, "REST: subscription is null in onNext!"); } } catch (InvalidProtocolBufferException ex) { + log.log(Level.SEVERE, "REST: JSON conversion failed", ex); onError(ex); } } @Override public void onError(Throwable throwable) { + log.log(Level.SEVERE, "REST: onError called", throwable); if (throwable instanceof A2AError jsonrpcError) { tube.send(new HTTPRestErrorResponse(jsonrpcError).toJson()); } else { @@ -435,6 +449,7 @@ public void onError(Throwable throwable) { @Override public void onComplete() { + log.log(Level.FINE, "REST: onComplete called, calling tube.complete()"); tube.complete(); } }); 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 7d930415b..db3ff97aa 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 @@ -30,7 +30,7 @@ public class RestHandlerTest extends AbstractA2ARequestHandlerTest { @Test public void testGetTaskSuccess() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); RestHandler.HTTPRestResponse response = handler.getTask(MINIMAL_TASK.id(), 0, "", callContext); @@ -59,7 +59,7 @@ public void testGetTaskNotFound() { @Test public void testListTasksStatusWireString() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); RestHandler.HTTPRestResponse response = handler.listTasks(null, "submitted", null, null, null, null, null, "", callContext); @@ -162,7 +162,7 @@ public void testSendMessageEmptyBody() { @Test public void testCancelTaskSuccess() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); agentExecutorCancel = (context, eventQueue) -> { // We need to cancel the task or the EventConsumer never finds a 'final' event. @@ -246,7 +246,7 @@ public void testSendStreamingMessageNotSupported() { @Test public void testPushNotificationConfigSuccess() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); String requestBody = """ { @@ -293,7 +293,7 @@ public void testPushNotificationConfigNotSupported() { @Test public void testGetPushNotificationConfig() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); // First, create a push notification config String createRequestBody = """ @@ -322,7 +322,7 @@ public void testGetPushNotificationConfig() { @Test public void testDeletePushNotificationConfig() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); RestHandler.HTTPRestResponse response = handler.deleteTaskPushNotificationConfiguration(MINIMAL_TASK.id(), "default-config-id", "", callContext); Assertions.assertEquals(204, response.getStatusCode()); } @@ -330,7 +330,7 @@ public void testDeletePushNotificationConfig() { @Test public void testListPushNotificationConfigs() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); RestHandler.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(MINIMAL_TASK.id(), 0, "", "", callContext); @@ -894,7 +894,7 @@ public void testListTasksNegativeTimestampReturns422() { @Test public void testListTasksUnixMillisecondsTimestamp() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); // Unix milliseconds timestamp should be accepted String timestampMillis = String.valueOf(System.currentTimeMillis() - 10000); @@ -909,7 +909,7 @@ public void testListTasksUnixMillisecondsTimestamp() { @Test public void testListTasksProtobufEnumStatus() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); // Protobuf enum format (TASK_STATE_SUBMITTED) should be accepted RestHandler.HTTPRestResponse response = handler.listTasks(null, "TASK_STATE_SUBMITTED", null, null, @@ -923,7 +923,7 @@ public void testListTasksProtobufEnumStatus() { @Test public void testListTasksEnumConstantStatus() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK); + taskStore.save(MINIMAL_TASK, false); // Enum constant format (SUBMITTED) should be accepted RestHandler.HTTPRestResponse response = handler.listTasks(null, "SUBMITTED", null, null, From 1c2af659792d85026768132449b9559292beb243 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 5 Feb 2026 11:21:25 +0000 Subject: [PATCH 010/192] feat: Replace quarkus-rest(-client)-jackson with quarkus-rest(-client) (#581) We no longer use Jackson --- boms/reference/src/it/reference-usage-test/pom.xml | 4 ++-- examples/helloworld/server/pom.xml | 2 +- extras/push-notification-config-store-database-jpa/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- tck/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/boms/reference/src/it/reference-usage-test/pom.xml b/boms/reference/src/it/reference-usage-test/pom.xml index 2e000a8a8..5e7a500f3 100644 --- a/boms/reference/src/it/reference-usage-test/pom.xml +++ b/boms/reference/src/it/reference-usage-test/pom.xml @@ -103,11 +103,11 @@ io.quarkus - quarkus-resteasy-jackson + quarkus-grpc io.quarkus - quarkus-grpc + quarkus-rest diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 4b0ea1564..699adf4d4 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -26,7 +26,7 @@ io.quarkus - quarkus-resteasy-jackson + quarkus-resteasy provided diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index b944295b3..4973fd8e8 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -55,7 +55,7 @@ io.quarkus - quarkus-rest-client-jackson + quarkus-rest-client test diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index b98aa7bf9..ff99cf514 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -59,7 +59,7 @@ io.quarkus - quarkus-rest-client-jackson + quarkus-rest-client test diff --git a/reference/common/pom.xml b/reference/common/pom.xml index e05266922..b9e8e57a7 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -60,7 +60,7 @@ io.quarkus - quarkus-rest-client-jackson + quarkus-rest-client test diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 37252458e..c23c817fd 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -74,7 +74,7 @@ io.quarkus - quarkus-rest-client-jackson + quarkus-rest-client test diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index 318c85e6c..796ff88fe 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -84,7 +84,7 @@ io.quarkus - quarkus-rest-client-jackson + quarkus-rest-client test diff --git a/tck/pom.xml b/tck/pom.xml index 39c289c72..7b2db1b81 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -30,7 +30,7 @@ io.quarkus - quarkus-rest-jackson + quarkus-rest provided From 168ff2dac4209c177e6f026f47b06c549c9d18d5 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 5 Feb 2026 12:21:45 +0100 Subject: [PATCH 011/192] refactor: extract shared SSE event handling into SPI module (#624) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create client-transport-spi module with AbstractSSEEventListener to eliminate code duplication between jsonrpc and rest transport implementations. - Add AbstractSSEEventListener with common event/error handling logic - Refactor jsonrpc and rest SSEEventListener to extend base class - Add comprehensive test coverage for shared functionality Fixes #623 🦕 Signed-off-by: Emmanuel Hugonnet --- .gitignore | 1 + .../jsonrpc/sse/SSEEventListener.java | 66 ++-- .../jsonrpc/sse/SSEEventListenerTest.java | 15 + .../client/transport/rest/RestTransport.java | 6 +- .../rest/sse/RestSSEEventListener.java | 87 ----- .../transport/rest/sse/SSEEventListener.java | 73 ++++ .../rest/sse/SSEEventListenerTest.java | 344 ++++++++++++++++++ .../spi/sse/AbstractSSEEventListener.java | 120 ++++++ .../transport/spi/sse/package-info.java | 5 + .../spi/sse/SSEEventListenerTest.java | 295 +++++++++++++++ 10 files changed, 879 insertions(+), 133 deletions(-) delete mode 100644 client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java create mode 100644 client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java create mode 100644 client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java create mode 100644 client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java create mode 100644 client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java create mode 100644 client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java diff --git a/.gitignore b/.gitignore index c95331d77..143f602c6 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,5 @@ nbactions.xml # Private Claude config .claude/ .serena/ +.bob/ claudedocs 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 3a24f5145..2c61d082e 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 @@ -4,42 +4,32 @@ import java.util.function.Consumer; import java.util.logging.Logger; +import io.a2a.client.transport.spi.sse.AbstractSSEEventListener; 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.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; import org.jspecify.annotations.Nullable; -public class SSEEventListener { +/** + * JSON-RPC transport implementation of SSE event listener. + * Handles parsing of JSON-RPC formatted messages from SSE streams. + */ +public class SSEEventListener extends AbstractSSEEventListener { private static final Logger log = Logger.getLogger(SSEEventListener.class.getName()); - private final Consumer eventHandler; - private final @Nullable - Consumer errorHandler; private volatile boolean completed = false; public SSEEventListener(Consumer eventHandler, @Nullable Consumer errorHandler) { - this.eventHandler = eventHandler; - this.errorHandler = errorHandler; + super(eventHandler, errorHandler); } + @Override public void onMessage(String message, @Nullable Future completableFuture) { - handleMessage(message, completableFuture); - } - - public void onError(Throwable throwable, @Nullable Future future) { - if (errorHandler != null) { - errorHandler.accept(throwable); - } - if (future != null) { - future.cancel(true); // close SSE channel - } + parseAndHandleMessage(message, completableFuture); } public void onComplete() { @@ -52,40 +42,30 @@ public void onComplete() { // Signal normal stream completion (null error means successful completion) log.fine("SSEEventListener.onComplete() called - signaling successful stream completion"); - if (errorHandler != null) { + if (getErrorHandler() != null) { log.fine("Calling errorHandler.accept(null) to signal successful completion"); - errorHandler.accept(null); + getErrorHandler().accept(null); } else { log.warning("errorHandler is null, cannot signal completion"); } } - private void handleMessage(String message, @Nullable Future future) { + /** + * Parses a JSON-RPC message and delegates to the base class for event handling. + * + * @param message The raw JSON-RPC message string + * @param future Optional future for controlling the SSE connection + */ + private void parseAndHandleMessage(String message, @Nullable Future future) { try { StreamResponse response = JSONRPCUtils.parseResponseEvent(message); - StreamingEventKind event = ProtoUtils.FromProto.streamingEventKind(response); - eventHandler.accept(event); - - // Client-side auto-close on final events to prevent connection leaks - // Handles both TaskStatusUpdateEvent and Task objects with final states - // This covers late subscriptions to completed tasks and ensures no connection leaks - boolean shouldClose = false; - if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) { - shouldClose = true; - } else if (event instanceof Task task) { - TaskState state = task.status().state(); - if (state.isFinal()) { - shouldClose = true; - } - } - - if (shouldClose && future != null) { - future.cancel(true); // close SSE channel - } + + // Delegate to base class for common event handling and auto-close logic + handleEvent(event, future); } catch (A2AError error) { - if (errorHandler != null) { - errorHandler.accept(error); + if (getErrorHandler() != null) { + getErrorHandler().accept(error); } } catch (JsonProcessingException e) { throw new RuntimeException(e); 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 17f805312..0817b753f 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 @@ -198,7 +198,22 @@ public void testFinalTaskStatusUpdateEventCancels() { error -> {} ); + // Parse the message event JSON + String eventData = JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT_FINAL.substring( + JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT_FINAL.indexOf("{")); + + // Call onMessage with a cancellable future + CancelCapturingFuture future = new CancelCapturingFuture(); + listener.onMessage(eventData, future); + // Verify the event was received and processed + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); + TaskStatusUpdateEvent received = (TaskStatusUpdateEvent) receivedEvent.get(); + assertTrue(received.isFinal()); + + // Verify the future was cancelled (auto-close on final event) + assertTrue(future.cancelHandlerCalled); } @Test 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 6513086da..ae01e0f3f 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 @@ -31,7 +31,7 @@ import io.a2a.client.http.A2AHttpClient; import io.a2a.client.http.A2AHttpClientFactory; import io.a2a.client.http.A2AHttpResponse; -import io.a2a.client.transport.rest.sse.RestSSEEventListener; +import io.a2a.client.transport.rest.sse.SSEEventListener; import io.a2a.client.transport.spi.ClientTransport; import io.a2a.client.transport.spi.interceptors.ClientCallContext; import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; @@ -110,7 +110,7 @@ public void sendMessageStreaming(MessageSendParams messageSendParams, Consumer> ref = new AtomicReference<>(); - RestSSEEventListener sseEventListener = new RestSSEEventListener(eventConsumer, errorConsumer); + SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); try { A2AHttpClient.PostBuilder postBuilder = createPostBuilder(Utils.buildBaseUrl(agentInterface, messageSendParams.tenant()) + "/message:stream", payloadAndHeaders); ref.set(postBuilder.postAsyncSSE( @@ -395,7 +395,7 @@ public void resubscribe(TaskIdParams request, Consumer event PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, builder, agentCard, context); AtomicReference> ref = new AtomicReference<>(); - RestSSEEventListener sseEventListener = new RestSSEEventListener(eventConsumer, errorConsumer); + SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); try { String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s:subscribe", request.id()); A2AHttpClient.PostBuilder postBuilder = createPostBuilder(url, payloadAndHeaders); diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java deleted file mode 100644 index 85e604da3..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/RestSSEEventListener.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.a2a.client.transport.rest.sse; - -import java.util.concurrent.Future; -import java.util.function.Consumer; -import java.util.logging.Logger; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.util.JsonFormat; -import io.a2a.client.transport.rest.RestErrorMapper; -import io.a2a.grpc.StreamResponse; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.jspecify.annotations.Nullable; - -public class RestSSEEventListener { - - private static final Logger log = Logger.getLogger(RestSSEEventListener.class.getName()); - private final Consumer eventHandler; - private final Consumer errorHandler; - - public RestSSEEventListener(Consumer eventHandler, - Consumer errorHandler) { - this.eventHandler = eventHandler; - this.errorHandler = errorHandler; - } - - public void onMessage(String message, @Nullable Future completableFuture) { - try { - log.fine("Streaming message received: " + message); - io.a2a.grpc.StreamResponse.Builder builder = io.a2a.grpc.StreamResponse.newBuilder(); - JsonFormat.parser().merge(message, builder); - handleMessage(builder.build(), completableFuture); - } catch (InvalidProtocolBufferException e) { - errorHandler.accept(RestErrorMapper.mapRestError(message, 500)); - } - } - - public void onError(Throwable throwable, @Nullable Future future) { - if (errorHandler != null) { - errorHandler.accept(throwable); - } - if (future != null) { - future.cancel(true); // close SSE channel - } - } - - private void handleMessage(StreamResponse response, @Nullable Future future) { - StreamingEventKind event; - switch (response.getPayloadCase()) { - case MESSAGE -> - event = ProtoUtils.FromProto.message(response.getMessage()); - case TASK -> - event = ProtoUtils.FromProto.task(response.getTask()); - case STATUS_UPDATE -> - event = ProtoUtils.FromProto.taskStatusUpdateEvent(response.getStatusUpdate()); - case ARTIFACT_UPDATE -> - event = ProtoUtils.FromProto.taskArtifactUpdateEvent(response.getArtifactUpdate()); - default -> { - log.warning("Invalid stream response " + response.getPayloadCase()); - errorHandler.accept(new IllegalStateException("Invalid stream response from server: " + response.getPayloadCase())); - return; - } - } - eventHandler.accept(event); - - // Client-side auto-close on final events to prevent connection leaks - // Handles both TaskStatusUpdateEvent and Task objects with final states - // This covers late subscriptions to completed tasks and ensures no connection leaks - boolean shouldClose = false; - if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) { - shouldClose = true; - } else if (event instanceof Task task) { - TaskState state = task.status().state(); - if (state.isFinal()) { - shouldClose = true; - } - } - - if (shouldClose && future != null) { - future.cancel(true); // close SSE channel - } - } - -} diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java new file mode 100644 index 000000000..2c9167b63 --- /dev/null +++ b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java @@ -0,0 +1,73 @@ +package io.a2a.client.transport.rest.sse; + +import java.util.concurrent.Future; +import java.util.function.Consumer; +import java.util.logging.Logger; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; +import io.a2a.client.transport.spi.sse.AbstractSSEEventListener; +import io.a2a.client.transport.rest.RestErrorMapper; +import io.a2a.grpc.StreamResponse; +import io.a2a.grpc.utils.ProtoUtils; +import io.a2a.spec.StreamingEventKind; +import org.jspecify.annotations.Nullable; + +/** + * REST transport implementation of SSE event listener. + * Handles parsing of JSON-formatted protobuf messages from REST SSE streams. + */ +public class SSEEventListener extends AbstractSSEEventListener { + + private static final Logger log = Logger.getLogger(SSEEventListener.class.getName()); + + public SSEEventListener(Consumer eventHandler, + @Nullable Consumer errorHandler) { + super(eventHandler, errorHandler); + } + + @Override + public void onMessage(String message, @Nullable Future completableFuture) { + try { + log.fine("Streaming message received: " + message); + io.a2a.grpc.StreamResponse.Builder builder = io.a2a.grpc.StreamResponse.newBuilder(); + JsonFormat.parser().merge(message, builder); + parseAndHandleMessage(builder.build(), completableFuture); + } catch (InvalidProtocolBufferException e) { + if (getErrorHandler() != null) { + getErrorHandler().accept(RestErrorMapper.mapRestError(message, 500)); + } + } + } + + /** + * Parses a StreamResponse protobuf message and delegates to the base class for event handling. + * + * @param response The parsed StreamResponse + * @param future Optional future for controlling the SSE connection + */ + private void parseAndHandleMessage(StreamResponse response, @Nullable Future future) { + StreamingEventKind event; + switch (response.getPayloadCase()) { + case MESSAGE -> + event = ProtoUtils.FromProto.message(response.getMessage()); + case TASK -> + event = ProtoUtils.FromProto.task(response.getTask()); + case STATUS_UPDATE -> + event = ProtoUtils.FromProto.taskStatusUpdateEvent(response.getStatusUpdate()); + case ARTIFACT_UPDATE -> + event = ProtoUtils.FromProto.taskArtifactUpdateEvent(response.getArtifactUpdate()); + default -> { + log.warning("Invalid stream response " + response.getPayloadCase()); + if (getErrorHandler() != null) { + getErrorHandler().accept(new IllegalStateException("Invalid stream response from server: " + response.getPayloadCase())); + } + return; + } + } + + // Delegate to base class for common event handling and auto-close logic + handleEvent(event, future); + } + +} diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java new file mode 100644 index 000000000..1a2bd7f26 --- /dev/null +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java @@ -0,0 +1,344 @@ +package io.a2a.client.transport.rest.sse; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import io.a2a.spec.Message; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.Task; +import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatusUpdateEvent; +import io.a2a.spec.TextPart; +import org.junit.jupiter.api.Test; + +/** + * Tests for REST transport SSEEventListener. + * Tests JSON parsing of protobuf messages and event handling. + */ +public class SSEEventListenerTest { + + /** + * Mock Future implementation that captures cancel calls. + */ + private static class CancelCapturingFuture implements Future { + private boolean cancelHandlerCalled = false; + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + cancelHandlerCalled = true; + return true; + } + + @Override + public boolean isCancelled() { + return cancelHandlerCalled; + } + + @Override + public boolean isDone() { + return false; + } + + @Override + public Void get() { + return null; + } + + @Override + public Void get(long timeout, TimeUnit unit) { + return null; + } + + public boolean wasCancelled() { + return cancelHandlerCalled; + } + } + + @Test + public void testOnMessageWithTaskResult() { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> receivedEvent.set(event), + error -> {} + ); + + // JSON format from REST SSE stream (protobuf as JSON) + String jsonMessage = """ + { + "task": { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "TASK_STATE_WORKING" + } + } + } + """; + + // Call the onMessage method + listener.onMessage(jsonMessage, null); + + // Verify the event was processed correctly + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof Task); + Task task = (Task) receivedEvent.get(); + assertEquals("task-123", task.id()); + assertEquals("context-456", task.contextId()); + assertEquals(TaskState.WORKING, task.status().state()); + } + + @Test + public void testOnMessageWithMessageResult() { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> receivedEvent.set(event), + error -> {} + ); + + // JSON format from REST SSE stream + String jsonMessage = """ + { + "message": { + "role": "ROLE_AGENT", + "messageId": "msg-123", + "contextId": "context-456", + "parts": [ + { + "text": "Hello, world!" + } + ] + } + } + """; + + // Call onMessage method + listener.onMessage(jsonMessage, null); + + // Verify the event was processed correctly + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof Message); + Message message = (Message) receivedEvent.get(); + assertEquals(Message.Role.AGENT, message.role()); + assertEquals("msg-123", message.messageId()); + assertEquals("context-456", message.contextId()); + assertEquals(1, message.parts().size()); + assertTrue(message.parts().get(0) instanceof TextPart); + assertEquals("Hello, world!", ((TextPart) message.parts().get(0)).text()); + } + + @Test + public void testOnMessageWithStatusUpdateEvent() { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> receivedEvent.set(event), + error -> {} + ); + + // JSON format from REST SSE stream + String jsonMessage = """ + { + "statusUpdate": { + "taskId": "1", + "contextId": "2", + "status": { + "state": "TASK_STATE_SUBMITTED" + }, + "final": false + } + } + """; + + // Call onMessage method + listener.onMessage(jsonMessage, null); + + // Verify the event was processed correctly + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); + TaskStatusUpdateEvent taskStatusUpdateEvent = (TaskStatusUpdateEvent) receivedEvent.get(); + assertEquals("1", taskStatusUpdateEvent.taskId()); + assertEquals("2", taskStatusUpdateEvent.contextId()); + assertEquals(TaskState.SUBMITTED, taskStatusUpdateEvent.status().state()); + assertEquals(false, taskStatusUpdateEvent.isFinal()); + } + + @Test + public void testOnMessageWithFinalStatusUpdateEventCancels() { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> receivedEvent.set(event), + error -> {} + ); + + // JSON format from REST SSE stream with final status + String jsonMessage = """ + { + "statusUpdate": { + "taskId": "1", + "contextId": "2", + "status": { + "state": "TASK_STATE_COMPLETED" + }, + "final": true + } + } + """; + + // Call onMessage with a cancellable future + CancelCapturingFuture future = new CancelCapturingFuture(); + listener.onMessage(jsonMessage, future); + + // Verify the event was received and processed + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); + TaskStatusUpdateEvent received = (TaskStatusUpdateEvent) receivedEvent.get(); + assertTrue(received.isFinal()); + assertEquals(TaskState.COMPLETED, received.status().state()); + + // Verify the future was cancelled (auto-close on final event) + assertTrue(future.wasCancelled()); + } + + @Test + public void testOnMessageWithCompletedTaskCancels() { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> receivedEvent.set(event), + error -> {} + ); + + // JSON format from REST SSE stream with completed task + String jsonMessage = """ + { + "task": { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "TASK_STATE_COMPLETED" + } + } + } + """; + + // Call onMessage with a cancellable future + CancelCapturingFuture future = new CancelCapturingFuture(); + listener.onMessage(jsonMessage, future); + + // Verify the event was received + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof Task); + Task task = (Task) receivedEvent.get(); + assertEquals(TaskState.COMPLETED, task.status().state()); + + // Verify the future was cancelled (auto-close on final task state) + assertTrue(future.wasCancelled()); + } + + @Test + public void testOnMessageWithInvalidJsonCallsErrorHandler() { + // Set up error handler + AtomicReference receivedError = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> {}, + error -> receivedError.set(error) + ); + + // Invalid JSON message + String invalidJson = "{ invalid json }"; + + // Call onMessage + listener.onMessage(invalidJson, null); + + // Verify error handler was called + assertNotNull(receivedError.get()); + } + + @Test + public void testOnMessageWithInvalidPayloadCaseCallsErrorHandler() { + // Set up error handler + AtomicReference receivedError = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> {}, + error -> receivedError.set(error) + ); + + // JSON with no recognized payload type (empty object) + String jsonMessage = "{}"; + + // Call onMessage + listener.onMessage(jsonMessage, null); + + // Verify error handler was called + assertNotNull(receivedError.get()); + assertTrue(receivedError.get() instanceof IllegalStateException); + assertTrue(receivedError.get().getMessage().contains("Invalid stream response")); + } + + @Test + public void testOnErrorCallsErrorHandler() { + // Set up error handler + AtomicReference receivedError = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> {}, + error -> receivedError.set(error) + ); + + // Create a test error + IllegalStateException testError = new IllegalStateException("Test error"); + + // Call onError + listener.onError(testError, null); + + // Verify error handler was called + assertNotNull(receivedError.get()); + assertEquals(testError, receivedError.get()); + } + + @Test + public void testOnErrorCancelsFuture() { + // Set up error handler + AtomicBoolean errorHandlerCalled = new AtomicBoolean(false); + SSEEventListener listener = new SSEEventListener( + event -> {}, + error -> errorHandlerCalled.set(true) + ); + + // Create a cancel-capturing future + CancelCapturingFuture future = new CancelCapturingFuture(); + + // Call onError with a future + listener.onError(new RuntimeException("Test error"), future); + + // Verify both error handler was called and future was cancelled + assertTrue(errorHandlerCalled.get()); + assertTrue(future.wasCancelled()); + } + + @Test + public void testOnMessageWithNullErrorHandler() { + // Set up with null error handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener listener = new SSEEventListener( + event -> receivedEvent.set(event), + null // Null error handler + ); + + // Invalid JSON message + String invalidJson = "{ invalid json }"; + + // Call onMessage - should not throw even with null error handler + listener.onMessage(invalidJson, null); + + // No exception thrown means test passes + } +} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java new file mode 100644 index 000000000..b6051bf41 --- /dev/null +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java @@ -0,0 +1,120 @@ +package io.a2a.client.transport.spi.sse; + +import java.util.concurrent.Future; +import java.util.function.Consumer; +import java.util.logging.Logger; + +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.Task; +import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatusUpdateEvent; +import org.jspecify.annotations.Nullable; + +/** + * Abstract base class for SSE event listeners that provides common functionality + * for handling Server-Sent Events across different transport implementations. + *

    + * This class implements the Template Method pattern, where subclasses provide + * the specific message parsing logic while the base class handles common concerns + * like error handling and connection lifecycle management. + */ +public abstract class AbstractSSEEventListener { + + private static final Logger log = Logger.getLogger(AbstractSSEEventListener.class.getName()); + + private final Consumer eventHandler; + private final @Nullable Consumer errorHandler; + + /** + * Creates a new SSE event listener with the specified handlers. + * + * @param eventHandler Handler for processing streaming events + * @param errorHandler Optional handler for processing errors + */ + protected AbstractSSEEventListener(Consumer eventHandler, + @Nullable Consumer errorHandler) { + this.eventHandler = eventHandler; + this.errorHandler = errorHandler; + } + + /** + * Gets the event handler for processing streaming events. + * + * @return The event handler + */ + protected Consumer getEventHandler() { + return eventHandler; + } + + /** + * Gets the error handler for processing errors. + * + * @return The error handler, or null if not set + */ + protected @Nullable Consumer getErrorHandler() { + return errorHandler; + } + + /** + * Handles incoming SSE messages. Subclasses must implement the specific + * parsing logic for their transport protocol. + * + * @param message The raw message string from the SSE stream + * @param completableFuture Optional future for controlling the SSE connection + */ + public abstract void onMessage(String message, @Nullable Future completableFuture); + + /** + * Handles errors that occur during SSE streaming. + * This method is identical across all implementations. + * + * @param throwable The error that occurred + * @param future Optional future for closing the SSE connection + */ + public void onError(Throwable throwable, @Nullable Future future) { + if (errorHandler != null) { + errorHandler.accept(throwable); + } + if (future != null) { + future.cancel(true); // close SSE channel + } + } + + /** + * Processes a parsed streaming event and handles auto-close logic for final events. + * This method encapsulates the common logic for handling events and determining + * when to close the SSE connection. + * + * @param event The parsed streaming event + * @param future Optional future for closing the SSE connection + */ + protected void handleEvent(StreamingEventKind event, @Nullable Future future) { + eventHandler.accept(event); + + // Client-side auto-close on final events to prevent connection leaks + // Handles both TaskStatusUpdateEvent and Task objects with final states + // This covers late subscriptions to completed tasks and ensures no connection leaks + if (shouldAutoClose(event) && future != null) { + log.fine("Auto-closing SSE connection for final event: " + event.getClass().getSimpleName()); + future.cancel(true); // close SSE channel + } + } + + /** + * Determines if the SSE connection should be automatically closed based on the event type. + * The connection is closed when receiving final task states to prevent connection leaks. + * + * @param event The streaming event to check + * @return true if the connection should be closed, false otherwise + */ + protected boolean shouldAutoClose(StreamingEventKind event) { + if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) { + return true; + } + if (event instanceof Task task) { + TaskState state = task.status().state(); + return state.isFinal(); + } + return false; + } +} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java new file mode 100644 index 000000000..1083bc32e --- /dev/null +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package io.a2a.client.transport.spi.sse; + +import org.jspecify.annotations.NullMarked; + diff --git a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java new file mode 100644 index 000000000..3b0f37b2e --- /dev/null +++ b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java @@ -0,0 +1,295 @@ +package io.a2a.client.transport.spi.sse; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import io.a2a.spec.Message; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.Task; +import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatus; +import io.a2a.spec.TaskStatusUpdateEvent; +import io.a2a.spec.TextPart; +import org.jspecify.annotations.Nullable; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * Tests for BaseSSEEventListener abstract class. + * Tests the common functionality provided by the base class for handling events and errors. + */ +public class SSEEventListenerTest { + + private static final String TEST_TASK_ID = "task-123"; + private static final String TEST_CONTEXT_ID = "ctx-456"; + private static final String TEST_MESSAGE_ID = "msg-123"; + private static final String TEST_TEXT = "test"; + + /** + * Concrete implementation of BaseSSEEventListener for testing. + * Simulates parsing by directly calling handleEvent with provided test data. + */ + private static class TestSSEEventListener extends AbstractSSEEventListener { + private StreamingEventKind eventToHandle; + + public TestSSEEventListener(Consumer eventHandler, + @Nullable Consumer errorHandler) { + super(eventHandler, errorHandler); + } + + @Override + public void onMessage(String message, @Nullable Future completableFuture) { + if (eventToHandle != null) { + handleEvent(eventToHandle, completableFuture); + } + } + + public void setEventToHandle(StreamingEventKind event) { + this.eventToHandle = event; + } + } + + /** + * Mock Future implementation that captures cancel calls. + */ + private static class CancelCapturingFuture implements Future { + private boolean cancelHandlerCalled = false; + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + cancelHandlerCalled = true; + return true; + } + + @Override + public boolean isCancelled() { + return cancelHandlerCalled; + } + + @Override + public boolean isDone() { + return false; + } + + @Override + public Void get() { + return null; + } + + @Override + public Void get(long timeout, TimeUnit unit) { + return null; + } + + public boolean wasCancelled() { + return cancelHandlerCalled; + } + } + + // Helper methods for creating test objects + + private static Message createMessage(Message.Role role) { + return Message.builder() + .role(role) + .messageId(TEST_MESSAGE_ID) + .contextId(TEST_CONTEXT_ID) + .parts(java.util.List.of(new TextPart(TEST_TEXT))) + .build(); + } + + private static Task createTask(TaskState state) { + return Task.builder() + .id(TEST_TASK_ID) + .contextId(TEST_CONTEXT_ID) + .status(new TaskStatus(state)) + .build(); + } + + private static TaskStatusUpdateEvent createTaskStatusUpdateEvent(TaskState state, boolean isFinal) { + return TaskStatusUpdateEvent.builder() + .taskId(TEST_TASK_ID) + .contextId(TEST_CONTEXT_ID) + .status(new TaskStatus(state)) + .isFinal(isFinal) + .build(); + } + + private static TestSSEEventListener createListenerWithEventCapture(AtomicReference eventCapture) { + return new TestSSEEventListener(eventCapture::set, null); + } + + private static TestSSEEventListener createListenerWithErrorCapture(AtomicReference errorCapture) { + return new TestSSEEventListener(event -> {}, errorCapture::set); + } + + private static TestSSEEventListener createBasicListener() { + return new TestSSEEventListener(event -> {}, null); + } + + // Tests + + @Test + public void testHandleEventCallsEventHandler() { + AtomicReference receivedEvent = new AtomicReference<>(); + TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); + + Message message = createMessage(Message.Role.USER); + + listener.setEventToHandle(message); + listener.onMessage(TEST_TEXT, null); + + assertNotNull(receivedEvent.get()); + assertEquals(message, receivedEvent.get()); + } + + @Test + public void testHandleEventWithNullErrorHandler() { + AtomicReference receivedEvent = new AtomicReference<>(); + TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); + + Task task = createTask(TaskState.WORKING); + + listener.setEventToHandle(task); + listener.onMessage(TEST_TEXT, null); + + assertNotNull(receivedEvent.get()); + } + + @Test + public void testOnErrorCallsErrorHandler() { + AtomicReference receivedError = new AtomicReference<>(); + TestSSEEventListener listener = createListenerWithErrorCapture(receivedError); + + IllegalStateException testError = new IllegalStateException("Test error"); + + listener.onError(testError, null); + + assertNotNull(receivedError.get()); + assertEquals(testError, receivedError.get()); + } + + @Test + public void testOnErrorWithNullErrorHandler() { + TestSSEEventListener listener = createBasicListener(); + + // Should not throw even with null error handler + listener.onError(new RuntimeException("Test error"), null); + } + + @Test + public void testOnErrorCancelsFuture() { + AtomicBoolean errorHandlerCalled = new AtomicBoolean(false); + TestSSEEventListener listener = new TestSSEEventListener( + event -> {}, + error -> errorHandlerCalled.set(true) + ); + + CancelCapturingFuture future = new CancelCapturingFuture(); + + listener.onError(new RuntimeException("Test error"), future); + + assertTrue(errorHandlerCalled.get()); + assertTrue(future.wasCancelled()); + } + + @Test + public void testShouldAutoCloseWithFinalTaskStatusUpdateEvent() { + TestSSEEventListener listener = createBasicListener(); + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.COMPLETED, true); + + assertTrue(listener.shouldAutoClose(finalEvent)); + } + + @Test + public void testShouldAutoCloseWithNonFinalTaskStatusUpdateEvent() { + TestSSEEventListener listener = createBasicListener(); + TaskStatusUpdateEvent nonFinalEvent = createTaskStatusUpdateEvent(TaskState.WORKING, false); + + assertFalse(listener.shouldAutoClose(nonFinalEvent)); + } + + @ParameterizedTest + @EnumSource(value = TaskState.class, names = {"COMPLETED", "FAILED", "CANCELED"}) + public void testShouldAutoCloseWithFinalTaskStates(TaskState finalState) { + TestSSEEventListener listener = createBasicListener(); + Task task = createTask(finalState); + + assertTrue(listener.shouldAutoClose(task), + "Task with state " + finalState + " should trigger auto-close"); + } + + @ParameterizedTest + @EnumSource(value = TaskState.class, names = {"WORKING", "SUBMITTED"}) + public void testShouldAutoCloseWithNonFinalTaskStates(TaskState nonFinalState) { + TestSSEEventListener listener = createBasicListener(); + Task task = createTask(nonFinalState); + + assertFalse(listener.shouldAutoClose(task), + "Task with state " + nonFinalState + " should not trigger auto-close"); + } + + @Test + public void testShouldAutoCloseWithMessage() { + TestSSEEventListener listener = createBasicListener(); + Message message = createMessage(Message.Role.AGENT); + + assertFalse(listener.shouldAutoClose(message)); + } + + @Test + public void testAutoCloseCancelsFutureForFinalEvent() { + AtomicReference receivedEvent = new AtomicReference<>(); + TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); + + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.COMPLETED, true); + CancelCapturingFuture future = new CancelCapturingFuture(); + + listener.setEventToHandle(finalEvent); + listener.onMessage(TEST_TEXT, future); + + assertNotNull(receivedEvent.get()); + assertEquals(finalEvent, receivedEvent.get()); + assertTrue(future.wasCancelled()); + } + + @Test + public void testAutoCloseDoesNotCancelFutureForNonFinalEvent() { + AtomicReference receivedEvent = new AtomicReference<>(); + TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); + + Message message = createMessage(Message.Role.AGENT); + CancelCapturingFuture future = new CancelCapturingFuture(); + + listener.setEventToHandle(message); + listener.onMessage(TEST_TEXT, future); + + assertNotNull(receivedEvent.get()); + assertFalse(future.wasCancelled()); + } + + @Test + public void testAutoCloseWithNullFuture() { + AtomicReference receivedEvent = new AtomicReference<>(); + TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); + + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.COMPLETED, true); + + // Should not throw with null future + listener.setEventToHandle(finalEvent); + listener.onMessage(TEST_TEXT, null); + + assertNotNull(receivedEvent.get()); + } +} \ No newline at end of file From 153a1de11fada3e94ca1557e334d00f99dfcf757 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 5 Feb 2026 12:25:38 +0100 Subject: [PATCH 012/192] chore: Managing tenant in JSONRPC. (#613) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the tenant is not defined in the JSONRPC payload, we use the one from the request path. Fixes #612 🦕 Signed-off-by: Emmanuel Hugonnet --- .../server/apps/quarkus/A2AServerRoutes.java | 19 +- .../apps/quarkus/A2AServerRoutesTest.java | 198 ++++++++++++++++++ .../server/rest/quarkus/A2AServerRoutes.java | 3 + .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 36 +++- .../io/a2a/grpc/utils/JSONRPCUtilsTest.java | 14 +- .../jsonrpc/context/JSONRPCContextKeys.java | 5 + .../rest/context/RestContextKeys.java | 4 + 7 files changed, 267 insertions(+), 12 deletions(-) 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 cb5bdb25b..672940db8 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 @@ -2,6 +2,7 @@ import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; +import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_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; @@ -102,7 +103,7 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { Multi> streamingResponse = null; A2AErrorResponse error = null; try { - A2ARequest request = JSONRPCUtils.parseRequestBody(body); + A2ARequest request = JSONRPCUtils.parseRequestBody(body, extractTenant(rc)); context.getState().put(METHOD_NAME_KEY, request.getMethod()); if (request instanceof NonStreamingJSONRPCRequest nonStreamingRequest) { nonStreamingResponse = processNonStreamingRequest(nonStreamingRequest, context); @@ -218,7 +219,6 @@ static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { } private ServerCallContext createCallContext(RoutingContext rc) { - if (callContextFactory.isUnsatisfied()) { User user; if (rc.user() == null) { @@ -245,6 +245,7 @@ public String getUsername() { Set headerNames = rc.request().headers().names(); headerNames.forEach(name -> headers.put(name, rc.request().getHeader(name))); state.put(HEADERS_KEY, headers); + state.put(TENANT_KEY, extractTenant(rc)); // Extract requested protocol version from X-A2A-Version header String requestedVersion = rc.request().getHeader(A2AHeaders.X_A2A_VERSION); @@ -260,6 +261,20 @@ public String getUsername() { } } + private String extractTenant(RoutingContext rc) { + String tenantPath = rc.normalizedPath(); + if (tenantPath == null || tenantPath.isBlank()) { + return ""; + } + if (tenantPath.startsWith("/")) { + tenantPath = tenantPath.substring(1); + } + if(tenantPath.endsWith("/")) { + tenantPath = tenantPath.substring(0, tenantPath.length() -1); + } + return tenantPath; + } + private static String serializeResponse(A2AResponse response) { // For error responses, use Jackson serialization (errors are standardized) if (response instanceof A2AErrorResponse error) { 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 3f28d564d..429eff9e1 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 @@ -5,6 +5,7 @@ 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 io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -108,6 +109,7 @@ public void setUp() { when(mockRoutingContext.user()).thenReturn(null); when(mockRequest.headers()).thenReturn(mockHeaders); when(mockRoutingContext.body()).thenReturn(mockRequestBody); + when(mockRoutingContext.normalizedPath()).thenReturn("/"); // Chain the response methods properly when(mockHttpResponse.setStatusCode(any(Integer.class))).thenReturn(mockHttpResponse); @@ -520,6 +522,202 @@ public void testGetExtendedCard_MethodNameSetInContext() { assertEquals(GET_EXTENDED_AGENT_CARD_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } + @Test + public void testTenantExtraction_MultiSegmentPath() { + // Arrange - simulate request to /test/titi + when(mockRoutingContext.normalizedPath()).thenReturn("/test/titi"); + String jsonRpcRequest = """ + { + "jsonrpc": "2.0", + "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", + "method": "GetTask", + "params": { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "historyLength": 10 + } + }"""; + when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); + + Task responseTask = Task.builder() + .id("de38c76d-d54c-436c-8b9f-4c2703648d64") + .contextId("context-1234") + .status(new TaskStatus(TaskState.SUBMITTED)) + .build(); + GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); + when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) + .thenReturn(realResponse); + + ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); + + // Act + routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); + + // Assert + verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); + ServerCallContext capturedContext = contextCaptor.getValue(); + assertNotNull(capturedContext); + assertEquals("test/titi", capturedContext.getState().get(TENANT_KEY)); + } + + @Test + public void testTenantExtraction_RootPath() { + // Arrange - simulate request to / + when(mockRoutingContext.normalizedPath()).thenReturn("/"); + String jsonRpcRequest = """ + { + "jsonrpc": "2.0", + "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", + "method": "GetTask", + "params": { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "historyLength": 10 + } + }"""; + when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); + + Task responseTask = Task.builder() + .id("de38c76d-d54c-436c-8b9f-4c2703648d64") + .contextId("context-1234") + .status(new TaskStatus(TaskState.SUBMITTED)) + .build(); + GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); + when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) + .thenReturn(realResponse); + + ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); + + // Act + routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); + + // Assert + verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); + ServerCallContext capturedContext = contextCaptor.getValue(); + assertNotNull(capturedContext); + assertEquals("", capturedContext.getState().get(TENANT_KEY)); + } + + @Test + public void testTenantExtraction_SingleSegmentPath() { + // Arrange - simulate request to /tenant1 + when(mockRoutingContext.normalizedPath()).thenReturn("/tenant1"); + String jsonRpcRequest = """ + { + "jsonrpc": "2.0", + "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", + "method": "GetTask", + "params": { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "historyLength": 10 + } + }"""; + when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); + + Task responseTask = Task.builder() + .id("de38c76d-d54c-436c-8b9f-4c2703648d64") + .contextId("context-1234") + .status(new TaskStatus(TaskState.SUBMITTED)) + .build(); + GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); + when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) + .thenReturn(realResponse); + + ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); + + // Act + routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); + + // Assert + verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); + ServerCallContext capturedContext = contextCaptor.getValue(); + assertNotNull(capturedContext); + assertEquals("tenant1", capturedContext.getState().get(TENANT_KEY)); + } + + @Test + public void testTenantExtraction_ThreeSegmentPath() { + // Arrange - simulate request to /tenant1/api/v1 + when(mockRoutingContext.normalizedPath()).thenReturn("/tenant1/api/v1"); + String jsonRpcRequest = """ + { + "jsonrpc": "2.0", + "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", + "method": "GetTask", + "params": { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "historyLength": 10 + } + }"""; + when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); + + Task responseTask = Task.builder() + .id("de38c76d-d54c-436c-8b9f-4c2703648d64") + .contextId("context-1234") + .status(new TaskStatus(TaskState.SUBMITTED)) + .build(); + GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); + when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) + .thenReturn(realResponse); + + ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); + + // Act + routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); + + // Assert + verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); + ServerCallContext capturedContext = contextCaptor.getValue(); + assertNotNull(capturedContext); + assertEquals("tenant1/api/v1", capturedContext.getState().get(TENANT_KEY)); + } + + @Test + public void testTenantExtraction_StreamingRequest() { + // Arrange - simulate streaming request to /myTenant/api + when(mockRoutingContext.normalizedPath()).thenReturn("/myTenant/api"); + String jsonRpcRequest = """ + { + "jsonrpc": "2.0", + "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", + "method": "SendStreamingMessage", + "params": { + "message": { + "messageId": "message-1234", + "contextId": "context-1234", + "role": "ROLE_USER", + "parts": [ + { + "text": "tell me a joke" + } + ], + "metadata": {} + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + }, + "metadata": {} + } + }"""; + when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); + + @SuppressWarnings("unchecked") + Flow.Publisher mockPublisher = mock(Flow.Publisher.class); + when(mockJsonRpcHandler.onMessageSendStream(any(SendStreamingMessageRequest.class), + any(ServerCallContext.class))).thenReturn(mockPublisher); + + ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); + + // Act + routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); + + // Assert + verify(mockJsonRpcHandler).onMessageSendStream(any(SendStreamingMessageRequest.class), + contextCaptor.capture()); + ServerCallContext capturedContext = contextCaptor.getValue(); + assertNotNull(capturedContext); + assertEquals("myTenant/api", capturedContext.getState().get(TENANT_KEY)); + } + /** * Helper method to set a field via reflection for testing purposes. */ 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 7a50f0afb..635202062 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 @@ -58,6 +58,8 @@ 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.TENANT_KEY; + @Singleton @Authenticated public class A2AServerRoutes { @@ -443,6 +445,7 @@ public String getUsername() { headerNames.forEach(name -> headers.put(name, rc.request().getHeader(name))); state.put(HEADERS_KEY, headers); state.put(METHOD_NAME_KEY, jsonRpcMethodName); + state.put(TENANT_KEY, extractTenant(rc)); // Extract requested protocol version from X-A2A-Version header String requestedVersion = rc.request().getHeader(A2AHeaders.X_A2A_VERSION); 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 1692ae3a5..e49bcbeec 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 @@ -183,7 +183,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 A2ARequest parseRequestBody(String body) throws JsonMappingException, JsonProcessingException { + public static A2ARequest parseRequestBody(String body, @Nullable String tenant) throws JsonMappingException, JsonProcessingException { JsonElement jelement = JsonParser.parseString(body); JsonObject jsonRpc = jelement.getAsJsonObject(); if (!jsonRpc.has("method")) { @@ -196,52 +196,76 @@ public static A2ARequest parseRequestBody(String body) throws JsonMappingExce String method = jsonRpc.get("method").getAsString(); JsonElement paramsNode = jsonRpc.get("params"); try { - return parseMethodRequest(version, id, method, paramsNode); + return parseMethodRequest(version, id, method, paramsNode, tenant); } catch (InvalidParamsError e) { throw new InvalidParamsJsonMappingException(Utils.defaultIfNull(e.getMessage(), "Invalid parameters"), id); } } - private static A2ARequest 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, @Nullable String tenant) throws InvalidParamsError, MethodNotFoundJsonMappingException, JsonProcessingException { switch (method) { case GET_TASK_METHOD -> { io.a2a.grpc.GetTaskRequest.Builder builder = io.a2a.grpc.GetTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new GetTaskRequest(version, id, ProtoUtils.FromProto.taskQueryParams(builder)); } case CANCEL_TASK_METHOD -> { io.a2a.grpc.CancelTaskRequest.Builder builder = io.a2a.grpc.CancelTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new CancelTaskRequest(version, id, ProtoUtils.FromProto.taskIdParams(builder)); } case LIST_TASK_METHOD -> { io.a2a.grpc.ListTasksRequest.Builder builder = io.a2a.grpc.ListTasksRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new ListTasksRequest(version, id, ProtoUtils.FromProto.listTasksParams(builder)); } case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.SetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.SetTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new SetTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.setTaskPushNotificationConfig(builder)); } case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new GetTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.getTaskPushNotificationConfigParams(builder)); } case SEND_MESSAGE_METHOD -> { io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new SendMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); } case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new ListTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.listTaskPushNotificationConfigParams(builder)); } case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new DeleteTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.deleteTaskPushNotificationConfigParams(builder)); } case GET_EXTENDED_AGENT_CARD_METHOD -> { @@ -250,11 +274,17 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin case SEND_STREAMING_MESSAGE_METHOD -> { io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new SendStreamingMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); } case SUBSCRIBE_TO_TASK_METHOD -> { io.a2a.grpc.SubscribeToTaskRequest.Builder builder = io.a2a.grpc.SubscribeToTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); + if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { + builder.setTenant(tenant); + } return new SubscribeToTaskRequest(version, id, ProtoUtils.FromProto.taskIdParams(builder)); } default -> 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 61506c88e..380353dea 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 @@ -49,7 +49,7 @@ public void testParseSetTaskPushNotificationConfigRequest_ValidProtoFormat() thr } """; - A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest); + A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest, null); assertNotNull(request); assertInstanceOf(SetTaskPushNotificationConfigRequest.class, request); @@ -78,7 +78,7 @@ public void testParseGetTaskPushNotificationConfigRequest_ValidProtoFormat() thr } """; - A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest); + A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest, null); assertNotNull(request); assertInstanceOf(GetTaskPushNotificationConfigRequest.class, request); @@ -101,7 +101,7 @@ public void testParseMalformedJSON_ThrowsJsonSyntaxException() { """; // Missing closing braces JsonSyntaxException exception = assertThrows(JsonSyntaxException.class, () -> { - JSONRPCUtils.parseRequestBody(malformedRequest); + JSONRPCUtils.parseRequestBody(malformedRequest, null); }); assertEquals("java.io.EOFException: End of input at line 6 column 1 path $.params.parent", exception.getMessage()); } @@ -119,7 +119,7 @@ public void testParseInvalidParams_ThrowsInvalidParamsJsonMappingException() { InvalidParamsJsonMappingException exception = assertThrows( InvalidParamsJsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(invalidParamsRequest) + () -> JSONRPCUtils.parseRequestBody(invalidParamsRequest, null) ); assertEquals(3, exception.getId()); } @@ -139,7 +139,7 @@ public void testParseInvalidProtoStructure_ThrowsInvalidParamsJsonMappingExcepti InvalidParamsJsonMappingException exception = assertThrows( InvalidParamsJsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(invalidStructure) + () -> JSONRPCUtils.parseRequestBody(invalidStructure, null) ); assertEquals(4, exception.getId()); assertEquals(ERROR_MESSAGE.formatted("invalid_field in message a2a.v1.SetTaskPushNotificationConfigRequest"), exception.getMessage()); @@ -169,7 +169,7 @@ public void testParseMissingField_ThrowsInvalidParamsError() throws JsonMappingE }"""; InvalidParamsJsonMappingException exception = assertThrows( InvalidParamsJsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(missingRoleMessage) + () -> JSONRPCUtils.parseRequestBody(missingRoleMessage, null) ); assertEquals(18, exception.getId()); } @@ -199,7 +199,7 @@ public void testParseUnknownField_ThrowsJsonMappingException() throws JsonMappin }"""; JsonMappingException exception = assertThrows( JsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(unkownFieldMessage) + () -> JSONRPCUtils.parseRequestBody(unkownFieldMessage, null) ); assertEquals(ERROR_MESSAGE.formatted("unknown in message a2a.v1.Message"), exception.getMessage()); } diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java index 015e3860a..fbed22192 100644 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java +++ b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java @@ -18,6 +18,11 @@ public final class JSONRPCContextKeys { */ public static final String METHOD_NAME_KEY = "method"; + /** + * Context key for storing the tenant identifier extracted from the normalized path. + */ + public static final String TENANT_KEY = "tenant"; + private JSONRPCContextKeys() { // Utility class } diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java b/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java index de35ca0cf..f822607ef 100644 --- a/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java +++ b/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java @@ -17,6 +17,10 @@ public final class RestContextKeys { * Context key for storing the method name being called. */ public static final String METHOD_NAME_KEY = "method"; + /** + * Context key for storing the tenant identifier extracted from the request path. + */ + public static final String TENANT_KEY = "tenant"; private RestContextKeys() { // Utility class From 2a797f444f2b963544bd4804d6b0b0357c6f0e2f Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 5 Feb 2026 12:55:21 +0000 Subject: [PATCH 013/192] chore: Add timouts to requesthandler tests (#626) This should make it easier to diagnose occasional hangs in the tests --- .../java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java | 2 ++ .../io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java | 2 ++ .../java/io/a2a/transport/rest/handler/RestHandlerTest.java | 2 ++ 3 files changed, 6 insertions(+) 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 afed1329f..187fd6e99 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 @@ -66,9 +66,11 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; import org.mockito.MockedConstruction; import org.mockito.Mockito; +@Timeout(value = 1, unit = TimeUnit.MINUTES) public class GrpcHandlerTest extends AbstractA2ARequestHandlerTest { private static final Message GRPC_MESSAGE = Message.newBuilder() 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 4dc151626..2053ada41 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 @@ -85,9 +85,11 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; import org.mockito.MockedConstruction; import org.mockito.Mockito; +@Timeout(value = 1, unit = TimeUnit.MINUTES) public class JSONRPCHandlerTest extends AbstractA2ARequestHandlerTest { private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); 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 db3ff97aa..21005c22f 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 @@ -22,7 +22,9 @@ import io.a2a.spec.Task; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +@Timeout(value = 1, unit = TimeUnit.MINUTES) public class RestHandlerTest extends AbstractA2ARequestHandlerTest { private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); From 147f9c1c74ad34f8d01685dc860943e2c8e55520 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Thu, 5 Feb 2026 14:43:49 +0100 Subject: [PATCH 014/192] feat!: Update a2a.proto d14f410 (#614) based on https://github.com/a2aproject/A2A/commit/d14f4107119bf0fe0dff9e2c577eb4ab70b51793 Signed-off-by: Jeff Mesnil --- README.md | 5 +- .../java/io/a2a/client/AbstractClient.java | 10 +- .../src/main/java/io/a2a/client/Client.java | 6 +- .../java/io/a2a/client/ClientBuilderTest.java | 1 - .../client/transport/grpc/GrpcTransport.java | 8 +- .../transport/jsonrpc/JSONRPCTransport.java | 10 +- .../jsonrpc/JSONRPCTransportTest.java | 9 +- .../transport/jsonrpc/JsonMessages.java | 5 +- .../client/transport/rest/RestTransport.java | 6 +- .../transport/rest/JsonRestMessages.java | 9 +- .../transport/rest/RestTransportTest.java | 9 +- .../client/transport/spi/ClientTransport.java | 8 +- .../cloud/CloudAgentCardProducer.java | 1 - .../helloworld/AgentCardProducer.java | 1 - ...otificationConfigStoreIntegrationTest.java | 2 +- .../MultiInstanceReplicationAgentCards.java | 1 - .../ReplicationTestAgentCardProducer.java | 1 - .../java/io/a2a/client/http/JsonMessages.java | 3 +- .../jsonrpc/common/wrappers/A2AResponse.java | 2 +- ...ateTaskPushNotificationConfigRequest.java} | 18 +- ...teTaskPushNotificationConfigResponse.java} | 10 +- .../wrappers/NonStreamingJSONRPCRequest.java | 2 +- .../server/apps/quarkus/A2AServerRoutes.java | 10 +- .../apps/quarkus/A2AServerRoutesTest.java | 14 +- .../server/rest/quarkus/A2AServerRoutes.java | 4 +- .../rest/quarkus/A2AServerRoutesTest.java | 8 +- .../DefaultRequestHandler.java | 2 +- .../requesthandlers/RequestHandler.java | 2 +- .../io/a2a/server/util/sse/SseFormatter.java | 6 +- .../AbstractA2ARequestHandlerTest.java | 5 +- spec-grpc/src/main/java/io/a2a/grpc/A2A.java | 339 +++++++++--------- .../main/java/io/a2a/grpc/A2AServiceGrpc.java | 76 ++-- .../java/io/a2a/grpc/AgentCapabilities.java | 125 +------ .../a2a/grpc/AgentCapabilitiesOrBuilder.java | 19 - .../java/io/a2a/grpc/CancelTaskRequest.java | 4 +- ...ateTaskPushNotificationConfigRequest.java} | 120 +++---- ...shNotificationConfigRequestOrBuilder.java} | 4 +- ...leteTaskPushNotificationConfigRequest.java | 4 +- .../main/java/io/a2a/grpc/GetTaskRequest.java | 4 +- ...istTaskPushNotificationConfigResponse.java | 4 +- .../java/io/a2a/grpc/SendMessageRequest.java | 4 +- .../grpc/mapper/AgentCapabilitiesMapper.java | 1 - ...eateTaskPushNotificationConfigMapper.java} | 30 +- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 12 +- .../java/io/a2a/grpc/utils/ProtoUtils.java | 18 +- spec-grpc/src/main/proto/a2a.proto | 26 +- .../io/a2a/grpc/utils/JSONRPCUtilsTest.java | 36 +- .../java/io/a2a/grpc/utils/ToProtoTest.java | 2 - .../src/main/java/io/a2a/spec/A2AMethods.java | 2 +- .../java/io/a2a/spec/AgentCapabilities.java | 26 +- .../io/a2a/tck/server/AgentCardProducer.java | 1 - .../apps/common/AbstractA2AServerTest.java | 8 +- .../server/apps/common/AgentCardProducer.java | 1 - .../transport/grpc/handler/GrpcHandler.java | 6 +- .../grpc/handler/GrpcHandlerTest.java | 44 +-- .../jsonrpc/handler/JSONRPCHandler.java | 18 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 50 ++- .../transport/rest/handler/RestHandler.java | 6 +- .../rest/handler/RestHandlerTest.java | 10 +- 59 files changed, 487 insertions(+), 691 deletions(-) rename jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/{SetTaskPushNotificationConfigRequest.java => CreateTaskPushNotificationConfigRequest.java} (76%) rename jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/{SetTaskPushNotificationConfigResponse.java => CreateTaskPushNotificationConfigResponse.java} (75%) rename spec-grpc/src/main/java/io/a2a/grpc/{SetTaskPushNotificationConfigRequest.java => CreateTaskPushNotificationConfigRequest.java} (85%) rename spec-grpc/src/main/java/io/a2a/grpc/{SetTaskPushNotificationConfigRequestOrBuilder.java => CreateTaskPushNotificationConfigRequestOrBuilder.java} (93%) rename spec-grpc/src/main/java/io/a2a/grpc/mapper/{SetTaskPushNotificationConfigMapper.java => CreateTaskPushNotificationConfigMapper.java} (79%) diff --git a/README.md b/README.md index 50a760b10..941419f45 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,6 @@ public class WeatherAgentCardProducer { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(false) - .stateTransitionHistory(false) .build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) @@ -575,10 +574,10 @@ TaskPushNotificationConfig taskConfig = TaskPushNotificationConfig.builder() .pushNotificationConfig(pushNotificationConfig) .build(); -TaskPushNotificationConfig result = client.setTaskPushNotificationConfiguration(taskConfig); +TaskPushNotificationConfig result = client.createTaskPushNotificationConfiguration(taskConfig); // You can also optionally specify a ClientCallContext with call-specific config to use -TaskPushNotificationConfig result = client.setTaskPushNotificationConfiguration(taskConfig, clientCallContext); +TaskPushNotificationConfig result = client.createTaskPushNotificationConfiguration(taskConfig, clientCallContext); ``` #### List the push notification configurations for a task 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 5d2785386..c47d8238b 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java @@ -224,26 +224,26 @@ public Task cancelTask(TaskIdParams request) throws A2AClientException { public abstract Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException; /** - * Set or update the push notification configuration for a specific task. + * Create or update the push notification configuration for a specific task. * * @param request the push notification configuration to set for the task * @return the configured TaskPushNotificationConfig * @throws A2AClientException if setting the task push notification configuration fails for any reason */ - public TaskPushNotificationConfig setTaskPushNotificationConfiguration( + public TaskPushNotificationConfig createTaskPushNotificationConfiguration( TaskPushNotificationConfig request) throws A2AClientException { - return setTaskPushNotificationConfiguration(request, null); + return createTaskPushNotificationConfiguration(request, null); } /** - * Set or update the push notification configuration for a specific task. + * Create or update the push notification configuration for a specific task. * * @param request the push notification configuration to set for the task * @param context optional client call context for the request (may be {@code null}) * @return the configured TaskPushNotificationConfig * @throws A2AClientException if setting the task push notification configuration fails for any reason */ - public abstract TaskPushNotificationConfig setTaskPushNotificationConfiguration( + public abstract TaskPushNotificationConfig createTaskPushNotificationConfiguration( TaskPushNotificationConfig request, @Nullable ClientCallContext context) throws A2AClientException; 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 117351098..405155ee2 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -431,7 +431,7 @@ public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context * ) * ) * ); - * client.setTaskPushNotificationConfiguration(config); + * client.createTaskPushNotificationConfiguration(config); * } * * @param request the push notification configuration for the task @@ -442,9 +442,9 @@ public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context * @see PushNotificationConfig */ @Override - public TaskPushNotificationConfig setTaskPushNotificationConfiguration( + public TaskPushNotificationConfig createTaskPushNotificationConfiguration( TaskPushNotificationConfig request, @Nullable ClientCallContext context) throws A2AClientException { - return clientTransport.setTaskPushNotificationConfiguration(request, context); + return clientTransport.createTaskPushNotificationConfiguration(request, context); } /** diff --git a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java index 56eb7560d..dd38c937d 100644 --- a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java +++ b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java @@ -31,7 +31,6 @@ public class ClientBuilderTest { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(true) - .stateTransitionHistory(true) .build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) 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 5cb431419..8cc67d7b0 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 @@ -229,12 +229,12 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo } @Override - public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushNotificationConfig request, - @Nullable ClientCallContext context) throws A2AClientException { + public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, + @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); String configId = request.pushNotificationConfig().id(); - io.a2a.grpc.SetTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.SetTaskPushNotificationConfigRequest.newBuilder() + io.a2a.grpc.CreateTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() .setParent("tasks/" + request.taskId()) .setConfig(ToProto.taskPushNotificationConfig(request)) .setConfigId(configId != null ? configId : request.taskId()) @@ -244,7 +244,7 @@ public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushN try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - return FromProto.taskPushNotificationConfig(stubWithMetadata.setTaskPushNotificationConfig(grpcRequest)); + return FromProto.taskPushNotificationConfig(stubWithMetadata.createTaskPushNotificationConfig(grpcRequest)); } catch (StatusRuntimeException | StatusException e) { throw GrpcErrorMapper.mapGrpcError(e, "Failed to create task push notification config: "); } 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 e991eecb3..21ea398c1 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 @@ -43,7 +43,7 @@ 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.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.spec.A2AClientError; import io.a2a.spec.A2AClientException; import io.a2a.spec.A2AError; @@ -182,15 +182,15 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo } @Override - public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushNotificationConfig request, - @Nullable ClientCallContext context) throws A2AClientException { + public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, + @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - ProtoUtils.ToProto.setTaskPushNotificationConfigRequest(request), agentCard, context); + ProtoUtils.ToProto.createTaskPushNotificationConfigRequest(request), agentCard, context); try { String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - SetTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + CreateTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); return response.getResult(); } catch (A2AClientException e) { throw e; diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 9b6f7f017..74fe9545a 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -1,7 +1,5 @@ package io.a2a.client.transport.jsonrpc; -import static io.a2a.client.transport.jsonrpc.JsonMessages.AGENT_CARD; -import static io.a2a.client.transport.jsonrpc.JsonMessages.AGENT_CARD_SUPPORTS_EXTENDED; import static io.a2a.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_REQUEST; import static io.a2a.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_RESPONSE; import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST; @@ -43,7 +41,6 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.VersionNotSupportedError; -import io.a2a.spec.AgentInterface; import io.a2a.spec.AgentSkill; import io.a2a.spec.Artifact; import io.a2a.spec.AuthenticationInfo; @@ -67,7 +64,6 @@ import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TaskState; import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; import io.a2a.util.Utils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -322,7 +318,7 @@ public void testA2AClientGetTaskPushNotificationConfig() throws Exception { } @Test - public void testA2AClientSetTaskPushNotificationConfig() throws Exception { + public void testA2AClientCreateTaskPushNotificationConfig() throws Exception { this.server.when( request() .withMethod("POST") @@ -337,7 +333,7 @@ public void testA2AClientSetTaskPushNotificationConfig() throws Exception { ); JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - TaskPushNotificationConfig taskPushNotificationConfig = client.setTaskPushNotificationConfiguration( + TaskPushNotificationConfig taskPushNotificationConfig = client.createTaskPushNotificationConfiguration( new TaskPushNotificationConfig("de38c76d-d54c-436c-8b9f-4c2703648d64", PushNotificationConfig.builder() .id("c295ea44-7543-4f78-b524-7a38915ad6e4") @@ -378,7 +374,6 @@ public void testA2AClientGetExtendedAgentCard() throws Exception { assertEquals("https://docs.examplegeoservices.com/georoute-agent/api", agentCard.documentationUrl()); assertTrue(agentCard.capabilities().streaming()); assertTrue(agentCard.capabilities().pushNotifications()); - assertFalse(agentCard.capabilities().stateTransitionHistory()); assertTrue(agentCard.capabilities().extendedAgentCard()); Map securitySchemes = agentCard.securitySchemes(); assertNotNull(securitySchemes); 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 dfdbb9741..211f5e4f6 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 @@ -28,7 +28,6 @@ public class JsonMessages { "capabilities": { "streaming": true, "pushNotifications": true, - "stateTransitionHistory": false, "extendedAgentCard": false }, "securitySchemes": { @@ -340,7 +339,7 @@ public class JsonMessages { static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ { "jsonrpc":"2.0", - "method":"SetTaskPushNotificationConfig", + "method":"CreateTaskPushNotificationConfig", "params":{ "parent":"tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", "configId":"c295ea44-7543-4f78-b524-7a38915ad6e4", @@ -610,7 +609,6 @@ public class JsonMessages { "capabilities": { "streaming": true, "pushNotifications": true, - "stateTransitionHistory": false, "extendedAgentCard": true }, "securitySchemes": { @@ -691,7 +689,6 @@ public class JsonMessages { "capabilities": { "streaming": true, "pushNotifications": true, - "stateTransitionHistory": false, "extendedAgentCard": true }, "securitySchemes": { 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 ae01e0f3f..88c86846d 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 @@ -269,10 +269,10 @@ private String buildListTasksQueryString(ListTasksParams request) { } @Override - public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushNotificationConfig request, @Nullable ClientCallContext context) throws A2AClientException { + public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - io.a2a.grpc.SetTaskPushNotificationConfigRequest.Builder builder - = io.a2a.grpc.SetTaskPushNotificationConfigRequest.newBuilder(); + io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder + = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); builder.setConfig(ProtoUtils.ToProto.taskPushNotificationConfig(request)) .setParent("tasks/" + request.taskId()); if (request.pushNotificationConfig().id() != null) { diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java index c0c2360b0..f324f004e 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java @@ -121,8 +121,7 @@ public class JsonRestMessages { "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", "capabilities": { "streaming": true, - "pushNotifications": true, - "stateTransitionHistory": false + "pushNotifications": true }, "securitySchemes": { "google": { @@ -188,8 +187,7 @@ public class JsonRestMessages { "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", "capabilities": { "streaming": true, - "pushNotifications": true, - "stateTransitionHistory": false + "pushNotifications": true }, "securitySchemes": { "google": { @@ -255,8 +253,7 @@ public class JsonRestMessages { "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", "capabilities": { "streaming": true, - "pushNotifications": true, - "stateTransitionHistory": false + "pushNotifications": true }, "securitySchemes": { "google": { diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index 879363d9c..04efb4eca 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -80,7 +80,6 @@ public class RestTransportTest { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(true) - .stateTransitionHistory(true) .build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) @@ -287,11 +286,11 @@ public void testSendMessageStreaming() throws Exception { } /** - * Test of setTaskPushNotificationConfiguration method, of class JSONRestTransport. + * Test of CreateTaskPushNotificationConfiguration method, of class JSONRestTransport. */ @Test - public void testSetTaskPushNotificationConfiguration() throws Exception { - log.info("Testing setTaskPushNotificationConfiguration"); + public void testCreateTaskPushNotificationConfiguration() throws Exception { + log.info("Testing CreateTaskPushNotificationConfiguration"); this.server.when( request() .withMethod("POST") @@ -312,7 +311,7 @@ public void testSetTaskPushNotificationConfiguration() throws Exception { .authentication( new AuthenticationInfo(Collections.singletonList("jwt"), null)) .build(), "tenant"); - TaskPushNotificationConfig taskPushNotificationConfig = client.setTaskPushNotificationConfiguration(pushedConfig, null); + TaskPushNotificationConfig taskPushNotificationConfig = client.createTaskPushNotificationConfiguration(pushedConfig, null); PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); 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 df95e9ffd..504e4c601 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 @@ -79,15 +79,15 @@ void sendMessageStreaming(MessageSendParams request, Consumer the type of the result value returned in successful responses */ -public abstract sealed class A2AResponse implements A2AMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetExtendedAgentCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, A2AErrorResponse, ListTaskPushNotificationConfigResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, SetTaskPushNotificationConfigResponse { +public abstract sealed class A2AResponse implements A2AMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetExtendedAgentCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, A2AErrorResponse, ListTaskPushNotificationConfigResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, CreateTaskPushNotificationConfigResponse { /** The JSON-RPC protocol version. */ protected String jsonrpc; diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java similarity index 76% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java index c01e7c2f4..b9b8716be 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java @@ -16,12 +16,12 @@ *

    * This class implements the JSON-RPC {@code tasks/pushNotificationConfig/set} method. * - * @see SetTaskPushNotificationConfigResponse for the response + * @see CreateTaskPushNotificationConfigResponse for the response * @see TaskPushNotificationConfig for the parameter structure * @see PushNotificationConfig for notification endpoint details * @see A2A Protocol Specification */ -public final class SetTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { +public final class CreateTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { /** * Constructs request with all parameters. @@ -30,7 +30,7 @@ public final class SetTaskPushNotificationConfigRequest extends NonStreamingJSON * @param id the request ID * @param params the request parameters */ - public SetTaskPushNotificationConfigRequest(String jsonrpc, Object id, TaskPushNotificationConfig params) { + public CreateTaskPushNotificationConfigRequest(String jsonrpc, Object id, TaskPushNotificationConfig params) { super(jsonrpc, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); } @@ -40,7 +40,7 @@ public SetTaskPushNotificationConfigRequest(String jsonrpc, Object id, TaskPushN * @param id the request ID * @param taskPushConfig the task push notification configuration */ - public SetTaskPushNotificationConfigRequest(String id, TaskPushNotificationConfig taskPushConfig) { + public CreateTaskPushNotificationConfigRequest(String id, TaskPushNotificationConfig taskPushConfig) { this(null, id, taskPushConfig); } @@ -73,7 +73,7 @@ private Builder() { * @param jsonrpc the JSON-RPC version * @return this builder for method chaining */ - public SetTaskPushNotificationConfigRequest.Builder jsonrpc(String jsonrpc) { + public CreateTaskPushNotificationConfigRequest.Builder jsonrpc(String jsonrpc) { this.jsonrpc = jsonrpc; return this; } @@ -84,7 +84,7 @@ public SetTaskPushNotificationConfigRequest.Builder jsonrpc(String jsonrpc) { * @param id the request ID * @return this builder for method chaining */ - public SetTaskPushNotificationConfigRequest.Builder id(Object id) { + public CreateTaskPushNotificationConfigRequest.Builder id(Object id) { this.id = id; return this; } @@ -95,7 +95,7 @@ public SetTaskPushNotificationConfigRequest.Builder id(Object id) { * @param params the request parameters * @return this builder for method chaining */ - public SetTaskPushNotificationConfigRequest.Builder params(TaskPushNotificationConfig params) { + public CreateTaskPushNotificationConfigRequest.Builder params(TaskPushNotificationConfig params) { this.params = params; return this; } @@ -105,11 +105,11 @@ public SetTaskPushNotificationConfigRequest.Builder params(TaskPushNotificationC * * @return a new instance */ - public SetTaskPushNotificationConfigRequest build() { + public CreateTaskPushNotificationConfigRequest build() { if (id == null) { id = UUID.randomUUID().toString(); } - return new SetTaskPushNotificationConfigRequest(jsonrpc, id, params); + return new CreateTaskPushNotificationConfigRequest(jsonrpc, id, params); } } } diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java similarity index 75% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java index 0c39b9713..e46aa7d2b 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java @@ -14,12 +14,12 @@ * If push notifications are not supported or an error occurs, the error field will contain * a {@link A2AError} (e.g., {@link PushNotificationNotSupportedError}). * - * @see SetTaskPushNotificationConfigRequest for the corresponding request + * @see CreateTaskPushNotificationConfigRequest 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 A2AResponse { +public final class CreateTaskPushNotificationConfigResponse extends A2AResponse { /** * Constructs response with all parameters. @@ -29,7 +29,7 @@ public final class SetTaskPushNotificationConfigResponse extends A2AResponse the type of the request parameters */ public abstract sealed class NonStreamingJSONRPCRequest extends A2ARequest permits GetTaskRequest, - CancelTaskRequest, SetTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, + CancelTaskRequest, CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, SendMessageRequest, DeleteTaskPushNotificationConfigRequest, ListTaskPushNotificationConfigRequest, GetExtendedAgentCardRequest, ListTasksRequest { 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 672940db8..548f88da3 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 @@ -51,8 +51,8 @@ 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.CreateTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; @@ -176,7 +176,7 @@ private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest if (request instanceof ListTasksRequest req) { return jsonRpcHandler.onListTasks(req, context); } - if (request instanceof SetTaskPushNotificationConfigRequest req) { + if (request instanceof CreateTaskPushNotificationConfigRequest req) { return jsonRpcHandler.setPushNotificationConfig(req, context); } if (request instanceof GetTaskPushNotificationConfigRequest req) { @@ -297,8 +297,8 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -366,7 +366,7 @@ public void testSetTaskPushNotificationConfig_MethodNameSetInContext() { routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); // Assert - verify(mockJsonRpcHandler).setPushNotificationConfig(any(SetTaskPushNotificationConfigRequest.class), + verify(mockJsonRpcHandler).setPushNotificationConfig(any(CreateTaskPushNotificationConfigRequest.class), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); 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 635202062..a41f2d361 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 @@ -263,7 +263,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) { + public void CreateTaskPushNotificationConfiguration(@Body String body, RoutingContext rc) { String taskId = rc.pathParam("taskId"); ServerCallContext context = createCallContext(rc, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); HTTPRestResponse response = null; @@ -271,7 +271,7 @@ public void setTaskPushNotificationConfiguration(@Body String body, RoutingConte if (taskId == null || taskId.isEmpty()) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); } else { - response = jsonRestHandler.setTaskPushNotificationConfiguration(taskId, body, extractTenant(rc), context); + response = jsonRestHandler.CreateTaskPushNotificationConfiguration(taskId, body, extractTenant(rc), context); } } catch (Throwable t) { response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); 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 0f07b421a..9ef8f7c47 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 @@ -198,23 +198,23 @@ public void testResubscribeTask_MethodNameSetInContext() { } @Test - public void testSetTaskPushNotificationConfiguration_MethodNameSetInContext() { + public void testCreateTaskPushNotificationConfiguration_MethodNameSetInContext() { // Arrange when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.setTaskPushNotificationConfiguration(anyString(), anyString(), anyString(), + when(mockRestHandler.CreateTaskPushNotificationConfiguration(anyString(), anyString(), anyString(), any(ServerCallContext.class))).thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); // Act - routes.setTaskPushNotificationConfiguration("{}", mockRoutingContext); + routes.CreateTaskPushNotificationConfiguration("{}", mockRoutingContext); // Assert - verify(mockRestHandler).setTaskPushNotificationConfiguration(eq("task123"), eq("{}"), anyString(), contextCaptor.capture()); + verify(mockRestHandler).CreateTaskPushNotificationConfiguration(eq("task123"), eq("{}"), anyString(), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); 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 c476c8741..e1a16eb3c 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 @@ -739,7 +739,7 @@ public void onComplete() { } @Override - public TaskPushNotificationConfig onSetTaskPushNotificationConfig( + public TaskPushNotificationConfig onCreateTaskPushNotificationConfig( TaskPushNotificationConfig 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 6d99fe399..639098967 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 @@ -39,7 +39,7 @@ Flow.Publisher onMessageSendStream( MessageSendParams params, ServerCallContext context) throws A2AError; - TaskPushNotificationConfig onSetTaskPushNotificationConfig( + TaskPushNotificationConfig onCreateTaskPushNotificationConfig( TaskPushNotificationConfig params, ServerCallContext context) throws A2AError; diff --git a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java index 737fbac23..ba02222e6 100644 --- a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java +++ b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java @@ -4,6 +4,7 @@ import io.a2a.jsonrpc.common.wrappers.A2AErrorResponse; import io.a2a.jsonrpc.common.wrappers.A2AResponse; import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; +import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; @@ -12,7 +13,6 @@ import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; /** * Framework-agnostic utility for formatting A2A responses as Server-Sent Events (SSE). @@ -116,8 +116,8 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse()) .defaultOutputModes(new ArrayList<>()) diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java index 0fa06787b..6dc06f861 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java @@ -247,10 +247,10 @@ public static void registerAllExtensions( com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_descriptor; + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; static final com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_fieldAccessorTable; + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_a2a_v1_SubscribeToTaskRequest_descriptor; static final @@ -361,172 +361,171 @@ public static void registerAllExtensions( ".a2a.v1.SecurityScheme:\0028\001B\024\n\022_documenta" + "tion_urlB\013\n\t_icon_urlJ\004\010\003\020\004J\004\010\016\020\017J\004\010\017\020\020\"" + "<\n\rAgentProvider\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\031\n\014or" + - "ganization\030\002 \001(\tB\003\340A\002\"\233\002\n\021AgentCapabilit" + + "ganization\030\002 \001(\tB\003\340A\002\"\335\001\n\021AgentCapabilit" + "ies\022\026\n\tstreaming\030\001 \001(\010H\000\210\001\001\022\037\n\022push_noti" + "fications\030\002 \001(\010H\001\210\001\001\022*\n\nextensions\030\003 \003(\013" + - "2\026.a2a.v1.AgentExtension\022%\n\030state_transi" + - "tion_history\030\004 \001(\010H\002\210\001\001\022 \n\023extended_agen" + - "t_card\030\005 \001(\010H\003\210\001\001B\014\n\n_streamingB\025\n\023_push" + - "_notificationsB\033\n\031_state_transition_hist" + - "oryB\026\n\024_extended_agent_card\"m\n\016AgentExte" + - "nsion\022\013\n\003uri\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022" + - "\020\n\010required\030\003 \001(\010\022\'\n\006params\030\004 \001(\0132\027.goog" + - "le.protobuf.Struct\"\276\001\n\nAgentSkill\022\017\n\002id\030" + - "\001 \001(\tB\003\340A\002\022\021\n\004name\030\002 \001(\tB\003\340A\002\022\030\n\013descrip" + - "tion\030\003 \001(\tB\003\340A\002\022\021\n\004tags\030\004 \003(\tB\003\340A\002\022\020\n\010ex" + - "amples\030\005 \003(\t\022\023\n\013input_modes\030\006 \003(\t\022\024\n\014out" + - "put_modes\030\007 \003(\t\022\"\n\010security\030\010 \003(\0132\020.a2a." + - "v1.Security\"m\n\022AgentCardSignature\022\026\n\tpro" + - "tected\030\001 \001(\tB\003\340A\002\022\026\n\tsignature\030\002 \001(\tB\003\340A" + - "\002\022\'\n\006header\030\003 \001(\0132\027.google.protobuf.Stru" + - "ct\"v\n\032TaskPushNotificationConfig\022\021\n\004name" + - "\030\001 \001(\tB\003\340A\002\022E\n\030push_notification_config\030" + - "\002 \001(\0132\036.a2a.v1.PushNotificationConfigB\003\340" + - "A\002\"\032\n\nStringList\022\014\n\004list\030\001 \003(\t\"~\n\010Securi" + - "ty\022.\n\007schemes\030\001 \003(\0132\035.a2a.v1.Security.Sc" + - "hemesEntry\032B\n\014SchemesEntry\022\013\n\003key\030\001 \001(\t\022" + - "!\n\005value\030\002 \001(\0132\022.a2a.v1.StringList:\0028\001\"\361" + - "\002\n\016SecurityScheme\022?\n\027api_key_security_sc" + - "heme\030\001 \001(\0132\034.a2a.v1.APIKeySecurityScheme" + - "H\000\022C\n\031http_auth_security_scheme\030\002 \001(\0132\036." + - "a2a.v1.HTTPAuthSecuritySchemeH\000\022>\n\026oauth" + - "2_security_scheme\030\003 \001(\0132\034.a2a.v1.OAuth2S" + - "ecuritySchemeH\000\022N\n\037open_id_connect_secur" + - "ity_scheme\030\004 \001(\0132#.a2a.v1.OpenIdConnectS" + - "ecuritySchemeH\000\022?\n\024mtls_security_scheme\030" + - "\005 \001(\0132\037.a2a.v1.MutualTlsSecuritySchemeH\000" + - "B\010\n\006scheme\"U\n\024APIKeySecurityScheme\022\023\n\013de" + - "scription\030\001 \001(\t\022\025\n\010location\030\002 \001(\tB\003\340A\002\022\021" + - "\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026HTTPAuthSecuritySch" + - "eme\022\023\n\013description\030\001 \001(\t\022\023\n\006scheme\030\002 \001(\t" + - "B\003\340A\002\022\025\n\rbearer_format\030\003 \001(\t\"p\n\024OAuth2Se" + - "curityScheme\022\023\n\013description\030\001 \001(\t\022&\n\005flo" + - "ws\030\002 \001(\0132\022.a2a.v1.OAuthFlowsB\003\340A\002\022\033\n\023oau" + - "th2_metadata_url\030\003 \001(\t\"T\n\033OpenIdConnectS" + - "ecurityScheme\022\023\n\013description\030\001 \001(\t\022 \n\023op" + - "en_id_connect_url\030\002 \001(\tB\003\340A\002\".\n\027MutualTl" + - "sSecurityScheme\022\023\n\013description\030\001 \001(\t\"\330\001\n" + - "\nOAuthFlows\022@\n\022authorization_code\030\001 \001(\0132" + - "\".a2a.v1.AuthorizationCodeOAuthFlowH\000\022@\n" + - "\022client_credentials\030\002 \001(\0132\".a2a.v1.Clien" + - "tCredentialsOAuthFlowH\000\0222\n\013device_code\030\005" + - " \001(\0132\033.a2a.v1.DeviceCodeOAuthFlowH\000B\006\n\004f" + - "lowJ\004\010\003\020\004J\004\010\004\020\005\"\364\001\n\032AuthorizationCodeOAu" + - "thFlow\022\036\n\021authorization_url\030\001 \001(\tB\003\340A\002\022\026" + - "\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 " + - "\001(\t\022C\n\006scopes\030\004 \003(\0132..a2a.v1.Authorizati" + - "onCodeOAuthFlow.ScopesEntryB\003\340A\002\022\025\n\rpkce" + - "_required\030\005 \001(\010\032-\n\013ScopesEntry\022\013\n\003key\030\001 " + - "\001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\275\001\n\032ClientCredent" + - "ialsOAuthFlow\022\026\n\ttoken_url\030\001 \001(\tB\003\340A\002\022\023\n" + - "\013refresh_url\030\002 \001(\t\022C\n\006scopes\030\003 \003(\0132..a2a" + - ".v1.ClientCredentialsOAuthFlow.ScopesEnt" + - "ryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005v" + - "alue\030\002 \001(\t:\0028\001\"\326\001\n\023DeviceCodeOAuthFlow\022%" + - "\n\030device_authorization_url\030\001 \001(\tB\003\340A\002\022\026\n" + - "\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001" + - "(\t\022<\n\006scopes\030\004 \003(\0132\'.a2a.v1.DeviceCodeOA" + - "uthFlow.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022" + - "\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\257\001\n\022Send" + - "MessageRequest\022\016\n\006tenant\030\004 \001(\t\022%\n\007messag" + - "e\030\001 \001(\0132\017.a2a.v1.MessageB\003\340A\002\0227\n\rconfigu" + - "ration\030\002 \001(\0132 .a2a.v1.SendMessageConfigu" + - "ration\022)\n\010metadata\030\003 \001(\0132\027.google.protob" + - "uf.Struct\"c\n\016GetTaskRequest\022\016\n\006tenant\030\003 " + - "\001(\t\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\033\n\016history_length" + - "\030\002 \001(\005H\000\210\001\001B\021\n\017_history_length\"\265\002\n\020ListT" + - "asksRequest\022\016\n\006tenant\030\t \001(\t\022\022\n\ncontext_i" + - "d\030\001 \001(\t\022!\n\006status\030\002 \001(\0162\021.a2a.v1.TaskSta" + - "te\022\026\n\tpage_size\030\003 \001(\005H\000\210\001\001\022\022\n\npage_token" + - "\030\004 \001(\t\022\033\n\016history_length\030\005 \001(\005H\001\210\001\001\022:\n\026s" + - "tatus_timestamp_after\030\006 \001(\0132\032.google.pro" + - "tobuf.Timestamp\022\036\n\021include_artifacts\030\007 \001" + - "(\010H\002\210\001\001B\014\n\n_page_sizeB\021\n\017_history_length" + - "B\024\n\022_include_artifacts\"\204\001\n\021ListTasksResp" + - "onse\022 \n\005tasks\030\001 \003(\0132\014.a2a.v1.TaskB\003\340A\002\022\034" + - "\n\017next_page_token\030\002 \001(\tB\003\340A\002\022\026\n\tpage_siz" + - "e\030\003 \001(\005B\003\340A\002\022\027\n\ntotal_size\030\004 \001(\005B\003\340A\002\"1\n" + - "\021CancelTaskRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004na" + - "me\030\001 \001(\t\"D\n$GetTaskPushNotificationConfi" + - "gRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"G" + - "\n\'DeleteTaskPushNotificationConfigReques" + - "t\022\016\n\006tenant\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"\234\001\n$SetT" + - "askPushNotificationConfigRequest\022\016\n\006tena" + - "nt\030\004 \001(\t\022\023\n\006parent\030\001 \001(\tB\003\340A\002\022\026\n\tconfig_" + - "id\030\002 \001(\tB\003\340A\002\0227\n\006config\030\003 \001(\0132\".a2a.v1.T" + - "askPushNotificationConfigB\003\340A\002\"6\n\026Subscr" + - "ibeToTaskRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004name" + - "\030\001 \001(\t\"n\n%ListTaskPushNotificationConfig" + - "Request\022\016\n\006tenant\030\004 \001(\t\022\016\n\006parent\030\001 \001(\t\022" + - "\021\n\tpage_size\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t\"-" + - "\n\033GetExtendedAgentCardRequest\022\016\n\006tenant\030" + - "\001 \001(\t\"b\n\023SendMessageResponse\022\034\n\004task\030\001 \001" + - "(\0132\014.a2a.v1.TaskH\000\022\"\n\007message\030\002 \001(\0132\017.a2" + - "a.v1.MessageH\000B\t\n\007payload\"\321\001\n\016StreamResp" + - "onse\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022\"\n\007me" + - "ssage\030\002 \001(\0132\017.a2a.v1.MessageH\000\0226\n\rstatus" + - "_update\030\003 \001(\0132\035.a2a.v1.TaskStatusUpdateE" + - "ventH\000\022:\n\017artifact_update\030\004 \001(\0132\037.a2a.v1" + - ".TaskArtifactUpdateEventH\000B\t\n\007payload\"v\n" + - "&ListTaskPushNotificationConfigResponse\022" + - "3\n\007configs\030\001 \003(\0132\".a2a.v1.TaskPushNotifi" + - "cationConfig\022\027\n\017next_page_token\030\002 \001(\t*\372\001" + - "\n\tTaskState\022\032\n\026TASK_STATE_UNSPECIFIED\020\000\022" + - "\030\n\024TASK_STATE_SUBMITTED\020\001\022\026\n\022TASK_STATE_" + - "WORKING\020\002\022\030\n\024TASK_STATE_COMPLETED\020\003\022\025\n\021T" + - "ASK_STATE_FAILED\020\004\022\030\n\024TASK_STATE_CANCELL" + - "ED\020\005\022\035\n\031TASK_STATE_INPUT_REQUIRED\020\006\022\027\n\023T" + - "ASK_STATE_REJECTED\020\007\022\034\n\030TASK_STATE_AUTH_" + - "REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE_UNSPECIFIED\020\000" + - "\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AGENT\020\0022\276\016\n\nA2AS" + - "ervice\022}\n\013SendMessage\022\032.a2a.v1.SendMessa" + - "geRequest\032\033.a2a.v1.SendMessageResponse\"5" + - "\202\323\344\223\002/\"\r/message:send:\001*Z\033\"\026/{tenant}/me" + - "ssage:send:\001*\022\207\001\n\024SendStreamingMessage\022\032" + - ".a2a.v1.SendMessageRequest\032\026.a2a.v1.Stre" + - "amResponse\"9\202\323\344\223\0023\"\017/message:stream:\001*Z\035" + - "\"\030/{tenant}/message:stream:\001*0\001\022k\n\007GetTa" + - "sk\022\026.a2a.v1.GetTaskRequest\032\014.a2a.v1.Task" + - "\":\332A\004name\202\323\344\223\002-\022\017/{name=tasks/*}Z\032\022\030/{te" + - "nant}/{name=tasks/*}\022c\n\tListTasks\022\030.a2a." + - "v1.ListTasksRequest\032\031.a2a.v1.ListTasksRe" + - "sponse\"!\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tenant}/task" + - "s\022~\n\nCancelTask\022\031.a2a.v1.CancelTaskReque" + - "st\032\014.a2a.v1.Task\"G\202\323\344\223\002A\"\026/{name=tasks/*" + - "}:cancel:\001*Z$\"\037/{tenant}/{name=tasks/*}:" + - "cancel:\001*\022\224\001\n\017SubscribeToTask\022\036.a2a.v1.S" + - "ubscribeToTaskRequest\032\026.a2a.v1.StreamRes" + - "ponse\"G\202\323\344\223\002A\022\031/{name=tasks/*}:subscribe" + - "Z$\022\"/{tenant}/{name=tasks/*}:subscribe0\001" + - "\022\373\001\n\035SetTaskPushNotificationConfig\022,.a2a" + - ".v1.SetTaskPushNotificationConfigRequest" + - "\032\".a2a.v1.TaskPushNotificationConfig\"\207\001\332" + - "A\rparent,config\202\323\344\223\002q\")/{parent=tasks/*/" + - "pushNotificationConfigs}:\006configZ<\"2/{te" + - "nant}/{parent=tasks/*/pushNotificationCo" + - "nfigs}:\006config\022\341\001\n\035GetTaskPushNotificati" + - "onConfig\022,.a2a.v1.GetTaskPushNotificatio" + - "nConfigRequest\032\".a2a.v1.TaskPushNotifica" + - "tionConfig\"n\332A\004name\202\323\344\223\002a\022)/{name=tasks/" + - "*/pushNotificationConfigs/*}Z4\0222/{tenant" + - "}/{name=tasks/*/pushNotificationConfigs/" + - "*}\022\361\001\n\036ListTaskPushNotificationConfig\022-." + - "a2a.v1.ListTaskPushNotificationConfigReq" + - "uest\032..a2a.v1.ListTaskPushNotificationCo" + - "nfigResponse\"p\332A\006parent\202\323\344\223\002a\022)/{parent=" + - "tasks/*}/pushNotificationConfigsZ4\0222/{te" + - "nant}/{parent=tasks/*}/pushNotificationC" + - "onfigs\022\211\001\n\024GetExtendedAgentCard\022#.a2a.v1" + - ".GetExtendedAgentCardRequest\032\021.a2a.v1.Ag" + - "entCard\"9\202\323\344\223\0023\022\022/extendedAgentCardZ\035\022\033/" + - "{tenant}/extendedAgentCard\022\333\001\n DeleteTas" + - "kPushNotificationConfig\022/.a2a.v1.DeleteT" + - "askPushNotificationConfigRequest\032\026.googl" + - "e.protobuf.Empty\"n\332A\004name\202\323\344\223\002a*)/{name=" + - "tasks/*/pushNotificationConfigs/*}Z4*2/{" + - "tenant}/{name=tasks/*/pushNotificationCo" + - "nfigs/*}B7\n\013io.a2a.grpcB\003A2AP\001Z\030google.g" + - "olang.org/a2a/v1\252\002\006A2a.V1b\006proto3" + "2\026.a2a.v1.AgentExtension\022 \n\023extended_age" + + "nt_card\030\005 \001(\010H\002\210\001\001B\014\n\n_streamingB\025\n\023_pus" + + "h_notificationsB\026\n\024_extended_agent_cardJ" + + "\004\010\004\020\005\"m\n\016AgentExtension\022\013\n\003uri\030\001 \001(\t\022\023\n\013" + + "description\030\002 \001(\t\022\020\n\010required\030\003 \001(\010\022\'\n\006p" + + "arams\030\004 \001(\0132\027.google.protobuf.Struct\"\276\001\n" + + "\nAgentSkill\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\021\n\004name\030\002 \001" + + "(\tB\003\340A\002\022\030\n\013description\030\003 \001(\tB\003\340A\002\022\021\n\004tag" + + "s\030\004 \003(\tB\003\340A\002\022\020\n\010examples\030\005 \003(\t\022\023\n\013input_" + + "modes\030\006 \003(\t\022\024\n\014output_modes\030\007 \003(\t\022\"\n\010sec" + + "urity\030\010 \003(\0132\020.a2a.v1.Security\"m\n\022AgentCa" + + "rdSignature\022\026\n\tprotected\030\001 \001(\tB\003\340A\002\022\026\n\ts" + + "ignature\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\0132\027.go" + + "ogle.protobuf.Struct\"v\n\032TaskPushNotifica" + + "tionConfig\022\021\n\004name\030\001 \001(\tB\003\340A\002\022E\n\030push_no" + + "tification_config\030\002 \001(\0132\036.a2a.v1.PushNot" + + "ificationConfigB\003\340A\002\"\032\n\nStringList\022\014\n\004li" + + "st\030\001 \003(\t\"~\n\010Security\022.\n\007schemes\030\001 \003(\0132\035." + + "a2a.v1.Security.SchemesEntry\032B\n\014SchemesE" + + "ntry\022\013\n\003key\030\001 \001(\t\022!\n\005value\030\002 \001(\0132\022.a2a.v" + + "1.StringList:\0028\001\"\361\002\n\016SecurityScheme\022?\n\027a" + + "pi_key_security_scheme\030\001 \001(\0132\034.a2a.v1.AP" + + "IKeySecuritySchemeH\000\022C\n\031http_auth_securi" + + "ty_scheme\030\002 \001(\0132\036.a2a.v1.HTTPAuthSecurit" + + "ySchemeH\000\022>\n\026oauth2_security_scheme\030\003 \001(" + + "\0132\034.a2a.v1.OAuth2SecuritySchemeH\000\022N\n\037ope" + + "n_id_connect_security_scheme\030\004 \001(\0132#.a2a" + + ".v1.OpenIdConnectSecuritySchemeH\000\022?\n\024mtl" + + "s_security_scheme\030\005 \001(\0132\037.a2a.v1.MutualT" + + "lsSecuritySchemeH\000B\010\n\006scheme\"U\n\024APIKeySe" + + "curityScheme\022\023\n\013description\030\001 \001(\t\022\025\n\010loc" + + "ation\030\002 \001(\tB\003\340A\002\022\021\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026H" + + "TTPAuthSecurityScheme\022\023\n\013description\030\001 \001" + + "(\t\022\023\n\006scheme\030\002 \001(\tB\003\340A\002\022\025\n\rbearer_format" + + "\030\003 \001(\t\"p\n\024OAuth2SecurityScheme\022\023\n\013descri" + + "ption\030\001 \001(\t\022&\n\005flows\030\002 \001(\0132\022.a2a.v1.OAut" + + "hFlowsB\003\340A\002\022\033\n\023oauth2_metadata_url\030\003 \001(\t" + + "\"T\n\033OpenIdConnectSecurityScheme\022\023\n\013descr" + + "iption\030\001 \001(\t\022 \n\023open_id_connect_url\030\002 \001(" + + "\tB\003\340A\002\".\n\027MutualTlsSecurityScheme\022\023\n\013des" + + "cription\030\001 \001(\t\"\330\001\n\nOAuthFlows\022@\n\022authori" + + "zation_code\030\001 \001(\0132\".a2a.v1.Authorization" + + "CodeOAuthFlowH\000\022@\n\022client_credentials\030\002 " + + "\001(\0132\".a2a.v1.ClientCredentialsOAuthFlowH" + + "\000\0222\n\013device_code\030\005 \001(\0132\033.a2a.v1.DeviceCo" + + "deOAuthFlowH\000B\006\n\004flowJ\004\010\003\020\004J\004\010\004\020\005\"\364\001\n\032Au" + + "thorizationCodeOAuthFlow\022\036\n\021authorizatio" + + "n_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002" + + "\022\023\n\013refresh_url\030\003 \001(\t\022C\n\006scopes\030\004 \003(\0132.." + + "a2a.v1.AuthorizationCodeOAuthFlow.Scopes" + + "EntryB\003\340A\002\022\025\n\rpkce_required\030\005 \001(\010\032-\n\013Sco" + + "pesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001" + + "\"\275\001\n\032ClientCredentialsOAuthFlow\022\026\n\ttoken" + + "_url\030\001 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022C\n\006" + + "scopes\030\003 \003(\0132..a2a.v1.ClientCredentialsO" + + "AuthFlow.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry" + + "\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\326\001\n\023Dev" + + "iceCodeOAuthFlow\022%\n\030device_authorization" + + "_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022" + + "\023\n\013refresh_url\030\003 \001(\t\022<\n\006scopes\030\004 \003(\0132\'.a" + + "2a.v1.DeviceCodeOAuthFlow.ScopesEntryB\003\340" + + "A\002\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030" + + "\002 \001(\t:\0028\001\"\257\001\n\022SendMessageRequest\022\016\n\006tena" + + "nt\030\004 \001(\t\022%\n\007message\030\001 \001(\0132\017.a2a.v1.Messa" + + "geB\003\340A\002\0227\n\rconfiguration\030\002 \001(\0132 .a2a.v1." + + "SendMessageConfiguration\022)\n\010metadata\030\003 \001" + + "(\0132\027.google.protobuf.Struct\"c\n\016GetTaskRe" + + "quest\022\016\n\006tenant\030\003 \001(\t\022\021\n\004name\030\001 \001(\tB\003\340A\002" + + "\022\033\n\016history_length\030\002 \001(\005H\000\210\001\001B\021\n\017_histor" + + "y_length\"\265\002\n\020ListTasksRequest\022\016\n\006tenant\030" + + "\t \001(\t\022\022\n\ncontext_id\030\001 \001(\t\022!\n\006status\030\002 \001(" + + "\0162\021.a2a.v1.TaskState\022\026\n\tpage_size\030\003 \001(\005H" + + "\000\210\001\001\022\022\n\npage_token\030\004 \001(\t\022\033\n\016history_leng" + + "th\030\005 \001(\005H\001\210\001\001\022:\n\026status_timestamp_after\030" + + "\006 \001(\0132\032.google.protobuf.Timestamp\022\036\n\021inc" + + "lude_artifacts\030\007 \001(\010H\002\210\001\001B\014\n\n_page_sizeB" + + "\021\n\017_history_lengthB\024\n\022_include_artifacts" + + "\"\204\001\n\021ListTasksResponse\022 \n\005tasks\030\001 \003(\0132\014." + + "a2a.v1.TaskB\003\340A\002\022\034\n\017next_page_token\030\002 \001(" + + "\tB\003\340A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022\027\n\ntotal_" + + "size\030\004 \001(\005B\003\340A\002\"1\n\021CancelTaskRequest\022\016\n\006" + + "tenant\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"D\n$GetTaskPus" + + "hNotificationConfigRequest\022\016\n\006tenant\030\002 \001" + + "(\t\022\014\n\004name\030\001 \001(\t\"G\n\'DeleteTaskPushNotifi" + + "cationConfigRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004n" + + "ame\030\001 \001(\t\"\237\001\n\'CreateTaskPushNotification" + + "ConfigRequest\022\016\n\006tenant\030\004 \001(\t\022\023\n\006parent\030" + + "\001 \001(\tB\003\340A\002\022\026\n\tconfig_id\030\002 \001(\tB\003\340A\002\0227\n\006co" + + "nfig\030\003 \001(\0132\".a2a.v1.TaskPushNotification" + + "ConfigB\003\340A\002\"6\n\026SubscribeToTaskRequest\022\016\n" + + "\006tenant\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"n\n%ListTaskP" + + "ushNotificationConfigRequest\022\016\n\006tenant\030\004" + + " \001(\t\022\016\n\006parent\030\001 \001(\t\022\021\n\tpage_size\030\002 \001(\005\022" + + "\022\n\npage_token\030\003 \001(\t\"-\n\033GetExtendedAgentC" + + "ardRequest\022\016\n\006tenant\030\001 \001(\t\"b\n\023SendMessag" + + "eResponse\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022" + + "\"\n\007message\030\002 \001(\0132\017.a2a.v1.MessageH\000B\t\n\007p" + + "ayload\"\321\001\n\016StreamResponse\022\034\n\004task\030\001 \001(\0132" + + "\014.a2a.v1.TaskH\000\022\"\n\007message\030\002 \001(\0132\017.a2a.v" + + "1.MessageH\000\0226\n\rstatus_update\030\003 \001(\0132\035.a2a" + + ".v1.TaskStatusUpdateEventH\000\022:\n\017artifact_" + + "update\030\004 \001(\0132\037.a2a.v1.TaskArtifactUpdate" + + "EventH\000B\t\n\007payload\"v\n&ListTaskPushNotifi" + + "cationConfigResponse\0223\n\007configs\030\001 \003(\0132\"." + + "a2a.v1.TaskPushNotificationConfig\022\027\n\017nex" + + "t_page_token\030\002 \001(\t*\372\001\n\tTaskState\022\032\n\026TASK" + + "_STATE_UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMI" + + "TTED\020\001\022\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_S" + + "TATE_COMPLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022" + + "\030\n\024TASK_STATE_CANCELLED\020\005\022\035\n\031TASK_STATE_" + + "INPUT_REQUIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020" + + "\007\022\034\n\030TASK_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022" + + "\024\n\020ROLE_UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\n" + + "ROLE_AGENT\020\0022\304\016\n\nA2AService\022}\n\013SendMessa" + + "ge\022\032.a2a.v1.SendMessageRequest\032\033.a2a.v1." + + "SendMessageResponse\"5\202\323\344\223\002/\"\r/message:se" + + "nd:\001*Z\033\"\026/{tenant}/message:send:\001*\022\207\001\n\024S" + + "endStreamingMessage\022\032.a2a.v1.SendMessage" + + "Request\032\026.a2a.v1.StreamResponse\"9\202\323\344\223\0023\"" + + "\017/message:stream:\001*Z\035\"\030/{tenant}/message" + + ":stream:\001*0\001\022k\n\007GetTask\022\026.a2a.v1.GetTask" + + "Request\032\014.a2a.v1.Task\":\332A\004name\202\323\344\223\002-\022\017/{" + + "name=tasks/*}Z\032\022\030/{tenant}/{name=tasks/*" + + "}\022c\n\tListTasks\022\030.a2a.v1.ListTasksRequest" + + "\032\031.a2a.v1.ListTasksResponse\"!\202\323\344\223\002\033\022\006/ta" + + "sksZ\021\022\017/{tenant}/tasks\022~\n\nCancelTask\022\031.a" + + "2a.v1.CancelTaskRequest\032\014.a2a.v1.Task\"G\202" + + "\323\344\223\002A\"\026/{name=tasks/*}:cancel:\001*Z$\"\037/{te" + + "nant}/{name=tasks/*}:cancel:\001*\022\224\001\n\017Subsc" + + "ribeToTask\022\036.a2a.v1.SubscribeToTaskReque" + + "st\032\026.a2a.v1.StreamResponse\"G\202\323\344\223\002A\022\031/{na" + + "me=tasks/*}:subscribeZ$\022\"/{tenant}/{name" + + "=tasks/*}:subscribe0\001\022\201\002\n CreateTaskPush" + + "NotificationConfig\022/.a2a.v1.CreateTaskPu" + + "shNotificationConfigRequest\032\".a2a.v1.Tas" + + "kPushNotificationConfig\"\207\001\332A\rparent,conf" + + "ig\202\323\344\223\002q\")/{parent=tasks/*/pushNotificat" + + "ionConfigs}:\006configZ<\"2/{tenant}/{parent" + + "=tasks/*/pushNotificationConfigs}:\006confi" + + "g\022\341\001\n\035GetTaskPushNotificationConfig\022,.a2" + + "a.v1.GetTaskPushNotificationConfigReques" + + "t\032\".a2a.v1.TaskPushNotificationConfig\"n\332" + + "A\004name\202\323\344\223\002a\022)/{name=tasks/*/pushNotific" + + "ationConfigs/*}Z4\0222/{tenant}/{name=tasks" + + "/*/pushNotificationConfigs/*}\022\361\001\n\036ListTa" + + "skPushNotificationConfig\022-.a2a.v1.ListTa" + + "skPushNotificationConfigRequest\032..a2a.v1" + + ".ListTaskPushNotificationConfigResponse\"" + + "p\332A\006parent\202\323\344\223\002a\022)/{parent=tasks/*}/push" + + "NotificationConfigsZ4\0222/{tenant}/{parent" + + "=tasks/*}/pushNotificationConfigs\022\211\001\n\024Ge" + + "tExtendedAgentCard\022#.a2a.v1.GetExtendedA" + + "gentCardRequest\032\021.a2a.v1.AgentCard\"9\202\323\344\223" + + "\0023\022\022/extendedAgentCardZ\035\022\033/{tenant}/exte" + + "ndedAgentCard\022\333\001\n DeleteTaskPushNotifica" + + "tionConfig\022/.a2a.v1.DeleteTaskPushNotifi" + + "cationConfigRequest\032\026.google.protobuf.Em" + + "pty\"n\332A\004name\202\323\344\223\002a*)/{name=tasks/*/pushN" + + "otificationConfigs/*}Z4*2/{tenant}/{name" + + "=tasks/*/pushNotificationConfigs/*}B7\n\013i" + + "o.a2a.grpcB\003A2AP\001Z\030google.golang.org/a2a" + + "/v1\252\002\006A2a.V1b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -639,7 +638,7 @@ public static void registerAllExtensions( internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentCapabilities_descriptor, - new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", "StateTransitionHistory", "ExtendedAgentCard", }); + new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", "ExtendedAgentCard", }); internal_static_a2a_v1_AgentExtension_descriptor = getDescriptor().getMessageType(16); internal_static_a2a_v1_AgentExtension_fieldAccessorTable = new @@ -802,11 +801,11 @@ public static void registerAllExtensions( com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "Name", }); - internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_descriptor = + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor = getDescriptor().getMessageType(39); - internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_fieldAccessorTable = new + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_descriptor, + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "Parent", "ConfigId", "Config", }); internal_static_a2a_v1_SubscribeToTaskRequest_descriptor = getDescriptor().getMessageType(40); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java index 0faa8f73d..522c9083b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java @@ -201,35 +201,35 @@ io.a2a.grpc.StreamResponse> getSubscribeToTaskMethod() { return getSubscribeToTaskMethod; } - private static volatile io.grpc.MethodDescriptor getSetTaskPushNotificationConfigMethod; + private static volatile io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "SetTaskPushNotificationConfig", - requestType = io.a2a.grpc.SetTaskPushNotificationConfigRequest.class, + fullMethodName = SERVICE_NAME + '/' + "CreateTaskPushNotificationConfig", + requestType = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, responseType = io.a2a.grpc.TaskPushNotificationConfig.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getSetTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getSetTaskPushNotificationConfigMethod; - if ((getSetTaskPushNotificationConfigMethod = A2AServiceGrpc.getSetTaskPushNotificationConfigMethod) == null) { + public static io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod() { + io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; + if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { synchronized (A2AServiceGrpc.class) { - if ((getSetTaskPushNotificationConfigMethod = A2AServiceGrpc.getSetTaskPushNotificationConfigMethod) == null) { - A2AServiceGrpc.getSetTaskPushNotificationConfigMethod = getSetTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() + if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { + A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod = getCreateTaskPushNotificationConfigMethod = + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SetTaskPushNotificationConfig")) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "CreateTaskPushNotificationConfig")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SetTaskPushNotificationConfigRequest.getDefaultInstance())) + io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SetTaskPushNotificationConfig")) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("CreateTaskPushNotificationConfig")) .build(); } } } - return getSetTaskPushNotificationConfigMethod; + return getCreateTaskPushNotificationConfigMethod; } private static volatile io.grpc.MethodDescriptor - * Set a push notification config for a task. + * Create a push notification config for a task. * */ - default void setTaskPushNotificationConfig(io.a2a.grpc.SetTaskPushNotificationConfigRequest request, + default void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSetTaskPushNotificationConfigMethod(), responseObserver); + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCreateTaskPushNotificationConfigMethod(), responseObserver); } /** @@ -636,13 +636,13 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, /** *

    -     * Set a push notification config for a task.
    +     * Create a push notification config for a task.
          * 
    */ - public void setTaskPushNotificationConfig(io.a2a.grpc.SetTaskPushNotificationConfigRequest request, + public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getSetTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); + getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); } /** @@ -776,12 +776,12 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws /** *
    -     * Set a push notification config for a task.
    +     * Create a push notification config for a task.
          * 
    */ - public io.a2a.grpc.TaskPushNotificationConfig setTaskPushNotificationConfig(io.a2a.grpc.SetTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getSetTaskPushNotificationConfigMethod(), getCallOptions(), request); + getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); } /** @@ -909,12 +909,12 @@ public java.util.Iterator subscribeToTask( /** *
    -     * Set a push notification config for a task.
    +     * Create a push notification config for a task.
          * 
    */ - public io.a2a.grpc.TaskPushNotificationConfig setTaskPushNotificationConfig(io.a2a.grpc.SetTaskPushNotificationConfigRequest request) { + public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getSetTaskPushNotificationConfigMethod(), getCallOptions(), request); + getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); } /** @@ -1023,13 +1023,13 @@ public com.google.common.util.concurrent.ListenableFuture canc /** *
    -     * Set a push notification config for a task.
    +     * Create a push notification config for a task.
          * 
    */ - public com.google.common.util.concurrent.ListenableFuture setTaskPushNotificationConfig( - io.a2a.grpc.SetTaskPushNotificationConfigRequest request) { + public com.google.common.util.concurrent.ListenableFuture createTaskPushNotificationConfig( + io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getSetTaskPushNotificationConfigMethod(), getCallOptions()), request); + getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request); } /** @@ -1083,7 +1083,7 @@ public com.google.common.util.concurrent.ListenableFuture responseObserv serviceImpl.subscribeToTask((io.a2a.grpc.SubscribeToTaskRequest) request, (io.grpc.stub.StreamObserver) responseObserver); break; - case METHODID_SET_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.setTaskPushNotificationConfig((io.a2a.grpc.SetTaskPushNotificationConfigRequest) request, + case METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG: + serviceImpl.createTaskPushNotificationConfig((io.a2a.grpc.CreateTaskPushNotificationConfigRequest) request, (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG: @@ -1211,12 +1211,12 @@ public static final io.grpc.ServerServiceDefinition bindService(AsyncService ser io.a2a.grpc.StreamResponse>( service, METHODID_SUBSCRIBE_TO_TASK))) .addMethod( - getSetTaskPushNotificationConfigMethod(), + getCreateTaskPushNotificationConfigMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.SetTaskPushNotificationConfigRequest, + io.a2a.grpc.CreateTaskPushNotificationConfigRequest, io.a2a.grpc.TaskPushNotificationConfig>( - service, METHODID_SET_TASK_PUSH_NOTIFICATION_CONFIG))) + service, METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG))) .addMethod( getGetTaskPushNotificationConfigMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( @@ -1299,7 +1299,7 @@ public static io.grpc.ServiceDescriptor getServiceDescriptor() { .addMethod(getListTasksMethod()) .addMethod(getCancelTaskMethod()) .addMethod(getSubscribeToTaskMethod()) - .addMethod(getSetTaskPushNotificationConfigMethod()) + .addMethod(getCreateTaskPushNotificationConfigMethod()) .addMethod(getGetTaskPushNotificationConfigMethod()) .addMethod(getListTaskPushNotificationConfigMethod()) .addMethod(getGetExtendedAgentCardMethod()) diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java index 2e6c44ab8..84796af69 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java @@ -165,33 +165,6 @@ public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( return extensions_.get(index); } - public static final int STATE_TRANSITION_HISTORY_FIELD_NUMBER = 4; - private boolean stateTransitionHistory_ = false; - /** - *
    -   * Indicates if the agent provides a history of state transitions for a task.
    -   * 
    - * - * optional bool state_transition_history = 4; - * @return Whether the stateTransitionHistory field is set. - */ - @java.lang.Override - public boolean hasStateTransitionHistory() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
    -   * Indicates if the agent provides a history of state transitions for a task.
    -   * 
    - * - * optional bool state_transition_history = 4; - * @return The stateTransitionHistory. - */ - @java.lang.Override - public boolean getStateTransitionHistory() { - return stateTransitionHistory_; - } - public static final int EXTENDED_AGENT_CARD_FIELD_NUMBER = 5; private boolean extendedAgentCard_ = false; /** @@ -204,7 +177,7 @@ public boolean getStateTransitionHistory() { */ @java.lang.Override public boolean hasExtendedAgentCard() { - return ((bitField0_ & 0x00000008) != 0); + return ((bitField0_ & 0x00000004) != 0); } /** *
    @@ -243,9 +216,6 @@ public void writeTo(com.google.protobuf.CodedOutputStream output)
           output.writeMessage(3, extensions_.get(i));
         }
         if (((bitField0_ & 0x00000004) != 0)) {
    -      output.writeBool(4, stateTransitionHistory_);
    -    }
    -    if (((bitField0_ & 0x00000008) != 0)) {
           output.writeBool(5, extendedAgentCard_);
         }
         getUnknownFields().writeTo(output);
    @@ -270,10 +240,6 @@ public int getSerializedSize() {
             .computeMessageSize(3, extensions_.get(i));
         }
         if (((bitField0_ & 0x00000004) != 0)) {
    -      size += com.google.protobuf.CodedOutputStream
    -        .computeBoolSize(4, stateTransitionHistory_);
    -    }
    -    if (((bitField0_ & 0x00000008) != 0)) {
           size += com.google.protobuf.CodedOutputStream
             .computeBoolSize(5, extendedAgentCard_);
         }
    @@ -304,11 +270,6 @@ public boolean equals(final java.lang.Object obj) {
         }
         if (!getExtensionsList()
             .equals(other.getExtensionsList())) return false;
    -    if (hasStateTransitionHistory() != other.hasStateTransitionHistory()) return false;
    -    if (hasStateTransitionHistory()) {
    -      if (getStateTransitionHistory()
    -          != other.getStateTransitionHistory()) return false;
    -    }
         if (hasExtendedAgentCard() != other.hasExtendedAgentCard()) return false;
         if (hasExtendedAgentCard()) {
           if (getExtendedAgentCard()
    @@ -339,11 +300,6 @@ public int hashCode() {
           hash = (37 * hash) + EXTENSIONS_FIELD_NUMBER;
           hash = (53 * hash) + getExtensionsList().hashCode();
         }
    -    if (hasStateTransitionHistory()) {
    -      hash = (37 * hash) + STATE_TRANSITION_HISTORY_FIELD_NUMBER;
    -      hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
    -          getStateTransitionHistory());
    -    }
         if (hasExtendedAgentCard()) {
           hash = (37 * hash) + EXTENDED_AGENT_CARD_FIELD_NUMBER;
           hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
    @@ -494,7 +450,6 @@ public Builder clear() {
             extensionsBuilder_.clear();
           }
           bitField0_ = (bitField0_ & ~0x00000004);
    -      stateTransitionHistory_ = false;
           extendedAgentCard_ = false;
           return this;
         }
    @@ -552,12 +507,8 @@ private void buildPartial0(io.a2a.grpc.AgentCapabilities result) {
             to_bitField0_ |= 0x00000002;
           }
           if (((from_bitField0_ & 0x00000008) != 0)) {
    -        result.stateTransitionHistory_ = stateTransitionHistory_;
    -        to_bitField0_ |= 0x00000004;
    -      }
    -      if (((from_bitField0_ & 0x00000010) != 0)) {
             result.extendedAgentCard_ = extendedAgentCard_;
    -        to_bitField0_ |= 0x00000008;
    +        to_bitField0_ |= 0x00000004;
           }
           result.bitField0_ |= to_bitField0_;
         }
    @@ -606,9 +557,6 @@ public Builder mergeFrom(io.a2a.grpc.AgentCapabilities other) {
               }
             }
           }
    -      if (other.hasStateTransitionHistory()) {
    -        setStateTransitionHistory(other.getStateTransitionHistory());
    -      }
           if (other.hasExtendedAgentCard()) {
             setExtendedAgentCard(other.getExtendedAgentCard());
           }
    @@ -661,14 +609,9 @@ public Builder mergeFrom(
                   }
                   break;
                 } // case 26
    -            case 32: {
    -              stateTransitionHistory_ = input.readBool();
    -              bitField0_ |= 0x00000008;
    -              break;
    -            } // case 32
                 case 40: {
                   extendedAgentCard_ = input.readBool();
    -              bitField0_ |= 0x00000010;
    +              bitField0_ |= 0x00000008;
                   break;
                 } // case 40
                 default: {
    @@ -1112,62 +1055,6 @@ public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder(
           return extensionsBuilder_;
         }
     
    -    private boolean stateTransitionHistory_ ;
    -    /**
    -     * 
    -     * Indicates if the agent provides a history of state transitions for a task.
    -     * 
    - * - * optional bool state_transition_history = 4; - * @return Whether the stateTransitionHistory field is set. - */ - @java.lang.Override - public boolean hasStateTransitionHistory() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
    -     * Indicates if the agent provides a history of state transitions for a task.
    -     * 
    - * - * optional bool state_transition_history = 4; - * @return The stateTransitionHistory. - */ - @java.lang.Override - public boolean getStateTransitionHistory() { - return stateTransitionHistory_; - } - /** - *
    -     * Indicates if the agent provides a history of state transitions for a task.
    -     * 
    - * - * optional bool state_transition_history = 4; - * @param value The stateTransitionHistory to set. - * @return This builder for chaining. - */ - public Builder setStateTransitionHistory(boolean value) { - - stateTransitionHistory_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
    -     * Indicates if the agent provides a history of state transitions for a task.
    -     * 
    - * - * optional bool state_transition_history = 4; - * @return This builder for chaining. - */ - public Builder clearStateTransitionHistory() { - bitField0_ = (bitField0_ & ~0x00000008); - stateTransitionHistory_ = false; - onChanged(); - return this; - } - private boolean extendedAgentCard_ ; /** *
    @@ -1179,7 +1066,7 @@ public Builder clearStateTransitionHistory() {
          */
         @java.lang.Override
         public boolean hasExtendedAgentCard() {
    -      return ((bitField0_ & 0x00000010) != 0);
    +      return ((bitField0_ & 0x00000008) != 0);
         }
         /**
          * 
    @@ -1205,7 +1092,7 @@ public boolean getExtendedAgentCard() {
         public Builder setExtendedAgentCard(boolean value) {
     
           extendedAgentCard_ = value;
    -      bitField0_ |= 0x00000010;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return this;
         }
    @@ -1218,7 +1105,7 @@ public Builder setExtendedAgentCard(boolean value) {
          * @return This builder for chaining.
          */
         public Builder clearExtendedAgentCard() {
    -      bitField0_ = (bitField0_ & ~0x00000010);
    +      bitField0_ = (bitField0_ & ~0x00000008);
           extendedAgentCard_ = false;
           onChanged();
           return this;
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java
    index b084db7ee..05c90e4d2 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java
    @@ -92,25 +92,6 @@ public interface AgentCapabilitiesOrBuilder extends
       io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
           int index);
     
    -  /**
    -   * 
    -   * Indicates if the agent provides a history of state transitions for a task.
    -   * 
    - * - * optional bool state_transition_history = 4; - * @return Whether the stateTransitionHistory field is set. - */ - boolean hasStateTransitionHistory(); - /** - *
    -   * Indicates if the agent provides a history of state transitions for a task.
    -   * 
    - * - * optional bool state_transition_history = 4; - * @return The stateTransitionHistory. - */ - boolean getStateTransitionHistory(); - /** *
        * Indicates if the agent supports providing an extended agent card when authenticated.
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java
    index 9ba0ba831..cb1e12880 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java
    @@ -8,7 +8,7 @@
     /**
      * 
      * --8<-- [start:CancelTaskRequest]
    - * Represents a request for the `tasks/cancel` method.
    + * Represents a request for the `CancelTask` method.
      * 
    * * Protobuf type {@code a2a.v1.CancelTaskRequest} @@ -315,7 +315,7 @@ protected Builder newBuilderForType( /** *
        * --8<-- [start:CancelTaskRequest]
    -   * Represents a request for the `tasks/cancel` method.
    +   * Represents a request for the `CancelTask` method.
        * 
    * * Protobuf type {@code a2a.v1.CancelTaskRequest} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SetTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java similarity index 85% rename from spec-grpc/src/main/java/io/a2a/grpc/SetTaskPushNotificationConfigRequest.java rename to spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java index 161a1b257..5f8143cb3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SetTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java @@ -7,17 +7,17 @@ /** *
    - * --8<-- [start:SetTaskPushNotificationConfigRequest]
    - * Represents a request for the `tasks/pushNotificationConfig/set` method.
    + * --8<-- [start:CreateTaskPushNotificationConfigRequest]
    + * Represents a request for the `CreateTaskPushNotificationConfig` method.
      * 
    * - * Protobuf type {@code a2a.v1.SetTaskPushNotificationConfigRequest} + * Protobuf type {@code a2a.v1.CreateTaskPushNotificationConfigRequest} */ @com.google.protobuf.Generated -public final class SetTaskPushNotificationConfigRequest extends +public final class CreateTaskPushNotificationConfigRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SetTaskPushNotificationConfigRequest) - SetTaskPushNotificationConfigRequestOrBuilder { + // @@protoc_insertion_point(message_implements:a2a.v1.CreateTaskPushNotificationConfigRequest) + CreateTaskPushNotificationConfigRequestOrBuilder { private static final long serialVersionUID = 0L; static { com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( @@ -26,13 +26,13 @@ public final class SetTaskPushNotificationConfigRequest extends /* minor= */ 33, /* patch= */ 1, /* suffix= */ "", - "SetTaskPushNotificationConfigRequest"); + "CreateTaskPushNotificationConfigRequest"); } - // Use SetTaskPushNotificationConfigRequest.newBuilder() to construct. - private SetTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + // Use CreateTaskPushNotificationConfigRequest.newBuilder() to construct. + private CreateTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); } - private SetTaskPushNotificationConfigRequest() { + private CreateTaskPushNotificationConfigRequest() { tenant_ = ""; parent_ = ""; configId_ = ""; @@ -40,15 +40,15 @@ private SetTaskPushNotificationConfigRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.SetTaskPushNotificationConfigRequest.class, io.a2a.grpc.SetTaskPushNotificationConfigRequest.Builder.class); + io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); } private int bitField0_; @@ -291,10 +291,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.a2a.grpc.SetTaskPushNotificationConfigRequest)) { + if (!(obj instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest)) { return super.equals(obj); } - io.a2a.grpc.SetTaskPushNotificationConfigRequest other = (io.a2a.grpc.SetTaskPushNotificationConfigRequest) obj; + io.a2a.grpc.CreateTaskPushNotificationConfigRequest other = (io.a2a.grpc.CreateTaskPushNotificationConfigRequest) obj; if (!getTenant() .equals(other.getTenant())) return false; @@ -333,44 +333,44 @@ public int hashCode() { return hash; } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom(byte[] data) + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -378,26 +378,26 @@ public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseDelimitedFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -410,7 +410,7 @@ public static io.a2a.grpc.SetTaskPushNotificationConfigRequest parseFrom( public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.a2a.grpc.SetTaskPushNotificationConfigRequest prototype) { + public static Builder newBuilder(io.a2a.grpc.CreateTaskPushNotificationConfigRequest prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -427,30 +427,30 @@ protected Builder newBuilderForType( } /** *
    -   * --8<-- [start:SetTaskPushNotificationConfigRequest]
    -   * Represents a request for the `tasks/pushNotificationConfig/set` method.
    +   * --8<-- [start:CreateTaskPushNotificationConfigRequest]
    +   * Represents a request for the `CreateTaskPushNotificationConfig` method.
        * 
    * - * Protobuf type {@code a2a.v1.SetTaskPushNotificationConfigRequest} + * Protobuf type {@code a2a.v1.CreateTaskPushNotificationConfigRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SetTaskPushNotificationConfigRequest) - io.a2a.grpc.SetTaskPushNotificationConfigRequestOrBuilder { + // @@protoc_insertion_point(builder_implements:a2a.v1.CreateTaskPushNotificationConfigRequest) + io.a2a.grpc.CreateTaskPushNotificationConfigRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.SetTaskPushNotificationConfigRequest.class, io.a2a.grpc.SetTaskPushNotificationConfigRequest.Builder.class); + io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); } - // Construct using io.a2a.grpc.SetTaskPushNotificationConfigRequest.newBuilder() + // Construct using io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -484,17 +484,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SetTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override - public io.a2a.grpc.SetTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return io.a2a.grpc.SetTaskPushNotificationConfigRequest.getDefaultInstance(); + public io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance(); } @java.lang.Override - public io.a2a.grpc.SetTaskPushNotificationConfigRequest build() { - io.a2a.grpc.SetTaskPushNotificationConfigRequest result = buildPartial(); + public io.a2a.grpc.CreateTaskPushNotificationConfigRequest build() { + io.a2a.grpc.CreateTaskPushNotificationConfigRequest result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -502,14 +502,14 @@ public io.a2a.grpc.SetTaskPushNotificationConfigRequest build() { } @java.lang.Override - public io.a2a.grpc.SetTaskPushNotificationConfigRequest buildPartial() { - io.a2a.grpc.SetTaskPushNotificationConfigRequest result = new io.a2a.grpc.SetTaskPushNotificationConfigRequest(this); + public io.a2a.grpc.CreateTaskPushNotificationConfigRequest buildPartial() { + io.a2a.grpc.CreateTaskPushNotificationConfigRequest result = new io.a2a.grpc.CreateTaskPushNotificationConfigRequest(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.a2a.grpc.SetTaskPushNotificationConfigRequest result) { + private void buildPartial0(io.a2a.grpc.CreateTaskPushNotificationConfigRequest result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { result.tenant_ = tenant_; @@ -532,16 +532,16 @@ private void buildPartial0(io.a2a.grpc.SetTaskPushNotificationConfigRequest resu @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.SetTaskPushNotificationConfigRequest) { - return mergeFrom((io.a2a.grpc.SetTaskPushNotificationConfigRequest)other); + if (other instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest) { + return mergeFrom((io.a2a.grpc.CreateTaskPushNotificationConfigRequest)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.a2a.grpc.SetTaskPushNotificationConfigRequest other) { - if (other == io.a2a.grpc.SetTaskPushNotificationConfigRequest.getDefaultInstance()) return this; + public Builder mergeFrom(io.a2a.grpc.CreateTaskPushNotificationConfigRequest other) { + if (other == io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance()) return this; if (!other.getTenant().isEmpty()) { tenant_ = other.tenant_; bitField0_ |= 0x00000001; @@ -1063,23 +1063,23 @@ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigOrBuilder() { return configBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.SetTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(builder_scope:a2a.v1.CreateTaskPushNotificationConfigRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.SetTaskPushNotificationConfigRequest) - private static final io.a2a.grpc.SetTaskPushNotificationConfigRequest DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:a2a.v1.CreateTaskPushNotificationConfigRequest) + private static final io.a2a.grpc.CreateTaskPushNotificationConfigRequest DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.a2a.grpc.SetTaskPushNotificationConfigRequest(); + DEFAULT_INSTANCE = new io.a2a.grpc.CreateTaskPushNotificationConfigRequest(); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest getDefaultInstance() { + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { @java.lang.Override - public SetTaskPushNotificationConfigRequest parsePartialFrom( + public CreateTaskPushNotificationConfigRequest parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { @@ -1098,17 +1098,17 @@ public SetTaskPushNotificationConfigRequest parsePartialFrom( } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } @java.lang.Override - public com.google.protobuf.Parser getParserForType() { + public com.google.protobuf.Parser getParserForType() { return PARSER; } @java.lang.Override - public io.a2a.grpc.SetTaskPushNotificationConfigRequest getDefaultInstanceForType() { + public io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstanceForType() { return DEFAULT_INSTANCE; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SetTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java similarity index 93% rename from spec-grpc/src/main/java/io/a2a/grpc/SetTaskPushNotificationConfigRequestOrBuilder.java rename to spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java index c5a01418a..536c31416 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SetTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java @@ -6,8 +6,8 @@ package io.a2a.grpc; @com.google.protobuf.Generated -public interface SetTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SetTaskPushNotificationConfigRequest) +public interface CreateTaskPushNotificationConfigRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.CreateTaskPushNotificationConfigRequest) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java index 8bfc24676..cb6914e0b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java @@ -8,7 +8,7 @@ /** *
      * --8<-- [start:DeleteTaskPushNotificationConfigRequest]
    - * Represents a request for the `tasks/pushNotificationConfig/delete` method.
    + * Represents a request for the `DeleteTaskPushNotificationConfig` method.
      * 
    * * Protobuf type {@code a2a.v1.DeleteTaskPushNotificationConfigRequest} @@ -315,7 +315,7 @@ protected Builder newBuilderForType( /** *
        * --8<-- [start:DeleteTaskPushNotificationConfigRequest]
    -   * Represents a request for the `tasks/pushNotificationConfig/delete` method.
    +   * Represents a request for the `DeleteTaskPushNotificationConfig` method.
        * 
    * * Protobuf type {@code a2a.v1.DeleteTaskPushNotificationConfigRequest} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java index 33395ab8d..76d9264a0 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java @@ -8,7 +8,7 @@ /** *
      * --8<-- [start:GetTaskRequest]
    - * Represents a request for the `tasks/get` method.
    + * Represents a request for the `GetTask` method.
      * 
    * * Protobuf type {@code a2a.v1.GetTaskRequest} @@ -365,7 +365,7 @@ protected Builder newBuilderForType( /** *
        * --8<-- [start:GetTaskRequest]
    -   * Represents a request for the `tasks/get` method.
    +   * Represents a request for the `GetTask` method.
        * 
    * * Protobuf type {@code a2a.v1.GetTaskRequest} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java index 452ea2312..e057230c9 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java @@ -8,7 +8,7 @@ /** *
      * --8<-- [start:ListTaskPushNotificationConfigResponse]
    - * Represents a successful response for the `tasks/pushNotificationConfig/list`
    + * Represents a successful response for the `ListTaskPushNotificationConfig`
      * method.
      * 
    * @@ -333,7 +333,7 @@ protected Builder newBuilderForType( /** *
        * --8<-- [start:ListTaskPushNotificationConfigResponse]
    -   * Represents a successful response for the `tasks/pushNotificationConfig/list`
    +   * Represents a successful response for the `ListTaskPushNotificationConfig`
        * method.
        * 
    * diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java index caaf9740e..943fc6067 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java @@ -9,7 +9,7 @@ *
      * /////////// Request Messages ///////////
      * --8<-- [start:SendMessageRequest]
    - * Represents a request for the `message/send` method.
    + * Represents a request for the `SendMessage` method.
      * 
    * * Protobuf type {@code a2a.v1.SendMessageRequest} @@ -420,7 +420,7 @@ protected Builder newBuilderForType( *
        * /////////// Request Messages ///////////
        * --8<-- [start:SendMessageRequest]
    -   * Represents a request for the `message/send` method.
    +   * Represents a request for the `SendMessage` method.
        * 
    * * Protobuf type {@code a2a.v1.SendMessageRequest} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java index 337ea8de6..a8216fec8 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java @@ -2,7 +2,6 @@ import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; /** * Mapper between {@link io.a2a.spec.AgentCapabilities} and {@link io.a2a.grpc.AgentCapabilities}. diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SetTaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java similarity index 79% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/SetTaskPushNotificationConfigMapper.java rename to spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java index 2e0215bc1..428ea2846 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SetTaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java @@ -1,13 +1,13 @@ package io.a2a.grpc.mapper; -import io.a2a.grpc.SetTaskPushNotificationConfigRequest; +import io.a2a.grpc.CreateTaskPushNotificationConfigRequest; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * MapStruct mapper for SetTaskPushNotificationConfigRequest → TaskPushNotificationConfig. + * MapStruct mapper for CreateTaskPushNotificationConfigRequest → TaskPushNotificationConfig. *

    * Handles resource name parsing and ID override logic for creating push notification configs. *

    @@ -21,37 +21,37 @@ * Compile-Time Safety: If the proto changes fields, MapStruct will fail to compile. */ @Mapper(config = A2AProtoMapperConfig.class, uses = {PushNotificationConfigMapper.class}) -public interface SetTaskPushNotificationConfigMapper { +public interface CreateTaskPushNotificationConfigMapper { - SetTaskPushNotificationConfigMapper INSTANCE = A2AMappers.getMapper(SetTaskPushNotificationConfigMapper.class); + CreateTaskPushNotificationConfigMapper INSTANCE = A2AMappers.getMapper(CreateTaskPushNotificationConfigMapper.class); /** - * Converts SetTaskPushNotificationConfigRequest to domain TaskPushNotificationConfig. + * Converts CreateTaskPushNotificationConfigRequest to domain TaskPushNotificationConfig. *

    * Extracts taskId from parent resource name and maps PushNotificationConfig with * ID override from config_id field. * The tenant field is set to null as it's not present in the protobuf definition. * - * @param request the protobuf SetTaskPushNotificationConfigRequest + * @param request the protobuf CreateTaskPushNotificationConfigRequest * @return domain TaskPushNotificationConfig */ @Mapping(target = "taskId", expression = "java(extractTaskId(request))") @Mapping(target = "pushNotificationConfig", expression = "java(mapPushNotificationConfigWithId(request))") - TaskPushNotificationConfig fromProto(SetTaskPushNotificationConfigRequest request); + TaskPushNotificationConfig fromProto(CreateTaskPushNotificationConfigRequest request); /** - * Converts SetTaskPushNotificationConfigRequest to domain TaskPushNotificationConfig. + * Converts CreateTaskPushNotificationConfigRequest to domain TaskPushNotificationConfig. *

    * Extracts taskId from parent resource name and maps PushNotificationConfig with * ID override from config_id field. * * @param config the domainTaskPushNotificationConfig - * @return proto SetTaskPushNotificationConfigRequest + * @return proto CreateTaskPushNotificationConfigRequest */ @Mapping(target = "parent", expression = "java(ResourceNameParser.defineTaskName(config.taskId()))") @Mapping(target = "configId", expression = "java(extractConfigId(config))") @Mapping(target = "config", expression = "java(mapPushNotificationConfig(config))") - SetTaskPushNotificationConfigRequest toProto(TaskPushNotificationConfig config); + CreateTaskPushNotificationConfigRequest toProto(TaskPushNotificationConfig config); /** * Extracts the task ID from the parent resource name. @@ -59,10 +59,10 @@ public interface SetTaskPushNotificationConfigMapper { * Format: "tasks/{task_id}" * Fallback: If parent is blank, extracts from config.name instead. * - * @param request the protobuf SetTaskPushNotificationConfigRequest + * @param request the protobuf CreateTaskPushNotificationConfigRequest * @return the extracted task ID */ - default String extractTaskId(SetTaskPushNotificationConfigRequest request) { + default String extractTaskId(CreateTaskPushNotificationConfigRequest request) { String parent = request.getParent(); if (parent == null || parent.isBlank()) { @@ -92,10 +92,10 @@ default String extractConfigId(TaskPushNotificationConfig config) { *

    * The config_id from the request overrides the ID in the proto's PushNotificationConfig. * - * @param request the protobuf SetTaskPushNotificationConfigRequest + * @param request the protobuf CreateTaskPushNotificationConfigRequest * @return domain PushNotificationConfig with config_id injected */ - default PushNotificationConfig mapPushNotificationConfigWithId(SetTaskPushNotificationConfigRequest request) { + default PushNotificationConfig mapPushNotificationConfigWithId(CreateTaskPushNotificationConfigRequest request) { // Check if config and push_notification_config exist if (!request.hasConfig() || !request.getConfig().hasPushNotificationConfig() @@ -128,7 +128,7 @@ default PushNotificationConfig mapPushNotificationConfigWithId(SetTaskPushNotifi *

    * The config_id from the request overrides the ID in the proto's PushNotificationConfig. * - * @param domain the protobuf SetTaskPushNotificationConfigRequest + * @param domain the protobuf CreateTaskPushNotificationConfigRequest * @return domain PushNotificationConfig with config_id injected */ default io.a2a.grpc.TaskPushNotificationConfig mapPushNotificationConfig(TaskPushNotificationConfig domain) { 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 e49bcbeec..3ac66bfa8 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 @@ -61,8 +61,8 @@ 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.CreateTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.spec.A2AError; import io.a2a.spec.ContentTypeNotSupportedError; @@ -229,12 +229,12 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new ListTasksRequest(version, id, ProtoUtils.FromProto.listTasksParams(builder)); } case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.SetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.SetTaskPushNotificationConfigRequest.newBuilder(); + io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); } - return new SetTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.setTaskPushNotificationConfig(builder)); + return new CreateTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.CreateTaskPushNotificationConfig(builder)); } case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); @@ -334,7 +334,7 @@ public static A2AResponse parseResponseBody(String body, String method) throw 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)); + return new CreateTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.taskPushNotificationConfig(builder)); } case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); @@ -380,7 +380,7 @@ public static A2AResponse parseError(JsonObject error, Object id, String meth return new ListTasksResponse(id, rpcError); } case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - return new SetTaskPushNotificationConfigResponse(id, rpcError); + return new CreateTaskPushNotificationConfigResponse(id, rpcError); } case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { return new GetTaskPushNotificationConfigResponse(id, rpcError); 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 b2941dc98..d4b1ca55f 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 @@ -14,7 +14,7 @@ import io.a2a.grpc.mapper.MessageMapper; import io.a2a.grpc.mapper.MessageSendConfigurationMapper; import io.a2a.grpc.mapper.MessageSendParamsMapper; -import io.a2a.grpc.mapper.SetTaskPushNotificationConfigMapper; +import io.a2a.grpc.mapper.CreateTaskPushNotificationConfigMapper; import io.a2a.grpc.mapper.StreamResponseMapper; import io.a2a.grpc.mapper.TaskArtifactUpdateEventMapper; import io.a2a.grpc.mapper.TaskIdParamsMapper; @@ -71,8 +71,8 @@ public static io.a2a.grpc.SubscribeToTaskRequest subscribeToTaskRequest(TaskIdPa return TaskIdParamsMapper.INSTANCE.toProtoSubscribeToTaskRequest(params); } - public static io.a2a.grpc.SetTaskPushNotificationConfigRequest setTaskPushNotificationConfigRequest(TaskPushNotificationConfig config) { - return SetTaskPushNotificationConfigMapper.INSTANCE.toProto(config); + public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest createTaskPushNotificationConfigRequest(TaskPushNotificationConfig config) { + return CreateTaskPushNotificationConfigMapper.INSTANCE.toProto(config); } public static io.a2a.grpc.GetTaskPushNotificationConfigRequest getTaskPushNotificationConfigRequest(GetTaskPushNotificationConfigParams params) { @@ -173,7 +173,7 @@ public static io.a2a.grpc.StreamResponse taskOrMessageStream(StreamingEventKind }; } - public static io.a2a.grpc.TaskPushNotificationConfig setTaskPushNotificationConfigResponse(TaskPushNotificationConfig config) { + public static io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfigResponse(TaskPushNotificationConfig config) { return taskPushNotificationConfig(config); } @@ -231,11 +231,11 @@ public static MessageSendParams messageSendParams(io.a2a.grpc.SendMessageRequest return convert(() -> MessageSendParamsMapper.INSTANCE.fromProto(requestProto)); } - public static TaskPushNotificationConfig setTaskPushNotificationConfig(io.a2a.grpc.SetTaskPushNotificationConfigRequestOrBuilder config) { - io.a2a.grpc.SetTaskPushNotificationConfigRequest reqProto = config instanceof io.a2a.grpc.SetTaskPushNotificationConfigRequest - ? (io.a2a.grpc.SetTaskPushNotificationConfigRequest) config - : ((io.a2a.grpc.SetTaskPushNotificationConfigRequest.Builder) config).build(); - return convert(() -> SetTaskPushNotificationConfigMapper.INSTANCE.fromProto(reqProto)); + public static TaskPushNotificationConfig CreateTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequestOrBuilder config) { + io.a2a.grpc.CreateTaskPushNotificationConfigRequest reqProto = config instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest + ? (io.a2a.grpc.CreateTaskPushNotificationConfigRequest) config + : ((io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder) config).build(); + return convert(() -> CreateTaskPushNotificationConfigMapper.INSTANCE.fromProto(reqProto)); } public static TaskPushNotificationConfig taskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfigOrBuilder config) { diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto index ccf37e6ab..0f701b6e8 100644 --- a/spec-grpc/src/main/proto/a2a.proto +++ b/spec-grpc/src/main/proto/a2a.proto @@ -81,8 +81,8 @@ service A2AService { }; } - // Set a push notification config for a task. - rpc SetTaskPushNotificationConfig(SetTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { + // Create a push notification config for a task. + rpc CreateTaskPushNotificationConfig(CreateTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { option (google.api.http) = { post: "/{parent=tasks/*/pushNotificationConfigs}" body: "config" @@ -480,8 +480,8 @@ message AgentCapabilities { optional bool push_notifications = 2; // A list of protocol extensions supported by the agent. repeated AgentExtension extensions = 3; - // Indicates if the agent provides a history of state transitions for a task. - optional bool state_transition_history = 4; + // Field 4 was previously used by state_transition_history capability. + reserved 4; // Indicates if the agent supports providing an extended agent card when authenticated. optional bool extended_agent_card = 5; } @@ -703,7 +703,7 @@ message DeviceCodeOAuthFlow { ///////////// Request Messages /////////// // --8<-- [start:SendMessageRequest] -// Represents a request for the `message/send` method. +// Represents a request for the `SendMessage` method. message SendMessageRequest { // Optional tenant, provided as a path parameter. string tenant = 4; @@ -717,7 +717,7 @@ message SendMessageRequest { // --8<-- [end:SendMessageRequest] // --8<-- [start:GetTaskRequest] -// Represents a request for the `tasks/get` method. +// Represents a request for the `GetTask` method. message GetTaskRequest { // Optional tenant, provided as a path parameter. string tenant = 3; @@ -772,7 +772,7 @@ message ListTasksResponse { // --8<-- [end:ListTasksResponse] // --8<-- [start:CancelTaskRequest] -// Represents a request for the `tasks/cancel` method. +// Represents a request for the `CancelTask` method. message CancelTaskRequest { // Optional tenant, provided as a path parameter. string tenant = 2; @@ -793,7 +793,7 @@ message GetTaskPushNotificationConfigRequest { // --8<-- [end:GetTaskPushNotificationConfigRequest] // --8<-- [start:DeleteTaskPushNotificationConfigRequest] -// Represents a request for the `tasks/pushNotificationConfig/delete` method. +// Represents a request for the `DeleteTaskPushNotificationConfig` method. message DeleteTaskPushNotificationConfigRequest { // Optional tenant, provided as a path parameter. string tenant = 2; @@ -803,9 +803,9 @@ message DeleteTaskPushNotificationConfigRequest { } // --8<-- [end:DeleteTaskPushNotificationConfigRequest] -// --8<-- [start:SetTaskPushNotificationConfigRequest] -// Represents a request for the `tasks/pushNotificationConfig/set` method. -message SetTaskPushNotificationConfigRequest { +// --8<-- [start:CreateTaskPushNotificationConfigRequest] +// Represents a request for the `CreateTaskPushNotificationConfig` method. +message CreateTaskPushNotificationConfigRequest { // Optional tenant, provided as a path parameter. string tenant = 4; // The parent task resource for this config. @@ -816,7 +816,7 @@ message SetTaskPushNotificationConfigRequest { // The configuration to create. TaskPushNotificationConfig config = 3 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:SetTaskPushNotificationConfigRequest] +// --8<-- [end:CreateTaskPushNotificationConfigRequest] // --8<-- [start:SubscribeToTaskRequest] message SubscribeToTaskRequest { @@ -877,7 +877,7 @@ message StreamResponse { // --8<-- [end:StreamResponse] // --8<-- [start:ListTaskPushNotificationConfigResponse] -// Represents a successful response for the `tasks/pushNotificationConfig/list` +// Represents a successful response for the `ListTaskPushNotificationConfig` // method. message ListTaskPushNotificationConfigResponse { // The list of push notification configurations. 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 380353dea..60f137893 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 @@ -15,8 +15,8 @@ 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.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.JSONParseError; import io.a2a.spec.PushNotificationConfig; @@ -26,11 +26,11 @@ public class JSONRPCUtilsTest { @Test - public void testParseSetTaskPushNotificationConfigRequest_ValidProtoFormat() throws JsonProcessingException { + public void testParseCreateTaskPushNotificationConfigRequest_ValidProtoFormat() throws JsonProcessingException { String validRequest = """ { "jsonrpc": "2.0", - "method": "SetTaskPushNotificationConfig", + "method": "CreateTaskPushNotificationConfig", "id": "1", "params": { "parent": "tasks/task-123", @@ -52,11 +52,11 @@ public void testParseSetTaskPushNotificationConfigRequest_ValidProtoFormat() thr A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest, null); assertNotNull(request); - assertInstanceOf(SetTaskPushNotificationConfigRequest.class, request); - SetTaskPushNotificationConfigRequest setRequest = (SetTaskPushNotificationConfigRequest) request; + assertInstanceOf(CreateTaskPushNotificationConfigRequest.class, request); + CreateTaskPushNotificationConfigRequest setRequest = (CreateTaskPushNotificationConfigRequest) request; assertEquals("2.0", setRequest.getJsonrpc()); assertEquals(1, setRequest.getId()); - assertEquals("SetTaskPushNotificationConfig", setRequest.getMethod()); + assertEquals("CreateTaskPushNotificationConfig", setRequest.getMethod()); TaskPushNotificationConfig config = setRequest.getParams(); assertNotNull(config); @@ -95,7 +95,7 @@ public void testParseMalformedJSON_ThrowsJsonSyntaxException() { String malformedRequest = """ { "jsonrpc": "2.0", - "method": "SetTaskPushNotificationConfig", + "method": "CreateTaskPushNotificationConfig", "params": { "parent": "tasks/task-123" """; // Missing closing braces @@ -111,7 +111,7 @@ public void testParseInvalidParams_ThrowsInvalidParamsJsonMappingException() { String invalidParamsRequest = """ { "jsonrpc": "2.0", - "method": "SetTaskPushNotificationConfig", + "method": "CreateTaskPushNotificationConfig", "id": "3", "params": "not_a_dict" } @@ -129,7 +129,7 @@ public void testParseInvalidProtoStructure_ThrowsInvalidParamsJsonMappingExcepti String invalidStructure = """ { "jsonrpc": "2.0", - "method": "SetTaskPushNotificationConfig", + "method": "CreateTaskPushNotificationConfig", "id": "4", "params": { "invalid_field": "value" @@ -142,7 +142,7 @@ public void testParseInvalidProtoStructure_ThrowsInvalidParamsJsonMappingExcepti () -> JSONRPCUtils.parseRequestBody(invalidStructure, null) ); assertEquals(4, exception.getId()); - assertEquals(ERROR_MESSAGE.formatted("invalid_field in message a2a.v1.SetTaskPushNotificationConfigRequest"), exception.getMessage()); + assertEquals(ERROR_MESSAGE.formatted("invalid_field in message a2a.v1.CreateTaskPushNotificationConfigRequest"), exception.getMessage()); } @Test @@ -262,7 +262,7 @@ public void testParseInvalidTypeWithValidId_PreservesId() throws Exception { } @Test - public void testGenerateSetTaskPushNotificationConfigResponse_Success() throws Exception { + public void testGenerateCreateTaskPushNotificationConfigResponse_Success() throws Exception { TaskPushNotificationConfig config = new TaskPushNotificationConfig( "task-123", PushNotificationConfig.builder() @@ -286,8 +286,8 @@ public void testGenerateSetTaskPushNotificationConfigResponse_Success() throws E } """; - SetTaskPushNotificationConfigResponse response = - (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(responseJson, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + CreateTaskPushNotificationConfigResponse response = + (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(responseJson, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); assertNotNull(response); assertEquals(1, response.getId()); @@ -335,8 +335,8 @@ public void testParseErrorResponse_InvalidParams() throws Exception { } """; - SetTaskPushNotificationConfigResponse response = - (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + CreateTaskPushNotificationConfigResponse response = + (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); assertNotNull(response); assertEquals(5, response.getId()); @@ -359,8 +359,8 @@ public void testParseErrorResponse_ParseError() throws Exception { } """; - SetTaskPushNotificationConfigResponse response = - (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + CreateTaskPushNotificationConfigResponse response = + (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); assertNotNull(response); assertEquals(6, response.getId()); diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index e0a67c9c8..2e3b412e0 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -55,7 +55,6 @@ public void convertAgentCard() { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(true) - .stateTransitionHistory(true) .build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) @@ -91,7 +90,6 @@ public void convertAgentCard() { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(true) - .stateTransitionHistory(true) .build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) diff --git a/spec/src/main/java/io/a2a/spec/A2AMethods.java b/spec/src/main/java/io/a2a/spec/A2AMethods.java index 636b0d81b..e270a7d91 100644 --- a/spec/src/main/java/io/a2a/spec/A2AMethods.java +++ b/spec/src/main/java/io/a2a/spec/A2AMethods.java @@ -24,7 +24,7 @@ public interface A2AMethods { /** Method name for sending a streaming message. */ String SEND_STREAMING_MESSAGE_METHOD = "SendStreamingMessage"; /** Method name for setting task push notification configuration. */ - String SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "SetTaskPushNotificationConfig"; + String SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "CreateTaskPushNotificationConfig"; /** Method name for subscribing to task events. */ String SUBSCRIBE_TO_TASK_METHOD = "SubscribeToTask"; diff --git a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java index ae8fb6f01..da166a4e1 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java +++ b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java @@ -16,25 +16,21 @@ * waiting for task completion *

  • pushNotifications: Agent can send proactive notifications to clients * when task state changes, eliminating the need for polling
  • - *
  • stateTransitionHistory: Agent maintains and provides a complete history - * of all state transitions for tasks, useful for debugging and auditing
  • * *

    * Capabilities are declared in the {@link AgentCard} and are immutable for the lifetime * of the agent instance. This class uses the Builder pattern for construction. * - * @param streaming whether the agent supports streaming responses with incremental artifacts + * @param streaming whether the agent supports streaming responses with incremental artifacts * @param pushNotifications whether the agent supports push notifications for state changes - * @param stateTransitionHistory whether the agent maintains state transition history * @param extendedAgentCard whether the agent supports an extended agent card - * @param extensions list of custom extensions supported by the agent (optional) + * @param extensions list of custom extensions supported by the agent (optional) * @see AgentCard * @see AgentExtension * @see A2A Protocol Specification */ public record AgentCapabilities(boolean streaming, boolean pushNotifications, - boolean stateTransitionHistory, boolean extendedAgentCard, List extensions) { @@ -57,7 +53,6 @@ public static Builder builder() { * AgentCapabilities capabilities = AgentCapabilities.builder() * .streaming(true) * .pushNotifications(false) - * .stateTransitionHistory(false) * .build(); * }

    */ @@ -65,7 +60,6 @@ public static class Builder { private boolean streaming; private boolean pushNotifications; - private boolean stateTransitionHistory; private boolean extendedAgentCard; private List extensions; @@ -103,20 +97,6 @@ public Builder pushNotifications(boolean pushNotifications) { return this; } - /** - * Sets whether the agent maintains state transition history. - *

    - * When enabled, the agent tracks and provides a complete history - * of all state transitions for each task. - * - * @param stateTransitionHistory true if state history is maintained, false otherwise - * @return this builder for method chaining - */ - public Builder stateTransitionHistory(boolean stateTransitionHistory) { - this.stateTransitionHistory = stateTransitionHistory; - return this; - } - /** * Sets whether the agent supports an extended agent card. * state transition history. @@ -150,7 +130,7 @@ public Builder extensions(List extensions) { * @return a new AgentCapabilities instance */ public AgentCapabilities build() { - return new AgentCapabilities(streaming, pushNotifications, stateTransitionHistory, extendedAgentCard, extensions); + return new AgentCapabilities(streaming, pushNotifications, extendedAgentCard, extensions); } } } diff --git a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java index 526b81ce5..599a0e12c 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java @@ -39,7 +39,6 @@ public AgentCard agentCard() { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(true) - .stateTransitionHistory(true) .build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) 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 62acc506e..f8031eb5f 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 @@ -80,7 +80,7 @@ import io.a2a.spec.TextPart; import io.a2a.spec.TransportProtocol; import io.a2a.spec.UnsupportedOperationError; -import io.a2a.util.Utils; + import io.restassured.RestAssured; import io.restassured.config.ObjectMapperConfig; import io.restassured.specification.RequestSpecification; @@ -553,7 +553,7 @@ public void testSetPushNotificationSuccess() throws Exception { TaskPushNotificationConfig taskPushConfig = new TaskPushNotificationConfig( MINIMAL_TASK.id(), PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); - TaskPushNotificationConfig config = getClient().setTaskPushNotificationConfiguration(taskPushConfig); + TaskPushNotificationConfig config = getClient().createTaskPushNotificationConfiguration(taskPushConfig); assertEquals(MINIMAL_TASK.id(), config.taskId()); assertEquals("http://example.com", config.pushNotificationConfig().url()); assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", config.pushNotificationConfig().id()); @@ -573,7 +573,7 @@ public void testGetPushNotificationSuccess() throws Exception { = new TaskPushNotificationConfig( MINIMAL_TASK.id(), PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); - TaskPushNotificationConfig setResult = getClient().setTaskPushNotificationConfiguration(taskPushConfig); + TaskPushNotificationConfig setResult = getClient().createTaskPushNotificationConfiguration(taskPushConfig); assertNotNull(setResult); TaskPushNotificationConfig config = getClient().getTaskPushNotificationConfiguration( @@ -624,7 +624,6 @@ public void testGetExtendedAgentCard() throws A2AClientException { assertEquals("http://example.com/docs", agentCard.documentationUrl()); assertTrue(agentCard.capabilities().pushNotifications()); assertTrue(agentCard.capabilities().streaming()); - assertTrue(agentCard.capabilities().stateTransitionHistory()); assertTrue(agentCard.capabilities().extendedAgentCard()); assertTrue(agentCard.skills().isEmpty()); } @@ -2119,7 +2118,6 @@ private AgentCard createTestAgentCard() { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(true) - .stateTransitionHistory(true) .build()) .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java index 03ec3481b..f9dae8d19 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java @@ -46,7 +46,6 @@ public AgentCard agentCard() { .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(true) - .stateTransitionHistory(true) .extendedAgentCard(true) .build()) .defaultInputModes(Collections.singletonList("text")) 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 439d97497..376d9b11d 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 @@ -159,7 +159,7 @@ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, } @Override - public void setTaskPushNotificationConfig(io.a2a.grpc.SetTaskPushNotificationConfigRequest request, + public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().pushNotifications()) { handleError(responseObserver, new PushNotificationNotSupportedError()); @@ -168,8 +168,8 @@ public void setTaskPushNotificationConfig(io.a2a.grpc.SetTaskPushNotificationCon try { ServerCallContext context = createCallContext(responseObserver); - TaskPushNotificationConfig config = FromProto.setTaskPushNotificationConfig(request); - TaskPushNotificationConfig responseConfig = getRequestHandler().onSetTaskPushNotificationConfig(config, context); + TaskPushNotificationConfig config = FromProto.CreateTaskPushNotificationConfig(request); + TaskPushNotificationConfig responseConfig = getRequestHandler().onCreateTaskPushNotificationConfig(config, context); responseObserver.onNext(ToProto.taskPushNotificationConfig(responseConfig)); responseObserver.onCompleted(); } catch (A2AError e) { 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 187fd6e99..c7cf79524 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 @@ -12,32 +12,10 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import jakarta.enterprise.inject.Instance; - import com.google.protobuf.Empty; import com.google.protobuf.Struct; -import io.a2a.grpc.AuthenticationInfo; -import io.a2a.grpc.CancelTaskRequest; -import io.a2a.grpc.DeleteTaskPushNotificationConfigRequest; -import io.a2a.grpc.GetTaskPushNotificationConfigRequest; -import io.a2a.grpc.GetTaskRequest; -import io.a2a.grpc.ListTaskPushNotificationConfigRequest; -import io.a2a.grpc.ListTaskPushNotificationConfigResponse; -import io.a2a.grpc.ListTasksRequest; -import io.a2a.grpc.ListTasksResponse; -import io.a2a.grpc.Message; -import io.a2a.grpc.Part; -import io.a2a.grpc.PushNotificationConfig; -import io.a2a.grpc.Role; -import io.a2a.grpc.SendMessageRequest; -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.*; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.events.EventConsumer; @@ -273,7 +251,7 @@ public void testGetPushNotificationConfigSuccess() throws Exception { @Test public void testPushNotificationsNotSupportedError() throws Exception { - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false, true); + AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); @@ -284,7 +262,7 @@ public void testPushNotificationsNotSupportedError() throws Exception { public void testOnGetPushNotificationNoPushNotifierConfig() throws Exception { // Create request handler without a push notifier DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true, false); + AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); StreamRecorder streamRecorder = getTaskPushNotificationConfigRequest(handler, NAME); @@ -295,7 +273,7 @@ public void testOnGetPushNotificationNoPushNotifierConfig() throws Exception { public void testOnSetPushNotificationNoPushNotifierConfig() throws Exception { // Create request handler without a push notifier DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true, false); + AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); @@ -612,7 +590,7 @@ public void testOnResubscribeExistingTaskSuccessMocks() throws Exception { @Test public void testStreamingNotSupportedError() throws Exception { - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true, true); + AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); assertGrpcError(streamRecorder, Status.Code.INVALID_ARGUMENT); @@ -621,7 +599,7 @@ public void testStreamingNotSupportedError() throws Exception { @Test public void testStreamingNotSupportedErrorOnResubscribeToTask() throws Exception { // This test does not exist in the Python implementation - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true, true); + AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) @@ -668,7 +646,7 @@ public void testListPushNotificationConfig() throws Exception { @Test public void testListPushNotificationConfigNotSupported() throws Exception { - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false, true); + AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { @@ -739,7 +717,7 @@ public void testDeletePushNotificationConfig() throws Exception { @Test public void testDeletePushNotificationConfigNotSupported() throws Exception { - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false, true); + AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { @@ -1179,14 +1157,14 @@ private StreamRecorder createTaskPushNotificationCon .setName(name) .setPushNotificationConfig(config) .build(); - SetTaskPushNotificationConfigRequest setRequest = SetTaskPushNotificationConfigRequest.newBuilder() + CreateTaskPushNotificationConfigRequest setRequest = CreateTaskPushNotificationConfigRequest.newBuilder() .setConfig(taskPushNotificationConfig) .setConfigId("config456") .setParent("tasks/" + MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); - handler.setTaskPushNotificationConfig(setRequest, streamRecorder); + handler.createTaskPushNotificationConfig(setRequest, streamRecorder); streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); return streamRecorder; } 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 2e1a1fdf0..a592bd55d 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 @@ -29,8 +29,8 @@ 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.CreateTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.AgentCardValidator; import io.a2a.server.ExtendedAgentCard; @@ -188,20 +188,20 @@ public GetTaskPushNotificationConfigResponse getPushNotificationConfig( } } - public SetTaskPushNotificationConfigResponse setPushNotificationConfig( - SetTaskPushNotificationConfigRequest request, ServerCallContext context) { + public CreateTaskPushNotificationConfigResponse setPushNotificationConfig( + CreateTaskPushNotificationConfigRequest request, ServerCallContext context) { if (!agentCard.capabilities().pushNotifications()) { - return new SetTaskPushNotificationConfigResponse(request.getId(), + return new CreateTaskPushNotificationConfigResponse(request.getId(), new PushNotificationNotSupportedError()); } try { TaskPushNotificationConfig config = - requestHandler.onSetTaskPushNotificationConfig(request.getParams(), context); - return new SetTaskPushNotificationConfigResponse(request.getId().toString(), config); + requestHandler.onCreateTaskPushNotificationConfig(request.getParams(), context); + return new CreateTaskPushNotificationConfigResponse(request.getId().toString(), config); } catch (A2AError e) { - return new SetTaskPushNotificationConfigResponse(request.getId(), e); + return new CreateTaskPushNotificationConfigResponse(request.getId(), e); } catch (Throwable t) { - return new SetTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); + return new CreateTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); } } 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 2053ada41..8d2751627 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 @@ -39,13 +39,12 @@ 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.CreateTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.events.EventConsumer; -import io.a2a.server.events.MainEventBusProcessorCallback; import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; import io.a2a.server.requesthandlers.DefaultRequestHandler; import io.a2a.server.tasks.ResultAggregator; @@ -650,8 +649,8 @@ public void testSetPushNotificationConfigSuccess() { PushNotificationConfig.builder().url("http://example.com") .id("c295ea44-7543-4f78-b524-7a38915ad6e4").build(), "tenant"); - SetTaskPushNotificationConfigRequest request = new SetTaskPushNotificationConfigRequest("1", taskPushConfig); - SetTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); + CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); + CreateTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); TaskPushNotificationConfig taskPushConfigResult = new TaskPushNotificationConfig( MINIMAL_TASK.id(), PushNotificationConfig.builder().url("http://example.com") @@ -674,7 +673,7 @@ public void testGetPushNotificationConfigSuccess() { MINIMAL_TASK.id(), PushNotificationConfig.builder() .id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), "tenant"); - SetTaskPushNotificationConfigRequest request = new SetTaskPushNotificationConfigRequest("1", taskPushConfig); + CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); GetTaskPushNotificationConfigRequest getRequest @@ -715,7 +714,6 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex .status(new TaskStatus(TaskState.COMPLETED)) .build()); - agentExecutorExecute = (context, eventQueue) -> { // Hardcode the events to send here for (Event event : events) { @@ -727,8 +725,8 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex MINIMAL_TASK.id(), PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), "tenant"); - SetTaskPushNotificationConfigRequest stpnRequest = new SetTaskPushNotificationConfigRequest("1", config); - SetTaskPushNotificationConfigResponse stpnResponse = handler.setPushNotificationConfig(stpnRequest, callContext); + CreateTaskPushNotificationConfigRequest stpnRequest = new CreateTaskPushNotificationConfigRequest("1", config); + CreateTaskPushNotificationConfigResponse stpnResponse = handler.setPushNotificationConfig(stpnRequest, callContext); assertNull(stpnResponse.getError()); Message msg = Message.builder(MESSAGE) @@ -1000,7 +998,7 @@ public void onComplete() { @Test public void testStreamingNotSupportedError() { - AgentCard card = createAgentCard(false, true, true); + AgentCard card = createAgentCard(false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); SendStreamingMessageRequest request = SendStreamingMessageRequest.builder() @@ -1052,7 +1050,7 @@ public void onComplete() { @Test public void testStreamingNotSupportedErrorOnResubscribeToTask() { // This test does not exist in the Python implementation - AgentCard card = createAgentCard(false, true, true); + AgentCard card = createAgentCard(false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); @@ -1098,7 +1096,7 @@ public void onComplete() { @Test public void testPushNotificationsNotSupportedError() { - AgentCard card = createAgentCard(true, false, true); + AgentCard card = createAgentCard(true, false); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); @@ -1110,10 +1108,10 @@ public void testPushNotificationsNotSupportedError() { .url("http://example.com") .build(), "tenant"); - SetTaskPushNotificationConfigRequest request = SetTaskPushNotificationConfigRequest.builder() + CreateTaskPushNotificationConfigRequest request = CreateTaskPushNotificationConfigRequest.builder() .params(config) .build(); - SetTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); + CreateTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); assertInstanceOf(PushNotificationNotSupportedError.class, response.getError()); } @@ -1121,7 +1119,7 @@ public void testPushNotificationsNotSupportedError() { public void testOnGetPushNotificationNoPushNotifierConfig() { // Create request handler without a push notifier DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = createAgentCard(false, true, false); + AgentCard card = createAgentCard(false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); @@ -1139,7 +1137,7 @@ public void testOnGetPushNotificationNoPushNotifierConfig() { public void testOnSetPushNotificationNoPushNotifierConfig() { // Create request handler without a push notifier DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = createAgentCard(false, true, false); + AgentCard card = createAgentCard(false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); @@ -1152,10 +1150,10 @@ public void testOnSetPushNotificationNoPushNotifierConfig() { .url("http://example.com") .build(), "tenant"); - SetTaskPushNotificationConfigRequest request = SetTaskPushNotificationConfigRequest.builder() + CreateTaskPushNotificationConfigRequest request = CreateTaskPushNotificationConfigRequest.builder() .params(config) .build(); - SetTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); + CreateTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); assertInstanceOf(UnsupportedOperationError.class, response.getError()); assertEquals("This operation is not supported", response.getError().getMessage()); @@ -1230,7 +1228,7 @@ public void testDefaultRequestHandlerWithCustomComponents() { @Test public void testOnMessageSendErrorHandling() { DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = createAgentCard(false, true, false); + AgentCard card = createAgentCard(false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); @@ -1341,7 +1339,7 @@ public void testListPushNotificationConfig() { .url("http://example.com") .id(MINIMAL_TASK.id()) .build(), "tenant"); - SetTaskPushNotificationConfigRequest request = new SetTaskPushNotificationConfigRequest("1", taskPushConfig); + CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); TaskPushNotificationConfig result = new TaskPushNotificationConfig( MINIMAL_TASK.id(), PushNotificationConfig.builder() @@ -1359,7 +1357,7 @@ public void testListPushNotificationConfig() { @Test public void testListPushNotificationConfigNotSupported() { - AgentCard card = createAgentCard(true, false, true); + AgentCard card = createAgentCard(true, false); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { @@ -1372,7 +1370,7 @@ public void testListPushNotificationConfigNotSupported() { .url("http://example.com") .id(MINIMAL_TASK.id()) .build(), "tenant"); - SetTaskPushNotificationConfigRequest request = new SetTaskPushNotificationConfigRequest("1", taskPushConfig); + CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); ListTaskPushNotificationConfigRequest listRequest @@ -1435,7 +1433,7 @@ public void testDeletePushNotificationConfig() { .url("http://example.com") .id(MINIMAL_TASK.id()) .build(), "tenant"); - SetTaskPushNotificationConfigRequest request = new SetTaskPushNotificationConfigRequest("1", taskPushConfig); + CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); DeleteTaskPushNotificationConfigRequest deleteRequest @@ -1450,7 +1448,7 @@ public void testDeletePushNotificationConfig() { @Test public void testDeletePushNotificationConfigNotSupported() { - AgentCard card = createAgentCard(true, false, true); + AgentCard card = createAgentCard(true, false); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, eventQueue) -> { @@ -1463,7 +1461,7 @@ public void testDeletePushNotificationConfigNotSupported() { .url("http://example.com") .id(MINIMAL_TASK.id()) .build(), "tenant"); - SetTaskPushNotificationConfigRequest request = new SetTaskPushNotificationConfigRequest("1", taskPushConfig); + CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); DeleteTaskPushNotificationConfigRequest deleteRequest @@ -1492,7 +1490,7 @@ public void testDeletePushNotificationConfigNoPushConfigStore() { .url("http://example.com") .id(MINIMAL_TASK.id()) .build(), "tenant"); - SetTaskPushNotificationConfigRequest request = new SetTaskPushNotificationConfigRequest("1", taskPushConfig); + CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); DeleteTaskPushNotificationConfigRequest deleteRequest 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 3273d6119..f4b594f6b 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 @@ -161,15 +161,15 @@ public HTTPRestResponse cancelTask(String taskId, String tenant, ServerCallConte } } - public HTTPRestResponse setTaskPushNotificationConfiguration(String taskId, String body, String tenant, ServerCallContext context) { + public HTTPRestResponse CreateTaskPushNotificationConfiguration(String taskId, String body, String tenant, ServerCallContext context) { try { if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); } - io.a2a.grpc.SetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.SetTaskPushNotificationConfigRequest.newBuilder(); + io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(body, builder); builder.setTenant(tenant); - TaskPushNotificationConfig result = requestHandler.onSetTaskPushNotificationConfig(ProtoUtils.FromProto.setTaskPushNotificationConfig(builder), context); + TaskPushNotificationConfig result = requestHandler.onCreateTaskPushNotificationConfig(ProtoUtils.FromProto.CreateTaskPushNotificationConfig(builder), context); return createSuccessResponse(201, io.a2a.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(result))); } catch (A2AError e) { return createErrorResponse(e); 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 21005c22f..48eaae912 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 @@ -226,7 +226,7 @@ public void testSendStreamingMessageSuccess() { @Test public void testSendStreamingMessageNotSupported() { - AgentCard card = createAgentCard(false, true, true); + AgentCard card = createAgentCard(false, true); RestHandler handler = new RestHandler(card, requestHandler, internalExecutor); String requestBody = """ @@ -265,7 +265,7 @@ public void testPushNotificationConfigSuccess() { } }""".formatted(MINIMAL_TASK.id(), MINIMAL_TASK.id()); - RestHandler.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration( MINIMAL_TASK.id(), requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.CreateTaskPushNotificationConfiguration( MINIMAL_TASK.id(), requestBody, "", callContext); Assertions.assertEquals(201, response.getStatusCode(), response.toString()); Assertions.assertEquals("application/json", response.getContentType()); @@ -274,7 +274,7 @@ public void testPushNotificationConfigSuccess() { @Test public void testPushNotificationConfigNotSupported() { - AgentCard card = createAgentCard(true, false, true); + AgentCard card = createAgentCard(true, false); RestHandler handler = new RestHandler(card, requestHandler, internalExecutor); String requestBody = """ @@ -286,7 +286,7 @@ public void testPushNotificationConfigNotSupported() { } """.formatted(MINIMAL_TASK.id()); - RestHandler.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.id(), requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.CreateTaskPushNotificationConfiguration(MINIMAL_TASK.id(), requestBody, "", callContext); Assertions.assertEquals(501, response.getStatusCode()); Assertions.assertTrue(response.getBody().contains("PushNotificationNotSupportedError")); @@ -312,7 +312,7 @@ public void testGetPushNotificationConfig() { } } }""".formatted(MINIMAL_TASK.id(), MINIMAL_TASK.id()); - RestHandler.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.id(), createRequestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.CreateTaskPushNotificationConfiguration(MINIMAL_TASK.id(), createRequestBody, "", callContext); Assertions.assertEquals(201, response.getStatusCode(), response.toString()); Assertions.assertEquals("application/json", response.getContentType()); // Now get it From 06b9fe553489b092e818cec532a61083aa5a0f37 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 5 Feb 2026 14:45:08 +0100 Subject: [PATCH 015/192] chore: fixing flaky test (#628) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Problem The second sendMessage call doesn't wait for its streaming subscription to be established. This creates a race condition: - The agent receives message2 and immediately sends events (artifact-2 + completion) - But the streamConsumer subscription might not be fully wired up yet - The events get delivered to the resubConsumer (which is already established) but missed by the streamConsumer The Fix Add the awaitStreamingSubscription() pattern before the second sendMessage call: Fixes #627 🦕 Signed-off-by: Emmanuel Hugonnet --- .../io/a2a/server/apps/common/AbstractA2AServerTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) 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 f8031eb5f..6b99776c7 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 @@ -1425,9 +1425,18 @@ public void testNonBlockingWithMultipleMessages() throws Exception { } }; + // Wait for streaming subscription to be established before sending message + CountDownLatch streamSubscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> streamSubscriptionLatch.countDown()); + // Streaming message adds artifact-2 and completes task getClient().sendMessage(message2, List.of(streamConsumer), null); + // Ensure subscription is established before agent sends events + assertTrue(streamSubscriptionLatch.await(15, TimeUnit.SECONDS), + "Stream subscription should be established"); + // 4. Verify both consumers received artifact-2 and completion assertTrue(resubEventLatch.await(10, TimeUnit.SECONDS)); assertTrue(streamEventLatch.await(10, TimeUnit.SECONDS)); From 29bd6bb15680ba01ddc7496bc9453b83a22d4677 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 5 Feb 2026 14:45:27 +0100 Subject: [PATCH 016/192] chore: Upgrade Nullaway and error prone (#629) Upgrading Nullaway fro 0.12.14 to 0.13.1: https://github.com/uber/NullAway/compare/v0.12.14...v0.13.1 Signed-off-by: Emmanuel Hugonnet --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index adf31c903..8f3545dba 100644 --- a/pom.xml +++ b/pom.xml @@ -69,8 +69,8 @@ 5.5.1 2.0.17 1.5.18 - 2.45.0 - 0.12.14 + 2.47.0 + 0.13.1 -XDaddTypeAnnotationsToSymbol=true -Xplugin:ErrorProne -XepDisableAllChecks -Xep:NullAway:ERROR -Xep:RequireExplicitNullMarking:WARN -XepOpt:NullAway:ExhaustiveOverride=true -XepOpt:NullAway:OnlyNullMarked=true -XepOpt:NullAway:JSpecifyMode=true -XepExcludedPaths:.*/src/test/.* -XepDisableWarningsInGeneratedCode From 3dfa2bfe079e29efc6e00d0b3266d3a11f10dd86 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 5 Feb 2026 17:05:03 +0000 Subject: [PATCH 017/192] fix: Eliminate race condition in testInputRequiredWorkflow (#630) The test consumers were counting down their latches on the FIRST TaskEvent received, which could be the intermediate WORKING state instead of the expected terminal state (INPUT_REQUIRED or COMPLETED). This caused intermittent test failures with: expected: but was: Fix: Both consumers now only count down when receiving the expected terminal state: - initialConsumer waits for INPUT_REQUIRED (not WORKING) - completionConsumer waits for COMPLETED (not WORKING) This matches the agent's event emission pattern: agentEmitter.startWork() // WORKING state agentEmitter.requiresInput(...) // INPUT_REQUIRED state ...later... agentEmitter.startWork() // WORKING state agentEmitter.complete() // COMPLETED state --- .../apps/common/AbstractA2AServerTest.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) 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 6b99776c7..a15f2b087 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 @@ -1512,9 +1512,17 @@ public void testInputRequiredWorkflow() throws Exception { AtomicBoolean initialUnexpectedEvent = new AtomicBoolean(false); BiConsumer initialConsumer = (event, agentCard) -> { + // Idempotency guard: prevent late events from modifying state after latch countdown + if (initialLatch.getCount() == 0) { + return; + } if (event instanceof TaskEvent te) { - initialState.set(te.getTask().status().state()); - initialLatch.countDown(); + TaskState state = te.getTask().status().state(); + initialState.set(state); + // Only count down when we receive INPUT_REQUIRED, not intermediate states like WORKING + if (state == TaskState.INPUT_REQUIRED) { + initialLatch.countDown(); + } } else { initialUnexpectedEvent.set(true); } @@ -1538,9 +1546,17 @@ public void testInputRequiredWorkflow() throws Exception { AtomicBoolean completionUnexpectedEvent = new AtomicBoolean(false); BiConsumer completionConsumer = (event, agentCard) -> { + // Idempotency guard: prevent late events from modifying state after latch countdown + if (completionLatch.getCount() == 0) { + return; + } if (event instanceof TaskEvent te) { - completedState.set(te.getTask().status().state()); - completionLatch.countDown(); + TaskState state = te.getTask().status().state(); + completedState.set(state); + // Only count down when we receive COMPLETED, not intermediate states like WORKING + if (state == TaskState.COMPLETED) { + completionLatch.countDown(); + } } else { completionUnexpectedEvent.set(true); } From 767ca4348d6c4b2062700ad4cf32de295bf1a3fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=AA=85=ED=98=84?= <117622409+flex-myeonghyeon@users.noreply.github.com> Date: Fri, 6 Feb 2026 19:38:52 +0900 Subject: [PATCH 018/192] fix: merge metadata appendArtifactToTask metadata #615 (#616) Co-authored-by: mhyeon-lee --- .../java/io/a2a/server/tasks/TaskManagerTest.java | 5 +++++ spec/src/main/java/io/a2a/util/Utils.java | 15 +++++++++++++++ 2 files changed, 20 insertions(+) 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 91010e52e..ca4aa07b1 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 @@ -191,6 +191,7 @@ public void testTaskArtifactUpdateEventAppendTrueWithExistingArtifact() throws A .artifactId("artifact-id") .name("artifact-1") .parts(Collections.singletonList(new TextPart("existing content"))) + .metadata(Map.of("key1", "value1")) .build(); Task taskWithArtifact = Task.builder(initialTask) .artifacts(Collections.singletonList(existingArtifact)) @@ -202,6 +203,7 @@ public void testTaskArtifactUpdateEventAppendTrueWithExistingArtifact() throws A .artifactId("artifact-id") .name("artifact-1") .parts(Collections.singletonList(new TextPart("new content"))) + .metadata(Map.of("key2", "value2")) .build(); TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() .taskId(minimalTask.id()) @@ -219,6 +221,9 @@ public void testTaskArtifactUpdateEventAppendTrueWithExistingArtifact() throws A assertEquals(2, updatedArtifact.parts().size()); assertEquals("existing content", ((TextPart) updatedArtifact.parts().get(0)).text()); assertEquals("new content", ((TextPart) updatedArtifact.parts().get(1)).text()); + + assertEquals("value1", updatedArtifact.metadata().get("key1")); + assertEquals("value2", updatedArtifact.metadata().get("key2")); } @Test diff --git a/spec/src/main/java/io/a2a/util/Utils.java b/spec/src/main/java/io/a2a/util/Utils.java index 792365579..44d713f75 100644 --- a/spec/src/main/java/io/a2a/util/Utils.java +++ b/spec/src/main/java/io/a2a/util/Utils.java @@ -3,7 +3,9 @@ import static io.a2a.util.Assert.checkNotNullParam; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.logging.Logger; import com.google.gson.Gson; @@ -129,8 +131,21 @@ public static Task appendArtifactToTask(Task task, TaskArtifactUpdateEvent event log.fine(String.format("Appending parts to artifact id %s for task %s", artifactId, taskId)); List> parts = new ArrayList<>(existingArtifact.parts()); parts.addAll(newArtifact.parts()); + + Map mergedMetadata = null; + if (existingArtifact.metadata() != null || newArtifact.metadata() != null) { + mergedMetadata = new HashMap<>(); + if (existingArtifact.metadata() != null) { + mergedMetadata.putAll(existingArtifact.metadata()); + } + if (newArtifact.metadata() != null) { + mergedMetadata.putAll(newArtifact.metadata()); + } + } + Artifact updated = Artifact.builder(existingArtifact) .parts(parts) + .metadata(mergedMetadata) .build(); artifacts.set(existingArtifactIndex, updated); } else { From 18d2abff5c35e0079b63fdf9e1b40d0d463520e2 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 6 Feb 2026 12:06:08 +0000 Subject: [PATCH 019/192] =?UTF-8?q?fix:=20Eliminate=20intermittent=20failu?= =?UTF-8?q?re=20in=20testQueueClosedEventTerminates=E2=80=A6=20(#631)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …RemoteSubscribers Two-part fix for race condition in Kafka replication test: 1. EventQueue: Signal polling started BEFORE any early returns - Moved signalQueuePollerStarted() to beginning of dequeueEventItem() - Previously in finally block, which didn't execute if queue was closed - Race: If queue closed before first dequeue, EventQueueClosedException thrown BEFORE try block, so finally never ran and signal never sent - Now always signals even if queue immediately throws on closure 2. Test: Replace unreliable Thread.sleep with proper synchronization - Inject QueueManager to access the queue for the task - Replace Thread.sleep(2000) with queueManager.awaitQueuePollerStart() - Ensures EventConsumer is actually polling before sending QueueClosedEvent - Add debug logging to diagnose future failures Root cause: signalQueuePollerStarted() was only called in finally block, which was skipped when queue was already closed at first dequeue attempt. This caused awaitQueuePollerStart() to hang or timeout intermittently. --- .../KafkaReplicationIntegrationTest.java | 20 +++++++- .../java/io/a2a/server/events/EventQueue.java | 48 +++++++++---------- 2 files changed, 42 insertions(+), 26 deletions(-) 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 c4b23fb0d..d38f8244c 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 @@ -30,7 +30,9 @@ 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.EventQueue; import io.a2a.server.events.QueueClosedEvent; +import io.a2a.server.events.QueueManager; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; import io.a2a.spec.Message; @@ -46,6 +48,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Integration test for Kafka replication functionality. @@ -54,6 +58,8 @@ @QuarkusTest public class KafkaReplicationIntegrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(KafkaReplicationIntegrationTest.class); + @Inject @PublicAgentCard AgentCard agentCard; @@ -65,6 +71,9 @@ public class KafkaReplicationIntegrationTest { @Channel("replicated-events-out") Emitter testEmitter; + @Inject + QueueManager queueManager; + private Client streamingClient; private Client nonStreamingClient; private Client pollingClient; @@ -367,8 +376,11 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { // Resubscribe to the task - this creates a streaming subscription streamingClient.resubscribe(new TaskIdParams(taskId), List.of(consumer), errorHandler); - // Wait a moment to ensure the streaming subscription is fully established - Thread.sleep(2000); + // Wait for the EventConsumer to start polling (replaces unreliable Thread.sleep) + // This ensures the consumer is ready to receive the QueueClosedEvent + EventQueue queue = queueManager.get(taskId); + assertNotNull(queue, "Queue should exist for task " + taskId); + queueManager.awaitQueuePollerStart(queue); // Now manually send a QueueClosedEvent to Kafka to simulate queue closure on another node QueueClosedEvent closedEvent = new QueueClosedEvent(taskId); @@ -384,6 +396,10 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { "Streaming subscription should complete when QueueClosedEvent is received"); // Verify the stream completed normally (not with an error) + if (!streamCompleted.get()) { + LOGGER.error("Stream did not complete normally! streamErrored={}, errorRef={}", + streamErrored.get(), errorRef.get(), errorRef.get()); + } assertTrue(streamCompleted.get(), "Stream should complete normally when QueueClosedEvent is received"); assertFalse(streamErrored.get(), "Stream should not error on QueueClosedEvent"); assertNull(errorRef.get(), "Should not receive error when stream completes gracefully"); 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 99f8bc2dc..122d4b0f8 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 @@ -662,6 +662,10 @@ public void enqueueLocalOnly(EventQueueItem item) { @Override @Nullable public EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueClosedException { + // CRITICAL: Signal polling started BEFORE any early returns + // This ensures awaitQueuePollerStart() unblocks even if queue is already closed + signalQueuePollerStarted(); + // For immediate close: exit immediately even if queue is not empty (race with MainEventBusProcessor) // For graceful close: only exit when queue is empty (wait for all events to be consumed) // BUT: if awaiting final event, keep polling even if closed and empty @@ -672,32 +676,28 @@ public EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueCl queue.size()); throw new EventQueueClosedException(); } - try { - if (waitMilliSeconds <= 0) { - EventQueueItem item = queue.poll(); - if (item != null) { - Event event = item.getEvent(); - LOGGER.debug("Dequeued event item (no wait) {} {}", this, event instanceof Throwable ? event.toString() : event); - } - return item; + if (waitMilliSeconds <= 0) { + EventQueueItem item = queue.poll(); + if (item != null) { + Event event = item.getEvent(); + LOGGER.debug("Dequeued event item (no wait) {} {}", this, event instanceof Throwable ? event.toString() : event); } - try { - LOGGER.trace("Polling ChildQueue {} (wait={}ms)", System.identityHashCode(this), waitMilliSeconds); - EventQueueItem item = queue.poll(waitMilliSeconds, TimeUnit.MILLISECONDS); - if (item != null) { - Event event = item.getEvent(); - LOGGER.debug("Dequeued event item (waiting) {} {}", this, event instanceof Throwable ? event.toString() : event); - } else { - LOGGER.trace("Dequeue timeout (null) from ChildQueue {}", System.identityHashCode(this)); - } - return item; - } catch (InterruptedException e) { - LOGGER.debug("Interrupted dequeue (waiting) {}", this); - Thread.currentThread().interrupt(); - return null; + return item; + } + try { + LOGGER.trace("Polling ChildQueue {} (wait={}ms)", System.identityHashCode(this), waitMilliSeconds); + EventQueueItem item = queue.poll(waitMilliSeconds, TimeUnit.MILLISECONDS); + if (item != null) { + Event event = item.getEvent(); + LOGGER.debug("Dequeued event item (waiting) {} {}", this, event instanceof Throwable ? event.toString() : event); + } else { + LOGGER.trace("Dequeue timeout (null) from ChildQueue {}", System.identityHashCode(this)); } - } finally { - signalQueuePollerStarted(); + return item; + } catch (InterruptedException e) { + LOGGER.debug("Interrupted dequeue (waiting) {}", this); + Thread.currentThread().interrupt(); + return null; } } From 5d2cd75ab7f3f93c299c5f1d1fa03d0ec3ad5575 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Fri, 6 Feb 2026 18:30:28 +0100 Subject: [PATCH 020/192] refactor: Update A2A protocol to align with spec revision (#633) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move protocol version from AgentCard to AgentInterface level - Simplify resource identifiers from hierarchical names to flat IDs (e.g., "tasks/123" -> "123") - Restructure Part types: remove FilePart/DataPart in favor of unified Part with url/raw/data variants - Add OAuth flow support (ImplicitOAuthFlow, PasswordOAuthFlow) - Rename Security to SecurityRequirement for clarity - Standardize spelling: CANCELLED -> CANCELED - Update all client transports (gRPC, JSON-RPC, REST) and tests - Rename resubscribe to subscribeToTask Breaking changes in proto API affecting: - Task operations (get, cancel, subscribe) - Push notification config management - Message part structure Fixes #632 🦕 Signed-off-by: Emmanuel Hugonnet --- README.md | 16 +- .../java/io/a2a/client/AbstractClient.java | 22 +- .../src/main/java/io/a2a/client/Client.java | 16 +- .../AuthenticationAuthorizationTest.java | 2 - .../java/io/a2a/client/ClientBuilderTest.java | 2 - .../client/transport/grpc/GrpcTransport.java | 50 +- .../transport/jsonrpc/JSONRPCTransport.java | 2 +- .../JSONRPCTransportStreamingTest.java | 18 +- .../jsonrpc/JSONRPCTransportTest.java | 15 +- .../transport/jsonrpc/JsonMessages.java | 99 +- .../jsonrpc/JsonStreamingMessages.java | 12 +- .../jsonrpc/sse/SSEEventListenerTest.java | 15 +- .../client/transport/rest/RestTransport.java | 23 +- .../transport/rest/JsonRestMessages.java | 51 +- .../transport/rest/RestTransportTest.java | 21 +- .../rest/sse/SSEEventListenerTest.java | 6 +- .../client/transport/spi/ClientTransport.java | 6 +- .../interceptors/auth/AuthInterceptor.java | 4 +- .../auth/AuthInterceptorTest.java | 6 +- .../spi/sse/SSEEventListenerTest.java | 14 +- .../cloud/CloudAgentCardProducer.java | 2 - .../examples/cloud/A2ACloudExampleClient.java | 2 +- .../helloworld/AgentCardProducer.java | 2 - ...otificationConfigStoreIntegrationTest.java | 4 +- .../core/ReplicatedQueueManager.java | 2 - .../core/EventSerializationTest.java | 3 - .../core/ReplicatedQueueManagerTest.java | 6 - ...ctiveMessagingReplicationStrategyTest.java | 2 - .../MultiInstanceReplicationAgentCards.java | 2 - .../MultiInstanceReplicationTest.java | 12 +- .../KafkaReplicationIntegrationTest.java | 21 +- .../ReplicationTestAgentCardProducer.java | 2 - .../java/io/a2a/client/http/JsonMessages.java | 3 +- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 12 +- .../wrappers/StreamingJSONRPCRequest.java | 2 +- .../wrappers/SubscribeToTaskRequest.java | 2 +- .../StreamingEventKindSerializationTest.java | 1 - .../apps/quarkus/A2AServerRoutesTest.java | 35 +- .../rest/quarkus/A2AServerRoutesTest.java | 2 +- .../java/io/a2a/server/events/EventQueue.java | 6 +- .../DefaultRequestHandler.java | 12 +- .../requesthandlers/RequestHandler.java | 2 +- .../java/io/a2a/server/tasks/TaskUpdater.java | 1 - .../io/a2a/server/util/ArtifactUtils.java | 12 +- .../server/version/A2AVersionValidator.java | 16 +- .../a2a/server/events/EventConsumerTest.java | 9 +- .../io/a2a/server/events/EventQueueTest.java | 1 - .../AbstractA2ARequestHandlerTest.java | 4 +- .../io/a2a/server/tasks/TaskManagerTest.java | 10 - .../io/a2a/server/tasks/TaskUpdaterTest.java | 8 +- .../version/A2AVersionValidatorTest.java | 3 +- spec-grpc/pom.xml | 2 +- spec-grpc/src/main/java/io/a2a/grpc/A2A.java | 613 ++++----- .../main/java/io/a2a/grpc/A2AServiceGrpc.java | 8 +- .../src/main/java/io/a2a/grpc/AgentCard.java | 873 +++++-------- .../java/io/a2a/grpc/AgentCardOrBuilder.java | 82 +- .../main/java/io/a2a/grpc/AgentInterface.java | 182 ++- .../io/a2a/grpc/AgentInterfaceOrBuilder.java | 24 + .../src/main/java/io/a2a/grpc/AgentSkill.java | 359 +++--- .../java/io/a2a/grpc/AgentSkillOrBuilder.java | 29 +- .../java/io/a2a/grpc/AuthenticationInfo.java | 282 ++--- .../a2a/grpc/AuthenticationInfoOrBuilder.java | 43 +- .../java/io/a2a/grpc/CancelTaskRequest.java | 117 +- .../a2a/grpc/CancelTaskRequestOrBuilder.java | 18 +- ...eateTaskPushNotificationConfigRequest.java | 207 ++- ...ushNotificationConfigRequestOrBuilder.java | 28 +- .../src/main/java/io/a2a/grpc/DataPart.java | 617 --------- .../java/io/a2a/grpc/DataPartOrBuilder.java | 39 - ...leteTaskPushNotificationConfigRequest.java | 283 ++++- ...ushNotificationConfigRequestOrBuilder.java | 38 +- .../src/main/java/io/a2a/grpc/FilePart.java | 1109 ----------------- .../java/io/a2a/grpc/FilePartOrBuilder.java | 102 -- .../GetTaskPushNotificationConfigRequest.java | 283 ++++- ...ushNotificationConfigRequestOrBuilder.java | 38 +- .../main/java/io/a2a/grpc/GetTaskRequest.java | 117 +- .../io/a2a/grpc/GetTaskRequestOrBuilder.java | 18 +- .../java/io/a2a/grpc/ImplicitOAuthFlow.java | 1050 ++++++++++++++++ .../a2a/grpc/ImplicitOAuthFlowOrBuilder.java | 115 ++ ...ListTaskPushNotificationConfigRequest.java | 117 +- ...ushNotificationConfigRequestOrBuilder.java | 18 +- .../src/main/java/io/a2a/grpc/OAuthFlows.java | 432 +++++++ .../java/io/a2a/grpc/OAuthFlowsOrBuilder.java | 38 + spec-grpc/src/main/java/io/a2a/grpc/Part.java | 1055 +++++++++++----- .../main/java/io/a2a/grpc/PartOrBuilder.java | 109 +- .../java/io/a2a/grpc/PasswordOAuthFlow.java | 1050 ++++++++++++++++ .../a2a/grpc/PasswordOAuthFlowOrBuilder.java | 115 ++ .../io/a2a/grpc/PushNotificationConfig.java | 24 +- .../grpc/PushNotificationConfigOrBuilder.java | 6 +- ...Security.java => SecurityRequirement.java} | 114 +- ...java => SecurityRequirementOrBuilder.java} | 4 +- .../io/a2a/grpc/SendMessageConfiguration.java | 8 +- .../SendMessageConfigurationOrBuilder.java | 2 +- .../io/a2a/grpc/SubscribeToTaskRequest.java | 117 +- .../grpc/SubscribeToTaskRequestOrBuilder.java | 18 +- .../a2a/grpc/TaskPushNotificationConfig.java | 465 +++++-- .../TaskPushNotificationConfigOrBuilder.java | 58 +- .../src/main/java/io/a2a/grpc/TaskState.java | 20 +- .../io/a2a/grpc/TaskStatusUpdateEvent.java | 99 +- .../grpc/TaskStatusUpdateEventOrBuilder.java | 10 - .../a2a/grpc/mapper/A2ACommonFieldMapper.java | 25 +- .../a2a/grpc/mapper/AgentInterfaceMapper.java | 1 + .../grpc/mapper/AuthenticationInfoMapper.java | 14 + ...reateTaskPushNotificationConfigMapper.java | 82 +- .../io/a2a/grpc/mapper/DataPartMapper.java | 35 - ...askPushNotificationConfigParamsMapper.java | 12 +- .../io/a2a/grpc/mapper/FilePartMapper.java | 81 -- ...askPushNotificationConfigParamsMapper.java | 18 +- ...askPushNotificationConfigParamsMapper.java | 10 +- .../io/a2a/grpc/mapper/OAuthFlowsMapper.java | 2 + .../java/io/a2a/grpc/mapper/PartMapper.java | 71 +- .../io/a2a/grpc/mapper/SecurityMapper.java | 38 +- .../mapper/SubscribeToTaskRequestMapper.java | 6 +- .../a2a/grpc/mapper/TaskIdParamsMapper.java | 8 +- .../TaskPushNotificationConfigMapper.java | 76 +- .../grpc/mapper/TaskQueryParamsMapper.java | 4 +- .../io/a2a/grpc/mapper/TaskStateMapper.java | 4 +- .../mapper/TaskStatusUpdateEventMapper.java | 26 +- spec-grpc/src/main/proto/a2a.proto | 218 ++-- .../grpc/mapper/StreamResponseMapperTest.java | 3 - .../io/a2a/grpc/utils/JSONRPCUtilsTest.java | 20 +- .../java/io/a2a/grpc/utils/ToProtoTest.java | 81 +- .../java/io/a2a/spec/A2AProtocolError.java | 29 + spec/src/main/java/io/a2a/spec/AgentCard.java | 47 +- .../main/java/io/a2a/spec/AgentInterface.java | 28 +- .../src/main/java/io/a2a/spec/AgentSkill.java | 16 +- .../java/io/a2a/spec/AuthenticationInfo.java | 11 +- spec/src/main/java/io/a2a/spec/DataPart.java | 49 +- .../GetTaskPushNotificationConfigParams.java | 13 +- .../ListTaskPushNotificationConfigParams.java | 2 + .../main/java/io/a2a/spec/SecurityScheme.java | 2 +- .../io/a2a/spec/TaskStatusUpdateEvent.java | 39 +- .../io/a2a/spec/VersionNotSupportedError.java | 2 +- .../io/a2a/tck/server/AgentCardProducer.java | 2 - .../a2a/tck/server/AgentExecutorProducer.java | 18 +- .../apps/common/AbstractA2AServerTest.java | 58 +- .../server/apps/common/AgentCardProducer.java | 3 - .../transport/grpc/handler/GrpcHandler.java | 15 +- .../grpc/handler/GrpcHandlerTest.java | 276 ++-- .../jsonrpc/handler/JSONRPCHandler.java | 2 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 22 +- .../transport/rest/handler/RestHandler.java | 2 +- .../rest/handler/RestHandlerTest.java | 34 +- 142 files changed, 7092 insertions(+), 5569 deletions(-) delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/DataPart.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/DataPartOrBuilder.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/FilePart.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/FilePartOrBuilder.java create mode 100644 spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java create mode 100644 spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java create mode 100644 spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java create mode 100644 spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java rename spec-grpc/src/main/java/io/a2a/grpc/{Security.java => SecurityRequirement.java} (84%) rename spec-grpc/src/main/java/io/a2a/grpc/{SecurityOrBuilder.java => SecurityRequirementOrBuilder.java} (94%) delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/DataPartMapper.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/FilePartMapper.java diff --git a/README.md b/README.md index 941419f45..bd86952da 100644 --- a/README.md +++ b/README.md @@ -612,24 +612,24 @@ client.deleteTaskPushNotificationConfigurations( new DeleteTaskPushNotificationConfigParams("task-1234", "config-4567", clientCallContext); ``` -#### Resubscribe to a task +#### Subscribe to a task ```java -// Resubscribe to an ongoing task with id "task-1234" using configured consumers +// Subscribe to an ongoing task with id "task-1234" using configured consumers TaskIdParams taskIdParams = new TaskIdParams("task-1234"); -client.resubscribe(taskIdParams); +client.subscribeToTask(taskIdParams); -// Or resubscribe with custom consumers and error handler +// Or subscribe with custom consumers and error handler List> customConsumers = List.of( - (event, card) -> System.out.println("Resubscribe event: " + event) + (event, card) -> System.out.println("Subscribe event: " + event) ); Consumer customErrorHandler = error -> - System.err.println("Resubscribe error: " + error.getMessage()); + System.err.println("Subscribe error: " + error.getMessage()); -client.resubscribe(taskIdParams, customConsumers, customErrorHandler); +client.subscribeToTask(taskIdParams, customConsumers, customErrorHandler); // You can also optionally specify a ClientCallContext with call-specific config to use -client.resubscribe(taskIdParams, clientCallContext); +client.subscribeToTask(taskIdParams, clientCallContext); ``` #### Retrieve details about the server agent that this client agent is communicating with 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 c47d8238b..c3c8c648f 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java @@ -318,7 +318,7 @@ public abstract void deleteTaskPushNotificationConfigurations( @Nullable ClientCallContext context) throws A2AClientException; /** - * Resubscribe to a task's event stream. + * Subscribe to a task's event stream. * This is only available if both the client and server support streaming. * The configured client consumers will be used to handle messages, tasks, * and update events received from the remote agent. The configured streaming @@ -327,12 +327,12 @@ public abstract void deleteTaskPushNotificationConfigurations( * @param request the parameters specifying which task's notification configs to delete * @throws A2AClientException if resubscribing fails for any reason */ - public void resubscribe(@NonNull TaskIdParams request) throws A2AClientException { - resubscribe(request, consumers, streamingErrorHandler, null); + public void subscribeToTask(@NonNull TaskIdParams request) throws A2AClientException { + subscribeToTask(request, consumers, streamingErrorHandler, null); } /** - * Resubscribe to a task's event stream. + * Subscribe to a task's event stream. * This is only available if both the client and server support streaming. * The configured client consumers will be used to handle messages, tasks, * and update events received from the remote agent. The configured streaming @@ -342,13 +342,13 @@ public void resubscribe(@NonNull TaskIdParams request) throws A2AClientException * @param context optional client call context for the request * @throws A2AClientException if resubscribing fails for any reason */ - public void resubscribe(@NonNull TaskIdParams request, + public void subscribeToTask(@NonNull TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { - resubscribe(request, consumers, streamingErrorHandler, context); + subscribeToTask(request, consumers, streamingErrorHandler, context); } /** - * Resubscribe to a task's event stream. + * Subscribe to a task's event stream. * This is only available if both the client and server support streaming. * The specified client consumers will be used to handle messages, tasks, and * update events received from the remote agent. The specified streaming error @@ -359,14 +359,14 @@ public void resubscribe(@NonNull TaskIdParams request, * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs * @throws A2AClientException if resubscribing fails for any reason */ - public void resubscribe(@NonNull TaskIdParams request, + public void subscribeToTask(@NonNull TaskIdParams request, @NonNull List> consumers, @Nullable Consumer streamingErrorHandler) throws A2AClientException { - resubscribe(request, consumers, streamingErrorHandler, null); + subscribeToTask(request, consumers, streamingErrorHandler, null); } /** - * Resubscribe to a task's event stream. + * Subscribe to a task's event stream. * This is only available if both the client and server support streaming. * The specified client consumers will be used to handle messages, tasks, and * update events received from the remote agent. The specified streaming error @@ -378,7 +378,7 @@ public void resubscribe(@NonNull TaskIdParams request, * @param context optional client call context for the request * @throws A2AClientException if resubscribing fails for any reason */ - public abstract void resubscribe(@NonNull TaskIdParams request, + public abstract void subscribeToTask(@NonNull TaskIdParams request, @NonNull List> consumers, @Nullable Consumer streamingErrorHandler, @Nullable ClientCallContext context) throws A2AClientException; 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 405155ee2..e60cac4e5 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -152,7 +152,7 @@ * * // Later, reconnect and resume receiving events * String taskId = "task-123"; // From original request - * client.resubscribe( + * client.subscribeToTask( * new TaskIdParams(taskId), * List.of((event, card) -> { * // Process events from where we left off @@ -529,7 +529,7 @@ public void deleteTaskPushNotificationConfigurations( } /** - * Resubscribe to an existing task to receive remaining events. + * Subscribe to an existing task to receive remaining events. *

    * This method is useful when a client disconnects during a long-running task and wants to * resume receiving events without starting a new task. The agent will deliver any events @@ -551,7 +551,7 @@ public void deleteTaskPushNotificationConfigurations( * // ... client1 disconnects ... * * // Later, reconnect (client2) - * client2.resubscribe( + * client2.subscribeToTask( * new TaskIdParams(taskId), * List.of((event, card) -> { * if (event instanceof TaskUpdateEvent tue) { @@ -559,19 +559,19 @@ public void deleteTaskPushNotificationConfigurations( * tue.getTask().status().state()); * } * }), - * throwable -> System.err.println("Resubscribe error: " + throwable), + * throwable -> System.err.println("Subscribe error: " + throwable), * null * ); * }

    * - * @param request the task ID to resubscribe to + * @param request the task ID to subscribe to * @param consumers the event consumers for processing events (required) * @param streamingErrorHandler error handler for streaming errors (optional) * @param context custom call context for request interceptors (optional) - * @throws A2AClientException if resubscription is not supported or if the task cannot be found + * @throws A2AClientException if subscription is not supported or if the task cannot be found */ @Override - public void resubscribe(@NonNull TaskIdParams request, + public void subscribeToTask(@NonNull TaskIdParams request, @NonNull List> consumers, @Nullable Consumer streamingErrorHandler, @Nullable ClientCallContext context) throws A2AClientException { @@ -588,7 +588,7 @@ public void resubscribe(@NonNull TaskIdParams request, overriddenErrorHandler.accept(e); } }; - clientTransport.resubscribe(request, eventHandler, overriddenErrorHandler, context); + clientTransport.subscribeToTask(request, eventHandler, overriddenErrorHandler, context); } /** diff --git a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java b/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java index 58b528881..5b8d9c94a 100644 --- a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java +++ b/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java @@ -1,6 +1,5 @@ package io.a2a.client; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockserver.model.HttpRequest.request; @@ -90,7 +89,6 @@ public void setUp() { .description("Test skill") .tags(Collections.singletonList("test")) .build())) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .supportedInterfaces(java.util.Arrays.asList( new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_URL), new AgentInterface(TransportProtocol.HTTP_JSON.asString(), AGENT_URL), diff --git a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java index dd38c937d..3be9d4918 100644 --- a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java +++ b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java @@ -1,6 +1,5 @@ package io.a2a.client; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import java.util.Collections; import java.util.List; @@ -41,7 +40,6 @@ public class ClientBuilderTest { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .supportedInterfaces(List.of( new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))) .build(); 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 8cc67d7b0..7824e83c0 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 @@ -142,7 +142,7 @@ public void sendMessageStreaming(MessageSendParams request, Consumer eventConsumer, + public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); checkNotNullParam("eventConsumer", eventConsumer); io.a2a.grpc.SubscribeToTaskRequest grpcRequest = io.a2a.grpc.SubscribeToTaskRequest.newBuilder() .setTenant(resolveTenant(request.tenant())) - .setName("tasks/" + request.id()) + .setId(request.id()) .build(); PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, grpcRequest, agentCard, context); @@ -331,12 +336,13 @@ public void resubscribe(TaskIdParams request, Consumer event A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders); stubWithMetadata.subscribeToTask(grpcRequest, streamObserver); } catch (StatusRuntimeException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to resubscribe task push notification config: "); + throw GrpcErrorMapper.mapGrpcError(e, "Failed to subscribe task push notification config: "); } } /** * Ensure tenant is set, using agent default if not provided in request + * * @param request the initial request. * @return the updated request with the tenant set. */ @@ -447,24 +453,6 @@ private A2AServiceStub createAsyncStubWithMetadata(@Nullable ClientCallContext c return asyncStub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(metadata)); } - private String getTaskPushNotificationConfigName(GetTaskPushNotificationConfigParams params) { - return getTaskPushNotificationConfigName(params.id(), params.pushNotificationConfigId()); - } - - private String getTaskPushNotificationConfigName(String taskId, @Nullable String pushNotificationConfigId) { - StringBuilder name = new StringBuilder(); - name.append("tasks/"); - name.append(taskId); - if (pushNotificationConfigId != null) { - name.append("/pushNotificationConfigs/"); - name.append(pushNotificationConfigId); - } - //name.append("/pushNotificationConfigs/"); - // Use taskId as default config ID if none provided - //name.append(pushNotificationConfigId != null ? pushNotificationConfigId : taskId); - return name.toString(); - } - private PayloadAndHeaders applyInterceptors(String methodName, Object payload, AgentCard agentCard, @Nullable ClientCallContext clientCallContext) { PayloadAndHeaders payloadAndHeaders = new PayloadAndHeaders(payload, 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 21ea398c1..9b8af4ea2 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 @@ -255,7 +255,7 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC } @Override - public void resubscribe(TaskIdParams request, Consumer eventConsumer, + public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); checkNotNullParam("eventConsumer", eventConsumer); 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 c994ff89d..b06d07648 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 @@ -2,8 +2,8 @@ import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.SEND_MESSAGE_STREAMING_TEST_REQUEST; import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.SEND_MESSAGE_STREAMING_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.TASK_RESUBSCRIPTION_TEST_REQUEST; +import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.TASK_SUBSCRIPTION_TEST_REQUEST; +import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.TASK_SUBSCRIPTION_REQUEST_TEST_RESPONSE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -124,19 +124,17 @@ public void testA2AClientSendStreamingMessage() throws Exception { } @Test - public void testA2AClientResubscribeToTask() throws Exception { - this.server.when( - request() + public void testA2AClientSubscribeToTask() throws Exception { + this.server.when(request() .withMethod("POST") .withPath("/") - .withBody(JsonBody.json(TASK_RESUBSCRIPTION_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + .withBody(JsonBody.json(TASK_SUBSCRIPTION_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) ) - .respond( - response() + .respond(response() .withStatusCode(200) .withHeader("Content-Type", "text/event-stream") - .withBody(TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE) + .withBody(TASK_SUBSCRIPTION_REQUEST_TEST_RESPONSE) ); JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); @@ -149,7 +147,7 @@ public void testA2AClientResubscribeToTask() throws Exception { latch.countDown(); }; Consumer errorHandler = error -> {}; - client.resubscribe(taskIdParams, eventHandler, errorHandler, null); + client.subscribeToTask(taskIdParams, eventHandler, errorHandler, null); boolean eventReceived = latch.await(10, TimeUnit.SECONDS); assertTrue(eventReceived); diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 74fe9545a..f6677ff13 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -22,7 +22,7 @@ import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE; import static io.a2a.client.transport.jsonrpc.JsonMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; import static io.a2a.client.transport.jsonrpc.JsonMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; +import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -313,8 +313,7 @@ public void testA2AClientGetTaskPushNotificationConfig() throws Exception { assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertTrue(authenticationInfo.schemes().size() == 1); - assertEquals("jwt", authenticationInfo.schemes().get(0)); + assertEquals("jwt", authenticationInfo.scheme()); } @Test @@ -338,15 +337,13 @@ public void testA2AClientCreateTaskPushNotificationConfig() throws Exception { PushNotificationConfig.builder() .id("c295ea44-7543-4f78-b524-7a38915ad6e4") .url("https://example.com/callback") - .authentication(new AuthenticationInfo(Collections.singletonList("jwt"), - null)) + .authentication(new AuthenticationInfo("jwt", null)) .build(), ""), null); PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertEquals(1, authenticationInfo.schemes().size()); - assertEquals("jwt", authenticationInfo.schemes().get(0)); + assertEquals("jwt", authenticationInfo.scheme()); } @Test @@ -379,7 +376,7 @@ public void testA2AClientGetExtendedAgentCard() throws Exception { assertNotNull(securitySchemes); OpenIdConnectSecurityScheme google = (OpenIdConnectSecurityScheme) securitySchemes.get("google"); assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.openIdConnectUrl()); - List>> security = agentCard.security(); + List>> security = agentCard.securityRequirements(); assertEquals(1, security.size()); Map> securityMap = security.get(0); List scopes = securityMap.get("google"); @@ -418,7 +415,7 @@ public void testA2AClientGetExtendedAgentCard() throws Exception { assertEquals("This is an extended skill.", skills.get(2).description()); assertEquals(List.of("extended"), skills.get(2).tags()); assertEquals("https://georoute-agent.example.com/icon.png", agentCard.iconUrl()); - assertEquals(CURRENT_PROTOCOL_VERSION, agentCard.protocolVersions().get(0)); + assertEquals(CURRENT_PROTOCOL_VERSION, agentCard.supportedInterfaces().get(0).protocolVersion()); } @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 211f5e4f6..b55c0f9d1 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 @@ -1,6 +1,6 @@ package io.a2a.client.transport.jsonrpc; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; +import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; /** * Request and response messages used by the tests. These have been created following examples from @@ -8,9 +8,8 @@ */ public class JsonMessages { - static final String AGENT_CARD = String.format(""" + static final String AGENT_CARD = """ { - "protocolVersions": ["%s"], "name": "GeoSpatial Route Planner Agent", "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", "supportedInterfaces" : [ @@ -37,7 +36,7 @@ public class JsonMessages { } } }, - "security": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], + "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], "defaultInputModes": ["application/json", "text/plain"], "defaultOutputModes": ["application/json", "image/png"], "skills": [ @@ -81,7 +80,7 @@ public class JsonMessages { "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" } ] - }""", CURRENT_PROTOCOL_VERSION); + }"""; static final String SEND_MESSAGE_TEST_REQUEST = """ { @@ -228,7 +227,7 @@ public class JsonMessages { "jsonrpc":"2.0", "method":"GetTask", "params":{ - "name":"tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", "historyLength":10 } } @@ -262,16 +261,12 @@ public class JsonMessages { "text":"tell me a joke" }, { - "file":{ - "file_with_uri":"file:///path/to/file.txt", - "mediaType":"text/plain" - } + "url":"file:///path/to/file.txt", + "mediaType":"text/plain" }, { - "file":{ - "file_with_bytes":"aGVsbG8=", - "name":"hello.txt" - } + "raw":"aGVsbG8=", + "filename":"hello.txt" } ], "messageId":"message-123" @@ -289,7 +284,7 @@ public class JsonMessages { "jsonrpc":"2.0", "method":"CancelTask", "params":{ - "name":"tasks/de38c76d-d54c-436c-8b9f-4c2703648d64" + "id":"de38c76d-d54c-436c-8b9f-4c2703648d64" } } """; @@ -302,7 +297,7 @@ public class JsonMessages { "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", "contextId":"c295ea44-7543-4f78-b524-7a38915ad6e4", "status":{ - "state":"TASK_STATE_CANCELLED" + "state":"TASK_STATE_CANCELED" }, "metadata":{ @@ -316,7 +311,8 @@ public class JsonMessages { "jsonrpc":"2.0", "method":"GetTaskPushNotificationConfig", "params":{ - "name":"tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/c295ea44-7543-4f78-b524-7a38915ad6e4" + "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", + "id":"c295ea44-7543-4f78-b524-7a38915ad6e4" } }"""; @@ -325,11 +321,12 @@ public class JsonMessages { "jsonrpc": "2.0", "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "result": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/c295ea44-7543-4f78-b524-7a38915ad6e4", + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "c295ea44-7543-4f78-b524-7a38915ad6e4", "pushNotificationConfig": { "url": "https://example.com/callback", "authentication": { - "schemes": ["jwt"] + "scheme": "jwt" } } } @@ -341,17 +338,12 @@ public class JsonMessages { "jsonrpc":"2.0", "method":"CreateTaskPushNotificationConfig", "params":{ - "parent":"tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", "configId":"c295ea44-7543-4f78-b524-7a38915ad6e4", "config":{ - "name":"tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/c295ea44-7543-4f78-b524-7a38915ad6e4", - "pushNotificationConfig":{ - "url":"https://example.com/callback", - "authentication":{ - "schemes":[ - "jwt" - ] - } + "url":"https://example.com/callback", + "authentication":{ + "scheme":"jwt" } } } @@ -362,11 +354,12 @@ public class JsonMessages { "jsonrpc": "2.0", "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "result": { - "name":"tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/c295ea44-7543-4f78-b524-7a38915ad6e4", + "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", + "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", "pushNotificationConfig": { "url": "https://example.com/callback", "authentication": { - "schemes": ["jwt"] + "scheme": "jwt" } } } @@ -387,10 +380,8 @@ public class JsonMessages { "text":"analyze this image" }, { - "file":{ - "fileWithUri":"file:///path/to/image.jpg", - "mediaType":"image/jpeg" - } + "url":"file:///path/to/image.jpg", + "mediaType":"image/jpeg" } ], "metadata":{ @@ -453,12 +444,10 @@ public class JsonMessages { }, { "data":{ - "data":{ - "temperature":25.5, - "humidity":60.2, - "location":"San Francisco", - "timestamp":"2024-01-15T10:30:00Z" - } + "temperature":25.5, + "humidity":60.2, + "location":"San Francisco", + "timestamp":"2024-01-15T10:30:00Z" } } ], @@ -521,19 +510,15 @@ public class JsonMessages { "text":"analyze this data and image" }, { - "file":{ - "fileWithBytes":"aGVsbG8=", - "mediaType":"image/png", - "name":"chart.png" - } + "raw":"aGVsbG8=", + "mediaType":"image/png", + "filename":"chart.png" }, { "data":{ - "data":{ - "chartType":"bar", - "dataPoints":[10.0, 20.0, 30.0, 40.0], - "labels":["Q1", "Q2", "Q3", "Q4"] - } + "chartType":"bar", + "dataPoints":[10.0, 20.0, 30.0, 40.0], + "labels":["Q1", "Q2", "Q3", "Q4"] } } ], @@ -589,7 +574,7 @@ public class JsonMessages { } """; - static final String GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE = String.format(""" + static final String GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE = """ { "jsonrpc": "2.0", "id": "1", @@ -618,7 +603,7 @@ public class JsonMessages { } } }, - "security": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], + "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], "defaultInputModes": ["application/json", "text/plain"], "defaultOutputModes": ["application/json", "image/png"], "skills": [ @@ -662,7 +647,6 @@ public class JsonMessages { "tags": ["extended"] } ], - "protocolVersions": ["%s"], "signatures": [ { "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdUI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", @@ -670,9 +654,9 @@ public class JsonMessages { } ] } - }""", CURRENT_PROTOCOL_VERSION); + }"""; - static final String AGENT_CARD_SUPPORTS_EXTENDED = String.format(""" + static final String AGENT_CARD_SUPPORTS_EXTENDED = """ { "name": "GeoSpatial Route Planner Agent", "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", @@ -735,7 +719,6 @@ public class JsonMessages { "text/html" ] } - ], - "protocolVersions": ["%s"] - }""", CURRENT_PROTOCOL_VERSION); + ] + }"""; } diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java index 021c6c7f6..39f2d7859 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java @@ -50,8 +50,7 @@ public class JsonStreamingMessages { "contextId": "2", "status": { "state": "TASK_STATE_SUBMITTED" - }, - "final": false + } } } }"""; @@ -66,8 +65,7 @@ public class JsonStreamingMessages { "contextId": "2", "status": { "state": "TASK_STATE_COMPLETED" - }, - "final": true + } } } }"""; @@ -141,19 +139,19 @@ public class JsonStreamingMessages { """; - static final String TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE = + static final String TASK_SUBSCRIPTION_REQUEST_TEST_RESPONSE = """ event: message data: {"jsonrpc":"2.0","id":1,"result":{"task":{"id":"2","contextId":"context-1234","status":{"state":"TASK_STATE_COMPLETED"},"artifacts":[{"artifactId":"artifact-1","name":"joke","parts":[{"text":"Why did the chicken cross the road? To get to the other side!"}]}],"metadata":{}}}} """; - public static final String TASK_RESUBSCRIPTION_TEST_REQUEST = """ + public static final String TASK_SUBSCRIPTION_TEST_REQUEST = """ { "jsonrpc":"2.0", "method":"SubscribeToTask", "params":{ - "name":"tasks/task-1234" + "id":"task-1234" } }"""; } \ No newline at end of file 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 0817b753f..23e162e7c 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 @@ -184,12 +184,15 @@ public void testOnFailure() { @Test public void testFinalTaskStatusUpdateEventCancels() { - TaskStatusUpdateEvent tsue = TaskStatusUpdateEvent.builder() - .taskId("1234") - .contextId("xyz") - .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) - .build(); + TaskStatus completedStatus = new TaskStatus(TaskState.COMPLETED); + // Use constructor since Builder doesn't have isFinal method + TaskStatusUpdateEvent tsue = new TaskStatusUpdateEvent( + "1234", + completedStatus, + "xyz", + completedStatus.state().isFinal(), // Derive from state + null + ); // Set up event handler AtomicReference receivedEvent = new AtomicReference<>(); 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 88c86846d..61fb29428 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 @@ -27,7 +27,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.util.JsonFormat; -import io.a2a.client.http.A2ACardResolver; import io.a2a.client.http.A2AHttpClient; import io.a2a.client.http.A2AHttpClientFactory; import io.a2a.client.http.A2AHttpResponse; @@ -132,7 +131,7 @@ public void sendMessageStreaming(MessageSendParams messageSendParams, Consumer eventConsumer, + public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); io.a2a.grpc.SubscribeToTaskRequest.Builder builder = io.a2a.grpc.SubscribeToTaskRequest.newBuilder(); - builder.setName("tasks/" + request.id()); + builder.setId(request.id()); PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, builder, agentCard, context); AtomicReference> ref = new AtomicReference<>(); diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java index f324f004e..35ac4a9c5 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java @@ -48,7 +48,7 @@ public class JsonRestMessages { static final String CANCEL_TASK_TEST_REQUEST = """ { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64" + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64" }"""; static final String CANCEL_TASK_TEST_RESPONSE = """ @@ -56,7 +56,7 @@ public class JsonRestMessages { "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", "status": { - "state": "TASK_STATE_CANCELLED" + "state": "TASK_STATE_CANCELED" }, "metadata": {} }"""; @@ -86,16 +86,12 @@ public class JsonRestMessages { "text": "tell me a joke" }, { - "file": { - "file_with_uri": "file:///path/to/file.txt", - "mediaType": "text/plain" - } + "url": "file:///path/to/file.txt", + "mediaType": "text/plain" }, { - "file": { - "file_with_bytes": "aGVsbG8=", - "mediaType": "text/plain" - } + "raw": "aGVsbG8=", + "mediaType": "text/plain" } ], "messageId": "message-123" @@ -129,7 +125,7 @@ public class JsonRestMessages { "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" } }, - "security": [{ "google": ["openid", "profile", "email"] }], + "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], "defaultInputModes": ["application/json", "text/plain"], "defaultOutputModes": ["application/json", "image/png"], "skills": [ @@ -195,7 +191,7 @@ public class JsonRestMessages { "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" } }, - "security": [{ "google": ["openid", "profile", "email"] }], + "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], "defaultInputModes": ["application/json", "text/plain"], "defaultOutputModes": ["application/json", "image/png"], "skills": [ @@ -261,7 +257,7 @@ public class JsonRestMessages { "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" } }, - "security": [{ "google": ["openid", "profile", "email"] }], + "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], "defaultInputModes": ["application/json", "text/plain"], "defaultOutputModes": ["application/json", "image/png"], "skills": [ @@ -311,11 +307,12 @@ public class JsonRestMessages { static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10", + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "10", "pushNotificationConfig": { "url": "https://example.com/callback", "authentication": { - "schemes": ["jwt"] + "scheme": "jwt" } } }"""; @@ -323,16 +320,18 @@ public class JsonRestMessages { { "configs":[ { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10", + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "10", "pushNotificationConfig": { "url": "https://example.com/callback", "authentication": { - "schemes": ["jwt"] + "scheme": "jwt" } } }, { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/5", + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "5", "pushNotificationConfig": { "url": "https://test.com/callback" } @@ -343,26 +342,24 @@ public class JsonRestMessages { static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ { - "parent": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", "configId": "default-config-id", "config": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/default-config-id", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "authentication": { - "schemes": [ "jwt" ] - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } } }"""; static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10", + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "10", "pushNotificationConfig": { "url": "https://example.com/callback", "authentication": { - "schemes": ["jwt"] + "scheme": "jwt" } } }"""; diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index 04efb4eca..476a93ba2 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -13,7 +13,6 @@ import static io.a2a.client.transport.rest.JsonRestMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; import static io.a2a.client.transport.rest.JsonRestMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; import static io.a2a.client.transport.rest.JsonRestMessages.TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -90,7 +89,6 @@ public class RestTransportTest { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); @BeforeEach @@ -309,15 +307,14 @@ public void testCreateTaskPushNotificationConfiguration() throws Exception { .id("default-config-id") .url("https://example.com/callback") .authentication( - new AuthenticationInfo(Collections.singletonList("jwt"), null)) + new AuthenticationInfo("jwt", null)) .build(), "tenant"); TaskPushNotificationConfig taskPushNotificationConfig = client.createTaskPushNotificationConfiguration(pushedConfig, null); PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertEquals(1, authenticationInfo.schemes().size()); - assertEquals("jwt", authenticationInfo.schemes().get(0)); + assertEquals("jwt", authenticationInfo.scheme()); } /** @@ -343,8 +340,7 @@ public void testGetTaskPushNotificationConfiguration() throws Exception { assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertTrue(authenticationInfo.schemes().size() == 1); - assertEquals("jwt", authenticationInfo.schemes().get(0)); + assertEquals("jwt", authenticationInfo.scheme()); } /** @@ -372,8 +368,7 @@ public void testListTaskPushNotificationConfigurations() throws Exception { assertEquals("https://example.com/callback", pushNotificationConfig.url()); assertEquals("10", pushNotificationConfig.id()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertTrue(authenticationInfo.schemes().size() == 1); - assertEquals("jwt", authenticationInfo.schemes().get(0)); + assertEquals("jwt", authenticationInfo.scheme()); assertEquals("", authenticationInfo.credentials()); pushNotificationConfig = result.configs().get(1).pushNotificationConfig(); assertNotNull(pushNotificationConfig); @@ -404,11 +399,11 @@ public void testDeleteTaskPushNotificationConfigurations() throws Exception { } /** - * Test of resubscribe method, of class JSONRestTransport. + * Test of subscribe method, of class JSONRestTransport. */ @Test - public void testResubscribe() throws Exception { - log.info("Testing resubscribe"); + public void testSubscribe() throws Exception { + log.info("Testing subscribeToTask"); this.server.when( request() @@ -432,7 +427,7 @@ public void testResubscribe() throws Exception { latch.countDown(); }; Consumer errorHandler = error -> {}; - client.resubscribe(taskIdParams, eventHandler, errorHandler, null); + client.subscribeToTask(taskIdParams, eventHandler, errorHandler, null); boolean eventReceived = latch.await(10, TimeUnit.SECONDS); assertTrue(eventReceived); diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java index 1a2bd7f26..eed199ab3 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java @@ -151,8 +151,7 @@ public void testOnMessageWithStatusUpdateEvent() { "contextId": "2", "status": { "state": "TASK_STATE_SUBMITTED" - }, - "final": false + } } } """; @@ -187,8 +186,7 @@ public void testOnMessageWithFinalStatusUpdateEventCancels() { "contextId": "2", "status": { "state": "TASK_STATE_COMPLETED" - }, - "final": true + } } } """; 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 504e4c601..82fe40996 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 @@ -127,13 +127,13 @@ void deleteTaskPushNotificationConfigurations( /** * Reconnect to get task updates for an existing task. * - * @param request the task ID parameters specifying which task to resubscribe to + * @param request the task ID parameters specifying which task to subscribe to * @param eventConsumer consumer that will receive streaming events as they arrive * @param errorConsumer consumer that will be called if an error occurs during streaming * @param context optional client call context for the request (may be {@code null}) - * @throws A2AClientException if resubscribing to the task fails for any reason + * @throws A2AClientException if subscribing to the task fails for any reason */ - void resubscribe(TaskIdParams request, Consumer eventConsumer, + void subscribeToTask(TaskIdParams request, Consumer eventConsumer, Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException; /** diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java index 3573d6784..6cfc322da 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java @@ -35,10 +35,10 @@ public AuthInterceptor(final CredentialService credentialService) { public PayloadAndHeaders intercept(String methodName, @Nullable Object payload, Map headers, @Nullable AgentCard agentCard, @Nullable ClientCallContext clientCallContext) { Map updatedHeaders = new HashMap<>(headers == null ? new HashMap<>() : headers); - if (agentCard == null || agentCard.security() == null || agentCard.securitySchemes() == null) { + if (agentCard == null || agentCard.securityRequirements()== null || agentCard.securitySchemes() == null) { return new PayloadAndHeaders(payload, updatedHeaders); } - for (Map> requirement : agentCard.security()) { + for (Map> requirement : agentCard.securityRequirements()) { for (String securitySchemeName : requirement.keySet()) { String credential = credentialService.getCredential(securitySchemeName, clientCallContext); if (credential != null && agentCard.securitySchemes().containsKey(securitySchemeName)) { 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 a9f07c83e..9ea69f354 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 @@ -235,7 +235,7 @@ void testAvailableSecuritySchemeNotInAgentCardSecuritySchemes() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .security(List.of(Map.of(schemeName, List.of()))) + .securityRequirements(List.of(Map.of(schemeName, List.of()))) .securitySchemes(Map.of()) // no security schemes .build(); @@ -289,7 +289,7 @@ void testNoAgentCardSecuritySpecified() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .security(null) // no security info + .securityRequirements(null) // no security info .build(); Map requestPayload = Map.of("test", "payload"); @@ -321,7 +321,7 @@ private AgentCard createAgentCard(String schemeName, SecurityScheme securitySche .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .security(List.of(Map.of(schemeName, List.of()))) + .securityRequirements(List.of(Map.of(schemeName, List.of()))) .securitySchemes(Map.of(schemeName, securityScheme)) .build(); } diff --git a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java index 3b0f37b2e..ac1392c5e 100644 --- a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java +++ b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java @@ -118,12 +118,14 @@ private static Task createTask(TaskState state) { } private static TaskStatusUpdateEvent createTaskStatusUpdateEvent(TaskState state, boolean isFinal) { - return TaskStatusUpdateEvent.builder() - .taskId(TEST_TASK_ID) - .contextId(TEST_CONTEXT_ID) - .status(new TaskStatus(state)) - .isFinal(isFinal) - .build(); + // Use constructor since Builder doesn't have isFinal method + return new TaskStatusUpdateEvent( + TEST_TASK_ID, + new TaskStatus(state), + TEST_CONTEXT_ID, + isFinal, + null + ); } private static TestSSEEventListener createListenerWithEventCapture(AtomicReference eventCapture) { diff --git a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java b/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java index e96c6f1c1..b3adbcdd8 100644 --- a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java +++ b/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java @@ -1,6 +1,5 @@ package io.a2a.examples.cloud; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import java.util.Collections; import java.util.List; @@ -57,7 +56,6 @@ public AgentCard agentCard() { )) .build() )) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } } diff --git a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java b/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java index b29b0b55f..0dce363df 100644 --- a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java +++ b/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java @@ -199,7 +199,7 @@ private void subscribeToTaskUpdates() { Thread.sleep(1000); // Wait for Kafka events to propagate } - streamingClient.resubscribe( + streamingClient.subscribeToTask( new TaskIdParams(serverTaskId), List.of(this::handleSubscriptionEvent), this::handleSubscriptionError diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java index 165b1574e..3725e1bd7 100644 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java +++ b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java @@ -1,6 +1,5 @@ package io.a2a.examples.helloworld; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import java.util.Collections; import java.util.List; @@ -42,7 +41,6 @@ public AgentCard agentCard() { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } } 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 ab06747de..0366e236a 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 @@ -129,7 +129,7 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep // Step 3: Verify the configuration was stored using client API TaskPushNotificationConfig storedConfig = client.getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams(taskId)); + new GetTaskPushNotificationConfigParams(taskId, "test-config-1")); assertNotNull(storedConfig); assertEquals(taskId, storedConfig.taskId()); @@ -183,7 +183,7 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep // Verify deletion by asserting that getting the config now throws an exception assertThrows(A2AClientException.class, () -> { - client.getTaskPushNotificationConfiguration(new GetTaskPushNotificationConfigParams(taskId)); + client.getTaskPushNotificationConfiguration(new GetTaskPushNotificationConfigParams(taskId, "test-config-1")); }, "Getting a deleted config should throw an A2AClientException"); } 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 44dfbe427..a5e3c629c 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 @@ -16,7 +16,6 @@ import io.a2a.server.events.MainEventBus; import io.a2a.server.events.QueueManager; import io.a2a.server.tasks.TaskStateProvider; -import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -170,7 +169,6 @@ public void onTaskFinalized(@Observes(during = TransactionPhase.AFTER_SUCCESS) T .taskId(taskId) .contextId(finalTask.contextId()) .status(finalTask.status()) - .isFinal(true) .build(); // Send TaskStatusUpdateEvent FIRST to ensure it arrives before poison pill 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 ca781b5b0..33eaa908f 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 @@ -110,7 +110,6 @@ public void testTaskStatusUpdateEventSerialization() throws JsonProcessingExcept .taskId("test-task-abc") .contextId("test-context-def") .status(status) - .isFinal(true) .build(); // Test serialization as Event @@ -206,7 +205,6 @@ public void testReplicatedEventWithStreamingEventSerialization() throws JsonProc .taskId("replicated-test-task") .contextId("replicated-test-context") .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .build(); // Create ReplicatedEventQueueItem with StreamingEventKind @@ -280,7 +278,6 @@ public void testReplicatedEventBackwardCompatibility() throws JsonProcessingExce .taskId("backward-compat-task") .contextId("backward-compat-context") .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) .build(); // Use the backward compatibility constructor 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 14b4c1f51..b766863aa 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 @@ -67,7 +67,6 @@ void setUp() { .taskId("test-task") .contextId("test-context") .status(new TaskStatus(TaskState.SUBMITTED)) - .isFinal(false) .build(); } @@ -80,7 +79,6 @@ private TaskStatusUpdateEvent createEventForTask(String taskId) { .taskId(taskId) .contextId("test-context") .status(new TaskStatus(TaskState.SUBMITTED)) - .isFinal(false) .build(); } @@ -277,7 +275,6 @@ void testReplicatedEventJsonSerialization() throws Exception { .taskId("json-test-task") .contextId("json-test-context") .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) .build(); ReplicatedEventQueueItem original = new ReplicatedEventQueueItem("json-test-task", originalEvent); @@ -350,7 +347,6 @@ public void onTaskFinalized(String tid) { .taskId(taskId) // Use same taskId as queue .contextId("test-context") .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .build(); queue.enqueueEvent(event); } @@ -376,7 +372,6 @@ public void onTaskFinalized(String tid) { .taskId(taskId) // Use same taskId as queue .contextId("test-context") .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, event); queueManager.onReplicatedEvent(replicatedEvent); @@ -505,7 +500,6 @@ void testReplicatedEventToExistingQueueWhenTaskBecomesInactive() throws Interrup .taskId(taskId) .contextId("test-context") .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, newEvent); queueManager.onReplicatedEvent(replicatedEvent); 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 4638f7385..81bb9ffe0 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 @@ -44,7 +44,6 @@ public void setUp() { .taskId("test-task") .contextId("test-context") .status(new TaskStatus(TaskState.SUBMITTED)) - .isFinal(false) .build(); } @@ -54,7 +53,6 @@ private String createValidJsonMessage(String taskId, String contextId) throws Ex .taskId(taskId) .contextId(contextId) .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, event); return JsonUtil.toJson(replicatedEvent); diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java index a8020f5ae..4d1133ad9 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java @@ -1,6 +1,5 @@ package io.a2a.extras.queuemanager.replicated.tests.multiinstance.common; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import java.util.Collections; import java.util.List; @@ -47,7 +46,6 @@ public static AgentCard createAgentCard(int instanceNumber, int port) { .description("Fire-and-forget agent for testing replication") .tags(Collections.singletonList("test")) .build())) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } } diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java index b98f0e87d..81bc23af3 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java @@ -244,7 +244,7 @@ public void testInfrastructureStartup() { /** * Main multi-instance replication test following architect's guidance: * 1. Send initial message on app1 (creates task in non-final state) - * 2. Resubscribe to that task from both app1 and app2 + * 2. Subscribe to that task from both app1 and app2 * 3. Send message on app1, verify both subscribers receive it * 4. Send message on app2, verify both subscribers receive it * 5. Send final message to transition task to COMPLETED @@ -328,7 +328,7 @@ public void testMultiInstanceEventReplication() throws Exception { } System.out.println("APP1 received event: " + eventDetail); - // Per A2A spec 3.1.6: Handle initial TaskEvent on resubscribe + // Per A2A spec 3.1.6: Handle initial TaskEvent on subscribe if (!app1ReceivedInitialTask.get() && event instanceof io.a2a.client.TaskEvent) { app1ReceivedInitialTask.set(true); System.out.println("APP1 filtered initial TaskEvent"); @@ -360,7 +360,7 @@ public void testMultiInstanceEventReplication() throws Exception { } System.out.println("APP2 received event: " + eventDetail); - // Per A2A spec 3.1.6: Handle initial TaskEvent on resubscribe + // Per A2A spec 3.1.6: Handle initial TaskEvent on subscribe if (!app2ReceivedInitialTask.get() && event instanceof io.a2a.client.TaskEvent) { app2ReceivedInitialTask.set(true); System.out.println("APP2 filtered initial TaskEvent"); @@ -378,9 +378,9 @@ public void testMultiInstanceEventReplication() throws Exception { } }; - // Start subscriptions (resubscribe returns void) - getClient1().resubscribe(new TaskIdParams(taskId), List.of(app1Subscriber), app1ErrorHandler); - getClient2().resubscribe(new TaskIdParams(taskId), List.of(app2Subscriber), app2ErrorHandler); + // Start subscriptions (subscribe returns void) + getClient1().subscribeToTask(new TaskIdParams(taskId), List.of(app1Subscriber), app1ErrorHandler); + getClient2().subscribeToTask(new TaskIdParams(taskId), List.of(app2Subscriber), app2ErrorHandler); // Wait for subscriptions to be established - at least one event should arrive on each await() 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 d38f8244c..26fd1bb2d 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 @@ -227,13 +227,13 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { Thread.sleep(1000); // Set up resubscription to listen for task updates using streaming client - CountDownLatch resubscribeLatch = new CountDownLatch(1); + CountDownLatch subscribeLatch = new CountDownLatch(1); AtomicReference receivedCompletedEvent = new AtomicReference<>(); AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); AtomicReference errorRef = new AtomicReference<>(); AtomicBoolean receivedInitialTask = new AtomicBoolean(false); - // Create consumer to handle resubscribed events + // Create consumer to handle subscribed events BiConsumer consumer = (event, agentCard) -> { // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent if (!receivedInitialTask.get()) { @@ -241,7 +241,7 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { receivedInitialTask.set(true); return; } else { - throw new AssertionError("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + throw new AssertionError("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); } } @@ -250,7 +250,7 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { if (taskUpdateEvent.getUpdateEvent() instanceof TaskStatusUpdateEvent statusEvent) { if (statusEvent.status().state() == TaskState.COMPLETED) { receivedCompletedEvent.set(statusEvent); - resubscribeLatch.countDown(); + subscribeLatch.countDown(); } } else { wasUnexpectedEvent.set(true); @@ -267,18 +267,17 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { if (!isStreamClosedError(error)) { errorRef.set(error); } - resubscribeLatch.countDown(); + subscribeLatch.countDown(); }; - // Resubscribe to the task to listen for updates - streamingClient.resubscribe(new TaskIdParams(taskId), List.of(consumer), errorHandler); + // Subscribe to the task to listen for updates + streamingClient.subscribeToTask(new TaskIdParams(taskId), List.of(consumer), errorHandler); // Now manually send a TaskStatusUpdateEvent to Kafka using reactive messaging TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId(contextId) .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, statusEvent); @@ -289,7 +288,7 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { // Wait for the replicated event to be received via streaming resubscription // This tests the full round-trip: Manual Kafka Event -> A2A System -> Streaming Client - assertTrue(resubscribeLatch.await(15, TimeUnit.SECONDS), "Should receive COMPLETED event via resubscription"); + assertTrue(subscribeLatch.await(15, TimeUnit.SECONDS), "Should receive COMPLETED event via resubscription"); // Verify no unexpected events or errors assertFalse(wasUnexpectedEvent.get(), "Should not receive unexpected events"); @@ -373,8 +372,8 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { streamCompletedLatch.countDown(); }; - // Resubscribe to the task - this creates a streaming subscription - streamingClient.resubscribe(new TaskIdParams(taskId), List.of(consumer), errorHandler); + // Subscribe to the task - this creates a streaming subscription + streamingClient.subscribeToTask(new TaskIdParams(taskId), List.of(consumer), errorHandler); // Wait for the EventConsumer to start polling (replaces unreliable Thread.sleep) // This ensures the consumer is ready to receive the QueueClosedEvent diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java index 9b5bea30f..3461ab7d4 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java @@ -1,6 +1,5 @@ package io.a2a.extras.queuemanager.replicated.tests; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import java.util.List; @@ -38,7 +37,6 @@ public AgentCard agentCard() { .skills(List.of()) .supportedInterfaces(List.of( new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:8081"))) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } } \ No newline at end of file diff --git a/http-client/src/test/java/io/a2a/client/http/JsonMessages.java b/http-client/src/test/java/io/a2a/client/http/JsonMessages.java index eff6d55e5..89d146787 100644 --- a/http-client/src/test/java/io/a2a/client/http/JsonMessages.java +++ b/http-client/src/test/java/io/a2a/client/http/JsonMessages.java @@ -8,7 +8,6 @@ public class JsonMessages { static final String AGENT_CARD = """ { - "protocolVersions": ["0.2.9"], "name": "GeoSpatial Route Planner Agent", "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", "supportedInterfaces" : [ @@ -34,7 +33,7 @@ public class JsonMessages { } } }, - "security": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], + "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], "defaultInputModes": ["application/json", "text/plain"], "defaultOutputModes": ["application/json", "image/png"], "skills": [ diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index c0aea8ad2..77452f93e 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -567,9 +567,9 @@ public void write(JsonWriter out, Part value) throws java.io.IOException { out.name(FILE); delegateGson.toJson(filePart.file(), FileContent.class, out); } else if (value instanceof DataPart dataPart) { - // DataPart: { "data": {...} } + // DataPart: { "data": } out.name(DATA); - delegateGson.toJson(dataPart.data(), Map.class, out); + delegateGson.toJson(dataPart.data(), Object.class, out); } else { throw new JsonSyntaxException("Unknown Part subclass: " + value.getClass().getName()); } @@ -605,12 +605,12 @@ Part read(JsonReader in) throws java.io.IOException { case TEXT -> new TextPart(jsonObject.get(TEXT).getAsString()); case FILE -> new FilePart(delegateGson.fromJson(jsonObject.get(FILE), FileContent.class)); case DATA -> { - @SuppressWarnings("unchecked") - Map dataMap = delegateGson.fromJson( + // DataPart supports any JSON value: object, array, primitive, or null + Object data = delegateGson.fromJson( jsonObject.get(DATA), - new TypeToken>(){}.getType() + Object.class ); - yield new DataPart(dataMap); + yield new DataPart(data); } default -> throw new JsonSyntaxException(format("Part must have one of: %s (found: %s)", VALID_KEYS, discriminator)); diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java index cbf33a72d..c55200847 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java @@ -13,7 +13,7 @@ * The A2A Protocol defines two primary streaming operations: *
      *
    • {@link SendStreamingMessageRequest} - Stream task execution events in real-time
    • - *
    • {@link SubscribeToTaskRequest} - Resubscribe to events from an existing task
    • + *
    • {@link SubscribeToTaskRequest} - Subscribe to events from an existing task
    • *
    *

    * Streaming requests follow the JSON-RPC 2.0 specification structure but the response diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java index 27acb3a14..1c965d5b1 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java @@ -8,7 +8,7 @@ import io.a2a.spec.TaskIdParams; /** - * JSON-RPC request to resubscribe to an ongoing or completed task's event stream. + * JSON-RPC request to subscribe to an ongoing or completed task's event stream. *

    * This request allows clients to reconnect to a task and receive its events, enabling * recovery from disconnections or retrieval of missed updates. The agent will stream diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java index 08eea2835..e7dcdc670 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java @@ -97,7 +97,6 @@ void testTaskStatusUpdateEventSerialization() throws JsonProcessingException { .taskId("task-abc") .contextId("context-def") .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .build(); // Serialize as StreamingEventKind 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 b2da1d413..25b7cc708 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 @@ -3,7 +3,6 @@ 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 io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; import static java.util.Collections.singletonList; @@ -226,7 +225,7 @@ public void testGetTask_MethodNameSetInContext() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "GetTask", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", "historyLength": 10 } }"""; @@ -263,7 +262,7 @@ public void testCancelTask_MethodNameSetInContext() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "CancelTask", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64" + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64" } }"""; when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); @@ -299,7 +298,7 @@ public void testTaskResubscription_MethodNameSetInContext() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "SubscribeToTask", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64" + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64" } }"""; when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); @@ -331,16 +330,13 @@ public void testCreateTaskPushNotificationConfig_MethodNameSetInContext() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "CreateTaskPushNotificationConfig", "params": { - "parent": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", "configId": "config-123", "config": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/config-123", - "pushNotificationConfig": { "url": "https://example.com/callback", "authentication": { - "schemes": ["jwt"] + "scheme": "jwt" } - } } } }"""; @@ -352,7 +348,7 @@ public void testCreateTaskPushNotificationConfig_MethodNameSetInContext() { PushNotificationConfig.builder() .id("config-123") .url("https://example.com/callback") - .authentication(new AuthenticationInfo(Collections.singletonList("jwt"), null)) + .authentication(new AuthenticationInfo("jwt", null)) .build(), "tenant"); @@ -382,7 +378,8 @@ public void testGetTaskPushNotificationConfig_MethodNameSetInContext() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "GetTaskPushNotificationConfig", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/config-456" + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "config-456" } }"""; when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); @@ -422,7 +419,9 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "ListTaskPushNotificationConfig", "params": { - "parent": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64" + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "pageSize": 0, + "pageToken": "" } }"""; when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); @@ -462,7 +461,8 @@ public void testDeleteTaskPushNotificationConfig_MethodNameSetInContext() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "DeleteTaskPushNotificationConfig", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/config-456" + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "config-456" } }"""; when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); @@ -497,7 +497,6 @@ public void testGetExtendedCard_MethodNameSetInContext() { .name("Test Agent") .description("Test agent description") .version("1.0.0") - .protocolVersions(CURRENT_PROTOCOL_VERSION) .capabilities(AgentCapabilities.builder().build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) @@ -532,7 +531,7 @@ public void testTenantExtraction_MultiSegmentPath() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "GetTask", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", "historyLength": 10 } }"""; @@ -569,7 +568,7 @@ public void testTenantExtraction_RootPath() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "GetTask", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", "historyLength": 10 } }"""; @@ -606,7 +605,7 @@ public void testTenantExtraction_SingleSegmentPath() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "GetTask", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", "historyLength": 10 } }"""; @@ -643,7 +642,7 @@ public void testTenantExtraction_ThreeSegmentPath() { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "method": "GetTask", "params": { - "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", "historyLength": 10 } }"""; 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 9ef8f7c47..a8ce70f7f 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 @@ -175,7 +175,7 @@ public void testCancelTask_MethodNameSetInContext() { } @Test - public void testResubscribeTask_MethodNameSetInContext() { + public void testSubscribeTask_MethodNameSetInContext() { // Arrange when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); 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 122d4b0f8..4899a926d 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 @@ -224,7 +224,7 @@ public void enqueueEvent(Event event) { * Enqueues an event directly to this specific queue only, bypassing the MainEventBus. *

    * This method is used for enqueuing already-persisted events (e.g., current task state - * on resubscribe) that should only be sent to this specific subscriber, not distributed + * on subscribe) that should only be sent to this specific subscriber, not distributed * to all children or sent through MainEventBusProcessor. *

    *

    @@ -236,7 +236,7 @@ public void enqueueEvent(Event event) { */ public void enqueueLocalOnly(EventQueueItem item) { throw new UnsupportedOperationException( - "enqueueLocalOnly is only supported on ChildQueue for resubscribe scenarios"); + "enqueueLocalOnly is only supported on ChildQueue for subscribe scenarios"); } /** @@ -504,7 +504,7 @@ void childClosing(ChildQueue child, boolean immediate) { boolean isFinalized = taskStateProvider.isTaskFinalized(taskId); if (!isFinalized) { LOGGER.debug("MainQueue for task {} has no children, but task is not finalized - keeping queue open for potential resubscriptions", taskId); - return; // Don't close - keep queue open for fire-and-forget or late resubscribes + return; // Don't close - keep queue open for fire-and-forget or late subscribes } LOGGER.debug("MainQueue for task {} has no children and task is finalized - closing queue", taskId); } else { 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 e1a16eb3c..31a1a6670 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 @@ -14,7 +14,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Flow; import java.util.concurrent.TimeoutException; @@ -36,7 +35,6 @@ import io.a2a.server.events.EventQueue; import io.a2a.server.events.EventQueueItem; import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.server.events.MainEventBusProcessorCallback; import io.a2a.server.events.QueueManager; import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.server.tasks.PushNotificationSender; @@ -786,9 +784,9 @@ private PushNotificationConfig getPushNotificationConfig(ListTaskPushNotificatio } @Override - public Flow.Publisher onResubscribeToTask( + public Flow.Publisher onSubscribeToTask( TaskIdParams params, ServerCallContext context) throws A2AError { - LOGGER.debug("onResubscribeToTask - taskId: {}", params.id()); + LOGGER.debug("onSubscribeToTask - taskId: {}", params.id()); Task task = taskStore.get(params.id()); if (task == null) { throw new TaskNotFoundError(); @@ -797,7 +795,7 @@ public Flow.Publisher onResubscribeToTask( TaskManager taskManager = new TaskManager(task.id(), task.contextId(), taskStore, null); ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor, eventConsumerExecutor); EventQueue queue = queueManager.tap(task.id()); - LOGGER.debug("onResubscribeToTask - tapped queue: {}", queue != null ? System.identityHashCode(queue) : "null"); + LOGGER.debug("onSubscribeToTask - tapped queue: {}", queue != null ? System.identityHashCode(queue) : "null"); if (queue == null) { // If task is in final state, queue legitimately doesn't exist anymore @@ -815,11 +813,11 @@ public Flow.Publisher onResubscribeToTask( // representing the current state of the task at the time of subscription." // Enqueue the current task state directly to this ChildQueue only (already persisted, no need for MainEventBus) queue.enqueueEventLocalOnly(task); - LOGGER.debug("onResubscribeToTask - enqueued current task state as first event for taskId: {}", params.id()); + LOGGER.debug("onSubscribeToTask - enqueued current task state as first event for taskId: {}", params.id()); EventConsumer consumer = new EventConsumer(queue); Flow.Publisher results = resultAggregator.consumeAndEmit(consumer); - LOGGER.debug("onResubscribeToTask - returning publisher for taskId: {}", params.id()); + LOGGER.debug("onSubscribeToTask - returning publisher for taskId: {}", params.id()); return convertingProcessor(results, item -> (StreamingEventKind) item.getEvent()); } 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 639098967..ff6139654 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 @@ -47,7 +47,7 @@ TaskPushNotificationConfig onGetTaskPushNotificationConfig( GetTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError; - Flow.Publisher onResubscribeToTask( + Flow.Publisher onSubscribeToTask( TaskIdParams params, ServerCallContext context) throws A2AError; 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 022cde56b..c28e55c5c 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 @@ -52,7 +52,6 @@ public void updateStatus(TaskState state, @Nullable Message message, boolean isF TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId(contextId) - .isFinal(isFinal) .status(new TaskStatus(state, message, null)) .build(); eventQueue.enqueueEvent(event); 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 633b38ced..df49a7c8a 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 @@ -78,13 +78,15 @@ public static Artifact newTextArtifact(String name, String text) { /** * Creates a new Artifact object containing only a single DataPart. + *

    + * Supports any JSON value type: objects (Map), arrays (List), primitives (String, Number, Boolean), or null. * * @param name The human-readable name of the artifact. - * @param data The structured data content of the artifact. + * @param data The structured data content of the artifact (JSON object, array, primitive, or null). * @param description An optional description of the artifact. * @return A new {@code Artifact} object with a generated artifact_id. */ - public static Artifact newDataArtifact(String name, Map data, @Nullable String description) { + public static Artifact newDataArtifact(String name, Object data, @Nullable String description) { return newArtifact( name, List.of(new DataPart(data)), @@ -94,12 +96,14 @@ public static Artifact newDataArtifact(String name, Map data, @N /** * Creates a new Artifact object containing only a single DataPart with empty description. + *

    + * Supports any JSON value type: objects (Map), arrays (List), primitives (String, Number, Boolean), or null. * * @param name The human-readable name of the artifact. - * @param data The structured data content of the artifact. + * @param data The structured data content of the artifact (JSON object, array, primitive, or null). * @return A new {@code Artifact} object with a generated artifact_id. */ - public static Artifact newDataArtifact(String name, Map data) { + public static Artifact newDataArtifact(String name, Object data) { return newDataArtifact(name, data, null); } } diff --git a/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java b/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java index 91159428a..da667e538 100644 --- a/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java +++ b/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java @@ -1,9 +1,11 @@ package io.a2a.server.version; import java.util.List; +import java.util.stream.Collectors; import io.a2a.server.ServerCallContext; import io.a2a.spec.AgentCard; +import io.a2a.spec.AgentInterface; import io.a2a.spec.VersionNotSupportedError; /** @@ -16,15 +18,15 @@ * * *

    If the client does not specify a version, the current protocol version - * ({@link AgentCard#CURRENT_PROTOCOL_VERSION}) is assumed as the default. + * ({@link AgentInterface#CURRENT_PROTOCOL_VERSION}) is assumed as the default. */ public class A2AVersionValidator { /** * Validates that the client's requested protocol version is compatible with the agent's - * supported version. + * supported versions across all interfaces. * - * @param agentCard the agent card containing the supported protocol version + * @param agentCard the agent card containing the supported interfaces with their protocol versions * @param context the server call context containing the requested protocol version * @throws VersionNotSupportedError if the versions are incompatible */ @@ -34,10 +36,14 @@ public static void validateProtocolVersion(AgentCard agentCard, ServerCallContex // If client didn't specify a version, default to current version if (requestedVersion == null || requestedVersion.trim().isEmpty()) { - requestedVersion = AgentCard.CURRENT_PROTOCOL_VERSION; + requestedVersion = AgentInterface.CURRENT_PROTOCOL_VERSION; } - List supportedVersions = agentCard.protocolVersions(); + // Collect all unique protocol versions from all supported interfaces + List supportedVersions = agentCard.supportedInterfaces().stream() + .map(AgentInterface::protocolVersion) + .distinct() + .collect(Collectors.toList()); if (!isVersionCompatible(supportedVersions, requestedVersion)) { throw new VersionNotSupportedError( 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 146bfb10a..2dcf7c4b1 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 @@ -158,8 +158,7 @@ public void testConsumeAllMultipleEvents() throws JsonProcessingException { TaskStatusUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") - .status(new TaskStatus(TaskState.WORKING)) - .isFinal(true) + .status(new TaskStatus(TaskState.COMPLETED)) .build()); for (Event event : events) { @@ -194,8 +193,7 @@ public void testConsumeUntilMessage() throws Exception { TaskStatusUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") - .status(new TaskStatus(TaskState.WORKING)) - .isFinal(true) + .status(new TaskStatus(TaskState.COMPLETED)) .build()); for (Event event : events) { @@ -258,8 +256,7 @@ public void testConsumeTaskInputRequired() { TaskStatusUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") - .status(new TaskStatus(TaskState.WORKING)) - .isFinal(true) + .status(new TaskStatus(TaskState.COMPLETED)) .build()); for (Event event : events) { eventQueue.enqueueEvent(event); 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 2499a8173..1adcc57ca 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 @@ -352,7 +352,6 @@ public void testDequeueEventWait() throws Exception { .taskId(TASK_ID) .contextId("session-xyz") .status(new TaskStatus(TaskState.WORKING)) - .isFinal(true) .build(); eventQueue.enqueueEvent(event); 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 274453fd1..968937b89 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 @@ -1,6 +1,5 @@ package io.a2a.server.requesthandlers; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import java.io.IOException; import java.io.InputStream; @@ -144,8 +143,7 @@ protected static AgentCard createAgentCard(boolean streaming, boolean pushNotifi .build()) .defaultInputModes(new ArrayList<>()) .defaultOutputModes(new ArrayList<>()) - .skills(new ArrayList<>()) - .protocolVersions(CURRENT_PROTOCOL_VERSION); + .skills(new ArrayList<>()); return builder.build(); } 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 ca4aa07b1..c058ee22e 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 @@ -141,7 +141,6 @@ public void testEnsureTaskNonExistentForStatusUpdate() throws A2AServerException .taskId("new-task") .contextId("some-context") .status(new TaskStatus(TaskState.SUBMITTED)) - .isFinal(false) .build(); taskManagerWithoutId.saveTaskEvent(event, false); @@ -353,7 +352,6 @@ public void testAddingTaskWithDifferentIdViaStatusUpdateFails() { .taskId("different-task-id") .contextId("session-xyz") .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .build(); assertThrows(A2AServerException.class, () -> { @@ -399,7 +397,6 @@ public void testTaskWithNoMessageUsesInitialMessage() throws A2AServerException .taskId("new-task-id") .contextId("some-context") .status(new TaskStatus(TaskState.SUBMITTED)) - .isFinal(false) .build(); taskManagerWithInitialMessage.saveTaskEvent(event, false); @@ -437,7 +434,6 @@ public void testTaskWithMessageDoesNotUseInitialMessage() throws A2AServerExcept .taskId("new-task-id") .contextId("some-context") .status(new TaskStatus(TaskState.SUBMITTED, taskMessage, null)) - .isFinal(false) .build(); taskManagerWithInitialMessage.saveTaskEvent(event, false); @@ -566,7 +562,6 @@ public void testSaveTaskEventMetadataUpdate() throws A2AServerException { .taskId(minimalTask.id()) .contextId(minimalTask.contextId()) .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .metadata(newMetadata) .build(); @@ -586,7 +581,6 @@ public void testSaveTaskEventMetadataUpdateNull() throws A2AServerException { .taskId(minimalTask.id()) .contextId(minimalTask.contextId()) .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .metadata(null) .build(); @@ -615,7 +609,6 @@ public void testSaveTaskEventMetadataMergeExisting() throws A2AServerException { .taskId(minimalTask.id()) .contextId(minimalTask.contextId()) .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .metadata(newMetadata) .build(); @@ -643,7 +636,6 @@ public void testCreateTaskWithInitialMessage() throws A2AServerException { .taskId("new-task-id") .contextId("some-context") .status(new TaskStatus(TaskState.SUBMITTED)) - .isFinal(false) .build(); taskManagerWithMessage.saveTaskEvent(event, false); @@ -672,7 +664,6 @@ public void testCreateTaskWithoutInitialMessage() throws A2AServerException { .taskId("new-task-id") .contextId("some-context") .status(new TaskStatus(TaskState.SUBMITTED)) - .isFinal(false) .build(); taskManagerWithoutMessage.saveTaskEvent(event, false); @@ -728,7 +719,6 @@ public void testUpdateWithMessage() throws A2AServerException { .taskId("new-task-id") .contextId("some-context") .status(new TaskStatus(TaskState.SUBMITTED, taskMessage, null)) - .isFinal(false) .build(); taskManagerWithInitialMessage.saveTaskEvent(event, false); diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java b/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java index 73da17824..a5ec77f01 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java @@ -186,13 +186,13 @@ public void testRequiresInputWithMessage() throws Exception { @Test public void testRequiresInputWithFinalTrue() throws Exception { taskUpdater.requiresInput(true); - checkTaskStatusUpdateEventOnQueue(true, TaskState.INPUT_REQUIRED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, null); } @Test public void testRequiresInputWithMessageAndFinalTrue() throws Exception { taskUpdater.requiresInput(SAMPLE_MESSAGE, true); - checkTaskStatusUpdateEventOnQueue(true, TaskState.INPUT_REQUIRED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, SAMPLE_MESSAGE); } @Test @@ -210,13 +210,13 @@ public void testRequiresAuthWithMessage() throws Exception { @Test public void testRequiresAuthWithFinalTrue() throws Exception { taskUpdater.requiresAuth(true); - checkTaskStatusUpdateEventOnQueue(true, TaskState.AUTH_REQUIRED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, null); } @Test public void testRequiresAuthWithMessageAndFinalTrue() throws Exception { taskUpdater.requiresAuth(SAMPLE_MESSAGE, true); - checkTaskStatusUpdateEventOnQueue(true, TaskState.AUTH_REQUIRED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, SAMPLE_MESSAGE); } @Test diff --git a/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java b/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java index 43e0f55dd..8156fad4c 100644 --- a/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java +++ b/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java @@ -144,7 +144,7 @@ private AgentCard createAgentCard(String protocolVersion) { return AgentCard.builder() .name("test-card") .description("Test card") - .supportedInterfaces(List.of(new AgentInterface("GRPC", "http://localhost:9999"))) + .supportedInterfaces(List.of(new AgentInterface("GRPC", "http://localhost:9999", "", protocolVersion))) .version("1.0.0") .capabilities(AgentCapabilities.builder() .streaming(false) @@ -153,7 +153,6 @@ private AgentCard createAgentCard(String protocolVersion) { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(Collections.emptyList()) - .protocolVersions(protocolVersion) .build(); } diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index b602f7613..3b2f28c0d 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -96,7 +96,7 @@ io.github.ascopes protobuf-maven-plugin - 4.0.3 + 4.1.2 ${skip.protobuf.generate} true diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java index 6dc06f861..7b1286314 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java @@ -46,16 +46,6 @@ public static void registerAllExtensions( static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_a2a_v1_Part_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_FilePart_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_FilePart_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_DataPart_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_DataPart_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_a2a_v1_Message_descriptor; static final @@ -137,15 +127,15 @@ public static void registerAllExtensions( com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_a2a_v1_StringList_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_Security_descriptor; + internal_static_a2a_v1_SecurityRequirement_descriptor; static final com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_Security_fieldAccessorTable; + internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_Security_SchemesEntry_descriptor; + internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor; static final com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_Security_SchemesEntry_fieldAccessorTable; + internal_static_a2a_v1_SecurityRequirement_SchemesEntry_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_a2a_v1_SecurityScheme_descriptor; static final @@ -201,6 +191,26 @@ public static void registerAllExtensions( static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; static final @@ -308,224 +318,237 @@ public static void registerAllExtensions( "\n\nTaskStatus\022%\n\005state\030\001 \001(\0162\021.a2a.v1.Tas" + "kStateB\003\340A\002\022 \n\007message\030\002 \001(\0132\017.a2a.v1.Me" + "ssage\022-\n\ttimestamp\030\003 \001(\0132\032.google.protob" + - "uf.Timestamp\"\215\001\n\004Part\022\016\n\004text\030\001 \001(\tH\000\022 \n" + - "\004file\030\002 \001(\0132\020.a2a.v1.FilePartH\000\022 \n\004data\030" + - "\003 \001(\0132\020.a2a.v1.DataPartH\000\022)\n\010metadata\030\004 " + - "\001(\0132\027.google.protobuf.StructB\006\n\004part\"h\n\010" + - "FilePart\022\027\n\rfile_with_uri\030\001 \001(\tH\000\022\031\n\017fil" + - "e_with_bytes\030\002 \001(\014H\000\022\022\n\nmedia_type\030\003 \001(\t" + - "\022\014\n\004name\030\004 \001(\tB\006\n\004file\"6\n\010DataPart\022*\n\004da" + - "ta\030\001 \001(\0132\027.google.protobuf.StructB\003\340A\002\"\345" + - "\001\n\007Message\022\027\n\nmessage_id\030\001 \001(\tB\003\340A\002\022\022\n\nc" + - "ontext_id\030\002 \001(\t\022\017\n\007task_id\030\003 \001(\t\022\037\n\004role" + - "\030\004 \001(\0162\014.a2a.v1.RoleB\003\340A\002\022 \n\005parts\030\005 \003(\013" + + "uf.Timestamp\"\270\001\n\004Part\022\016\n\004text\030\001 \001(\tH\000\022\r\n" + + "\003raw\030\002 \001(\014H\000\022\r\n\003url\030\003 \001(\tH\000\022&\n\004data\030\004 \001(" + + "\0132\026.google.protobuf.ValueH\000\022)\n\010metadata\030" + + "\005 \001(\0132\027.google.protobuf.Struct\022\020\n\010filena" + + "me\030\006 \001(\t\022\022\n\nmedia_type\030\007 \001(\tB\t\n\007content\"" + + "\345\001\n\007Message\022\027\n\nmessage_id\030\001 \001(\tB\003\340A\002\022\022\n\n" + + "context_id\030\002 \001(\t\022\017\n\007task_id\030\003 \001(\t\022\037\n\004rol" + + "e\030\004 \001(\0162\014.a2a.v1.RoleB\003\340A\002\022 \n\005parts\030\005 \003(" + + "\0132\014.a2a.v1.PartB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027" + + ".google.protobuf.Struct\022\022\n\nextensions\030\007 " + + "\003(\t\022\032\n\022reference_task_ids\030\010 \003(\t\"\250\001\n\010Arti" + + "fact\022\030\n\013artifact_id\030\001 \001(\tB\003\340A\002\022\014\n\004name\030\003" + + " \001(\t\022\023\n\013description\030\004 \001(\t\022 \n\005parts\030\005 \003(\013" + "2\014.a2a.v1.PartB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027." + "google.protobuf.Struct\022\022\n\nextensions\030\007 \003" + - "(\t\022\032\n\022reference_task_ids\030\010 \003(\t\"\250\001\n\010Artif" + - "act\022\030\n\013artifact_id\030\001 \001(\tB\003\340A\002\022\014\n\004name\030\003 " + - "\001(\t\022\023\n\013description\030\004 \001(\t\022 \n\005parts\030\005 \003(\0132" + - "\014.a2a.v1.PartB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027.g" + - "oogle.protobuf.Struct\022\022\n\nextensions\030\007 \003(" + - "\t\"\256\001\n\025TaskStatusUpdateEvent\022\024\n\007task_id\030\001" + - " \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022\'\n\006st" + - "atus\030\003 \001(\0132\022.a2a.v1.TaskStatusB\003\340A\002\022\022\n\005f" + - "inal\030\004 \001(\010B\003\340A\002\022)\n\010metadata\030\005 \001(\0132\027.goog" + - "le.protobuf.Struct\"\300\001\n\027TaskArtifactUpdat" + - "eEvent\022\024\n\007task_id\030\001 \001(\tB\003\340A\002\022\027\n\ncontext_" + - "id\030\002 \001(\tB\003\340A\002\022\'\n\010artifact\030\003 \001(\0132\020.a2a.v1" + - ".ArtifactB\003\340A\002\022\016\n\006append\030\004 \001(\010\022\022\n\nlast_c" + - "hunk\030\005 \001(\010\022)\n\010metadata\030\006 \001(\0132\027.google.pr" + - "otobuf.Struct\"y\n\026PushNotificationConfig\022" + - "\n\n\002id\030\001 \001(\t\022\020\n\003url\030\002 \001(\tB\003\340A\002\022\r\n\005token\030\003" + - " \001(\t\0222\n\016authentication\030\004 \001(\0132\032.a2a.v1.Au" + - "thenticationInfo\"?\n\022AuthenticationInfo\022\024" + - "\n\007schemes\030\001 \003(\tB\003\340A\002\022\023\n\013credentials\030\002 \001(" + - "\t\"Q\n\016AgentInterface\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\035\n" + - "\020protocol_binding\030\002 \001(\tB\003\340A\002\022\016\n\006tenant\030\003" + - " \001(\t\"\310\005\n\tAgentCard\022\036\n\021protocol_versions\030" + - "\020 \003(\tB\003\340A\002\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\030\n\013descrip" + - "tion\030\002 \001(\tB\003\340A\002\0229\n\024supported_interfaces\030" + - "\023 \003(\0132\026.a2a.v1.AgentInterfaceB\003\340A\002\022\'\n\010pr" + - "ovider\030\004 \001(\0132\025.a2a.v1.AgentProvider\022\024\n\007v" + - "ersion\030\005 \001(\tB\003\340A\002\022\036\n\021documentation_url\030\006" + - " \001(\tH\000\210\001\001\0224\n\014capabilities\030\007 \001(\0132\031.a2a.v1" + - ".AgentCapabilitiesB\003\340A\002\022@\n\020security_sche" + - "mes\030\010 \003(\0132&.a2a.v1.AgentCard.SecuritySch" + - "emesEntry\022\"\n\010security\030\t \003(\0132\020.a2a.v1.Sec" + - "urity\022 \n\023default_input_modes\030\n \003(\tB\003\340A\002\022" + - "!\n\024default_output_modes\030\013 \003(\tB\003\340A\002\022\'\n\006sk" + - "ills\030\014 \003(\0132\022.a2a.v1.AgentSkillB\003\340A\002\022.\n\ns" + - "ignatures\030\021 \003(\0132\032.a2a.v1.AgentCardSignat" + - "ure\022\025\n\010icon_url\030\022 \001(\tH\001\210\001\001\032N\n\024SecuritySc" + - "hemesEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026" + - ".a2a.v1.SecurityScheme:\0028\001B\024\n\022_documenta" + - "tion_urlB\013\n\t_icon_urlJ\004\010\003\020\004J\004\010\016\020\017J\004\010\017\020\020\"" + - "<\n\rAgentProvider\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\031\n\014or" + - "ganization\030\002 \001(\tB\003\340A\002\"\335\001\n\021AgentCapabilit" + - "ies\022\026\n\tstreaming\030\001 \001(\010H\000\210\001\001\022\037\n\022push_noti" + - "fications\030\002 \001(\010H\001\210\001\001\022*\n\nextensions\030\003 \003(\013" + - "2\026.a2a.v1.AgentExtension\022 \n\023extended_age" + - "nt_card\030\005 \001(\010H\002\210\001\001B\014\n\n_streamingB\025\n\023_pus" + - "h_notificationsB\026\n\024_extended_agent_cardJ" + - "\004\010\004\020\005\"m\n\016AgentExtension\022\013\n\003uri\030\001 \001(\t\022\023\n\013" + - "description\030\002 \001(\t\022\020\n\010required\030\003 \001(\010\022\'\n\006p" + - "arams\030\004 \001(\0132\027.google.protobuf.Struct\"\276\001\n" + - "\nAgentSkill\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\021\n\004name\030\002 \001" + - "(\tB\003\340A\002\022\030\n\013description\030\003 \001(\tB\003\340A\002\022\021\n\004tag" + - "s\030\004 \003(\tB\003\340A\002\022\020\n\010examples\030\005 \003(\t\022\023\n\013input_" + - "modes\030\006 \003(\t\022\024\n\014output_modes\030\007 \003(\t\022\"\n\010sec" + - "urity\030\010 \003(\0132\020.a2a.v1.Security\"m\n\022AgentCa" + - "rdSignature\022\026\n\tprotected\030\001 \001(\tB\003\340A\002\022\026\n\ts" + - "ignature\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\0132\027.go" + - "ogle.protobuf.Struct\"v\n\032TaskPushNotifica" + - "tionConfig\022\021\n\004name\030\001 \001(\tB\003\340A\002\022E\n\030push_no" + - "tification_config\030\002 \001(\0132\036.a2a.v1.PushNot" + - "ificationConfigB\003\340A\002\"\032\n\nStringList\022\014\n\004li" + - "st\030\001 \003(\t\"~\n\010Security\022.\n\007schemes\030\001 \003(\0132\035." + - "a2a.v1.Security.SchemesEntry\032B\n\014SchemesE" + - "ntry\022\013\n\003key\030\001 \001(\t\022!\n\005value\030\002 \001(\0132\022.a2a.v" + - "1.StringList:\0028\001\"\361\002\n\016SecurityScheme\022?\n\027a" + - "pi_key_security_scheme\030\001 \001(\0132\034.a2a.v1.AP" + - "IKeySecuritySchemeH\000\022C\n\031http_auth_securi" + - "ty_scheme\030\002 \001(\0132\036.a2a.v1.HTTPAuthSecurit" + - "ySchemeH\000\022>\n\026oauth2_security_scheme\030\003 \001(" + - "\0132\034.a2a.v1.OAuth2SecuritySchemeH\000\022N\n\037ope" + - "n_id_connect_security_scheme\030\004 \001(\0132#.a2a" + - ".v1.OpenIdConnectSecuritySchemeH\000\022?\n\024mtl" + - "s_security_scheme\030\005 \001(\0132\037.a2a.v1.MutualT" + - "lsSecuritySchemeH\000B\010\n\006scheme\"U\n\024APIKeySe" + - "curityScheme\022\023\n\013description\030\001 \001(\t\022\025\n\010loc" + - "ation\030\002 \001(\tB\003\340A\002\022\021\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026H" + - "TTPAuthSecurityScheme\022\023\n\013description\030\001 \001" + - "(\t\022\023\n\006scheme\030\002 \001(\tB\003\340A\002\022\025\n\rbearer_format" + - "\030\003 \001(\t\"p\n\024OAuth2SecurityScheme\022\023\n\013descri" + - "ption\030\001 \001(\t\022&\n\005flows\030\002 \001(\0132\022.a2a.v1.OAut" + - "hFlowsB\003\340A\002\022\033\n\023oauth2_metadata_url\030\003 \001(\t" + - "\"T\n\033OpenIdConnectSecurityScheme\022\023\n\013descr" + - "iption\030\001 \001(\t\022 \n\023open_id_connect_url\030\002 \001(" + - "\tB\003\340A\002\".\n\027MutualTlsSecurityScheme\022\023\n\013des" + - "cription\030\001 \001(\t\"\330\001\n\nOAuthFlows\022@\n\022authori" + - "zation_code\030\001 \001(\0132\".a2a.v1.Authorization" + - "CodeOAuthFlowH\000\022@\n\022client_credentials\030\002 " + - "\001(\0132\".a2a.v1.ClientCredentialsOAuthFlowH" + - "\000\0222\n\013device_code\030\005 \001(\0132\033.a2a.v1.DeviceCo" + - "deOAuthFlowH\000B\006\n\004flowJ\004\010\003\020\004J\004\010\004\020\005\"\364\001\n\032Au" + - "thorizationCodeOAuthFlow\022\036\n\021authorizatio" + - "n_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002" + - "\022\023\n\013refresh_url\030\003 \001(\t\022C\n\006scopes\030\004 \003(\0132.." + - "a2a.v1.AuthorizationCodeOAuthFlow.Scopes" + - "EntryB\003\340A\002\022\025\n\rpkce_required\030\005 \001(\010\032-\n\013Sco" + - "pesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001" + - "\"\275\001\n\032ClientCredentialsOAuthFlow\022\026\n\ttoken" + - "_url\030\001 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022C\n\006" + - "scopes\030\003 \003(\0132..a2a.v1.ClientCredentialsO" + - "AuthFlow.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry" + - "\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\326\001\n\023Dev" + - "iceCodeOAuthFlow\022%\n\030device_authorization" + - "_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022" + - "\023\n\013refresh_url\030\003 \001(\t\022<\n\006scopes\030\004 \003(\0132\'.a" + - "2a.v1.DeviceCodeOAuthFlow.ScopesEntryB\003\340" + - "A\002\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030" + - "\002 \001(\t:\0028\001\"\257\001\n\022SendMessageRequest\022\016\n\006tena" + - "nt\030\004 \001(\t\022%\n\007message\030\001 \001(\0132\017.a2a.v1.Messa" + - "geB\003\340A\002\0227\n\rconfiguration\030\002 \001(\0132 .a2a.v1." + - "SendMessageConfiguration\022)\n\010metadata\030\003 \001" + - "(\0132\027.google.protobuf.Struct\"c\n\016GetTaskRe" + - "quest\022\016\n\006tenant\030\003 \001(\t\022\021\n\004name\030\001 \001(\tB\003\340A\002" + - "\022\033\n\016history_length\030\002 \001(\005H\000\210\001\001B\021\n\017_histor" + - "y_length\"\265\002\n\020ListTasksRequest\022\016\n\006tenant\030" + - "\t \001(\t\022\022\n\ncontext_id\030\001 \001(\t\022!\n\006status\030\002 \001(" + - "\0162\021.a2a.v1.TaskState\022\026\n\tpage_size\030\003 \001(\005H" + - "\000\210\001\001\022\022\n\npage_token\030\004 \001(\t\022\033\n\016history_leng" + - "th\030\005 \001(\005H\001\210\001\001\022:\n\026status_timestamp_after\030" + - "\006 \001(\0132\032.google.protobuf.Timestamp\022\036\n\021inc" + - "lude_artifacts\030\007 \001(\010H\002\210\001\001B\014\n\n_page_sizeB" + - "\021\n\017_history_lengthB\024\n\022_include_artifacts" + - "\"\204\001\n\021ListTasksResponse\022 \n\005tasks\030\001 \003(\0132\014." + - "a2a.v1.TaskB\003\340A\002\022\034\n\017next_page_token\030\002 \001(" + - "\tB\003\340A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022\027\n\ntotal_" + - "size\030\004 \001(\005B\003\340A\002\"1\n\021CancelTaskRequest\022\016\n\006" + - "tenant\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"D\n$GetTaskPus" + - "hNotificationConfigRequest\022\016\n\006tenant\030\002 \001" + - "(\t\022\014\n\004name\030\001 \001(\t\"G\n\'DeleteTaskPushNotifi" + - "cationConfigRequest\022\016\n\006tenant\030\002 \001(\t\022\014\n\004n" + - "ame\030\001 \001(\t\"\237\001\n\'CreateTaskPushNotification" + - "ConfigRequest\022\016\n\006tenant\030\004 \001(\t\022\023\n\006parent\030" + - "\001 \001(\tB\003\340A\002\022\026\n\tconfig_id\030\002 \001(\tB\003\340A\002\0227\n\006co" + - "nfig\030\003 \001(\0132\".a2a.v1.TaskPushNotification" + - "ConfigB\003\340A\002\"6\n\026SubscribeToTaskRequest\022\016\n" + - "\006tenant\030\002 \001(\t\022\014\n\004name\030\001 \001(\t\"n\n%ListTaskP" + - "ushNotificationConfigRequest\022\016\n\006tenant\030\004" + - " \001(\t\022\016\n\006parent\030\001 \001(\t\022\021\n\tpage_size\030\002 \001(\005\022" + - "\022\n\npage_token\030\003 \001(\t\"-\n\033GetExtendedAgentC" + - "ardRequest\022\016\n\006tenant\030\001 \001(\t\"b\n\023SendMessag" + - "eResponse\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022" + - "\"\n\007message\030\002 \001(\0132\017.a2a.v1.MessageH\000B\t\n\007p" + - "ayload\"\321\001\n\016StreamResponse\022\034\n\004task\030\001 \001(\0132" + - "\014.a2a.v1.TaskH\000\022\"\n\007message\030\002 \001(\0132\017.a2a.v" + - "1.MessageH\000\0226\n\rstatus_update\030\003 \001(\0132\035.a2a" + - ".v1.TaskStatusUpdateEventH\000\022:\n\017artifact_" + - "update\030\004 \001(\0132\037.a2a.v1.TaskArtifactUpdate" + - "EventH\000B\t\n\007payload\"v\n&ListTaskPushNotifi" + - "cationConfigResponse\0223\n\007configs\030\001 \003(\0132\"." + - "a2a.v1.TaskPushNotificationConfig\022\027\n\017nex" + - "t_page_token\030\002 \001(\t*\372\001\n\tTaskState\022\032\n\026TASK" + - "_STATE_UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMI" + - "TTED\020\001\022\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_S" + - "TATE_COMPLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022" + - "\030\n\024TASK_STATE_CANCELLED\020\005\022\035\n\031TASK_STATE_" + - "INPUT_REQUIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020" + - "\007\022\034\n\030TASK_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022" + - "\024\n\020ROLE_UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\n" + - "ROLE_AGENT\020\0022\304\016\n\nA2AService\022}\n\013SendMessa" + - "ge\022\032.a2a.v1.SendMessageRequest\032\033.a2a.v1." + - "SendMessageResponse\"5\202\323\344\223\002/\"\r/message:se" + - "nd:\001*Z\033\"\026/{tenant}/message:send:\001*\022\207\001\n\024S" + - "endStreamingMessage\022\032.a2a.v1.SendMessage" + - "Request\032\026.a2a.v1.StreamResponse\"9\202\323\344\223\0023\"" + - "\017/message:stream:\001*Z\035\"\030/{tenant}/message" + - ":stream:\001*0\001\022k\n\007GetTask\022\026.a2a.v1.GetTask" + - "Request\032\014.a2a.v1.Task\":\332A\004name\202\323\344\223\002-\022\017/{" + - "name=tasks/*}Z\032\022\030/{tenant}/{name=tasks/*" + - "}\022c\n\tListTasks\022\030.a2a.v1.ListTasksRequest" + - "\032\031.a2a.v1.ListTasksResponse\"!\202\323\344\223\002\033\022\006/ta" + - "sksZ\021\022\017/{tenant}/tasks\022~\n\nCancelTask\022\031.a" + - "2a.v1.CancelTaskRequest\032\014.a2a.v1.Task\"G\202" + - "\323\344\223\002A\"\026/{name=tasks/*}:cancel:\001*Z$\"\037/{te" + - "nant}/{name=tasks/*}:cancel:\001*\022\224\001\n\017Subsc" + - "ribeToTask\022\036.a2a.v1.SubscribeToTaskReque" + - "st\032\026.a2a.v1.StreamResponse\"G\202\323\344\223\002A\022\031/{na" + - "me=tasks/*}:subscribeZ$\022\"/{tenant}/{name" + - "=tasks/*}:subscribe0\001\022\201\002\n CreateTaskPush" + - "NotificationConfig\022/.a2a.v1.CreateTaskPu" + - "shNotificationConfigRequest\032\".a2a.v1.Tas" + - "kPushNotificationConfig\"\207\001\332A\rparent,conf" + - "ig\202\323\344\223\002q\")/{parent=tasks/*/pushNotificat" + - "ionConfigs}:\006configZ<\"2/{tenant}/{parent" + - "=tasks/*/pushNotificationConfigs}:\006confi" + - "g\022\341\001\n\035GetTaskPushNotificationConfig\022,.a2" + - "a.v1.GetTaskPushNotificationConfigReques" + - "t\032\".a2a.v1.TaskPushNotificationConfig\"n\332" + - "A\004name\202\323\344\223\002a\022)/{name=tasks/*/pushNotific" + - "ationConfigs/*}Z4\0222/{tenant}/{name=tasks" + - "/*/pushNotificationConfigs/*}\022\361\001\n\036ListTa" + - "skPushNotificationConfig\022-.a2a.v1.ListTa" + - "skPushNotificationConfigRequest\032..a2a.v1" + - ".ListTaskPushNotificationConfigResponse\"" + - "p\332A\006parent\202\323\344\223\002a\022)/{parent=tasks/*}/push" + - "NotificationConfigsZ4\0222/{tenant}/{parent" + - "=tasks/*}/pushNotificationConfigs\022\211\001\n\024Ge" + - "tExtendedAgentCard\022#.a2a.v1.GetExtendedA" + - "gentCardRequest\032\021.a2a.v1.AgentCard\"9\202\323\344\223" + - "\0023\022\022/extendedAgentCardZ\035\022\033/{tenant}/exte" + - "ndedAgentCard\022\333\001\n DeleteTaskPushNotifica" + - "tionConfig\022/.a2a.v1.DeleteTaskPushNotifi" + - "cationConfigRequest\032\026.google.protobuf.Em" + - "pty\"n\332A\004name\202\323\344\223\002a*)/{name=tasks/*/pushN" + - "otificationConfigs/*}Z4*2/{tenant}/{name" + - "=tasks/*/pushNotificationConfigs/*}B7\n\013i" + - "o.a2a.grpcB\003A2AP\001Z\030google.golang.org/a2a" + - "/v1\252\002\006A2a.V1b\006proto3" + "(\t\"\240\001\n\025TaskStatusUpdateEvent\022\024\n\007task_id\030" + + "\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022\'\n\006s" + + "tatus\030\003 \001(\0132\022.a2a.v1.TaskStatusB\003\340A\002\022)\n\010" + + "metadata\030\005 \001(\0132\027.google.protobuf.StructJ" + + "\004\010\004\020\005\"\300\001\n\027TaskArtifactUpdateEvent\022\024\n\007tas" + + "k_id\030\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002" + + "\022\'\n\010artifact\030\003 \001(\0132\020.a2a.v1.ArtifactB\003\340A" + + "\002\022\016\n\006append\030\004 \001(\010\022\022\n\nlast_chunk\030\005 \001(\010\022)\n" + + "\010metadata\030\006 \001(\0132\027.google.protobuf.Struct" + + "\"y\n\026PushNotificationConfig\022\n\n\002id\030\001 \001(\t\022\020" + + "\n\003url\030\002 \001(\tB\003\340A\002\022\r\n\005token\030\003 \001(\t\0222\n\016authe" + + "ntication\030\004 \001(\0132\032.a2a.v1.AuthenticationI" + + "nfo\">\n\022AuthenticationInfo\022\023\n\006scheme\030\001 \001(" + + "\tB\003\340A\002\022\023\n\013credentials\030\002 \001(\t\"p\n\016AgentInte" + + "rface\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\035\n\020protocol_bind" + + "ing\030\002 \001(\tB\003\340A\002\022\016\n\006tenant\030\003 \001(\t\022\035\n\020protoc" + + "ol_version\030\004 \001(\tB\003\340A\002\"\314\005\n\tAgentCard\022\021\n\004n" + + "ame\030\001 \001(\tB\003\340A\002\022\030\n\013description\030\002 \001(\tB\003\340A\002" + + "\0229\n\024supported_interfaces\030\023 \003(\0132\026.a2a.v1." + + "AgentInterfaceB\003\340A\002\022\'\n\010provider\030\004 \001(\0132\025." + + "a2a.v1.AgentProvider\022\024\n\007version\030\005 \001(\tB\003\340" + + "A\002\022\036\n\021documentation_url\030\006 \001(\tH\000\210\001\001\0224\n\014ca" + + "pabilities\030\007 \001(\0132\031.a2a.v1.AgentCapabilit" + + "iesB\003\340A\002\022@\n\020security_schemes\030\010 \003(\0132&.a2a" + + ".v1.AgentCard.SecuritySchemesEntry\022:\n\025se" + + "curity_requirements\030\r \003(\0132\033.a2a.v1.Secur" + + "ityRequirement\022 \n\023default_input_modes\030\n " + + "\003(\tB\003\340A\002\022!\n\024default_output_modes\030\013 \003(\tB\003" + + "\340A\002\022\'\n\006skills\030\014 \003(\0132\022.a2a.v1.AgentSkillB" + + "\003\340A\002\022.\n\nsignatures\030\021 \003(\0132\032.a2a.v1.AgentC" + + "ardSignature\022\025\n\010icon_url\030\022 \001(\tH\001\210\001\001\032N\n\024S" + + "ecuritySchemesEntry\022\013\n\003key\030\001 \001(\t\022%\n\005valu" + + "e\030\002 \001(\0132\026.a2a.v1.SecurityScheme:\0028\001B\024\n\022_" + + "documentation_urlB\013\n\t_icon_urlJ\004\010\003\020\004J\004\010\t" + + "\020\nJ\004\010\016\020\017J\004\010\017\020\020J\004\010\020\020\021\"<\n\rAgentProvider\022\020\n" + + "\003url\030\001 \001(\tB\003\340A\002\022\031\n\014organization\030\002 \001(\tB\003\340" + + "A\002\"\335\001\n\021AgentCapabilities\022\026\n\tstreaming\030\001 " + + "\001(\010H\000\210\001\001\022\037\n\022push_notifications\030\002 \001(\010H\001\210\001" + + "\001\022*\n\nextensions\030\003 \003(\0132\026.a2a.v1.AgentExte" + + "nsion\022 \n\023extended_agent_card\030\005 \001(\010H\002\210\001\001B" + + "\014\n\n_streamingB\025\n\023_push_notificationsB\026\n\024" + + "_extended_agent_cardJ\004\010\004\020\005\"m\n\016AgentExten" + + "sion\022\013\n\003uri\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022\020" + + "\n\010required\030\003 \001(\010\022\'\n\006params\030\004 \001(\0132\027.googl" + + "e.protobuf.Struct\"\326\001\n\nAgentSkill\022\017\n\002id\030\001" + + " \001(\tB\003\340A\002\022\021\n\004name\030\002 \001(\tB\003\340A\002\022\030\n\013descript" + + "ion\030\003 \001(\tB\003\340A\002\022\021\n\004tags\030\004 \003(\tB\003\340A\002\022\020\n\010exa" + + "mples\030\005 \003(\t\022\023\n\013input_modes\030\006 \003(\t\022\024\n\014outp" + + "ut_modes\030\007 \003(\t\022:\n\025security_requirements\030" + + "\010 \003(\0132\033.a2a.v1.SecurityRequirement\"m\n\022Ag" + + "entCardSignature\022\026\n\tprotected\030\001 \001(\tB\003\340A\002" + + "\022\026\n\tsignature\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\013" + + "2\027.google.protobuf.Struct\"\232\001\n\032TaskPushNo" + + "tificationConfig\022\016\n\006tenant\030\004 \001(\t\022\017\n\002id\030\001" + + " \001(\tB\003\340A\002\022\024\n\007task_id\030\003 \001(\tB\003\340A\002\022E\n\030push_" + + "notification_config\030\002 \001(\0132\036.a2a.v1.PushN" + + "otificationConfigB\003\340A\002\"\032\n\nStringList\022\014\n\004" + + "list\030\001 \003(\t\"\224\001\n\023SecurityRequirement\0229\n\007sc" + + "hemes\030\001 \003(\0132(.a2a.v1.SecurityRequirement" + + ".SchemesEntry\032B\n\014SchemesEntry\022\013\n\003key\030\001 \001" + + "(\t\022!\n\005value\030\002 \001(\0132\022.a2a.v1.StringList:\0028" + + "\001\"\361\002\n\016SecurityScheme\022?\n\027api_key_security" + + "_scheme\030\001 \001(\0132\034.a2a.v1.APIKeySecuritySch" + + "emeH\000\022C\n\031http_auth_security_scheme\030\002 \001(\013" + + "2\036.a2a.v1.HTTPAuthSecuritySchemeH\000\022>\n\026oa" + + "uth2_security_scheme\030\003 \001(\0132\034.a2a.v1.OAut" + + "h2SecuritySchemeH\000\022N\n\037open_id_connect_se" + + "curity_scheme\030\004 \001(\0132#.a2a.v1.OpenIdConne" + + "ctSecuritySchemeH\000\022?\n\024mtls_security_sche" + + "me\030\005 \001(\0132\037.a2a.v1.MutualTlsSecuritySchem" + + "eH\000B\010\n\006scheme\"U\n\024APIKeySecurityScheme\022\023\n" + + "\013description\030\001 \001(\t\022\025\n\010location\030\002 \001(\tB\003\340A" + + "\002\022\021\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026HTTPAuthSecurity" + + "Scheme\022\023\n\013description\030\001 \001(\t\022\023\n\006scheme\030\002 " + + "\001(\tB\003\340A\002\022\025\n\rbearer_format\030\003 \001(\t\"p\n\024OAuth" + + "2SecurityScheme\022\023\n\013description\030\001 \001(\t\022&\n\005" + + "flows\030\002 \001(\0132\022.a2a.v1.OAuthFlowsB\003\340A\002\022\033\n\023" + + "oauth2_metadata_url\030\003 \001(\t\"T\n\033OpenIdConne" + + "ctSecurityScheme\022\023\n\013description\030\001 \001(\t\022 \n" + + "\023open_id_connect_url\030\002 \001(\tB\003\340A\002\".\n\027Mutua" + + "lTlsSecurityScheme\022\023\n\013description\030\001 \001(\t\"" + + "\262\002\n\nOAuthFlows\022@\n\022authorization_code\030\001 \001" + + "(\0132\".a2a.v1.AuthorizationCodeOAuthFlowH\000" + + "\022@\n\022client_credentials\030\002 \001(\0132\".a2a.v1.Cl" + + "ientCredentialsOAuthFlowH\000\0221\n\010implicit\030\003" + + " \001(\0132\031.a2a.v1.ImplicitOAuthFlowB\002\030\001H\000\0221\n" + + "\010password\030\004 \001(\0132\031.a2a.v1.PasswordOAuthFl" + + "owB\002\030\001H\000\0222\n\013device_code\030\005 \001(\0132\033.a2a.v1.D" + + "eviceCodeOAuthFlowH\000B\006\n\004flow\"\364\001\n\032Authori" + + "zationCodeOAuthFlow\022\036\n\021authorization_url" + + "\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013r" + + "efresh_url\030\003 \001(\t\022C\n\006scopes\030\004 \003(\0132..a2a.v" + + "1.AuthorizationCodeOAuthFlow.ScopesEntry" + + "B\003\340A\002\022\025\n\rpkce_required\030\005 \001(\010\032-\n\013ScopesEn" + + "try\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\275\001\n\032" + + "ClientCredentialsOAuthFlow\022\026\n\ttoken_url\030" + + "\001 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022C\n\006scope" + + "s\030\003 \003(\0132..a2a.v1.ClientCredentialsOAuthF" + + "low.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003k" + + "ey\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\251\001\n\021Implicit" + + "OAuthFlow\022\031\n\021authorization_url\030\001 \001(\t\022\023\n\013" + + "refresh_url\030\002 \001(\t\0225\n\006scopes\030\003 \003(\0132%.a2a." + + "v1.ImplicitOAuthFlow.ScopesEntry\032-\n\013Scop" + + "esEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"" + + "\241\001\n\021PasswordOAuthFlow\022\021\n\ttoken_url\030\001 \001(\t" + + "\022\023\n\013refresh_url\030\002 \001(\t\0225\n\006scopes\030\003 \003(\0132%." + + "a2a.v1.PasswordOAuthFlow.ScopesEntry\032-\n\013" + + "ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:" + + "\0028\001\"\326\001\n\023DeviceCodeOAuthFlow\022%\n\030device_au" + + "thorization_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030" + + "\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001(\t\022<\n\006scope" + + "s\030\004 \003(\0132\'.a2a.v1.DeviceCodeOAuthFlow.Sco" + + "pesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(" + + "\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\257\001\n\022SendMessageRequ" + + "est\022\016\n\006tenant\030\004 \001(\t\022%\n\007message\030\001 \001(\0132\017.a" + + "2a.v1.MessageB\003\340A\002\0227\n\rconfiguration\030\002 \001(" + + "\0132 .a2a.v1.SendMessageConfiguration\022)\n\010m" + + "etadata\030\003 \001(\0132\027.google.protobuf.Struct\"a" + + "\n\016GetTaskRequest\022\016\n\006tenant\030\003 \001(\t\022\017\n\002id\030\001" + + " \001(\tB\003\340A\002\022\033\n\016history_length\030\002 \001(\005H\000\210\001\001B\021" + + "\n\017_history_length\"\265\002\n\020ListTasksRequest\022\016" + + "\n\006tenant\030\t \001(\t\022\022\n\ncontext_id\030\001 \001(\t\022!\n\006st" + + "atus\030\002 \001(\0162\021.a2a.v1.TaskState\022\026\n\tpage_si" + + "ze\030\003 \001(\005H\000\210\001\001\022\022\n\npage_token\030\004 \001(\t\022\033\n\016his" + + "tory_length\030\005 \001(\005H\001\210\001\001\022:\n\026status_timesta" + + "mp_after\030\006 \001(\0132\032.google.protobuf.Timesta" + + "mp\022\036\n\021include_artifacts\030\007 \001(\010H\002\210\001\001B\014\n\n_p" + + "age_sizeB\021\n\017_history_lengthB\024\n\022_include_" + + "artifacts\"\204\001\n\021ListTasksResponse\022 \n\005tasks" + + "\030\001 \003(\0132\014.a2a.v1.TaskB\003\340A\002\022\034\n\017next_page_t" + + "oken\030\002 \001(\tB\003\340A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022" + + "\027\n\ntotal_size\030\004 \001(\005B\003\340A\002\"4\n\021CancelTaskRe" + + "quest\022\016\n\006tenant\030\002 \001(\t\022\017\n\002id\030\001 \001(\tB\003\340A\002\"]" + + "\n$GetTaskPushNotificationConfigRequest\022\016" + + "\n\006tenant\030\002 \001(\t\022\024\n\007task_id\030\003 \001(\tB\003\340A\002\022\017\n\002" + + "id\030\001 \001(\tB\003\340A\002\"`\n\'DeleteTaskPushNotificat" + + "ionConfigRequest\022\016\n\006tenant\030\002 \001(\t\022\024\n\007task" + + "_id\030\003 \001(\tB\003\340A\002\022\017\n\002id\030\001 \001(\tB\003\340A\002\"\242\001\n\'Crea" + + "teTaskPushNotificationConfigRequest\022\016\n\006t" + + "enant\030\004 \001(\t\022\024\n\007task_id\030\001 \001(\tB\003\340A\002\022\026\n\tcon" + + "fig_id\030\002 \001(\tB\003\340A\002\0223\n\006config\030\005 \001(\0132\036.a2a." + + "v1.PushNotificationConfigB\003\340A\002J\004\010\003\020\004\"9\n\026" + + "SubscribeToTaskRequest\022\016\n\006tenant\030\002 \001(\t\022\017" + + "\n\002id\030\001 \001(\tB\003\340A\002\"t\n%ListTaskPushNotificat" + + "ionConfigRequest\022\016\n\006tenant\030\004 \001(\t\022\024\n\007task" + + "_id\030\001 \001(\tB\003\340A\002\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npag" + + "e_token\030\003 \001(\t\"-\n\033GetExtendedAgentCardReq" + + "uest\022\016\n\006tenant\030\001 \001(\t\"b\n\023SendMessageRespo" + + "nse\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022\"\n\007mes" + + "sage\030\002 \001(\0132\017.a2a.v1.MessageH\000B\t\n\007payload" + + "\"\321\001\n\016StreamResponse\022\034\n\004task\030\001 \001(\0132\014.a2a." + + "v1.TaskH\000\022\"\n\007message\030\002 \001(\0132\017.a2a.v1.Mess" + + "ageH\000\0226\n\rstatus_update\030\003 \001(\0132\035.a2a.v1.Ta" + + "skStatusUpdateEventH\000\022:\n\017artifact_update" + + "\030\004 \001(\0132\037.a2a.v1.TaskArtifactUpdateEventH" + + "\000B\t\n\007payload\"v\n&ListTaskPushNotification" + + "ConfigResponse\0223\n\007configs\030\001 \003(\0132\".a2a.v1" + + ".TaskPushNotificationConfig\022\027\n\017next_page" + + "_token\030\002 \001(\t*\371\001\n\tTaskState\022\032\n\026TASK_STATE" + + "_UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMITTED\020\001" + + "\022\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_STATE_C" + + "OMPLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022\027\n\023TAS" + + "K_STATE_CANCELED\020\005\022\035\n\031TASK_STATE_INPUT_R" + + "EQUIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020\007\022\034\n\030TA" + + "SK_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE" + + "_UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AG" + + "ENT\020\0022\352\016\n\nA2AService\022}\n\013SendMessage\022\032.a2" + + "a.v1.SendMessageRequest\032\033.a2a.v1.SendMes" + + "sageResponse\"5\202\323\344\223\002/\"\r/message:send:\001*Z\033" + + "\"\026/{tenant}/message:send:\001*\022\207\001\n\024SendStre" + + "amingMessage\022\032.a2a.v1.SendMessageRequest" + + "\032\026.a2a.v1.StreamResponse\"9\202\323\344\223\0023\"\017/messa" + + "ge:stream:\001*Z\035\"\030/{tenant}/message:stream" + + ":\001*0\001\022e\n\007GetTask\022\026.a2a.v1.GetTaskRequest" + + "\032\014.a2a.v1.Task\"4\332A\002id\202\323\344\223\002)\022\r/tasks/{id=" + + "*}Z\030\022\026/{tenant}/tasks/{id=*}\022c\n\tListTask" + + "s\022\030.a2a.v1.ListTasksRequest\032\031.a2a.v1.Lis" + + "tTasksResponse\"!\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tena" + + "nt}/tasks\022z\n\nCancelTask\022\031.a2a.v1.CancelT" + + "askRequest\032\014.a2a.v1.Task\"C\202\323\344\223\002=\"\024/tasks" + + "/{id=*}:cancel:\001*Z\"\"\035/{tenant}/tasks/{id" + + "=*}:cancel:\001*\022\220\001\n\017SubscribeToTask\022\036.a2a." + + "v1.SubscribeToTaskRequest\032\026.a2a.v1.Strea" + + "mResponse\"C\202\323\344\223\002=\022\027/tasks/{id=*}:subscri" + + "beZ\"\022 /{tenant}/tasks/{id=*}:subscribe0\001" + + "\022\204\002\n CreateTaskPushNotificationConfig\022/." + + "a2a.v1.CreateTaskPushNotificationConfigR" + + "equest\032\".a2a.v1.TaskPushNotificationConf" + + "ig\"\212\001\332A\016task_id,config\202\323\344\223\002s\"*/tasks/{ta" + + "sk_id=*}/pushNotificationConfigs:\006config" + + "Z=\"3/{tenant}/tasks/{task_id=*}/pushNoti" + + "ficationConfigs:\006config\022\370\001\n\035GetTaskPushN" + + "otificationConfig\022,.a2a.v1.GetTaskPushNo" + + "tificationConfigRequest\032\".a2a.v1.TaskPus" + + "hNotificationConfig\"\204\001\332A\ntask_id,id\202\323\344\223\002" + + "q\0221/tasks/{task_id=*}/pushNotificationCo" + + "nfigs/{id=*}Z<\022:/{tenant}/tasks/{task_id" + + "=*}/pushNotificationConfigs/{id=*}\022\364\001\n\036L" + + "istTaskPushNotificationConfig\022-.a2a.v1.L" + + "istTaskPushNotificationConfigRequest\032..a" + + "2a.v1.ListTaskPushNotificationConfigResp" + + "onse\"s\332A\007task_id\202\323\344\223\002c\022*/tasks/{task_id=" + + "*}/pushNotificationConfigsZ5\0223/{tenant}/" + + "tasks/{task_id=*}/pushNotificationConfig" + + "s\022\211\001\n\024GetExtendedAgentCard\022#.a2a.v1.GetE" + + "xtendedAgentCardRequest\032\021.a2a.v1.AgentCa" + + "rd\"9\202\323\344\223\0023\022\022/extendedAgentCardZ\035\022\033/{tena" + + "nt}/extendedAgentCard\022\362\001\n DeleteTaskPush" + + "NotificationConfig\022/.a2a.v1.DeleteTaskPu" + + "shNotificationConfigRequest\032\026.google.pro" + + "tobuf.Empty\"\204\001\332A\ntask_id,id\202\323\344\223\002q*1/task" + + "s/{task_id=*}/pushNotificationConfigs/{i" + + "d=*}Z<*:/{tenant}/tasks/{task_id=*}/push" + + "NotificationConfigs/{id=*}B7\n\013io.a2a.grp" + + "cB\003A2AP\001Z\030google.golang.org/a2a/v1\252\002\006A2a" + + ".V1b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -560,67 +583,55 @@ public static void registerAllExtensions( internal_static_a2a_v1_Part_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_Part_descriptor, - new java.lang.String[] { "Text", "File", "Data", "Metadata", "Part", }); - internal_static_a2a_v1_FilePart_descriptor = - getDescriptor().getMessageType(4); - internal_static_a2a_v1_FilePart_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_FilePart_descriptor, - new java.lang.String[] { "FileWithUri", "FileWithBytes", "MediaType", "Name", "File", }); - internal_static_a2a_v1_DataPart_descriptor = - getDescriptor().getMessageType(5); - internal_static_a2a_v1_DataPart_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_DataPart_descriptor, - new java.lang.String[] { "Data", }); + new java.lang.String[] { "Text", "Raw", "Url", "Data", "Metadata", "Filename", "MediaType", "Content", }); internal_static_a2a_v1_Message_descriptor = - getDescriptor().getMessageType(6); + getDescriptor().getMessageType(4); internal_static_a2a_v1_Message_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_Message_descriptor, new java.lang.String[] { "MessageId", "ContextId", "TaskId", "Role", "Parts", "Metadata", "Extensions", "ReferenceTaskIds", }); internal_static_a2a_v1_Artifact_descriptor = - getDescriptor().getMessageType(7); + getDescriptor().getMessageType(5); internal_static_a2a_v1_Artifact_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_Artifact_descriptor, new java.lang.String[] { "ArtifactId", "Name", "Description", "Parts", "Metadata", "Extensions", }); internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor = - getDescriptor().getMessageType(8); + getDescriptor().getMessageType(6); internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor, - new java.lang.String[] { "TaskId", "ContextId", "Status", "Final", "Metadata", }); + new java.lang.String[] { "TaskId", "ContextId", "Status", "Metadata", }); internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor = - getDescriptor().getMessageType(9); + getDescriptor().getMessageType(7); internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor, new java.lang.String[] { "TaskId", "ContextId", "Artifact", "Append", "LastChunk", "Metadata", }); internal_static_a2a_v1_PushNotificationConfig_descriptor = - getDescriptor().getMessageType(10); + getDescriptor().getMessageType(8); internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_PushNotificationConfig_descriptor, new java.lang.String[] { "Id", "Url", "Token", "Authentication", }); internal_static_a2a_v1_AuthenticationInfo_descriptor = - getDescriptor().getMessageType(11); + getDescriptor().getMessageType(9); internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AuthenticationInfo_descriptor, - new java.lang.String[] { "Schemes", "Credentials", }); + new java.lang.String[] { "Scheme", "Credentials", }); internal_static_a2a_v1_AgentInterface_descriptor = - getDescriptor().getMessageType(12); + getDescriptor().getMessageType(10); internal_static_a2a_v1_AgentInterface_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentInterface_descriptor, - new java.lang.String[] { "Url", "ProtocolBinding", "Tenant", }); + new java.lang.String[] { "Url", "ProtocolBinding", "Tenant", "ProtocolVersion", }); internal_static_a2a_v1_AgentCard_descriptor = - getDescriptor().getMessageType(13); + getDescriptor().getMessageType(11); internal_static_a2a_v1_AgentCard_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentCard_descriptor, - new java.lang.String[] { "ProtocolVersions", "Name", "Description", "SupportedInterfaces", "Provider", "Version", "DocumentationUrl", "Capabilities", "SecuritySchemes", "Security", "DefaultInputModes", "DefaultOutputModes", "Skills", "Signatures", "IconUrl", }); + new java.lang.String[] { "Name", "Description", "SupportedInterfaces", "Provider", "Version", "DocumentationUrl", "Capabilities", "SecuritySchemes", "SecurityRequirements", "DefaultInputModes", "DefaultOutputModes", "Skills", "Signatures", "IconUrl", }); internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor = internal_static_a2a_v1_AgentCard_descriptor.getNestedType(0); internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_fieldAccessorTable = new @@ -628,103 +639,103 @@ public static void registerAllExtensions( internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_a2a_v1_AgentProvider_descriptor = - getDescriptor().getMessageType(14); + getDescriptor().getMessageType(12); internal_static_a2a_v1_AgentProvider_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentProvider_descriptor, new java.lang.String[] { "Url", "Organization", }); internal_static_a2a_v1_AgentCapabilities_descriptor = - getDescriptor().getMessageType(15); + getDescriptor().getMessageType(13); internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentCapabilities_descriptor, new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", "ExtendedAgentCard", }); internal_static_a2a_v1_AgentExtension_descriptor = - getDescriptor().getMessageType(16); + getDescriptor().getMessageType(14); internal_static_a2a_v1_AgentExtension_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentExtension_descriptor, new java.lang.String[] { "Uri", "Description", "Required", "Params", }); internal_static_a2a_v1_AgentSkill_descriptor = - getDescriptor().getMessageType(17); + getDescriptor().getMessageType(15); internal_static_a2a_v1_AgentSkill_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentSkill_descriptor, - new java.lang.String[] { "Id", "Name", "Description", "Tags", "Examples", "InputModes", "OutputModes", "Security", }); + new java.lang.String[] { "Id", "Name", "Description", "Tags", "Examples", "InputModes", "OutputModes", "SecurityRequirements", }); internal_static_a2a_v1_AgentCardSignature_descriptor = - getDescriptor().getMessageType(18); + getDescriptor().getMessageType(16); internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AgentCardSignature_descriptor, new java.lang.String[] { "Protected", "Signature", "Header", }); internal_static_a2a_v1_TaskPushNotificationConfig_descriptor = - getDescriptor().getMessageType(19); + getDescriptor().getMessageType(17); internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_TaskPushNotificationConfig_descriptor, - new java.lang.String[] { "Name", "PushNotificationConfig", }); + new java.lang.String[] { "Tenant", "Id", "TaskId", "PushNotificationConfig", }); internal_static_a2a_v1_StringList_descriptor = - getDescriptor().getMessageType(20); + getDescriptor().getMessageType(18); internal_static_a2a_v1_StringList_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_StringList_descriptor, new java.lang.String[] { "List", }); - internal_static_a2a_v1_Security_descriptor = - getDescriptor().getMessageType(21); - internal_static_a2a_v1_Security_fieldAccessorTable = new + internal_static_a2a_v1_SecurityRequirement_descriptor = + getDescriptor().getMessageType(19); + internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Security_descriptor, + internal_static_a2a_v1_SecurityRequirement_descriptor, new java.lang.String[] { "Schemes", }); - internal_static_a2a_v1_Security_SchemesEntry_descriptor = - internal_static_a2a_v1_Security_descriptor.getNestedType(0); - internal_static_a2a_v1_Security_SchemesEntry_fieldAccessorTable = new + internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor = + internal_static_a2a_v1_SecurityRequirement_descriptor.getNestedType(0); + internal_static_a2a_v1_SecurityRequirement_SchemesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Security_SchemesEntry_descriptor, + internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_a2a_v1_SecurityScheme_descriptor = - getDescriptor().getMessageType(22); + getDescriptor().getMessageType(20); internal_static_a2a_v1_SecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_SecurityScheme_descriptor, new java.lang.String[] { "ApiKeySecurityScheme", "HttpAuthSecurityScheme", "Oauth2SecurityScheme", "OpenIdConnectSecurityScheme", "MtlsSecurityScheme", "Scheme", }); internal_static_a2a_v1_APIKeySecurityScheme_descriptor = - getDescriptor().getMessageType(23); + getDescriptor().getMessageType(21); internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_APIKeySecurityScheme_descriptor, new java.lang.String[] { "Description", "Location", "Name", }); internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor = - getDescriptor().getMessageType(24); + getDescriptor().getMessageType(22); internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor, new java.lang.String[] { "Description", "Scheme", "BearerFormat", }); internal_static_a2a_v1_OAuth2SecurityScheme_descriptor = - getDescriptor().getMessageType(25); + getDescriptor().getMessageType(23); internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_OAuth2SecurityScheme_descriptor, new java.lang.String[] { "Description", "Flows", "Oauth2MetadataUrl", }); internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor = - getDescriptor().getMessageType(26); + getDescriptor().getMessageType(24); internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor, new java.lang.String[] { "Description", "OpenIdConnectUrl", }); internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor = - getDescriptor().getMessageType(27); + getDescriptor().getMessageType(25); internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor, new java.lang.String[] { "Description", }); internal_static_a2a_v1_OAuthFlows_descriptor = - getDescriptor().getMessageType(28); + getDescriptor().getMessageType(26); internal_static_a2a_v1_OAuthFlows_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_OAuthFlows_descriptor, - new java.lang.String[] { "AuthorizationCode", "ClientCredentials", "DeviceCode", "Flow", }); + new java.lang.String[] { "AuthorizationCode", "ClientCredentials", "Implicit", "Password", "DeviceCode", "Flow", }); internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor = - getDescriptor().getMessageType(29); + getDescriptor().getMessageType(27); internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor, @@ -736,7 +747,7 @@ public static void registerAllExtensions( internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor = - getDescriptor().getMessageType(30); + getDescriptor().getMessageType(28); internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor, @@ -747,6 +758,30 @@ public static void registerAllExtensions( com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); + internal_static_a2a_v1_ImplicitOAuthFlow_descriptor = + getDescriptor().getMessageType(29); + internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_ImplicitOAuthFlow_descriptor, + new java.lang.String[] { "AuthorizationUrl", "RefreshUrl", "Scopes", }); + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor = + internal_static_a2a_v1_ImplicitOAuthFlow_descriptor.getNestedType(0); + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + internal_static_a2a_v1_PasswordOAuthFlow_descriptor = + getDescriptor().getMessageType(30); + internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_PasswordOAuthFlow_descriptor, + new java.lang.String[] { "TokenUrl", "RefreshUrl", "Scopes", }); + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor = + internal_static_a2a_v1_PasswordOAuthFlow_descriptor.getNestedType(0); + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor = getDescriptor().getMessageType(31); internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable = new @@ -770,7 +805,7 @@ public static void registerAllExtensions( internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_GetTaskRequest_descriptor, - new java.lang.String[] { "Tenant", "Name", "HistoryLength", }); + new java.lang.String[] { "Tenant", "Id", "HistoryLength", }); internal_static_a2a_v1_ListTasksRequest_descriptor = getDescriptor().getMessageType(34); internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable = new @@ -788,37 +823,37 @@ public static void registerAllExtensions( internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_CancelTaskRequest_descriptor, - new java.lang.String[] { "Tenant", "Name", }); + new java.lang.String[] { "Tenant", "Id", }); internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor = getDescriptor().getMessageType(37); internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "Name", }); + new java.lang.String[] { "Tenant", "TaskId", "Id", }); internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor = getDescriptor().getMessageType(38); internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "Name", }); + new java.lang.String[] { "Tenant", "TaskId", "Id", }); internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor = getDescriptor().getMessageType(39); internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "Parent", "ConfigId", "Config", }); + new java.lang.String[] { "Tenant", "TaskId", "ConfigId", "Config", }); internal_static_a2a_v1_SubscribeToTaskRequest_descriptor = getDescriptor().getMessageType(40); internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_SubscribeToTaskRequest_descriptor, - new java.lang.String[] { "Tenant", "Name", }); + new java.lang.String[] { "Tenant", "Id", }); internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor = getDescriptor().getMessageType(41); internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "Parent", "PageSize", "PageToken", }); + new java.lang.String[] { "Tenant", "TaskId", "PageSize", "PageToken", }); internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor = getDescriptor().getMessageType(42); internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable = new diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java index 522c9083b..6d179b674 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java @@ -475,7 +475,7 @@ default void cancelTask(io.a2a.grpc.CancelTaskRequest request, /** *

          * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
    -     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, cancelled, rejected).
    +     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
          * 
    */ default void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, @@ -625,7 +625,7 @@ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, /** *
          * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
    -     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, cancelled, rejected).
    +     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
          * 
    */ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, @@ -764,7 +764,7 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws /** *
          * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
    -     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, cancelled, rejected).
    +     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
          * 
    */ @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") @@ -898,7 +898,7 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) { /** *
          * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
    -     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, cancelled, rejected).
    +     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
          * 
    */ public java.util.Iterator subscribeToTask( diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java index 5111e4f12..2b06f54b8 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java @@ -36,14 +36,12 @@ private AgentCard(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); } private AgentCard() { - protocolVersions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); name_ = ""; description_ = ""; supportedInterfaces_ = java.util.Collections.emptyList(); version_ = ""; documentationUrl_ = ""; - security_ = java.util.Collections.emptyList(); + securityRequirements_ = java.util.Collections.emptyList(); defaultInputModes_ = com.google.protobuf.LazyStringArrayList.emptyList(); defaultOutputModes_ = @@ -79,71 +77,6 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl } private int bitField0_; - public static final int PROTOCOL_VERSIONS_FIELD_NUMBER = 16; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList protocolVersions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
    -   * The versions of the A2A protocol this agent supports.
    -   * For stable versions (1.x+), list only the latest supported minor version per major version.
    -   * For legacy experimental versions (0.x), explicitly list each supported version.
    -   * Default: ["1.0"]
    -   * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the protocolVersions. - */ - public com.google.protobuf.ProtocolStringList - getProtocolVersionsList() { - return protocolVersions_; - } - /** - *
    -   * The versions of the A2A protocol this agent supports.
    -   * For stable versions (1.x+), list only the latest supported minor version per major version.
    -   * For legacy experimental versions (0.x), explicitly list each supported version.
    -   * Default: ["1.0"]
    -   * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of protocolVersions. - */ - public int getProtocolVersionsCount() { - return protocolVersions_.size(); - } - /** - *
    -   * The versions of the A2A protocol this agent supports.
    -   * For stable versions (1.x+), list only the latest supported minor version per major version.
    -   * For legacy experimental versions (0.x), explicitly list each supported version.
    -   * Default: ["1.0"]
    -   * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The protocolVersions at the given index. - */ - public java.lang.String getProtocolVersions(int index) { - return protocolVersions_.get(index); - } - /** - *
    -   * The versions of the A2A protocol this agent supports.
    -   * For stable versions (1.x+), list only the latest supported minor version per major version.
    -   * For legacy experimental versions (0.x), explicitly list each supported version.
    -   * Default: ["1.0"]
    -   * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the protocolVersions at the given index. - */ - public com.google.protobuf.ByteString - getProtocolVersionsBytes(int index) { - return protocolVersions_.getByteString(index); - } - public static final int NAME_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object name_ = ""; @@ -584,70 +517,65 @@ public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( return map.get(key); } - public static final int SECURITY_FIELD_NUMBER = 9; + public static final int SECURITY_REQUIREMENTS_FIELD_NUMBER = 13; @SuppressWarnings("serial") - private java.util.List security_; + private java.util.List securityRequirements_; /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ @java.lang.Override - public java.util.List getSecurityList() { - return security_; + public java.util.List getSecurityRequirementsList() { + return securityRequirements_; } /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ @java.lang.Override - public java.util.List - getSecurityOrBuilderList() { - return security_; + public java.util.List + getSecurityRequirementsOrBuilderList() { + return securityRequirements_; } /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ @java.lang.Override - public int getSecurityCount() { - return security_.size(); + public int getSecurityRequirementsCount() { + return securityRequirements_.size(); } /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ @java.lang.Override - public io.a2a.grpc.Security getSecurity(int index) { - return security_.get(index); + public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { + return securityRequirements_.get(index); } /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ @java.lang.Override - public io.a2a.grpc.SecurityOrBuilder getSecurityOrBuilder( + public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index) { - return security_.get(index); + return securityRequirements_.get(index); } public static final int DEFAULT_INPUT_MODES_FIELD_NUMBER = 10; @@ -993,9 +921,6 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) internalGetSecuritySchemes(), SecuritySchemesDefaultEntryHolder.defaultEntry, 8); - for (int i = 0; i < security_.size(); i++) { - output.writeMessage(9, security_.get(i)); - } for (int i = 0; i < defaultInputModes_.size(); i++) { com.google.protobuf.GeneratedMessage.writeString(output, 10, defaultInputModes_.getRaw(i)); } @@ -1005,8 +930,8 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) for (int i = 0; i < skills_.size(); i++) { output.writeMessage(12, skills_.get(i)); } - for (int i = 0; i < protocolVersions_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 16, protocolVersions_.getRaw(i)); + for (int i = 0; i < securityRequirements_.size(); i++) { + output.writeMessage(13, securityRequirements_.get(i)); } for (int i = 0; i < signatures_.size(); i++) { output.writeMessage(17, signatures_.get(i)); @@ -1056,10 +981,6 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(8, securitySchemes__); } - for (int i = 0; i < security_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(9, security_.get(i)); - } { int dataSize = 0; for (int i = 0; i < defaultInputModes_.size(); i++) { @@ -1080,13 +1001,9 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(12, skills_.get(i)); } - { - int dataSize = 0; - for (int i = 0; i < protocolVersions_.size(); i++) { - dataSize += computeStringSizeNoTag(protocolVersions_.getRaw(i)); - } - size += dataSize; - size += 2 * getProtocolVersionsList().size(); + for (int i = 0; i < securityRequirements_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(13, securityRequirements_.get(i)); } for (int i = 0; i < signatures_.size(); i++) { size += com.google.protobuf.CodedOutputStream @@ -1114,8 +1031,6 @@ public boolean equals(final java.lang.Object obj) { } io.a2a.grpc.AgentCard other = (io.a2a.grpc.AgentCard) obj; - if (!getProtocolVersionsList() - .equals(other.getProtocolVersionsList())) return false; if (!getName() .equals(other.getName())) return false; if (!getDescription() @@ -1141,8 +1056,8 @@ public boolean equals(final java.lang.Object obj) { } if (!internalGetSecuritySchemes().equals( other.internalGetSecuritySchemes())) return false; - if (!getSecurityList() - .equals(other.getSecurityList())) return false; + if (!getSecurityRequirementsList() + .equals(other.getSecurityRequirementsList())) return false; if (!getDefaultInputModesList() .equals(other.getDefaultInputModesList())) return false; if (!getDefaultOutputModesList() @@ -1167,10 +1082,6 @@ public int hashCode() { } int hash = 41; hash = (19 * hash) + getDescriptor().hashCode(); - if (getProtocolVersionsCount() > 0) { - hash = (37 * hash) + PROTOCOL_VERSIONS_FIELD_NUMBER; - hash = (53 * hash) + getProtocolVersionsList().hashCode(); - } hash = (37 * hash) + NAME_FIELD_NUMBER; hash = (53 * hash) + getName().hashCode(); hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; @@ -1197,9 +1108,9 @@ public int hashCode() { hash = (37 * hash) + SECURITY_SCHEMES_FIELD_NUMBER; hash = (53 * hash) + internalGetSecuritySchemes().hashCode(); } - if (getSecurityCount() > 0) { - hash = (37 * hash) + SECURITY_FIELD_NUMBER; - hash = (53 * hash) + getSecurityList().hashCode(); + if (getSecurityRequirementsCount() > 0) { + hash = (37 * hash) + SECURITY_REQUIREMENTS_FIELD_NUMBER; + hash = (53 * hash) + getSecurityRequirementsList().hashCode(); } if (getDefaultInputModesCount() > 0) { hash = (37 * hash) + DEFAULT_INPUT_MODES_FIELD_NUMBER; @@ -1384,7 +1295,7 @@ private void maybeForceBuilderInitialization() { internalGetSupportedInterfacesFieldBuilder(); internalGetProviderFieldBuilder(); internalGetCapabilitiesFieldBuilder(); - internalGetSecurityFieldBuilder(); + internalGetSecurityRequirementsFieldBuilder(); internalGetSkillsFieldBuilder(); internalGetSignaturesFieldBuilder(); } @@ -1393,8 +1304,6 @@ private void maybeForceBuilderInitialization() { public Builder clear() { super.clear(); bitField0_ = 0; - protocolVersions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); name_ = ""; description_ = ""; if (supportedInterfacesBuilder_ == null) { @@ -1403,7 +1312,7 @@ public Builder clear() { supportedInterfaces_ = null; supportedInterfacesBuilder_.clear(); } - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000004); provider_ = null; if (providerBuilder_ != null) { providerBuilder_.dispose(); @@ -1417,13 +1326,13 @@ public Builder clear() { capabilitiesBuilder_ = null; } internalGetMutableSecuritySchemes().clear(); - if (securityBuilder_ == null) { - security_ = java.util.Collections.emptyList(); + if (securityRequirementsBuilder_ == null) { + securityRequirements_ = java.util.Collections.emptyList(); } else { - security_ = null; - securityBuilder_.clear(); + securityRequirements_ = null; + securityRequirementsBuilder_.clear(); } - bitField0_ = (bitField0_ & ~0x00000200); + bitField0_ = (bitField0_ & ~0x00000100); defaultInputModes_ = com.google.protobuf.LazyStringArrayList.emptyList(); defaultOutputModes_ = @@ -1434,14 +1343,14 @@ public Builder clear() { skills_ = null; skillsBuilder_.clear(); } - bitField0_ = (bitField0_ & ~0x00001000); + bitField0_ = (bitField0_ & ~0x00000800); if (signaturesBuilder_ == null) { signatures_ = java.util.Collections.emptyList(); } else { signatures_ = null; signaturesBuilder_.clear(); } - bitField0_ = (bitField0_ & ~0x00002000); + bitField0_ = (bitField0_ & ~0x00001000); iconUrl_ = ""; return this; } @@ -1477,36 +1386,36 @@ public io.a2a.grpc.AgentCard buildPartial() { private void buildPartialRepeatedFields(io.a2a.grpc.AgentCard result) { if (supportedInterfacesBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0)) { + if (((bitField0_ & 0x00000004) != 0)) { supportedInterfaces_ = java.util.Collections.unmodifiableList(supportedInterfaces_); - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000004); } result.supportedInterfaces_ = supportedInterfaces_; } else { result.supportedInterfaces_ = supportedInterfacesBuilder_.build(); } - if (securityBuilder_ == null) { - if (((bitField0_ & 0x00000200) != 0)) { - security_ = java.util.Collections.unmodifiableList(security_); - bitField0_ = (bitField0_ & ~0x00000200); + if (securityRequirementsBuilder_ == null) { + if (((bitField0_ & 0x00000100) != 0)) { + securityRequirements_ = java.util.Collections.unmodifiableList(securityRequirements_); + bitField0_ = (bitField0_ & ~0x00000100); } - result.security_ = security_; + result.securityRequirements_ = securityRequirements_; } else { - result.security_ = securityBuilder_.build(); + result.securityRequirements_ = securityRequirementsBuilder_.build(); } if (skillsBuilder_ == null) { - if (((bitField0_ & 0x00001000) != 0)) { + if (((bitField0_ & 0x00000800) != 0)) { skills_ = java.util.Collections.unmodifiableList(skills_); - bitField0_ = (bitField0_ & ~0x00001000); + bitField0_ = (bitField0_ & ~0x00000800); } result.skills_ = skills_; } else { result.skills_ = skillsBuilder_.build(); } if (signaturesBuilder_ == null) { - if (((bitField0_ & 0x00002000) != 0)) { + if (((bitField0_ & 0x00001000) != 0)) { signatures_ = java.util.Collections.unmodifiableList(signatures_); - bitField0_ = (bitField0_ & ~0x00002000); + bitField0_ = (bitField0_ & ~0x00001000); } result.signatures_ = signatures_; } else { @@ -1517,47 +1426,43 @@ private void buildPartialRepeatedFields(io.a2a.grpc.AgentCard result) { private void buildPartial0(io.a2a.grpc.AgentCard result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { - protocolVersions_.makeImmutable(); - result.protocolVersions_ = protocolVersions_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { result.name_ = name_; } - if (((from_bitField0_ & 0x00000004) != 0)) { + if (((from_bitField0_ & 0x00000002) != 0)) { result.description_ = description_; } int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000010) != 0)) { + if (((from_bitField0_ & 0x00000008) != 0)) { result.provider_ = providerBuilder_ == null ? provider_ : providerBuilder_.build(); to_bitField0_ |= 0x00000001; } - if (((from_bitField0_ & 0x00000020) != 0)) { + if (((from_bitField0_ & 0x00000010) != 0)) { result.version_ = version_; } - if (((from_bitField0_ & 0x00000040) != 0)) { + if (((from_bitField0_ & 0x00000020) != 0)) { result.documentationUrl_ = documentationUrl_; to_bitField0_ |= 0x00000002; } - if (((from_bitField0_ & 0x00000080) != 0)) { + if (((from_bitField0_ & 0x00000040) != 0)) { result.capabilities_ = capabilitiesBuilder_ == null ? capabilities_ : capabilitiesBuilder_.build(); to_bitField0_ |= 0x00000004; } - if (((from_bitField0_ & 0x00000100) != 0)) { + if (((from_bitField0_ & 0x00000080) != 0)) { result.securitySchemes_ = internalGetSecuritySchemes().build(SecuritySchemesDefaultEntryHolder.defaultEntry); } - if (((from_bitField0_ & 0x00000400) != 0)) { + if (((from_bitField0_ & 0x00000200) != 0)) { defaultInputModes_.makeImmutable(); result.defaultInputModes_ = defaultInputModes_; } - if (((from_bitField0_ & 0x00000800) != 0)) { + if (((from_bitField0_ & 0x00000400) != 0)) { defaultOutputModes_.makeImmutable(); result.defaultOutputModes_ = defaultOutputModes_; } - if (((from_bitField0_ & 0x00004000) != 0)) { + if (((from_bitField0_ & 0x00002000) != 0)) { result.iconUrl_ = iconUrl_; to_bitField0_ |= 0x00000008; } @@ -1576,31 +1481,21 @@ public Builder mergeFrom(com.google.protobuf.Message other) { public Builder mergeFrom(io.a2a.grpc.AgentCard other) { if (other == io.a2a.grpc.AgentCard.getDefaultInstance()) return this; - if (!other.protocolVersions_.isEmpty()) { - if (protocolVersions_.isEmpty()) { - protocolVersions_ = other.protocolVersions_; - bitField0_ |= 0x00000001; - } else { - ensureProtocolVersionsIsMutable(); - protocolVersions_.addAll(other.protocolVersions_); - } - onChanged(); - } if (!other.getName().isEmpty()) { name_ = other.name_; - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000001; onChanged(); } if (!other.getDescription().isEmpty()) { description_ = other.description_; - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; onChanged(); } if (supportedInterfacesBuilder_ == null) { if (!other.supportedInterfaces_.isEmpty()) { if (supportedInterfaces_.isEmpty()) { supportedInterfaces_ = other.supportedInterfaces_; - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000004); } else { ensureSupportedInterfacesIsMutable(); supportedInterfaces_.addAll(other.supportedInterfaces_); @@ -1613,7 +1508,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { supportedInterfacesBuilder_.dispose(); supportedInterfacesBuilder_ = null; supportedInterfaces_ = other.supportedInterfaces_; - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000004); supportedInterfacesBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? internalGetSupportedInterfacesFieldBuilder() : null; @@ -1627,12 +1522,12 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { } if (!other.getVersion().isEmpty()) { version_ = other.version_; - bitField0_ |= 0x00000020; + bitField0_ |= 0x00000010; onChanged(); } if (other.hasDocumentationUrl()) { documentationUrl_ = other.documentationUrl_; - bitField0_ |= 0x00000040; + bitField0_ |= 0x00000020; onChanged(); } if (other.hasCapabilities()) { @@ -1640,37 +1535,37 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { } internalGetMutableSecuritySchemes().mergeFrom( other.internalGetSecuritySchemes()); - bitField0_ |= 0x00000100; - if (securityBuilder_ == null) { - if (!other.security_.isEmpty()) { - if (security_.isEmpty()) { - security_ = other.security_; - bitField0_ = (bitField0_ & ~0x00000200); + bitField0_ |= 0x00000080; + if (securityRequirementsBuilder_ == null) { + if (!other.securityRequirements_.isEmpty()) { + if (securityRequirements_.isEmpty()) { + securityRequirements_ = other.securityRequirements_; + bitField0_ = (bitField0_ & ~0x00000100); } else { - ensureSecurityIsMutable(); - security_.addAll(other.security_); + ensureSecurityRequirementsIsMutable(); + securityRequirements_.addAll(other.securityRequirements_); } onChanged(); } } else { - if (!other.security_.isEmpty()) { - if (securityBuilder_.isEmpty()) { - securityBuilder_.dispose(); - securityBuilder_ = null; - security_ = other.security_; - bitField0_ = (bitField0_ & ~0x00000200); - securityBuilder_ = + if (!other.securityRequirements_.isEmpty()) { + if (securityRequirementsBuilder_.isEmpty()) { + securityRequirementsBuilder_.dispose(); + securityRequirementsBuilder_ = null; + securityRequirements_ = other.securityRequirements_; + bitField0_ = (bitField0_ & ~0x00000100); + securityRequirementsBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetSecurityFieldBuilder() : null; + internalGetSecurityRequirementsFieldBuilder() : null; } else { - securityBuilder_.addAllMessages(other.security_); + securityRequirementsBuilder_.addAllMessages(other.securityRequirements_); } } } if (!other.defaultInputModes_.isEmpty()) { if (defaultInputModes_.isEmpty()) { defaultInputModes_ = other.defaultInputModes_; - bitField0_ |= 0x00000400; + bitField0_ |= 0x00000200; } else { ensureDefaultInputModesIsMutable(); defaultInputModes_.addAll(other.defaultInputModes_); @@ -1680,7 +1575,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { if (!other.defaultOutputModes_.isEmpty()) { if (defaultOutputModes_.isEmpty()) { defaultOutputModes_ = other.defaultOutputModes_; - bitField0_ |= 0x00000800; + bitField0_ |= 0x00000400; } else { ensureDefaultOutputModesIsMutable(); defaultOutputModes_.addAll(other.defaultOutputModes_); @@ -1691,7 +1586,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { if (!other.skills_.isEmpty()) { if (skills_.isEmpty()) { skills_ = other.skills_; - bitField0_ = (bitField0_ & ~0x00001000); + bitField0_ = (bitField0_ & ~0x00000800); } else { ensureSkillsIsMutable(); skills_.addAll(other.skills_); @@ -1704,7 +1599,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { skillsBuilder_.dispose(); skillsBuilder_ = null; skills_ = other.skills_; - bitField0_ = (bitField0_ & ~0x00001000); + bitField0_ = (bitField0_ & ~0x00000800); skillsBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? internalGetSkillsFieldBuilder() : null; @@ -1717,7 +1612,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { if (!other.signatures_.isEmpty()) { if (signatures_.isEmpty()) { signatures_ = other.signatures_; - bitField0_ = (bitField0_ & ~0x00002000); + bitField0_ = (bitField0_ & ~0x00001000); } else { ensureSignaturesIsMutable(); signatures_.addAll(other.signatures_); @@ -1730,7 +1625,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { signaturesBuilder_.dispose(); signaturesBuilder_ = null; signatures_ = other.signatures_; - bitField0_ = (bitField0_ & ~0x00002000); + bitField0_ = (bitField0_ & ~0x00001000); signaturesBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? internalGetSignaturesFieldBuilder() : null; @@ -1741,7 +1636,7 @@ public Builder mergeFrom(io.a2a.grpc.AgentCard other) { } if (other.hasIconUrl()) { iconUrl_ = other.iconUrl_; - bitField0_ |= 0x00004000; + bitField0_ |= 0x00002000; onChanged(); } this.mergeUnknownFields(other.getUnknownFields()); @@ -1772,36 +1667,36 @@ public Builder mergeFrom( break; case 10: { name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000001; break; } // case 10 case 18: { description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; break; } // case 18 case 34: { input.readMessage( internalGetProviderFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x00000010; + bitField0_ |= 0x00000008; break; } // case 34 case 42: { version_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000020; + bitField0_ |= 0x00000010; break; } // case 42 case 50: { documentationUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000040; + bitField0_ |= 0x00000020; break; } // case 50 case 58: { input.readMessage( internalGetCapabilitiesFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x00000080; + bitField0_ |= 0x00000040; break; } // case 58 case 66: { @@ -1810,22 +1705,9 @@ public Builder mergeFrom( SecuritySchemesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); internalGetMutableSecuritySchemes().ensureBuilderMap().put( securitySchemes__.getKey(), securitySchemes__.getValue()); - bitField0_ |= 0x00000100; + bitField0_ |= 0x00000080; break; } // case 66 - case 74: { - io.a2a.grpc.Security m = - input.readMessage( - io.a2a.grpc.Security.parser(), - extensionRegistry); - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.add(m); - } else { - securityBuilder_.addMessage(m); - } - break; - } // case 74 case 82: { java.lang.String s = input.readStringRequireUtf8(); ensureDefaultInputModesIsMutable(); @@ -1851,12 +1733,19 @@ public Builder mergeFrom( } break; } // case 98 - case 130: { - java.lang.String s = input.readStringRequireUtf8(); - ensureProtocolVersionsIsMutable(); - protocolVersions_.add(s); + case 106: { + io.a2a.grpc.SecurityRequirement m = + input.readMessage( + io.a2a.grpc.SecurityRequirement.parser(), + extensionRegistry); + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(m); + } else { + securityRequirementsBuilder_.addMessage(m); + } break; - } // case 130 + } // case 106 case 138: { io.a2a.grpc.AgentCardSignature m = input.readMessage( @@ -1872,7 +1761,7 @@ public Builder mergeFrom( } // case 138 case 146: { iconUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00004000; + bitField0_ |= 0x00002000; break; } // case 146 case 154: { @@ -1905,180 +1794,6 @@ public Builder mergeFrom( } private int bitField0_; - private com.google.protobuf.LazyStringArrayList protocolVersions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureProtocolVersionsIsMutable() { - if (!protocolVersions_.isModifiable()) { - protocolVersions_ = new com.google.protobuf.LazyStringArrayList(protocolVersions_); - } - bitField0_ |= 0x00000001; - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the protocolVersions. - */ - public com.google.protobuf.ProtocolStringList - getProtocolVersionsList() { - protocolVersions_.makeImmutable(); - return protocolVersions_; - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of protocolVersions. - */ - public int getProtocolVersionsCount() { - return protocolVersions_.size(); - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The protocolVersions at the given index. - */ - public java.lang.String getProtocolVersions(int index) { - return protocolVersions_.get(index); - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the protocolVersions at the given index. - */ - public com.google.protobuf.ByteString - getProtocolVersionsBytes(int index) { - return protocolVersions_.getByteString(index); - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index to set the value at. - * @param value The protocolVersions to set. - * @return This builder for chaining. - */ - public Builder setProtocolVersions( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureProtocolVersionsIsMutable(); - protocolVersions_.set(index, value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param value The protocolVersions to add. - * @return This builder for chaining. - */ - public Builder addProtocolVersions( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureProtocolVersionsIsMutable(); - protocolVersions_.add(value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param values The protocolVersions to add. - * @return This builder for chaining. - */ - public Builder addAllProtocolVersions( - java.lang.Iterable values) { - ensureProtocolVersionsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, protocolVersions_); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearProtocolVersions() { - protocolVersions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001);; - onChanged(); - return this; - } - /** - *
    -     * The versions of the A2A protocol this agent supports.
    -     * For stable versions (1.x+), list only the latest supported minor version per major version.
    -     * For legacy experimental versions (0.x), explicitly list each supported version.
    -     * Default: ["1.0"]
    -     * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes of the protocolVersions to add. - * @return This builder for chaining. - */ - public Builder addProtocolVersionsBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureProtocolVersionsIsMutable(); - protocolVersions_.add(value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - private java.lang.Object name_ = ""; /** *
    @@ -2137,7 +1852,7 @@ public Builder setName(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
           name_ = value;
    -      bitField0_ |= 0x00000002;
    +      bitField0_ |= 0x00000001;
           onChanged();
           return this;
         }
    @@ -2152,7 +1867,7 @@ public Builder setName(
          */
         public Builder clearName() {
           name_ = getDefaultInstance().getName();
    -      bitField0_ = (bitField0_ & ~0x00000002);
    +      bitField0_ = (bitField0_ & ~0x00000001);
           onChanged();
           return this;
         }
    @@ -2171,7 +1886,7 @@ public Builder setNameBytes(
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
           name_ = value;
    -      bitField0_ |= 0x00000002;
    +      bitField0_ |= 0x00000001;
           onChanged();
           return this;
         }
    @@ -2237,7 +1952,7 @@ public Builder setDescription(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
           description_ = value;
    -      bitField0_ |= 0x00000004;
    +      bitField0_ |= 0x00000002;
           onChanged();
           return this;
         }
    @@ -2253,7 +1968,7 @@ public Builder setDescription(
          */
         public Builder clearDescription() {
           description_ = getDefaultInstance().getDescription();
    -      bitField0_ = (bitField0_ & ~0x00000004);
    +      bitField0_ = (bitField0_ & ~0x00000002);
           onChanged();
           return this;
         }
    @@ -2273,7 +1988,7 @@ public Builder setDescriptionBytes(
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
           description_ = value;
    -      bitField0_ |= 0x00000004;
    +      bitField0_ |= 0x00000002;
           onChanged();
           return this;
         }
    @@ -2281,9 +1996,9 @@ public Builder setDescriptionBytes(
         private java.util.List supportedInterfaces_ =
           java.util.Collections.emptyList();
         private void ensureSupportedInterfacesIsMutable() {
    -      if (!((bitField0_ & 0x00000008) != 0)) {
    +      if (!((bitField0_ & 0x00000004) != 0)) {
             supportedInterfaces_ = new java.util.ArrayList(supportedInterfaces_);
    -        bitField0_ |= 0x00000008;
    +        bitField0_ |= 0x00000004;
            }
         }
     
    @@ -2477,7 +2192,7 @@ public Builder addAllSupportedInterfaces(
         public Builder clearSupportedInterfaces() {
           if (supportedInterfacesBuilder_ == null) {
             supportedInterfaces_ = java.util.Collections.emptyList();
    -        bitField0_ = (bitField0_ & ~0x00000008);
    +        bitField0_ = (bitField0_ & ~0x00000004);
             onChanged();
           } else {
             supportedInterfacesBuilder_.clear();
    @@ -2582,7 +2297,7 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder(
             supportedInterfacesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                 io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder>(
                     supportedInterfaces_,
    -                ((bitField0_ & 0x00000008) != 0),
    +                ((bitField0_ & 0x00000004) != 0),
                     getParentForChildren(),
                     isClean());
             supportedInterfaces_ = null;
    @@ -2602,7 +2317,7 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder(
          * @return Whether the provider field is set.
          */
         public boolean hasProvider() {
    -      return ((bitField0_ & 0x00000010) != 0);
    +      return ((bitField0_ & 0x00000008) != 0);
         }
         /**
          * 
    @@ -2635,7 +2350,7 @@ public Builder setProvider(io.a2a.grpc.AgentProvider value) {
           } else {
             providerBuilder_.setMessage(value);
           }
    -      bitField0_ |= 0x00000010;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return this;
         }
    @@ -2653,7 +2368,7 @@ public Builder setProvider(
           } else {
             providerBuilder_.setMessage(builderForValue.build());
           }
    -      bitField0_ |= 0x00000010;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return this;
         }
    @@ -2666,7 +2381,7 @@ public Builder setProvider(
          */
         public Builder mergeProvider(io.a2a.grpc.AgentProvider value) {
           if (providerBuilder_ == null) {
    -        if (((bitField0_ & 0x00000010) != 0) &&
    +        if (((bitField0_ & 0x00000008) != 0) &&
               provider_ != null &&
               provider_ != io.a2a.grpc.AgentProvider.getDefaultInstance()) {
               getProviderBuilder().mergeFrom(value);
    @@ -2677,7 +2392,7 @@ public Builder mergeProvider(io.a2a.grpc.AgentProvider value) {
             providerBuilder_.mergeFrom(value);
           }
           if (provider_ != null) {
    -        bitField0_ |= 0x00000010;
    +        bitField0_ |= 0x00000008;
             onChanged();
           }
           return this;
    @@ -2690,7 +2405,7 @@ public Builder mergeProvider(io.a2a.grpc.AgentProvider value) {
          * .a2a.v1.AgentProvider provider = 4;
          */
         public Builder clearProvider() {
    -      bitField0_ = (bitField0_ & ~0x00000010);
    +      bitField0_ = (bitField0_ & ~0x00000008);
           provider_ = null;
           if (providerBuilder_ != null) {
             providerBuilder_.dispose();
    @@ -2707,7 +2422,7 @@ public Builder clearProvider() {
          * .a2a.v1.AgentProvider provider = 4;
          */
         public io.a2a.grpc.AgentProvider.Builder getProviderBuilder() {
    -      bitField0_ |= 0x00000010;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return internalGetProviderFieldBuilder().getBuilder();
         }
    @@ -2805,7 +2520,7 @@ public Builder setVersion(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
           version_ = value;
    -      bitField0_ |= 0x00000020;
    +      bitField0_ |= 0x00000010;
           onChanged();
           return this;
         }
    @@ -2820,7 +2535,7 @@ public Builder setVersion(
          */
         public Builder clearVersion() {
           version_ = getDefaultInstance().getVersion();
    -      bitField0_ = (bitField0_ & ~0x00000020);
    +      bitField0_ = (bitField0_ & ~0x00000010);
           onChanged();
           return this;
         }
    @@ -2839,7 +2554,7 @@ public Builder setVersionBytes(
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
           version_ = value;
    -      bitField0_ |= 0x00000020;
    +      bitField0_ |= 0x00000010;
           onChanged();
           return this;
         }
    @@ -2854,7 +2569,7 @@ public Builder setVersionBytes(
          * @return Whether the documentationUrl field is set.
          */
         public boolean hasDocumentationUrl() {
    -      return ((bitField0_ & 0x00000040) != 0);
    +      return ((bitField0_ & 0x00000020) != 0);
         }
         /**
          * 
    @@ -2910,7 +2625,7 @@ public Builder setDocumentationUrl(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
           documentationUrl_ = value;
    -      bitField0_ |= 0x00000040;
    +      bitField0_ |= 0x00000020;
           onChanged();
           return this;
         }
    @@ -2924,7 +2639,7 @@ public Builder setDocumentationUrl(
          */
         public Builder clearDocumentationUrl() {
           documentationUrl_ = getDefaultInstance().getDocumentationUrl();
    -      bitField0_ = (bitField0_ & ~0x00000040);
    +      bitField0_ = (bitField0_ & ~0x00000020);
           onChanged();
           return this;
         }
    @@ -2942,7 +2657,7 @@ public Builder setDocumentationUrlBytes(
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
           documentationUrl_ = value;
    -      bitField0_ |= 0x00000040;
    +      bitField0_ |= 0x00000020;
           onChanged();
           return this;
         }
    @@ -2959,7 +2674,7 @@ public Builder setDocumentationUrlBytes(
          * @return Whether the capabilities field is set.
          */
         public boolean hasCapabilities() {
    -      return ((bitField0_ & 0x00000080) != 0);
    +      return ((bitField0_ & 0x00000040) != 0);
         }
         /**
          * 
    @@ -2992,7 +2707,7 @@ public Builder setCapabilities(io.a2a.grpc.AgentCapabilities value) {
           } else {
             capabilitiesBuilder_.setMessage(value);
           }
    -      bitField0_ |= 0x00000080;
    +      bitField0_ |= 0x00000040;
           onChanged();
           return this;
         }
    @@ -3010,7 +2725,7 @@ public Builder setCapabilities(
           } else {
             capabilitiesBuilder_.setMessage(builderForValue.build());
           }
    -      bitField0_ |= 0x00000080;
    +      bitField0_ |= 0x00000040;
           onChanged();
           return this;
         }
    @@ -3023,7 +2738,7 @@ public Builder setCapabilities(
          */
         public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) {
           if (capabilitiesBuilder_ == null) {
    -        if (((bitField0_ & 0x00000080) != 0) &&
    +        if (((bitField0_ & 0x00000040) != 0) &&
               capabilities_ != null &&
               capabilities_ != io.a2a.grpc.AgentCapabilities.getDefaultInstance()) {
               getCapabilitiesBuilder().mergeFrom(value);
    @@ -3034,7 +2749,7 @@ public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) {
             capabilitiesBuilder_.mergeFrom(value);
           }
           if (capabilities_ != null) {
    -        bitField0_ |= 0x00000080;
    +        bitField0_ |= 0x00000040;
             onChanged();
           }
           return this;
    @@ -3047,7 +2762,7 @@ public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) {
          * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
          */
         public Builder clearCapabilities() {
    -      bitField0_ = (bitField0_ & ~0x00000080);
    +      bitField0_ = (bitField0_ & ~0x00000040);
           capabilities_ = null;
           if (capabilitiesBuilder_ != null) {
             capabilitiesBuilder_.dispose();
    @@ -3064,7 +2779,7 @@ public Builder clearCapabilities() {
          * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
          */
         public io.a2a.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() {
    -      bitField0_ |= 0x00000080;
    +      bitField0_ |= 0x00000040;
           onChanged();
           return internalGetCapabilitiesFieldBuilder().getBuilder();
         }
    @@ -3132,7 +2847,7 @@ public com.google.protobuf.MapEntry(securitySchemesConverter);
           }
    -      bitField0_ |= 0x00000100;
    +      bitField0_ |= 0x00000080;
           onChanged();
           return securitySchemes_;
         }
    @@ -3206,7 +2921,7 @@ public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
           return securitySchemesConverter.build(map.get(key));
         }
         public Builder clearSecuritySchemes() {
    -      bitField0_ = (bitField0_ & ~0x00000100);
    +      bitField0_ = (bitField0_ & ~0x00000080);
           internalGetMutableSecuritySchemes().clear();
           return this;
         }
    @@ -3230,7 +2945,7 @@ public Builder removeSecuritySchemes(
         @java.lang.Deprecated
         public java.util.Map
             getMutableSecuritySchemes() {
    -      bitField0_ |= 0x00000100;
    +      bitField0_ |= 0x00000080;
           return internalGetMutableSecuritySchemes().ensureMessageMap();
         }
         /**
    @@ -3247,7 +2962,7 @@ public Builder putSecuritySchemes(
           if (value == null) { throw new NullPointerException("map value"); }
           internalGetMutableSecuritySchemes().ensureBuilderMap()
               .put(key, value);
    -      bitField0_ |= 0x00000100;
    +      bitField0_ |= 0x00000080;
           return this;
         }
         /**
    @@ -3266,7 +2981,7 @@ public Builder putAllSecuritySchemes(
           }
           internalGetMutableSecuritySchemes().ensureBuilderMap()
               .putAll(values);
    -      bitField0_ |= 0x00000100;
    +      bitField0_ |= 0x00000080;
           return this;
         }
         /**
    @@ -3291,334 +3006,316 @@ public io.a2a.grpc.SecurityScheme.Builder putSecuritySchemesBuilderIfAbsent(
           return (io.a2a.grpc.SecurityScheme.Builder) entry;
         }
     
    -    private java.util.List security_ =
    +    private java.util.List securityRequirements_ =
           java.util.Collections.emptyList();
    -    private void ensureSecurityIsMutable() {
    -      if (!((bitField0_ & 0x00000200) != 0)) {
    -        security_ = new java.util.ArrayList(security_);
    -        bitField0_ |= 0x00000200;
    +    private void ensureSecurityRequirementsIsMutable() {
    +      if (!((bitField0_ & 0x00000100) != 0)) {
    +        securityRequirements_ = new java.util.ArrayList(securityRequirements_);
    +        bitField0_ |= 0x00000100;
            }
         }
     
         private com.google.protobuf.RepeatedFieldBuilder<
    -        io.a2a.grpc.Security, io.a2a.grpc.Security.Builder, io.a2a.grpc.SecurityOrBuilder> securityBuilder_;
    +        io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> securityRequirementsBuilder_;
     
         /**
          * 
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public java.util.List getSecurityList() { - if (securityBuilder_ == null) { - return java.util.Collections.unmodifiableList(security_); + public java.util.List getSecurityRequirementsList() { + if (securityRequirementsBuilder_ == null) { + return java.util.Collections.unmodifiableList(securityRequirements_); } else { - return securityBuilder_.getMessageList(); + return securityRequirementsBuilder_.getMessageList(); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public int getSecurityCount() { - if (securityBuilder_ == null) { - return security_.size(); + public int getSecurityRequirementsCount() { + if (securityRequirementsBuilder_ == null) { + return securityRequirements_.size(); } else { - return securityBuilder_.getCount(); + return securityRequirementsBuilder_.getCount(); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public io.a2a.grpc.Security getSecurity(int index) { - if (securityBuilder_ == null) { - return security_.get(index); + public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { + if (securityRequirementsBuilder_ == null) { + return securityRequirements_.get(index); } else { - return securityBuilder_.getMessage(index); + return securityRequirementsBuilder_.getMessage(index); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder setSecurity( - int index, io.a2a.grpc.Security value) { - if (securityBuilder_ == null) { + public Builder setSecurityRequirements( + int index, io.a2a.grpc.SecurityRequirement value) { + if (securityRequirementsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureSecurityIsMutable(); - security_.set(index, value); + ensureSecurityRequirementsIsMutable(); + securityRequirements_.set(index, value); onChanged(); } else { - securityBuilder_.setMessage(index, value); + securityRequirementsBuilder_.setMessage(index, value); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder setSecurity( - int index, io.a2a.grpc.Security.Builder builderForValue) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.set(index, builderForValue.build()); + public Builder setSecurityRequirements( + int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.set(index, builderForValue.build()); onChanged(); } else { - securityBuilder_.setMessage(index, builderForValue.build()); + securityRequirementsBuilder_.setMessage(index, builderForValue.build()); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder addSecurity(io.a2a.grpc.Security value) { - if (securityBuilder_ == null) { + public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) { + if (securityRequirementsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureSecurityIsMutable(); - security_.add(value); + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(value); onChanged(); } else { - securityBuilder_.addMessage(value); + securityRequirementsBuilder_.addMessage(value); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder addSecurity( - int index, io.a2a.grpc.Security value) { - if (securityBuilder_ == null) { + public Builder addSecurityRequirements( + int index, io.a2a.grpc.SecurityRequirement value) { + if (securityRequirementsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureSecurityIsMutable(); - security_.add(index, value); + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(index, value); onChanged(); } else { - securityBuilder_.addMessage(index, value); + securityRequirementsBuilder_.addMessage(index, value); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder addSecurity( - io.a2a.grpc.Security.Builder builderForValue) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.add(builderForValue.build()); + public Builder addSecurityRequirements( + io.a2a.grpc.SecurityRequirement.Builder builderForValue) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(builderForValue.build()); onChanged(); } else { - securityBuilder_.addMessage(builderForValue.build()); + securityRequirementsBuilder_.addMessage(builderForValue.build()); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder addSecurity( - int index, io.a2a.grpc.Security.Builder builderForValue) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.add(index, builderForValue.build()); + public Builder addSecurityRequirements( + int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(index, builderForValue.build()); onChanged(); } else { - securityBuilder_.addMessage(index, builderForValue.build()); + securityRequirementsBuilder_.addMessage(index, builderForValue.build()); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder addAllSecurity( - java.lang.Iterable values) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); + public Builder addAllSecurityRequirements( + java.lang.Iterable values) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, security_); + values, securityRequirements_); onChanged(); } else { - securityBuilder_.addAllMessages(values); + securityRequirementsBuilder_.addAllMessages(values); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder clearSecurity() { - if (securityBuilder_ == null) { - security_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000200); + public Builder clearSecurityRequirements() { + if (securityRequirementsBuilder_ == null) { + securityRequirements_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000100); onChanged(); } else { - securityBuilder_.clear(); + securityRequirementsBuilder_.clear(); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public Builder removeSecurity(int index) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.remove(index); + public Builder removeSecurityRequirements(int index) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.remove(index); onChanged(); } else { - securityBuilder_.remove(index); + securityRequirementsBuilder_.remove(index); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public io.a2a.grpc.Security.Builder getSecurityBuilder( + public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder( int index) { - return internalGetSecurityFieldBuilder().getBuilder(index); + return internalGetSecurityRequirementsFieldBuilder().getBuilder(index); } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public io.a2a.grpc.SecurityOrBuilder getSecurityOrBuilder( + public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index) { - if (securityBuilder_ == null) { - return security_.get(index); } else { - return securityBuilder_.getMessageOrBuilder(index); + if (securityRequirementsBuilder_ == null) { + return securityRequirements_.get(index); } else { + return securityRequirementsBuilder_.getMessageOrBuilder(index); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public java.util.List - getSecurityOrBuilderList() { - if (securityBuilder_ != null) { - return securityBuilder_.getMessageOrBuilderList(); + public java.util.List + getSecurityRequirementsOrBuilderList() { + if (securityRequirementsBuilder_ != null) { + return securityRequirementsBuilder_.getMessageOrBuilderList(); } else { - return java.util.Collections.unmodifiableList(security_); + return java.util.Collections.unmodifiableList(securityRequirements_); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public io.a2a.grpc.Security.Builder addSecurityBuilder() { - return internalGetSecurityFieldBuilder().addBuilder( - io.a2a.grpc.Security.getDefaultInstance()); + public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() { + return internalGetSecurityRequirementsFieldBuilder().addBuilder( + io.a2a.grpc.SecurityRequirement.getDefaultInstance()); } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public io.a2a.grpc.Security.Builder addSecurityBuilder( + public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( int index) { - return internalGetSecurityFieldBuilder().addBuilder( - index, io.a2a.grpc.Security.getDefaultInstance()); + return internalGetSecurityRequirementsFieldBuilder().addBuilder( + index, io.a2a.grpc.SecurityRequirement.getDefaultInstance()); } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security requirements for contacting the agent.
          * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - public java.util.List - getSecurityBuilderList() { - return internalGetSecurityFieldBuilder().getBuilderList(); + public java.util.List + getSecurityRequirementsBuilderList() { + return internalGetSecurityRequirementsFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Security, io.a2a.grpc.Security.Builder, io.a2a.grpc.SecurityOrBuilder> - internalGetSecurityFieldBuilder() { - if (securityBuilder_ == null) { - securityBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Security, io.a2a.grpc.Security.Builder, io.a2a.grpc.SecurityOrBuilder>( - security_, - ((bitField0_ & 0x00000200) != 0), + io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> + internalGetSecurityRequirementsFieldBuilder() { + if (securityRequirementsBuilder_ == null) { + securityRequirementsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder>( + securityRequirements_, + ((bitField0_ & 0x00000100) != 0), getParentForChildren(), isClean()); - security_ = null; + securityRequirements_ = null; } - return securityBuilder_; + return securityRequirementsBuilder_; } private com.google.protobuf.LazyStringArrayList defaultInputModes_ = @@ -3627,7 +3324,7 @@ private void ensureDefaultInputModesIsMutable() { if (!defaultInputModes_.isModifiable()) { defaultInputModes_ = new com.google.protobuf.LazyStringArrayList(defaultInputModes_); } - bitField0_ |= 0x00000400; + bitField0_ |= 0x00000200; } /** *
    @@ -3703,7 +3400,7 @@ public Builder setDefaultInputModes(
           if (value == null) { throw new NullPointerException(); }
           ensureDefaultInputModesIsMutable();
           defaultInputModes_.set(index, value);
    -      bitField0_ |= 0x00000400;
    +      bitField0_ |= 0x00000200;
           onChanged();
           return this;
         }
    @@ -3723,7 +3420,7 @@ public Builder addDefaultInputModes(
           if (value == null) { throw new NullPointerException(); }
           ensureDefaultInputModesIsMutable();
           defaultInputModes_.add(value);
    -      bitField0_ |= 0x00000400;
    +      bitField0_ |= 0x00000200;
           onChanged();
           return this;
         }
    @@ -3743,7 +3440,7 @@ public Builder addAllDefaultInputModes(
           ensureDefaultInputModesIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
               values, defaultInputModes_);
    -      bitField0_ |= 0x00000400;
    +      bitField0_ |= 0x00000200;
           onChanged();
           return this;
         }
    @@ -3760,7 +3457,7 @@ public Builder addAllDefaultInputModes(
         public Builder clearDefaultInputModes() {
           defaultInputModes_ =
             com.google.protobuf.LazyStringArrayList.emptyList();
    -      bitField0_ = (bitField0_ & ~0x00000400);;
    +      bitField0_ = (bitField0_ & ~0x00000200);;
           onChanged();
           return this;
         }
    @@ -3781,7 +3478,7 @@ public Builder addDefaultInputModesBytes(
           checkByteStringIsUtf8(value);
           ensureDefaultInputModesIsMutable();
           defaultInputModes_.add(value);
    -      bitField0_ |= 0x00000400;
    +      bitField0_ |= 0x00000200;
           onChanged();
           return this;
         }
    @@ -3792,7 +3489,7 @@ private void ensureDefaultOutputModesIsMutable() {
           if (!defaultOutputModes_.isModifiable()) {
             defaultOutputModes_ = new com.google.protobuf.LazyStringArrayList(defaultOutputModes_);
           }
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000400;
         }
         /**
          * 
    @@ -3858,7 +3555,7 @@ public Builder setDefaultOutputModes(
           if (value == null) { throw new NullPointerException(); }
           ensureDefaultOutputModesIsMutable();
           defaultOutputModes_.set(index, value);
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000400;
           onChanged();
           return this;
         }
    @@ -3876,7 +3573,7 @@ public Builder addDefaultOutputModes(
           if (value == null) { throw new NullPointerException(); }
           ensureDefaultOutputModesIsMutable();
           defaultOutputModes_.add(value);
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000400;
           onChanged();
           return this;
         }
    @@ -3894,7 +3591,7 @@ public Builder addAllDefaultOutputModes(
           ensureDefaultOutputModesIsMutable();
           com.google.protobuf.AbstractMessageLite.Builder.addAll(
               values, defaultOutputModes_);
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000400;
           onChanged();
           return this;
         }
    @@ -3909,7 +3606,7 @@ public Builder addAllDefaultOutputModes(
         public Builder clearDefaultOutputModes() {
           defaultOutputModes_ =
             com.google.protobuf.LazyStringArrayList.emptyList();
    -      bitField0_ = (bitField0_ & ~0x00000800);;
    +      bitField0_ = (bitField0_ & ~0x00000400);;
           onChanged();
           return this;
         }
    @@ -3928,7 +3625,7 @@ public Builder addDefaultOutputModesBytes(
           checkByteStringIsUtf8(value);
           ensureDefaultOutputModesIsMutable();
           defaultOutputModes_.add(value);
    -      bitField0_ |= 0x00000800;
    +      bitField0_ |= 0x00000400;
           onChanged();
           return this;
         }
    @@ -3936,9 +3633,9 @@ public Builder addDefaultOutputModesBytes(
         private java.util.List skills_ =
           java.util.Collections.emptyList();
         private void ensureSkillsIsMutable() {
    -      if (!((bitField0_ & 0x00001000) != 0)) {
    +      if (!((bitField0_ & 0x00000800) != 0)) {
             skills_ = new java.util.ArrayList(skills_);
    -        bitField0_ |= 0x00001000;
    +        bitField0_ |= 0x00000800;
            }
         }
     
    @@ -4154,7 +3851,7 @@ public Builder addAllSkills(
         public Builder clearSkills() {
           if (skillsBuilder_ == null) {
             skills_ = java.util.Collections.emptyList();
    -        bitField0_ = (bitField0_ & ~0x00001000);
    +        bitField0_ = (bitField0_ & ~0x00000800);
             onChanged();
           } else {
             skillsBuilder_.clear();
    @@ -4273,7 +3970,7 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder(
             skillsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                 io.a2a.grpc.AgentSkill, io.a2a.grpc.AgentSkill.Builder, io.a2a.grpc.AgentSkillOrBuilder>(
                     skills_,
    -                ((bitField0_ & 0x00001000) != 0),
    +                ((bitField0_ & 0x00000800) != 0),
                     getParentForChildren(),
                     isClean());
             skills_ = null;
    @@ -4284,9 +3981,9 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder(
         private java.util.List signatures_ =
           java.util.Collections.emptyList();
         private void ensureSignaturesIsMutable() {
    -      if (!((bitField0_ & 0x00002000) != 0)) {
    +      if (!((bitField0_ & 0x00001000) != 0)) {
             signatures_ = new java.util.ArrayList(signatures_);
    -        bitField0_ |= 0x00002000;
    +        bitField0_ |= 0x00001000;
            }
         }
     
    @@ -4480,7 +4177,7 @@ public Builder addAllSignatures(
         public Builder clearSignatures() {
           if (signaturesBuilder_ == null) {
             signatures_ = java.util.Collections.emptyList();
    -        bitField0_ = (bitField0_ & ~0x00002000);
    +        bitField0_ = (bitField0_ & ~0x00001000);
             onChanged();
           } else {
             signaturesBuilder_.clear();
    @@ -4585,7 +4282,7 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder(
             signaturesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                 io.a2a.grpc.AgentCardSignature, io.a2a.grpc.AgentCardSignature.Builder, io.a2a.grpc.AgentCardSignatureOrBuilder>(
                     signatures_,
    -                ((bitField0_ & 0x00002000) != 0),
    +                ((bitField0_ & 0x00001000) != 0),
                     getParentForChildren(),
                     isClean());
             signatures_ = null;
    @@ -4603,7 +4300,7 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder(
          * @return Whether the iconUrl field is set.
          */
         public boolean hasIconUrl() {
    -      return ((bitField0_ & 0x00004000) != 0);
    +      return ((bitField0_ & 0x00002000) != 0);
         }
         /**
          * 
    @@ -4659,7 +4356,7 @@ public Builder setIconUrl(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
           iconUrl_ = value;
    -      bitField0_ |= 0x00004000;
    +      bitField0_ |= 0x00002000;
           onChanged();
           return this;
         }
    @@ -4673,7 +4370,7 @@ public Builder setIconUrl(
          */
         public Builder clearIconUrl() {
           iconUrl_ = getDefaultInstance().getIconUrl();
    -      bitField0_ = (bitField0_ & ~0x00004000);
    +      bitField0_ = (bitField0_ & ~0x00002000);
           onChanged();
           return this;
         }
    @@ -4691,7 +4388,7 @@ public Builder setIconUrlBytes(
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
           iconUrl_ = value;
    -      bitField0_ |= 0x00004000;
    +      bitField0_ |= 0x00002000;
           onChanged();
           return this;
         }
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java
    index 8c31e3053..379ec0282 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java
    @@ -10,59 +10,6 @@ public interface AgentCardOrBuilder extends
         // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCard)
         com.google.protobuf.MessageOrBuilder {
     
    -  /**
    -   * 
    -   * The versions of the A2A protocol this agent supports.
    -   * For stable versions (1.x+), list only the latest supported minor version per major version.
    -   * For legacy experimental versions (0.x), explicitly list each supported version.
    -   * Default: ["1.0"]
    -   * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the protocolVersions. - */ - java.util.List - getProtocolVersionsList(); - /** - *
    -   * The versions of the A2A protocol this agent supports.
    -   * For stable versions (1.x+), list only the latest supported minor version per major version.
    -   * For legacy experimental versions (0.x), explicitly list each supported version.
    -   * Default: ["1.0"]
    -   * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of protocolVersions. - */ - int getProtocolVersionsCount(); - /** - *
    -   * The versions of the A2A protocol this agent supports.
    -   * For stable versions (1.x+), list only the latest supported minor version per major version.
    -   * For legacy experimental versions (0.x), explicitly list each supported version.
    -   * Default: ["1.0"]
    -   * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The protocolVersions at the given index. - */ - java.lang.String getProtocolVersions(int index); - /** - *
    -   * The versions of the A2A protocol this agent supports.
    -   * For stable versions (1.x+), list only the latest supported minor version per major version.
    -   * For legacy experimental versions (0.x), explicitly list each supported version.
    -   * Default: ["1.0"]
    -   * 
    - * - * repeated string protocol_versions = 16 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the protocolVersions at the given index. - */ - com.google.protobuf.ByteString - getProtocolVersionsBytes(int index); - /** *
        * A human readable name for the agent.
    @@ -314,51 +261,46 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
     
       /**
        * 
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - java.util.List - getSecurityList(); + java.util.List + getSecurityRequirementsList(); /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - io.a2a.grpc.Security getSecurity(int index); + io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index); /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - int getSecurityCount(); + int getSecurityRequirementsCount(); /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - java.util.List - getSecurityOrBuilderList(); + java.util.List + getSecurityRequirementsOrBuilderList(); /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security requirements for contacting the agent.
        * 
    * - * repeated .a2a.v1.Security security = 9; + * repeated .a2a.v1.SecurityRequirement security_requirements = 13; */ - io.a2a.grpc.SecurityOrBuilder getSecurityOrBuilder( + io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index); /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java index 17db01b94..ac8001a8e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java @@ -8,7 +8,7 @@ /** *
      * --8<-- [start:AgentInterface]
    - * Declares a combination of a target URL and a transport protocol for interacting with the agent.
    + * Declares a combination of a target URL, transport and protocol version for interacting with the agent.
      * This allows agents to expose the same functionality over multiple protocol binding mechanisms.
      * 
    * @@ -37,6 +37,7 @@ private AgentInterface() { url_ = ""; protocolBinding_ = ""; tenant_ = ""; + protocolVersion_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -199,6 +200,57 @@ public java.lang.String getTenant() { } } + public static final int PROTOCOL_VERSION_FIELD_NUMBER = 4; + @SuppressWarnings("serial") + private volatile java.lang.Object protocolVersion_ = ""; + /** + *
    +   * The version of the A2A protocol this interface exposes.
    +   * Use the latest supported minor version per major version.
    +   * Examples: "0.3", "1.0"
    +   * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The protocolVersion. + */ + @java.lang.Override + public java.lang.String getProtocolVersion() { + java.lang.Object ref = protocolVersion_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + protocolVersion_ = s; + return s; + } + } + /** + *
    +   * The version of the A2A protocol this interface exposes.
    +   * Use the latest supported minor version per major version.
    +   * Examples: "0.3", "1.0"
    +   * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for protocolVersion. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getProtocolVersionBytes() { + java.lang.Object ref = protocolVersion_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + protocolVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -222,6 +274,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { com.google.protobuf.GeneratedMessage.writeString(output, 3, tenant_); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protocolVersion_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 4, protocolVersion_); + } getUnknownFields().writeTo(output); } @@ -240,6 +295,9 @@ public int getSerializedSize() { if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(3, tenant_); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protocolVersion_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(4, protocolVersion_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -261,6 +319,8 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getProtocolBinding())) return false; if (!getTenant() .equals(other.getTenant())) return false; + if (!getProtocolVersion() + .equals(other.getProtocolVersion())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -278,6 +338,8 @@ public int hashCode() { hash = (53 * hash) + getProtocolBinding().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); + hash = (37 * hash) + PROTOCOL_VERSION_FIELD_NUMBER; + hash = (53 * hash) + getProtocolVersion().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -378,7 +440,7 @@ protected Builder newBuilderForType( /** *
        * --8<-- [start:AgentInterface]
    -   * Declares a combination of a target URL and a transport protocol for interacting with the agent.
    +   * Declares a combination of a target URL, transport and protocol version for interacting with the agent.
        * This allows agents to expose the same functionality over multiple protocol binding mechanisms.
        * 
    * @@ -418,6 +480,7 @@ public Builder clear() { url_ = ""; protocolBinding_ = ""; tenant_ = ""; + protocolVersion_ = ""; return this; } @@ -460,6 +523,9 @@ private void buildPartial0(io.a2a.grpc.AgentInterface result) { if (((from_bitField0_ & 0x00000004) != 0)) { result.tenant_ = tenant_; } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.protocolVersion_ = protocolVersion_; + } } @java.lang.Override @@ -489,6 +555,11 @@ public Builder mergeFrom(io.a2a.grpc.AgentInterface other) { bitField0_ |= 0x00000004; onChanged(); } + if (!other.getProtocolVersion().isEmpty()) { + protocolVersion_ = other.protocolVersion_; + bitField0_ |= 0x00000008; + onChanged(); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -530,6 +601,11 @@ public Builder mergeFrom( bitField0_ |= 0x00000004; break; } // case 26 + case 34: { + protocolVersion_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000008; + break; + } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -838,6 +914,108 @@ public Builder setTenantBytes( return this; } + private java.lang.Object protocolVersion_ = ""; + /** + *
    +     * The version of the A2A protocol this interface exposes.
    +     * Use the latest supported minor version per major version.
    +     * Examples: "0.3", "1.0"
    +     * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The protocolVersion. + */ + public java.lang.String getProtocolVersion() { + java.lang.Object ref = protocolVersion_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + protocolVersion_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The version of the A2A protocol this interface exposes.
    +     * Use the latest supported minor version per major version.
    +     * Examples: "0.3", "1.0"
    +     * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for protocolVersion. + */ + public com.google.protobuf.ByteString + getProtocolVersionBytes() { + java.lang.Object ref = protocolVersion_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + protocolVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The version of the A2A protocol this interface exposes.
    +     * Use the latest supported minor version per major version.
    +     * Examples: "0.3", "1.0"
    +     * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @param value The protocolVersion to set. + * @return This builder for chaining. + */ + public Builder setProtocolVersion( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + protocolVersion_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
    +     * The version of the A2A protocol this interface exposes.
    +     * Use the latest supported minor version per major version.
    +     * Examples: "0.3", "1.0"
    +     * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearProtocolVersion() { + protocolVersion_ = getDefaultInstance().getProtocolVersion(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + return this; + } + /** + *
    +     * The version of the A2A protocol this interface exposes.
    +     * Use the latest supported minor version per major version.
    +     * Examples: "0.3", "1.0"
    +     * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for protocolVersion to set. + * @return This builder for chaining. + */ + public Builder setProtocolVersionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + protocolVersion_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentInterface) } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java index cfc8b7ad9..3dfe76f41 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java @@ -75,4 +75,28 @@ public interface AgentInterfaceOrBuilder extends */ com.google.protobuf.ByteString getTenantBytes(); + + /** + *
    +   * The version of the A2A protocol this interface exposes.
    +   * Use the latest supported minor version per major version.
    +   * Examples: "0.3", "1.0"
    +   * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The protocolVersion. + */ + java.lang.String getProtocolVersion(); + /** + *
    +   * The version of the A2A protocol this interface exposes.
    +   * Use the latest supported minor version per major version.
    +   * Examples: "0.3", "1.0"
    +   * 
    + * + * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for protocolVersion. + */ + com.google.protobuf.ByteString + getProtocolVersionBytes(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java index 19596fe14..087596019 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java @@ -44,7 +44,7 @@ private AgentSkill() { com.google.protobuf.LazyStringArrayList.emptyList(); outputModes_ = com.google.protobuf.LazyStringArrayList.emptyList(); - security_ = java.util.Collections.emptyList(); + securityRequirements_ = java.util.Collections.emptyList(); } public static final com.google.protobuf.Descriptors.Descriptor @@ -413,70 +413,65 @@ public java.lang.String getOutputModes(int index) { return outputModes_.getByteString(index); } - public static final int SECURITY_FIELD_NUMBER = 8; + public static final int SECURITY_REQUIREMENTS_FIELD_NUMBER = 8; @SuppressWarnings("serial") - private java.util.List security_; + private java.util.List securityRequirements_; /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override - public java.util.List getSecurityList() { - return security_; + public java.util.List getSecurityRequirementsList() { + return securityRequirements_; } /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override - public java.util.List - getSecurityOrBuilderList() { - return security_; + public java.util.List + getSecurityRequirementsOrBuilderList() { + return securityRequirements_; } /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override - public int getSecurityCount() { - return security_.size(); + public int getSecurityRequirementsCount() { + return securityRequirements_.size(); } /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override - public io.a2a.grpc.Security getSecurity(int index) { - return security_.get(index); + public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { + return securityRequirements_.get(index); } /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override - public io.a2a.grpc.SecurityOrBuilder getSecurityOrBuilder( + public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index) { - return security_.get(index); + return securityRequirements_.get(index); } private byte memoizedIsInitialized = -1; @@ -514,8 +509,8 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) for (int i = 0; i < outputModes_.size(); i++) { com.google.protobuf.GeneratedMessage.writeString(output, 7, outputModes_.getRaw(i)); } - for (int i = 0; i < security_.size(); i++) { - output.writeMessage(8, security_.get(i)); + for (int i = 0; i < securityRequirements_.size(); i++) { + output.writeMessage(8, securityRequirements_.get(i)); } getUnknownFields().writeTo(output); } @@ -567,9 +562,9 @@ public int getSerializedSize() { size += dataSize; size += 1 * getOutputModesList().size(); } - for (int i = 0; i < security_.size(); i++) { + for (int i = 0; i < securityRequirements_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(8, security_.get(i)); + .computeMessageSize(8, securityRequirements_.get(i)); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -600,8 +595,8 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getInputModesList())) return false; if (!getOutputModesList() .equals(other.getOutputModesList())) return false; - if (!getSecurityList() - .equals(other.getSecurityList())) return false; + if (!getSecurityRequirementsList() + .equals(other.getSecurityRequirementsList())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -635,9 +630,9 @@ public int hashCode() { hash = (37 * hash) + OUTPUT_MODES_FIELD_NUMBER; hash = (53 * hash) + getOutputModesList().hashCode(); } - if (getSecurityCount() > 0) { - hash = (37 * hash) + SECURITY_FIELD_NUMBER; - hash = (53 * hash) + getSecurityList().hashCode(); + if (getSecurityRequirementsCount() > 0) { + hash = (37 * hash) + SECURITY_REQUIREMENTS_FIELD_NUMBER; + hash = (53 * hash) + getSecurityRequirementsList().hashCode(); } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; @@ -786,11 +781,11 @@ public Builder clear() { com.google.protobuf.LazyStringArrayList.emptyList(); outputModes_ = com.google.protobuf.LazyStringArrayList.emptyList(); - if (securityBuilder_ == null) { - security_ = java.util.Collections.emptyList(); + if (securityRequirementsBuilder_ == null) { + securityRequirements_ = java.util.Collections.emptyList(); } else { - security_ = null; - securityBuilder_.clear(); + securityRequirements_ = null; + securityRequirementsBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000080); return this; @@ -826,14 +821,14 @@ public io.a2a.grpc.AgentSkill buildPartial() { } private void buildPartialRepeatedFields(io.a2a.grpc.AgentSkill result) { - if (securityBuilder_ == null) { + if (securityRequirementsBuilder_ == null) { if (((bitField0_ & 0x00000080) != 0)) { - security_ = java.util.Collections.unmodifiableList(security_); + securityRequirements_ = java.util.Collections.unmodifiableList(securityRequirements_); bitField0_ = (bitField0_ & ~0x00000080); } - result.security_ = security_; + result.securityRequirements_ = securityRequirements_; } else { - result.security_ = securityBuilder_.build(); + result.securityRequirements_ = securityRequirementsBuilder_.build(); } } @@ -933,29 +928,29 @@ public Builder mergeFrom(io.a2a.grpc.AgentSkill other) { } onChanged(); } - if (securityBuilder_ == null) { - if (!other.security_.isEmpty()) { - if (security_.isEmpty()) { - security_ = other.security_; + if (securityRequirementsBuilder_ == null) { + if (!other.securityRequirements_.isEmpty()) { + if (securityRequirements_.isEmpty()) { + securityRequirements_ = other.securityRequirements_; bitField0_ = (bitField0_ & ~0x00000080); } else { - ensureSecurityIsMutable(); - security_.addAll(other.security_); + ensureSecurityRequirementsIsMutable(); + securityRequirements_.addAll(other.securityRequirements_); } onChanged(); } } else { - if (!other.security_.isEmpty()) { - if (securityBuilder_.isEmpty()) { - securityBuilder_.dispose(); - securityBuilder_ = null; - security_ = other.security_; + if (!other.securityRequirements_.isEmpty()) { + if (securityRequirementsBuilder_.isEmpty()) { + securityRequirementsBuilder_.dispose(); + securityRequirementsBuilder_ = null; + securityRequirements_ = other.securityRequirements_; bitField0_ = (bitField0_ & ~0x00000080); - securityBuilder_ = + securityRequirementsBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetSecurityFieldBuilder() : null; + internalGetSecurityRequirementsFieldBuilder() : null; } else { - securityBuilder_.addAllMessages(other.security_); + securityRequirementsBuilder_.addAllMessages(other.securityRequirements_); } } } @@ -1025,15 +1020,15 @@ public Builder mergeFrom( break; } // case 58 case 66: { - io.a2a.grpc.Security m = + io.a2a.grpc.SecurityRequirement m = input.readMessage( - io.a2a.grpc.Security.parser(), + io.a2a.grpc.SecurityRequirement.parser(), extensionRegistry); - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.add(m); + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(m); } else { - securityBuilder_.addMessage(m); + securityRequirementsBuilder_.addMessage(m); } break; } // case 66 @@ -1918,334 +1913,316 @@ public Builder addOutputModesBytes( return this; } - private java.util.List security_ = + private java.util.List securityRequirements_ = java.util.Collections.emptyList(); - private void ensureSecurityIsMutable() { + private void ensureSecurityRequirementsIsMutable() { if (!((bitField0_ & 0x00000080) != 0)) { - security_ = new java.util.ArrayList(security_); + securityRequirements_ = new java.util.ArrayList(securityRequirements_); bitField0_ |= 0x00000080; } } private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Security, io.a2a.grpc.Security.Builder, io.a2a.grpc.SecurityOrBuilder> securityBuilder_; + io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> securityRequirementsBuilder_; /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public java.util.List getSecurityList() { - if (securityBuilder_ == null) { - return java.util.Collections.unmodifiableList(security_); + public java.util.List getSecurityRequirementsList() { + if (securityRequirementsBuilder_ == null) { + return java.util.Collections.unmodifiableList(securityRequirements_); } else { - return securityBuilder_.getMessageList(); + return securityRequirementsBuilder_.getMessageList(); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public int getSecurityCount() { - if (securityBuilder_ == null) { - return security_.size(); + public int getSecurityRequirementsCount() { + if (securityRequirementsBuilder_ == null) { + return securityRequirements_.size(); } else { - return securityBuilder_.getCount(); + return securityRequirementsBuilder_.getCount(); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public io.a2a.grpc.Security getSecurity(int index) { - if (securityBuilder_ == null) { - return security_.get(index); + public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { + if (securityRequirementsBuilder_ == null) { + return securityRequirements_.get(index); } else { - return securityBuilder_.getMessage(index); + return securityRequirementsBuilder_.getMessage(index); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder setSecurity( - int index, io.a2a.grpc.Security value) { - if (securityBuilder_ == null) { + public Builder setSecurityRequirements( + int index, io.a2a.grpc.SecurityRequirement value) { + if (securityRequirementsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureSecurityIsMutable(); - security_.set(index, value); + ensureSecurityRequirementsIsMutable(); + securityRequirements_.set(index, value); onChanged(); } else { - securityBuilder_.setMessage(index, value); + securityRequirementsBuilder_.setMessage(index, value); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder setSecurity( - int index, io.a2a.grpc.Security.Builder builderForValue) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.set(index, builderForValue.build()); + public Builder setSecurityRequirements( + int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.set(index, builderForValue.build()); onChanged(); } else { - securityBuilder_.setMessage(index, builderForValue.build()); + securityRequirementsBuilder_.setMessage(index, builderForValue.build()); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder addSecurity(io.a2a.grpc.Security value) { - if (securityBuilder_ == null) { + public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) { + if (securityRequirementsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureSecurityIsMutable(); - security_.add(value); + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(value); onChanged(); } else { - securityBuilder_.addMessage(value); + securityRequirementsBuilder_.addMessage(value); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder addSecurity( - int index, io.a2a.grpc.Security value) { - if (securityBuilder_ == null) { + public Builder addSecurityRequirements( + int index, io.a2a.grpc.SecurityRequirement value) { + if (securityRequirementsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureSecurityIsMutable(); - security_.add(index, value); + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(index, value); onChanged(); } else { - securityBuilder_.addMessage(index, value); + securityRequirementsBuilder_.addMessage(index, value); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder addSecurity( - io.a2a.grpc.Security.Builder builderForValue) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.add(builderForValue.build()); + public Builder addSecurityRequirements( + io.a2a.grpc.SecurityRequirement.Builder builderForValue) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(builderForValue.build()); onChanged(); } else { - securityBuilder_.addMessage(builderForValue.build()); + securityRequirementsBuilder_.addMessage(builderForValue.build()); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder addSecurity( - int index, io.a2a.grpc.Security.Builder builderForValue) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.add(index, builderForValue.build()); + public Builder addSecurityRequirements( + int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(index, builderForValue.build()); onChanged(); } else { - securityBuilder_.addMessage(index, builderForValue.build()); + securityRequirementsBuilder_.addMessage(index, builderForValue.build()); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder addAllSecurity( - java.lang.Iterable values) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); + public Builder addAllSecurityRequirements( + java.lang.Iterable values) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, security_); + values, securityRequirements_); onChanged(); } else { - securityBuilder_.addAllMessages(values); + securityRequirementsBuilder_.addAllMessages(values); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder clearSecurity() { - if (securityBuilder_ == null) { - security_ = java.util.Collections.emptyList(); + public Builder clearSecurityRequirements() { + if (securityRequirementsBuilder_ == null) { + securityRequirements_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000080); onChanged(); } else { - securityBuilder_.clear(); + securityRequirementsBuilder_.clear(); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public Builder removeSecurity(int index) { - if (securityBuilder_ == null) { - ensureSecurityIsMutable(); - security_.remove(index); + public Builder removeSecurityRequirements(int index) { + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.remove(index); onChanged(); } else { - securityBuilder_.remove(index); + securityRequirementsBuilder_.remove(index); } return this; } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public io.a2a.grpc.Security.Builder getSecurityBuilder( + public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder( int index) { - return internalGetSecurityFieldBuilder().getBuilder(index); + return internalGetSecurityRequirementsFieldBuilder().getBuilder(index); } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public io.a2a.grpc.SecurityOrBuilder getSecurityOrBuilder( + public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index) { - if (securityBuilder_ == null) { - return security_.get(index); } else { - return securityBuilder_.getMessageOrBuilder(index); + if (securityRequirementsBuilder_ == null) { + return securityRequirements_.get(index); } else { + return securityRequirementsBuilder_.getMessageOrBuilder(index); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public java.util.List - getSecurityOrBuilderList() { - if (securityBuilder_ != null) { - return securityBuilder_.getMessageOrBuilderList(); + public java.util.List + getSecurityRequirementsOrBuilderList() { + if (securityRequirementsBuilder_ != null) { + return securityRequirementsBuilder_.getMessageOrBuilderList(); } else { - return java.util.Collections.unmodifiableList(security_); + return java.util.Collections.unmodifiableList(securityRequirements_); } } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public io.a2a.grpc.Security.Builder addSecurityBuilder() { - return internalGetSecurityFieldBuilder().addBuilder( - io.a2a.grpc.Security.getDefaultInstance()); + public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() { + return internalGetSecurityRequirementsFieldBuilder().addBuilder( + io.a2a.grpc.SecurityRequirement.getDefaultInstance()); } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public io.a2a.grpc.Security.Builder addSecurityBuilder( + public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( int index) { - return internalGetSecurityFieldBuilder().addBuilder( - index, io.a2a.grpc.Security.getDefaultInstance()); + return internalGetSecurityRequirementsFieldBuilder().addBuilder( + index, io.a2a.grpc.SecurityRequirement.getDefaultInstance()); } /** *
    -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
          * Security schemes necessary for this skill.
          * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - public java.util.List - getSecurityBuilderList() { - return internalGetSecurityFieldBuilder().getBuilderList(); + public java.util.List + getSecurityRequirementsBuilderList() { + return internalGetSecurityRequirementsFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Security, io.a2a.grpc.Security.Builder, io.a2a.grpc.SecurityOrBuilder> - internalGetSecurityFieldBuilder() { - if (securityBuilder_ == null) { - securityBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Security, io.a2a.grpc.Security.Builder, io.a2a.grpc.SecurityOrBuilder>( - security_, + io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> + internalGetSecurityRequirementsFieldBuilder() { + if (securityRequirementsBuilder_ == null) { + securityRequirementsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder>( + securityRequirements_, ((bitField0_ & 0x00000080) != 0), getParentForChildren(), isClean()); - security_ = null; + securityRequirements_ = null; } - return securityBuilder_; + return securityRequirementsBuilder_; } // @@protoc_insertion_point(builder_scope:a2a.v1.AgentSkill) diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java index c9615febc..8cb65a6c5 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java @@ -236,50 +236,45 @@ public interface AgentSkillOrBuilder extends /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - java.util.List - getSecurityList(); + java.util.List + getSecurityRequirementsList(); /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - io.a2a.grpc.Security getSecurity(int index); + io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index); /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - int getSecurityCount(); + int getSecurityRequirementsCount(); /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - java.util.List - getSecurityOrBuilderList(); + java.util.List + getSecurityRequirementsOrBuilderList(); /** *
    -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        * Security schemes necessary for this skill.
        * 
    * - * repeated .a2a.v1.Security security = 8; + * repeated .a2a.v1.SecurityRequirement security_requirements = 8; */ - io.a2a.grpc.SecurityOrBuilder getSecurityOrBuilder( + io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java index 38b9e065c..703a6da52 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java @@ -33,8 +33,7 @@ private AuthenticationInfo(com.google.protobuf.GeneratedMessage.Builder build super(builder); } private AuthenticationInfo() { - schemes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); + scheme_ = ""; credentials_ = ""; } @@ -51,57 +50,53 @@ private AuthenticationInfo() { io.a2a.grpc.AuthenticationInfo.class, io.a2a.grpc.AuthenticationInfo.Builder.class); } - public static final int SCHEMES_FIELD_NUMBER = 1; + public static final int SCHEME_FIELD_NUMBER = 1; @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList schemes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); + private volatile java.lang.Object scheme_ = ""; /** *
    -   * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +   * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the schemes. + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The scheme. */ - public com.google.protobuf.ProtocolStringList - getSchemesList() { - return schemes_; - } - /** - *
    -   * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    -   * 
    - * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of schemes. - */ - public int getSchemesCount() { - return schemes_.size(); - } - /** - *
    -   * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    -   * 
    - * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The schemes at the given index. - */ - public java.lang.String getSchemes(int index) { - return schemes_.get(index); + @java.lang.Override + public java.lang.String getScheme() { + java.lang.Object ref = scheme_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + scheme_ = s; + return s; + } } /** *
    -   * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +   * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the schemes at the given index. + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for scheme. */ + @java.lang.Override public com.google.protobuf.ByteString - getSchemesBytes(int index) { - return schemes_.getByteString(index); + getSchemeBytes() { + java.lang.Object ref = scheme_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + scheme_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } } public static final int CREDENTIALS_FIELD_NUMBER = 2; @@ -109,7 +104,7 @@ public java.lang.String getSchemes(int index) { private volatile java.lang.Object credentials_ = ""; /** *
    -   * Optional credentials
    +   * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
        * 
    * * string credentials = 2; @@ -130,7 +125,7 @@ public java.lang.String getCredentials() { } /** *
    -   * Optional credentials
    +   * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
        * 
    * * string credentials = 2; @@ -165,8 +160,8 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - for (int i = 0; i < schemes_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, schemes_.getRaw(i)); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(scheme_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, scheme_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(credentials_)) { com.google.protobuf.GeneratedMessage.writeString(output, 2, credentials_); @@ -180,13 +175,8 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - { - int dataSize = 0; - for (int i = 0; i < schemes_.size(); i++) { - dataSize += computeStringSizeNoTag(schemes_.getRaw(i)); - } - size += dataSize; - size += 1 * getSchemesList().size(); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(scheme_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, scheme_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(credentials_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(2, credentials_); @@ -206,8 +196,8 @@ public boolean equals(final java.lang.Object obj) { } io.a2a.grpc.AuthenticationInfo other = (io.a2a.grpc.AuthenticationInfo) obj; - if (!getSchemesList() - .equals(other.getSchemesList())) return false; + if (!getScheme() + .equals(other.getScheme())) return false; if (!getCredentials() .equals(other.getCredentials())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; @@ -221,10 +211,8 @@ public int hashCode() { } int hash = 41; hash = (19 * hash) + getDescriptor().hashCode(); - if (getSchemesCount() > 0) { - hash = (37 * hash) + SCHEMES_FIELD_NUMBER; - hash = (53 * hash) + getSchemesList().hashCode(); - } + hash = (37 * hash) + SCHEME_FIELD_NUMBER; + hash = (53 * hash) + getScheme().hashCode(); hash = (37 * hash) + CREDENTIALS_FIELD_NUMBER; hash = (53 * hash) + getCredentials().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); @@ -363,8 +351,7 @@ private Builder( public Builder clear() { super.clear(); bitField0_ = 0; - schemes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); + scheme_ = ""; credentials_ = ""; return this; } @@ -400,8 +387,7 @@ public io.a2a.grpc.AuthenticationInfo buildPartial() { private void buildPartial0(io.a2a.grpc.AuthenticationInfo result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { - schemes_.makeImmutable(); - result.schemes_ = schemes_; + result.scheme_ = scheme_; } if (((from_bitField0_ & 0x00000002) != 0)) { result.credentials_ = credentials_; @@ -420,14 +406,9 @@ public Builder mergeFrom(com.google.protobuf.Message other) { public Builder mergeFrom(io.a2a.grpc.AuthenticationInfo other) { if (other == io.a2a.grpc.AuthenticationInfo.getDefaultInstance()) return this; - if (!other.schemes_.isEmpty()) { - if (schemes_.isEmpty()) { - schemes_ = other.schemes_; - bitField0_ |= 0x00000001; - } else { - ensureSchemesIsMutable(); - schemes_.addAll(other.schemes_); - } + if (!other.getScheme().isEmpty()) { + scheme_ = other.scheme_; + bitField0_ |= 0x00000001; onChanged(); } if (!other.getCredentials().isEmpty()) { @@ -462,9 +443,8 @@ public Builder mergeFrom( done = true; break; case 10: { - java.lang.String s = input.readStringRequireUtf8(); - ensureSchemesIsMutable(); - schemes_.add(s); + scheme_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; break; } // case 10 case 18: { @@ -489,148 +469,98 @@ public Builder mergeFrom( } private int bitField0_; - private com.google.protobuf.LazyStringArrayList schemes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureSchemesIsMutable() { - if (!schemes_.isModifiable()) { - schemes_ = new com.google.protobuf.LazyStringArrayList(schemes_); - } - bitField0_ |= 0x00000001; - } - /** - *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    -     * 
    - * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the schemes. - */ - public com.google.protobuf.ProtocolStringList - getSchemesList() { - schemes_.makeImmutable(); - return schemes_; - } - /** - *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    -     * 
    - * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of schemes. - */ - public int getSchemesCount() { - return schemes_.size(); - } + private java.lang.Object scheme_ = ""; /** *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
          * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The schemes at the given index. + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The scheme. */ - public java.lang.String getSchemes(int index) { - return schemes_.get(index); + public java.lang.String getScheme() { + java.lang.Object ref = scheme_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + scheme_ = s; + return s; + } else { + return (java.lang.String) ref; + } } /** *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
          * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the schemes at the given index. + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for scheme. */ public com.google.protobuf.ByteString - getSchemesBytes(int index) { - return schemes_.getByteString(index); - } - /** - *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    -     * 
    - * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index to set the value at. - * @param value The schemes to set. - * @return This builder for chaining. - */ - public Builder setSchemes( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureSchemesIsMutable(); - schemes_.set(index, value); - bitField0_ |= 0x00000001; - onChanged(); - return this; + getSchemeBytes() { + java.lang.Object ref = scheme_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + scheme_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } } /** *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
          * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The schemes to add. + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The scheme to set. * @return This builder for chaining. */ - public Builder addSchemes( + public Builder setScheme( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - ensureSchemesIsMutable(); - schemes_.add(value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    -     * 
    - * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param values The schemes to add. - * @return This builder for chaining. - */ - public Builder addAllSchemes( - java.lang.Iterable values) { - ensureSchemesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, schemes_); + scheme_ = value; bitField0_ |= 0x00000001; onChanged(); return this; } /** *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
          * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearSchemes() { - schemes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001);; + public Builder clearScheme() { + scheme_ = getDefaultInstance().getScheme(); + bitField0_ = (bitField0_ & ~0x00000001); onChanged(); return this; } /** *
    -     * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
          * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes of the schemes to add. + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for scheme to set. * @return This builder for chaining. */ - public Builder addSchemesBytes( + public Builder setSchemeBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - ensureSchemesIsMutable(); - schemes_.add(value); + scheme_ = value; bitField0_ |= 0x00000001; onChanged(); return this; @@ -639,7 +569,7 @@ public Builder addSchemesBytes( private java.lang.Object credentials_ = ""; /** *
    -     * Optional credentials
    +     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
          * 
    * * string credentials = 2; @@ -659,7 +589,7 @@ public java.lang.String getCredentials() { } /** *
    -     * Optional credentials
    +     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
          * 
    * * string credentials = 2; @@ -680,7 +610,7 @@ public java.lang.String getCredentials() { } /** *
    -     * Optional credentials
    +     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
          * 
    * * string credentials = 2; @@ -697,7 +627,7 @@ public Builder setCredentials( } /** *
    -     * Optional credentials
    +     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
          * 
    * * string credentials = 2; @@ -711,7 +641,7 @@ public Builder clearCredentials() { } /** *
    -     * Optional credentials
    +     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
          * 
    * * string credentials = 2; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java index 37c96ed29..b142c3670 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java @@ -12,48 +12,29 @@ public interface AuthenticationInfoOrBuilder extends /** *
    -   * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +   * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the schemes. + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The scheme. */ - java.util.List - getSchemesList(); + java.lang.String getScheme(); /** *
    -   * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    +   * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
    +   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        * 
    * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of schemes. - */ - int getSchemesCount(); - /** - *
    -   * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    -   * 
    - * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The schemes at the given index. - */ - java.lang.String getSchemes(int index); - /** - *
    -   * A list of supported authentication schemes (e.g., 'Basic', 'Bearer').
    -   * 
    - * - * repeated string schemes = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the schemes at the given index. + * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for scheme. */ com.google.protobuf.ByteString - getSchemesBytes(int index); + getSchemeBytes(); /** *
    -   * Optional credentials
    +   * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
        * 
    * * string credentials = 2; @@ -62,7 +43,7 @@ public interface AuthenticationInfoOrBuilder extends java.lang.String getCredentials(); /** *
    -   * Optional credentials
    +   * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
        * 
    * * string credentials = 2; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java index cb1e12880..3aa57435f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java @@ -34,7 +34,7 @@ private CancelTaskRequest(com.google.protobuf.GeneratedMessage.Builder builde } private CancelTaskRequest() { tenant_ = ""; - name_ = ""; + id_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -97,49 +97,47 @@ public java.lang.String getTenant() { } } - public static final int NAME_FIELD_NUMBER = 1; + public static final int ID_FIELD_NUMBER = 1; @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; + private volatile java.lang.Object id_ = ""; /** *
    -   * The resource name of the task to cancel.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task to cancel.
        * 
    * - * string name = 1; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getId() { + java.lang.Object ref = id_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + id_ = s; return s; } } /** *
    -   * The resource name of the task to cancel.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task to cancel.
        * 
    * - * string name = 1; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ @java.lang.Override public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getIdBytes() { + java.lang.Object ref = id_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + id_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -160,8 +158,8 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); @@ -175,8 +173,8 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); @@ -198,8 +196,8 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (!getName() - .equals(other.getName())) return false; + if (!getId() + .equals(other.getId())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -213,8 +211,8 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -352,7 +350,7 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - name_ = ""; + id_ = ""; return this; } @@ -390,7 +388,7 @@ private void buildPartial0(io.a2a.grpc.CancelTaskRequest result) { result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.name_ = name_; + result.id_ = id_; } } @@ -411,8 +409,8 @@ public Builder mergeFrom(io.a2a.grpc.CancelTaskRequest other) { bitField0_ |= 0x00000001; onChanged(); } - if (!other.getName().isEmpty()) { - name_ = other.name_; + if (!other.getId().isEmpty()) { + id_ = other.id_; bitField0_ |= 0x00000002; onChanged(); } @@ -443,7 +441,7 @@ public Builder mergeFrom( done = true; break; case 10: { - name_ = input.readStringRequireUtf8(); + id_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; } // case 10 @@ -561,23 +559,22 @@ public Builder setTenantBytes( return this; } - private java.lang.Object name_ = ""; + private java.lang.Object id_ = ""; /** *
    -     * The resource name of the task to cancel.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to cancel.
          * 
    * - * string name = 1; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getId() { + java.lang.Object ref = id_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + id_ = s; return s; } else { return (java.lang.String) ref; @@ -585,21 +582,20 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the task to cancel.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to cancel.
          * 
    * - * string name = 1; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getIdBytes() { + java.lang.Object ref = id_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + id_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -607,52 +603,49 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the task to cancel.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to cancel.
          * 
    * - * string name = 1; - * @param value The name to set. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The id to set. * @return This builder for chaining. */ - public Builder setName( + public Builder setId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - name_ = value; + id_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } /** *
    -     * The resource name of the task to cancel.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to cancel.
          * 
    * - * string name = 1; + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); + public Builder clearId() { + id_ = getDefaultInstance().getId(); bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } /** *
    -     * The resource name of the task to cancel.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to cancel.
          * 
    * - * string name = 1; - * @param value The bytes for name to set. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for id to set. * @return This builder for chaining. */ - public Builder setNameBytes( + public Builder setIdBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - name_ = value; + id_ = value; bitField0_ |= 0x00000002; onChanged(); return this; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java index b8a5e4f11..1e3251328 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java @@ -32,23 +32,21 @@ public interface CancelTaskRequestOrBuilder extends /** *
    -   * The resource name of the task to cancel.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task to cancel.
        * 
    * - * string name = 1; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ - java.lang.String getName(); + java.lang.String getId(); /** *
    -   * The resource name of the task to cancel.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task to cancel.
        * 
    * - * string name = 1; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ com.google.protobuf.ByteString - getNameBytes(); + getIdBytes(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java index 5f8143cb3..f445a86d2 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java @@ -34,7 +34,7 @@ private CreateTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMes } private CreateTaskPushNotificationConfigRequest() { tenant_ = ""; - parent_ = ""; + taskId_ = ""; configId_ = ""; } @@ -99,49 +99,47 @@ public java.lang.String getTenant() { } } - public static final int PARENT_FIELD_NUMBER = 1; + public static final int TASK_ID_FIELD_NUMBER = 1; @SuppressWarnings("serial") - private volatile java.lang.Object parent_ = ""; + private volatile java.lang.Object taskId_ = ""; /** *
    -   * The parent task resource for this config.
    -   * Format: tasks/{task_id}
    +   * The parent task resource id.
        * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ @java.lang.Override - public java.lang.String getParent() { - java.lang.Object ref = parent_; + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - parent_ = s; + taskId_ = s; return s; } } /** *
    -   * The parent task resource for this config.
    -   * Format: tasks/{task_id}
    +   * The parent task resource id.
        * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ @java.lang.Override public com.google.protobuf.ByteString - getParentBytes() { - java.lang.Object ref = parent_; + getTaskIdBytes() { + java.lang.Object ref = taskId_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - parent_ = b; + taskId_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -195,14 +193,14 @@ public java.lang.String getConfigId() { } } - public static final int CONFIG_FIELD_NUMBER = 3; - private io.a2a.grpc.TaskPushNotificationConfig config_; + public static final int CONFIG_FIELD_NUMBER = 5; + private io.a2a.grpc.PushNotificationConfig config_; /** *
        * The configuration to create.
        * 
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the config field is set. */ @java.lang.Override @@ -214,23 +212,23 @@ public boolean hasConfig() { * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; * @return The config. */ @java.lang.Override - public io.a2a.grpc.TaskPushNotificationConfig getConfig() { - return config_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : config_; + public io.a2a.grpc.PushNotificationConfig getConfig() { + return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; } /** *
        * The configuration to create.
        * 
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override - public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigOrBuilder() { - return config_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : config_; + public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { + return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; } private byte memoizedIsInitialized = -1; @@ -247,18 +245,18 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(parent_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, parent_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(configId_)) { com.google.protobuf.GeneratedMessage.writeString(output, 2, configId_); } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(3, getConfig()); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(5, getConfig()); + } getUnknownFields().writeTo(output); } @@ -268,19 +266,19 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(parent_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, parent_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(configId_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(2, configId_); } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getConfig()); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, getConfig()); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -298,8 +296,8 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (!getParent() - .equals(other.getParent())) return false; + if (!getTaskId() + .equals(other.getTaskId())) return false; if (!getConfigId() .equals(other.getConfigId())) return false; if (hasConfig() != other.hasConfig()) return false; @@ -320,8 +318,8 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + PARENT_FIELD_NUMBER; - hash = (53 * hash) + getParent().hashCode(); + hash = (37 * hash) + TASK_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskId().hashCode(); hash = (37 * hash) + CONFIG_ID_FIELD_NUMBER; hash = (53 * hash) + getConfigId().hashCode(); if (hasConfig()) { @@ -471,7 +469,7 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - parent_ = ""; + taskId_ = ""; configId_ = ""; config_ = null; if (configBuilder_ != null) { @@ -515,7 +513,7 @@ private void buildPartial0(io.a2a.grpc.CreateTaskPushNotificationConfigRequest r result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.parent_ = parent_; + result.taskId_ = taskId_; } if (((from_bitField0_ & 0x00000004) != 0)) { result.configId_ = configId_; @@ -547,8 +545,8 @@ public Builder mergeFrom(io.a2a.grpc.CreateTaskPushNotificationConfigRequest oth bitField0_ |= 0x00000001; onChanged(); } - if (!other.getParent().isEmpty()) { - parent_ = other.parent_; + if (!other.getTaskId().isEmpty()) { + taskId_ = other.taskId_; bitField0_ |= 0x00000002; onChanged(); } @@ -587,7 +585,7 @@ public Builder mergeFrom( done = true; break; case 10: { - parent_ = input.readStringRequireUtf8(); + taskId_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; } // case 10 @@ -596,18 +594,18 @@ public Builder mergeFrom( bitField0_ |= 0x00000004; break; } // case 18 - case 26: { - input.readMessage( - internalGetConfigFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 26 case 34: { tenant_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000001; break; } // case 34 + case 42: { + input.readMessage( + internalGetConfigFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000008; + break; + } // case 42 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -717,23 +715,22 @@ public Builder setTenantBytes( return this; } - private java.lang.Object parent_ = ""; + private java.lang.Object taskId_ = ""; /** *
    -     * The parent task resource for this config.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ - public java.lang.String getParent() { - java.lang.Object ref = parent_; + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - parent_ = s; + taskId_ = s; return s; } else { return (java.lang.String) ref; @@ -741,21 +738,20 @@ public java.lang.String getParent() { } /** *
    -     * The parent task resource for this config.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ public com.google.protobuf.ByteString - getParentBytes() { - java.lang.Object ref = parent_; + getTaskIdBytes() { + java.lang.Object ref = taskId_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - parent_ = b; + taskId_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -763,52 +759,49 @@ public java.lang.String getParent() { } /** *
    -     * The parent task resource for this config.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The parent to set. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The taskId to set. * @return This builder for chaining. */ - public Builder setParent( + public Builder setTaskId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - parent_ = value; + taskId_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } /** *
    -     * The parent task resource for this config.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearParent() { - parent_ = getDefaultInstance().getParent(); + public Builder clearTaskId() { + taskId_ = getDefaultInstance().getTaskId(); bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } /** *
    -     * The parent task resource for this config.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for parent to set. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for taskId to set. * @return This builder for chaining. */ - public Builder setParentBytes( + public Builder setTaskIdBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - parent_ = value; + taskId_ = value; bitField0_ |= 0x00000002; onChanged(); return this; @@ -906,15 +899,15 @@ public Builder setConfigIdBytes( return this; } - private io.a2a.grpc.TaskPushNotificationConfig config_; + private io.a2a.grpc.PushNotificationConfig config_; private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> configBuilder_; + io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> configBuilder_; /** *
          * The configuration to create.
          * 
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the config field is set. */ public boolean hasConfig() { @@ -925,12 +918,12 @@ public boolean hasConfig() { * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; * @return The config. */ - public io.a2a.grpc.TaskPushNotificationConfig getConfig() { + public io.a2a.grpc.PushNotificationConfig getConfig() { if (configBuilder_ == null) { - return config_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : config_; + return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; } else { return configBuilder_.getMessage(); } @@ -940,9 +933,9 @@ public io.a2a.grpc.TaskPushNotificationConfig getConfig() { * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ - public Builder setConfig(io.a2a.grpc.TaskPushNotificationConfig value) { + public Builder setConfig(io.a2a.grpc.PushNotificationConfig value) { if (configBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -960,10 +953,10 @@ public Builder setConfig(io.a2a.grpc.TaskPushNotificationConfig value) { * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setConfig( - io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) { + io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { if (configBuilder_ == null) { config_ = builderForValue.build(); } else { @@ -978,13 +971,13 @@ public Builder setConfig( * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ - public Builder mergeConfig(io.a2a.grpc.TaskPushNotificationConfig value) { + public Builder mergeConfig(io.a2a.grpc.PushNotificationConfig value) { if (configBuilder_ == null) { if (((bitField0_ & 0x00000008) != 0) && config_ != null && - config_ != io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance()) { + config_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { getConfigBuilder().mergeFrom(value); } else { config_ = value; @@ -1003,7 +996,7 @@ public Builder mergeConfig(io.a2a.grpc.TaskPushNotificationConfig value) { * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearConfig() { bitField0_ = (bitField0_ & ~0x00000008); @@ -1020,9 +1013,9 @@ public Builder clearConfig() { * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ - public io.a2a.grpc.TaskPushNotificationConfig.Builder getConfigBuilder() { + public io.a2a.grpc.PushNotificationConfig.Builder getConfigBuilder() { bitField0_ |= 0x00000008; onChanged(); return internalGetConfigFieldBuilder().getBuilder(); @@ -1032,14 +1025,14 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder getConfigBuilder() { * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ - public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigOrBuilder() { + public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { if (configBuilder_ != null) { return configBuilder_.getMessageOrBuilder(); } else { return config_ == null ? - io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : config_; + io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; } } /** @@ -1047,14 +1040,14 @@ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigOrBuilder() { * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> + io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> internalGetConfigFieldBuilder() { if (configBuilder_ == null) { configBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder>( + io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder>( getConfig(), getParentForChildren(), isClean()); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java index 536c31416..77a661f26 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java @@ -32,25 +32,23 @@ public interface CreateTaskPushNotificationConfigRequestOrBuilder extends /** *
    -   * The parent task resource for this config.
    -   * Format: tasks/{task_id}
    +   * The parent task resource id.
        * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ - java.lang.String getParent(); + java.lang.String getTaskId(); /** *
    -   * The parent task resource for this config.
    -   * Format: tasks/{task_id}
    +   * The parent task resource id.
        * 
    * - * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ com.google.protobuf.ByteString - getParentBytes(); + getTaskIdBytes(); /** *
    @@ -77,7 +75,7 @@ public interface CreateTaskPushNotificationConfigRequestOrBuilder extends
        * The configuration to create.
        * 
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the config field is set. */ boolean hasConfig(); @@ -86,16 +84,16 @@ public interface CreateTaskPushNotificationConfigRequestOrBuilder extends * The configuration to create. *
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; * @return The config. */ - io.a2a.grpc.TaskPushNotificationConfig getConfig(); + io.a2a.grpc.PushNotificationConfig getConfig(); /** *
        * The configuration to create.
        * 
    * - * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; */ - io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigOrBuilder(); + io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DataPart.java b/spec-grpc/src/main/java/io/a2a/grpc/DataPart.java deleted file mode 100644 index 92d0a6e6e..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/DataPart.java +++ /dev/null @@ -1,617 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
    - * --8<-- [start:DataPart]
    - * DataPart represents a structured blob.
    - * 
    - * - * Protobuf type {@code a2a.v1.DataPart} - */ -@com.google.protobuf.Generated -public final class DataPart extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.DataPart) - DataPartOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "DataPart"); - } - // Use DataPart.newBuilder() to construct. - private DataPart(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private DataPart() { - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DataPart_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DataPart_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.DataPart.class, io.a2a.grpc.DataPart.Builder.class); - } - - private int bitField0_; - public static final int DATA_FIELD_NUMBER = 1; - private com.google.protobuf.Struct data_; - /** - *
    -   * A JSON object containing arbitrary data.
    -   * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the data field is set. - */ - @java.lang.Override - public boolean hasData() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
    -   * A JSON object containing arbitrary data.
    -   * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The data. - */ - @java.lang.Override - public com.google.protobuf.Struct getData() { - return data_ == null ? com.google.protobuf.Struct.getDefaultInstance() : data_; - } - /** - *
    -   * A JSON object containing arbitrary data.
    -   * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getDataOrBuilder() { - return data_ == null ? com.google.protobuf.Struct.getDefaultInstance() : data_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(1, getData()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, getData()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.DataPart)) { - return super.equals(obj); - } - io.a2a.grpc.DataPart other = (io.a2a.grpc.DataPart) obj; - - if (hasData() != other.hasData()) return false; - if (hasData()) { - if (!getData() - .equals(other.getData())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (hasData()) { - hash = (37 * hash) + DATA_FIELD_NUMBER; - hash = (53 * hash) + getData().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.DataPart parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DataPart parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DataPart parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DataPart parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DataPart parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DataPart parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DataPart parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.DataPart parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.DataPart parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.DataPart parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.DataPart parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.DataPart parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.DataPart prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
    -   * --8<-- [start:DataPart]
    -   * DataPart represents a structured blob.
    -   * 
    - * - * Protobuf type {@code a2a.v1.DataPart} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.DataPart) - io.a2a.grpc.DataPartOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DataPart_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DataPart_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.DataPart.class, io.a2a.grpc.DataPart.Builder.class); - } - - // Construct using io.a2a.grpc.DataPart.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetDataFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - data_ = null; - if (dataBuilder_ != null) { - dataBuilder_.dispose(); - dataBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DataPart_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.DataPart getDefaultInstanceForType() { - return io.a2a.grpc.DataPart.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.DataPart build() { - io.a2a.grpc.DataPart result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.DataPart buildPartial() { - io.a2a.grpc.DataPart result = new io.a2a.grpc.DataPart(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.DataPart result) { - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.data_ = dataBuilder_ == null - ? data_ - : dataBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.DataPart) { - return mergeFrom((io.a2a.grpc.DataPart)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.DataPart other) { - if (other == io.a2a.grpc.DataPart.getDefaultInstance()) return this; - if (other.hasData()) { - mergeData(other.getData()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - input.readMessage( - internalGetDataFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000001; - break; - } // case 10 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private com.google.protobuf.Struct data_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> dataBuilder_; - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the data field is set. - */ - public boolean hasData() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The data. - */ - public com.google.protobuf.Struct getData() { - if (dataBuilder_ == null) { - return data_ == null ? com.google.protobuf.Struct.getDefaultInstance() : data_; - } else { - return dataBuilder_.getMessage(); - } - } - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setData(com.google.protobuf.Struct value) { - if (dataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - data_ = value; - } else { - dataBuilder_.setMessage(value); - } - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setData( - com.google.protobuf.Struct.Builder builderForValue) { - if (dataBuilder_ == null) { - data_ = builderForValue.build(); - } else { - dataBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeData(com.google.protobuf.Struct value) { - if (dataBuilder_ == null) { - if (((bitField0_ & 0x00000001) != 0) && - data_ != null && - data_ != com.google.protobuf.Struct.getDefaultInstance()) { - getDataBuilder().mergeFrom(value); - } else { - data_ = value; - } - } else { - dataBuilder_.mergeFrom(value); - } - if (data_ != null) { - bitField0_ |= 0x00000001; - onChanged(); - } - return this; - } - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearData() { - bitField0_ = (bitField0_ & ~0x00000001); - data_ = null; - if (dataBuilder_ != null) { - dataBuilder_.dispose(); - dataBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public com.google.protobuf.Struct.Builder getDataBuilder() { - bitField0_ |= 0x00000001; - onChanged(); - return internalGetDataFieldBuilder().getBuilder(); - } - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public com.google.protobuf.StructOrBuilder getDataOrBuilder() { - if (dataBuilder_ != null) { - return dataBuilder_.getMessageOrBuilder(); - } else { - return data_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : data_; - } - } - /** - *
    -     * A JSON object containing arbitrary data.
    -     * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetDataFieldBuilder() { - if (dataBuilder_ == null) { - dataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getData(), - getParentForChildren(), - isClean()); - data_ = null; - } - return dataBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.DataPart) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.DataPart) - private static final io.a2a.grpc.DataPart DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.DataPart(); - } - - public static io.a2a.grpc.DataPart getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public DataPart parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.DataPart getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DataPartOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/DataPartOrBuilder.java deleted file mode 100644 index 4b61fc851..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/DataPartOrBuilder.java +++ /dev/null @@ -1,39 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface DataPartOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.DataPart) - com.google.protobuf.MessageOrBuilder { - - /** - *
    -   * A JSON object containing arbitrary data.
    -   * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the data field is set. - */ - boolean hasData(); - /** - *
    -   * A JSON object containing arbitrary data.
    -   * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The data. - */ - com.google.protobuf.Struct getData(); - /** - *
    -   * A JSON object containing arbitrary data.
    -   * 
    - * - * .google.protobuf.Struct data = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - com.google.protobuf.StructOrBuilder getDataOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java index cb6914e0b..bb1ac53b5 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java @@ -34,7 +34,8 @@ private DeleteTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMes } private DeleteTaskPushNotificationConfigRequest() { tenant_ = ""; - name_ = ""; + taskId_ = ""; + id_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -97,49 +98,94 @@ public java.lang.String getTenant() { } } - public static final int NAME_FIELD_NUMBER = 1; + public static final int TASK_ID_FIELD_NUMBER = 3; @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; + private volatile java.lang.Object taskId_ = ""; /** *
    -   * The resource name of the config to delete.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * The parent task resource id.
        * 
    * - * string name = 1; - * @return The name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + taskId_ = s; return s; } } /** *
    -   * The resource name of the config to delete.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * The parent task resource id.
        * 
    * - * string name = 1; - * @return The bytes for name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ @java.lang.Override public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getTaskIdBytes() { + java.lang.Object ref = taskId_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object id_ = ""; + /** + *
    +   * The resource id of the config to delete.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + @java.lang.Override + public java.lang.String getId() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + *
    +   * The resource id of the config to delete.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -160,12 +206,15 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); + } getUnknownFields().writeTo(output); } @@ -175,12 +224,15 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -198,8 +250,10 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (!getName() - .equals(other.getName())) return false; + if (!getTaskId() + .equals(other.getTaskId())) return false; + if (!getId() + .equals(other.getId())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -213,8 +267,10 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + TASK_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskId().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -352,7 +408,8 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - name_ = ""; + taskId_ = ""; + id_ = ""; return this; } @@ -390,7 +447,10 @@ private void buildPartial0(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest r result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.name_ = name_; + result.taskId_ = taskId_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.id_ = id_; } } @@ -411,11 +471,16 @@ public Builder mergeFrom(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest oth bitField0_ |= 0x00000001; onChanged(); } - if (!other.getName().isEmpty()) { - name_ = other.name_; + if (!other.getTaskId().isEmpty()) { + taskId_ = other.taskId_; bitField0_ |= 0x00000002; onChanged(); } + if (!other.getId().isEmpty()) { + id_ = other.id_; + bitField0_ |= 0x00000004; + onChanged(); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -443,8 +508,8 @@ public Builder mergeFrom( done = true; break; case 10: { - name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; break; } // case 10 case 18: { @@ -452,6 +517,11 @@ public Builder mergeFrom( bitField0_ |= 0x00000001; break; } // case 18 + case 26: { + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 26 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -561,23 +631,22 @@ public Builder setTenantBytes( return this; } - private java.lang.Object name_ = ""; + private java.lang.Object taskId_ = ""; /** *
    -     * The resource name of the config to delete.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; - * @return The name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + taskId_ = s; return s; } else { return (java.lang.String) ref; @@ -585,21 +654,20 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the config to delete.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; - * @return The bytes for name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getTaskIdBytes() { + java.lang.Object ref = taskId_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + taskId_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -607,57 +675,146 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the config to delete.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; - * @param value The name to set. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @param value The taskId to set. * @return This builder for chaining. */ - public Builder setName( + public Builder setTaskId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - name_ = value; + taskId_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } /** *
    -     * The resource name of the config to delete.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); + public Builder clearTaskId() { + taskId_ = getDefaultInstance().getTaskId(); bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } /** *
    -     * The resource name of the config to delete.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; - * @param value The bytes for name to set. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for taskId to set. * @return This builder for chaining. */ - public Builder setNameBytes( + public Builder setTaskIdBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - name_ = value; + taskId_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } + private java.lang.Object id_ = ""; + /** + *
    +     * The resource id of the config to delete.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + public java.lang.String getId() { + java.lang.Object ref = id_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The resource id of the config to delete.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The resource id of the config to delete.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + id_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
    +     * The resource id of the config to delete.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearId() { + id_ = getDefaultInstance().getId(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
    +     * The resource id of the config to delete.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + id_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:a2a.v1.DeleteTaskPushNotificationConfigRequest) } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java index 336d7eba7..4219aea04 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java @@ -32,23 +32,41 @@ public interface DeleteTaskPushNotificationConfigRequestOrBuilder extends /** *
    -   * The resource name of the config to delete.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * The parent task resource id.
        * 
    * - * string name = 1; - * @return The name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ - java.lang.String getName(); + java.lang.String getTaskId(); /** *
    -   * The resource name of the config to delete.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * The parent task resource id.
        * 
    * - * string name = 1; - * @return The bytes for name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ com.google.protobuf.ByteString - getNameBytes(); + getTaskIdBytes(); + + /** + *
    +   * The resource id of the config to delete.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + java.lang.String getId(); + /** + *
    +   * The resource id of the config to delete.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/FilePart.java b/spec-grpc/src/main/java/io/a2a/grpc/FilePart.java deleted file mode 100644 index 8d2526d62..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/FilePart.java +++ /dev/null @@ -1,1109 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
    - * --8<-- [start:FilePart]
    - * FilePart represents the different ways files can be provided. If files are
    - * small, directly feeding the bytes is supported via file_with_bytes. If the
    - * file is large, the agent should read the content as appropriate directly
    - * from the file_with_uri source.
    - * 
    - * - * Protobuf type {@code a2a.v1.FilePart} - */ -@com.google.protobuf.Generated -public final class FilePart extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.FilePart) - FilePartOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "FilePart"); - } - // Use FilePart.newBuilder() to construct. - private FilePart(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private FilePart() { - mediaType_ = ""; - name_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_FilePart_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_FilePart_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.FilePart.class, io.a2a.grpc.FilePart.Builder.class); - } - - private int fileCase_ = 0; - @SuppressWarnings("serial") - private java.lang.Object file_; - public enum FileCase - implements com.google.protobuf.Internal.EnumLite, - com.google.protobuf.AbstractMessage.InternalOneOfEnum { - FILE_WITH_URI(1), - FILE_WITH_BYTES(2), - FILE_NOT_SET(0); - private final int value; - private FileCase(int value) { - this.value = value; - } - /** - * @param value The number of the enum to look for. - * @return The enum associated with the given number. - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static FileCase valueOf(int value) { - return forNumber(value); - } - - public static FileCase forNumber(int value) { - switch (value) { - case 1: return FILE_WITH_URI; - case 2: return FILE_WITH_BYTES; - case 0: return FILE_NOT_SET; - default: return null; - } - } - public int getNumber() { - return this.value; - } - }; - - public FileCase - getFileCase() { - return FileCase.forNumber( - fileCase_); - } - - public static final int FILE_WITH_URI_FIELD_NUMBER = 1; - /** - *
    -   * A URL pointing to the file's content.
    -   * 
    - * - * string file_with_uri = 1; - * @return Whether the fileWithUri field is set. - */ - public boolean hasFileWithUri() { - return fileCase_ == 1; - } - /** - *
    -   * A URL pointing to the file's content.
    -   * 
    - * - * string file_with_uri = 1; - * @return The fileWithUri. - */ - public java.lang.String getFileWithUri() { - java.lang.Object ref = ""; - if (fileCase_ == 1) { - ref = file_; - } - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (fileCase_ == 1) { - file_ = s; - } - return s; - } - } - /** - *
    -   * A URL pointing to the file's content.
    -   * 
    - * - * string file_with_uri = 1; - * @return The bytes for fileWithUri. - */ - public com.google.protobuf.ByteString - getFileWithUriBytes() { - java.lang.Object ref = ""; - if (fileCase_ == 1) { - ref = file_; - } - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - if (fileCase_ == 1) { - file_ = b; - } - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int FILE_WITH_BYTES_FIELD_NUMBER = 2; - /** - *
    -   * The base64-encoded content of the file.
    -   * 
    - * - * bytes file_with_bytes = 2; - * @return Whether the fileWithBytes field is set. - */ - @java.lang.Override - public boolean hasFileWithBytes() { - return fileCase_ == 2; - } - /** - *
    -   * The base64-encoded content of the file.
    -   * 
    - * - * bytes file_with_bytes = 2; - * @return The fileWithBytes. - */ - @java.lang.Override - public com.google.protobuf.ByteString getFileWithBytes() { - if (fileCase_ == 2) { - return (com.google.protobuf.ByteString) file_; - } - return com.google.protobuf.ByteString.EMPTY; - } - - public static final int MEDIA_TYPE_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object mediaType_ = ""; - /** - *
    -   * The media type of the file (e.g., "application/pdf").
    -   * 
    - * - * string media_type = 3; - * @return The mediaType. - */ - @java.lang.Override - public java.lang.String getMediaType() { - java.lang.Object ref = mediaType_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - mediaType_ = s; - return s; - } - } - /** - *
    -   * The media type of the file (e.g., "application/pdf").
    -   * 
    - * - * string media_type = 3; - * @return The bytes for mediaType. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getMediaTypeBytes() { - java.lang.Object ref = mediaType_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - mediaType_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int NAME_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; - /** - *
    -   * An optional name for the file (e.g., "document.pdf").
    -   * 
    - * - * string name = 4; - * @return The name. - */ - @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } - } - /** - *
    -   * An optional name for the file (e.g., "document.pdf").
    -   * 
    - * - * string name = 4; - * @return The bytes for name. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (fileCase_ == 1) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, file_); - } - if (fileCase_ == 2) { - output.writeBytes( - 2, (com.google.protobuf.ByteString) file_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(mediaType_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, mediaType_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, name_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (fileCase_ == 1) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, file_); - } - if (fileCase_ == 2) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize( - 2, (com.google.protobuf.ByteString) file_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(mediaType_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, mediaType_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, name_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.FilePart)) { - return super.equals(obj); - } - io.a2a.grpc.FilePart other = (io.a2a.grpc.FilePart) obj; - - if (!getMediaType() - .equals(other.getMediaType())) return false; - if (!getName() - .equals(other.getName())) return false; - if (!getFileCase().equals(other.getFileCase())) return false; - switch (fileCase_) { - case 1: - if (!getFileWithUri() - .equals(other.getFileWithUri())) return false; - break; - case 2: - if (!getFileWithBytes() - .equals(other.getFileWithBytes())) return false; - break; - case 0: - default: - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + MEDIA_TYPE_FIELD_NUMBER; - hash = (53 * hash) + getMediaType().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); - switch (fileCase_) { - case 1: - hash = (37 * hash) + FILE_WITH_URI_FIELD_NUMBER; - hash = (53 * hash) + getFileWithUri().hashCode(); - break; - case 2: - hash = (37 * hash) + FILE_WITH_BYTES_FIELD_NUMBER; - hash = (53 * hash) + getFileWithBytes().hashCode(); - break; - case 0: - default: - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.FilePart parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.FilePart parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.FilePart parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.FilePart parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.FilePart parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.FilePart parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.FilePart parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.FilePart parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.FilePart parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.FilePart parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.FilePart parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.FilePart parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.FilePart prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
    -   * --8<-- [start:FilePart]
    -   * FilePart represents the different ways files can be provided. If files are
    -   * small, directly feeding the bytes is supported via file_with_bytes. If the
    -   * file is large, the agent should read the content as appropriate directly
    -   * from the file_with_uri source.
    -   * 
    - * - * Protobuf type {@code a2a.v1.FilePart} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.FilePart) - io.a2a.grpc.FilePartOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_FilePart_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_FilePart_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.FilePart.class, io.a2a.grpc.FilePart.Builder.class); - } - - // Construct using io.a2a.grpc.FilePart.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - mediaType_ = ""; - name_ = ""; - fileCase_ = 0; - file_ = null; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_FilePart_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.FilePart getDefaultInstanceForType() { - return io.a2a.grpc.FilePart.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.FilePart build() { - io.a2a.grpc.FilePart result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.FilePart buildPartial() { - io.a2a.grpc.FilePart result = new io.a2a.grpc.FilePart(this); - if (bitField0_ != 0) { buildPartial0(result); } - buildPartialOneofs(result); - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.FilePart result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000004) != 0)) { - result.mediaType_ = mediaType_; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.name_ = name_; - } - } - - private void buildPartialOneofs(io.a2a.grpc.FilePart result) { - result.fileCase_ = fileCase_; - result.file_ = this.file_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.FilePart) { - return mergeFrom((io.a2a.grpc.FilePart)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.FilePart other) { - if (other == io.a2a.grpc.FilePart.getDefaultInstance()) return this; - if (!other.getMediaType().isEmpty()) { - mediaType_ = other.mediaType_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (!other.getName().isEmpty()) { - name_ = other.name_; - bitField0_ |= 0x00000008; - onChanged(); - } - switch (other.getFileCase()) { - case FILE_WITH_URI: { - fileCase_ = 1; - file_ = other.file_; - onChanged(); - break; - } - case FILE_WITH_BYTES: { - setFileWithBytes(other.getFileWithBytes()); - break; - } - case FILE_NOT_SET: { - break; - } - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - java.lang.String s = input.readStringRequireUtf8(); - fileCase_ = 1; - file_ = s; - break; - } // case 10 - case 18: { - file_ = input.readBytes(); - fileCase_ = 2; - break; - } // case 18 - case 26: { - mediaType_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000008; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int fileCase_ = 0; - private java.lang.Object file_; - public FileCase - getFileCase() { - return FileCase.forNumber( - fileCase_); - } - - public Builder clearFile() { - fileCase_ = 0; - file_ = null; - onChanged(); - return this; - } - - private int bitField0_; - - /** - *
    -     * A URL pointing to the file's content.
    -     * 
    - * - * string file_with_uri = 1; - * @return Whether the fileWithUri field is set. - */ - @java.lang.Override - public boolean hasFileWithUri() { - return fileCase_ == 1; - } - /** - *
    -     * A URL pointing to the file's content.
    -     * 
    - * - * string file_with_uri = 1; - * @return The fileWithUri. - */ - @java.lang.Override - public java.lang.String getFileWithUri() { - java.lang.Object ref = ""; - if (fileCase_ == 1) { - ref = file_; - } - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (fileCase_ == 1) { - file_ = s; - } - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
    -     * A URL pointing to the file's content.
    -     * 
    - * - * string file_with_uri = 1; - * @return The bytes for fileWithUri. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getFileWithUriBytes() { - java.lang.Object ref = ""; - if (fileCase_ == 1) { - ref = file_; - } - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - if (fileCase_ == 1) { - file_ = b; - } - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
    -     * A URL pointing to the file's content.
    -     * 
    - * - * string file_with_uri = 1; - * @param value The fileWithUri to set. - * @return This builder for chaining. - */ - public Builder setFileWithUri( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - fileCase_ = 1; - file_ = value; - onChanged(); - return this; - } - /** - *
    -     * A URL pointing to the file's content.
    -     * 
    - * - * string file_with_uri = 1; - * @return This builder for chaining. - */ - public Builder clearFileWithUri() { - if (fileCase_ == 1) { - fileCase_ = 0; - file_ = null; - onChanged(); - } - return this; - } - /** - *
    -     * A URL pointing to the file's content.
    -     * 
    - * - * string file_with_uri = 1; - * @param value The bytes for fileWithUri to set. - * @return This builder for chaining. - */ - public Builder setFileWithUriBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - fileCase_ = 1; - file_ = value; - onChanged(); - return this; - } - - /** - *
    -     * The base64-encoded content of the file.
    -     * 
    - * - * bytes file_with_bytes = 2; - * @return Whether the fileWithBytes field is set. - */ - public boolean hasFileWithBytes() { - return fileCase_ == 2; - } - /** - *
    -     * The base64-encoded content of the file.
    -     * 
    - * - * bytes file_with_bytes = 2; - * @return The fileWithBytes. - */ - public com.google.protobuf.ByteString getFileWithBytes() { - if (fileCase_ == 2) { - return (com.google.protobuf.ByteString) file_; - } - return com.google.protobuf.ByteString.EMPTY; - } - /** - *
    -     * The base64-encoded content of the file.
    -     * 
    - * - * bytes file_with_bytes = 2; - * @param value The fileWithBytes to set. - * @return This builder for chaining. - */ - public Builder setFileWithBytes(com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - fileCase_ = 2; - file_ = value; - onChanged(); - return this; - } - /** - *
    -     * The base64-encoded content of the file.
    -     * 
    - * - * bytes file_with_bytes = 2; - * @return This builder for chaining. - */ - public Builder clearFileWithBytes() { - if (fileCase_ == 2) { - fileCase_ = 0; - file_ = null; - onChanged(); - } - return this; - } - - private java.lang.Object mediaType_ = ""; - /** - *
    -     * The media type of the file (e.g., "application/pdf").
    -     * 
    - * - * string media_type = 3; - * @return The mediaType. - */ - public java.lang.String getMediaType() { - java.lang.Object ref = mediaType_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - mediaType_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
    -     * The media type of the file (e.g., "application/pdf").
    -     * 
    - * - * string media_type = 3; - * @return The bytes for mediaType. - */ - public com.google.protobuf.ByteString - getMediaTypeBytes() { - java.lang.Object ref = mediaType_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - mediaType_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
    -     * The media type of the file (e.g., "application/pdf").
    -     * 
    - * - * string media_type = 3; - * @param value The mediaType to set. - * @return This builder for chaining. - */ - public Builder setMediaType( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - mediaType_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
    -     * The media type of the file (e.g., "application/pdf").
    -     * 
    - * - * string media_type = 3; - * @return This builder for chaining. - */ - public Builder clearMediaType() { - mediaType_ = getDefaultInstance().getMediaType(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
    -     * The media type of the file (e.g., "application/pdf").
    -     * 
    - * - * string media_type = 3; - * @param value The bytes for mediaType to set. - * @return This builder for chaining. - */ - public Builder setMediaTypeBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - mediaType_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private java.lang.Object name_ = ""; - /** - *
    -     * An optional name for the file (e.g., "document.pdf").
    -     * 
    - * - * string name = 4; - * @return The name. - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
    -     * An optional name for the file (e.g., "document.pdf").
    -     * 
    - * - * string name = 4; - * @return The bytes for name. - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
    -     * An optional name for the file (e.g., "document.pdf").
    -     * 
    - * - * string name = 4; - * @param value The name to set. - * @return This builder for chaining. - */ - public Builder setName( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - name_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
    -     * An optional name for the file (e.g., "document.pdf").
    -     * 
    - * - * string name = 4; - * @return This builder for chaining. - */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); - bitField0_ = (bitField0_ & ~0x00000008); - onChanged(); - return this; - } - /** - *
    -     * An optional name for the file (e.g., "document.pdf").
    -     * 
    - * - * string name = 4; - * @param value The bytes for name to set. - * @return This builder for chaining. - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - name_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.FilePart) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.FilePart) - private static final io.a2a.grpc.FilePart DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.FilePart(); - } - - public static io.a2a.grpc.FilePart getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public FilePart parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.FilePart getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/FilePartOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/FilePartOrBuilder.java deleted file mode 100644 index 2fbad2bf2..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/FilePartOrBuilder.java +++ /dev/null @@ -1,102 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface FilePartOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.FilePart) - com.google.protobuf.MessageOrBuilder { - - /** - *
    -   * A URL pointing to the file's content.
    -   * 
    - * - * string file_with_uri = 1; - * @return Whether the fileWithUri field is set. - */ - boolean hasFileWithUri(); - /** - *
    -   * A URL pointing to the file's content.
    -   * 
    - * - * string file_with_uri = 1; - * @return The fileWithUri. - */ - java.lang.String getFileWithUri(); - /** - *
    -   * A URL pointing to the file's content.
    -   * 
    - * - * string file_with_uri = 1; - * @return The bytes for fileWithUri. - */ - com.google.protobuf.ByteString - getFileWithUriBytes(); - - /** - *
    -   * The base64-encoded content of the file.
    -   * 
    - * - * bytes file_with_bytes = 2; - * @return Whether the fileWithBytes field is set. - */ - boolean hasFileWithBytes(); - /** - *
    -   * The base64-encoded content of the file.
    -   * 
    - * - * bytes file_with_bytes = 2; - * @return The fileWithBytes. - */ - com.google.protobuf.ByteString getFileWithBytes(); - - /** - *
    -   * The media type of the file (e.g., "application/pdf").
    -   * 
    - * - * string media_type = 3; - * @return The mediaType. - */ - java.lang.String getMediaType(); - /** - *
    -   * The media type of the file (e.g., "application/pdf").
    -   * 
    - * - * string media_type = 3; - * @return The bytes for mediaType. - */ - com.google.protobuf.ByteString - getMediaTypeBytes(); - - /** - *
    -   * An optional name for the file (e.g., "document.pdf").
    -   * 
    - * - * string name = 4; - * @return The name. - */ - java.lang.String getName(); - /** - *
    -   * An optional name for the file (e.g., "document.pdf").
    -   * 
    - * - * string name = 4; - * @return The bytes for name. - */ - com.google.protobuf.ByteString - getNameBytes(); - - io.a2a.grpc.FilePart.FileCase getFileCase(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java index 5d5819669..e254a9022 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java @@ -33,7 +33,8 @@ private GetTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessag } private GetTaskPushNotificationConfigRequest() { tenant_ = ""; - name_ = ""; + taskId_ = ""; + id_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -96,49 +97,94 @@ public java.lang.String getTenant() { } } - public static final int NAME_FIELD_NUMBER = 1; + public static final int TASK_ID_FIELD_NUMBER = 3; @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; + private volatile java.lang.Object taskId_ = ""; /** *
    -   * The resource name of the config to retrieve.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * The parent task resource id.
        * 
    * - * string name = 1; - * @return The name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + taskId_ = s; return s; } } /** *
    -   * The resource name of the config to retrieve.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * The parent task resource id.
        * 
    * - * string name = 1; - * @return The bytes for name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ @java.lang.Override public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getTaskIdBytes() { + java.lang.Object ref = taskId_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object id_ = ""; + /** + *
    +   * The resource id of the config to retrieve.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + @java.lang.Override + public java.lang.String getId() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + *
    +   * The resource id of the config to retrieve.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -159,12 +205,15 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); + } getUnknownFields().writeTo(output); } @@ -174,12 +223,15 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -197,8 +249,10 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (!getName() - .equals(other.getName())) return false; + if (!getTaskId() + .equals(other.getTaskId())) return false; + if (!getId() + .equals(other.getId())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -212,8 +266,10 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + TASK_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskId().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -350,7 +406,8 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - name_ = ""; + taskId_ = ""; + id_ = ""; return this; } @@ -388,7 +445,10 @@ private void buildPartial0(io.a2a.grpc.GetTaskPushNotificationConfigRequest resu result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.name_ = name_; + result.taskId_ = taskId_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.id_ = id_; } } @@ -409,11 +469,16 @@ public Builder mergeFrom(io.a2a.grpc.GetTaskPushNotificationConfigRequest other) bitField0_ |= 0x00000001; onChanged(); } - if (!other.getName().isEmpty()) { - name_ = other.name_; + if (!other.getTaskId().isEmpty()) { + taskId_ = other.taskId_; bitField0_ |= 0x00000002; onChanged(); } + if (!other.getId().isEmpty()) { + id_ = other.id_; + bitField0_ |= 0x00000004; + onChanged(); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -441,8 +506,8 @@ public Builder mergeFrom( done = true; break; case 10: { - name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; break; } // case 10 case 18: { @@ -450,6 +515,11 @@ public Builder mergeFrom( bitField0_ |= 0x00000001; break; } // case 18 + case 26: { + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 26 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -559,23 +629,22 @@ public Builder setTenantBytes( return this; } - private java.lang.Object name_ = ""; + private java.lang.Object taskId_ = ""; /** *
    -     * The resource name of the config to retrieve.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; - * @return The name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + taskId_ = s; return s; } else { return (java.lang.String) ref; @@ -583,21 +652,20 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the config to retrieve.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; - * @return The bytes for name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getTaskIdBytes() { + java.lang.Object ref = taskId_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + taskId_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -605,57 +673,146 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the config to retrieve.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; - * @param value The name to set. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @param value The taskId to set. * @return This builder for chaining. */ - public Builder setName( + public Builder setTaskId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - name_ = value; + taskId_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } /** *
    -     * The resource name of the config to retrieve.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); + public Builder clearTaskId() { + taskId_ = getDefaultInstance().getTaskId(); bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } /** *
    -     * The resource name of the config to retrieve.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * The parent task resource id.
          * 
    * - * string name = 1; - * @param value The bytes for name to set. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for taskId to set. * @return This builder for chaining. */ - public Builder setNameBytes( + public Builder setTaskIdBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - name_ = value; + taskId_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } + private java.lang.Object id_ = ""; + /** + *
    +     * The resource id of the config to retrieve.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + public java.lang.String getId() { + java.lang.Object ref = id_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The resource id of the config to retrieve.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The resource id of the config to retrieve.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + id_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
    +     * The resource id of the config to retrieve.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearId() { + id_ = getDefaultInstance().getId(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
    +     * The resource id of the config to retrieve.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + id_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:a2a.v1.GetTaskPushNotificationConfigRequest) } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java index 8224a30a2..5e9047f46 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java @@ -32,23 +32,41 @@ public interface GetTaskPushNotificationConfigRequestOrBuilder extends /** *
    -   * The resource name of the config to retrieve.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * The parent task resource id.
        * 
    * - * string name = 1; - * @return The name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ - java.lang.String getName(); + java.lang.String getTaskId(); /** *
    -   * The resource name of the config to retrieve.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * The parent task resource id.
        * 
    * - * string name = 1; - * @return The bytes for name. + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ com.google.protobuf.ByteString - getNameBytes(); + getTaskIdBytes(); + + /** + *
    +   * The resource id of the config to retrieve.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + java.lang.String getId(); + /** + *
    +   * The resource id of the config to retrieve.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java index 76d9264a0..9fa872c52 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java @@ -34,7 +34,7 @@ private GetTaskRequest(com.google.protobuf.GeneratedMessage.Builder builder) } private GetTaskRequest() { tenant_ = ""; - name_ = ""; + id_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -98,49 +98,47 @@ public java.lang.String getTenant() { } } - public static final int NAME_FIELD_NUMBER = 1; + public static final int ID_FIELD_NUMBER = 1; @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; + private volatile java.lang.Object id_ = ""; /** *
    -   * The resource name of the task.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task.
        * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getId() { + java.lang.Object ref = id_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + id_ = s; return s; } } /** *
    -   * The resource name of the task.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task.
        * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ @java.lang.Override public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getIdBytes() { + java.lang.Object ref = id_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + id_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -194,8 +192,8 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); } if (((bitField0_ & 0x00000001) != 0)) { output.writeInt32(2, historyLength_); @@ -212,8 +210,8 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream @@ -239,8 +237,8 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (!getName() - .equals(other.getName())) return false; + if (!getId() + .equals(other.getId())) return false; if (hasHistoryLength() != other.hasHistoryLength()) return false; if (hasHistoryLength()) { if (getHistoryLength() @@ -259,8 +257,8 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); if (hasHistoryLength()) { hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER; hash = (53 * hash) + getHistoryLength(); @@ -402,7 +400,7 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - name_ = ""; + id_ = ""; historyLength_ = 0; return this; } @@ -441,7 +439,7 @@ private void buildPartial0(io.a2a.grpc.GetTaskRequest result) { result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.name_ = name_; + result.id_ = id_; } int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000004) != 0)) { @@ -468,8 +466,8 @@ public Builder mergeFrom(io.a2a.grpc.GetTaskRequest other) { bitField0_ |= 0x00000001; onChanged(); } - if (!other.getName().isEmpty()) { - name_ = other.name_; + if (!other.getId().isEmpty()) { + id_ = other.id_; bitField0_ |= 0x00000002; onChanged(); } @@ -503,7 +501,7 @@ public Builder mergeFrom( done = true; break; case 10: { - name_ = input.readStringRequireUtf8(); + id_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; } // case 10 @@ -626,23 +624,22 @@ public Builder setTenantBytes( return this; } - private java.lang.Object name_ = ""; + private java.lang.Object id_ = ""; /** *
    -     * The resource name of the task.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task.
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getId() { + java.lang.Object ref = id_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + id_ = s; return s; } else { return (java.lang.String) ref; @@ -650,21 +647,20 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the task.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task.
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getIdBytes() { + java.lang.Object ref = id_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + id_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -672,52 +668,49 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the task.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task.
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The name to set. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The id to set. * @return This builder for chaining. */ - public Builder setName( + public Builder setId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - name_ = value; + id_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } /** *
    -     * The resource name of the task.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task.
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); + public Builder clearId() { + id_ = getDefaultInstance().getId(); bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } /** *
    -     * The resource name of the task.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task.
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for name to set. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for id to set. * @return This builder for chaining. */ - public Builder setNameBytes( + public Builder setIdBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - name_ = value; + id_ = value; bitField0_ |= 0x00000002; onChanged(); return this; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java index 1ef78600d..7a86eb56c 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java @@ -32,25 +32,23 @@ public interface GetTaskRequestOrBuilder extends /** *
    -   * The resource name of the task.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task.
        * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ - java.lang.String getName(); + java.lang.String getId(); /** *
    -   * The resource name of the task.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task.
        * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ com.google.protobuf.ByteString - getNameBytes(); + getIdBytes(); /** *
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java
    new file mode 100644
    index 000000000..e1fd0601c
    --- /dev/null
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java
    @@ -0,0 +1,1050 @@
    +// Generated by the protocol buffer compiler.  DO NOT EDIT!
    +// NO CHECKED-IN PROTOBUF GENCODE
    +// source: a2a.proto
    +// Protobuf Java Version: 4.33.1
    +
    +package io.a2a.grpc;
    +
    +/**
    + * 
    + * DEPRECATED
    + * 
    + * + * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} + */ +@com.google.protobuf.Generated +public final class ImplicitOAuthFlow extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.ImplicitOAuthFlow) + ImplicitOAuthFlowOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "ImplicitOAuthFlow"); + } + // Use ImplicitOAuthFlow.newBuilder() to construct. + private ImplicitOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private ImplicitOAuthFlow() { + authorizationUrl_ = ""; + refreshUrl_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class); + } + + public static final int AUTHORIZATION_URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object authorizationUrl_ = ""; + /** + *
    +   * The authorization URL to be used for this flow. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS
    +   * 
    + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + @java.lang.Override + public java.lang.String getAuthorizationUrl() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + authorizationUrl_ = s; + return s; + } + } + /** + *
    +   * The authorization URL to be used for this flow. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS
    +   * 
    + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getAuthorizationUrlBytes() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + authorizationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REFRESH_URL_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object refreshUrl_ = ""; + /** + *
    +   * The URL to be used for obtaining refresh tokens. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + @java.lang.Override + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } + } + /** + *
    +   * The URL to be used for obtaining refresh tokens. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCOPES_FIELD_NUMBER = 3; + private static final class ScopesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, java.lang.String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, authorizationUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetScopes(), + ScopesDefaultEntryHolder.defaultEntry, + 3); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, authorizationUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); + } + for (java.util.Map.Entry entry + : internalGetScopes().getMap().entrySet()) { + com.google.protobuf.MapEntry + scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, scopes__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof io.a2a.grpc.ImplicitOAuthFlow)) { + return super.equals(obj); + } + io.a2a.grpc.ImplicitOAuthFlow other = (io.a2a.grpc.ImplicitOAuthFlow) obj; + + if (!getAuthorizationUrl() + .equals(other.getAuthorizationUrl())) return false; + if (!getRefreshUrl() + .equals(other.getRefreshUrl())) return false; + if (!internalGetScopes().equals( + other.internalGetScopes())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + AUTHORIZATION_URL_FIELD_NUMBER; + hash = (53 * hash) + getAuthorizationUrl().hashCode(); + hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; + hash = (53 * hash) + getRefreshUrl().hashCode(); + if (!internalGetScopes().getMap().isEmpty()) { + hash = (37 * hash) + SCOPES_FIELD_NUMBER; + hash = (53 * hash) + internalGetScopes().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static io.a2a.grpc.ImplicitOAuthFlow parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static io.a2a.grpc.ImplicitOAuthFlow parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(io.a2a.grpc.ImplicitOAuthFlow prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
    +   * DEPRECATED
    +   * 
    + * + * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.ImplicitOAuthFlow) + io.a2a.grpc.ImplicitOAuthFlowOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetMutableScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class); + } + + // Construct using io.a2a.grpc.ImplicitOAuthFlow.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + authorizationUrl_ = ""; + refreshUrl_ = ""; + internalGetMutableScopes().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + } + + @java.lang.Override + public io.a2a.grpc.ImplicitOAuthFlow getDefaultInstanceForType() { + return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); + } + + @java.lang.Override + public io.a2a.grpc.ImplicitOAuthFlow build() { + io.a2a.grpc.ImplicitOAuthFlow result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public io.a2a.grpc.ImplicitOAuthFlow buildPartial() { + io.a2a.grpc.ImplicitOAuthFlow result = new io.a2a.grpc.ImplicitOAuthFlow(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(io.a2a.grpc.ImplicitOAuthFlow result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.authorizationUrl_ = authorizationUrl_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.refreshUrl_ = refreshUrl_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.scopes_ = internalGetScopes(); + result.scopes_.makeImmutable(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof io.a2a.grpc.ImplicitOAuthFlow) { + return mergeFrom((io.a2a.grpc.ImplicitOAuthFlow)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(io.a2a.grpc.ImplicitOAuthFlow other) { + if (other == io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance()) return this; + if (!other.getAuthorizationUrl().isEmpty()) { + authorizationUrl_ = other.authorizationUrl_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getRefreshUrl().isEmpty()) { + refreshUrl_ = other.refreshUrl_; + bitField0_ |= 0x00000002; + onChanged(); + } + internalGetMutableScopes().mergeFrom( + other.internalGetScopes()); + bitField0_ |= 0x00000004; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + authorizationUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + refreshUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + com.google.protobuf.MapEntry + scopes__ = input.readMessage( + ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableScopes().getMutableMap().put( + scopes__.getKey(), scopes__.getValue()); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object authorizationUrl_ = ""; + /** + *
    +     * The authorization URL to be used for this flow. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS
    +     * 
    + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + public java.lang.String getAuthorizationUrl() { + java.lang.Object ref = authorizationUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + authorizationUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The authorization URL to be used for this flow. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS
    +     * 
    + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + public com.google.protobuf.ByteString + getAuthorizationUrlBytes() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + authorizationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The authorization URL to be used for this flow. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS
    +     * 
    + * + * string authorization_url = 1; + * @param value The authorizationUrl to set. + * @return This builder for chaining. + */ + public Builder setAuthorizationUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + authorizationUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
    +     * The authorization URL to be used for this flow. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS
    +     * 
    + * + * string authorization_url = 1; + * @return This builder for chaining. + */ + public Builder clearAuthorizationUrl() { + authorizationUrl_ = getDefaultInstance().getAuthorizationUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
    +     * The authorization URL to be used for this flow. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS
    +     * 
    + * + * string authorization_url = 1; + * @param value The bytes for authorizationUrl to set. + * @return This builder for chaining. + */ + public Builder setAuthorizationUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + authorizationUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object refreshUrl_ = ""; + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @param value The refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @return This builder for chaining. + */ + public Builder clearRefreshUrl() { + refreshUrl_ = getDefaultInstance().getRefreshUrl(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @param value The bytes for refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + private com.google.protobuf.MapField + internalGetMutableScopes() { + if (scopes_ == null) { + scopes_ = com.google.protobuf.MapField.newMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + if (!scopes_.isMutable()) { + scopes_ = scopes_.copy(); + } + bitField0_ |= 0x00000004; + onChanged(); + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + public Builder clearScopes() { + bitField0_ = (bitField0_ & ~0x00000004); + internalGetMutableScopes().getMutableMap() + .clear(); + return this; + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + public Builder removeScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableScopes().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableScopes() { + bitField0_ |= 0x00000004; + return internalGetMutableScopes().getMutableMap(); + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + public Builder putScopes( + java.lang.String key, + java.lang.String value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableScopes().getMutableMap() + .put(key, value); + bitField0_ |= 0x00000004; + return this; + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + public Builder putAllScopes( + java.util.Map values) { + internalGetMutableScopes().getMutableMap() + .putAll(values); + bitField0_ |= 0x00000004; + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.ImplicitOAuthFlow) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.ImplicitOAuthFlow) + private static final io.a2a.grpc.ImplicitOAuthFlow DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new io.a2a.grpc.ImplicitOAuthFlow(); + } + + public static io.a2a.grpc.ImplicitOAuthFlow getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ImplicitOAuthFlow parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public io.a2a.grpc.ImplicitOAuthFlow getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java new file mode 100644 index 000000000..3b0180dbc --- /dev/null +++ b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java @@ -0,0 +1,115 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package io.a2a.grpc; + +@com.google.protobuf.Generated +public interface ImplicitOAuthFlowOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.ImplicitOAuthFlow) + com.google.protobuf.MessageOrBuilder { + + /** + *
    +   * The authorization URL to be used for this flow. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS
    +   * 
    + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + java.lang.String getAuthorizationUrl(); + /** + *
    +   * The authorization URL to be used for this flow. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS
    +   * 
    + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + com.google.protobuf.ByteString + getAuthorizationUrlBytes(); + + /** + *
    +   * The URL to be used for obtaining refresh tokens. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + java.lang.String getRefreshUrl(); + /** + *
    +   * The URL to be used for obtaining refresh tokens. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + com.google.protobuf.ByteString + getRefreshUrlBytes(); + + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + int getScopesCount(); + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + boolean containsScopes( + java.lang.String key); + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getScopes(); + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + java.util.Map + getScopesMap(); + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue); + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + java.lang.String getScopesOrThrow( + java.lang.String key); +} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java index cbcdcfd18..b80396df7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java @@ -33,7 +33,7 @@ private ListTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessa } private ListTaskPushNotificationConfigRequest() { tenant_ = ""; - parent_ = ""; + taskId_ = ""; pageToken_ = ""; } @@ -97,49 +97,47 @@ public java.lang.String getTenant() { } } - public static final int PARENT_FIELD_NUMBER = 1; + public static final int TASK_ID_FIELD_NUMBER = 1; @SuppressWarnings("serial") - private volatile java.lang.Object parent_ = ""; + private volatile java.lang.Object taskId_ = ""; /** *
    -   * The parent task resource.
    -   * Format: tasks/{task_id}
    +   * The parent task resource id.
        * 
    * - * string parent = 1; - * @return The parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ @java.lang.Override - public java.lang.String getParent() { - java.lang.Object ref = parent_; + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - parent_ = s; + taskId_ = s; return s; } } /** *
    -   * The parent task resource.
    -   * Format: tasks/{task_id}
    +   * The parent task resource id.
        * 
    * - * string parent = 1; - * @return The bytes for parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ @java.lang.Override public com.google.protobuf.ByteString - getParentBytes() { - java.lang.Object ref = parent_; + getTaskIdBytes() { + java.lang.Object ref = taskId_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - parent_ = b; + taskId_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -222,8 +220,8 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(parent_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, parent_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); } if (pageSize_ != 0) { output.writeInt32(2, pageSize_); @@ -243,8 +241,8 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(parent_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, parent_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); } if (pageSize_ != 0) { size += com.google.protobuf.CodedOutputStream @@ -273,8 +271,8 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (!getParent() - .equals(other.getParent())) return false; + if (!getTaskId() + .equals(other.getTaskId())) return false; if (getPageSize() != other.getPageSize()) return false; if (!getPageToken() @@ -292,8 +290,8 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + PARENT_FIELD_NUMBER; - hash = (53 * hash) + getParent().hashCode(); + hash = (37 * hash) + TASK_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskId().hashCode(); hash = (37 * hash) + PAGE_SIZE_FIELD_NUMBER; hash = (53 * hash) + getPageSize(); hash = (37 * hash) + PAGE_TOKEN_FIELD_NUMBER; @@ -434,7 +432,7 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - parent_ = ""; + taskId_ = ""; pageSize_ = 0; pageToken_ = ""; return this; @@ -474,7 +472,7 @@ private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigRequest res result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.parent_ = parent_; + result.taskId_ = taskId_; } if (((from_bitField0_ & 0x00000004) != 0)) { result.pageSize_ = pageSize_; @@ -501,8 +499,8 @@ public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigRequest other bitField0_ |= 0x00000001; onChanged(); } - if (!other.getParent().isEmpty()) { - parent_ = other.parent_; + if (!other.getTaskId().isEmpty()) { + taskId_ = other.taskId_; bitField0_ |= 0x00000002; onChanged(); } @@ -541,7 +539,7 @@ public Builder mergeFrom( done = true; break; case 10: { - parent_ = input.readStringRequireUtf8(); + taskId_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; } // case 10 @@ -669,23 +667,22 @@ public Builder setTenantBytes( return this; } - private java.lang.Object parent_ = ""; + private java.lang.Object taskId_ = ""; /** *
    -     * The parent task resource.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1; - * @return The parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ - public java.lang.String getParent() { - java.lang.Object ref = parent_; + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - parent_ = s; + taskId_ = s; return s; } else { return (java.lang.String) ref; @@ -693,21 +690,20 @@ public java.lang.String getParent() { } /** *
    -     * The parent task resource.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1; - * @return The bytes for parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ public com.google.protobuf.ByteString - getParentBytes() { - java.lang.Object ref = parent_; + getTaskIdBytes() { + java.lang.Object ref = taskId_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - parent_ = b; + taskId_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -715,52 +711,49 @@ public java.lang.String getParent() { } /** *
    -     * The parent task resource.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1; - * @param value The parent to set. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The taskId to set. * @return This builder for chaining. */ - public Builder setParent( + public Builder setTaskId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - parent_ = value; + taskId_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } /** *
    -     * The parent task resource.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1; + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearParent() { - parent_ = getDefaultInstance().getParent(); + public Builder clearTaskId() { + taskId_ = getDefaultInstance().getTaskId(); bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } /** *
    -     * The parent task resource.
    -     * Format: tasks/{task_id}
    +     * The parent task resource id.
          * 
    * - * string parent = 1; - * @param value The bytes for parent to set. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for taskId to set. * @return This builder for chaining. */ - public Builder setParentBytes( + public Builder setTaskIdBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - parent_ = value; + taskId_ = value; bitField0_ |= 0x00000002; onChanged(); return this; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java index 690539ac2..ba43bb3d7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java @@ -32,25 +32,23 @@ public interface ListTaskPushNotificationConfigRequestOrBuilder extends /** *
    -   * The parent task resource.
    -   * Format: tasks/{task_id}
    +   * The parent task resource id.
        * 
    * - * string parent = 1; - * @return The parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. */ - java.lang.String getParent(); + java.lang.String getTaskId(); /** *
    -   * The parent task resource.
    -   * Format: tasks/{task_id}
    +   * The parent task resource id.
        * 
    * - * string parent = 1; - * @return The bytes for parent. + * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. */ com.google.protobuf.ByteString - getParentBytes(); + getTaskIdBytes(); /** *
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java
    index e4fd7c957..8b1a661f7 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java
    @@ -56,6 +56,8 @@ public enum FlowCase
               com.google.protobuf.AbstractMessage.InternalOneOfEnum {
         AUTHORIZATION_CODE(1),
         CLIENT_CREDENTIALS(2),
    +    @java.lang.Deprecated IMPLICIT(3),
    +    @java.lang.Deprecated PASSWORD(4),
         DEVICE_CODE(5),
         FLOW_NOT_SET(0);
         private final int value;
    @@ -76,6 +78,8 @@ public static FlowCase forNumber(int value) {
           switch (value) {
             case 1: return AUTHORIZATION_CODE;
             case 2: return CLIENT_CREDENTIALS;
    +        case 3: return IMPLICIT;
    +        case 4: return PASSWORD;
             case 5: return DEVICE_CODE;
             case 0: return FLOW_NOT_SET;
             default: return null;
    @@ -178,6 +182,76 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
         return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
       }
     
    +  public static final int IMPLICIT_FIELD_NUMBER = 3;
    +  /**
    +   * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +   * @deprecated a2a.v1.OAuthFlows.implicit is deprecated.
    +   *     See a2a.proto;l=633
    +   * @return Whether the implicit field is set.
    +   */
    +  @java.lang.Override
    +  @java.lang.Deprecated public boolean hasImplicit() {
    +    return flowCase_ == 3;
    +  }
    +  /**
    +   * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +   * @deprecated a2a.v1.OAuthFlows.implicit is deprecated.
    +   *     See a2a.proto;l=633
    +   * @return The implicit.
    +   */
    +  @java.lang.Override
    +  @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow getImplicit() {
    +    if (flowCase_ == 3) {
    +       return (io.a2a.grpc.ImplicitOAuthFlow) flow_;
    +    }
    +    return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
    +  }
    +  /**
    +   * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +   */
    +  @java.lang.Override
    +  @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() {
    +    if (flowCase_ == 3) {
    +       return (io.a2a.grpc.ImplicitOAuthFlow) flow_;
    +    }
    +    return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
    +  }
    +
    +  public static final int PASSWORD_FIELD_NUMBER = 4;
    +  /**
    +   * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +   * @deprecated a2a.v1.OAuthFlows.password is deprecated.
    +   *     See a2a.proto;l=634
    +   * @return Whether the password field is set.
    +   */
    +  @java.lang.Override
    +  @java.lang.Deprecated public boolean hasPassword() {
    +    return flowCase_ == 4;
    +  }
    +  /**
    +   * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +   * @deprecated a2a.v1.OAuthFlows.password is deprecated.
    +   *     See a2a.proto;l=634
    +   * @return The password.
    +   */
    +  @java.lang.Override
    +  @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow getPassword() {
    +    if (flowCase_ == 4) {
    +       return (io.a2a.grpc.PasswordOAuthFlow) flow_;
    +    }
    +    return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
    +  }
    +  /**
    +   * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +   */
    +  @java.lang.Override
    +  @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() {
    +    if (flowCase_ == 4) {
    +       return (io.a2a.grpc.PasswordOAuthFlow) flow_;
    +    }
    +    return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
    +  }
    +
       public static final int DEVICE_CODE_FIELD_NUMBER = 5;
       /**
        * 
    @@ -241,6 +315,12 @@ public void writeTo(com.google.protobuf.CodedOutputStream output)
         if (flowCase_ == 2) {
           output.writeMessage(2, (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_);
         }
    +    if (flowCase_ == 3) {
    +      output.writeMessage(3, (io.a2a.grpc.ImplicitOAuthFlow) flow_);
    +    }
    +    if (flowCase_ == 4) {
    +      output.writeMessage(4, (io.a2a.grpc.PasswordOAuthFlow) flow_);
    +    }
         if (flowCase_ == 5) {
           output.writeMessage(5, (io.a2a.grpc.DeviceCodeOAuthFlow) flow_);
         }
    @@ -261,6 +341,14 @@ public int getSerializedSize() {
           size += com.google.protobuf.CodedOutputStream
             .computeMessageSize(2, (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_);
         }
    +    if (flowCase_ == 3) {
    +      size += com.google.protobuf.CodedOutputStream
    +        .computeMessageSize(3, (io.a2a.grpc.ImplicitOAuthFlow) flow_);
    +    }
    +    if (flowCase_ == 4) {
    +      size += com.google.protobuf.CodedOutputStream
    +        .computeMessageSize(4, (io.a2a.grpc.PasswordOAuthFlow) flow_);
    +    }
         if (flowCase_ == 5) {
           size += com.google.protobuf.CodedOutputStream
             .computeMessageSize(5, (io.a2a.grpc.DeviceCodeOAuthFlow) flow_);
    @@ -290,6 +378,14 @@ public boolean equals(final java.lang.Object obj) {
             if (!getClientCredentials()
                 .equals(other.getClientCredentials())) return false;
             break;
    +      case 3:
    +        if (!getImplicit()
    +            .equals(other.getImplicit())) return false;
    +        break;
    +      case 4:
    +        if (!getPassword()
    +            .equals(other.getPassword())) return false;
    +        break;
           case 5:
             if (!getDeviceCode()
                 .equals(other.getDeviceCode())) return false;
    @@ -317,6 +413,14 @@ public int hashCode() {
             hash = (37 * hash) + CLIENT_CREDENTIALS_FIELD_NUMBER;
             hash = (53 * hash) + getClientCredentials().hashCode();
             break;
    +      case 3:
    +        hash = (37 * hash) + IMPLICIT_FIELD_NUMBER;
    +        hash = (53 * hash) + getImplicit().hashCode();
    +        break;
    +      case 4:
    +        hash = (37 * hash) + PASSWORD_FIELD_NUMBER;
    +        hash = (53 * hash) + getPassword().hashCode();
    +        break;
           case 5:
             hash = (37 * hash) + DEVICE_CODE_FIELD_NUMBER;
             hash = (53 * hash) + getDeviceCode().hashCode();
    @@ -466,6 +570,12 @@ public Builder clear() {
           if (clientCredentialsBuilder_ != null) {
             clientCredentialsBuilder_.clear();
           }
    +      if (implicitBuilder_ != null) {
    +        implicitBuilder_.clear();
    +      }
    +      if (passwordBuilder_ != null) {
    +        passwordBuilder_.clear();
    +      }
           if (deviceCodeBuilder_ != null) {
             deviceCodeBuilder_.clear();
           }
    @@ -518,6 +628,14 @@ private void buildPartialOneofs(io.a2a.grpc.OAuthFlows result) {
               clientCredentialsBuilder_ != null) {
             result.flow_ = clientCredentialsBuilder_.build();
           }
    +      if (flowCase_ == 3 &&
    +          implicitBuilder_ != null) {
    +        result.flow_ = implicitBuilder_.build();
    +      }
    +      if (flowCase_ == 4 &&
    +          passwordBuilder_ != null) {
    +        result.flow_ = passwordBuilder_.build();
    +      }
           if (flowCase_ == 5 &&
               deviceCodeBuilder_ != null) {
             result.flow_ = deviceCodeBuilder_.build();
    @@ -545,6 +663,14 @@ public Builder mergeFrom(io.a2a.grpc.OAuthFlows other) {
               mergeClientCredentials(other.getClientCredentials());
               break;
             }
    +        case IMPLICIT: {
    +          mergeImplicit(other.getImplicit());
    +          break;
    +        }
    +        case PASSWORD: {
    +          mergePassword(other.getPassword());
    +          break;
    +        }
             case DEVICE_CODE: {
               mergeDeviceCode(other.getDeviceCode());
               break;
    @@ -593,6 +719,20 @@ public Builder mergeFrom(
                   flowCase_ = 2;
                   break;
                 } // case 18
    +            case 26: {
    +              input.readMessage(
    +                  internalGetImplicitFieldBuilder().getBuilder(),
    +                  extensionRegistry);
    +              flowCase_ = 3;
    +              break;
    +            } // case 26
    +            case 34: {
    +              input.readMessage(
    +                  internalGetPasswordFieldBuilder().getBuilder(),
    +                  extensionRegistry);
    +              flowCase_ = 4;
    +              break;
    +            } // case 34
                 case 42: {
                   input.readMessage(
                       internalGetDeviceCodeFieldBuilder().getBuilder(),
    @@ -988,6 +1128,298 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
           return clientCredentialsBuilder_;
         }
     
    +    private com.google.protobuf.SingleFieldBuilder<
    +        io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> implicitBuilder_;
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     * @deprecated a2a.v1.OAuthFlows.implicit is deprecated.
    +     *     See a2a.proto;l=633
    +     * @return Whether the implicit field is set.
    +     */
    +    @java.lang.Override
    +    @java.lang.Deprecated public boolean hasImplicit() {
    +      return flowCase_ == 3;
    +    }
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     * @deprecated a2a.v1.OAuthFlows.implicit is deprecated.
    +     *     See a2a.proto;l=633
    +     * @return The implicit.
    +     */
    +    @java.lang.Override
    +    @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow getImplicit() {
    +      if (implicitBuilder_ == null) {
    +        if (flowCase_ == 3) {
    +          return (io.a2a.grpc.ImplicitOAuthFlow) flow_;
    +        }
    +        return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
    +      } else {
    +        if (flowCase_ == 3) {
    +          return implicitBuilder_.getMessage();
    +        }
    +        return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
    +      }
    +    }
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public Builder setImplicit(io.a2a.grpc.ImplicitOAuthFlow value) {
    +      if (implicitBuilder_ == null) {
    +        if (value == null) {
    +          throw new NullPointerException();
    +        }
    +        flow_ = value;
    +        onChanged();
    +      } else {
    +        implicitBuilder_.setMessage(value);
    +      }
    +      flowCase_ = 3;
    +      return this;
    +    }
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public Builder setImplicit(
    +        io.a2a.grpc.ImplicitOAuthFlow.Builder builderForValue) {
    +      if (implicitBuilder_ == null) {
    +        flow_ = builderForValue.build();
    +        onChanged();
    +      } else {
    +        implicitBuilder_.setMessage(builderForValue.build());
    +      }
    +      flowCase_ = 3;
    +      return this;
    +    }
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public Builder mergeImplicit(io.a2a.grpc.ImplicitOAuthFlow value) {
    +      if (implicitBuilder_ == null) {
    +        if (flowCase_ == 3 &&
    +            flow_ != io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance()) {
    +          flow_ = io.a2a.grpc.ImplicitOAuthFlow.newBuilder((io.a2a.grpc.ImplicitOAuthFlow) flow_)
    +              .mergeFrom(value).buildPartial();
    +        } else {
    +          flow_ = value;
    +        }
    +        onChanged();
    +      } else {
    +        if (flowCase_ == 3) {
    +          implicitBuilder_.mergeFrom(value);
    +        } else {
    +          implicitBuilder_.setMessage(value);
    +        }
    +      }
    +      flowCase_ = 3;
    +      return this;
    +    }
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public Builder clearImplicit() {
    +      if (implicitBuilder_ == null) {
    +        if (flowCase_ == 3) {
    +          flowCase_ = 0;
    +          flow_ = null;
    +          onChanged();
    +        }
    +      } else {
    +        if (flowCase_ == 3) {
    +          flowCase_ = 0;
    +          flow_ = null;
    +        }
    +        implicitBuilder_.clear();
    +      }
    +      return this;
    +    }
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow.Builder getImplicitBuilder() {
    +      return internalGetImplicitFieldBuilder().getBuilder();
    +    }
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     */
    +    @java.lang.Override
    +    @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() {
    +      if ((flowCase_ == 3) && (implicitBuilder_ != null)) {
    +        return implicitBuilder_.getMessageOrBuilder();
    +      } else {
    +        if (flowCase_ == 3) {
    +          return (io.a2a.grpc.ImplicitOAuthFlow) flow_;
    +        }
    +        return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
    +      }
    +    }
    +    /**
    +     * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +     */
    +    private com.google.protobuf.SingleFieldBuilder<
    +        io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> 
    +        internalGetImplicitFieldBuilder() {
    +      if (implicitBuilder_ == null) {
    +        if (!(flowCase_ == 3)) {
    +          flow_ = io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
    +        }
    +        implicitBuilder_ = new com.google.protobuf.SingleFieldBuilder<
    +            io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder>(
    +                (io.a2a.grpc.ImplicitOAuthFlow) flow_,
    +                getParentForChildren(),
    +                isClean());
    +        flow_ = null;
    +      }
    +      flowCase_ = 3;
    +      onChanged();
    +      return implicitBuilder_;
    +    }
    +
    +    private com.google.protobuf.SingleFieldBuilder<
    +        io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> passwordBuilder_;
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     * @deprecated a2a.v1.OAuthFlows.password is deprecated.
    +     *     See a2a.proto;l=634
    +     * @return Whether the password field is set.
    +     */
    +    @java.lang.Override
    +    @java.lang.Deprecated public boolean hasPassword() {
    +      return flowCase_ == 4;
    +    }
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     * @deprecated a2a.v1.OAuthFlows.password is deprecated.
    +     *     See a2a.proto;l=634
    +     * @return The password.
    +     */
    +    @java.lang.Override
    +    @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow getPassword() {
    +      if (passwordBuilder_ == null) {
    +        if (flowCase_ == 4) {
    +          return (io.a2a.grpc.PasswordOAuthFlow) flow_;
    +        }
    +        return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
    +      } else {
    +        if (flowCase_ == 4) {
    +          return passwordBuilder_.getMessage();
    +        }
    +        return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
    +      }
    +    }
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public Builder setPassword(io.a2a.grpc.PasswordOAuthFlow value) {
    +      if (passwordBuilder_ == null) {
    +        if (value == null) {
    +          throw new NullPointerException();
    +        }
    +        flow_ = value;
    +        onChanged();
    +      } else {
    +        passwordBuilder_.setMessage(value);
    +      }
    +      flowCase_ = 4;
    +      return this;
    +    }
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public Builder setPassword(
    +        io.a2a.grpc.PasswordOAuthFlow.Builder builderForValue) {
    +      if (passwordBuilder_ == null) {
    +        flow_ = builderForValue.build();
    +        onChanged();
    +      } else {
    +        passwordBuilder_.setMessage(builderForValue.build());
    +      }
    +      flowCase_ = 4;
    +      return this;
    +    }
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public Builder mergePassword(io.a2a.grpc.PasswordOAuthFlow value) {
    +      if (passwordBuilder_ == null) {
    +        if (flowCase_ == 4 &&
    +            flow_ != io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance()) {
    +          flow_ = io.a2a.grpc.PasswordOAuthFlow.newBuilder((io.a2a.grpc.PasswordOAuthFlow) flow_)
    +              .mergeFrom(value).buildPartial();
    +        } else {
    +          flow_ = value;
    +        }
    +        onChanged();
    +      } else {
    +        if (flowCase_ == 4) {
    +          passwordBuilder_.mergeFrom(value);
    +        } else {
    +          passwordBuilder_.setMessage(value);
    +        }
    +      }
    +      flowCase_ = 4;
    +      return this;
    +    }
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public Builder clearPassword() {
    +      if (passwordBuilder_ == null) {
    +        if (flowCase_ == 4) {
    +          flowCase_ = 0;
    +          flow_ = null;
    +          onChanged();
    +        }
    +      } else {
    +        if (flowCase_ == 4) {
    +          flowCase_ = 0;
    +          flow_ = null;
    +        }
    +        passwordBuilder_.clear();
    +      }
    +      return this;
    +    }
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     */
    +    @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow.Builder getPasswordBuilder() {
    +      return internalGetPasswordFieldBuilder().getBuilder();
    +    }
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     */
    +    @java.lang.Override
    +    @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() {
    +      if ((flowCase_ == 4) && (passwordBuilder_ != null)) {
    +        return passwordBuilder_.getMessageOrBuilder();
    +      } else {
    +        if (flowCase_ == 4) {
    +          return (io.a2a.grpc.PasswordOAuthFlow) flow_;
    +        }
    +        return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
    +      }
    +    }
    +    /**
    +     * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +     */
    +    private com.google.protobuf.SingleFieldBuilder<
    +        io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> 
    +        internalGetPasswordFieldBuilder() {
    +      if (passwordBuilder_ == null) {
    +        if (!(flowCase_ == 4)) {
    +          flow_ = io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
    +        }
    +        passwordBuilder_ = new com.google.protobuf.SingleFieldBuilder<
    +            io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder>(
    +                (io.a2a.grpc.PasswordOAuthFlow) flow_,
    +                getParentForChildren(),
    +                isClean());
    +        flow_ = null;
    +      }
    +      flowCase_ = 4;
    +      onChanged();
    +      return passwordBuilder_;
    +    }
    +
         private com.google.protobuf.SingleFieldBuilder<
             io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder> deviceCodeBuilder_;
         /**
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java
    index cb84fa83e..1debd6d12 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java
    @@ -64,6 +64,44 @@ public interface OAuthFlowsOrBuilder extends
        */
       io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder();
     
    +  /**
    +   * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +   * @deprecated a2a.v1.OAuthFlows.implicit is deprecated.
    +   *     See a2a.proto;l=633
    +   * @return Whether the implicit field is set.
    +   */
    +  @java.lang.Deprecated boolean hasImplicit();
    +  /**
    +   * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +   * @deprecated a2a.v1.OAuthFlows.implicit is deprecated.
    +   *     See a2a.proto;l=633
    +   * @return The implicit.
    +   */
    +  @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlow getImplicit();
    +  /**
    +   * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
    +   */
    +  @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder();
    +
    +  /**
    +   * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +   * @deprecated a2a.v1.OAuthFlows.password is deprecated.
    +   *     See a2a.proto;l=634
    +   * @return Whether the password field is set.
    +   */
    +  @java.lang.Deprecated boolean hasPassword();
    +  /**
    +   * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +   * @deprecated a2a.v1.OAuthFlows.password is deprecated.
    +   *     See a2a.proto;l=634
    +   * @return The password.
    +   */
    +  @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlow getPassword();
    +  /**
    +   * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
    +   */
    +  @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder();
    +
       /**
        * 
        * Configuration for the OAuth Device Code flow.
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Part.java b/spec-grpc/src/main/java/io/a2a/grpc/Part.java
    index 511d10dae..879380c96 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/Part.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/Part.java
    @@ -35,6 +35,8 @@ private Part(com.google.protobuf.GeneratedMessage.Builder builder) {
         super(builder);
       }
       private Part() {
    +    filename_ = "";
    +    mediaType_ = "";
       }
     
       public static final com.google.protobuf.Descriptors.Descriptor
    @@ -51,18 +53,19 @@ private Part() {
       }
     
       private int bitField0_;
    -  private int partCase_ = 0;
    +  private int contentCase_ = 0;
       @SuppressWarnings("serial")
    -  private java.lang.Object part_;
    -  public enum PartCase
    +  private java.lang.Object content_;
    +  public enum ContentCase
           implements com.google.protobuf.Internal.EnumLite,
               com.google.protobuf.AbstractMessage.InternalOneOfEnum {
         TEXT(1),
    -    FILE(2),
    -    DATA(3),
    -    PART_NOT_SET(0);
    +    RAW(2),
    +    URL(3),
    +    DATA(4),
    +    CONTENT_NOT_SET(0);
         private final int value;
    -    private PartCase(int value) {
    +    private ContentCase(int value) {
           this.value = value;
         }
         /**
    @@ -71,16 +74,17 @@ private PartCase(int value) {
          * @deprecated Use {@link #forNumber(int)} instead.
          */
         @java.lang.Deprecated
    -    public static PartCase valueOf(int value) {
    +    public static ContentCase valueOf(int value) {
           return forNumber(value);
         }
     
    -    public static PartCase forNumber(int value) {
    +    public static ContentCase forNumber(int value) {
           switch (value) {
             case 1: return TEXT;
    -        case 2: return FILE;
    -        case 3: return DATA;
    -        case 0: return PART_NOT_SET;
    +        case 2: return RAW;
    +        case 3: return URL;
    +        case 4: return DATA;
    +        case 0: return CONTENT_NOT_SET;
             default: return null;
           }
         }
    @@ -89,10 +93,10 @@ public int getNumber() {
         }
       };
     
    -  public PartCase
    -  getPartCase() {
    -    return PartCase.forNumber(
    -        partCase_);
    +  public ContentCase
    +  getContentCase() {
    +    return ContentCase.forNumber(
    +        contentCase_);
       }
     
       public static final int TEXT_FIELD_NUMBER = 1;
    @@ -105,7 +109,7 @@ public int getNumber() {
        * @return Whether the text field is set.
        */
       public boolean hasText() {
    -    return partCase_ == 1;
    +    return contentCase_ == 1;
       }
       /**
        * 
    @@ -117,8 +121,8 @@ public boolean hasText() {
        */
       public java.lang.String getText() {
         java.lang.Object ref = "";
    -    if (partCase_ == 1) {
    -      ref = part_;
    +    if (contentCase_ == 1) {
    +      ref = content_;
         }
         if (ref instanceof java.lang.String) {
           return (java.lang.String) ref;
    @@ -126,8 +130,8 @@ public java.lang.String getText() {
           com.google.protobuf.ByteString bs = 
               (com.google.protobuf.ByteString) ref;
           java.lang.String s = bs.toStringUtf8();
    -      if (partCase_ == 1) {
    -        part_ = s;
    +      if (contentCase_ == 1) {
    +        content_ = s;
           }
           return s;
         }
    @@ -143,15 +147,15 @@ public java.lang.String getText() {
       public com.google.protobuf.ByteString
           getTextBytes() {
         java.lang.Object ref = "";
    -    if (partCase_ == 1) {
    -      ref = part_;
    +    if (contentCase_ == 1) {
    +      ref = content_;
         }
         if (ref instanceof java.lang.String) {
           com.google.protobuf.ByteString b = 
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
    -      if (partCase_ == 1) {
    -        part_ = b;
    +      if (contentCase_ == 1) {
    +        content_ = b;
           }
           return b;
         } else {
    @@ -159,100 +163,150 @@ public java.lang.String getText() {
         }
       }
     
    -  public static final int FILE_FIELD_NUMBER = 2;
    +  public static final int RAW_FIELD_NUMBER = 2;
       /**
        * 
    -   * The file content, represented as either a URI or as base64-encoded bytes.
    +   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        * 
    * - * .a2a.v1.FilePart file = 2; - * @return Whether the file field is set. + * bytes raw = 2; + * @return Whether the raw field is set. */ @java.lang.Override - public boolean hasFile() { - return partCase_ == 2; + public boolean hasRaw() { + return contentCase_ == 2; } /** *
    -   * The file content, represented as either a URI or as base64-encoded bytes.
    +   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        * 
    * - * .a2a.v1.FilePart file = 2; - * @return The file. + * bytes raw = 2; + * @return The raw. */ @java.lang.Override - public io.a2a.grpc.FilePart getFile() { - if (partCase_ == 2) { - return (io.a2a.grpc.FilePart) part_; + public com.google.protobuf.ByteString getRaw() { + if (contentCase_ == 2) { + return (com.google.protobuf.ByteString) content_; } - return io.a2a.grpc.FilePart.getDefaultInstance(); + return com.google.protobuf.ByteString.EMPTY; } + + public static final int URL_FIELD_NUMBER = 3; /** *
    -   * The file content, represented as either a URI or as base64-encoded bytes.
    +   * A URL pointing to the file's content.
        * 
    * - * .a2a.v1.FilePart file = 2; + * string url = 3; + * @return Whether the url field is set. */ - @java.lang.Override - public io.a2a.grpc.FilePartOrBuilder getFileOrBuilder() { - if (partCase_ == 2) { - return (io.a2a.grpc.FilePart) part_; + public boolean hasUrl() { + return contentCase_ == 3; + } + /** + *
    +   * A URL pointing to the file's content.
    +   * 
    + * + * string url = 3; + * @return The url. + */ + public java.lang.String getUrl() { + java.lang.Object ref = ""; + if (contentCase_ == 3) { + ref = content_; + } + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (contentCase_ == 3) { + content_ = s; + } + return s; + } + } + /** + *
    +   * A URL pointing to the file's content.
    +   * 
    + * + * string url = 3; + * @return The bytes for url. + */ + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = ""; + if (contentCase_ == 3) { + ref = content_; + } + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + if (contentCase_ == 3) { + content_ = b; + } + return b; + } else { + return (com.google.protobuf.ByteString) ref; } - return io.a2a.grpc.FilePart.getDefaultInstance(); } - public static final int DATA_FIELD_NUMBER = 3; + public static final int DATA_FIELD_NUMBER = 4; /** *
    -   * The structured data content.
    +   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; * @return Whether the data field is set. */ @java.lang.Override public boolean hasData() { - return partCase_ == 3; + return contentCase_ == 4; } /** *
    -   * The structured data content.
    +   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; * @return The data. */ @java.lang.Override - public io.a2a.grpc.DataPart getData() { - if (partCase_ == 3) { - return (io.a2a.grpc.DataPart) part_; + public com.google.protobuf.Value getData() { + if (contentCase_ == 4) { + return (com.google.protobuf.Value) content_; } - return io.a2a.grpc.DataPart.getDefaultInstance(); + return com.google.protobuf.Value.getDefaultInstance(); } /** *
    -   * The structured data content.
    +   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ @java.lang.Override - public io.a2a.grpc.DataPartOrBuilder getDataOrBuilder() { - if (partCase_ == 3) { - return (io.a2a.grpc.DataPart) part_; + public com.google.protobuf.ValueOrBuilder getDataOrBuilder() { + if (contentCase_ == 4) { + return (com.google.protobuf.Value) content_; } - return io.a2a.grpc.DataPart.getDefaultInstance(); + return com.google.protobuf.Value.getDefaultInstance(); } - public static final int METADATA_FIELD_NUMBER = 4; + public static final int METADATA_FIELD_NUMBER = 5; private com.google.protobuf.Struct metadata_; /** *
        * Optional metadata associated with this part.
        * 
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; * @return Whether the metadata field is set. */ @java.lang.Override @@ -264,7 +318,7 @@ public boolean hasMetadata() { * Optional metadata associated with this part. *
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; * @return The metadata. */ @java.lang.Override @@ -276,13 +330,109 @@ public com.google.protobuf.Struct getMetadata() { * Optional metadata associated with this part. *
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ @java.lang.Override public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; } + public static final int FILENAME_FIELD_NUMBER = 6; + @SuppressWarnings("serial") + private volatile java.lang.Object filename_ = ""; + /** + *
    +   * An optional name for the file (e.g., "document.pdf").
    +   * 
    + * + * string filename = 6; + * @return The filename. + */ + @java.lang.Override + public java.lang.String getFilename() { + java.lang.Object ref = filename_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + filename_ = s; + return s; + } + } + /** + *
    +   * An optional name for the file (e.g., "document.pdf").
    +   * 
    + * + * string filename = 6; + * @return The bytes for filename. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getFilenameBytes() { + java.lang.Object ref = filename_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + filename_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int MEDIA_TYPE_FIELD_NUMBER = 7; + @SuppressWarnings("serial") + private volatile java.lang.Object mediaType_ = ""; + /** + *
    +   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +   * This field is available for all part types.
    +   * 
    + * + * string media_type = 7; + * @return The mediaType. + */ + @java.lang.Override + public java.lang.String getMediaType() { + java.lang.Object ref = mediaType_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + mediaType_ = s; + return s; + } + } + /** + *
    +   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +   * This field is available for all part types.
    +   * 
    + * + * string media_type = 7; + * @return The bytes for mediaType. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getMediaTypeBytes() { + java.lang.Object ref = mediaType_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + mediaType_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -297,17 +447,27 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (partCase_ == 1) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, part_); + if (contentCase_ == 1) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, content_); } - if (partCase_ == 2) { - output.writeMessage(2, (io.a2a.grpc.FilePart) part_); + if (contentCase_ == 2) { + output.writeBytes( + 2, (com.google.protobuf.ByteString) content_); } - if (partCase_ == 3) { - output.writeMessage(3, (io.a2a.grpc.DataPart) part_); + if (contentCase_ == 3) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, content_); + } + if (contentCase_ == 4) { + output.writeMessage(4, (com.google.protobuf.Value) content_); } if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(4, getMetadata()); + output.writeMessage(5, getMetadata()); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(filename_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 6, filename_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(mediaType_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 7, mediaType_); } getUnknownFields().writeTo(output); } @@ -318,20 +478,30 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (partCase_ == 1) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, part_); + if (contentCase_ == 1) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, content_); } - if (partCase_ == 2) { + if (contentCase_ == 2) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, (io.a2a.grpc.FilePart) part_); + .computeBytesSize( + 2, (com.google.protobuf.ByteString) content_); + } + if (contentCase_ == 3) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, content_); } - if (partCase_ == 3) { + if (contentCase_ == 4) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, (io.a2a.grpc.DataPart) part_); + .computeMessageSize(4, (com.google.protobuf.Value) content_); } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, getMetadata()); + .computeMessageSize(5, getMetadata()); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(filename_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(6, filename_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(mediaType_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(7, mediaType_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -353,17 +523,25 @@ public boolean equals(final java.lang.Object obj) { if (!getMetadata() .equals(other.getMetadata())) return false; } - if (!getPartCase().equals(other.getPartCase())) return false; - switch (partCase_) { + if (!getFilename() + .equals(other.getFilename())) return false; + if (!getMediaType() + .equals(other.getMediaType())) return false; + if (!getContentCase().equals(other.getContentCase())) return false; + switch (contentCase_) { case 1: if (!getText() .equals(other.getText())) return false; break; case 2: - if (!getFile() - .equals(other.getFile())) return false; + if (!getRaw() + .equals(other.getRaw())) return false; break; case 3: + if (!getUrl() + .equals(other.getUrl())) return false; + break; + case 4: if (!getData() .equals(other.getData())) return false; break; @@ -385,16 +563,24 @@ public int hashCode() { hash = (37 * hash) + METADATA_FIELD_NUMBER; hash = (53 * hash) + getMetadata().hashCode(); } - switch (partCase_) { + hash = (37 * hash) + FILENAME_FIELD_NUMBER; + hash = (53 * hash) + getFilename().hashCode(); + hash = (37 * hash) + MEDIA_TYPE_FIELD_NUMBER; + hash = (53 * hash) + getMediaType().hashCode(); + switch (contentCase_) { case 1: hash = (37 * hash) + TEXT_FIELD_NUMBER; hash = (53 * hash) + getText().hashCode(); break; case 2: - hash = (37 * hash) + FILE_FIELD_NUMBER; - hash = (53 * hash) + getFile().hashCode(); + hash = (37 * hash) + RAW_FIELD_NUMBER; + hash = (53 * hash) + getRaw().hashCode(); break; case 3: + hash = (37 * hash) + URL_FIELD_NUMBER; + hash = (53 * hash) + getUrl().hashCode(); + break; + case 4: hash = (37 * hash) + DATA_FIELD_NUMBER; hash = (53 * hash) + getData().hashCode(); break; @@ -545,9 +731,6 @@ private void maybeForceBuilderInitialization() { public Builder clear() { super.clear(); bitField0_ = 0; - if (fileBuilder_ != null) { - fileBuilder_.clear(); - } if (dataBuilder_ != null) { dataBuilder_.clear(); } @@ -556,8 +739,10 @@ public Builder clear() { metadataBuilder_.dispose(); metadataBuilder_ = null; } - partCase_ = 0; - part_ = null; + filename_ = ""; + mediaType_ = ""; + contentCase_ = 0; + content_ = null; return this; } @@ -593,25 +778,27 @@ public io.a2a.grpc.Part buildPartial() { private void buildPartial0(io.a2a.grpc.Part result) { int from_bitField0_ = bitField0_; int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { + if (((from_bitField0_ & 0x00000010) != 0)) { result.metadata_ = metadataBuilder_ == null ? metadata_ : metadataBuilder_.build(); to_bitField0_ |= 0x00000001; } + if (((from_bitField0_ & 0x00000020) != 0)) { + result.filename_ = filename_; + } + if (((from_bitField0_ & 0x00000040) != 0)) { + result.mediaType_ = mediaType_; + } result.bitField0_ |= to_bitField0_; } private void buildPartialOneofs(io.a2a.grpc.Part result) { - result.partCase_ = partCase_; - result.part_ = this.part_; - if (partCase_ == 2 && - fileBuilder_ != null) { - result.part_ = fileBuilder_.build(); - } - if (partCase_ == 3 && + result.contentCase_ = contentCase_; + result.content_ = this.content_; + if (contentCase_ == 4 && dataBuilder_ != null) { - result.part_ = dataBuilder_.build(); + result.content_ = dataBuilder_.build(); } } @@ -630,22 +817,38 @@ public Builder mergeFrom(io.a2a.grpc.Part other) { if (other.hasMetadata()) { mergeMetadata(other.getMetadata()); } - switch (other.getPartCase()) { + if (!other.getFilename().isEmpty()) { + filename_ = other.filename_; + bitField0_ |= 0x00000020; + onChanged(); + } + if (!other.getMediaType().isEmpty()) { + mediaType_ = other.mediaType_; + bitField0_ |= 0x00000040; + onChanged(); + } + switch (other.getContentCase()) { case TEXT: { - partCase_ = 1; - part_ = other.part_; + contentCase_ = 1; + content_ = other.content_; onChanged(); break; } - case FILE: { - mergeFile(other.getFile()); + case RAW: { + setRaw(other.getRaw()); + break; + } + case URL: { + contentCase_ = 3; + content_ = other.content_; + onChanged(); break; } case DATA: { mergeData(other.getData()); break; } - case PART_NOT_SET: { + case CONTENT_NOT_SET: { break; } } @@ -677,31 +880,45 @@ public Builder mergeFrom( break; case 10: { java.lang.String s = input.readStringRequireUtf8(); - partCase_ = 1; - part_ = s; + contentCase_ = 1; + content_ = s; break; } // case 10 case 18: { - input.readMessage( - internalGetFileFieldBuilder().getBuilder(), - extensionRegistry); - partCase_ = 2; + content_ = input.readBytes(); + contentCase_ = 2; break; } // case 18 case 26: { + java.lang.String s = input.readStringRequireUtf8(); + contentCase_ = 3; + content_ = s; + break; + } // case 26 + case 34: { input.readMessage( internalGetDataFieldBuilder().getBuilder(), extensionRegistry); - partCase_ = 3; + contentCase_ = 4; break; - } // case 26 - case 34: { + } // case 34 + case 42: { input.readMessage( internalGetMetadataFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; break; - } // case 34 + } // case 42 + case 50: { + filename_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000020; + break; + } // case 50 + case 58: { + mediaType_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000040; + break; + } // case 58 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -717,17 +934,17 @@ public Builder mergeFrom( } // finally return this; } - private int partCase_ = 0; - private java.lang.Object part_; - public PartCase - getPartCase() { - return PartCase.forNumber( - partCase_); + private int contentCase_ = 0; + private java.lang.Object content_; + public ContentCase + getContentCase() { + return ContentCase.forNumber( + contentCase_); } - public Builder clearPart() { - partCase_ = 0; - part_ = null; + public Builder clearContent() { + contentCase_ = 0; + content_ = null; onChanged(); return this; } @@ -744,7 +961,7 @@ public Builder clearPart() { */ @java.lang.Override public boolean hasText() { - return partCase_ == 1; + return contentCase_ == 1; } /** *
    @@ -757,15 +974,15 @@ public boolean hasText() {
         @java.lang.Override
         public java.lang.String getText() {
           java.lang.Object ref = "";
    -      if (partCase_ == 1) {
    -        ref = part_;
    +      if (contentCase_ == 1) {
    +        ref = content_;
           }
           if (!(ref instanceof java.lang.String)) {
             com.google.protobuf.ByteString bs =
                 (com.google.protobuf.ByteString) ref;
             java.lang.String s = bs.toStringUtf8();
    -        if (partCase_ == 1) {
    -          part_ = s;
    +        if (contentCase_ == 1) {
    +          content_ = s;
             }
             return s;
           } else {
    @@ -784,15 +1001,15 @@ public java.lang.String getText() {
         public com.google.protobuf.ByteString
             getTextBytes() {
           java.lang.Object ref = "";
    -      if (partCase_ == 1) {
    -        ref = part_;
    +      if (contentCase_ == 1) {
    +        ref = content_;
           }
           if (ref instanceof String) {
             com.google.protobuf.ByteString b = 
                 com.google.protobuf.ByteString.copyFromUtf8(
                     (java.lang.String) ref);
    -        if (partCase_ == 1) {
    -          part_ = b;
    +        if (contentCase_ == 1) {
    +          content_ = b;
             }
             return b;
           } else {
    @@ -811,8 +1028,8 @@ public java.lang.String getText() {
         public Builder setText(
             java.lang.String value) {
           if (value == null) { throw new NullPointerException(); }
    -      partCase_ = 1;
    -      part_ = value;
    +      contentCase_ = 1;
    +      content_ = value;
           onChanged();
           return this;
         }
    @@ -825,9 +1042,9 @@ public Builder setText(
          * @return This builder for chaining.
          */
         public Builder clearText() {
    -      if (partCase_ == 1) {
    -        partCase_ = 0;
    -        part_ = null;
    +      if (contentCase_ == 1) {
    +        contentCase_ = 0;
    +        content_ = null;
             onChanged();
           }
           return this;
    @@ -845,309 +1062,306 @@ public Builder setTextBytes(
             com.google.protobuf.ByteString value) {
           if (value == null) { throw new NullPointerException(); }
           checkByteStringIsUtf8(value);
    -      partCase_ = 1;
    -      part_ = value;
    +      contentCase_ = 1;
    +      content_ = value;
           onChanged();
           return this;
         }
     
    -    private com.google.protobuf.SingleFieldBuilder<
    -        io.a2a.grpc.FilePart, io.a2a.grpc.FilePart.Builder, io.a2a.grpc.FilePartOrBuilder> fileBuilder_;
         /**
          * 
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
          * 
    * - * .a2a.v1.FilePart file = 2; - * @return Whether the file field is set. + * bytes raw = 2; + * @return Whether the raw field is set. */ - @java.lang.Override - public boolean hasFile() { - return partCase_ == 2; + public boolean hasRaw() { + return contentCase_ == 2; } /** *
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
          * 
    * - * .a2a.v1.FilePart file = 2; - * @return The file. + * bytes raw = 2; + * @return The raw. */ - @java.lang.Override - public io.a2a.grpc.FilePart getFile() { - if (fileBuilder_ == null) { - if (partCase_ == 2) { - return (io.a2a.grpc.FilePart) part_; - } - return io.a2a.grpc.FilePart.getDefaultInstance(); - } else { - if (partCase_ == 2) { - return fileBuilder_.getMessage(); - } - return io.a2a.grpc.FilePart.getDefaultInstance(); + public com.google.protobuf.ByteString getRaw() { + if (contentCase_ == 2) { + return (com.google.protobuf.ByteString) content_; } + return com.google.protobuf.ByteString.EMPTY; } /** *
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
          * 
    * - * .a2a.v1.FilePart file = 2; + * bytes raw = 2; + * @param value The raw to set. + * @return This builder for chaining. */ - public Builder setFile(io.a2a.grpc.FilePart value) { - if (fileBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - part_ = value; - onChanged(); - } else { - fileBuilder_.setMessage(value); - } - partCase_ = 2; + public Builder setRaw(com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + contentCase_ = 2; + content_ = value; + onChanged(); return this; } /** *
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
          * 
    * - * .a2a.v1.FilePart file = 2; + * bytes raw = 2; + * @return This builder for chaining. */ - public Builder setFile( - io.a2a.grpc.FilePart.Builder builderForValue) { - if (fileBuilder_ == null) { - part_ = builderForValue.build(); + public Builder clearRaw() { + if (contentCase_ == 2) { + contentCase_ = 0; + content_ = null; onChanged(); - } else { - fileBuilder_.setMessage(builderForValue.build()); } - partCase_ = 2; return this; } + /** *
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * A URL pointing to the file's content.
          * 
    * - * .a2a.v1.FilePart file = 2; + * string url = 3; + * @return Whether the url field is set. */ - public Builder mergeFile(io.a2a.grpc.FilePart value) { - if (fileBuilder_ == null) { - if (partCase_ == 2 && - part_ != io.a2a.grpc.FilePart.getDefaultInstance()) { - part_ = io.a2a.grpc.FilePart.newBuilder((io.a2a.grpc.FilePart) part_) - .mergeFrom(value).buildPartial(); - } else { - part_ = value; + @java.lang.Override + public boolean hasUrl() { + return contentCase_ == 3; + } + /** + *
    +     * A URL pointing to the file's content.
    +     * 
    + * + * string url = 3; + * @return The url. + */ + @java.lang.Override + public java.lang.String getUrl() { + java.lang.Object ref = ""; + if (contentCase_ == 3) { + ref = content_; + } + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (contentCase_ == 3) { + content_ = s; } - onChanged(); + return s; } else { - if (partCase_ == 2) { - fileBuilder_.mergeFrom(value); - } else { - fileBuilder_.setMessage(value); - } + return (java.lang.String) ref; } - partCase_ = 2; - return this; } /** *
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * A URL pointing to the file's content.
          * 
    * - * .a2a.v1.FilePart file = 2; + * string url = 3; + * @return The bytes for url. */ - public Builder clearFile() { - if (fileBuilder_ == null) { - if (partCase_ == 2) { - partCase_ = 0; - part_ = null; - onChanged(); + @java.lang.Override + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = ""; + if (contentCase_ == 3) { + ref = content_; + } + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + if (contentCase_ == 3) { + content_ = b; } + return b; } else { - if (partCase_ == 2) { - partCase_ = 0; - part_ = null; - } - fileBuilder_.clear(); + return (com.google.protobuf.ByteString) ref; } - return this; } /** *
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * A URL pointing to the file's content.
          * 
    * - * .a2a.v1.FilePart file = 2; + * string url = 3; + * @param value The url to set. + * @return This builder for chaining. */ - public io.a2a.grpc.FilePart.Builder getFileBuilder() { - return internalGetFileFieldBuilder().getBuilder(); + public Builder setUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + contentCase_ = 3; + content_ = value; + onChanged(); + return this; } /** *
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * A URL pointing to the file's content.
          * 
    * - * .a2a.v1.FilePart file = 2; + * string url = 3; + * @return This builder for chaining. */ - @java.lang.Override - public io.a2a.grpc.FilePartOrBuilder getFileOrBuilder() { - if ((partCase_ == 2) && (fileBuilder_ != null)) { - return fileBuilder_.getMessageOrBuilder(); - } else { - if (partCase_ == 2) { - return (io.a2a.grpc.FilePart) part_; - } - return io.a2a.grpc.FilePart.getDefaultInstance(); + public Builder clearUrl() { + if (contentCase_ == 3) { + contentCase_ = 0; + content_ = null; + onChanged(); } + return this; } /** *
    -     * The file content, represented as either a URI or as base64-encoded bytes.
    +     * A URL pointing to the file's content.
          * 
    * - * .a2a.v1.FilePart file = 2; + * string url = 3; + * @param value The bytes for url to set. + * @return This builder for chaining. */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.FilePart, io.a2a.grpc.FilePart.Builder, io.a2a.grpc.FilePartOrBuilder> - internalGetFileFieldBuilder() { - if (fileBuilder_ == null) { - if (!(partCase_ == 2)) { - part_ = io.a2a.grpc.FilePart.getDefaultInstance(); - } - fileBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.FilePart, io.a2a.grpc.FilePart.Builder, io.a2a.grpc.FilePartOrBuilder>( - (io.a2a.grpc.FilePart) part_, - getParentForChildren(), - isClean()); - part_ = null; - } - partCase_ = 2; + public Builder setUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + contentCase_ = 3; + content_ = value; onChanged(); - return fileBuilder_; + return this; } private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.DataPart, io.a2a.grpc.DataPart.Builder, io.a2a.grpc.DataPartOrBuilder> dataBuilder_; + com.google.protobuf.Value, com.google.protobuf.Value.Builder, com.google.protobuf.ValueOrBuilder> dataBuilder_; /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; * @return Whether the data field is set. */ @java.lang.Override public boolean hasData() { - return partCase_ == 3; + return contentCase_ == 4; } /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; * @return The data. */ @java.lang.Override - public io.a2a.grpc.DataPart getData() { + public com.google.protobuf.Value getData() { if (dataBuilder_ == null) { - if (partCase_ == 3) { - return (io.a2a.grpc.DataPart) part_; + if (contentCase_ == 4) { + return (com.google.protobuf.Value) content_; } - return io.a2a.grpc.DataPart.getDefaultInstance(); + return com.google.protobuf.Value.getDefaultInstance(); } else { - if (partCase_ == 3) { + if (contentCase_ == 4) { return dataBuilder_.getMessage(); } - return io.a2a.grpc.DataPart.getDefaultInstance(); + return com.google.protobuf.Value.getDefaultInstance(); } } /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ - public Builder setData(io.a2a.grpc.DataPart value) { + public Builder setData(com.google.protobuf.Value value) { if (dataBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - part_ = value; + content_ = value; onChanged(); } else { dataBuilder_.setMessage(value); } - partCase_ = 3; + contentCase_ = 4; return this; } /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ public Builder setData( - io.a2a.grpc.DataPart.Builder builderForValue) { + com.google.protobuf.Value.Builder builderForValue) { if (dataBuilder_ == null) { - part_ = builderForValue.build(); + content_ = builderForValue.build(); onChanged(); } else { dataBuilder_.setMessage(builderForValue.build()); } - partCase_ = 3; + contentCase_ = 4; return this; } /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ - public Builder mergeData(io.a2a.grpc.DataPart value) { + public Builder mergeData(com.google.protobuf.Value value) { if (dataBuilder_ == null) { - if (partCase_ == 3 && - part_ != io.a2a.grpc.DataPart.getDefaultInstance()) { - part_ = io.a2a.grpc.DataPart.newBuilder((io.a2a.grpc.DataPart) part_) + if (contentCase_ == 4 && + content_ != com.google.protobuf.Value.getDefaultInstance()) { + content_ = com.google.protobuf.Value.newBuilder((com.google.protobuf.Value) content_) .mergeFrom(value).buildPartial(); } else { - part_ = value; + content_ = value; } onChanged(); } else { - if (partCase_ == 3) { + if (contentCase_ == 4) { dataBuilder_.mergeFrom(value); } else { dataBuilder_.setMessage(value); } } - partCase_ = 3; + contentCase_ = 4; return this; } /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ public Builder clearData() { if (dataBuilder_ == null) { - if (partCase_ == 3) { - partCase_ = 0; - part_ = null; + if (contentCase_ == 4) { + contentCase_ = 0; + content_ = null; onChanged(); } } else { - if (partCase_ == 3) { - partCase_ = 0; - part_ = null; + if (contentCase_ == 4) { + contentCase_ = 0; + content_ = null; } dataBuilder_.clear(); } @@ -1155,54 +1369,54 @@ public Builder clearData() { } /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ - public io.a2a.grpc.DataPart.Builder getDataBuilder() { + public com.google.protobuf.Value.Builder getDataBuilder() { return internalGetDataFieldBuilder().getBuilder(); } /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ @java.lang.Override - public io.a2a.grpc.DataPartOrBuilder getDataOrBuilder() { - if ((partCase_ == 3) && (dataBuilder_ != null)) { + public com.google.protobuf.ValueOrBuilder getDataOrBuilder() { + if ((contentCase_ == 4) && (dataBuilder_ != null)) { return dataBuilder_.getMessageOrBuilder(); } else { - if (partCase_ == 3) { - return (io.a2a.grpc.DataPart) part_; + if (contentCase_ == 4) { + return (com.google.protobuf.Value) content_; } - return io.a2a.grpc.DataPart.getDefaultInstance(); + return com.google.protobuf.Value.getDefaultInstance(); } } /** *
    -     * The structured data content.
    +     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
          * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.DataPart, io.a2a.grpc.DataPart.Builder, io.a2a.grpc.DataPartOrBuilder> + com.google.protobuf.Value, com.google.protobuf.Value.Builder, com.google.protobuf.ValueOrBuilder> internalGetDataFieldBuilder() { if (dataBuilder_ == null) { - if (!(partCase_ == 3)) { - part_ = io.a2a.grpc.DataPart.getDefaultInstance(); + if (!(contentCase_ == 4)) { + content_ = com.google.protobuf.Value.getDefaultInstance(); } dataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.DataPart, io.a2a.grpc.DataPart.Builder, io.a2a.grpc.DataPartOrBuilder>( - (io.a2a.grpc.DataPart) part_, + com.google.protobuf.Value, com.google.protobuf.Value.Builder, com.google.protobuf.ValueOrBuilder>( + (com.google.protobuf.Value) content_, getParentForChildren(), isClean()); - part_ = null; + content_ = null; } - partCase_ = 3; + contentCase_ = 4; onChanged(); return dataBuilder_; } @@ -1215,18 +1429,18 @@ public io.a2a.grpc.DataPartOrBuilder getDataOrBuilder() { * Optional metadata associated with this part. *
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; * @return Whether the metadata field is set. */ public boolean hasMetadata() { - return ((bitField0_ & 0x00000008) != 0); + return ((bitField0_ & 0x00000010) != 0); } /** *
          * Optional metadata associated with this part.
          * 
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; * @return The metadata. */ public com.google.protobuf.Struct getMetadata() { @@ -1241,7 +1455,7 @@ public com.google.protobuf.Struct getMetadata() { * Optional metadata associated with this part. *
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ public Builder setMetadata(com.google.protobuf.Struct value) { if (metadataBuilder_ == null) { @@ -1252,7 +1466,7 @@ public Builder setMetadata(com.google.protobuf.Struct value) { } else { metadataBuilder_.setMessage(value); } - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; onChanged(); return this; } @@ -1261,7 +1475,7 @@ public Builder setMetadata(com.google.protobuf.Struct value) { * Optional metadata associated with this part. *
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ public Builder setMetadata( com.google.protobuf.Struct.Builder builderForValue) { @@ -1270,7 +1484,7 @@ public Builder setMetadata( } else { metadataBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; onChanged(); return this; } @@ -1279,11 +1493,11 @@ public Builder setMetadata( * Optional metadata associated with this part. *
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ public Builder mergeMetadata(com.google.protobuf.Struct value) { if (metadataBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && + if (((bitField0_ & 0x00000010) != 0) && metadata_ != null && metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { getMetadataBuilder().mergeFrom(value); @@ -1294,7 +1508,7 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) { metadataBuilder_.mergeFrom(value); } if (metadata_ != null) { - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; onChanged(); } return this; @@ -1304,10 +1518,10 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) { * Optional metadata associated with this part. * * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ public Builder clearMetadata() { - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000010); metadata_ = null; if (metadataBuilder_ != null) { metadataBuilder_.dispose(); @@ -1321,10 +1535,10 @@ public Builder clearMetadata() { * Optional metadata associated with this part. * * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ public com.google.protobuf.Struct.Builder getMetadataBuilder() { - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; onChanged(); return internalGetMetadataFieldBuilder().getBuilder(); } @@ -1333,7 +1547,7 @@ public com.google.protobuf.Struct.Builder getMetadataBuilder() { * Optional metadata associated with this part. * * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { if (metadataBuilder_ != null) { @@ -1348,7 +1562,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { * Optional metadata associated with this part. * * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ private com.google.protobuf.SingleFieldBuilder< com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> @@ -1364,6 +1578,195 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { return metadataBuilder_; } + private java.lang.Object filename_ = ""; + /** + *
    +     * An optional name for the file (e.g., "document.pdf").
    +     * 
    + * + * string filename = 6; + * @return The filename. + */ + public java.lang.String getFilename() { + java.lang.Object ref = filename_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + filename_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * An optional name for the file (e.g., "document.pdf").
    +     * 
    + * + * string filename = 6; + * @return The bytes for filename. + */ + public com.google.protobuf.ByteString + getFilenameBytes() { + java.lang.Object ref = filename_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + filename_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * An optional name for the file (e.g., "document.pdf").
    +     * 
    + * + * string filename = 6; + * @param value The filename to set. + * @return This builder for chaining. + */ + public Builder setFilename( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + filename_ = value; + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
    +     * An optional name for the file (e.g., "document.pdf").
    +     * 
    + * + * string filename = 6; + * @return This builder for chaining. + */ + public Builder clearFilename() { + filename_ = getDefaultInstance().getFilename(); + bitField0_ = (bitField0_ & ~0x00000020); + onChanged(); + return this; + } + /** + *
    +     * An optional name for the file (e.g., "document.pdf").
    +     * 
    + * + * string filename = 6; + * @param value The bytes for filename to set. + * @return This builder for chaining. + */ + public Builder setFilenameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + filename_ = value; + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + + private java.lang.Object mediaType_ = ""; + /** + *
    +     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +     * This field is available for all part types.
    +     * 
    + * + * string media_type = 7; + * @return The mediaType. + */ + public java.lang.String getMediaType() { + java.lang.Object ref = mediaType_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + mediaType_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +     * This field is available for all part types.
    +     * 
    + * + * string media_type = 7; + * @return The bytes for mediaType. + */ + public com.google.protobuf.ByteString + getMediaTypeBytes() { + java.lang.Object ref = mediaType_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + mediaType_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +     * This field is available for all part types.
    +     * 
    + * + * string media_type = 7; + * @param value The mediaType to set. + * @return This builder for chaining. + */ + public Builder setMediaType( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + mediaType_ = value; + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
    +     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +     * This field is available for all part types.
    +     * 
    + * + * string media_type = 7; + * @return This builder for chaining. + */ + public Builder clearMediaType() { + mediaType_ = getDefaultInstance().getMediaType(); + bitField0_ = (bitField0_ & ~0x00000040); + onChanged(); + return this; + } + /** + *
    +     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +     * This field is available for all part types.
    +     * 
    + * + * string media_type = 7; + * @param value The bytes for mediaType to set. + * @return This builder for chaining. + */ + public Builder setMediaTypeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + mediaType_ = value; + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:a2a.v1.Part) } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java index 8c8657625..0216594f2 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java @@ -41,64 +41,85 @@ public interface PartOrBuilder extends /** *
    -   * The file content, represented as either a URI or as base64-encoded bytes.
    +   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        * 
    * - * .a2a.v1.FilePart file = 2; - * @return Whether the file field is set. + * bytes raw = 2; + * @return Whether the raw field is set. */ - boolean hasFile(); + boolean hasRaw(); /** *
    -   * The file content, represented as either a URI or as base64-encoded bytes.
    +   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        * 
    * - * .a2a.v1.FilePart file = 2; - * @return The file. + * bytes raw = 2; + * @return The raw. */ - io.a2a.grpc.FilePart getFile(); + com.google.protobuf.ByteString getRaw(); + + /** + *
    +   * A URL pointing to the file's content.
    +   * 
    + * + * string url = 3; + * @return Whether the url field is set. + */ + boolean hasUrl(); + /** + *
    +   * A URL pointing to the file's content.
    +   * 
    + * + * string url = 3; + * @return The url. + */ + java.lang.String getUrl(); /** *
    -   * The file content, represented as either a URI or as base64-encoded bytes.
    +   * A URL pointing to the file's content.
        * 
    * - * .a2a.v1.FilePart file = 2; + * string url = 3; + * @return The bytes for url. */ - io.a2a.grpc.FilePartOrBuilder getFileOrBuilder(); + com.google.protobuf.ByteString + getUrlBytes(); /** *
    -   * The structured data content.
    +   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; * @return Whether the data field is set. */ boolean hasData(); /** *
    -   * The structured data content.
    +   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; * @return The data. */ - io.a2a.grpc.DataPart getData(); + com.google.protobuf.Value getData(); /** *
    -   * The structured data content.
    +   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        * 
    * - * .a2a.v1.DataPart data = 3; + * .google.protobuf.Value data = 4; */ - io.a2a.grpc.DataPartOrBuilder getDataOrBuilder(); + com.google.protobuf.ValueOrBuilder getDataOrBuilder(); /** *
        * Optional metadata associated with this part.
        * 
    * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; * @return Whether the metadata field is set. */ boolean hasMetadata(); @@ -107,7 +128,7 @@ public interface PartOrBuilder extends * Optional metadata associated with this part. * * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; * @return The metadata. */ com.google.protobuf.Struct getMetadata(); @@ -116,9 +137,51 @@ public interface PartOrBuilder extends * Optional metadata associated with this part. * * - * .google.protobuf.Struct metadata = 4; + * .google.protobuf.Struct metadata = 5; */ com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); - io.a2a.grpc.Part.PartCase getPartCase(); + /** + *
    +   * An optional name for the file (e.g., "document.pdf").
    +   * 
    + * + * string filename = 6; + * @return The filename. + */ + java.lang.String getFilename(); + /** + *
    +   * An optional name for the file (e.g., "document.pdf").
    +   * 
    + * + * string filename = 6; + * @return The bytes for filename. + */ + com.google.protobuf.ByteString + getFilenameBytes(); + + /** + *
    +   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +   * This field is available for all part types.
    +   * 
    + * + * string media_type = 7; + * @return The mediaType. + */ + java.lang.String getMediaType(); + /** + *
    +   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
    +   * This field is available for all part types.
    +   * 
    + * + * string media_type = 7; + * @return The bytes for mediaType. + */ + com.google.protobuf.ByteString + getMediaTypeBytes(); + + io.a2a.grpc.Part.ContentCase getContentCase(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java new file mode 100644 index 000000000..50f6032bb --- /dev/null +++ b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java @@ -0,0 +1,1050 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package io.a2a.grpc; + +/** + *
    + * DEPRECATED
    + * 
    + * + * Protobuf type {@code a2a.v1.PasswordOAuthFlow} + */ +@com.google.protobuf.Generated +public final class PasswordOAuthFlow extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.PasswordOAuthFlow) + PasswordOAuthFlowOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "PasswordOAuthFlow"); + } + // Use PasswordOAuthFlow.newBuilder() to construct. + private PasswordOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private PasswordOAuthFlow() { + tokenUrl_ = ""; + refreshUrl_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class); + } + + public static final int TOKEN_URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object tokenUrl_ = ""; + /** + *
    +   * The token URL to be used for this flow. This MUST be in the form of a URL.
    +   * The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string token_url = 1; + * @return The tokenUrl. + */ + @java.lang.Override + public java.lang.String getTokenUrl() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + tokenUrl_ = s; + return s; + } + } + /** + *
    +   * The token URL to be used for this flow. This MUST be in the form of a URL.
    +   * The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTokenUrlBytes() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tokenUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REFRESH_URL_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object refreshUrl_ = ""; + /** + *
    +   * The URL to be used for obtaining refresh tokens. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + @java.lang.Override + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } + } + /** + *
    +   * The URL to be used for obtaining refresh tokens. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCOPES_FIELD_NUMBER = 3; + private static final class ScopesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, java.lang.String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, tokenUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetScopes(), + ScopesDefaultEntryHolder.defaultEntry, + 3); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tokenUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); + } + for (java.util.Map.Entry entry + : internalGetScopes().getMap().entrySet()) { + com.google.protobuf.MapEntry + scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, scopes__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof io.a2a.grpc.PasswordOAuthFlow)) { + return super.equals(obj); + } + io.a2a.grpc.PasswordOAuthFlow other = (io.a2a.grpc.PasswordOAuthFlow) obj; + + if (!getTokenUrl() + .equals(other.getTokenUrl())) return false; + if (!getRefreshUrl() + .equals(other.getRefreshUrl())) return false; + if (!internalGetScopes().equals( + other.internalGetScopes())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; + hash = (53 * hash) + getTokenUrl().hashCode(); + hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; + hash = (53 * hash) + getRefreshUrl().hashCode(); + if (!internalGetScopes().getMap().isEmpty()) { + hash = (37 * hash) + SCOPES_FIELD_NUMBER; + hash = (53 * hash) + internalGetScopes().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static io.a2a.grpc.PasswordOAuthFlow parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static io.a2a.grpc.PasswordOAuthFlow parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static io.a2a.grpc.PasswordOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(io.a2a.grpc.PasswordOAuthFlow prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
    +   * DEPRECATED
    +   * 
    + * + * Protobuf type {@code a2a.v1.PasswordOAuthFlow} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.PasswordOAuthFlow) + io.a2a.grpc.PasswordOAuthFlowOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetMutableScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class); + } + + // Construct using io.a2a.grpc.PasswordOAuthFlow.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + tokenUrl_ = ""; + refreshUrl_ = ""; + internalGetMutableScopes().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + } + + @java.lang.Override + public io.a2a.grpc.PasswordOAuthFlow getDefaultInstanceForType() { + return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); + } + + @java.lang.Override + public io.a2a.grpc.PasswordOAuthFlow build() { + io.a2a.grpc.PasswordOAuthFlow result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public io.a2a.grpc.PasswordOAuthFlow buildPartial() { + io.a2a.grpc.PasswordOAuthFlow result = new io.a2a.grpc.PasswordOAuthFlow(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(io.a2a.grpc.PasswordOAuthFlow result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.tokenUrl_ = tokenUrl_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.refreshUrl_ = refreshUrl_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.scopes_ = internalGetScopes(); + result.scopes_.makeImmutable(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof io.a2a.grpc.PasswordOAuthFlow) { + return mergeFrom((io.a2a.grpc.PasswordOAuthFlow)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(io.a2a.grpc.PasswordOAuthFlow other) { + if (other == io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance()) return this; + if (!other.getTokenUrl().isEmpty()) { + tokenUrl_ = other.tokenUrl_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getRefreshUrl().isEmpty()) { + refreshUrl_ = other.refreshUrl_; + bitField0_ |= 0x00000002; + onChanged(); + } + internalGetMutableScopes().mergeFrom( + other.internalGetScopes()); + bitField0_ |= 0x00000004; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + tokenUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + refreshUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + com.google.protobuf.MapEntry + scopes__ = input.readMessage( + ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableScopes().getMutableMap().put( + scopes__.getKey(), scopes__.getValue()); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object tokenUrl_ = ""; + /** + *
    +     * The token URL to be used for this flow. This MUST be in the form of a URL.
    +     * The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string token_url = 1; + * @return The tokenUrl. + */ + public java.lang.String getTokenUrl() { + java.lang.Object ref = tokenUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + tokenUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The token URL to be used for this flow. This MUST be in the form of a URL.
    +     * The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + public com.google.protobuf.ByteString + getTokenUrlBytes() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tokenUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The token URL to be used for this flow. This MUST be in the form of a URL.
    +     * The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string token_url = 1; + * @param value The tokenUrl to set. + * @return This builder for chaining. + */ + public Builder setTokenUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + tokenUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
    +     * The token URL to be used for this flow. This MUST be in the form of a URL.
    +     * The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string token_url = 1; + * @return This builder for chaining. + */ + public Builder clearTokenUrl() { + tokenUrl_ = getDefaultInstance().getTokenUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
    +     * The token URL to be used for this flow. This MUST be in the form of a URL.
    +     * The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string token_url = 1; + * @param value The bytes for tokenUrl to set. + * @return This builder for chaining. + */ + public Builder setTokenUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + tokenUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object refreshUrl_ = ""; + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @param value The refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @return This builder for chaining. + */ + public Builder clearRefreshUrl() { + refreshUrl_ = getDefaultInstance().getRefreshUrl(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
    +     * The URL to be used for obtaining refresh tokens. This MUST be in the
    +     * form of a URL. The OAuth2 standard requires the use of TLS.
    +     * 
    + * + * string refresh_url = 2; + * @param value The bytes for refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + private com.google.protobuf.MapField + internalGetMutableScopes() { + if (scopes_ == null) { + scopes_ = com.google.protobuf.MapField.newMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + if (!scopes_.isMutable()) { + scopes_ = scopes_.copy(); + } + bitField0_ |= 0x00000004; + onChanged(); + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + public Builder clearScopes() { + bitField0_ = (bitField0_ & ~0x00000004); + internalGetMutableScopes().getMutableMap() + .clear(); + return this; + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + public Builder removeScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableScopes().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableScopes() { + bitField0_ |= 0x00000004; + return internalGetMutableScopes().getMutableMap(); + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + public Builder putScopes( + java.lang.String key, + java.lang.String value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableScopes().getMutableMap() + .put(key, value); + bitField0_ |= 0x00000004; + return this; + } + /** + *
    +     * The available scopes for the OAuth2 security scheme. A map between the
    +     * scope name and a short description for it. The map MAY be empty.
    +     * 
    + * + * map<string, string> scopes = 3; + */ + public Builder putAllScopes( + java.util.Map values) { + internalGetMutableScopes().getMutableMap() + .putAll(values); + bitField0_ |= 0x00000004; + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.PasswordOAuthFlow) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.PasswordOAuthFlow) + private static final io.a2a.grpc.PasswordOAuthFlow DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new io.a2a.grpc.PasswordOAuthFlow(); + } + + public static io.a2a.grpc.PasswordOAuthFlow getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public PasswordOAuthFlow parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public io.a2a.grpc.PasswordOAuthFlow getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java new file mode 100644 index 000000000..d319dd1e7 --- /dev/null +++ b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java @@ -0,0 +1,115 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package io.a2a.grpc; + +@com.google.protobuf.Generated +public interface PasswordOAuthFlowOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.PasswordOAuthFlow) + com.google.protobuf.MessageOrBuilder { + + /** + *
    +   * The token URL to be used for this flow. This MUST be in the form of a URL.
    +   * The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string token_url = 1; + * @return The tokenUrl. + */ + java.lang.String getTokenUrl(); + /** + *
    +   * The token URL to be used for this flow. This MUST be in the form of a URL.
    +   * The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + com.google.protobuf.ByteString + getTokenUrlBytes(); + + /** + *
    +   * The URL to be used for obtaining refresh tokens. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + java.lang.String getRefreshUrl(); + /** + *
    +   * The URL to be used for obtaining refresh tokens. This MUST be in the
    +   * form of a URL. The OAuth2 standard requires the use of TLS.
    +   * 
    + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + com.google.protobuf.ByteString + getRefreshUrlBytes(); + + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + int getScopesCount(); + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + boolean containsScopes( + java.lang.String key); + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getScopes(); + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + java.util.Map + getScopesMap(); + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue); + /** + *
    +   * The available scopes for the OAuth2 security scheme. A map between the
    +   * scope name and a short description for it. The map MAY be empty.
    +   * 
    + * + * map<string, string> scopes = 3; + */ + java.lang.String getScopesOrThrow( + java.lang.String key); +} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java index cec0fdf08..5c23d23ba 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java @@ -197,7 +197,7 @@ public java.lang.String getToken() { private io.a2a.grpc.AuthenticationInfo authentication_; /** *
    -   * Information about the authentication to sent with the notification
    +   * Authentication information required to send the notification
        * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -209,7 +209,7 @@ public boolean hasAuthentication() { } /** *
    -   * Information about the authentication to sent with the notification
    +   * Authentication information required to send the notification
        * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -221,7 +221,7 @@ public io.a2a.grpc.AuthenticationInfo getAuthentication() { } /** *
    -   * Information about the authentication to sent with the notification
    +   * Authentication information required to send the notification
        * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -904,7 +904,7 @@ public Builder setTokenBytes( io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> authenticationBuilder_; /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -915,7 +915,7 @@ public boolean hasAuthentication() { } /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -930,7 +930,7 @@ public io.a2a.grpc.AuthenticationInfo getAuthentication() { } /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -950,7 +950,7 @@ public Builder setAuthentication(io.a2a.grpc.AuthenticationInfo value) { } /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -968,7 +968,7 @@ public Builder setAuthentication( } /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -993,7 +993,7 @@ public Builder mergeAuthentication(io.a2a.grpc.AuthenticationInfo value) { } /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -1010,7 +1010,7 @@ public Builder clearAuthentication() { } /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -1022,7 +1022,7 @@ public io.a2a.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() { } /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -1037,7 +1037,7 @@ public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { } /** *
    -     * Information about the authentication to sent with the notification
    +     * Authentication information required to send the notification
          * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java index bcfaf4c2e..b65c0d5a0 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java @@ -72,7 +72,7 @@ public interface PushNotificationConfigOrBuilder extends /** *
    -   * Information about the authentication to sent with the notification
    +   * Authentication information required to send the notification
        * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -81,7 +81,7 @@ public interface PushNotificationConfigOrBuilder extends boolean hasAuthentication(); /** *
    -   * Information about the authentication to sent with the notification
    +   * Authentication information required to send the notification
        * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; @@ -90,7 +90,7 @@ public interface PushNotificationConfigOrBuilder extends io.a2a.grpc.AuthenticationInfo getAuthentication(); /** *
    -   * Information about the authentication to sent with the notification
    +   * Authentication information required to send the notification
        * 
    * * .a2a.v1.AuthenticationInfo authentication = 4; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Security.java b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java similarity index 84% rename from spec-grpc/src/main/java/io/a2a/grpc/Security.java rename to spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java index f04498f98..945b2608d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/Security.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java @@ -6,13 +6,13 @@ package io.a2a.grpc; /** - * Protobuf type {@code a2a.v1.Security} + * Protobuf type {@code a2a.v1.SecurityRequirement} */ @com.google.protobuf.Generated -public final class Security extends +public final class SecurityRequirement extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Security) - SecurityOrBuilder { + // @@protoc_insertion_point(message_implements:a2a.v1.SecurityRequirement) + SecurityRequirementOrBuilder { private static final long serialVersionUID = 0L; static { com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( @@ -21,18 +21,18 @@ public final class Security extends /* minor= */ 33, /* patch= */ 1, /* suffix= */ "", - "Security"); + "SecurityRequirement"); } - // Use Security.newBuilder() to construct. - private Security(com.google.protobuf.GeneratedMessage.Builder builder) { + // Use SecurityRequirement.newBuilder() to construct. + private SecurityRequirement(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); } - private Security() { + private SecurityRequirement() { } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Security_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -50,9 +50,9 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Security_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.Security.class, io.a2a.grpc.Security.Builder.class); + io.a2a.grpc.SecurityRequirement.class, io.a2a.grpc.SecurityRequirement.Builder.class); } public static final int SCHEMES_FIELD_NUMBER = 1; @@ -61,7 +61,7 @@ private static final class SchemesDefaultEntryHolder { java.lang.String, io.a2a.grpc.StringList> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_Security_SchemesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.MESSAGE, @@ -183,10 +183,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.a2a.grpc.Security)) { + if (!(obj instanceof io.a2a.grpc.SecurityRequirement)) { return super.equals(obj); } - io.a2a.grpc.Security other = (io.a2a.grpc.Security) obj; + io.a2a.grpc.SecurityRequirement other = (io.a2a.grpc.SecurityRequirement) obj; if (!internalGetSchemes().equals( other.internalGetSchemes())) return false; @@ -210,44 +210,44 @@ public int hashCode() { return hash; } - public static io.a2a.grpc.Security parseFrom( + public static io.a2a.grpc.SecurityRequirement parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.Security parseFrom( + public static io.a2a.grpc.SecurityRequirement parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.Security parseFrom( + public static io.a2a.grpc.SecurityRequirement parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.Security parseFrom( + public static io.a2a.grpc.SecurityRequirement parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.Security parseFrom(byte[] data) + public static io.a2a.grpc.SecurityRequirement parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.Security parseFrom( + public static io.a2a.grpc.SecurityRequirement parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.Security parseFrom(java.io.InputStream input) + public static io.a2a.grpc.SecurityRequirement parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.Security parseFrom( + public static io.a2a.grpc.SecurityRequirement parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -255,26 +255,26 @@ public static io.a2a.grpc.Security parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.Security parseDelimitedFrom(java.io.InputStream input) + public static io.a2a.grpc.SecurityRequirement parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.a2a.grpc.Security parseDelimitedFrom( + public static io.a2a.grpc.SecurityRequirement parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.Security parseFrom( + public static io.a2a.grpc.SecurityRequirement parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.Security parseFrom( + public static io.a2a.grpc.SecurityRequirement parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -287,7 +287,7 @@ public static io.a2a.grpc.Security parseFrom( public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.a2a.grpc.Security prototype) { + public static Builder newBuilder(io.a2a.grpc.SecurityRequirement prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -303,15 +303,15 @@ protected Builder newBuilderForType( return builder; } /** - * Protobuf type {@code a2a.v1.Security} + * Protobuf type {@code a2a.v1.SecurityRequirement} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Security) - io.a2a.grpc.SecurityOrBuilder { + // @@protoc_insertion_point(builder_implements:a2a.v1.SecurityRequirement) + io.a2a.grpc.SecurityRequirementOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Security_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -339,12 +339,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Security_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.Security.class, io.a2a.grpc.Security.Builder.class); + io.a2a.grpc.SecurityRequirement.class, io.a2a.grpc.SecurityRequirement.Builder.class); } - // Construct using io.a2a.grpc.Security.newBuilder() + // Construct using io.a2a.grpc.SecurityRequirement.newBuilder() private Builder() { } @@ -365,17 +365,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Security_descriptor; + return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; } @java.lang.Override - public io.a2a.grpc.Security getDefaultInstanceForType() { - return io.a2a.grpc.Security.getDefaultInstance(); + public io.a2a.grpc.SecurityRequirement getDefaultInstanceForType() { + return io.a2a.grpc.SecurityRequirement.getDefaultInstance(); } @java.lang.Override - public io.a2a.grpc.Security build() { - io.a2a.grpc.Security result = buildPartial(); + public io.a2a.grpc.SecurityRequirement build() { + io.a2a.grpc.SecurityRequirement result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -383,14 +383,14 @@ public io.a2a.grpc.Security build() { } @java.lang.Override - public io.a2a.grpc.Security buildPartial() { - io.a2a.grpc.Security result = new io.a2a.grpc.Security(this); + public io.a2a.grpc.SecurityRequirement buildPartial() { + io.a2a.grpc.SecurityRequirement result = new io.a2a.grpc.SecurityRequirement(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.a2a.grpc.Security result) { + private void buildPartial0(io.a2a.grpc.SecurityRequirement result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { result.schemes_ = internalGetSchemes().build(SchemesDefaultEntryHolder.defaultEntry); @@ -399,16 +399,16 @@ private void buildPartial0(io.a2a.grpc.Security result) { @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.Security) { - return mergeFrom((io.a2a.grpc.Security)other); + if (other instanceof io.a2a.grpc.SecurityRequirement) { + return mergeFrom((io.a2a.grpc.SecurityRequirement)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.a2a.grpc.Security other) { - if (other == io.a2a.grpc.Security.getDefaultInstance()) return this; + public Builder mergeFrom(io.a2a.grpc.SecurityRequirement other) { + if (other == io.a2a.grpc.SecurityRequirement.getDefaultInstance()) return this; internalGetMutableSchemes().mergeFrom( other.internalGetSchemes()); bitField0_ |= 0x00000001; @@ -619,23 +619,23 @@ public io.a2a.grpc.StringList.Builder putSchemesBuilderIfAbsent( return (io.a2a.grpc.StringList.Builder) entry; } - // @@protoc_insertion_point(builder_scope:a2a.v1.Security) + // @@protoc_insertion_point(builder_scope:a2a.v1.SecurityRequirement) } - // @@protoc_insertion_point(class_scope:a2a.v1.Security) - private static final io.a2a.grpc.Security DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:a2a.v1.SecurityRequirement) + private static final io.a2a.grpc.SecurityRequirement DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.a2a.grpc.Security(); + DEFAULT_INSTANCE = new io.a2a.grpc.SecurityRequirement(); } - public static io.a2a.grpc.Security getDefaultInstance() { + public static io.a2a.grpc.SecurityRequirement getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { @java.lang.Override - public Security parsePartialFrom( + public SecurityRequirement parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { @@ -654,17 +654,17 @@ public Security parsePartialFrom( } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } @java.lang.Override - public com.google.protobuf.Parser getParserForType() { + public com.google.protobuf.Parser getParserForType() { return PARSER; } @java.lang.Override - public io.a2a.grpc.Security getDefaultInstanceForType() { + public io.a2a.grpc.SecurityRequirement getDefaultInstanceForType() { return DEFAULT_INSTANCE; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java similarity index 94% rename from spec-grpc/src/main/java/io/a2a/grpc/SecurityOrBuilder.java rename to spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java index cb1b2372f..14b23d252 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java @@ -6,8 +6,8 @@ package io.a2a.grpc; @com.google.protobuf.Generated -public interface SecurityOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Security) +public interface SecurityRequirementOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.SecurityRequirement) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java index 6bec1fb51..57374039f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java @@ -179,7 +179,7 @@ public int getHistoryLength() { private boolean blocking_ = false; /** *
    -   * If true, the operation waits until the task reaches a terminal state before returning. Default is false.
    +   * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
        * 
    * * bool blocking = 4; @@ -977,7 +977,7 @@ public Builder clearHistoryLength() { private boolean blocking_ ; /** *
    -     * If true, the operation waits until the task reaches a terminal state before returning. Default is false.
    +     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
          * 
    * * bool blocking = 4; @@ -989,7 +989,7 @@ public boolean getBlocking() { } /** *
    -     * If true, the operation waits until the task reaches a terminal state before returning. Default is false.
    +     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
          * 
    * * bool blocking = 4; @@ -1005,7 +1005,7 @@ public Builder setBlocking(boolean value) { } /** *
    -     * If true, the operation waits until the task reaches a terminal state before returning. Default is false.
    +     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
          * 
    * * bool blocking = 4; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java index 2fed6a6af..a9e9fc401 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java @@ -105,7 +105,7 @@ public interface SendMessageConfigurationOrBuilder extends /** *
    -   * If true, the operation waits until the task reaches a terminal state before returning. Default is false.
    +   * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
        * 
    * * bool blocking = 4; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java index cdef789c1..82a95620a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java @@ -33,7 +33,7 @@ private SubscribeToTaskRequest(com.google.protobuf.GeneratedMessage.Builder b } private SubscribeToTaskRequest() { tenant_ = ""; - name_ = ""; + id_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -96,49 +96,47 @@ public java.lang.String getTenant() { } } - public static final int NAME_FIELD_NUMBER = 1; + public static final int ID_FIELD_NUMBER = 1; @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; + private volatile java.lang.Object id_ = ""; /** *
    -   * The resource name of the task to subscribe to.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task to subscribe to.
        * 
    * - * string name = 1; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getId() { + java.lang.Object ref = id_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + id_ = s; return s; } } /** *
    -   * The resource name of the task to subscribe to.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task to subscribe to.
        * 
    * - * string name = 1; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ @java.lang.Override public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getIdBytes() { + java.lang.Object ref = id_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + id_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -159,8 +157,8 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); @@ -174,8 +172,8 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); @@ -197,8 +195,8 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (!getName() - .equals(other.getName())) return false; + if (!getId() + .equals(other.getId())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -212,8 +210,8 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -350,7 +348,7 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - name_ = ""; + id_ = ""; return this; } @@ -388,7 +386,7 @@ private void buildPartial0(io.a2a.grpc.SubscribeToTaskRequest result) { result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.name_ = name_; + result.id_ = id_; } } @@ -409,8 +407,8 @@ public Builder mergeFrom(io.a2a.grpc.SubscribeToTaskRequest other) { bitField0_ |= 0x00000001; onChanged(); } - if (!other.getName().isEmpty()) { - name_ = other.name_; + if (!other.getId().isEmpty()) { + id_ = other.id_; bitField0_ |= 0x00000002; onChanged(); } @@ -441,7 +439,7 @@ public Builder mergeFrom( done = true; break; case 10: { - name_ = input.readStringRequireUtf8(); + id_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; } // case 10 @@ -559,23 +557,22 @@ public Builder setTenantBytes( return this; } - private java.lang.Object name_ = ""; + private java.lang.Object id_ = ""; /** *
    -     * The resource name of the task to subscribe to.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to subscribe to.
          * 
    * - * string name = 1; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getId() { + java.lang.Object ref = id_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + id_ = s; return s; } else { return (java.lang.String) ref; @@ -583,21 +580,20 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the task to subscribe to.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to subscribe to.
          * 
    * - * string name = 1; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getIdBytes() { + java.lang.Object ref = id_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + id_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -605,52 +601,49 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the task to subscribe to.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to subscribe to.
          * 
    * - * string name = 1; - * @param value The name to set. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The id to set. * @return This builder for chaining. */ - public Builder setName( + public Builder setId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - name_ = value; + id_ = value; bitField0_ |= 0x00000002; onChanged(); return this; } /** *
    -     * The resource name of the task to subscribe to.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to subscribe to.
          * 
    * - * string name = 1; + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); + public Builder clearId() { + id_ = getDefaultInstance().getId(); bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } /** *
    -     * The resource name of the task to subscribe to.
    -     * Format: tasks/{task_id}
    +     * The resource id of the task to subscribe to.
          * 
    * - * string name = 1; - * @param value The bytes for name to set. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for id to set. * @return This builder for chaining. */ - public Builder setNameBytes( + public Builder setIdBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - name_ = value; + id_ = value; bitField0_ |= 0x00000002; onChanged(); return this; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java index 0d4a4fda9..39f287b30 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java @@ -32,23 +32,21 @@ public interface SubscribeToTaskRequestOrBuilder extends /** *
    -   * The resource name of the task to subscribe to.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task to subscribe to.
        * 
    * - * string name = 1; - * @return The name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. */ - java.lang.String getName(); + java.lang.String getId(); /** *
    -   * The resource name of the task to subscribe to.
    -   * Format: tasks/{task_id}
    +   * The resource id of the task to subscribe to.
        * 
    * - * string name = 1; - * @return The bytes for name. + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. */ com.google.protobuf.ByteString - getNameBytes(); + getIdBytes(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java index e33fb5cf4..745594565 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java @@ -34,7 +34,9 @@ private TaskPushNotificationConfig(com.google.protobuf.GeneratedMessage.Builder< super(builder); } private TaskPushNotificationConfig() { - name_ = ""; + tenant_ = ""; + id_ = ""; + taskId_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -51,49 +53,141 @@ private TaskPushNotificationConfig() { } private int bitField0_; - public static final int NAME_FIELD_NUMBER = 1; + public static final int TENANT_FIELD_NUMBER = 4; @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; + private volatile java.lang.Object tenant_ = ""; /** *
    -   * The resource name of the config.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * Optional tenant
        * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. + * string tenant = 4; + * @return The tenant. */ @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getTenant() { + java.lang.Object ref = tenant_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + tenant_ = s; return s; } } /** *
    -   * The resource name of the config.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * Optional tenant
        * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. + * string tenant = 4; + * @return The bytes for tenant. */ @java.lang.Override public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getTenantBytes() { + java.lang.Object ref = tenant_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + tenant_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object id_ = ""; + /** + *
    +   * The id of the config.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + @java.lang.Override + public java.lang.String getId() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + *
    +   * The id of the config.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TASK_ID_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object taskId_ = ""; + /** + *
    +   * The id of the task this config is associated with.
    +   * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. + */ + @java.lang.Override + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + taskId_ = s; + return s; + } + } + /** + *
    +   * The id of the task this config is associated with.
    +   * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTaskIdBytes() { + java.lang.Object ref = taskId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + taskId_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -152,12 +246,18 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); } if (((bitField0_ & 0x00000001) != 0)) { output.writeMessage(2, getPushNotificationConfig()); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); + } getUnknownFields().writeTo(output); } @@ -167,13 +267,19 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream .computeMessageSize(2, getPushNotificationConfig()); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -189,8 +295,12 @@ public boolean equals(final java.lang.Object obj) { } io.a2a.grpc.TaskPushNotificationConfig other = (io.a2a.grpc.TaskPushNotificationConfig) obj; - if (!getName() - .equals(other.getName())) return false; + if (!getTenant() + .equals(other.getTenant())) return false; + if (!getId() + .equals(other.getId())) return false; + if (!getTaskId() + .equals(other.getTaskId())) return false; if (hasPushNotificationConfig() != other.hasPushNotificationConfig()) return false; if (hasPushNotificationConfig()) { if (!getPushNotificationConfig() @@ -207,8 +317,12 @@ public int hashCode() { } int hash = 41; hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + TENANT_FIELD_NUMBER; + hash = (53 * hash) + getTenant().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); + hash = (37 * hash) + TASK_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskId().hashCode(); if (hasPushNotificationConfig()) { hash = (37 * hash) + PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER; hash = (53 * hash) + getPushNotificationConfig().hashCode(); @@ -356,7 +470,9 @@ private void maybeForceBuilderInitialization() { public Builder clear() { super.clear(); bitField0_ = 0; - name_ = ""; + tenant_ = ""; + id_ = ""; + taskId_ = ""; pushNotificationConfig_ = null; if (pushNotificationConfigBuilder_ != null) { pushNotificationConfigBuilder_.dispose(); @@ -396,10 +512,16 @@ public io.a2a.grpc.TaskPushNotificationConfig buildPartial() { private void buildPartial0(io.a2a.grpc.TaskPushNotificationConfig result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { - result.name_ = name_; + result.tenant_ = tenant_; } - int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000002) != 0)) { + result.id_ = id_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.taskId_ = taskId_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000008) != 0)) { result.pushNotificationConfig_ = pushNotificationConfigBuilder_ == null ? pushNotificationConfig_ : pushNotificationConfigBuilder_.build(); @@ -420,11 +542,21 @@ public Builder mergeFrom(com.google.protobuf.Message other) { public Builder mergeFrom(io.a2a.grpc.TaskPushNotificationConfig other) { if (other == io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance()) return this; - if (!other.getName().isEmpty()) { - name_ = other.name_; + if (!other.getTenant().isEmpty()) { + tenant_ = other.tenant_; bitField0_ |= 0x00000001; onChanged(); } + if (!other.getId().isEmpty()) { + id_ = other.id_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getTaskId().isEmpty()) { + taskId_ = other.taskId_; + bitField0_ |= 0x00000004; + onChanged(); + } if (other.hasPushNotificationConfig()) { mergePushNotificationConfig(other.getPushNotificationConfig()); } @@ -455,17 +587,27 @@ public Builder mergeFrom( done = true; break; case 10: { - name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; break; } // case 10 case 18: { input.readMessage( internalGetPushNotificationConfigFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000008; break; } // case 18 + case 26: { + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 34: { + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -483,23 +625,22 @@ public Builder mergeFrom( } private int bitField0_; - private java.lang.Object name_ = ""; + private java.lang.Object tenant_ = ""; /** *
    -     * The resource name of the config.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * Optional tenant
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. + * string tenant = 4; + * @return The tenant. */ - public java.lang.String getName() { - java.lang.Object ref = name_; + public java.lang.String getTenant() { + java.lang.Object ref = tenant_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); - name_ = s; + tenant_ = s; return s; } else { return (java.lang.String) ref; @@ -507,21 +648,20 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the config.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * Optional tenant
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. + * string tenant = 4; + * @return The bytes for tenant. */ public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; + getTenantBytes() { + java.lang.Object ref = tenant_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); - name_ = b; + tenant_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; @@ -529,57 +669,238 @@ public java.lang.String getName() { } /** *
    -     * The resource name of the config.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * Optional tenant
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The name to set. + * string tenant = 4; + * @param value The tenant to set. * @return This builder for chaining. */ - public Builder setName( + public Builder setTenant( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - name_ = value; + tenant_ = value; bitField0_ |= 0x00000001; onChanged(); return this; } /** *
    -     * The resource name of the config.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * Optional tenant
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * string tenant = 4; * @return This builder for chaining. */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); + public Builder clearTenant() { + tenant_ = getDefaultInstance().getTenant(); bitField0_ = (bitField0_ & ~0x00000001); onChanged(); return this; } /** *
    -     * The resource name of the config.
    -     * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +     * Optional tenant
          * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for name to set. + * string tenant = 4; + * @param value The bytes for tenant to set. * @return This builder for chaining. */ - public Builder setNameBytes( + public Builder setTenantBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); - name_ = value; + tenant_ = value; bitField0_ |= 0x00000001; onChanged(); return this; } + private java.lang.Object id_ = ""; + /** + *
    +     * The id of the config.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + public java.lang.String getId() { + java.lang.Object ref = id_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The id of the config.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The id of the config.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + id_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
    +     * The id of the config.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearId() { + id_ = getDefaultInstance().getId(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
    +     * The id of the config.
    +     * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + id_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object taskId_ = ""; + /** + *
    +     * The id of the task this config is associated with.
    +     * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. + */ + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + taskId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
    +     * The id of the task this config is associated with.
    +     * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. + */ + public com.google.protobuf.ByteString + getTaskIdBytes() { + java.lang.Object ref = taskId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
    +     * The id of the task this config is associated with.
    +     * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @param value The taskId to set. + * @return This builder for chaining. + */ + public Builder setTaskId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + taskId_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
    +     * The id of the task this config is associated with.
    +     * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearTaskId() { + taskId_ = getDefaultInstance().getTaskId(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
    +     * The id of the task this config is associated with.
    +     * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for taskId to set. + * @return This builder for chaining. + */ + public Builder setTaskIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + taskId_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> pushNotificationConfigBuilder_; @@ -592,7 +913,7 @@ public Builder setNameBytes( * @return Whether the pushNotificationConfig field is set. */ public boolean hasPushNotificationConfig() { - return ((bitField0_ & 0x00000002) != 0); + return ((bitField0_ & 0x00000008) != 0); } /** *
    @@ -625,7 +946,7 @@ public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig valu
           } else {
             pushNotificationConfigBuilder_.setMessage(value);
           }
    -      bitField0_ |= 0x00000002;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return this;
         }
    @@ -643,7 +964,7 @@ public Builder setPushNotificationConfig(
           } else {
             pushNotificationConfigBuilder_.setMessage(builderForValue.build());
           }
    -      bitField0_ |= 0x00000002;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return this;
         }
    @@ -656,7 +977,7 @@ public Builder setPushNotificationConfig(
          */
         public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) {
           if (pushNotificationConfigBuilder_ == null) {
    -        if (((bitField0_ & 0x00000002) != 0) &&
    +        if (((bitField0_ & 0x00000008) != 0) &&
               pushNotificationConfig_ != null &&
               pushNotificationConfig_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) {
               getPushNotificationConfigBuilder().mergeFrom(value);
    @@ -667,7 +988,7 @@ public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig va
             pushNotificationConfigBuilder_.mergeFrom(value);
           }
           if (pushNotificationConfig_ != null) {
    -        bitField0_ |= 0x00000002;
    +        bitField0_ |= 0x00000008;
             onChanged();
           }
           return this;
    @@ -680,7 +1001,7 @@ public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig va
          * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED];
          */
         public Builder clearPushNotificationConfig() {
    -      bitField0_ = (bitField0_ & ~0x00000002);
    +      bitField0_ = (bitField0_ & ~0x00000008);
           pushNotificationConfig_ = null;
           if (pushNotificationConfigBuilder_ != null) {
             pushNotificationConfigBuilder_.dispose();
    @@ -697,7 +1018,7 @@ public Builder clearPushNotificationConfig() {
          * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED];
          */
         public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuilder() {
    -      bitField0_ |= 0x00000002;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return internalGetPushNotificationConfigFieldBuilder().getBuilder();
         }
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java
    index 741c9b4cf..2da32ae41 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java
    @@ -12,25 +12,63 @@ public interface TaskPushNotificationConfigOrBuilder extends
     
       /**
        * 
    -   * The resource name of the config.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * Optional tenant
        * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. + * string tenant = 4; + * @return The tenant. */ - java.lang.String getName(); + java.lang.String getTenant(); /** *
    -   * The resource name of the config.
    -   * Format: tasks/{task_id}/pushNotificationConfigs/{config_id}
    +   * Optional tenant
        * 
    * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. + * string tenant = 4; + * @return The bytes for tenant. */ com.google.protobuf.ByteString - getNameBytes(); + getTenantBytes(); + + /** + *
    +   * The id of the config.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The id. + */ + java.lang.String getId(); + /** + *
    +   * The id of the config.
    +   * 
    + * + * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); + + /** + *
    +   * The id of the task this config is associated with.
    +   * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The taskId. + */ + java.lang.String getTaskId(); + /** + *
    +   * The id of the task this config is associated with.
    +   * 
    + * + * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for taskId. + */ + com.google.protobuf.ByteString + getTaskIdBytes(); /** *
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java
    index c5f4bccd6..9fc6b6441 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java
    @@ -58,13 +58,13 @@ public enum TaskState
       TASK_STATE_FAILED(4),
       /**
        * 
    -   * Represents the status a task was cancelled before it finished.
    +   * Represents the status a task was canceled before it finished.
        * This is a terminal state.
        * 
    * - * TASK_STATE_CANCELLED = 5; + * TASK_STATE_CANCELED = 5; */ - TASK_STATE_CANCELLED(5), + TASK_STATE_CANCELED(5), /** *
        * Represents the status that the task requires information to complete.
    @@ -87,8 +87,7 @@ public enum TaskState
       /**
        * 
        * Represents the state that some authentication is needed from the upstream
    -   * client. Authentication is expected to come out-of-band thus this is not
    -   * an interrupted or terminal state.
    +   * client. This is an interrupted state. Authentication is expected to come out-of-band.
        * 
    * * TASK_STATE_AUTH_REQUIRED = 8; @@ -148,13 +147,13 @@ public enum TaskState public static final int TASK_STATE_FAILED_VALUE = 4; /** *
    -   * Represents the status a task was cancelled before it finished.
    +   * Represents the status a task was canceled before it finished.
        * This is a terminal state.
        * 
    * - * TASK_STATE_CANCELLED = 5; + * TASK_STATE_CANCELED = 5; */ - public static final int TASK_STATE_CANCELLED_VALUE = 5; + public static final int TASK_STATE_CANCELED_VALUE = 5; /** *
        * Represents the status that the task requires information to complete.
    @@ -177,8 +176,7 @@ public enum TaskState
       /**
        * 
        * Represents the state that some authentication is needed from the upstream
    -   * client. Authentication is expected to come out-of-band thus this is not
    -   * an interrupted or terminal state.
    +   * client. This is an interrupted state. Authentication is expected to come out-of-band.
        * 
    * * TASK_STATE_AUTH_REQUIRED = 8; @@ -215,7 +213,7 @@ public static TaskState forNumber(int value) { case 2: return TASK_STATE_WORKING; case 3: return TASK_STATE_COMPLETED; case 4: return TASK_STATE_FAILED; - case 5: return TASK_STATE_CANCELLED; + case 5: return TASK_STATE_CANCELED; case 6: return TASK_STATE_INPUT_REQUIRED; case 7: return TASK_STATE_REJECTED; case 8: return TASK_STATE_AUTH_REQUIRED; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java index 38b6b4768..06cb104e0 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java @@ -184,21 +184,6 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; } - public static final int FINAL_FIELD_NUMBER = 4; - private boolean final_ = false; - /** - *
    -   * If true, this is the final event in the stream for this interaction.
    -   * 
    - * - * bool final = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The final. - */ - @java.lang.Override - public boolean getFinal() { - return final_; - } - public static final int METADATA_FIELD_NUMBER = 5; private com.google.protobuf.Struct metadata_; /** @@ -260,9 +245,6 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (((bitField0_ & 0x00000001) != 0)) { output.writeMessage(3, getStatus()); } - if (final_ != false) { - output.writeBool(4, final_); - } if (((bitField0_ & 0x00000002) != 0)) { output.writeMessage(5, getMetadata()); } @@ -285,10 +267,6 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(3, getStatus()); } - if (final_ != false) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(4, final_); - } if (((bitField0_ & 0x00000002) != 0)) { size += com.google.protobuf.CodedOutputStream .computeMessageSize(5, getMetadata()); @@ -317,8 +295,6 @@ public boolean equals(final java.lang.Object obj) { if (!getStatus() .equals(other.getStatus())) return false; } - if (getFinal() - != other.getFinal()) return false; if (hasMetadata() != other.hasMetadata()) return false; if (hasMetadata()) { if (!getMetadata() @@ -343,9 +319,6 @@ public int hashCode() { hash = (37 * hash) + STATUS_FIELD_NUMBER; hash = (53 * hash) + getStatus().hashCode(); } - hash = (37 * hash) + FINAL_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getFinal()); if (hasMetadata()) { hash = (37 * hash) + METADATA_FIELD_NUMBER; hash = (53 * hash) + getMetadata().hashCode(); @@ -501,7 +474,6 @@ public Builder clear() { statusBuilder_.dispose(); statusBuilder_ = null; } - final_ = false; metadata_ = null; if (metadataBuilder_ != null) { metadataBuilder_.dispose(); @@ -554,9 +526,6 @@ private void buildPartial0(io.a2a.grpc.TaskStatusUpdateEvent result) { to_bitField0_ |= 0x00000001; } if (((from_bitField0_ & 0x00000008) != 0)) { - result.final_ = final_; - } - if (((from_bitField0_ & 0x00000010) != 0)) { result.metadata_ = metadataBuilder_ == null ? metadata_ : metadataBuilder_.build(); @@ -590,9 +559,6 @@ public Builder mergeFrom(io.a2a.grpc.TaskStatusUpdateEvent other) { if (other.hasStatus()) { mergeStatus(other.getStatus()); } - if (other.getFinal() != false) { - setFinal(other.getFinal()); - } if (other.hasMetadata()) { mergeMetadata(other.getMetadata()); } @@ -639,16 +605,11 @@ public Builder mergeFrom( bitField0_ |= 0x00000004; break; } // case 26 - case 32: { - final_ = input.readBool(); - bitField0_ |= 0x00000008; - break; - } // case 32 case 42: { input.readMessage( internalGetMetadataFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x00000010; + bitField0_ |= 0x00000008; break; } // case 42 default: { @@ -1009,50 +970,6 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { return statusBuilder_; } - private boolean final_ ; - /** - *
    -     * If true, this is the final event in the stream for this interaction.
    -     * 
    - * - * bool final = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The final. - */ - @java.lang.Override - public boolean getFinal() { - return final_; - } - /** - *
    -     * If true, this is the final event in the stream for this interaction.
    -     * 
    - * - * bool final = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param value The final to set. - * @return This builder for chaining. - */ - public Builder setFinal(boolean value) { - - final_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
    -     * If true, this is the final event in the stream for this interaction.
    -     * 
    - * - * bool final = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearFinal() { - bitField0_ = (bitField0_ & ~0x00000008); - final_ = false; - onChanged(); - return this; - } - private com.google.protobuf.Struct metadata_; private com.google.protobuf.SingleFieldBuilder< com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; @@ -1065,7 +982,7 @@ public Builder clearFinal() { * @return Whether the metadata field is set. */ public boolean hasMetadata() { - return ((bitField0_ & 0x00000010) != 0); + return ((bitField0_ & 0x00000008) != 0); } /** *
    @@ -1098,7 +1015,7 @@ public Builder setMetadata(com.google.protobuf.Struct value) {
           } else {
             metadataBuilder_.setMessage(value);
           }
    -      bitField0_ |= 0x00000010;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return this;
         }
    @@ -1116,7 +1033,7 @@ public Builder setMetadata(
           } else {
             metadataBuilder_.setMessage(builderForValue.build());
           }
    -      bitField0_ |= 0x00000010;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return this;
         }
    @@ -1129,7 +1046,7 @@ public Builder setMetadata(
          */
         public Builder mergeMetadata(com.google.protobuf.Struct value) {
           if (metadataBuilder_ == null) {
    -        if (((bitField0_ & 0x00000010) != 0) &&
    +        if (((bitField0_ & 0x00000008) != 0) &&
               metadata_ != null &&
               metadata_ != com.google.protobuf.Struct.getDefaultInstance()) {
               getMetadataBuilder().mergeFrom(value);
    @@ -1140,7 +1057,7 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) {
             metadataBuilder_.mergeFrom(value);
           }
           if (metadata_ != null) {
    -        bitField0_ |= 0x00000010;
    +        bitField0_ |= 0x00000008;
             onChanged();
           }
           return this;
    @@ -1153,7 +1070,7 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) {
          * .google.protobuf.Struct metadata = 5;
          */
         public Builder clearMetadata() {
    -      bitField0_ = (bitField0_ & ~0x00000010);
    +      bitField0_ = (bitField0_ & ~0x00000008);
           metadata_ = null;
           if (metadataBuilder_ != null) {
             metadataBuilder_.dispose();
    @@ -1170,7 +1087,7 @@ public Builder clearMetadata() {
          * .google.protobuf.Struct metadata = 5;
          */
         public com.google.protobuf.Struct.Builder getMetadataBuilder() {
    -      bitField0_ |= 0x00000010;
    +      bitField0_ |= 0x00000008;
           onChanged();
           return internalGetMetadataFieldBuilder().getBuilder();
         }
    diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java
    index 6e086c3f3..225000e2a 100644
    --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java
    +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java
    @@ -77,16 +77,6 @@ public interface TaskStatusUpdateEventOrBuilder extends
        */
       io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder();
     
    -  /**
    -   * 
    -   * If true, this is the final event in the stream for this interaction.
    -   * 
    - * - * bool final = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The final. - */ - boolean getFinal(); - /** *
        * Optional metadata to associate with the task update.
    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 0acdc5d3e..45063b3ed 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
    @@ -173,13 +173,14 @@ default Map structToMap(Struct struct) {
         /**
          * Converts a Java Object to protobuf Value.
          * 

    - * Supports String, Number, Boolean, Map, and List types. - * Used internally for struct conversion. + * Supports String, Number, Boolean, Map, List types, and null. + * Used for struct conversion and arbitrary JSON data. * * @param value the Java object * @return protobuf Value */ - private Value objectToValue(Object value) { + @SuppressWarnings("unchecked") + default Value objectToValue(Object value) { Value.Builder valueBuilder = Value.newBuilder(); if (value instanceof String) { valueBuilder.setStringValue((String) value); @@ -198,13 +199,21 @@ private Value objectToValue(Object value) { /** * Converts protobuf Value to Java Object. *

    - * Returns appropriate Java type based on Value's kind. - * Used internally for struct conversion. + * Returns appropriate Java type based on Value's kind: + *

      + *
    • STRUCT_VALUE -> {@code Map}
    • + *
    • LIST_VALUE -> {@code List} + *
    • BOOL_VALUE -> {@code Boolean}
    • + *
    • NUMBER_VALUE -> {@code Double}
    • + *
    • STRING_VALUE -> {@code String}
    • + *
    • NULL_VALUE -> {@code null}
    • + * + * Used for struct conversion and arbitrary JSON data. * * @param value the protobuf Value * @return Java object (String, Double, Boolean, Map, List, or null) */ - private Object valueToObject(Value value) { + default Object valueToObject(Value value) { switch (value.getKindCase()) { case STRUCT_VALUE: return structToMap(value.getStructValue()); @@ -227,12 +236,12 @@ private Object valueToObject(Value value) { /** * Converts Java List to protobuf ListValue. *

      - * Used internally for struct conversion. + * Used for struct conversion and arbitrary JSON data. * * @param list the Java list * @return protobuf ListValue */ - private com.google.protobuf.ListValue listToListValue(List list) { + default com.google.protobuf.ListValue listToListValue(List list) { com.google.protobuf.ListValue.Builder listValueBuilder = com.google.protobuf.ListValue.newBuilder(); if (list != null) { list.forEach(o -> listValueBuilder.addValues(objectToValue(o))); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java index 383afb3a1..184a8c346 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java @@ -2,6 +2,7 @@ import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; /** * Mapper between {@link io.a2a.spec.AgentInterface} and {@link io.a2a.grpc.AgentInterface}. diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java index 8d6db42ea..1e50f6d3d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java @@ -1,11 +1,15 @@ package io.a2a.grpc.mapper; + import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** * Mapper between {@link io.a2a.spec.AuthenticationInfo} and {@link io.a2a.grpc.AuthenticationInfo}. + *

      + * Maps between domain AuthenticationInfo (schemes as List of String) and proto AuthenticationInfo (scheme as String). + * The proto scheme field is mapped to/from the first element of the domain schemes list. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) @@ -13,8 +17,18 @@ public interface AuthenticationInfoMapper { AuthenticationInfoMapper INSTANCE = A2AMappers.getMapper(AuthenticationInfoMapper.class); + /** + * Converts domain AuthenticationInfo to proto AuthenticationInfo. + * Takes the first scheme from the schemes list. + */ @Mapping(target = "credentials", source = "credentials", conditionExpression = "java(domain.credentials() != null)") io.a2a.grpc.AuthenticationInfo toProto(io.a2a.spec.AuthenticationInfo domain); + /** + * Converts proto AuthenticationInfo to domain AuthenticationInfo. + * Wraps the single scheme in a list. + */ io.a2a.spec.AuthenticationInfo fromProto(io.a2a.grpc.AuthenticationInfo proto); + + } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java index 428ea2846..ed15e7500 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java @@ -8,17 +8,6 @@ /** * MapStruct mapper for CreateTaskPushNotificationConfigRequest → TaskPushNotificationConfig. - *

      - * Handles resource name parsing and ID override logic for creating push notification configs. - *

      - * Resource Name Handling: - *

        - *
      • Extracts taskId from parent resource name (format: "tasks/{task_id}")
      • - *
      • Fallback: Extracts from config.name if parent is blank
      • - *
      • Overrides PushNotificationConfig.id with config_id from request
      • - *
      - *

      - * Compile-Time Safety: If the proto changes fields, MapStruct will fail to compile. */ @Mapper(config = A2AProtoMapperConfig.class, uses = {PushNotificationConfigMapper.class}) public interface CreateTaskPushNotificationConfigMapper { @@ -27,87 +16,50 @@ public interface CreateTaskPushNotificationConfigMapper { /** * Converts CreateTaskPushNotificationConfigRequest to domain TaskPushNotificationConfig. - *

      - * Extracts taskId from parent resource name and maps PushNotificationConfig with - * ID override from config_id field. - * The tenant field is set to null as it's not present in the protobuf definition. * * @param request the protobuf CreateTaskPushNotificationConfigRequest * @return domain TaskPushNotificationConfig */ - @Mapping(target = "taskId", expression = "java(extractTaskId(request))") + @Mapping(target = "taskId", source = "taskId") @Mapping(target = "pushNotificationConfig", expression = "java(mapPushNotificationConfigWithId(request))") + @Mapping(target = "tenant", source = "tenant") TaskPushNotificationConfig fromProto(CreateTaskPushNotificationConfigRequest request); /** - * Converts CreateTaskPushNotificationConfigRequest to domain TaskPushNotificationConfig. - *

      - * Extracts taskId from parent resource name and maps PushNotificationConfig with - * ID override from config_id field. + * Converts domain TaskPushNotificationConfig to CreateTaskPushNotificationConfigRequest. * - * @param config the domainTaskPushNotificationConfig + * @param config the domain TaskPushNotificationConfig * @return proto CreateTaskPushNotificationConfigRequest */ - @Mapping(target = "parent", expression = "java(ResourceNameParser.defineTaskName(config.taskId()))") + @Mapping(target = "taskId", source = "taskId") @Mapping(target = "configId", expression = "java(extractConfigId(config))") - @Mapping(target = "config", expression = "java(mapPushNotificationConfig(config))") + @Mapping(target = "config", source = "pushNotificationConfig") + @Mapping(target = "tenant", source = "tenant") CreateTaskPushNotificationConfigRequest toProto(TaskPushNotificationConfig config); /** - * Extracts the task ID from the parent resource name. - *

      - * Format: "tasks/{task_id}" - * Fallback: If parent is blank, extracts from config.name instead. - * - * @param request the protobuf CreateTaskPushNotificationConfigRequest - * @return the extracted task ID - */ - default String extractTaskId(CreateTaskPushNotificationConfigRequest request) { - String parent = request.getParent(); - - if (parent == null || parent.isBlank()) { - // Fallback: extract from config.name - return ResourceNameParser.extractTaskId(request.getConfig().getName()); - } - - // Extract from parent resource name - return ResourceNameParser.extractParentId(parent); - } - - /** - * Extracts the config ID from the configuration. If it is not defined, the task ID is used. + * Extracts the config ID from the configuration. * * @param config the TaskPushNotificationConfig * @return the extracted config ID */ default String extractConfigId(TaskPushNotificationConfig config) { - if (config.pushNotificationConfig() != null && config.pushNotificationConfig().id() != null && !config.pushNotificationConfig().id().isBlank()) { - return config.pushNotificationConfig().id(); - } - return config.taskId(); + return config.pushNotificationConfig() != null ? config.pushNotificationConfig().id() : null; } /** * Maps the protobuf PushNotificationConfig to domain, injecting config_id from request. - *

      - * The config_id from the request overrides the ID in the proto's PushNotificationConfig. * * @param request the protobuf CreateTaskPushNotificationConfigRequest * @return domain PushNotificationConfig with config_id injected */ default PushNotificationConfig mapPushNotificationConfigWithId(CreateTaskPushNotificationConfigRequest request) { - // Check if config and push_notification_config exist - if (!request.hasConfig() - || !request.getConfig().hasPushNotificationConfig() - || request.getConfig().getPushNotificationConfig() - .equals(io.a2a.grpc.PushNotificationConfig.getDefaultInstance())) { + if (!request.hasConfig()) { return null; } // Map the proto PushNotificationConfig - PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto( - request.getConfig().getPushNotificationConfig() - ); + PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto(request.getConfig()); // Override ID with config_id from request String configId = request.getConfigId(); @@ -122,16 +74,4 @@ default PushNotificationConfig mapPushNotificationConfigWithId(CreateTaskPushNot return result; } - - /** - * Maps the protobuf PushNotificationConfig to domain, injecting config_id from request. - *

      - * The config_id from the request overrides the ID in the proto's PushNotificationConfig. - * - * @param domain the protobuf CreateTaskPushNotificationConfigRequest - * @return domain PushNotificationConfig with config_id injected - */ - default io.a2a.grpc.TaskPushNotificationConfig mapPushNotificationConfig(TaskPushNotificationConfig domain) { - return TaskPushNotificationConfigMapper.INSTANCE.toProto(domain); - } } 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 deleted file mode 100644 index 68a79eea6..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DataPartMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.DataPart} and {@link io.a2a.grpc.DataPart}. - *

      - * Handles conversion of structured data using Protobuf Struct. - * Uses CommonFieldMapper for Map ↔ Struct conversion. - *

      - * Note: Proto DataPart only has 'data' field. Domain DataPart also has 'metadata' field - * (inherited from Part), which is not persisted in the proto and will be null after conversion. - * Uses @ObjectFactory to resolve constructor ambiguity. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {A2ACommonFieldMapper.class}) -public interface DataPartMapper { - - DataPartMapper INSTANCE = A2AMappers.getMapper(DataPartMapper.class); - - /** - * Converts domain DataPart to proto DataPart. - * Uses CommonFieldMapper for Map → Struct conversion. - * Metadata is ignored (not part of proto definition). - */ - @Mapping(target = "data", source = "data", conditionExpression = "java(domain.data() != null)", qualifiedByName = "mapToStruct") - io.a2a.grpc.DataPart toProto(io.a2a.spec.DataPart domain); - - /** - * Converts proto DataPart to domain DataPart. - * Uses CommonFieldMapper for Struct → Map conversion via Builder. - */ - @Mapping(target = "data", source = "data", qualifiedByName = "structToMap") - io.a2a.spec.DataPart fromProto(io.a2a.grpc.DataPart proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java index 5ab14bf2c..f7ddd3ce4 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java @@ -8,8 +8,6 @@ /** * Mapper between {@link io.a2a.grpc.DeleteTaskPushNotificationConfigRequest} and {@link io.a2a.spec.DeleteTaskPushNotificationConfigParams}. - *

      - * Extracts task ID and config ID from resource name format "tasks/{taskId}/pushNotificationConfigs/{configId}" using {@link ResourceNameParser}. */ @Mapper(config = A2AProtoMapperConfig.class) public interface DeleteTaskPushNotificationConfigParamsMapper { @@ -18,18 +16,18 @@ public interface DeleteTaskPushNotificationConfigParamsMapper { /** * Converts proto DeleteTaskPushNotificationConfigRequest to domain DeleteTaskPushNotificationConfigParams. - * Parses the name field to extract both task ID and config ID. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", expression = "java(ResourceNameParser.parseTaskPushNotificationConfigName(proto.getName())[0])") - @Mapping(target = "pushNotificationConfigId", expression = "java(ResourceNameParser.parseTaskPushNotificationConfigName(proto.getName())[1])") + @Mapping(target = "id", source = "taskId") + @Mapping(target = "pushNotificationConfigId", source = "id") @Mapping(target = "tenant", source = "tenant") DeleteTaskPushNotificationConfigParams fromProto(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest proto); /** * Converts domain DeleteTaskPushNotificationConfigParams to proto DeleteTaskPushNotificationConfigRequest. - * Constructs the name field from task ID and config ID. */ - @Mapping(target = "name", expression = "java(ResourceNameParser.defineTaskPushNotificationConfigName(domain.id(), domain.pushNotificationConfigId()))") + @Mapping(target = "taskId", source = "id") + @Mapping(target = "id", source = "pushNotificationConfigId") + @Mapping(target = "tenant", source = "tenant") io.a2a.grpc.DeleteTaskPushNotificationConfigRequest toProto(DeleteTaskPushNotificationConfigParams domain); } 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 deleted file mode 100644 index 2b1993756..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/FilePartMapper.java +++ /dev/null @@ -1,81 +0,0 @@ -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 org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.FilePart} and {@link io.a2a.grpc.FilePart}. - *

      - * Handles polymorphic FileContent (FileWithBytes vs FileWithUri) conversion. - *

      - * Manual Implementation Required: Must use manual default methods to handle protobuf oneof pattern - * (file_with_bytes vs file_with_uri fields) and ByteString conversion, which MapStruct cannot automatically handle. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface FilePartMapper { - - FilePartMapper INSTANCE = A2AMappers.getMapper(FilePartMapper.class); - - /** - * Converts domain FilePart to proto FilePart. - * Handles FileWithBytes and FileWithUri polymorphism. - */ - default io.a2a.grpc.FilePart toProto(io.a2a.spec.FilePart domain) { - if (domain == null) { - return null; - } - - io.a2a.grpc.FilePart.Builder builder = io.a2a.grpc.FilePart.newBuilder(); - FileContent fileContent = domain.file(); - - if (fileContent instanceof FileWithBytes fileWithBytes) { - builder.setFileWithBytes(ByteString.copyFrom(Base64.getDecoder().decode(fileWithBytes.bytes()))); - if (fileWithBytes.mimeType() != null) { - builder.setMediaType(fileWithBytes.mimeType()); - } - if (fileWithBytes.name() != null) { - builder.setName(fileWithBytes.name()); - } - } else if (fileContent instanceof FileWithUri fileWithUri) { - builder.setFileWithUri(fileWithUri.uri()); - if (fileWithUri.mimeType() != null) { - builder.setMediaType(fileWithUri.mimeType()); - } - if (fileWithUri.name() != null) { - builder.setName(fileWithUri.name()); - } - } - - return builder.build(); - } - - /** - * Converts proto FilePart to domain FilePart. - * Reconstructs FileWithBytes or FileWithUri based on oneof field. - */ - default io.a2a.spec.FilePart fromProto(io.a2a.grpc.FilePart proto) { - if (proto == null) { - return null; - } - - String mimeType = proto.getMediaType().isEmpty() ? null : proto.getMediaType(); - String name = proto.getName().isEmpty() ? null : proto.getName(); - - if (proto.hasFileWithBytes()) { - String bytes = Base64.getEncoder().encodeToString(proto.getFileWithBytes().toByteArray()); - return new io.a2a.spec.FilePart(new FileWithBytes(mimeType, name, bytes)); - } else if (proto.hasFileWithUri()) { - String uri = proto.getFileWithUri(); - return new io.a2a.spec.FilePart(new FileWithUri(mimeType, name, uri)); - } - - throw new InvalidRequestError(); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java index 2a4be5f34..5a74ac2cc 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java @@ -8,11 +8,6 @@ /** * Mapper between {@link io.a2a.grpc.GetTaskPushNotificationConfigRequest} and {@link io.a2a.spec.GetTaskPushNotificationConfigParams}. - *

      - * Extracts task ID and config ID from resource name using {@link ResourceNameParser}. - * Handles both formats: - * - "tasks/{taskId}" (uses taskId as configId) - * - "tasks/{taskId}/pushNotificationConfigs/{configId}" */ @Mapper(config = A2AProtoMapperConfig.class) public interface GetTaskPushNotificationConfigParamsMapper { @@ -21,19 +16,18 @@ public interface GetTaskPushNotificationConfigParamsMapper { /** * Converts proto GetTaskPushNotificationConfigRequest to domain GetTaskPushNotificationConfigParams. - * Parses the name field to extract both task ID and config ID. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", expression = "java(ResourceNameParser.parseGetTaskPushNotificationConfigName(proto.getName())[0])") - @Mapping(target = "pushNotificationConfigId", expression = "java(ResourceNameParser.parseGetTaskPushNotificationConfigName(proto.getName())[1])") + @Mapping(target = "id", source = "taskId") + @Mapping(target = "pushNotificationConfigId", source = "id") @Mapping(target = "tenant", source = "tenant") GetTaskPushNotificationConfigParams fromProto(io.a2a.grpc.GetTaskPushNotificationConfigRequest proto); /** - * Converts domain Message to proto Message.Uses CommonFieldMapper for metadata conversion and ADDER_PREFERRED for lists. - * @param domain - * @return + * Converts domain GetTaskPushNotificationConfigParams to proto GetTaskPushNotificationConfigRequest. */ - @Mapping(target = "name", expression = "java(ResourceNameParser.defineGetTaskPushNotificationConfigName(domain.id(), domain.pushNotificationConfigId()))") + @Mapping(target = "taskId", source = "id") + @Mapping(target = "id", source = "pushNotificationConfigId", conditionExpression = "java(domain.pushNotificationConfigId() != null)") + @Mapping(target = "tenant", source = "tenant") io.a2a.grpc.GetTaskPushNotificationConfigRequest toProto(GetTaskPushNotificationConfigParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java index 1e653eea8..f54ba28d2 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java @@ -8,8 +8,6 @@ /** * Mapper between {@link io.a2a.grpc.ListTaskPushNotificationConfigRequest} and {@link io.a2a.spec.ListTaskPushNotificationConfigParams}. - *

      - * Extracts task ID from parent resource name format "tasks/{id}" using {@link ResourceNameParser}. */ @Mapper(config = A2AProtoMapperConfig.class) public interface ListTaskPushNotificationConfigParamsMapper { @@ -18,16 +16,16 @@ public interface ListTaskPushNotificationConfigParamsMapper { /** * Converts proto ListTaskPushNotificationConfigRequest to domain ListTaskPushNotificationConfigParams. - * Extracts task ID from the parent field and maps pagination parameters. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", expression = "java(ResourceNameParser.extractParentId(proto.getParent()))") + @Mapping(target = "id", source = "taskId") + @Mapping(target = "tenant", source = "tenant") ListTaskPushNotificationConfigParams fromProto(io.a2a.grpc.ListTaskPushNotificationConfigRequest proto); /** * Converts domain ListTaskPushNotificationConfigParams to proto ListTaskPushNotificationConfigRequest. - * Constructs the parent field from task ID. */ - @Mapping(target = "parent", expression = "java(ResourceNameParser.defineTaskName(domain.id()))") + @Mapping(target = "taskId", source = "id") + @Mapping(target = "tenant", source = "tenant") io.a2a.grpc.ListTaskPushNotificationConfigRequest toProto(ListTaskPushNotificationConfigParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java index e919b50d6..66894d49a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java @@ -17,6 +17,8 @@ public interface OAuthFlowsMapper { OAuthFlowsMapper INSTANCE = A2AMappers.getMapper(OAuthFlowsMapper.class); + @Mapping(target = "implicit", ignore = true) + @Mapping(target = "password", ignore = true) io.a2a.grpc.OAuthFlows toProto(io.a2a.spec.OAuthFlows domain); io.a2a.spec.OAuthFlows fromProto(io.a2a.grpc.OAuthFlows proto); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java index 98c777256..41cef1a8d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java @@ -1,7 +1,14 @@ package io.a2a.grpc.mapper; +import java.util.Base64; + +import com.google.protobuf.ByteString; +import com.google.protobuf.Value; import io.a2a.spec.DataPart; +import io.a2a.spec.FileContent; import io.a2a.spec.FilePart; +import io.a2a.spec.FileWithBytes; +import io.a2a.spec.FileWithUri; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.Part; import io.a2a.spec.TextPart; @@ -10,24 +17,25 @@ /** * Mapper between {@link io.a2a.spec.Part} and {@link io.a2a.grpc.Part}. *

      - * Handles polymorphic Part conversion by delegating to type-specific mappers: + * Handles polymorphic Part conversion using the proto's oneof content field: *

        - *
      • TextPart - handled directly (text field on proto Part)
      • - *
      • FilePart - delegated to FilePartMapper
      • - *
      • DataPart - delegated to DataPartMapper
      • + *
      • TextPart - maps to Part.text
      • + *
      • FilePart(FileWithBytes) - maps to Part.raw + Part.filename + Part.media_type
      • + *
      • FilePart(FileWithUri) - maps to Part.url + Part.filename + Part.media_type
      • + *
      • DataPart - maps to Part.data (google.protobuf.Value containing any JSON value: object, array, primitive, or null)
      • *
      *

      - * Manual Implementation Required: Must use manual instanceof dispatch to handle protobuf oneof pattern - * (text vs file vs data fields), as MapStruct's @SubclassMapping maps to different target types, not different fields of the same type. + * Manual Implementation Required: Must use manual instanceof dispatch to handle protobuf oneof pattern, + * as MapStruct's @SubclassMapping maps to different target types, not different fields of the same type. */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {FilePartMapper.class, DataPartMapper.class}) +@Mapper(config = A2AProtoMapperConfig.class, uses = {A2ACommonFieldMapper.class}) public interface PartMapper { PartMapper INSTANCE = A2AMappers.getMapper(PartMapper.class); /** * Converts domain Part to proto Part. - * Handles TextPart, FilePart, and DataPart polymorphism. + * Handles TextPart, FilePart (FileWithBytes and FileWithUri), and DataPart polymorphism. */ default io.a2a.grpc.Part toProto(Part domain) { if (domain == null) { @@ -39,9 +47,31 @@ default io.a2a.grpc.Part toProto(Part domain) { if (domain instanceof TextPart textPart) { builder.setText(textPart.text()); } else if (domain instanceof FilePart filePart) { - builder.setFile(FilePartMapper.INSTANCE.toProto(filePart)); + FileContent fileContent = filePart.file(); + + if (fileContent instanceof FileWithBytes fileWithBytes) { + // Map to raw (bytes), filename, and media_type + builder.setRaw(ByteString.copyFrom(Base64.getDecoder().decode(fileWithBytes.bytes()))); + if (fileWithBytes.name() != null) { + builder.setFilename(fileWithBytes.name()); + } + if (fileWithBytes.mimeType() != null) { + builder.setMediaType(fileWithBytes.mimeType()); + } + } else if (fileContent instanceof FileWithUri fileWithUri) { + // Map to url, filename, and media_type + builder.setUrl(fileWithUri.uri()); + if (fileWithUri.name() != null) { + builder.setFilename(fileWithUri.name()); + } + if (fileWithUri.mimeType() != null) { + builder.setMediaType(fileWithUri.mimeType()); + } + } } else if (domain instanceof DataPart dataPart) { - builder.setData(DataPartMapper.INSTANCE.toProto(dataPart)); + // Map data to google.protobuf.Value (supports object, array, primitive, or null) + Value dataValue = A2ACommonFieldMapper.INSTANCE.objectToValue(dataPart.data()); + builder.setData(dataValue); } return builder.build(); @@ -49,7 +79,7 @@ default io.a2a.grpc.Part toProto(Part domain) { /** * Converts proto Part to domain Part. - * Reconstructs TextPart, FilePart, or DataPart based on oneof field. + * Reconstructs TextPart, FilePart, or DataPart based on oneof content field. */ default Part fromProto(io.a2a.grpc.Part proto) { if (proto == null) { @@ -58,10 +88,23 @@ default Part fromProto(io.a2a.grpc.Part proto) { if (proto.hasText()) { return new TextPart(proto.getText()); - } else if (proto.hasFile()) { - return FilePartMapper.INSTANCE.fromProto(proto.getFile()); + } else if (proto.hasRaw()) { + // raw bytes → FilePart(FileWithBytes) + String bytes = Base64.getEncoder().encodeToString(proto.getRaw().toByteArray()); + String mimeType = proto.getMediaType().isEmpty() ? null : proto.getMediaType(); + String name = proto.getFilename().isEmpty() ? null : proto.getFilename(); + return new FilePart(new FileWithBytes(mimeType, name, bytes)); + } else if (proto.hasUrl()) { + // url → FilePart(FileWithUri) + String uri = proto.getUrl(); + String mimeType = proto.getMediaType().isEmpty() ? null : proto.getMediaType(); + String name = proto.getFilename().isEmpty() ? null : proto.getFilename(); + return new FilePart(new FileWithUri(mimeType, name, uri)); } else if (proto.hasData()) { - return DataPartMapper.INSTANCE.fromProto(proto.getData()); + // data (google.protobuf.Value containing any JSON value) → DataPart + Value dataValue = proto.getData(); + Object data = A2ACommonFieldMapper.INSTANCE.valueToObject(dataValue); + return new DataPart(data); } throw new InvalidRequestError(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityMapper.java index 1e6f26dde..e00e5f70f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityMapper.java @@ -6,17 +6,17 @@ import java.util.Map; import com.google.protobuf.ProtocolStringList; -import io.a2a.grpc.Security; +import io.a2a.grpc.SecurityRequirement; import io.a2a.grpc.StringList; import org.mapstruct.Mapper; /** - * Mapper between domain security requirements and protobuf Security messages. + * Mapper between domain security requirements and protobuf SecurityRequirement messages. *

      * Domain representation: {@code List>>} where each map represents * one security option with scheme names as keys and scopes as values. *

      - * Proto representation: {@code repeated Security} where each Security has + * Proto representation: {@code repeated SecurityRequirement} where each SecurityRequirement has * {@code map schemes}. *

      * Example: A security requirement that allows either OAuth2 with read/write scopes OR API Key: @@ -26,13 +26,13 @@ * {"apiKey": []} * ] * Proto: [ - * Security{schemes: {"oauth2": StringList{values: ["read", "write"]}}}, - * Security{schemes: {"apiKey": StringList{values: []}}} + * SecurityRequirement{schemes: {"oauth2": StringList{values: ["read", "write"]}}}, + * SecurityRequirement{schemes: {"apiKey": StringList{values: []}}} * ] * *

      * Manual Implementation Required: Handles complex nested structure ({@code List>>} ↔ - * {@code repeated Security} with {@code map}) requiring manual iteration and StringList wrapper handling. + * {@code repeated SecurityRequirement} with {@code map}) requiring manual iteration and StringList wrapper handling. */ @Mapper(config = A2AProtoMapperConfig.class) public interface SecurityMapper { @@ -40,19 +40,19 @@ public interface SecurityMapper { SecurityMapper INSTANCE = A2AMappers.getMapper(SecurityMapper.class); /** - * Converts a single domain security requirement map to a proto Security message. + * Converts a single domain security requirement map to a proto SecurityRequirement message. *

      * MapStruct will call this method for each element when mapping the list. * * @param schemeMap map of scheme names to scopes - * @return Security proto message, or null if input is null + * @return SecurityRequirement proto message, or null if input is null */ - default Security mapSecurityItem(Map> schemeMap) { + default SecurityRequirement mapSecurityItem(Map> schemeMap) { if (schemeMap == null) { return null; } - Security.Builder securityBuilder = Security.newBuilder(); + SecurityRequirement.Builder securityBuilder = SecurityRequirement.newBuilder(); for (Map.Entry> entry : schemeMap.entrySet()) { StringList.Builder stringListBuilder = StringList.newBuilder(); if (entry.getValue() != null) { @@ -64,20 +64,20 @@ default Security mapSecurityItem(Map> schemeMap) { } /** - * Converts domain security requirements to proto Security messages. + * Converts domain security requirements to proto SecurityRequirement messages. *

      - * Each Map in the domain list becomes one Security message in proto, representing + * Each Map in the domain list becomes one SecurityRequirement message in proto, representing * one way to satisfy the security requirements (OR relationship between list items). * * @param domainSecurity list of maps representing security requirement options - * @return list of Security proto messages, or null if input is null + * @return list of SecurityRequirement proto messages, or null if input is null */ - default List toProto(List>> domainSecurity) { + default List toProto(List>> domainSecurity) { if (domainSecurity == null) { return null; } - List protoList = new ArrayList<>(domainSecurity.size()); + List protoList = new ArrayList<>(domainSecurity.size()); for (Map> schemeMap : domainSecurity) { protoList.add(mapSecurityItem(schemeMap)); } @@ -85,18 +85,18 @@ default List toProto(List>> domainSecurity) { } /** - * Converts proto Security messages to domain security requirements. + * Converts proto SecurityRequirement messages to domain security requirements. * - * @param protoSecurity list of Security proto messages + * @param protoSecurity list of SecurityRequirement proto messages * @return list of maps representing security requirement options, or null if input is null */ - default List>> fromProto(List protoSecurity) { + default List>> fromProto(List protoSecurity) { if (protoSecurity == null) { return null; } List>> domainList = new ArrayList<>(protoSecurity.size()); - for (Security security : protoSecurity) { + for (SecurityRequirement security : protoSecurity) { Map> schemeMap = new LinkedHashMap<>(); for (Map.Entry entry : security.getSchemesMap().entrySet()) { ProtocolStringList listList = entry.getValue().getListList(); 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 4768fd5c7..c21d1d8a7 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 @@ -33,7 +33,7 @@ default io.a2a.grpc.SubscribeToTaskRequest toProto(SubscribeToTaskRequest domain return null; } return io.a2a.grpc.SubscribeToTaskRequest.newBuilder() - .setName(ResourceNameParser.defineTaskName(domain.getParams().id())) + .setId(domain.getParams().id()) .build(); } @@ -45,11 +45,11 @@ default io.a2a.grpc.SubscribeToTaskRequest toProto(SubscribeToTaskRequest domain * @return the domain SubscribeToTaskRequest */ default SubscribeToTaskRequest fromProto(io.a2a.grpc.SubscribeToTaskRequest proto) { - if (proto == null || proto.getName() == null) { + if (proto == null || proto.getId()== null) { return null; } return SubscribeToTaskRequest.builder() - .params(new io.a2a.spec.TaskIdParams(ResourceNameParser.extractTaskId(proto.getName()))) + .params(new io.a2a.spec.TaskIdParams(proto.getId())) .build(); } } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java index e83c90a42..70595b50e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java @@ -21,7 +21,7 @@ public interface TaskIdParamsMapper { * Extracts task ID from the resource name. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", expression = "java(ResourceNameParser.extractTaskId(proto.getName()))") + @Mapping(target = "id", source = "id") TaskIdParams fromProtoCancelTaskRequest(io.a2a.grpc.CancelTaskRequest proto); /** @@ -29,7 +29,7 @@ public interface TaskIdParamsMapper { * Extracts task ID from the resource name. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "name", expression = "java(ResourceNameParser.defineTaskName(domain.id()))") + @Mapping(target = "id", source = "id") io.a2a.grpc.CancelTaskRequest toProtoCancelTaskRequest(TaskIdParams domain); @@ -38,7 +38,7 @@ public interface TaskIdParamsMapper { * Extracts task ID from the resource name. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", expression = "java(ResourceNameParser.extractTaskId(proto.getName()))") + @Mapping(target = "id", source = "id") @Mapping(target = "tenant", source = "tenant") TaskIdParams fromProtoSubscribeToTaskRequest(io.a2a.grpc.SubscribeToTaskRequest proto); @@ -47,6 +47,6 @@ public interface TaskIdParamsMapper { * Creates resource name from task ID. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "name", expression = "java(ResourceNameParser.defineTaskName(domain.id()))") + @Mapping(target = "id", source = "id") io.a2a.grpc.SubscribeToTaskRequest toProtoSubscribeToTaskRequest(TaskIdParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java index 1289938e7..996bda0ac 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java @@ -6,17 +6,10 @@ import org.mapstruct.Mapping; /** - * MapStruct mapper for TaskPushNotificationConfig with resource name handling. + * MapStruct mapper for TaskPushNotificationConfig. *

      - * This mapper provides compile-time safety while handling the Google Cloud resource name - * convention where the protobuf has a single "name" field in the format - * "tasks/{task_id}/pushNotificationConfigs/{config_id}", but the domain model has separate - * taskId and configId fields. - *

      - * Resource Name Format: tasks/{task_id}/pushNotificationConfigs/{config_id} - *

      - * Compile-Time Safety: If the proto adds/removes/renames fields, MapStruct will - * fail to compile, ensuring we update the domain model accordingly. + * Maps between domain TaskPushNotificationConfig and proto TaskPushNotificationConfig. + * The proto now has direct task_id and id fields instead of a resource name. */ @Mapper(config = A2AProtoMapperConfig.class, uses = {PushNotificationConfigMapper.class}) public interface TaskPushNotificationConfigMapper { @@ -25,80 +18,44 @@ public interface TaskPushNotificationConfigMapper { /** * Converts domain TaskPushNotificationConfig to protobuf TaskPushNotificationConfig. - *

      - * Synthesizes the resource name from taskId and configId following the format: - * "tasks/{task_id}/pushNotificationConfigs/{config_id}" * * @param config the domain TaskPushNotificationConfig - * @return protobuf TaskPushNotificationConfig with synthesized resource name + * @return protobuf TaskPushNotificationConfig */ - @Mapping(target = "name", expression = "java(buildResourceName(config))") + @Mapping(target = "id", expression = "java(extractId(config))") + @Mapping(target = "taskId", source = "taskId") @Mapping(target = "pushNotificationConfig", source = "pushNotificationConfig") + @Mapping(target = "tenant", source = "tenant", conditionExpression = "java(config.tenant() != null)") io.a2a.grpc.TaskPushNotificationConfig toProto(TaskPushNotificationConfig config); /** * Converts protobuf TaskPushNotificationConfig to domain TaskPushNotificationConfig. - *

      - * Parses the resource name to extract taskId and configId, then creates the domain object. - * The configId is injected into the PushNotificationConfig if it differs from what's in the proto. - * The tenant field is set to null as it's not present in the protobuf definition. * * @param proto the protobuf TaskPushNotificationConfig - * @return domain TaskPushNotificationConfig with extracted taskId and configId - * @throws IllegalArgumentException if the resource name format is invalid + * @return domain TaskPushNotificationConfig */ - @Mapping(target = "taskId", expression = "java(extractTaskId(proto))") + @Mapping(target = "taskId", source = "taskId") @Mapping(target = "pushNotificationConfig", expression = "java(mapPushNotificationConfigWithId(proto))") - @Mapping(target = "tenant", expression = "java(null)") + @Mapping(target = "tenant", expression = "java(proto.getTenant().isEmpty() ? null : proto.getTenant())") TaskPushNotificationConfig fromProto(io.a2a.grpc.TaskPushNotificationConfig proto); /** - * Builds the resource name from domain model fields. - *

      - * Format: "tasks/{task_id}/pushNotificationConfigs/{config_id}" - * If configId is null, format: "tasks/{task_id}/pushNotificationConfigs" + * Extracts the config ID from the PushNotificationConfig. * * @param config the domain TaskPushNotificationConfig - * @return the synthesized resource name + * @return the config ID */ - default String buildResourceName(TaskPushNotificationConfig config) { - String taskId = config.taskId(); - String configId = config.pushNotificationConfig().id(); - - if (configId == null || configId.isEmpty()) { - return "tasks/" + taskId + "/pushNotificationConfigs"; - } - return "tasks/" + taskId + "/pushNotificationConfigs/" + configId; + default String extractId(TaskPushNotificationConfig config) { + return config.pushNotificationConfig() != null ? config.pushNotificationConfig().id() : null; } /** - * Extracts the task ID from the protobuf resource name. - * - * @param proto the protobuf TaskPushNotificationConfig - * @return the extracted task ID - * @throws IllegalArgumentException if the resource name format is invalid - */ - default String extractTaskId(io.a2a.grpc.TaskPushNotificationConfig proto) { - String[] parts = ResourceNameParser.parseTaskPushNotificationConfigName(proto.getName()); - return parts[0]; // taskId - } - - /** - * Maps the protobuf PushNotificationConfig to domain, injecting the configId from the resource name. - *

      - * The configId is parsed from the resource name and may override the ID in the proto's - * PushNotificationConfig if they differ. + * Maps the protobuf PushNotificationConfig to domain, ensuring the ID matches the proto's id field. * * @param proto the protobuf TaskPushNotificationConfig * @return domain PushNotificationConfig with correct ID - * @throws IllegalArgumentException if the resource name format is invalid */ default PushNotificationConfig mapPushNotificationConfigWithId(io.a2a.grpc.TaskPushNotificationConfig proto) { - // Parse configId from resource name - String[] parts = ResourceNameParser.parseTaskPushNotificationConfigName(proto.getName()); - String configId = parts[1]; // configId - - // Check if proto has PushNotificationConfig if (!proto.hasPushNotificationConfig() || proto.getPushNotificationConfig().equals(io.a2a.grpc.PushNotificationConfig.getDefaultInstance())) { return null; @@ -107,7 +64,8 @@ default PushNotificationConfig mapPushNotificationConfigWithId(io.a2a.grpc.TaskP // Map the proto PushNotificationConfig PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto(proto.getPushNotificationConfig()); - // Override ID if configId from resource name differs from the one in PushNotificationConfig + // Override ID with the id from TaskPushNotificationConfig if they differ + String configId = proto.getId(); if (configId != null && !configId.isEmpty() && !configId.equals(result.id())) { return new PushNotificationConfig(result.url(), result.token(), result.authentication(), configId); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java index 5c0ddabaa..4d13ff514 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java @@ -21,12 +21,12 @@ public interface TaskQueryParamsMapper { * Extracts task ID from the resource name. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", expression = "java(ResourceNameParser.extractTaskId(proto.getName()))") + @Mapping(target = "id", source = "id") @Mapping(target = "historyLength", source = "historyLength") TaskQueryParams fromProto(io.a2a.grpc.GetTaskRequest proto); @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "name", expression = "java(ResourceNameParser.defineTaskName(domain.id()))") + @Mapping(target = "id", source = "id") @Mapping(target = "historyLength", source = "historyLength") @Mapping(target = "tenant", source = "tenant") io.a2a.grpc.GetTaskRequest toProto(TaskQueryParams domain); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java index f151be7c2..80e260a61 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java @@ -35,7 +35,7 @@ default io.a2a.grpc.TaskState toProto(io.a2a.spec.TaskState domain) { case INPUT_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_INPUT_REQUIRED; case AUTH_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_AUTH_REQUIRED; case COMPLETED -> io.a2a.grpc.TaskState.TASK_STATE_COMPLETED; - case CANCELED -> io.a2a.grpc.TaskState.TASK_STATE_CANCELLED; // Note spelling difference + case CANCELED -> io.a2a.grpc.TaskState.TASK_STATE_CANCELED; case FAILED -> io.a2a.grpc.TaskState.TASK_STATE_FAILED; case REJECTED -> io.a2a.grpc.TaskState.TASK_STATE_REJECTED; case UNKNOWN -> io.a2a.grpc.TaskState.UNRECOGNIZED; @@ -59,7 +59,7 @@ default io.a2a.spec.TaskState fromProto(io.a2a.grpc.TaskState proto) { case TASK_STATE_INPUT_REQUIRED -> io.a2a.spec.TaskState.INPUT_REQUIRED; case TASK_STATE_AUTH_REQUIRED -> io.a2a.spec.TaskState.AUTH_REQUIRED; case TASK_STATE_COMPLETED -> io.a2a.spec.TaskState.COMPLETED; - case TASK_STATE_CANCELLED -> io.a2a.spec.TaskState.CANCELED; // Note spelling difference + case TASK_STATE_CANCELED -> io.a2a.spec.TaskState.CANCELED; case TASK_STATE_FAILED -> io.a2a.spec.TaskState.FAILED; case TASK_STATE_REJECTED -> io.a2a.spec.TaskState.REJECTED; case TASK_STATE_UNSPECIFIED, UNRECOGNIZED -> io.a2a.spec.TaskState.UNKNOWN; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java index 8187df48a..f8ced3ecf 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java @@ -1,8 +1,7 @@ package io.a2a.grpc.mapper; +import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -20,19 +19,26 @@ public interface TaskStatusUpdateEventMapper { /** * Converts domain TaskStatusUpdateEvent to proto. * Uses declarative mapping with CommonFieldMapper for metadata conversion. - * Maps record's isFinal field to proto's final field. + * Note: isFinal field is ignored as it has been removed from the proto (field 4 is reserved). */ @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - @Mapping(target = "final", source = "isFinal") io.a2a.grpc.TaskStatusUpdateEvent toProto(TaskStatusUpdateEvent domain); /** * Converts proto TaskStatusUpdateEvent to domain. - * Now fully declarative using Builder pattern configured via @BeanMapping. - * MapStruct automatically maps proto.getFinal() → builder.isFinal(). + * Note: isFinal is derived from status.state().isFinal() since the field has been removed from the proto (field 4 is reserved). */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "isFinal", source = "final") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - TaskStatusUpdateEvent fromProto(io.a2a.grpc.TaskStatusUpdateEvent proto); + default TaskStatusUpdateEvent fromProto(io.a2a.grpc.TaskStatusUpdateEvent proto) { + if (proto == null) { + return null; + } + TaskStatus status = TaskStatusMapper.INSTANCE.fromProto(proto.getStatus()); + return new TaskStatusUpdateEvent( + proto.getTaskId(), + status, + proto.getContextId(), + status != null && status.state() != null && status.state().isFinal(), + A2ACommonFieldMapper.INSTANCE.metadataFromProto(proto.getMetadata()) + ); + } } diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto index 0f701b6e8..97157cce8 100644 --- a/spec-grpc/src/main/proto/a2a.proto +++ b/spec-grpc/src/main/proto/a2a.proto @@ -9,6 +9,8 @@ import "google/protobuf/empty.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; +//From commit b86d8bb2edd20a972951666823cf6c9f51317550 + option csharp_namespace = "A2a.V1"; option go_package = "google.golang.org/a2a/v1"; option java_multiple_files = true; @@ -43,12 +45,12 @@ service A2AService { // Get the current state of a task from the agent. rpc GetTask(GetTaskRequest) returns (Task) { option (google.api.http) = { - get: "/{name=tasks/*}" + get: "/tasks/{id=*}" additional_bindings: { - get: "/{tenant}/{name=tasks/*}" + get: "/{tenant}/tasks/{id=*}" } }; - option (google.api.method_signature) = "name"; + option (google.api.method_signature) = "id"; } // List tasks with optional filtering and pagination. rpc ListTasks(ListTasksRequest) returns (ListTasksResponse) { @@ -62,21 +64,21 @@ service A2AService { // Cancel a task. rpc CancelTask(CancelTaskRequest) returns (Task) { option (google.api.http) = { - post: "/{name=tasks/*}:cancel" + post: "/tasks/{id=*}:cancel" body: "*" additional_bindings: { - post: "/{tenant}/{name=tasks/*}:cancel" + post: "/{tenant}/tasks/{id=*}:cancel" body: "*" } }; } // SubscribeToTask allows subscribing to task updates for tasks not in terminal state. - // Returns UnsupportedOperationError if task is in terminal state (completed, failed, cancelled, rejected). + // Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected). rpc SubscribeToTask(SubscribeToTaskRequest) returns (stream StreamResponse) { option (google.api.http) = { - get: "/{name=tasks/*}:subscribe" + get: "/tasks/{id=*}:subscribe" additional_bindings: { - get: "/{tenant}/{name=tasks/*}:subscribe" + get: "/{tenant}/tasks/{id=*}:subscribe" } }; } @@ -84,34 +86,34 @@ service A2AService { // Create a push notification config for a task. rpc CreateTaskPushNotificationConfig(CreateTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { option (google.api.http) = { - post: "/{parent=tasks/*/pushNotificationConfigs}" + post: "/tasks/{task_id=*}/pushNotificationConfigs" body: "config" additional_bindings: { - post: "/{tenant}/{parent=tasks/*/pushNotificationConfigs}" + post: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs" body: "config" } }; - option (google.api.method_signature) = "parent,config"; + option (google.api.method_signature) = "task_id,config"; } // Get a push notification config for a task. rpc GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { option (google.api.http) = { - get: "/{name=tasks/*/pushNotificationConfigs/*}" + get: "/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" additional_bindings: { - get: "/{tenant}/{name=tasks/*/pushNotificationConfigs/*}" + get: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" } }; - option (google.api.method_signature) = "name"; + option (google.api.method_signature) = "task_id,id"; } // Get a list of push notifications configured for a task. rpc ListTaskPushNotificationConfig(ListTaskPushNotificationConfigRequest) returns (ListTaskPushNotificationConfigResponse) { option (google.api.http) = { - get: "/{parent=tasks/*}/pushNotificationConfigs" + get: "/tasks/{task_id=*}/pushNotificationConfigs" additional_bindings: { - get: "/{tenant}/{parent=tasks/*}/pushNotificationConfigs" + get: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs" } }; - option (google.api.method_signature) = "parent"; + option (google.api.method_signature) = "task_id"; } // GetExtendedAgentCard returns the extended agent card for authenticated agents. rpc GetExtendedAgentCard(GetExtendedAgentCardRequest) returns (AgentCard) { @@ -125,12 +127,12 @@ service A2AService { // Delete a push notification config for a task. rpc DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest) returns (google.protobuf.Empty) { option (google.api.http) = { - delete: "/{name=tasks/*/pushNotificationConfigs/*}" + delete: "/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" additional_bindings: { - delete: "/{tenant}/{name=tasks/*/pushNotificationConfigs/*}" + delete: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" } }; - option (google.api.method_signature) = "name"; + option (google.api.method_signature) = "task_id,id"; } } @@ -148,7 +150,7 @@ message SendMessageConfiguration { // value of zero is a request to not include any messages. The server MUST NOT // return more messages than the provided value, but MAY apply a lower limit. optional int32 history_length = 3; - // If true, the operation waits until the task reaches a terminal state before returning. Default is false. + // If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false. bool blocking = 4; } // --8<-- [end:SendMessageConfiguration] @@ -191,9 +193,9 @@ enum TaskState { TASK_STATE_COMPLETED = 3; // Represents the status a task is done but failed. This is a terminal state. TASK_STATE_FAILED = 4; - // Represents the status a task was cancelled before it finished. + // Represents the status a task was canceled before it finished. // This is a terminal state. - TASK_STATE_CANCELLED = 5; + TASK_STATE_CANCELED = 5; // Represents the status that the task requires information to complete. // This is an interrupted state. TASK_STATE_INPUT_REQUIRED = 6; @@ -202,8 +204,7 @@ enum TaskState { // has determined it can't or won't proceed. This is a terminal state. TASK_STATE_REJECTED = 7; // Represents the state that some authentication is needed from the upstream - // client. Authentication is expected to come out-of-band thus this is not - // an interrupted or terminal state. + // client. This is an interrupted state. Authentication is expected to come out-of-band. TASK_STATE_AUTH_REQUIRED = 8; } // --8<-- [end:TaskState] @@ -226,45 +227,25 @@ message TaskStatus { // Parts can be purely textual, some sort of file (image, video, etc) or // a structured data blob (i.e. JSON). message Part { - oneof part { + oneof content { // The string content of the text part. string text = 1; - // The file content, represented as either a URI or as base64-encoded bytes. - FilePart file = 2; - // The structured data content. - DataPart data = 3; - } - // Optional metadata associated with this part. - google.protobuf.Struct metadata = 4; -} -// --8<-- [end:Part] - -// --8<-- [start:FilePart] -// FilePart represents the different ways files can be provided. If files are -// small, directly feeding the bytes is supported via file_with_bytes. If the -// file is large, the agent should read the content as appropriate directly -// from the file_with_uri source. -message FilePart { - oneof file { + // The raw byte content of a file. In JSON serialization, this is encoded as a base64 string. + bytes raw = 2; // A URL pointing to the file's content. - string file_with_uri = 1; - // The base64-encoded content of the file. - bytes file_with_bytes = 2; + string url = 3; + // Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null). + google.protobuf.Value data = 4; } - // The media type of the file (e.g., "application/pdf"). - string media_type = 3; + // Optional metadata associated with this part. + google.protobuf.Struct metadata = 5; // An optional name for the file (e.g., "document.pdf"). - string name = 4; + string filename = 6; + // The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png"). + // This field is available for all part types. + string media_type = 7; } -// --8<-- [end:FilePart] - -// --8<-- [start:DataPart] -// DataPart represents a structured blob. -message DataPart { - // A JSON object containing arbitrary data. - google.protobuf.Struct data = 1 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:DataPart] +// --8<-- [end:Part] // --8<-- [start:Role] // Defines the sender of a message in A2A protocol communication. @@ -338,8 +319,7 @@ message TaskStatusUpdateEvent { string context_id = 2 [(google.api.field_behavior) = REQUIRED]; // The new status of the task. TaskStatus status = 3 [(google.api.field_behavior) = REQUIRED]; - // If true, this is the final event in the stream for this interaction. - bool final = 4 [(google.api.field_behavior) = REQUIRED]; + reserved 4; // Optional metadata to associate with the task update. google.protobuf.Struct metadata = 5; } @@ -374,7 +354,7 @@ message PushNotificationConfig { string url = 2 [(google.api.field_behavior) = REQUIRED]; // Token unique for this task/session string token = 3; - // Information about the authentication to sent with the notification + // Authentication information required to send the notification AuthenticationInfo authentication = 4; } // --8<-- [end:PushNotificationConfig] @@ -382,15 +362,16 @@ message PushNotificationConfig { // --8<-- [start:PushNotificationAuthenticationInfo] // Defines authentication details, used for push notifications. message AuthenticationInfo { - // A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). - repeated string schemes = 1 [(google.api.field_behavior) = REQUIRED]; - // Optional credentials + // HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/). + // Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1). + string scheme = 1 [(google.api.field_behavior) = REQUIRED]; + // Push Notification credentials. Format depends on the scheme (e.g., token for Bearer). string credentials = 2; } // --8<-- [end:PushNotificationAuthenticationInfo] // --8<-- [start:AgentInterface] -// Declares a combination of a target URL and a transport protocol for interacting with the agent. +// Declares a combination of a target URL, transport and protocol version for interacting with the agent. // This allows agents to expose the same functionality over multiple protocol binding mechanisms. message AgentInterface { // The URL where this interface is available. Must be a valid absolute HTTPS URL in production. @@ -402,6 +383,10 @@ message AgentInterface { string protocol_binding = 2 [(google.api.field_behavior) = REQUIRED]; // Tenant to be set in the request when calling the agent. string tenant = 3; + // The version of the A2A protocol this interface exposes. + // Use the latest supported minor version per major version. + // Examples: "0.3", "1.0" + string protocol_version = 4 [(google.api.field_behavior) = REQUIRED]; } // --8<-- [end:AgentInterface] @@ -411,14 +396,9 @@ message AgentInterface { // communication methods, and security requirements. // Next ID: 20 message AgentCard { - // The versions of the A2A protocol this agent supports. - // For stable versions (1.x+), list only the latest supported minor version per major version. - // For legacy experimental versions (0.x), explicitly list each supported version. - // Default: ["1.0"] - repeated string protocol_versions = 16 [(google.api.field_behavior) = REQUIRED]; // Reserve these field numbers as they were previously used by removed // fields. - reserved 3, 14, 15; + reserved 3, 9, 14, 15, 16; // A human readable name for the agent. // Example: "Recipe Agent" string name = 1 [(google.api.field_behavior) = REQUIRED]; @@ -439,9 +419,8 @@ message AgentCard { AgentCapabilities capabilities = 7 [(google.api.field_behavior) = REQUIRED]; // The security scheme details used for authenticating with this agent. map security_schemes = 8; - // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED // Security requirements for contacting the agent. - repeated Security security = 9; + repeated SecurityRequirement security_requirements = 13; // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED // The set of interaction modes that the agent supports across all skills. // This can be overridden per skill. Defined as media types. @@ -518,10 +497,8 @@ message AgentSkill { repeated string input_modes = 6; // The set of supported output media types for this skill, overriding the agent's defaults. repeated string output_modes = 7; - // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED // Security schemes necessary for this skill. - repeated Security security = 8; - // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED + repeated SecurityRequirement security_requirements = 8; } // --8<-- [end:AgentSkill] @@ -543,9 +520,15 @@ message AgentCardSignature { // A container associating a push notification configuration with a specific // task. message TaskPushNotificationConfig { - // The resource name of the config. - // Format: tasks/{task_id}/pushNotificationConfigs/{config_id} - string name = 1 [(google.api.field_behavior) = REQUIRED]; + // Optional tenant + string tenant = 4; + + // The id of the config. + string id = 1 [(google.api.field_behavior) = REQUIRED]; + + // The id of the task this config is associated with. + string task_id = 3 [(google.api.field_behavior) = REQUIRED]; + // The push notification configuration details. PushNotificationConfig push_notification_config = 2 [(google.api.field_behavior) = REQUIRED]; } @@ -557,7 +540,7 @@ message StringList { } // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED -message Security { +message SecurityRequirement { map schemes = 1; } @@ -643,13 +626,13 @@ message MutualTlsSecurityScheme { // --8<-- [start:OAuthFlows] // Defines the configuration for the supported OAuth 2.0 flows. message OAuthFlows { - // Tags 3 and 4 were previously used by deprecated OAuth flows. - reserved 3, 4; oneof flow { // Configuration for the OAuth Authorization Code flow. AuthorizationCodeOAuthFlow authorization_code = 1; // Configuration for the OAuth Client Credentials flow. ClientCredentialsOAuthFlow client_credentials = 2; + ImplicitOAuthFlow implicit = 3 [deprecated = true]; + PasswordOAuthFlow password = 4 [deprecated = true]; // Configuration for the OAuth Device Code flow. DeviceCodeOAuthFlow device_code = 5; } @@ -685,6 +668,32 @@ message ClientCredentialsOAuthFlow { } // --8<-- [end:ClientCredentialsOAuthFlow] +// DEPRECATED +message ImplicitOAuthFlow { + // The authorization URL to be used for this flow. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS + string authorization_url = 1; + // The URL to be used for obtaining refresh tokens. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS. + string refresh_url = 2; + // The available scopes for the OAuth2 security scheme. A map between the + // scope name and a short description for it. The map MAY be empty. + map scopes = 3; +} + +// DEPRECATED +message PasswordOAuthFlow { + // The token URL to be used for this flow. This MUST be in the form of a URL. + // The OAuth2 standard requires the use of TLS. + string token_url = 1; + // The URL to be used for obtaining refresh tokens. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS. + string refresh_url = 2; + // The available scopes for the OAuth2 security scheme. A map between the + // scope name and a short description for it. The map MAY be empty. + map scopes = 3; +} + // --8<-- [start:DeviceCodeOAuthFlow] // Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628). // This flow is designed for input-constrained devices such as IoT devices, @@ -721,9 +730,8 @@ message SendMessageRequest { message GetTaskRequest { // Optional tenant, provided as a path parameter. string tenant = 3; - // The resource name of the task. - // Format: tasks/{task_id} - string name = 1 [(google.api.field_behavior) = REQUIRED]; + // The resource id of the task. + string id = 1 [(google.api.field_behavior) = REQUIRED]; // The maximum number of most recent messages from the task's history to retrieve. An // unset value means the client does not impose any limit. A value of zero is // a request to not include any messages. The server MUST NOT return more @@ -776,9 +784,8 @@ message ListTasksResponse { message CancelTaskRequest { // Optional tenant, provided as a path parameter. string tenant = 2; - // The resource name of the task to cancel. - // Format: tasks/{task_id} - string name = 1; + // The resource id of the task to cancel. + string id = 1 [(google.api.field_behavior) = REQUIRED]; } // --8<-- [end:CancelTaskRequest] @@ -786,9 +793,10 @@ message CancelTaskRequest { message GetTaskPushNotificationConfigRequest { // Optional tenant, provided as a path parameter. string tenant = 2; - // The resource name of the config to retrieve. - // Format: tasks/{task_id}/pushNotificationConfigs/{config_id} - string name = 1; + // The parent task resource id. + string task_id = 3 [(google.api.field_behavior) = REQUIRED]; + // The resource id of the config to retrieve. + string id = 1 [(google.api.field_behavior) = REQUIRED]; } // --8<-- [end:GetTaskPushNotificationConfigRequest] @@ -797,24 +805,25 @@ message GetTaskPushNotificationConfigRequest { message DeleteTaskPushNotificationConfigRequest { // Optional tenant, provided as a path parameter. string tenant = 2; - // The resource name of the config to delete. - // Format: tasks/{task_id}/pushNotificationConfigs/{config_id} - string name = 1; + // The parent task resource id. + string task_id = 3 [(google.api.field_behavior) = REQUIRED]; + // The resource id of the config to delete. + string id = 1 [(google.api.field_behavior) = REQUIRED]; } // --8<-- [end:DeleteTaskPushNotificationConfigRequest] // --8<-- [start:CreateTaskPushNotificationConfigRequest] // Represents a request for the `CreateTaskPushNotificationConfig` method. message CreateTaskPushNotificationConfigRequest { + reserved 3; // Optional tenant, provided as a path parameter. string tenant = 4; - // The parent task resource for this config. - // Format: tasks/{task_id} - string parent = 1 [(google.api.field_behavior) = REQUIRED]; + // The parent task resource id. + string task_id = 1 [(google.api.field_behavior) = REQUIRED]; // The ID for the new config. string config_id = 2 [(google.api.field_behavior) = REQUIRED]; // The configuration to create. - TaskPushNotificationConfig config = 3 [(google.api.field_behavior) = REQUIRED]; + PushNotificationConfig config = 5 [(google.api.field_behavior) = REQUIRED]; } // --8<-- [end:CreateTaskPushNotificationConfigRequest] @@ -822,9 +831,8 @@ message CreateTaskPushNotificationConfigRequest { message SubscribeToTaskRequest { // Optional tenant, provided as a path parameter. string tenant = 2; - // The resource name of the task to subscribe to. - // Format: tasks/{task_id} - string name = 1; + // The resource id of the task to subscribe to. + string id = 1 [(google.api.field_behavior) = REQUIRED]; } // --8<-- [end:SubscribeToTaskRequest] @@ -832,9 +840,9 @@ message SubscribeToTaskRequest { message ListTaskPushNotificationConfigRequest { // Optional tenant, provided as a path parameter. string tenant = 4; - // The parent task resource. - // Format: tasks/{task_id} - string parent = 1; + // The parent task resource id. + string task_id = 1 [(google.api.field_behavior) = REQUIRED]; + // The maximum number of configurations to return. int32 page_size = 2; @@ -886,4 +894,4 @@ message ListTaskPushNotificationConfigResponse { // If this field is omitted, there are no subsequent pages. string next_page_token = 2; } -// --8<-- [end:ListTaskPushNotificationConfigResponse] \ No newline at end of file +// --8<-- [end:ListTaskPushNotificationConfigResponse] 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 bd007d61f..4fad9f91e 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 @@ -119,7 +119,6 @@ void testConvertTaskStatusUpdateEvent_ToProto() { .taskId("task-123") .contextId("context-456") .status(new TaskStatus(TaskState.WORKING)) - .isFinal(false) .build(); // Act @@ -131,7 +130,6 @@ void testConvertTaskStatusUpdateEvent_ToProto() { assertEquals("task-123", result.getStatusUpdate().getTaskId()); assertEquals("context-456", result.getStatusUpdate().getContextId()); assertEquals(io.a2a.grpc.TaskState.TASK_STATE_WORKING, result.getStatusUpdate().getStatus().getState()); - assertEquals(false, result.getStatusUpdate().getFinal()); } @Test @@ -144,7 +142,6 @@ void testConvertTaskStatusUpdateEvent_FromProto() { .setStatus(io.a2a.grpc.TaskStatus.newBuilder() .setState(io.a2a.grpc.TaskState.TASK_STATE_WORKING) .build()) - .setFinal(false) .build()) .build(); 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 60f137893..f10692424 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 @@ -33,16 +33,13 @@ public void testParseCreateTaskPushNotificationConfigRequest_ValidProtoFormat() "method": "CreateTaskPushNotificationConfig", "id": "1", "params": { - "parent": "tasks/task-123", + "taskId": "task-123", "configId": "config-456", "tenant": "", "config": { - "name": "tasks/task-123/pushNotificationConfigs/config-456", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "authentication": { - "schemes": ["jwt"] - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } } } @@ -73,7 +70,8 @@ public void testParseGetTaskPushNotificationConfigRequest_ValidProtoFormat() thr "method": "GetTaskPushNotificationConfig", "id": "2", "params": { - "name": "tasks/task-123/pushNotificationConfigs/config-456" + "taskId": "task-123", + "id": "config-456" } } """; @@ -277,7 +275,8 @@ public void testGenerateCreateTaskPushNotificationConfigResponse_Success() throw "jsonrpc": "2.0", "id": "1", "result": { - "name": "tasks/task-123/pushNotificationConfigs/config-456", + "taskId": "task-123", + "id": "config-456", "pushNotificationConfig": { "url": "https://example.com/callback", "id": "config-456" @@ -303,7 +302,8 @@ public void testGenerateGetTaskPushNotificationConfigResponse_Success() throws E "jsonrpc": "2.0", "id": "2", "result": { - "name": "tasks/task-123/pushNotificationConfigs/config-456", + "taskId": "task-123", + "id": "config-456", "pushNotificationConfig": { "url": "https://example.com/callback", "id": "config-456" diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index 2e3b412e0..4a3b1e2c6 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -2,11 +2,10 @@ import static io.a2a.grpc.Role.ROLE_AGENT; import static io.a2a.grpc.Role.ROLE_USER; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; +import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.OffsetDateTime; import java.util.Collections; @@ -49,7 +48,7 @@ public void convertAgentCard() { AgentCard agentCard = AgentCard.builder() .name("Hello World Agent") .description("Just a hello world agent") - .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://localhost:9999", ""))) + .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://localhost:9999", "", "123"))) .version("1.0.0") .documentationUrl("http://example.com/docs") .capabilities(AgentCapabilities.builder() @@ -65,7 +64,6 @@ public void convertAgentCard() { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersions("123") // Weird protool version on purpose to make sure non-default takes effect .build(); io.a2a.grpc.AgentCard result = ProtoUtils.ToProto.agentCard(agentCard); assertEquals("Hello World Agent", result.getName()); @@ -73,18 +71,18 @@ public void convertAgentCard() { assertEquals(1, result.getSupportedInterfacesList().size()); assertEquals("http://localhost:9999", result.getSupportedInterfacesList().get(0).getUrl()); assertEquals("jsonrpc", result.getSupportedInterfacesList().get(0).getProtocolBinding()); + assertEquals("123", result.getSupportedInterfacesList().get(0).getProtocolVersion()); assertEquals("1.0.0", result.getVersion()); assertEquals("http://example.com/docs", result.getDocumentationUrl()); assertEquals(1, result.getDefaultInputModesCount()); assertEquals("text", result.getDefaultInputModes(0)); assertEquals(1, result.getDefaultOutputModesCount()); assertEquals("text", result.getDefaultOutputModes(0)); - // protocolVersions is now a repeated field, checking if the list contains the value - assertTrue(result.getProtocolVersionsList().contains("123")); + // protocolVersion is now in AgentInterface agentCard = AgentCard.builder() .name("Hello World Agent") .description("Just a hello world agent") - .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://localhost:9999", ""))) + .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://localhost:9999"))) .version("1.0.0") .documentationUrl("http://example.com/docs") .capabilities(AgentCapabilities.builder() @@ -102,8 +100,7 @@ public void convertAgentCard() { .build())) // .iconUrl("http://example.com/icon.svg") .securitySchemes(Map.of("basic", HTTPAuthSecurityScheme.builder().scheme("basic").description("Basic Auth").build())) - .security(List.of(Map.of("oauth", List.of("read")))) - .protocolVersions(CURRENT_PROTOCOL_VERSION) + .securityRequirements(List.of(Map.of("oauth", List.of("read")))) .build(); result = ProtoUtils.ToProto.agentCard(agentCard); assertEquals("Hello World Agent", result.getName()); @@ -111,19 +108,19 @@ public void convertAgentCard() { assertEquals(1, result.getSupportedInterfacesList().size()); assertEquals("http://localhost:9999", result.getSupportedInterfacesList().get(0).getUrl()); assertEquals("jsonrpc", result.getSupportedInterfacesList().get(0).getProtocolBinding()); + assertEquals(CURRENT_PROTOCOL_VERSION, result.getSupportedInterfacesList().get(0).getProtocolVersion()); assertEquals("1.0.0", result.getVersion()); assertEquals("http://example.com/docs", result.getDocumentationUrl()); assertEquals(1, result.getDefaultInputModesCount()); assertEquals("text", result.getDefaultInputModes(0)); assertEquals(1, result.getDefaultOutputModesCount()); assertEquals("text", result.getDefaultOutputModes(0)); - // protocolVersions is now a repeated field, checking if the list contains the value - assertTrue(result.getProtocolVersionsList().contains(CURRENT_PROTOCOL_VERSION)); - assertEquals(1, result.getSecurityCount()); - assertEquals(1, result.getSecurity(0).getSchemesMap().size()); - assertEquals(true, result.getSecurity(0).getSchemesMap().containsKey("oauth")); - assertEquals(1, result.getSecurity(0).getSchemesMap().get("oauth").getListCount()); - assertEquals("read", result.getSecurity(0).getSchemesMap().get("oauth").getList(0)); + // protocolVersions field has been removed from the proto + assertEquals(1, result.getSecurityRequirementsCount()); + assertEquals(1, result.getSecurityRequirements(0).getSchemesMap().size()); + assertEquals(true, result.getSecurityRequirements(0).getSchemesMap().containsKey("oauth")); + assertEquals(1, result.getSecurityRequirements(0).getSchemesMap().get("oauth").getListCount()); + assertEquals("read", result.getSecurityRequirements(0).getSchemesMap().get("oauth").getList(0)); assertEquals(1, result.getSecuritySchemesMap().size()); assertEquals(true, result.getSecuritySchemesMap().containsKey("basic")); assertEquals(result.getSecuritySchemesMap().get("basic").getApiKeySecurityScheme().getDefaultInstanceForType(), result.getSecuritySchemesMap().get("basic").getApiKeySecurityScheme()); @@ -164,7 +161,8 @@ public void convertTask() { assertEquals("artefact", result.getArtifacts(0).getName()); assertEquals(1, result.getArtifacts(0).getPartsCount()); assertEquals(true, result.getArtifacts(0).getParts(0).hasText()); - assertEquals(false, result.getArtifacts(0).getParts(0).hasFile()); + assertEquals(false, result.getArtifacts(0).getParts(0).hasRaw()); + assertEquals(false, result.getArtifacts(0).getParts(0).hasUrl()); assertEquals(false, result.getArtifacts(0).getParts(0).hasData()); assertEquals("text", result.getArtifacts(0).getParts(0).getText()); assertEquals(1, result.getHistoryCount()); @@ -173,8 +171,9 @@ public void convertTask() { assertEquals(ROLE_USER, result.getHistory(0).getRole()); assertEquals(1, result.getHistory(0).getPartsCount()); assertEquals("tell me a joke", result.getHistory(0).getParts(0).getText()); - assertEquals(io.a2a.grpc.FilePart.getDefaultInstance(), result.getHistory(0).getParts(0).getFile()); - assertEquals(io.a2a.grpc.DataPart.getDefaultInstance(), result.getHistory(0).getParts(0).getData()); + assertEquals(false, result.getHistory(0).getParts(0).hasRaw()); + assertEquals(false, result.getHistory(0).getParts(0).hasUrl()); + assertEquals(false, result.getHistory(0).getParts(0).hasData()); } @Test @@ -185,8 +184,9 @@ public void convertMessage() { assertEquals(ROLE_USER, result.getRole()); assertEquals(1, result.getPartsCount()); assertEquals("tell me a joke", result.getParts(0).getText()); - assertEquals(io.a2a.grpc.FilePart.getDefaultInstance(), result.getParts(0).getFile()); - assertEquals(io.a2a.grpc.DataPart.getDefaultInstance(), result.getParts(0).getData()); + assertEquals(false, result.getParts(0).hasRaw()); + assertEquals(false, result.getParts(0).hasUrl()); + assertEquals(false, result.getParts(0).hasData()); Message message = Message.builder() .role(Message.Role.AGENT) .parts(Collections.singletonList(new TextPart("tell me a joke"))) @@ -198,8 +198,9 @@ public void convertMessage() { assertEquals(ROLE_AGENT, result.getRole()); assertEquals(1, result.getPartsCount()); assertEquals("tell me a joke", result.getParts(0).getText()); - assertEquals(io.a2a.grpc.FilePart.getDefaultInstance(), result.getParts(0).getFile()); - assertEquals(io.a2a.grpc.DataPart.getDefaultInstance(), result.getParts(0).getData()); + assertEquals(false, result.getParts(0).hasRaw()); + assertEquals(false, result.getParts(0).hasUrl()); + assertEquals(false, result.getParts(0).hasData()); } @Test @@ -210,7 +211,8 @@ public void convertTaskPushNotificationConfig() { .id("xyz") .build(), null); io.a2a.grpc.TaskPushNotificationConfig result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); - assertEquals("tasks/push-task-123/pushNotificationConfigs/xyz", result.getName()); + assertEquals("push-task-123", result.getTaskId()); + assertEquals("xyz", result.getId()); assertNotNull(result.getPushNotificationConfig()); assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); assertEquals("xyz", result.getPushNotificationConfig().getId()); @@ -219,20 +221,20 @@ public void convertTaskPushNotificationConfig() { = new TaskPushNotificationConfig("push-task-123", PushNotificationConfig.builder() .token("AAAAAA") - .authentication(new AuthenticationInfo(Collections.singletonList("jwt"), "credentials")) + .authentication(new AuthenticationInfo("jwt", "credentials")) .url("http://example.com") .id("xyz") .build(), null); result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); - assertEquals("tasks/push-task-123/pushNotificationConfigs/xyz", result.getName()); + assertEquals("push-task-123", result.getTaskId()); + assertEquals("xyz", result.getId()); assertNotNull(result.getPushNotificationConfig()); assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); assertEquals("xyz", result.getPushNotificationConfig().getId()); assertEquals("AAAAAA", result.getPushNotificationConfig().getToken()); assertEquals(true, result.getPushNotificationConfig().hasAuthentication()); assertEquals("credentials", result.getPushNotificationConfig().getAuthentication().getCredentials()); - assertEquals(1, result.getPushNotificationConfig().getAuthentication().getSchemesCount()); - assertEquals("jwt", result.getPushNotificationConfig().getAuthentication().getSchemes(0)); + assertEquals("jwt", result.getPushNotificationConfig().getAuthentication().getScheme()); } @Test @@ -255,16 +257,20 @@ public void convertTaskArtifactUpdateEvent() { @Test public void convertTaskStatusUpdateEvent() { - TaskStatusUpdateEvent tsue = TaskStatusUpdateEvent.builder() - .taskId("1234") - .contextId("xyz") - .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) - .build(); + TaskStatus completedStatus = new TaskStatus(TaskState.COMPLETED); + // Use constructor since Builder doesn't have isFinal method + TaskStatusUpdateEvent tsue = new TaskStatusUpdateEvent( + "1234", + completedStatus, + "xyz", + completedStatus.state().isFinal(), // Derive from state + null + ); io.a2a.grpc.TaskStatusUpdateEvent result = ProtoUtils.ToProto.taskStatusUpdateEvent(tsue); assertEquals("1234", result.getTaskId()); assertEquals("xyz", result.getContextId()); - assertEquals(true, result.getFinal()); + // Note: isFinal field has been removed from the proto (field 4 is reserved) + // It is now derived from status.state().isFinal() assertEquals(io.a2a.grpc.TaskState.TASK_STATE_COMPLETED, result.getStatus().getState()); } @@ -307,7 +313,8 @@ public void convertDeleteTaskPushNotificationConfigRequest() { io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result = ProtoUtils.ToProto.deleteTaskPushNotificationConfigRequest(params); - assertEquals("tasks/task-123/pushNotificationConfigs/config-456", result.getName()); + assertEquals("task-123", result.getTaskId()); + assertEquals("config-456", result.getId()); // Test round-trip conversion DeleteTaskPushNotificationConfigParams convertedBack = @@ -323,7 +330,7 @@ public void convertListTaskPushNotificationConfigRequest() { io.a2a.grpc.ListTaskPushNotificationConfigRequest result = ProtoUtils.ToProto.listTaskPushNotificationConfigRequest(params); - assertEquals("tasks/task-789", result.getParent()); + assertEquals("task-789", result.getTaskId()); // Test round-trip conversion ListTaskPushNotificationConfigParams convertedBack = diff --git a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java b/spec/src/main/java/io/a2a/spec/A2AProtocolError.java index e8dfb3c47..e2655175d 100644 --- a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java +++ b/spec/src/main/java/io/a2a/spec/A2AProtocolError.java @@ -1,14 +1,43 @@ package io.a2a.spec; +/** + * Represents a protocol-level error in the A2A Protocol with a reference URL. + *

      + * This error extends {@link A2AError} to include a URL field that provides a reference + * to documentation, specification details, or additional context about the protocol error. + * This is particularly useful for protocol version mismatches, unsupported features, or + * other situations where pointing to the protocol specification would help diagnose the issue. + * + * @see A2AError for the base error implementation + */ public class A2AProtocolError extends A2AError { + /** + * URL reference for additional information about this protocol error. + */ private final String url; + /** + * Constructs a protocol error with the specified code, message, data, and reference URL. + * + * @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) + * @param url URL reference providing additional context about this protocol error (optional) + */ public A2AProtocolError(Integer code, String message, Object data, String url) { super(code, message, data); this.url = url; } + /** + * Gets the URL reference for additional information about this protocol error. + *

      + * This URL typically points to protocol specification documentation or other resources + * that provide context about the error condition. + * + * @return the reference URL, or null if not provided + */ public String getUrl() { return url; } diff --git a/spec/src/main/java/io/a2a/spec/AgentCard.java b/spec/src/main/java/io/a2a/spec/AgentCard.java index f5a642509..d49dcc862 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCard.java +++ b/spec/src/main/java/io/a2a/spec/AgentCard.java @@ -33,10 +33,9 @@ * @param defaultOutputModes list of supported output modes, e.g., "text", "audio" (required) * @param skills list of skills that this agent can perform (required) * @param securitySchemes map of security scheme names to their definitions (optional) - * @param security list of security requirements for accessing the agent (optional) + * @param securityRequirements list of security requirements for accessing the agent (optional) * @param iconUrl URL to an icon representing the agent (optional) * @param supportedInterfaces ordered list of protocol+URL interface combinations; first entry is preferred (required) - * @param protocolVersions the versions of the A2A Protocol this agent implements (defaults to a singleton list of {@link #CURRENT_PROTOCOL_VERSION}) * @param signatures digital signatures verifying the authenticity of the agent card (optional) * @see AgentInterface * @see A2A Protocol Specification @@ -52,17 +51,13 @@ public record AgentCard( List defaultOutputModes, List skills, Map securitySchemes, - List>> security, + List>> securityRequirements, String iconUrl, List supportedInterfaces, - List protocolVersions, List signatures) { - /** The default A2A Protocol version used when not explicitly specified. */ - public static final String CURRENT_PROTOCOL_VERSION = "1.0"; - /** - * Compact constructor that validates required fields and sets defaults. + * Compact constructor that validates required fields. * * @param name the name parameter (see class-level JavaDoc) * @param description the description parameter (see class-level JavaDoc) @@ -74,10 +69,9 @@ public record AgentCard( * @param defaultOutputModes the defaultOutputModes parameter (see class-level JavaDoc) * @param skills the skills parameter (see class-level JavaDoc) * @param securitySchemes the securitySchemes parameter (see class-level JavaDoc) - * @param security the security parameter (see class-level JavaDoc) + * @param securityRequirements the security parameter (see class-level JavaDoc) * @param iconUrl the iconUrl parameter (see class-level JavaDoc) * @param supportedInterfaces the supportedInterfaces parameter (see class-level JavaDoc) - * @param protocolVersions the protocolVersions parameter (see class-level JavaDoc) * @param signatures the signatures parameter (see class-level JavaDoc) * @throws IllegalArgumentException if any required field is null */ @@ -90,10 +84,6 @@ public record AgentCard( Assert.checkNotNullParam("skills", skills); Assert.checkNotNullParam("supportedInterfaces", supportedInterfaces); Assert.checkNotNullParam("version", version); - - if (protocolVersions == null || protocolVersions.isEmpty()) { - protocolVersions = List.of(CURRENT_PROTOCOL_VERSION); - } } /** @@ -160,10 +150,9 @@ public static class Builder { private List defaultOutputModes; private List skills; private Map securitySchemes; - private List>> security; + private List>> securityRequirements; private String iconUrl; private List supportedInterfaces; - private List protocolVersions; private List signatures; /** @@ -192,10 +181,9 @@ private Builder(AgentCard card) { this.defaultOutputModes = card.defaultOutputModes != null ? new ArrayList<>(card.defaultOutputModes) : null; this.skills = card.skills != null ? new ArrayList<>(card.skills) : null; this.securitySchemes = card.securitySchemes != null ? Map.copyOf(card.securitySchemes) : null; - this.security = card.security != null ? new ArrayList<>(card.security) : null; + this.securityRequirements = card.securityRequirements != null ? new ArrayList<>(card.securityRequirements) : null; this.iconUrl = card.iconUrl; this.supportedInterfaces = card.supportedInterfaces != null ? new ArrayList<>(card.supportedInterfaces) : null; - this.protocolVersions = card.protocolVersions; this.signatures = card.signatures != null ? new ArrayList<>(card.signatures) : null; } @@ -332,11 +320,11 @@ public Builder securitySchemes(Map securitySchemes) { * Each entry in the list represents an alternative security requirement, * where each map contains scheme names and their required scopes. * - * @param security the list of security requirements (optional) + * @param securityRequirements the list of security requirements (optional) * @return this builder for method chaining */ - public Builder security(List>> security) { - this.security = security; + public Builder securityRequirements(List>> securityRequirements) { + this.securityRequirements = securityRequirements; return this; } @@ -375,19 +363,6 @@ public Builder supportedInterfaces(List supportedInterfaces) { return this; } - /** - * Sets the version of the A2A Protocol this agent implements. - *

      - * If not set, defaults to a single list of {@link AgentCard#CURRENT_PROTOCOL_VERSION}. - * - * @param protocolVersions the protocol versions - * @return this builder for method chaining - */ - public Builder protocolVersions(String... protocolVersions) { - this.protocolVersions = List.of(protocolVersions); - return this; - } - /** * Sets the digital signatures verifying the authenticity of the agent card. *

      @@ -414,8 +389,8 @@ public Builder signatures(List signatures) { public AgentCard build() { return new AgentCard(name, description, provider, version, documentationUrl, capabilities, defaultInputModes, defaultOutputModes, skills, - securitySchemes, security, iconUrl, - supportedInterfaces, protocolVersions, signatures); + securitySchemes, securityRequirements, iconUrl, + supportedInterfaces, signatures); } } } diff --git a/spec/src/main/java/io/a2a/spec/AgentInterface.java b/spec/src/main/java/io/a2a/spec/AgentInterface.java index 042d8b56a..dccf4cc75 100644 --- a/spec/src/main/java/io/a2a/spec/AgentInterface.java +++ b/spec/src/main/java/io/a2a/spec/AgentInterface.java @@ -20,11 +20,15 @@ * @param url the endpoint URL where this interface is available; must be a valid absolute HTTPS URL in production * (required) * @param tenant the tenant to be set in the request when calling the agent. + * @param protocolVersion the version of the A2A protocol this interface exposes (e.g., "1.0", "0.3") (required) * @see AgentCard * @see TransportProtocol * @see A2A Protocol Specification */ -public record AgentInterface(String protocolBinding, String url, String tenant) { +public record AgentInterface(String protocolBinding, String url, String tenant, String protocolVersion) { + + /** The default A2A Protocol version used when not explicitly specified. */ + public static final String CURRENT_PROTOCOL_VERSION = "1.0"; /** * Compact constructor that validates required fields. @@ -32,21 +36,37 @@ public record AgentInterface(String protocolBinding, String url, String tenant) * @param protocolBinding the protocolBinding parameter (see class-level JavaDoc) * @param url the url parameter (see class-level JavaDoc) * @param tenant the tenant parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if protocolBinding or url is null + * @param protocolVersion the protocolVersion parameter (see class-level JavaDoc) + * @throws IllegalArgumentException if protocolBinding, url, or protocolVersion is null */ public AgentInterface { Assert.checkNotNullParam("protocolBinding", protocolBinding); Assert.checkNotNullParam("url", url); Assert.checkNotNullParam("tenant", tenant); + + if (protocolVersion == null || protocolVersion.isEmpty()) { + protocolVersion = CURRENT_PROTOCOL_VERSION; + } + } + + /** + * Convenience constructor for creating an AgentInterface with specified tenant and default protocol version. + * + * @param protocolBinding the protocol binding (see class-level JavaDoc) + * @param url the endpoint URL (see class-level JavaDoc) + * @param tenant the tenant (see class-level JavaDoc) + */ + public AgentInterface(String protocolBinding, String url, String tenant) { + this(protocolBinding, url, tenant, CURRENT_PROTOCOL_VERSION); } /** - * Convenience constructor for creating an AgentInterface without a tenant. + * Convenience constructor for creating an AgentInterface with default protocol version and no tenant. * * @param protocolBinding the protocol binding (see class-level JavaDoc) * @param url the endpoint URL (see class-level JavaDoc) */ public AgentInterface(String protocolBinding, String url) { - this(protocolBinding, url, ""); + this(protocolBinding, url, "", CURRENT_PROTOCOL_VERSION); } } diff --git a/spec/src/main/java/io/a2a/spec/AgentSkill.java b/spec/src/main/java/io/a2a/spec/AgentSkill.java index 5eb8e1755..2ff217f5d 100644 --- a/spec/src/main/java/io/a2a/spec/AgentSkill.java +++ b/spec/src/main/java/io/a2a/spec/AgentSkill.java @@ -35,13 +35,13 @@ * @param examples example queries or use cases demonstrating the skill (optional) * @param inputModes supported input formats for this skill (optional, inherits from AgentCard if not set) * @param outputModes supported output formats for this skill (optional, inherits from AgentCard if not set) - * @param security security requirements specific to this skill (optional) + * @param securityRequirements security requirements specific to this skill (optional) * @see AgentCard * @see A2A Protocol Specification */ public record AgentSkill(String id, String name, String description, List tags, List examples, List inputModes, List outputModes, - List>> security) { + List>> securityRequirements) { /** * Compact constructor that validates required fields. @@ -53,7 +53,7 @@ public record AgentSkill(String id, String name, String description, List examples; private List inputModes; private List outputModes; - private List>> security; + private List>> securityRequirements; /** * Creates a new Builder with all fields unset. @@ -216,11 +216,11 @@ public Builder outputModes(List outputModes) { * defined in the AgentCard. Each entry represents an alternative security * requirement, where each map contains scheme names and their required scopes. * - * @param security list of security requirements (optional) + * @param securityRequirements list of security requirements (optional) * @return this builder for method chaining */ - public Builder security(List>> security) { - this.security = security; + public Builder securityRequirements(List>> securityRequirements) { + this.securityRequirements = securityRequirements; return this; } @@ -231,7 +231,7 @@ public Builder security(List>> security) { * @throws IllegalArgumentException if any required field (id, name, description, tags) is null */ public AgentSkill build() { - return new AgentSkill(id, name, description, tags, examples, inputModes, outputModes, security); + return new AgentSkill(id, name, description, tags, examples, inputModes, outputModes, securityRequirements); } } } diff --git a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java b/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java index 8bbe69092..29d1201d1 100644 --- a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java +++ b/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java @@ -1,6 +1,5 @@ package io.a2a.spec; -import java.util.List; import io.a2a.util.Assert; @@ -10,28 +9,28 @@ * This record encapsulates authentication schemes and credentials for two primary use cases: *

        *
      • Agent Authentication: Clients authenticate to access protected agent resources. - * The {@code schemes} list references security schemes from {@link AgentCard#securitySchemes()}.
      • + * The {@code scheme} reference a security scheme from {@link AgentCard#securitySchemes()}. *
      • Push Notification Authentication: Agents authenticate when POSTing task updates to * client-provided push notification endpoints. Supports HTTP Basic, Bearer tokens, API keys, OAuth.
      • *
      * - * @param schemes list of security scheme names for authentication (required) + * @param scheme security scheme name for authentication (required) * @param credentials optional credentials string (format depends on scheme, e.g., base64-encoded for Basic auth) * @see AgentCard#securitySchemes() for available security schemes * @see PushNotificationConfig for push notification configuration * @see SecurityScheme for security scheme definitions * @see A2A Protocol Specification */ -public record AuthenticationInfo(List schemes, String credentials) { +public record AuthenticationInfo(String scheme, String credentials) { /** * Compact constructor that validates required fields. * - * @param schemes the schemes parameter (see class-level JavaDoc) + * @param scheme the schemes parameter (see class-level JavaDoc) * @param credentials the credentials parameter (see class-level JavaDoc) * @throws IllegalArgumentException if schemes is null */ public AuthenticationInfo { - Assert.checkNotNullParam("schemes", schemes); + Assert.checkNotNullParam("scheme", scheme); } } diff --git a/spec/src/main/java/io/a2a/spec/DataPart.java b/spec/src/main/java/io/a2a/spec/DataPart.java index 55157a205..b358d14d9 100644 --- a/spec/src/main/java/io/a2a/spec/DataPart.java +++ b/spec/src/main/java/io/a2a/spec/DataPart.java @@ -8,35 +8,40 @@ /** * Represents a structured data content part within a {@link Message} or {@link Artifact}. *

      - * DataPart contains structured data (typically JSON objects) for machine-to-machine communication. + * DataPart contains arbitrary JSON data for machine-to-machine communication. * It is used when content needs to be processed programmatically rather than displayed as text, * such as API responses, configuration data, analysis results, or structured metadata. *

      - * The data is represented as a Map of key-value pairs, which can contain nested structures - * including lists, maps, and primitive values. + * The data can be any valid JSON value: + *

        + *
      • JSON objects: {@code Map}
      • + *
      • JSON arrays: {@code List} + *
      • Primitives: {@code String}, {@code Number}, {@code Boolean}
      • + *
      • Null values: {@code null}
      • + * *

        * Example usage: *

        {@code
        - * // Simple structured data
        - * DataPart result = new DataPart(Map.of(
        + * // JSON object
        + * DataPart obj = new DataPart(Map.of(
          *     "status", "success",
          *     "count", 42,
          *     "items", List.of("item1", "item2")
          * ));
          *
        - * // With metadata
        - * DataPart withMeta = new DataPart(
        - *     Map.of("temperature", 72.5, "unit", "F"),
        - *     Map.of("source", "weather-api", "timestamp", "2024-01-20T12:00:00Z")
        - * );
        + * // JSON array
        + * DataPart array = new DataPart(List.of("item1", "item2", "item3"));
        + *
        + * // Primitive value
        + * DataPart primitive = new DataPart(42);
          * }
        * - * @param data the structured data map (required, defensively copied for immutability) + * @param data the structured data (required, supports JSON objects, arrays, primitives, and null) * @see Part * @see Message * @see Artifact */ -public record DataPart(Map data) implements Part> { +public record DataPart(Object data) implements Part { /** * The JSON member name discriminator for data parts: "data". @@ -47,14 +52,16 @@ public record DataPart(Map data) implements Part + * Note: For mutable data types (Map, List), callers should ensure immutability + * by using {@code Map.copyOf()} or {@code List.copyOf()} before passing to this constructor. * - * @param data the structured data map (required, defensively copied for immutability) + * @param data the structured data (supports JSON objects, arrays, primitives, and null) * @throws IllegalArgumentException if data is null */ public DataPart { Assert.checkNotNullParam("data", data); - data = Map.copyOf(data); } /** @@ -67,10 +74,10 @@ public static Builder builder() { } /** - * Builder for constructing immutable {@link DataPart} instances. + * Builder for constructing {@link DataPart} instances. */ public static class Builder { - private Map data; + private Object data; /** * Creates a new Builder with all fields unset. @@ -79,18 +86,18 @@ private Builder() { } /** - * Sets the structured data map. + * Sets the structured data. * - * @param data the structured data (required) + * @param data the structured data (required, supports JSON objects, arrays, primitives, and null) * @return this builder for method chaining */ - public Builder data(Map data) { + public Builder data(Object data) { this.data = data; return this; } /** - * Builds a new immutable {@link DataPart} from the current builder state. + * Builds a new {@link DataPart} from the current builder state. * * @return a new DataPart instance * @throws IllegalArgumentException if data is null diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java index 36f2db3fb..81537ce97 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java @@ -3,7 +3,6 @@ import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; /** * Parameters for retrieving push notification configuration for a specific task. @@ -17,7 +16,7 @@ * @see TaskPushNotificationConfig for the returned configuration structure * @see A2A Protocol Specification */ -public record GetTaskPushNotificationConfigParams(String id, @Nullable String pushNotificationConfigId, String tenant) { +public record GetTaskPushNotificationConfigParams(String id, String pushNotificationConfigId, String tenant) { /** * Compact constructor that validates required fields. @@ -29,18 +28,10 @@ public record GetTaskPushNotificationConfigParams(String id, @Nullable String pu */ public GetTaskPushNotificationConfigParams { Assert.checkNotNullParam("id", id); + Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId); Assert.checkNotNullParam("tenant", tenant); } - /** - * Convenience constructor for creating parameters with only task ID. - * - * @param id the task identifier (required) - */ - public GetTaskPushNotificationConfigParams(String id) { - this(id, null, ""); - } - /** * Convenience constructor for creating parameters without tenant. * diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java index 644fed897..766945603 100644 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java @@ -10,6 +10,8 @@ * * @param id the task identifier (required) * @param tenant optional tenant, provided as a path parameter. + * @param pageSize the maximum number of items to return per page + * @param pageToken the pagination token for the next page * @see TaskPushNotificationConfig for the configuration structure * @see A2A Protocol Specification */ diff --git a/spec/src/main/java/io/a2a/spec/SecurityScheme.java b/spec/src/main/java/io/a2a/spec/SecurityScheme.java index b481b4c4a..0fad71ed7 100644 --- a/spec/src/main/java/io/a2a/spec/SecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/SecurityScheme.java @@ -25,13 +25,13 @@ public sealed interface SecurityScheme permits APIKeySecurityScheme, HTTPAuthSec /** * Returns the human-readable description of this security scheme. - * * @return the description, or null if not provided */ String description(); /** * Returns the type of the security scheme. + * @return the type of the security scheme. */ String type(); } diff --git a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java index 09e3bf39a..547a6e089 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java +++ b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java @@ -1,5 +1,11 @@ package io.a2a.spec; +import static io.a2a.spec.TaskState.CANCELED; +import static io.a2a.spec.TaskState.COMPLETED; +import static io.a2a.spec.TaskState.FAILED; +import static io.a2a.spec.TaskState.INPUT_REQUIRED; +import static io.a2a.spec.TaskState.REJECTED; + import java.util.Map; import com.google.gson.annotations.SerializedName; @@ -19,9 +25,10 @@ public record TaskStatusUpdateEvent( String taskId, TaskStatus status, String contextId, - @SerializedName("final") boolean isFinal, + @SerializedName("final") + boolean isFinal, Map metadata -) implements EventKind, StreamingEventKind, UpdateEvent { + ) implements EventKind, StreamingEventKind, UpdateEvent { /** * The identifier when used in streaming responses @@ -30,6 +37,7 @@ public record TaskStatusUpdateEvent( /** * Compact constructor with validation. + * * @param taskId the task identifier (required) * @param status the task status (required) * @param contextId the context identifier (required) @@ -41,6 +49,9 @@ public record TaskStatusUpdateEvent( Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("status", status); Assert.checkNotNullParam("contextId", contextId); + if (isFinal != status.state().isFinal()) { + throw new IllegalArgumentException("isFinal must be the same as the Status state"); + } } @Override @@ -48,6 +59,14 @@ public String kind() { return STREAMING_EVENT_ID; } + /** + * Indicates if the task is fianl or waiting for some inputs from the client. + * @return true if the task is fianl or waiting for some inputs from the client - false otherwise. + */ + public boolean isFinalOrInterrupted() { + return status.state() == COMPLETED || status.state() == FAILED || status.state() == CANCELED || status.state() == REJECTED || status.state() == INPUT_REQUIRED; + } + /** * Create a new Builder * @@ -71,10 +90,10 @@ public static Builder builder(TaskStatusUpdateEvent event) { * Builder for constructing {@link TaskStatusUpdateEvent} instances. */ public static class Builder { + private String taskId; private TaskStatus status; private String contextId; - private boolean isFinal; private Map metadata; private Builder() { @@ -84,7 +103,6 @@ private Builder(TaskStatusUpdateEvent existingTaskStatusUpdateEvent) { this.taskId = existingTaskStatusUpdateEvent.taskId; this.status = existingTaskStatusUpdateEvent.status; this.contextId = existingTaskStatusUpdateEvent.contextId; - this.isFinal = existingTaskStatusUpdateEvent.isFinal; this.metadata = existingTaskStatusUpdateEvent.metadata; } @@ -121,17 +139,6 @@ public Builder contextId(String contextId) { return this; } - /** - * Sets whether this is a final status. - * - * @param isFinal true if this is a final status - * @return this builder for method chaining - */ - public Builder isFinal(boolean isFinal) { - this.isFinal = isFinal; - return this; - } - /** * Sets the metadata. * @@ -149,7 +156,7 @@ public Builder metadata(Map metadata) { * @return a new TaskStatusUpdateEvent instance */ public TaskStatusUpdateEvent build() { - return new TaskStatusUpdateEvent(taskId, status, contextId, isFinal, metadata); + return new TaskStatusUpdateEvent(taskId, status, contextId, status.state().isFinal(), metadata); } } } diff --git a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java index 955709986..72a05bc74 100644 --- a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java @@ -23,7 +23,7 @@ * } * } * - * @see AgentCard#protocolVersions() for supported version declaration + * @see AgentInterface#protocolVersion() for supported version declaration * @see A2A Protocol Specification */ public class VersionNotSupportedError extends A2AProtocolError { diff --git a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java index 599a0e12c..571e2bb1f 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java @@ -1,6 +1,5 @@ package io.a2a.tck.server; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import java.util.Collections; import java.util.List; @@ -49,7 +48,6 @@ public AgentCard agentCard() { .tags(Collections.singletonList("hello world")) .examples(List.of("hi", "hello world")) .build())) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } 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 d1f5af5a6..848ced9ec 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java @@ -49,10 +49,10 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr eventQueue.enqueueEvent(task); } - // Sleep to allow task state persistence before TCK resubscribe test - if (context.getMessage() != null && context.getMessage().messageId().startsWith("test-resubscribe-message-id")) { + // Sleep to allow task state persistence before TCK subscribe test + if (context.getMessage() != null && context.getMessage().messageId().startsWith("test-subscribe-message-id")) { int timeoutMs = Integer.parseInt(System.getenv().getOrDefault("RESUBSCRIBE_TIMEOUT_MS", "3000")); - System.out.println("====> task id starts with test-resubscribe-message-id, sleeping for " + timeoutMs + " ms"); + System.out.println("====> task id starts with test-subscribe-message-id, sleeping for " + timeoutMs + " ms"); try { Thread.sleep(timeoutMs); } catch (InterruptedException e) { @@ -89,12 +89,12 @@ public void cancel(RequestContext context, EventQueue eventQueue) throws A2AErro TaskUpdater updater = new TaskUpdater(context, eventQueue); updater.cancel(); - eventQueue.enqueueEvent(TaskStatusUpdateEvent.builder() - .taskId(task.id()) - .contextId(task.contextId()) - .status(new TaskStatus(TaskState.CANCELED)) - .isFinal(true) - .build()); + eventQueue.enqueueEvent(new TaskStatusUpdateEvent( + task.id(), + new TaskStatus(TaskState.CANCELED), + task.contextId(), + true, // isFinal - TaskState.CANCELED is a final state + null)); System.out.println("====> task canceled"); } 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 a15f2b087..5522e4dbf 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,7 +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; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -577,7 +576,7 @@ public void testGetPushNotificationSuccess() throws Exception { assertNotNull(setResult); TaskPushNotificationConfig config = getClient().getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + new GetTaskPushNotificationConfigParams(MINIMAL_TASK.id(), "c295ea44-7543-4f78-b524-7a38915ad6e4")); assertEquals(MINIMAL_TASK.id(), config.taskId()); assertEquals("http://example.com", config.pushNotificationConfig().url()); } catch (A2AClientException e) { @@ -640,7 +639,7 @@ public void testSendMessageStreamExistingTaskSuccess() throws Exception { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) - public void testResubscribeExistingTaskSuccess() throws Exception { + public void testSubscribeExistingTaskSuccess() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); try { // attempting to send a streaming message instead of explicitly calling queueManager#createOrTap @@ -654,7 +653,7 @@ public void testResubscribeExistingTaskSuccess() throws Exception { AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); AtomicReference errorRef = new AtomicReference<>(); - // Create consumer to handle resubscribed events + // Create consumer to handle subscribed events AtomicBoolean receivedInitialTask = new AtomicBoolean(false); BiConsumer consumer = (event, agentCard) -> { // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent @@ -664,7 +663,7 @@ public void testResubscribeExistingTaskSuccess() throws Exception { // Don't count down latch for initial Task return; } else { - fail("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + fail("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); } } @@ -697,8 +696,8 @@ public void testResubscribeExistingTaskSuccess() throws Exception { awaitStreamingSubscription() .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); - // Resubscribe to the task with specific consumer and error handler - getClient().resubscribe(new TaskIdParams(MINIMAL_TASK.id()), List.of(consumer), errorHandler); + // subscribe to the task with specific consumer and error handler + getClient().subscribeToTask(new TaskIdParams(MINIMAL_TASK.id()), List.of(consumer), errorHandler); // Wait for subscription to be established assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); @@ -717,7 +716,6 @@ public void testResubscribeExistingTaskSuccess() throws Exception { .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) .build()); for (Event event : events) { @@ -752,7 +750,7 @@ public void testResubscribeExistingTaskSuccess() throws Exception { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) - public void testResubscribeExistingTaskSuccessWithClientConsumers() throws Exception { + public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); try { // attempting to send a streaming message instead of explicitly calling queueManager#createOrTap @@ -766,7 +764,7 @@ public void testResubscribeExistingTaskSuccessWithClientConsumers() throws Excep AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); AtomicReference errorRef = new AtomicReference<>(); - // Create consumer to handle resubscribed events + // Create consumer to handle subscribed events AtomicBoolean receivedInitialTask = new AtomicBoolean(false); AgentCard agentCard = createTestAgentCard(); @@ -781,7 +779,7 @@ public void testResubscribeExistingTaskSuccessWithClientConsumers() throws Excep // Don't count down latch for initial Task return; } else { - fail("First event on resubscribe MUST be TaskEvent, but was: " + evt.getClass().getSimpleName()); + fail("First event on subscribe MUST be TaskEvent, but was: " + evt.getClass().getSimpleName()); } } @@ -816,8 +814,8 @@ public void testResubscribeExistingTaskSuccessWithClientConsumers() throws Excep awaitStreamingSubscription() .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); - // Resubscribe to the task with the client consumer and error handler - clientWithConsumer.resubscribe(new TaskIdParams(MINIMAL_TASK.id())); + // Subscribe to the task with the client consumer and error handler + clientWithConsumer.subscribeToTask(new TaskIdParams(MINIMAL_TASK.id())); // Wait for subscription to be established assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); @@ -836,7 +834,6 @@ public void testResubscribeExistingTaskSuccessWithClientConsumers() throws Excep .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) .status(new TaskStatus(TaskState.COMPLETED)) - .isFinal(true) .build()); for (Event event : events) { @@ -870,7 +867,7 @@ public void testResubscribeExistingTaskSuccessWithClientConsumers() throws Excep } @Test - public void testResubscribeNoExistingTaskError() throws Exception { + public void testSubscribeNoExistingTaskError() throws Exception { CountDownLatch errorLatch = new CountDownLatch(1); AtomicReference errorRef = new AtomicReference<>(); @@ -887,7 +884,7 @@ public void testResubscribeNoExistingTaskError() throws Exception { }; try { - getClient().resubscribe(new TaskIdParams("non-existent-task"), List.of(), errorHandler); + getClient().subscribeToTask(new TaskIdParams("non-existent-task"), List.of(), errorHandler); // Wait for error to be captured (may come via error handler for streaming) boolean errorReceived = errorLatch.await(10, TimeUnit.SECONDS); @@ -952,7 +949,7 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti firstReceivedInitialTask.set(true); return; } else { - fail("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + fail("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); } } @@ -977,7 +974,7 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti awaitStreamingSubscription() .whenComplete((unused, throwable) -> firstSubscriptionLatch.countDown()); - getClient().resubscribe(new TaskIdParams(MINIMAL_TASK.id()), + getClient().subscribeToTask(new TaskIdParams(MINIMAL_TASK.id()), List.of(firstConsumer), firstErrorHandler); @@ -1000,11 +997,11 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti assertNull(firstErrorRef.get()); assertNotNull(firstConsumerEvent.get()); - // Verify we have multiple child queues (ensureQueue + first resubscribe) + // Verify we have multiple child queues (ensureQueue + first subscribe) int childCountBeforeSecond = getChildQueueCount(MINIMAL_TASK.id()); assertTrue(childCountBeforeSecond >= 2, "Should have at least 2 child queues"); - // 3. Second consumer resubscribes while first is still active + // 3. Second consumer subscribes while first is still active // This simulates the Kafka replication race condition where resubscription happens // while other consumers are still active. Without reference counting, the MainQueue // might close when the ensureQueue ChildQueue closes, preventing this resubscription. @@ -1021,7 +1018,7 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti secondReceivedInitialTask.set(true); return; } else { - fail("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + fail("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); } } @@ -1048,7 +1045,7 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti // This should succeed with reference counting because MainQueue stays alive // while first consumer's ChildQueue exists - getClient().resubscribe(new TaskIdParams(MINIMAL_TASK.id()), + getClient().subscribeToTask(new TaskIdParams(MINIMAL_TASK.id()), List.of(secondConsumer), secondErrorHandler); @@ -1360,7 +1357,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { assertNotNull(taskId); assertEquals(multiEventTaskId, taskId); - // 2. Resubscribe to task (queue should still be open) + // 2. Subscribe to task (queue should still be open) CountDownLatch resubEventLatch = new CountDownLatch(2); // artifact-2 + completion List resubReceivedEvents = new CopyOnWriteArrayList<>(); AtomicBoolean resubUnexpectedEvent = new AtomicBoolean(false); @@ -1374,7 +1371,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { resubReceivedInitialTask.set(true); return; } else { - fail("First event on resubscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); + fail("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); } } @@ -1398,7 +1395,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { awaitStreamingSubscription() .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); - getClient().resubscribe(new TaskIdParams(taskId), + getClient().subscribeToTask(new TaskIdParams(taskId), List.of(resubConsumer), resubErrorHandler); @@ -1416,7 +1413,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { AtomicBoolean streamUnexpectedEvent = new AtomicBoolean(false); BiConsumer streamConsumer = (event, agentCard) -> { - // This consumer is for sendMessage() (not resubscribe), so it doesn't get initial TaskEvent + // This consumer is for sendMessage() (not subscribe), so it doesn't get initial TaskEvent if (event instanceof TaskUpdateEvent tue) { streamReceivedEvents.add(tue.getUpdateEvent()); streamEventLatch.countDown(); @@ -2148,7 +2145,6 @@ private AgentCard createTestAgentCard() { .defaultOutputModes(List.of("text")) .skills(List.of()) .supportedInterfaces(List.of(new AgentInterface(getTransportProtocol(), getTransportUrl()))) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .build(); } @@ -2251,7 +2247,7 @@ public void testMainQueueStaysOpenForNonFinalTasks() throws Exception { // Give agent time to finish (task remains in WORKING state - non-final) Thread.sleep(2000); - // THE BIG IDEA TEST: Resubscribe to the task + // THE BIG IDEA TEST: Subscribe to the task // Even though the agent finished and original ChildQueue closed, // MainQueue should still be open because task is in non-final WORKING state CountDownLatch resubLatch = new CountDownLatch(1); @@ -2274,7 +2270,7 @@ public void testMainQueueStaysOpenForNonFinalTasks() throws Exception { awaitStreamingSubscription() .whenComplete((unused, throwable) -> resubSubscriptionLatch.countDown()); - getClient().resubscribe(new TaskIdParams(taskId), + getClient().subscribeToTask(new TaskIdParams(taskId), List.of(resubConsumer), resubErrorHandler); @@ -2353,7 +2349,7 @@ public void testMainQueueClosesForFinalizedTasks() throws Exception { // Give cleanup time to run after final event Thread.sleep(2000); - // Try to resubscribe to finalized task - should fail + // Try to subscribe to finalized task - should fail CountDownLatch errorLatch = new CountDownLatch(1); AtomicReference resubErrorRef = new AtomicReference<>(); @@ -2370,7 +2366,7 @@ public void testMainQueueClosesForFinalizedTasks() throws Exception { // Attempt resubscription try { - getClient().resubscribe(new TaskIdParams(taskId), + getClient().subscribeToTask(new TaskIdParams(taskId), List.of(), resubErrorHandler); diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java index f9dae8d19..06cdb17f6 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java @@ -1,6 +1,5 @@ package io.a2a.server.apps.common; -import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import static io.a2a.spec.TransportProtocol.GRPC; import java.io.IOException; @@ -18,7 +17,6 @@ import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; import io.quarkus.arc.profile.IfBuildProfile; import org.junit.jupiter.api.Assertions; @@ -51,7 +49,6 @@ public AgentCard agentCard() { .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) .skills(new ArrayList<>()) - .protocolVersions(CURRENT_PROTOCOL_VERSION) .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, transportUrl))); return builder.build(); } 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 376d9b11d..979bb5ef4 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 @@ -263,7 +263,7 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, try { ServerCallContext context = createCallContext(responseObserver); TaskIdParams params = FromProto.taskIdParams(request); - Flow.Publisher publisher = getRequestHandler().onResubscribeToTask(params, context); + Flow.Publisher publisher = getRequestHandler().onSubscribeToTask(params, context); convertToStreamResponse(publisher, responseObserver, context); } catch (A2AError e) { handleError(responseObserver, e); @@ -309,8 +309,17 @@ public void cancelled(Context ctx) { public void onNext(StreamingEventKind event) { StreamResponse response = ToProto.streamResponse(event); responseObserver.onNext(response); - if (response.hasStatusUpdate() && response.getStatusUpdate().getFinal()) { - responseObserver.onCompleted(); + if (response.hasStatusUpdate()) { + io.a2a.grpc.TaskState state = response.getStatusUpdate().getStatus().getState(); + boolean isFinal = state == io.a2a.grpc.TaskState.TASK_STATE_CANCELED + || state == io.a2a.grpc.TaskState.TASK_STATE_COMPLETED + || state == io.a2a.grpc.TaskState.TASK_STATE_FAILED + || state == io.a2a.grpc.TaskState.TASK_STATE_REJECTED; + if (isFinal) { + responseObserver.onCompleted(); + } else { + subscription.request(1); + } } else { subscription.request(1); } 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 c7cf79524..2bd8c8453 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 @@ -1,5 +1,6 @@ package io.a2a.transport.grpc.handler; +import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; @@ -60,13 +61,12 @@ public class GrpcHandlerTest extends AbstractA2ARequestHandlerTest { .setMetadata(Struct.newBuilder().build()) .build(); - @Test public void testOnGetTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); GetTaskRequest request = GetTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -87,7 +87,7 @@ public void testOnGetTaskSuccess() throws Exception { public void testOnGetTaskNotFound() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); GetTaskRequest request = GetTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -112,7 +112,7 @@ public void testOnCancelTaskSuccess() throws Exception { }; CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.cancelTask(request, streamRecorder); @@ -125,7 +125,7 @@ public void testOnCancelTaskSuccess() throws Exception { Task task = result.get(0); assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), task.getId()); assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), task.getContextId()); - assertEquals(TaskState.TASK_STATE_CANCELLED, task.getStatus().getState()); + assertEquals(TaskState.TASK_STATE_CANCELED, task.getStatus().getState()); } @Test @@ -138,7 +138,7 @@ public void testOnCancelTaskNotSupported() throws Exception { }; CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.cancelTask(request, streamRecorder); @@ -151,7 +151,7 @@ public void testOnCancelTaskNotSupported() throws Exception { public void testOnCancelTaskNotFound() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.cancelTask(request, streamRecorder); @@ -205,17 +205,18 @@ public void testOnMessageError() throws Exception { @Test public void testSetPushNotificationConfigSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + "config456"; - StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); + StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), "config456"); Assertions.assertNull(streamRecorder.getError()); List result = streamRecorder.getValues(); Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); TaskPushNotificationConfig response = result.get(0); - assertEquals(NAME, response.getName()); + assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), response.getTaskId()); PushNotificationConfig responseConfig = response.getPushNotificationConfig(); assertEquals("config456", responseConfig.getId()); + assertEquals("config456", response.getId()); assertEquals("http://example.com", responseConfig.getUrl()); assertEquals(AuthenticationInfo.getDefaultInstance(), responseConfig.getAuthentication()); Assertions.assertTrue(responseConfig.getToken().isEmpty()); @@ -228,20 +229,20 @@ public void testGetPushNotificationConfigSuccess() throws Exception { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + "config456"; - // first set the task push notification config - StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); + StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), "config456"); Assertions.assertNull(streamRecorder.getError()); // then get the task push notification config - streamRecorder = getTaskPushNotificationConfigRequest(handler, NAME); + streamRecorder = getTaskPushNotificationConfigRequest(handler, AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), "config456"); Assertions.assertNull(streamRecorder.getError()); List result = streamRecorder.getValues(); Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); TaskPushNotificationConfig response = result.get(0); - assertEquals(NAME, response.getName()); + assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), response.getTaskId()); + assertEquals("config456", response.getId()); PushNotificationConfig responseConfig = response.getPushNotificationConfig(); assertEquals("config456", responseConfig.getId()); assertEquals("http://example.com", responseConfig.getUrl()); @@ -253,8 +254,8 @@ public void testGetPushNotificationConfigSuccess() throws Exception { public void testPushNotificationsNotSupportedError() throws Exception { AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); - StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); + StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); } @@ -264,8 +265,8 @@ public void testOnGetPushNotificationNoPushNotifierConfig() throws Exception { DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); - StreamRecorder streamRecorder = getTaskPushNotificationConfigRequest(handler, NAME); + StreamRecorder streamRecorder = getTaskPushNotificationConfigRequest(handler, + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); } @@ -275,8 +276,8 @@ public void testOnSetPushNotificationNoPushNotifierConfig() throws Exception { DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); - StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); + StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); } @@ -379,7 +380,8 @@ public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() throws Excep try (MockedConstruction mocked = Mockito.mockConstruction( EventConsumer.class, (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll();})){ + Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll(); + })) { streamRecorder = sendStreamingMessageRequest(handler); } Assertions.assertNull(streamRecorder.getError()); @@ -410,71 +412,70 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); List events = List.of( AbstractA2ARequestHandlerTest.MINIMAL_TASK, - TaskArtifactUpdateEvent.builder() - .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.COMPLETED)) - .build()); - - - agentExecutorExecute = (context, eventQueue) -> { - // Hardcode the events to send here - for (Event event : events) { - eventQueue.enqueueEvent(event); - } - }; - - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); - StreamRecorder pushStreamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); - Assertions.assertNull(pushStreamRecorder.getError()); - - List results = new ArrayList<>(); - List errors = new ArrayList<>(); - final CountDownLatch latch = new CountDownLatch(6); - httpClient.latch = latch; - StreamObserver streamObserver = new StreamObserver<>() { - @Override - public void onNext(StreamResponse streamResponse) { - results.add(streamResponse); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - errors.add(throwable); - } + TaskArtifactUpdateEvent.builder() + .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) + .artifact(Artifact.builder() + .artifactId("11") + .parts(new TextPart("text")) + .build()) + .build(), + TaskStatusUpdateEvent.builder() + .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) + .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.COMPLETED)) + .build()); + + agentExecutorExecute = (context, eventQueue) -> { + // Hardcode the events to send here + for (Event event : events) { + eventQueue.enqueueEvent(event); + } + }; + + StreamRecorder pushStreamRecorder = createTaskPushNotificationConfigRequest( + handler, AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); + Assertions.assertNull(pushStreamRecorder.getError()); + + List results = new ArrayList<>(); + List errors = new ArrayList<>(); + final CountDownLatch latch = new CountDownLatch(6); + httpClient.latch = latch; + StreamObserver streamObserver = new StreamObserver<>() { + @Override + public void onNext(StreamResponse streamResponse) { + results.add(streamResponse); + latch.countDown(); + } + + @Override + public void onError(Throwable throwable) { + errors.add(throwable); + } + + @Override + public void onCompleted() { + } + }; + sendStreamingMessageRequest(handler, streamObserver); + Assertions.assertTrue(latch.await(5, TimeUnit.SECONDS)); + Assertions.assertTrue(errors.isEmpty()); + Assertions.assertEquals(3, results.size()); + Assertions.assertEquals(3, httpClient.tasks.size()); + + io.a2a.spec.Task curr = httpClient.tasks.get(0); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), curr.status().state()); + Assertions.assertEquals(0, curr.artifacts() == null ? 0 : curr.artifacts().size()); - @Override - public void onCompleted() { - } - }; - sendStreamingMessageRequest(handler, streamObserver); - Assertions.assertTrue(latch.await(5, TimeUnit.SECONDS)); - Assertions.assertTrue(errors.isEmpty()); - Assertions.assertEquals(3, results.size()); - Assertions.assertEquals(3, httpClient.tasks.size()); - - io.a2a.spec.Task curr = httpClient.tasks.get(0); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), curr.status().state()); - Assertions.assertEquals(0, curr.artifacts() == null ? 0 : curr.artifacts().size()); - - curr = httpClient.tasks.get(1); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), curr.status().state()); - Assertions.assertEquals(1, curr.artifacts().size()); - Assertions.assertEquals(1, curr.artifacts().get(0).parts().size()); - Assertions.assertEquals("text", ((TextPart)curr.artifacts().get(0).parts().get(0)).text()); + curr = httpClient.tasks.get(1); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), curr.status().state()); + Assertions.assertEquals(1, curr.artifacts().size()); + Assertions.assertEquals(1, curr.artifacts().get(0).parts().size()); + Assertions.assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); curr = httpClient.tasks.get(2); Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); @@ -482,17 +483,17 @@ public void onCompleted() { Assertions.assertEquals(io.a2a.spec.TaskState.COMPLETED, curr.status().state()); Assertions.assertEquals(1, curr.artifacts().size()); Assertions.assertEquals(1, curr.artifacts().get(0).parts().size()); - Assertions.assertEquals("text", ((TextPart)curr.artifacts().get(0).parts().get(0)).text()); + Assertions.assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); } finally { mainEventBusProcessor.setPushNotificationExecutor(null); } } @Test - public void testOnResubscribeNoExistingTaskError() throws Exception { + public void testOnSubscribeNoExistingTaskError() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.subscribeToTask(request, streamRecorder); @@ -501,7 +502,7 @@ public void testOnResubscribeNoExistingTaskError() throws Exception { } @Test - public void testOnResubscribeExistingTaskSuccess() throws Exception { + public void testOnSubscribeExistingTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); queueManager.createOrTap(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); @@ -512,7 +513,7 @@ public void testOnResubscribeExistingTaskSuccess() throws Exception { StreamRecorder streamRecorder = StreamRecorder.create(); SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); handler.subscribeToTask(request, streamRecorder); @@ -528,24 +529,24 @@ public void testOnResubscribeExistingTaskSuccess() throws Exception { streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); List result = streamRecorder.getValues(); Assertions.assertNotNull(result); - // Per A2A Protocol Spec 3.1.6, resubscribe sends current Task as first event, + // Per A2A Protocol Spec 3.1.6, subscribe sends current Task as first event, // followed by the Message from the agent executor Assertions.assertEquals(2, result.size()); // ENFORCE that first event is Task Assertions.assertTrue(result.get(0).hasTask(), - "First event on resubscribe MUST be Task (current state)"); + "First event on subscribe MUST be Task (current state)"); // Second event should be Message from agent executor StreamResponse response = result.get(1); Assertions.assertTrue(response.hasMessage(), - "Expected Message after initial Task"); + "Expected Message after initial Task"); assertEquals(GRPC_MESSAGE, response.getMessage()); Assertions.assertNull(streamRecorder.getError()); } @Test - public void testOnResubscribeExistingTaskSuccessMocks() throws Exception { + public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); queueManager.createOrTap(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); @@ -567,12 +568,13 @@ public void testOnResubscribeExistingTaskSuccessMocks() throws Exception { StreamRecorder streamRecorder = StreamRecorder.create(); SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); try (MockedConstruction mocked = Mockito.mockConstruction( EventConsumer.class, (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll();})){ + Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll(); + })) { handler.subscribeToTask(request, streamRecorder); streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); } @@ -597,12 +599,12 @@ public void testStreamingNotSupportedError() throws Exception { } @Test - public void testStreamingNotSupportedErrorOnResubscribeToTask() throws Exception { + public void testStreamingNotSupportedErrorOnSubscribeToTask() throws Exception { // This test does not exist in the Python implementation AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() - .setName("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.subscribeToTask(request, streamRecorder); @@ -627,14 +629,14 @@ public void testListPushNotificationConfig() throws Exception { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); - StreamRecorder pushRecorder = createTaskPushNotificationConfigRequest(handler, NAME); + StreamRecorder pushRecorder = createTaskPushNotificationConfigRequest(handler, + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); Assertions.assertNull(pushRecorder.getError()); ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() - .setParent("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); + StreamRecorder streamRecorder = StreamRecorder.create(); handler.listTaskPushNotificationConfig(request, streamRecorder); Assertions.assertNull(streamRecorder.getError()); List result = streamRecorder.getValues(); @@ -654,9 +656,9 @@ public void testListPushNotificationConfigNotSupported() throws Exception { }; ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() - .setParent("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); + StreamRecorder streamRecorder = StreamRecorder.create(); handler.listTaskPushNotificationConfig(request, streamRecorder); assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); } @@ -671,9 +673,9 @@ public void testListPushNotificationConfigNoPushConfigStore() { }; ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() - .setParent("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); + StreamRecorder streamRecorder = StreamRecorder.create(); handler.listTaskPushNotificationConfig(request, streamRecorder); assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); } @@ -686,9 +688,9 @@ public void testListPushNotificationConfigTaskNotFound() { }; ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() - .setParent("tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); + StreamRecorder streamRecorder = StreamRecorder.create(); handler.listTaskPushNotificationConfig(request, streamRecorder); assertGrpcError(streamRecorder, Status.Code.NOT_FOUND); } @@ -700,13 +702,13 @@ public void testDeletePushNotificationConfig() throws Exception { agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); - StreamRecorder pushRecorder = createTaskPushNotificationConfigRequest(handler, NAME); + StreamRecorder pushRecorder = createTaskPushNotificationConfigRequest(handler, AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); Assertions.assertNull(pushRecorder.getError()); DeleteTaskPushNotificationConfigRequest request = DeleteTaskPushNotificationConfigRequest.newBuilder() - .setName(NAME) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.deleteTaskPushNotificationConfig(request, streamRecorder); @@ -723,10 +725,9 @@ public void testDeletePushNotificationConfigNotSupported() throws Exception { agentExecutorExecute = (context, eventQueue) -> { eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); DeleteTaskPushNotificationConfigRequest request = DeleteTaskPushNotificationConfigRequest.newBuilder() - .setName(NAME) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.deleteTaskPushNotificationConfig(request, streamRecorder); @@ -737,9 +738,9 @@ public void testDeletePushNotificationConfigNotSupported() throws Exception { public void testDeletePushNotificationConfigNoPushConfigStore() { DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - String NAME = "tasks/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id() + "/pushNotificationConfigs/" + AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(); DeleteTaskPushNotificationConfigRequest request = DeleteTaskPushNotificationConfigRequest.newBuilder() - .setName(NAME) + .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) + .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.deleteTaskPushNotificationConfig(request, streamRecorder); @@ -754,13 +755,13 @@ public void testOnGetExtendedAgentCard() throws Exception { @Test public void testStreamingDoesNotBlockMainThread() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - + // Track if the main thread gets blocked during streaming AtomicBoolean eventReceived = new AtomicBoolean(false); CountDownLatch streamStarted = new CountDownLatch(1); GrpcHandler.setStreamingSubscribedRunnable(streamStarted::countDown); CountDownLatch eventProcessed = new CountDownLatch(1); - + agentExecutorExecute = (context, eventQueue) -> { // Wait a bit to ensure the main thread continues try { @@ -797,16 +798,16 @@ public void onCompleted() { sendStreamingMessageRequest(handler, streamObserver); // The main thread should not be blocked - we should be able to continue immediately - Assertions.assertTrue(streamStarted.await(100, TimeUnit.MILLISECONDS), - "Streaming subscription should start quickly without blocking main thread"); + Assertions.assertTrue(streamStarted.await(100, TimeUnit.MILLISECONDS), + "Streaming subscription should start quickly without blocking main thread"); // This proves the main thread is not blocked - we can do other work // Simulate main thread doing other work Thread.sleep(50); // Wait for the actual event processing to complete - Assertions.assertTrue(eventProcessed.await(2, TimeUnit.SECONDS), - "Event should be processed within reasonable time"); + Assertions.assertTrue(eventProcessed.await(2, TimeUnit.SECONDS), + "Event should be processed within reasonable time"); // Verify we received the event and no errors occurred Assertions.assertTrue(eventReceived.get(), "Should have received streaming event"); @@ -835,7 +836,6 @@ public void testExtensionSupportRequiredErrorOnSendMessage() throws Exception { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); GrpcHandler handler = new TestGrpcHandler(cardWithExtension, requestHandler, internalExecutor); @@ -871,7 +871,6 @@ public void testExtensionSupportRequiredErrorOnSendStreamingMessage() throws Exc .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); GrpcHandler handler = new TestGrpcHandler(cardWithExtension, requestHandler, internalExecutor); @@ -907,7 +906,6 @@ public void testRequiredExtensionProvidedSuccess() throws Exception { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); // Create a TestGrpcHandler that provides the required extension in the context @@ -973,7 +971,7 @@ public ServerCallContext create(StreamObserver streamObserver) { UnauthenticatedUser.INSTANCE, Map.of("grpc_response_observer", streamObserver), new HashSet<>(), - "2.0" // Incompatible version + "2.0" // Incompatible version ); } }; @@ -1018,7 +1016,7 @@ public ServerCallContext create(StreamObserver streamObserver) { UnauthenticatedUser.INSTANCE, Map.of("grpc_response_observer", streamObserver), new HashSet<>(), - "2.0" // Incompatible version + "2.0" // Incompatible version ); } }; @@ -1063,7 +1061,7 @@ public ServerCallContext create(StreamObserver streamObserver) { UnauthenticatedUser.INSTANCE, Map.of("grpc_response_observer", streamObserver), new HashSet<>(), - "1.1" // Compatible version (same major version) + "1.1" // Compatible version (same major version) ); } }; @@ -1114,7 +1112,7 @@ public ServerCallContext create(StreamObserver streamObserver) { UnauthenticatedUser.INSTANCE, Map.of("grpc_response_observer", streamObserver), new HashSet<>(), - null // No version - should default to 1.0 + null // No version - should default to 1.0 ); } }; @@ -1147,20 +1145,16 @@ private StreamRecorder sendMessageRequest(GrpcHandler handl return streamRecorder; } - private StreamRecorder createTaskPushNotificationConfigRequest(GrpcHandler handler, String name) throws Exception { + private StreamRecorder createTaskPushNotificationConfigRequest(GrpcHandler handler, String taskId, String id) throws Exception { taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); PushNotificationConfig config = PushNotificationConfig.newBuilder() .setUrl("http://example.com") .setId("config456") .build(); - TaskPushNotificationConfig taskPushNotificationConfig = TaskPushNotificationConfig.newBuilder() - .setName(name) - .setPushNotificationConfig(config) - .build(); CreateTaskPushNotificationConfigRequest setRequest = CreateTaskPushNotificationConfigRequest.newBuilder() - .setConfig(taskPushNotificationConfig) + .setConfig(config) .setConfigId("config456") - .setParent("tasks/" + MINIMAL_TASK.id()) + .setTaskId(MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -1169,9 +1163,10 @@ private StreamRecorder createTaskPushNotificationCon return streamRecorder; } - private StreamRecorder getTaskPushNotificationConfigRequest(GrpcHandler handler, String name) throws Exception { + private StreamRecorder getTaskPushNotificationConfigRequest(GrpcHandler handler, String taskId, String id) throws Exception { GetTaskPushNotificationConfigRequest request = GetTaskPushNotificationConfigRequest.newBuilder() - .setName(name) + .setTaskId(taskId) + .setId(id) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); handler.getTaskPushNotificationConfig(request, streamRecorder); @@ -1251,6 +1246,7 @@ public void testListTasksEmptyResultIncludesAllFields() throws Exception { } private static class TestGrpcHandler extends GrpcHandler { + private final AgentCard card; private final RequestHandler handler; private final java.util.concurrent.Executor executor; 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 a592bd55d..da22cf592 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 @@ -160,7 +160,7 @@ public Flow.Publisher onSubscribeToTask( try { Flow.Publisher publisher = - requestHandler.onResubscribeToTask(request.getParams(), context); + requestHandler.onSubscribeToTask(request.getParams(), context); // 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); 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 8d2751627..3e925e266 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 @@ -677,7 +677,9 @@ public void testGetPushNotificationConfigSuccess() { handler.setPushNotificationConfig(request, callContext); GetTaskPushNotificationConfigRequest getRequest - = new GetTaskPushNotificationConfigRequest("111", new GetTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + = new GetTaskPushNotificationConfigRequest("111", new GetTaskPushNotificationConfigParams( + MINIMAL_TASK.id(), + "c295ea44-7543-4f78-b524-7a38915ad6e4")); GetTaskPushNotificationConfigResponse getResponse = handler.getPushNotificationConfig(getRequest, callContext); TaskPushNotificationConfig expectedConfig = new TaskPushNotificationConfig(MINIMAL_TASK.id(), @@ -802,7 +804,7 @@ public void onComplete() { } @Test - public void testOnResubscribeExistingTaskSuccess() { + public void testOnSubscribeExistingTaskSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); queueManager.createOrTap(MINIMAL_TASK.id()); @@ -850,7 +852,7 @@ public void onNext(SendStreamingMessageResponse item) { // Per A2A Protocol Spec 3.1.6: ENFORCE that first event is Task if (!receivedInitialTask.get()) { assertTrue(event instanceof Task, - "First event on resubscribe MUST be Task (current state), but was: " + event.getClass().getSimpleName()); + "First event on subscribe MUST be Task (current state), but was: " + event.getClass().getSimpleName()); receivedInitialTask.set(true); } else { // Subsequent events should be the expected type (Message in this case) @@ -882,7 +884,7 @@ public void onComplete() { } @Test - public void testOnResubscribeExistingTaskSuccessMocks() throws Exception { + public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); queueManager.createOrTap(MINIMAL_TASK.id()); @@ -915,7 +917,7 @@ public void testOnResubscribeExistingTaskSuccessMocks() throws Exception { CompletableFuture future = new CompletableFuture<>(); List results = new ArrayList<>(); - // Unlike testOnResubscribeExistingTaskSuccess() the ZeroPublisher.fromIterable() + // Unlike testOnSubscribeExistingTaskSuccess() the ZeroPublisher.fromIterable() // used to mock the events completes once it has sent all the items. So no special thread // handling is needed. response.subscribe(new Flow.Subscriber<>() { @@ -955,7 +957,7 @@ public void onComplete() { } @Test - public void testOnResubscribeNoExistingTaskError() { + public void testOnSubscribeNoExistingTaskError() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); @@ -1048,7 +1050,7 @@ public void onComplete() { } @Test - public void testStreamingNotSupportedErrorOnResubscribeToTask() { + public void testStreamingNotSupportedErrorOnSubscribeToTask() { // This test does not exist in the Python implementation AgentCard card = createAgentCard(false, true); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); @@ -1125,7 +1127,8 @@ public void testOnGetPushNotificationNoPushNotifierConfig() { taskStore.save(MINIMAL_TASK, false); GetTaskPushNotificationConfigRequest request - = new GetTaskPushNotificationConfigRequest("id", new GetTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + = new GetTaskPushNotificationConfigRequest("id", new GetTaskPushNotificationConfigParams( + MINIMAL_TASK.id(),"c295ea44-7543-4f78-b524-7a38915ad6e4")); GetTaskPushNotificationConfigResponse response = handler.getPushNotificationConfig(request, callContext); Assertions.assertNotNull(response.getError()); @@ -1612,7 +1615,6 @@ public void testExtensionSupportRequiredErrorOnMessageSend() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); @@ -1651,7 +1653,6 @@ public void testExtensionSupportRequiredErrorOnMessageSendStream() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); @@ -1720,7 +1721,6 @@ public void testRequiredExtensionProvidedSuccess() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); 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 f4b594f6b..ada8e8170 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 @@ -184,7 +184,7 @@ public HTTPRestResponse subscribeToTask(String taskId, String tenant, ServerCall return createErrorResponse(new InvalidRequestError("Streaming is not supported by the agent")); } TaskIdParams params = new TaskIdParams(taskId, tenant); - Flow.Publisher publisher = requestHandler.onResubscribeToTask(params, context); + Flow.Publisher publisher = requestHandler.onSubscribeToTask(params, context); return createStreamingResponse(publisher); } catch (A2AError e) { return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(e).toJson())); 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 48eaae912..2d1c19b84 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,5 +1,6 @@ package io.a2a.transport.rest.handler; + import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -252,18 +253,15 @@ public void testPushNotificationConfigSuccess() { String requestBody = """ { - "parent": "tasks/%s", + "taskId": "%s", + "configId": "default-config-id", "config": { - "name": "tasks/%s/pushNotificationConfigs/default-config-id", - "pushNotificationConfig": { - "id":"default-config-id", - "url": "https://example.com/callback", - "authentication": { - "schemes": ["jwt"] - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } } - }""".formatted(MINIMAL_TASK.id(), MINIMAL_TASK.id()); + }""".formatted(MINIMAL_TASK.id()); RestHandler.HTTPRestResponse response = handler.CreateTaskPushNotificationConfiguration( MINIMAL_TASK.id(), requestBody, "", callContext); @@ -300,18 +298,15 @@ public void testGetPushNotificationConfig() { // First, create a push notification config String createRequestBody = """ { - "parent": "tasks/%s", + "taskId": "%s", + "configId": "default-config-id", "config": { - "name": "tasks/%s/pushNotificationConfigs/default-config-id", - "pushNotificationConfig": { - "id":"default-config-id", - "url": "https://example.com/callback", - "authentication": { - "schemes": ["jwt"] - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } } - }""".formatted(MINIMAL_TASK.id(), MINIMAL_TASK.id()); + }""".formatted(MINIMAL_TASK.id()); RestHandler.HTTPRestResponse response = handler.CreateTaskPushNotificationConfiguration(MINIMAL_TASK.id(), createRequestBody, "", callContext); Assertions.assertEquals(201, response.getStatusCode(), response.toString()); Assertions.assertEquals("application/json", response.getContentType()); @@ -458,7 +453,6 @@ public void testExtensionSupportRequiredErrorOnSendMessage() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); @@ -508,7 +502,6 @@ public void testExtensionSupportRequiredErrorOnSendStreamingMessage() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); @@ -596,7 +589,6 @@ public void testRequiredExtensionProvidedSuccess() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .protocolVersions(AgentCard.CURRENT_PROTOCOL_VERSION) .build(); RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); From b103c8a2cb7808af01de3ce68bd65e296269a8a4 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 9 Feb 2026 18:22:52 +0000 Subject: [PATCH 021/192] fix: Noargs constructor for Jakarta CDI compatibility (#637) --- .../server/events/MainEventBusProcessor.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java index 8b3dc6fa3..ca47c7444 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java @@ -58,17 +58,26 @@ public class MainEventBusProcessor implements Runnable { */ private volatile @Nullable java.util.concurrent.Executor pushNotificationExecutor = null; - private final MainEventBus eventBus; + private MainEventBus eventBus; - private final TaskStore taskStore; + private TaskStore taskStore; - private final PushNotificationSender pushSender; + private PushNotificationSender pushSender; - private final QueueManager queueManager; + private QueueManager queueManager; private volatile boolean running = true; private @Nullable Thread processorThread; + /** + * No-arg constructor for CDI proxying. + * CDI requires this for @ApplicationScoped beans. + * Fields are initialized via the @Inject constructor. + */ + @SuppressWarnings("NullAway") + protected MainEventBusProcessor() { + } + @Inject public MainEventBusProcessor(MainEventBus eventBus, TaskStore taskStore, PushNotificationSender pushSender, QueueManager queueManager) { this.eventBus = eventBus; From ce6453c119dd21457663f4cb2fbf037bfdc43fbe Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 10 Feb 2026 13:57:01 +0000 Subject: [PATCH 022/192] fix: Race condition in testNonBlockingWithMultipleMessages (#636) Addresses intermittent test failure where subscribeToTask created child queues but EventConsumer polling loops hadn't started yet when the agent executed, causing emitted events to be lost. Root Cause: - awaitStreamingSubscription() only guarantees transport-level subscription (Flow.Subscriber.onSubscribe() called) - EventConsumer polling starts asynchronously on eventConsumerExecutor thread - Agent execution could begin before EventConsumer was actively polling - Events emitted before polling started were lost in the queue Solution: - Added awaitChildQueueCountStable() to TestUtilsBean - Waits for child queue count to match expected value for 3 consecutive checks (150ms total), ensuring EventConsumer is actively polling - Follows pattern from commit 18d2abff which fixed similar race condition - Exposed REST endpoints in all transports (JSON-RPC, gRPC, REST) - Added client helper in AbstractA2AServerTest - Applied stability check after subscribeToTask() in tests - Increased timeouts from 10s to 15s for CI stability Files Modified: - TestUtilsBean.java: Core synchronization logic with comprehensive Javadoc - A2ATestRoutes.java (JSON-RPC, REST): REST endpoints for stability checks - A2ATestResource.java (gRPC): REST endpoints for stability checks - AbstractA2AServerTest.java: Client helper and extensive inline comments --- .../server/grpc/quarkus/A2ATestResource.java | 36 ++++++++++++++ .../server/apps/quarkus/A2ATestRoutes.java | 24 +++++++++ .../server/rest/quarkus/A2ATestRoutes.java | 24 +++++++++ .../apps/common/AbstractA2AServerTest.java | 45 ++++++++++++++++- .../a2a/server/apps/common/TestUtilsBean.java | 49 +++++++++++++++++++ 5 files changed, 176 insertions(+), 2 deletions(-) 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 4136eb70b..fc57c705d 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 @@ -137,4 +137,40 @@ public Response savePushNotificationConfigInStore(@PathParam("taskId") String ta testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); return Response.ok().build(); } + + /** + * REST endpoint to wait for queue poller to start. + * Waits for the EventConsumer polling loop to start for the specified task's queue, + * ensuring the queue is ready to receive and process events. + * + * @param taskId the task ID whose queue poller to wait for + * @return HTTP 200 response when poller has started + * @throws InterruptedException if interrupted while waiting + */ + @POST + @Path("/queue/awaitPollerStart/{taskId}") + public Response awaitQueuePollerStart(@PathParam("taskId") String taskId) throws InterruptedException { + testUtilsBean.awaitQueuePollerStart(taskId); + return Response.ok().build(); + } + + /** + * REST endpoint to wait for child queue count to stabilize. + * Waits for the specified task's child queue count to match expectedCount for 3 consecutive + * checks (150ms total), ensuring EventConsumer polling loops have started. + * + * @param taskId the task ID whose child queues to monitor + * @param expectedCount the expected number of active child queues + * @param timeoutMs maximum time to wait in milliseconds + * @return HTTP 200 response with "true" if count stabilized, "false" if timeout occurred + * @throws InterruptedException if interrupted while waiting + */ + @POST + @Path("/queue/awaitChildCountStable/{taskId}/{expectedCount}/{timeoutMs}") + public Response awaitChildQueueCountStable(@PathParam("taskId") String taskId, + @PathParam("expectedCount") int expectedCount, + @PathParam("timeoutMs") long timeoutMs) throws InterruptedException { + boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); + return Response.ok(String.valueOf(stable), TEXT_PLAIN).build(); + } } 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 12eae5a4d..937c8a2b1 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 @@ -185,6 +185,30 @@ public void saveTaskPushNotificationConfig(@Param String taskId, @Body String bo } } + /** + * REST endpoint to wait for child queue count to stabilize. + * Waits for the specified task's child queue count to match expectedCount for 3 consecutive + * checks (150ms total), ensuring EventConsumer polling loops have started. + * + * @param taskId the task ID whose child queues to monitor + * @param expectedCountStr the expected number of active child queues (as string) + * @param timeoutMsStr maximum time to wait in milliseconds (as string) + * @param rc the Vert.x routing context + */ + @Route(path = "/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) + public void awaitChildQueueCountStable(@Param("taskId") String taskId, @Param("expectedCount") String expectedCountStr, @Param("timeoutMs") String timeoutMsStr, RoutingContext rc) { + try { + int expectedCount = Integer.parseInt(expectedCountStr); + long timeoutMs = Long.parseLong(timeoutMsStr); + boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); + rc.response() + .setStatusCode(200) + .end(String.valueOf(stable)); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + private void errorResponse(Throwable t, RoutingContext rc) { t.printStackTrace(); rc.response() 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 57d6965a4..0ce5750b3 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 @@ -185,6 +185,30 @@ public void saveTaskPushNotificationConfig(@Param String taskId, @Body String bo } } + /** + * REST endpoint to wait for child queue count to stabilize. + * Waits for the specified task's child queue count to match expectedCount for 3 consecutive + * checks (150ms total), ensuring EventConsumer polling loops have started. + * + * @param taskId the task ID whose child queues to monitor + * @param expectedCountStr the expected number of active child queues (as string) + * @param timeoutMsStr maximum time to wait in milliseconds (as string) + * @param rc the Vert.x routing context + */ + @Route(path = "/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) + public void awaitChildQueueCountStable(@Param("taskId") String taskId, @Param("expectedCount") String expectedCountStr, @Param("timeoutMs") String timeoutMsStr, RoutingContext rc) { + try { + int expectedCount = Integer.parseInt(expectedCountStr); + long timeoutMs = Long.parseLong(timeoutMsStr); + boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); + rc.response() + .setStatusCode(200) + .end(String.valueOf(stable)); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + private void errorResponse(Throwable t, RoutingContext rc) { t.printStackTrace(); rc.response() 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 5522e4dbf..1c6dcdde4 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 @@ -1401,6 +1401,19 @@ public void testNonBlockingWithMultipleMessages() throws Exception { assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); + // CRITICAL SYNCHRONIZATION: Wait for subscribeToTask's EventConsumer polling loop to start + // + // Race condition: awaitStreamingSubscription() only guarantees transport-level subscription + // (Flow.Subscriber.onSubscribe() called), but EventConsumer polling starts asynchronously + // on a separate thread. Without this check, the agent could emit events before any consumer + // is ready to receive them, causing events to be lost. + // + // This stability check waits for the child queue count to match expectedCount for 3 + // consecutive checks (150ms), ensuring the EventConsumer is actively polling and won't + // miss events when the agent executes. + assertTrue(awaitChildQueueCountStable(taskId, 1, 15000), + "subscribeToTask child queue should be created and stable"); + // 3. Send second streaming message to same taskId Message message2 = Message.builder(MESSAGE) .taskId(multiEventTaskId) // Same taskId @@ -1435,8 +1448,8 @@ public void testNonBlockingWithMultipleMessages() throws Exception { "Stream subscription should be established"); // 4. Verify both consumers received artifact-2 and completion - assertTrue(resubEventLatch.await(10, TimeUnit.SECONDS)); - assertTrue(streamEventLatch.await(10, TimeUnit.SECONDS)); + assertTrue(resubEventLatch.await(15, TimeUnit.SECONDS)); + assertTrue(streamEventLatch.await(15, TimeUnit.SECONDS)); assertFalse(resubUnexpectedEvent.get()); assertFalse(streamUnexpectedEvent.get()); @@ -1492,6 +1505,34 @@ public void testNonBlockingWithMultipleMessages() throws Exception { } } + /** + * Waits for the child queue count to stabilize at the expected value by calling the server's + * test endpoint. This ensures EventConsumer polling loops have started before proceeding. + * + * @param taskId the task ID whose child queues to monitor + * @param expectedCount the expected number of active child queues + * @param timeoutMs maximum time to wait in milliseconds + * @return true if the count stabilized at the expected value, false if timeout occurred + * @throws IOException if the HTTP request fails + * @throws InterruptedException if interrupted while waiting + */ + private boolean awaitChildQueueCountStable(String taskId, int expectedCount, long timeoutMs) throws IOException, InterruptedException { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/queue/awaitChildCountStable/" + + taskId + "/" + expectedCount + "/" + timeoutMs)) + .POST(HttpRequest.BodyPublishers.noBody()) + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(response.statusCode() + ": Awaiting child queue count failed! " + response.body()); + } + return Boolean.parseBoolean(response.body()); + } + @Test @Timeout(value = 1, unit = TimeUnit.MINUTES) public void testInputRequiredWorkflow() throws Exception { diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java index 45483f214..f94d93043 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java @@ -61,4 +61,53 @@ public void deleteTaskPushNotificationConfig(String taskId, String configId) { public void saveTaskPushNotificationConfig(String taskId, PushNotificationConfig notificationConfig) { pushNotificationConfigStore.setInfo(taskId, notificationConfig); } + + /** + * Waits for the EventConsumer polling loop to start for the specified task's queue. + * This ensures the queue is ready to receive and process events. + * + * @param taskId the task ID whose queue poller to wait for + * @throws InterruptedException if interrupted while waiting + */ + public void awaitQueuePollerStart(String taskId) throws InterruptedException { + queueManager.awaitQueuePollerStart(queueManager.get(taskId)); + } + + /** + * Waits for the child queue count to stabilize at the expected value. + *

        + * This method addresses a race condition where EventConsumer polling loops may not have started + * yet when events are emitted. It waits for the child queue count to match the expected value + * for 3 consecutive checks (150ms total), ensuring EventConsumers are actively polling and + * won't miss events. + *

        + * Use this after operations that create child queues (e.g., subscribeToTask, sendMessage) to + * ensure their EventConsumer polling loops have started before the agent emits events. + * + * @param taskId the task ID whose child queues to monitor + * @param expectedCount the expected number of active child queues + * @param timeoutMs maximum time to wait in milliseconds + * @return true if the count stabilized at the expected value, false if timeout occurred + * @throws InterruptedException if interrupted while waiting + */ + public boolean awaitChildQueueCountStable(String taskId, int expectedCount, long timeoutMs) throws InterruptedException { + long endTime = System.currentTimeMillis() + timeoutMs; + int consecutiveMatches = 0; + final int requiredMatches = 3; // Count must match 3 times in a row (150ms) to be considered stable + + while (System.currentTimeMillis() < endTime) { + int count = queueManager.getActiveChildQueueCount(taskId); + if (count == expectedCount) { + consecutiveMatches++; + if (consecutiveMatches >= requiredMatches) { + // Count is stable - all child queues exist and haven't closed + return true; + } + } else { + consecutiveMatches = 0; // Reset if count changes + } + Thread.sleep(50); + } + return false; + } } From 02ba508be90781c9365d4d3b388bf792a17ad3fc Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 10 Feb 2026 14:55:45 +0000 Subject: [PATCH 023/192] feat: Implement PushNotifications as per the 1.0 spec (#622) Fixes #490 Fixes: #594 --- ...otificationConfigStoreIntegrationTest.java | 30 +-- .../jpa/MockPushNotificationSender.java | 23 +- .../server/events/MainEventBusProcessor.java | 46 ++-- .../tasks/BasePushNotificationSender.java | 52 ++++- .../server/tasks/PushNotificationSender.java | 34 ++- .../AbstractA2ARequestHandlerTest.java | 11 +- .../tasks/PushNotificationSenderTest.java | 201 +++++++++++++++--- .../grpc/handler/GrpcHandlerTest.java | 47 ++-- .../jsonrpc/handler/JSONRPCHandlerTest.java | 48 +++-- 9 files changed, 345 insertions(+), 147 deletions(-) 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 0366e236a..96f8f3adc 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 @@ -151,11 +151,12 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep assertTrue(updateLatch.await(10, TimeUnit.SECONDS), "Timeout waiting for task update"); // Step 5: Poll for the async notification to be captured + // With the new StreamingEventKind support, we receive all event types (Task, Message, TaskArtifactUpdateEvent, etc.) long end = System.currentTimeMillis() + 5000; boolean notificationReceived = false; while (System.currentTimeMillis() < end) { - if (!mockPushNotificationSender.getCapturedTasks().isEmpty()) { + if (!mockPushNotificationSender.getCapturedEvents().isEmpty()) { notificationReceived = true; break; } @@ -165,17 +166,22 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep assertTrue(notificationReceived, "Timeout waiting for push notification."); // Step 6: Verify the captured notification - Queue capturedTasks = mockPushNotificationSender.getCapturedTasks(); - - // Verify the notification contains the correct task with artifacts - Task notifiedTaskWithArtifact = capturedTasks.stream() - .filter(t -> taskId.equals(t.id()) && t.artifacts() != null && t.artifacts().size() > 0) - .findFirst() - .orElse(null); - - assertNotNull(notifiedTaskWithArtifact, "Notification should contain the updated task with artifacts"); - assertEquals(taskId, notifiedTaskWithArtifact.id()); - assertEquals(1, notifiedTaskWithArtifact.artifacts().size(), "Task should have one artifact from the update"); + // Check if we received events for this task (could be Task, TaskArtifactUpdateEvent, etc.) + Queue capturedEvents = mockPushNotificationSender.getCapturedEvents(); + + // Look for Task events with artifacts OR TaskArtifactUpdateEvent for this task + boolean hasTaskWithArtifact = capturedEvents.stream() + .filter(e -> e instanceof Task) + .map(e -> (Task) e) + .anyMatch(t -> taskId.equals(t.id()) && t.artifacts() != null && t.artifacts().size() > 0); + + boolean hasArtifactUpdateEvent = capturedEvents.stream() + .filter(e -> e instanceof io.a2a.spec.TaskArtifactUpdateEvent) + .map(e -> (io.a2a.spec.TaskArtifactUpdateEvent) e) + .anyMatch(e -> taskId.equals(e.taskId())); + + assertTrue(hasTaskWithArtifact || hasArtifactUpdateEvent, + "Notification should contain either Task with artifacts or TaskArtifactUpdateEvent for task " + taskId); // Step 7: Clean up - delete the push notification configuration client.deleteTaskPushNotificationConfigurations( diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java index 0a6bba415..2275388a9 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java @@ -8,6 +8,7 @@ import jakarta.enterprise.inject.Alternative; import io.a2a.server.tasks.PushNotificationSender; +import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; /** @@ -19,18 +20,30 @@ @Priority(100) public class MockPushNotificationSender implements PushNotificationSender { - private final Queue capturedTasks = new ConcurrentLinkedQueue<>(); + private final Queue capturedEvents = new ConcurrentLinkedQueue<>(); @Override - public void sendNotification(Task task) { - capturedTasks.add(task); + public void sendNotification(StreamingEventKind event) { + capturedEvents.add(event); } + public Queue getCapturedEvents() { + return capturedEvents; + } + + /** + * For backward compatibility - provides access to Task events only. + */ public Queue getCapturedTasks() { - return capturedTasks; + Queue tasks = new ConcurrentLinkedQueue<>(); + capturedEvents.stream() + .filter(e -> e instanceof Task) + .map(e -> (Task) e) + .forEach(tasks::add); + return tasks; } public void clear() { - capturedTasks.clear(); + capturedEvents.clear(); } } diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java index ca47c7444..0fc7b3aa9 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java @@ -16,6 +16,7 @@ import io.a2a.spec.InternalError; import io.a2a.spec.Message; import io.a2a.spec.Task; +import io.a2a.spec.StreamingEventKind; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatusUpdateEvent; import org.slf4j.Logger; @@ -220,24 +221,14 @@ private void processEvent(MainEventBusContext context) { // Step 2: Send push notification AFTER successful persistence (only from active node) // Skip push notifications for replicated events to avoid duplicate notifications in multi-instance deployments - if (eventToDistribute == event && !isReplicated) { - // Capture task state immediately after persistence, before going async - // This ensures we send the task as it existed when THIS event was processed, - // not whatever state might exist later when the async callback executes - Task taskSnapshot = taskStore.get(taskId); - if (taskSnapshot != null) { - sendPushNotification(taskId, taskSnapshot); - } else { - LOGGER.warn("Task {} not found in TaskStore after successful persistence, skipping push notification", taskId); - } + // Push notifications are sent for all StreamingEventKind events (Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent) + // per A2A spec section 4.3.3 + if (!isReplicated && event instanceof StreamingEventKind streamingEvent) { + // Send the streaming event directly - it will be wrapped in StreamResponse format by PushNotificationSender + sendPushNotification(taskId, streamingEvent); } // Step 3: Then distribute to ChildQueues (clients see either event or error AFTER persistence attempt) - if (eventToDistribute == null) { - LOGGER.error("MainEventBusProcessor: eventToDistribute is NULL for task {} - this should never happen!", taskId); - eventToDistribute = new InternalError("Internal error: event processing failed"); - } - int childCount = mainQueue.getChildCount(); LOGGER.debug("MainEventBusProcessor: Distributing {} to {} children for task {}", eventToDistribute.getClass().getSimpleName(), childCount, taskId); @@ -313,7 +304,7 @@ private boolean updateTaskStore(String taskId, Event event, boolean isReplicated } /** - * Sends push notification for the task AFTER persistence. + * Sends push notification for the streaming event AFTER persistence. *

        * This is called after updateTaskStore() to ensure the notification contains * the latest persisted state, avoiding race conditions. @@ -324,10 +315,15 @@ private boolean updateTaskStore(String taskId, Event event, boolean isReplicated * PushNotificationSender.sendNotification() was causing streaming delays. *

        *

        - * IMPORTANT: The task parameter is a snapshot captured immediately after - * persistence. This ensures we send the task state as it existed when THIS event - * was processed, not whatever state might exist in TaskStore when the async - * callback executes (subsequent events may have already updated the store). + * IMPORTANT: The event parameter is the actual event being processed. + * This ensures we send the event as it was when processed, not whatever state + * might exist in TaskStore when the async callback executes (subsequent events + * may have already updated the store). + *

        + *

        + * Supports all StreamingEventKind event types per A2A spec section 4.3.3: + * Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent. + * The event will be automatically wrapped in StreamResponse format by JsonUtil. *

        *

        * NOTE: Tests can inject a synchronous executor via setPushNotificationExecutor() @@ -335,16 +331,16 @@ private boolean updateTaskStore(String taskId, Event event, boolean isReplicated *

        * * @param taskId the task ID - * @param task the task snapshot to send (captured immediately after persistence) + * @param event the streaming event to send (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent) */ - private void sendPushNotification(String taskId, Task task) { + private void sendPushNotification(String taskId, StreamingEventKind event) { Runnable pushTask = () -> { try { - if (task != null) { + if (event != null) { LOGGER.debug("Sending push notification for task {}", taskId); - pushSender.sendNotification(task); + pushSender.sendNotification(event); } else { - LOGGER.debug("Skipping push notification - task snapshot is null for task {}", taskId); + LOGGER.debug("Skipping push notification - event is null for task {}", taskId); } } catch (Exception e) { LOGGER.error("Error sending push notification for task {}", taskId, e); 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 d6d4a2369..58c03369d 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 @@ -5,6 +5,7 @@ import static io.a2a.common.A2AHeaders.X_A2A_NOTIFICATION_TOKEN; import io.a2a.spec.TaskPushNotificationConfig; +import jakarta.annotation.Nullable; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -20,8 +21,12 @@ import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.Message; import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; +import io.a2a.spec.TaskArtifactUpdateEvent; +import io.a2a.spec.TaskStatusUpdateEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,11 +67,17 @@ public BasePushNotificationSender(PushNotificationConfigStore configStore, A2AHt } @Override - public void sendNotification(Task task) { + public void sendNotification(StreamingEventKind event) { + String taskId = extractTaskId(event); + if (taskId == null) { + LOGGER.warn("Cannot send push notification: event does not contain taskId"); + return; + } + List configs = new ArrayList<>(); String nextPageToken = null; do { - ListTaskPushNotificationConfigResult pageResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(task.id(), + ListTaskPushNotificationConfigResult pageResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId, DEFAULT_PAGE_SIZE, nextPageToken, "")); if (!pageResult.configs().isEmpty()) { configs.addAll(pageResult.configs()); @@ -76,7 +87,7 @@ public void sendNotification(Task task) { List> dispatchResults = configs .stream() - .map(pushConfig -> dispatch(task, pushConfig.pushNotificationConfig())) + .map(pushConfig -> dispatch(event, pushConfig.pushNotificationConfig())) .toList(); CompletableFuture allFutures = CompletableFuture.allOf(dispatchResults.toArray(new CompletableFuture[0])); CompletableFuture dispatchResult = allFutures.thenApply(v -> dispatchResults.stream() @@ -84,18 +95,37 @@ public void sendNotification(Task task) { try { boolean allSent = dispatchResult.get(); if (!allSent) { - LOGGER.warn("Some push notifications failed to send for taskId: " + task.id()); + LOGGER.warn("Some push notifications failed to send for taskId: " + taskId); } } catch (InterruptedException | ExecutionException e) { - LOGGER.warn("Some push notifications failed to send for taskId " + task.id() + ": {}", e.getMessage(), e); + LOGGER.warn("Some push notifications failed to send for taskId " + taskId + ": {}", e.getMessage(), e); + } + } + + /** + * Extracts the task ID from a StreamingEventKind event. + * + * @param event the streaming event + * @return the task ID, or null if not available + */ + protected @Nullable String extractTaskId(StreamingEventKind event) { + if (event instanceof Task task) { + return task.id(); + } else if (event instanceof Message message) { + return message.taskId(); + } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { + return statusUpdate.taskId(); + } else if (event instanceof TaskArtifactUpdateEvent artifactUpdate) { + return artifactUpdate.taskId(); } + throw new IllegalStateException("Unknown StreamingEventKind: " + event); } - private CompletableFuture dispatch(Task task, PushNotificationConfig pushInfo) { - return CompletableFuture.supplyAsync(() -> dispatchNotification(task, pushInfo)); + private CompletableFuture dispatch(StreamingEventKind event, PushNotificationConfig pushInfo) { + return CompletableFuture.supplyAsync(() -> dispatchNotification(event, pushInfo)); } - private boolean dispatchNotification(Task task, PushNotificationConfig pushInfo) { + private boolean dispatchNotification(StreamingEventKind event, PushNotificationConfig pushInfo) { String url = pushInfo.url(); String token = pushInfo.token(); @@ -106,9 +136,11 @@ private boolean dispatchNotification(Task task, PushNotificationConfig pushInfo) String body; try { - body = JsonUtil.toJson(task); + // JsonUtil.toJson automatically wraps StreamingEventKind in StreamResponse format + // (task/message/statusUpdate/artifactUpdate) per A2A spec section 4.3.3 + body = JsonUtil.toJson(event); } catch (Throwable throwable) { - LOGGER.debug("Error writing value as string: {}", throwable.getMessage(), throwable); + LOGGER.error("Error serializing StreamingEventKind to JSON: {}", throwable.getMessage(), throwable); return false; } diff --git a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java index 2013d6a22..f8b7b018d 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java +++ b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java @@ -1,5 +1,6 @@ package io.a2a.server.tasks; +import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; /** @@ -27,7 +28,8 @@ * {@link BasePushNotificationSender} provides HTTP webhook delivery: *
          *
        • Retrieves webhook URLs from {@link PushNotificationConfigStore}
        • - *
        • Sends HTTP POST requests with task JSON payload
        • + *
        • Wraps events in StreamResponse format (per A2A spec section 4.3.3)
        • + *
        • Sends HTTP POST requests with StreamResponse JSON payload
        • *
        • Logs errors but doesn't fail the request
        • *
        * @@ -47,11 +49,12 @@ * @Priority(100) * public class KafkaPushNotificationSender implements PushNotificationSender { * @Inject - * KafkaProducer producer; + * KafkaProducer producer; * * @Override - * public void sendNotification(Task task) { - * producer.send("task-updates", task.id(), task); + * public void sendNotification(StreamingEventKind event) { + * String taskId = extractTaskId(event); + * producer.send("task-updates", taskId, event); * } * } * } @@ -78,18 +81,29 @@ public interface PushNotificationSender { /** - * Sends a push notification containing the latest task state. + * Sends a push notification containing a streaming event. *

        - * Called after the task has been persisted to {@link TaskStore}. Retrieve push - * notification URLs or messaging configurations from {@link PushNotificationConfigStore} - * using {@code task.id()}. + * Called after the event has been persisted to {@link TaskStore}. The event is wrapped + * in a StreamResponse format (per A2A spec section 4.3.3) with the appropriate oneof + * field set (task, message, statusUpdate, or artifactUpdate). *

        *

        + * Retrieve push notification URLs or messaging configurations from + * {@link PushNotificationConfigStore} using the task ID extracted from the event. + *

        + * Supported event types: + *
          + *
        • {@link Task} - wrapped in StreamResponse.task
        • + *
        • {@link io.a2a.spec.Message} - wrapped in StreamResponse.message
        • + *
        • {@link io.a2a.spec.TaskStatusUpdateEvent} - wrapped in StreamResponse.statusUpdate
        • + *
        • {@link io.a2a.spec.TaskArtifactUpdateEvent} - wrapped in StreamResponse.artifactUpdate
        • + *
        + *

        * Error Handling: Log errors but don't throw exceptions. Notifications are * best-effort and should not fail the primary request. *

        * - * @param task the task with current state and artifacts to send + * @param event the streaming event to send (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent) */ - void sendNotification(Task task); + void sendNotification(StreamingEventKind event); } 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 968937b89..e428c679e 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 @@ -41,6 +41,7 @@ import io.a2a.spec.AgentInterface; import io.a2a.spec.Event; import io.a2a.spec.Message; +import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; @@ -189,7 +190,7 @@ public boolean isReplicated() { @Dependent @IfBuildProfile("test") protected static class TestHttpClient implements A2AHttpClient { - public final List tasks = Collections.synchronizedList(new ArrayList<>()); + public final List events = Collections.synchronizedList(new ArrayList<>()); public volatile CountDownLatch latch; @Override @@ -218,8 +219,10 @@ public PostBuilder body(String body) { @Override public A2AHttpResponse post() throws IOException, InterruptedException { try { - Task task = JsonUtil.fromJson(body, Task.class); - tasks.add(task); + // Parse StreamResponse format to extract the streaming event + // The body contains a wrapper with one of: task, message, statusUpdate, artifactUpdate + StreamingEventKind event = JsonUtil.fromJson(body, StreamingEventKind.class); + events.add(event); return new A2AHttpResponse() { @Override public int status() { @@ -237,7 +240,7 @@ public String body() { } }; } catch (JsonProcessingException e) { - throw new IOException("Failed to parse task JSON", e); + throw new IOException("Failed to parse StreamingEventKind JSON", e); } finally { if (latch != null) { latch.countDown(); 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 7bb67f681..e58ad384b 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 @@ -21,10 +21,17 @@ import io.a2a.common.A2AHeaders; import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.jsonrpc.common.json.JsonUtil; +import io.a2a.spec.Artifact; +import io.a2a.spec.Message; +import io.a2a.spec.Part; import io.a2a.spec.PushNotificationConfig; +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.BeforeEach; import org.junit.jupiter.api.Test; @@ -35,12 +42,14 @@ public class PushNotificationSenderTest { private BasePushNotificationSender sender; /** - * Simple test implementation of A2AHttpClient that captures HTTP calls for verification + * Simple test implementation of A2AHttpClient that captures HTTP calls for verification. + * Now captures StreamingEventKind events wrapped in StreamResponse format. */ private static class TestHttpClient implements A2AHttpClient { - final List tasks = Collections.synchronizedList(new ArrayList<>()); + final List events = Collections.synchronizedList(new ArrayList<>()); final List urls = Collections.synchronizedList(new ArrayList<>()); final List> headers = Collections.synchronizedList(new ArrayList<>()); + final List rawBodies = Collections.synchronizedList(new ArrayList<>()); volatile CountDownLatch latch; volatile boolean shouldThrowException = false; @@ -77,8 +86,13 @@ public A2AHttpResponse post() throws IOException, InterruptedException { } try { - Task task = JsonUtil.fromJson(body, Task.class); - tasks.add(task); + // Store raw body for verification + rawBodies.add(body); + + // Parse StreamResponse format to extract the event + // The body contains a wrapper with one of: task, message, statusUpdate, artifactUpdate + StreamingEventKind event = JsonUtil.fromJson(body, StreamingEventKind.class); + events.add(event); urls.add(url); headers.add(new java.util.HashMap<>(requestHeaders)); @@ -99,7 +113,7 @@ public String body() { } }; } catch (JsonProcessingException e) { - throw new IOException("Failed to parse task JSON", e); + throw new IOException("Failed to parse StreamingEventKind JSON", e); } finally { if (latch != null) { latch.countDown(); @@ -154,12 +168,14 @@ private void testSendNotificationWithInvalidToken(String token, String testName) // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the task was sent via HTTP - assertEquals(1, testHttpClient.tasks.size()); - Task sentTask = testHttpClient.tasks.get(0); + + // Verify the task was sent via HTTP wrapped in StreamResponse format + assertEquals(1, testHttpClient.events.size()); + StreamingEventKind sentEvent = testHttpClient.events.get(0); + assertTrue(sentEvent instanceof Task, "Event should be a Task"); + Task sentTask = (Task) sentEvent; assertEquals(taskData.id(), sentTask.id()); - + // Verify that no authentication header was sent (invalid token should not add header) assertEquals(1, testHttpClient.headers.size()); Map sentHeaders = testHttpClient.headers.get(0); @@ -192,10 +208,10 @@ public void testSendNotificationSuccess() throws InterruptedException { String taskId = "task_send_success"; Task taskData = createSampleTask(taskId, TaskState.COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - + // Set up the configuration in the store configStore.setInfo(taskId, config); - + // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); @@ -203,13 +219,19 @@ public void testSendNotificationSuccess() throws InterruptedException { // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the task was sent via HTTP - assertEquals(1, testHttpClient.tasks.size()); - Task sentTask = testHttpClient.tasks.get(0); + + // Verify the task was sent via HTTP wrapped in StreamResponse format + assertEquals(1, testHttpClient.events.size()); + StreamingEventKind sentEvent = testHttpClient.events.get(0); + assertTrue(sentEvent instanceof Task, "Event should be a Task"); + Task sentTask = (Task) sentEvent; assertEquals(taskData.id(), sentTask.id()); assertEquals(taskData.contextId(), sentTask.contextId()); assertEquals(taskData.status().state(), sentTask.status().state()); + + // Verify StreamResponse wrapper is present in raw body + String rawBody = testHttpClient.rawBodies.get(0); + assertTrue(rawBody.contains("\"task\""), "Raw body should contain 'task' discriminator for StreamResponse"); } @Test @@ -217,10 +239,10 @@ public void testSendNotificationWithTokenSuccess() throws InterruptedException { String taskId = "task_send_with_token"; Task taskData = createSampleTask(taskId, TaskState.COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); - + // Set up the configuration in the store configStore.setInfo(taskId, config); - + // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); @@ -228,12 +250,14 @@ public void testSendNotificationWithTokenSuccess() throws InterruptedException { // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the task was sent via HTTP - assertEquals(1, testHttpClient.tasks.size()); - Task sentTask = testHttpClient.tasks.get(0); + + // Verify the task was sent via HTTP wrapped in StreamResponse format + assertEquals(1, testHttpClient.events.size()); + StreamingEventKind sentEvent = testHttpClient.events.get(0); + assertTrue(sentEvent instanceof Task, "Event should be a Task"); + Task sentTask = (Task) sentEvent; assertEquals(taskData.id(), sentTask.id()); - + // Verify that the X-A2A-Notification-Token header is sent with the correct token assertEquals(1, testHttpClient.headers.size()); Map sentHeaders = testHttpClient.headers.get(0); @@ -250,12 +274,12 @@ public void testSendNotificationWithTokenSuccess() throws InterruptedException { public void testSendNotificationNoConfig() { String taskId = "task_send_no_config"; Task taskData = createSampleTask(taskId, TaskState.COMPLETED); - + // Don't set any configuration in the store sender.sendNotification(taskData); // Verify no HTTP calls were made - assertEquals(0, testHttpClient.tasks.size()); + assertEquals(0, testHttpClient.events.size()); } @Test @@ -274,11 +298,11 @@ public void testSendNotificationMultipleConfigs() throws InterruptedException { Task taskData = createSampleTask(taskId, TaskState.COMPLETED); PushNotificationConfig config1 = createSamplePushConfig("http://notify.me/cfg1", "cfg1", null); PushNotificationConfig config2 = createSamplePushConfig("http://notify.me/cfg2", "cfg2", null); - + // Set up multiple configurations in the store configStore.setInfo(taskId, config1); configStore.setInfo(taskId, config2); - + // Set up latch to wait for async completion (2 calls expected) testHttpClient.latch = new CountDownLatch(2); @@ -286,14 +310,16 @@ public void testSendNotificationMultipleConfigs() throws InterruptedException { // Wait for the async operations to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP calls should complete within 5 seconds"); - - // Verify both tasks were sent via HTTP - assertEquals(2, testHttpClient.tasks.size()); + + // Verify both events were sent via HTTP wrapped in StreamResponse format + assertEquals(2, testHttpClient.events.size()); assertEquals(2, testHttpClient.urls.size()); assertTrue(testHttpClient.urls.containsAll(java.util.List.of("http://notify.me/cfg1", "http://notify.me/cfg2"))); - - // Both tasks should be identical (same task sent to different endpoints) - for (Task sentTask : testHttpClient.tasks) { + + // Both events should be identical (same event sent to different endpoints) + for (StreamingEventKind sentEvent : testHttpClient.events) { + assertTrue(sentEvent instanceof Task, "Event should be a Task"); + Task sentTask = (Task) sentEvent; assertEquals(taskData.id(), sentTask.id()); assertEquals(taskData.contextId(), sentTask.contextId()); assertEquals(taskData.status().state(), sentTask.status().state()); @@ -315,7 +341,112 @@ public void testSendNotificationHttpError() { // This should not throw an exception - errors should be handled gracefully sender.sendNotification(taskData); - // Verify no tasks were successfully processed due to the error - assertEquals(0, testHttpClient.tasks.size()); + // Verify no events were successfully processed due to the error + assertEquals(0, testHttpClient.events.size()); + } + + @Test + public void testSendNotificationMessage() throws InterruptedException { + String taskId = "task_send_message"; + Message message = Message.builder() + .taskId(taskId) + .role(Message.Role.AGENT) + .parts(new TextPart("Hello from agent")) + .build(); + PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); + + // Set up the configuration in the store + configStore.setInfo(taskId, config); + + // Set up latch to wait for async completion + testHttpClient.latch = new CountDownLatch(1); + + sender.sendNotification(message); + + // Wait for the async operation to complete + assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); + + // Verify the message was sent via HTTP wrapped in StreamResponse format + assertEquals(1, testHttpClient.events.size()); + StreamingEventKind sentEvent = testHttpClient.events.get(0); + assertTrue(sentEvent instanceof Message, "Event should be a Message"); + Message sentMessage = (Message) sentEvent; + assertEquals(taskId, sentMessage.taskId()); + + // Verify StreamResponse wrapper with 'message' discriminator + String rawBody = testHttpClient.rawBodies.get(0); + assertTrue(rawBody.contains("\"message\""), "Raw body should contain 'message' discriminator for StreamResponse"); + } + + @Test + public void testSendNotificationTaskStatusUpdate() throws InterruptedException { + String taskId = "task_send_status_update"; + TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() + .taskId(taskId) + .contextId("ctx456") + .status(new TaskStatus(TaskState.WORKING)) + .build(); + PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); + + // Set up the configuration in the store + configStore.setInfo(taskId, config); + + // Set up latch to wait for async completion + testHttpClient.latch = new CountDownLatch(1); + + sender.sendNotification(statusUpdate); + + // Wait for the async operation to complete + assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); + + // Verify the status update was sent via HTTP wrapped in StreamResponse format + assertEquals(1, testHttpClient.events.size()); + StreamingEventKind sentEvent = testHttpClient.events.get(0); + assertTrue(sentEvent instanceof TaskStatusUpdateEvent, "Event should be a TaskStatusUpdateEvent"); + TaskStatusUpdateEvent sentUpdate = (TaskStatusUpdateEvent) sentEvent; + assertEquals(taskId, sentUpdate.taskId()); + assertEquals(TaskState.WORKING, sentUpdate.status().state()); + + // Verify StreamResponse wrapper with 'statusUpdate' discriminator + String rawBody = testHttpClient.rawBodies.get(0); + assertTrue(rawBody.contains("\"statusUpdate\""), "Raw body should contain 'statusUpdate' discriminator for StreamResponse"); + } + + @Test + public void testSendNotificationTaskArtifactUpdate() throws InterruptedException { + String taskId = "task_send_artifact_update"; + Artifact artifact = Artifact.builder() + .artifactId("artifact-1") + .name("test-artifact") + .parts(Collections.singletonList(new TextPart("Artifact chunk"))) + .build(); + TaskArtifactUpdateEvent artifactUpdate = TaskArtifactUpdateEvent.builder() + .taskId(taskId) + .contextId("ctx456") + .artifact(artifact) + .build(); + PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); + + // Set up the configuration in the store + configStore.setInfo(taskId, config); + + // Set up latch to wait for async completion + testHttpClient.latch = new CountDownLatch(1); + + sender.sendNotification(artifactUpdate); + + // Wait for the async operation to complete + assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); + + // Verify the artifact update was sent via HTTP wrapped in StreamResponse format + assertEquals(1, testHttpClient.events.size()); + StreamingEventKind sentEvent = testHttpClient.events.get(0); + assertTrue(sentEvent instanceof TaskArtifactUpdateEvent, "Event should be a TaskArtifactUpdateEvent"); + TaskArtifactUpdateEvent sentUpdate = (TaskArtifactUpdateEvent) sentEvent; + assertEquals(taskId, sentUpdate.taskId()); + + // Verify StreamResponse wrapper with 'artifactUpdate' discriminator + String rawBody = testHttpClient.rawBodies.get(0); + assertTrue(rawBody.contains("\"artifactUpdate\""), "Raw body should contain 'artifactUpdate' discriminator for StreamResponse"); } } 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 2bd8c8453..350e8b99a 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 @@ -461,29 +461,30 @@ public void onCompleted() { Assertions.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assertions.assertTrue(errors.isEmpty()); Assertions.assertEquals(3, results.size()); - Assertions.assertEquals(3, httpClient.tasks.size()); - - io.a2a.spec.Task curr = httpClient.tasks.get(0); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), curr.status().state()); - Assertions.assertEquals(0, curr.artifacts() == null ? 0 : curr.artifacts().size()); - - curr = httpClient.tasks.get(1); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), curr.status().state()); - Assertions.assertEquals(1, curr.artifacts().size()); - Assertions.assertEquals(1, curr.artifacts().get(0).parts().size()); - Assertions.assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); - - curr = httpClient.tasks.get(2); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), curr.id()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), curr.contextId()); - Assertions.assertEquals(io.a2a.spec.TaskState.COMPLETED, curr.status().state()); - Assertions.assertEquals(1, curr.artifacts().size()); - Assertions.assertEquals(1, curr.artifacts().get(0).parts().size()); - Assertions.assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); + Assertions.assertEquals(3, httpClient.events.size()); + + // Event 0: Task event + Assertions.assertTrue(httpClient.events.get(0) instanceof io.a2a.spec.Task, "First event should be Task"); + io.a2a.spec.Task task1 = (io.a2a.spec.Task) httpClient.events.get(0); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), task1.id()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), task1.contextId()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), task1.status().state()); + Assertions.assertEquals(0, task1.artifacts() == null ? 0 : task1.artifacts().size()); + + // Event 1: TaskArtifactUpdateEvent + Assertions.assertTrue(httpClient.events.get(1) instanceof TaskArtifactUpdateEvent, "Second event should be TaskArtifactUpdateEvent"); + TaskArtifactUpdateEvent artifactUpdate = (TaskArtifactUpdateEvent) httpClient.events.get(1); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), artifactUpdate.taskId()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), artifactUpdate.contextId()); + Assertions.assertEquals(1, artifactUpdate.artifact().parts().size()); + Assertions.assertEquals("text", ((TextPart) artifactUpdate.artifact().parts().get(0)).text()); + + // Event 2: TaskStatusUpdateEvent + Assertions.assertTrue(httpClient.events.get(2) instanceof TaskStatusUpdateEvent, "Third event should be TaskStatusUpdateEvent"); + TaskStatusUpdateEvent statusUpdate = (TaskStatusUpdateEvent) httpClient.events.get(2); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), statusUpdate.taskId()); + Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), statusUpdate.contextId()); + Assertions.assertEquals(io.a2a.spec.TaskState.COMPLETED, statusUpdate.status().state()); } finally { mainEventBusProcessor.setPushNotificationExecutor(null); } 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 3e925e266..a97883e5a 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 @@ -775,29 +775,31 @@ public void onComplete() { subscriptionRef.get().cancel(); assertEquals(3, results.size()); - assertEquals(3, httpClient.tasks.size()); - - Task curr = httpClient.tasks.get(0); - assertEquals(MINIMAL_TASK.id(), curr.id()); - assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); - assertEquals(MINIMAL_TASK.status().state(), curr.status().state()); - assertEquals(0, curr.artifacts() == null ? 0 : curr.artifacts().size()); - - curr = httpClient.tasks.get(1); - assertEquals(MINIMAL_TASK.id(), curr.id()); - assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); - assertEquals(MINIMAL_TASK.status().state(), curr.status().state()); - assertEquals(1, curr.artifacts().size()); - assertEquals(1, curr.artifacts().get(0).parts().size()); - assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); - - curr = httpClient.tasks.get(2); - assertEquals(MINIMAL_TASK.id(), curr.id()); - assertEquals(MINIMAL_TASK.contextId(), curr.contextId()); - assertEquals(TaskState.COMPLETED, curr.status().state()); - assertEquals(1, curr.artifacts().size()); - assertEquals(1, curr.artifacts().get(0).parts().size()); - assertEquals("text", ((TextPart) curr.artifacts().get(0).parts().get(0)).text()); + // Push notifications now send the actual StreamingEventKind events, not Task snapshots + assertEquals(3, httpClient.events.size()); + + // Event 0: Task event + assertTrue(httpClient.events.get(0) instanceof Task, "First event should be Task"); + Task task1 = (Task) httpClient.events.get(0); + assertEquals(MINIMAL_TASK.id(), task1.id()); + assertEquals(MINIMAL_TASK.contextId(), task1.contextId()); + assertEquals(MINIMAL_TASK.status().state(), task1.status().state()); + assertEquals(0, task1.artifacts() == null ? 0 : task1.artifacts().size()); + + // Event 1: TaskArtifactUpdateEvent + assertTrue(httpClient.events.get(1) instanceof TaskArtifactUpdateEvent, "Second event should be TaskArtifactUpdateEvent"); + TaskArtifactUpdateEvent artifactUpdate = (TaskArtifactUpdateEvent) httpClient.events.get(1); + assertEquals(MINIMAL_TASK.id(), artifactUpdate.taskId()); + assertEquals(MINIMAL_TASK.contextId(), artifactUpdate.contextId()); + assertEquals(1, artifactUpdate.artifact().parts().size()); + assertEquals("text", ((TextPart) artifactUpdate.artifact().parts().get(0)).text()); + + // Event 2: TaskStatusUpdateEvent + assertTrue(httpClient.events.get(2) instanceof TaskStatusUpdateEvent, "Third event should be TaskStatusUpdateEvent"); + TaskStatusUpdateEvent statusUpdate = (TaskStatusUpdateEvent) httpClient.events.get(2); + assertEquals(MINIMAL_TASK.id(), statusUpdate.taskId()); + assertEquals(MINIMAL_TASK.contextId(), statusUpdate.contextId()); + assertEquals(TaskState.COMPLETED, statusUpdate.status().state()); } finally { mainEventBusProcessor.setPushNotificationExecutor(null); } From b63f28cdcc52d2e39d8a919739999e486ba372a1 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 10 Feb 2026 17:43:55 +0000 Subject: [PATCH 024/192] feat!: Use AgentEmitter instead of EventQueue in AgentExecutor methods (#621) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: AgentEmitter contains the methods from the old TaskUpdater and is now the only way agents send results back to the caller. This hides the EventQueue mechanism from users. Also introduced a check that when placing a full Task object on the queue, which should only be done for calls with no existing Task, that the Task's ID is the one expected for the queue, as calculated by the RequestContext. Added Message and Task builders to AgentEmitter to help with using the proper taskID and contextId. Treat A2AErrors internally as a state transition to FAILED. Register EventConsumer callback before starting agent to fix a race condition/hang when an agent completes before the callback is registered. Fixes #604 🦕 --------- Signed-off-by: Emmanuel Hugonnet Co-authored-by: Emmanuel Hugonnet --- README.md | 21 +- examples/cloud-deployment/README.md | 21 +- .../cloud/CloudAgentExecutorProducer.java | 23 +- .../helloworld/AgentExecutorProducer.java | 9 +- ...ificationConfigStoreTestAgentExecutor.java | 17 +- .../core/ReplicatedQueueManagerTest.java | 11 +- ...MultiInstanceReplicationAgentExecutor.java | 17 +- .../tests/ReplicationTestAgentExecutor.java | 26 +- ...JpaDatabaseTaskStoreTestAgentExecutor.java | 18 +- .../server/agentexecution/AgentExecutor.java | 45 +- .../server/agentexecution/RequestContext.java | 2 +- .../a2a/server/events/EnhancedRunnable.java | 15 + .../io/a2a/server/events/EventConsumer.java | 5 + .../java/io/a2a/server/events/EventQueue.java | 45 ++ .../server/events/MainEventBusProcessor.java | 6 +- .../DefaultRequestHandler.java | 87 ++- .../io/a2a/server/tasks/AgentEmitter.java | 628 ++++++++++++++++++ .../io/a2a/server/tasks/ResultAggregator.java | 3 +- .../java/io/a2a/server/tasks/TaskManager.java | 38 ++ .../java/io/a2a/server/tasks/TaskUpdater.java | 190 ------ .../server/events/EnhancedRunnableTest.java | 136 ++++ .../AbstractA2ARequestHandlerTest.java | 12 +- .../tasks/AgentEmitterConcurrencyTest.java | 248 +++++++ ...UpdaterTest.java => AgentEmitterTest.java} | 90 +-- .../a2a/tck/server/AgentExecutorProducer.java | 25 +- .../apps/common/AgentExecutorProducer.java | 33 +- .../grpc/handler/GrpcHandlerTest.java | 83 ++- .../jsonrpc/handler/JSONRPCHandlerTest.java | 107 ++- .../rest/handler/RestHandlerTest.java | 31 +- 29 files changed, 1465 insertions(+), 527 deletions(-) create mode 100644 server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java delete mode 100644 server-common/src/main/java/io/a2a/server/tasks/TaskUpdater.java create mode 100644 server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java create mode 100644 server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java rename server-common/src/test/java/io/a2a/server/tasks/{TaskUpdaterTest.java => AgentEmitterTest.java} (87%) diff --git a/README.md b/README.md index bd86952da..48d28a8cd 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ public class WeatherAgentCardProducer { 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.server.tasks.AgentEmitter; import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Part; @@ -173,14 +173,12 @@ public class WeatherAgentExecutorProducer { } @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { - TaskUpdater updater = new TaskUpdater(context, eventQueue); - + public void execute(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { // mark the task as submitted and start working on it if (context.getTask() == null) { - updater.submit(); + agentEmitter.submit(); } - updater.startWork(); + agentEmitter.startWork(); // extract the text from the message String userMessage = extractTextFromMessage(context.getMessage()); @@ -189,16 +187,16 @@ public class WeatherAgentExecutorProducer { String response = weatherAgent.chat(userMessage); // create the response part - TextPart responsePart = new TextPart(response, null); + TextPart responsePart = new TextPart(response); List> parts = List.of(responsePart); // add the response as an artifact and complete the task - updater.addArtifact(parts, null, null, null); - updater.complete(); + agentEmitter.addArtifact(parts); + agentEmitter.complete(); } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { Task task = context.getTask(); if (task.getStatus().state() == TaskState.CANCELED) { @@ -212,8 +210,7 @@ public class WeatherAgentExecutorProducer { } // cancel the task - TaskUpdater updater = new TaskUpdater(context, eventQueue); - updater.cancel(); + agentEmitter.cancel(); } private String extractTextFromMessage(Message message) { diff --git a/examples/cloud-deployment/README.md b/examples/cloud-deployment/README.md index bf1e4cd60..fe146a6e9 100644 --- a/examples/cloud-deployment/README.md +++ b/examples/cloud-deployment/README.md @@ -224,8 +224,7 @@ The agent (`CloudAgentExecutorProducer`) implements a command-based protocol: ```java @Override -public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { - TaskUpdater updater = new TaskUpdater(context, eventQueue); +public void execute(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { String messageText = extractTextFromMessage(context.getMessage()).trim().toLowerCase(); // Get pod name from Kubernetes downward API @@ -234,21 +233,21 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP if ("complete".equals(messageText)) { // Completion trigger - add final artifact and complete String artifactText = "Completed by " + podName; - List> parts = List.of(new TextPart(artifactText, null)); - updater.addArtifact(parts); - updater.complete(); // Transition to COMPLETED state + List> parts = List.of(new TextPart(artifactText)); + agentEmitter.addArtifact(parts); + agentEmitter.complete(); // Transition to COMPLETED state } else if (context.getTask() == null) { // Initial "start" message - create task in SUBMITTED → WORKING state - updater.submit(); - updater.startWork(); + agentEmitter.submit(); + agentEmitter.startWork(); String artifactText = "Started by " + podName; - List> parts = List.of(new TextPart(artifactText, null)); - updater.addArtifact(parts); + List> parts = List.of(new TextPart(artifactText)); + agentEmitter.addArtifact(parts); } else { // Subsequent "process" messages - add artifacts (fire-and-forget, stays WORKING) String artifactText = "Processed by " + podName; - List> parts = List.of(new TextPart(artifactText, null)); - updater.addArtifact(parts); + List> parts = List.of(new TextPart(artifactText)); + agentEmitter.addArtifact(parts); } } ``` 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 d3d36044d..976826fb3 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 @@ -7,8 +7,7 @@ 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.server.tasks.AgentEmitter; import io.a2a.spec.A2AError; import io.a2a.spec.InternalError; import io.a2a.spec.Message; @@ -46,8 +45,7 @@ public AgentExecutor agentExecutor() { private static class CloudAgentExecutor implements AgentExecutor { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { - TaskUpdater updater = new TaskUpdater(context, eventQueue); + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { try { // Extract user message and normalize @@ -75,18 +73,18 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr LOGGER.info("Completion requested on pod: {}", podName); String artifactText = "Completed by " + podName; List> parts = List.of(new TextPart(artifactText)); - updater.addArtifact(parts); - updater.complete(); + agentEmitter.addArtifact(parts); + agentEmitter.complete(); LOGGER.info("Task completed on pod: {}", podName); } else if (context.getTask() == null) { // Initial message - create task in SUBMITTED → WORKING state LOGGER.info("Creating new task on pod: {}", podName); - updater.submit(); - updater.startWork(); + agentEmitter.submit(); + agentEmitter.startWork(); String artifactText = "Started by " + podName; List> parts = List.of(new TextPart(artifactText)); - updater.addArtifact(parts); + agentEmitter.addArtifact(parts); LOGGER.info("Task created and started on pod: {}", podName); } else { @@ -94,7 +92,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr LOGGER.info("Adding artifact on pod: {}", podName); String artifactText = "Processed by " + podName; List> parts = List.of(new TextPart(artifactText)); - updater.addArtifact(parts); + agentEmitter.addArtifact(parts); // No state change - task remains in WORKING LOGGER.info("Artifact added on pod: {}", podName); } @@ -109,10 +107,9 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { LOGGER.info("Task cancellation requested"); - TaskUpdater updater = new TaskUpdater(context, eventQueue); - updater.cancel(); + agentEmitter.cancel(); } /** 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 4bba596db..3c3be977b 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,10 +3,9 @@ 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.server.tasks.AgentEmitter; import io.a2a.spec.A2AError; import io.a2a.spec.UnsupportedOperationError; @@ -17,12 +16,12 @@ public class AgentExecutorProducer { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { - eventQueue.enqueueEvent(A2A.toAgentMessage("Hello World")); + public void execute(RequestContext context, AgentEmitter emitter) throws A2AError { + emitter.sendMessage("Hello World"); } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { + public void cancel(RequestContext context, AgentEmitter emitter) throws A2AError { throw new UnsupportedOperationError(); } }; 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 df29c1688..4061a3619 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 @@ -8,9 +8,8 @@ import io.a2a.server.agentexecution.AgentExecutor; import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; +import io.a2a.server.tasks.AgentEmitter; 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.Message; @@ -33,31 +32,29 @@ public class JpaDatabasePushNotificationConfigStoreTestAgentExecutor { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { String command = getLastTextPart(context.getMessage()); // Switch based on the command from the test client switch (command) { case "create": - taskUpdater.submit(); + agentEmitter.submit(); break; case "update": // Perform a meaningful update, like adding an artifact. // This state change is what will trigger the notification. - taskUpdater.addArtifact(List.of(new TextPart("updated-artifact")), "art-1", "test", null); + agentEmitter.addArtifact(List.of(new TextPart("updated-artifact")), "art-1", "test", null); break; default: // On the first message (which might have no text), just submit. - taskUpdater.submit(); + agentEmitter.submit(); break; } } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); - taskUpdater.cancel(); + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + agentEmitter.cancel(); } }; } 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 b766863aa..e69971adc 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 @@ -149,7 +149,7 @@ void testReplicationStrategyNotTriggeredOnReplicatedEvent() throws InterruptedEx String taskId = "test-task-2"; EventQueue queue = queueManager.createOrTap(taskId); - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, testEvent); + ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, getTaskStatusUpdateEventWithNewId(taskId)); queueManager.onReplicatedEvent(replicatedEvent); assertEquals(0, strategy.getCallCount()); @@ -172,7 +172,7 @@ void testReplicationStrategyWithCountingImplementation() throws InterruptedExcep assertEquals(taskId, countingStrategy.getLastTaskId()); assertEquals(event, countingStrategy.getLastEvent()); - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, testEvent); + ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, getTaskStatusUpdateEventWithNewId(taskId)); queueManager.onReplicatedEvent(replicatedEvent); assertEquals(2, countingStrategy.getCallCount()); @@ -483,7 +483,7 @@ void testReplicatedEventToExistingQueueWhenTaskBecomesInactive() throws Interrup // Create queue and enqueue an event EventQueue queue = queueManager.createOrTap(taskId); - queue.enqueueEvent(testEvent); + queue.enqueueEvent(getTaskStatusUpdateEventWithNewId(taskId)); // Dequeue to clear the queue try { @@ -607,6 +607,11 @@ void testReplicatedQueueClosedEventTerminatesConsumer() throws InterruptedExcept "Second event should be QueueClosedEvent"); } + private TaskStatusUpdateEvent getTaskStatusUpdateEventWithNewId(String taskId) { + return TaskStatusUpdateEvent.builder((TaskStatusUpdateEvent) testEvent).taskId(taskId).build(); + } + + private static class NoOpReplicationStrategy implements ReplicationStrategy { @Override public void send(String taskId, Event event) { 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 546d22939..d51ef8f32 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 @@ -2,8 +2,7 @@ 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.server.tasks.AgentEmitter; import io.a2a.spec.A2AError; import io.a2a.spec.Task; import io.a2a.spec.TextPart; @@ -18,9 +17,8 @@ */ public class MultiInstanceReplicationAgentExecutor implements AgentExecutor { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { Task task = context.getTask(); - TaskUpdater updater = new TaskUpdater(context, eventQueue); // Check if message contains "close" signal boolean shouldClose = context.getMessage().parts().stream() @@ -30,19 +28,18 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr if (shouldClose) { // Close the task - updater.complete(); + agentEmitter.complete(); } else if (task == null) { // First message - create task in SUBMITTED state - updater.submit(); + agentEmitter.submit(); } else { // Subsequent messages - add as artifact - updater.addArtifact(context.getMessage().parts()); + agentEmitter.addArtifact(context.getMessage().parts()); } } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { - TaskUpdater updater = new TaskUpdater(context, eventQueue); - updater.cancel(); + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + agentEmitter.cancel(); } } 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 8e4db21dd..8e934df7e 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 @@ -7,8 +7,7 @@ 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.server.tasks.AgentEmitter; import io.a2a.spec.A2AError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.Message; @@ -28,27 +27,25 @@ public class ReplicationTestAgentExecutor { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { - - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { String lastText = getLastTextPart(context.getMessage()); switch (lastText) { case "create": // Submit task - this should trigger TaskStatusUpdateEvent - taskUpdater.submit(); + agentEmitter.submit(); break; case "working": // Move task to WORKING state without completing - keeps queue alive - taskUpdater.submit(); - taskUpdater.startWork(); + agentEmitter.submit(); + agentEmitter.startWork(); break; case "complete": // Complete the task - should trigger poison pill generation - taskUpdater.submit(); - taskUpdater.startWork(); - taskUpdater.addArtifact(List.of(new TextPart("Task completed"))); - taskUpdater.complete(); + agentEmitter.submit(); + agentEmitter.startWork(); + agentEmitter.addArtifact(List.of(new TextPart("Task completed"))); + agentEmitter.complete(); break; default: throw new InvalidRequestError("Unknown command: " + lastText); @@ -56,9 +53,8 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); - taskUpdater.cancel(); + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + agentEmitter.cancel(); } }; } 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 f3b310750..fd530a761 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 @@ -7,8 +7,7 @@ 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.server.tasks.AgentEmitter; import io.a2a.spec.A2AError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.Message; @@ -17,7 +16,7 @@ import io.quarkus.arc.profile.IfBuildProfile; /** - * Simple test AgentExecutor that responds to messages and uses TaskUpdater.addArtifact() + * Simple test AgentExecutor that responds to messages and uses AgentEmitter.addArtifact() * to trigger TaskUpdateEvents for our integration test. */ @IfBuildProfile("test") @@ -28,18 +27,16 @@ public class JpaDatabaseTaskStoreTestAgentExecutor { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { System.out.println("TestAgentExecutor.execute() called for task: " + context.getTaskId()); System.out.println("Message " + context.getMessage()); - - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); String lastText = getLastTextPart(context.getMessage()); switch (lastText) { case "create": - taskUpdater.submit(); + agentEmitter.submit(); break; case "add-artifact": - taskUpdater.addArtifact(List.of(new TextPart(lastText)), "art-1", "test", null); + agentEmitter.addArtifact(List.of(new TextPart(lastText)), "art-1", "test", null); break; default: throw new InvalidRequestError(lastText + " is unknown"); @@ -47,9 +44,8 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); - taskUpdater.cancel(); + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + agentEmitter.cancel(); } }; } 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 0dfce6088..08d6b56d9 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,6 +1,7 @@ package io.a2a.server.agentexecution; import io.a2a.server.events.EventQueue; +import io.a2a.server.tasks.AgentEmitter; import io.a2a.spec.A2AError; /** @@ -17,9 +18,8 @@ * asynchronously in a background thread pool when requests arrive from transport layers. * Your implementation should: *
          - *
        • Use the {@link EventQueue} to enqueue task status updates and artifacts
        • - *
        • Use {@link io.a2a.server.tasks.TaskUpdater} helper for common lifecycle operations
        • - *
        • Handle cancellation via the {@link #cancel(RequestContext, EventQueue)} method
        • + *
        • Use the {@link AgentEmitter} to send messages, update task status, and stream artifacts
        • + *
        • Handle cancellation via the {@link #cancel(RequestContext, AgentEmitter)} method
        • *
        • Be thread-safe if maintaining state across invocations
        • *
        * @@ -56,14 +56,12 @@ * } * * @Override - * public void execute(RequestContext context, EventQueue eventQueue) { - * TaskUpdater updater = new TaskUpdater(context, eventQueue); - * + * public void execute(RequestContext context, AgentEmitter emitter) { * // Initialize task if this is a new conversation * if (context.getTask() == null) { - * updater.submit(); + * emitter.submit(); * } - * updater.startWork(); + * emitter.startWork(); * * // Extract user input from the message * String userMessage = context.getUserInput("\n"); @@ -72,14 +70,14 @@ * String weatherData = weatherService.getWeather(userMessage); * * // Return result as artifact - * updater.addArtifact(List.of(new TextPart(weatherData, null))); - * updater.complete(); + * emitter.addArtifact(List.of(new TextPart(weatherData, null))); + * emitter.complete(); * } * * @Override - * public void cancel(RequestContext context, EventQueue eventQueue) { + * public void cancel(RequestContext context, AgentEmitter emitter) { * // Clean up resources and mark as canceled - * new TaskUpdater(context, eventQueue).cancel(); + * emitter.cancel(); * } * } * } @@ -87,16 +85,15 @@ *

        Streaming Results

        * For long-running operations or LLM streaming, enqueue multiple artifacts: *
        {@code
        - * updater.startWork();
        + * emitter.startWork();
          * for (String chunk : llmService.stream(userInput)) {
        - *     updater.addArtifact(List.of(new TextPart(chunk, null)));
        + *     emitter.addArtifact(List.of(new TextPart(chunk, null)));
          * }
        - * updater.complete();  // Final event closes the queue
        + * emitter.complete();  // Final event closes the queue
          * }
        * * @see RequestContext - * @see io.a2a.server.tasks.TaskUpdater - * @see io.a2a.server.events.EventQueue + * @see AgentEmitter * @see io.a2a.server.requesthandlers.DefaultRequestHandler * @see io.a2a.spec.AgentCard */ @@ -111,15 +108,15 @@ public interface AgentExecutor { *

        *

        * Important: Don't throw exceptions for business logic errors. Instead, use - * {@code updater.fail(errorMessage)} to communicate failures to the client gracefully. + * {@code emitter.fail(errorMessage)} to communicate failures to the client gracefully. * Only throw {@link A2AError} for truly exceptional conditions. *

        * * @param context the request context containing the message, task state, and configuration - * @param eventQueue the queue for enqueueing status updates and artifacts + * @param emitter the agent emitter for sending messages, updating status, and streaming artifacts * @throws A2AError if execution fails catastrophically (exception propagates to client) */ - void execute(RequestContext context, EventQueue eventQueue) throws A2AError; + void execute(RequestContext context, AgentEmitter emitter) throws A2AError; /** * Cancels an ongoing agent execution. @@ -128,11 +125,11 @@ public interface AgentExecutor { * You should: *
          *
        • Stop any ongoing work (interrupt LLM calls, cancel API requests)
        • - *
        • Enqueue a CANCELED status event (typically via {@code TaskUpdater.cancel()})
        • + *
        • Enqueue a CANCELED status event (typically via {@code emitter.cancel()})
        • *
        • Clean up resources (close connections, release locks)
        • *
        *

        - * Note: The {@link #execute(RequestContext, EventQueue)} method may still be + * Note: The {@link #execute(RequestContext, AgentEmitter)} method may still be * running on another thread. Use appropriate synchronization or interruption mechanisms * if your agent maintains cancellable state. *

        @@ -146,9 +143,9 @@ public interface AgentExecutor { * * * @param context the request context for the task being canceled - * @param eventQueue the queue for enqueueing the cancellation event + * @param emitter the agent emitter for sending the cancellation event * @throws io.a2a.spec.TaskNotCancelableError if this agent does not support cancellation * @throws A2AError if cancellation is supported but failed to execute */ - void cancel(RequestContext context, EventQueue eventQueue) throws A2AError; + void cancel(RequestContext context, AgentEmitter emitter) 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 e79298703..82a8b9e17 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 @@ -35,7 +35,7 @@ * *

        Common Usage Patterns

        *
        {@code
        - * public void execute(RequestContext context, EventQueue queue) {
        + * public void execute(RequestContext context, AgentEmitter emitter) {
          *     // Check if this is a new conversation or continuation
          *     Task existingTask = context.getTask();
          *     if (existingTask == null) {
        diff --git a/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java b/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java
        index 779ad02da..2ccf3fb60 100644
        --- a/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java
        +++ b/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java
        @@ -2,12 +2,14 @@
         
         import java.util.List;
         import java.util.concurrent.CopyOnWriteArrayList;
        +import java.util.concurrent.atomic.AtomicBoolean;
         
         import org.jspecify.annotations.Nullable;
         
         public abstract class EnhancedRunnable implements Runnable {
             private volatile @Nullable Throwable error;
             private final List doneCallbacks = new CopyOnWriteArrayList<>();
        +    private final AtomicBoolean started = new AtomicBoolean(false);
         
             public @Nullable Throwable getError() {
                 return error;
        @@ -18,9 +20,22 @@ public void setError(Throwable error) {
             }
         
             public void addDoneCallback(DoneCallback doneCallback) {
        +        if (started.get()) {
        +            throw new IllegalStateException(
        +                "Cannot add callback after runnable has started execution. " +
        +                "Callbacks must be registered before CompletableFuture.runAsync() is called.");
        +        }
                 doneCallbacks.add(doneCallback);
             }
         
        +    /**
        +     * Marks this runnable as started, preventing further callback additions.
        +     * This should be called immediately before submitting to CompletableFuture.runAsync().
        +     */
        +    public void markStarted() {
        +        started.set(true);
        +    }
        +
             public void invokeDoneCallbacks() {
                 for (DoneCallback doneCallback : doneCallbacks) {
                     doneCallback.done(this);
        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 7c7b28452..239385a39 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,6 +2,7 @@
         
         import java.util.concurrent.Flow;
         
        +import io.a2a.spec.A2AError;
         import io.a2a.spec.A2AServerException;
         import io.a2a.spec.Event;
         import io.a2a.spec.Message;
        @@ -136,6 +137,10 @@ public Flow.Publisher consumeAll() {
                                     LOGGER.debug("Received QueueClosedEvent for task {}, treating as final event",
                                         ((QueueClosedEvent) event).getTaskId());
                                     isFinalEvent = true;
        +                        } else if (event instanceof A2AError) {
        +                            // A2AError events are terminal - they trigger automatic FAILED state transition
        +                            LOGGER.debug("Received A2AError event, treating as final event");
        +                            isFinalEvent = true;
                                 }
         
                                 // Only send event if it's not a QueueClosedEvent
        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 4899a926d..53ae22da4 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
        @@ -13,6 +13,7 @@
         import io.a2a.server.tasks.TaskStateProvider;
         import io.a2a.spec.Event;
         import io.a2a.spec.Task;
        +import io.a2a.spec.TaskArtifactUpdateEvent;
         import io.a2a.spec.TaskStatusUpdateEvent;
         import org.jspecify.annotations.Nullable;
         import org.slf4j.Logger;
        @@ -431,6 +432,9 @@ public void enqueueItem(EventQueueItem item) {
                     // We bypass the parent's closed check and enqueue directly
                     Event event = item.getEvent();
         
        +            // Validate event taskId matches queue taskId
        +            validateEventIds(event);
        +
                     // Check if this is a final event BEFORE submitting to MainEventBus
                     // If it is, notify all children to expect it (so they wait for MainEventBusProcessor)
                     if (isFinalEvent(event)) {
        @@ -458,6 +462,47 @@ public void enqueueItem(EventQueueItem item) {
                     mainEventBus.submit(taskId, this, item);
                 }
         
        +        /**
        +         * Validates that events with taskId fields match this queue's taskId.
        +         *
        +         * 

        Validation Rules: + *

          + *
        • Task, TaskStatusUpdateEvent, TaskArtifactUpdateEvent: MUST match queue taskId
        • + *
        • Message: taskId is OPTIONAL, not validated (can exist without tasks)
        • + *
        • Other events: no validation
        • + *
        • Null queue taskId: skip validation (initialization phase)
        • + *
        + * + * @param event the event to validate + * @throws IllegalArgumentException if event has mismatched taskId + */ + private void validateEventIds(Event event) { + if (taskId == null) { + return; // Allow any event during initialization + } + + String eventTaskId = null; + String eventType = null; + + if (event instanceof Task task) { + eventTaskId = task.id(); + eventType = "Task"; + } else if (event instanceof TaskStatusUpdateEvent statusEvent) { + eventTaskId = statusEvent.taskId(); + eventType = "TaskStatusUpdateEvent"; + } else if (event instanceof TaskArtifactUpdateEvent artifactEvent) { + eventTaskId = artifactEvent.taskId(); + eventType = "TaskArtifactUpdateEvent"; + } + // Note: Message.taskId is NOT validated - messages can exist independently + + if (eventTaskId != null && !eventTaskId.equals(taskId)) { + throw new IllegalArgumentException( + String.format("Event taskId mismatch: queue=%s, event=%s, eventType=%s", + taskId, eventTaskId, eventType)); + } + } + /** * Checks if an event represents a final task state. */ diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java index 0fc7b3aa9..575078679 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java @@ -11,6 +11,7 @@ import io.a2a.server.tasks.PushNotificationSender; import io.a2a.server.tasks.TaskManager; import io.a2a.server.tasks.TaskStore; +import io.a2a.spec.A2AError; import io.a2a.spec.A2AServerException; import io.a2a.spec.Event; import io.a2a.spec.InternalError; @@ -377,7 +378,7 @@ private String extractContextId(Event event) { * Checks if an event represents a final task state. * * @param event the event to check - * @return true if the event represents a final state (COMPLETED, FAILED, CANCELED, REJECTED, UNKNOWN) + * @return true if the event represents a final state (COMPLETED, FAILED, CANCELED, REJECTED, UNKNOWN, or A2AError) */ private boolean isFinalEvent(Event event) { if (event instanceof Task task) { @@ -385,6 +386,9 @@ private boolean isFinalEvent(Event event) { && task.status().state().isFinal(); } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { return statusUpdate.isFinal(); + } else if (event instanceof A2AError) { + // A2AError events are terminal - they trigger FAILED state transition + return true; } return false; } 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 31a1a6670..974482ce2 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 @@ -36,6 +36,7 @@ import io.a2a.server.events.EventQueueItem; import io.a2a.server.events.MainEventBusProcessor; import io.a2a.server.events.QueueManager; +import io.a2a.server.tasks.AgentEmitter; import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.server.tasks.PushNotificationSender; import io.a2a.server.tasks.ResultAggregator; @@ -98,7 +99,7 @@ *
      • Transport calls {@link #onMessageSend(MessageSendParams, ServerCallContext)}
      • *
      • Initialize {@link TaskManager} and {@link RequestContext}
      • *
      • Create or tap {@link EventQueue} via {@link QueueManager}
      • - *
      • Execute {@link AgentExecutor#execute(RequestContext, EventQueue)} asynchronously in background thread pool
      • + *
      • Execute {@link AgentExecutor#execute(RequestContext, AgentEmitter)} asynchronously in background thread pool
      • *
      • Consume events from queue on Vert.x worker thread via {@link EventConsumer}
      • *
      • For blocking=true: wait for agent completion and full event consumption
      • *
      • Return {@link Task} or {@link Message} to transport
      • @@ -109,7 +110,7 @@ *
          *
        1. Transport calls {@link #onMessageSendStream(MessageSendParams, ServerCallContext)}
        2. *
        3. Initialize components (same as blocking)
        4. - *
        5. Execute {@link AgentExecutor#execute(RequestContext, EventQueue)} asynchronously
        6. + *
        7. Execute {@link AgentExecutor#execute(RequestContext, AgentEmitter)} asynchronously
        8. *
        9. Return {@link java.util.concurrent.Flow.Publisher Flow.Publisher}<StreamingEventKind> immediately
        10. *
        11. Events stream to client as they arrive in the queue
        12. *
        13. On client disconnect: continue consumption in background (fire-and-forget)
        14. @@ -128,7 +129,7 @@ *

          Threading Model

          *
            *
          • Vert.x worker threads: Execute request handler methods (onMessageSend, etc.)
          • - *
          • Agent-executor pool (@Internal): Execute {@link AgentExecutor#execute(RequestContext, EventQueue)}
          • + *
          • Agent-executor pool (@Internal): Execute {@link AgentExecutor#execute(RequestContext, AgentEmitter)}
          • *
          • Background cleanup: {@link java.util.concurrent.CompletableFuture CompletableFuture} async tasks
          • *
          *

          @@ -378,14 +379,29 @@ public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor, eventConsumerExecutor); EventQueue queue = queueManager.createOrTap(task.id()); - agentExecutor.cancel( - requestContextBuilder.get() - .setTaskId(task.id()) - .setContextId(task.contextId()) - .setTask(task) - .setServerCallContext(context) - .build(), - queue); + RequestContext cancelRequestContext = requestContextBuilder.get() + .setTaskId(task.id()) + .setContextId(task.contextId()) + .setTask(task) + .setServerCallContext(context) + .build(); + AgentEmitter emitter = new AgentEmitter(cancelRequestContext, queue); + try { + agentExecutor.cancel(cancelRequestContext, emitter); + } catch (TaskNotCancelableError e) { + // Expected error - log at INFO level + LOGGER.info("Task {} is not cancelable", task.id()); + throw e; + } catch (A2AError e) { + // Other A2A errors - log at WARN level with stack trace + LOGGER.warn("Agent cancellation threw A2AError for task {}: {} - {}", + task.id(), e.getClass().getSimpleName(), e.getMessage(), e); + throw e; + } catch (Exception e) { + // Unexpected errors - log at ERROR level + LOGGER.error("Agent cancellation threw unexpected exception for task {}", task.id(), e); + throw new io.a2a.spec.InternalError("Agent cancellation failed: " + e.getMessage()); + } Optional.ofNullable(runningAgents.get(task.id())) .ifPresent(cf -> cf.cancel(true)); @@ -439,15 +455,14 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte boolean interruptedOrNonBlocking = false; - EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue); + // Create consumer BEFORE starting agent - callback is registered inside registerAndExecuteAgentAsync + EventConsumer consumer = new EventConsumer(queue); + + EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue, consumer.createAgentRunnableDoneCallback()); + ResultAggregator.EventTypeAndInterrupt etai = null; EventKind kind = null; // Declare outside try block so it's in scope for return try { - EventConsumer consumer = new EventConsumer(queue); - - // This callback must be added before we start consuming. Otherwise, - // any errors thrown by the producerRunnable are not picked up by the consumer - producerRunnable.addDoneCallback(consumer.createAgentRunnableDoneCallback()); // Get agent future before consuming (for blocking calls to wait for agent completion) CompletableFuture agentFuture = runningAgents.get(queueTaskId); @@ -621,11 +636,10 @@ public Flow.Publisher onMessageSendStream( ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); - EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue); - - // Move consumer creation and callback registration outside try block + // Create consumer BEFORE starting agent - callback is registered inside registerAndExecuteAgentAsync EventConsumer consumer = new EventConsumer(queue); - producerRunnable.addDoneCallback(consumer.createAgentRunnableDoneCallback()); + + EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue, consumer.createAgentRunnableDoneCallback()); // Store cancel callback in context for closeHandler to access // When client disconnects, closeHandler can call this to stop EventConsumer polling loop @@ -863,21 +877,48 @@ private boolean shouldAddPushInfo(MessageSendParams params) { * * This design avoids blocking agent-executor threads waiting for consumer polling to start, * eliminating cascading delays when Vert.x worker threads are busy. + * + * @param doneCallback Callback to invoke when agent completes - MUST be added before starting CompletableFuture */ - private EnhancedRunnable registerAndExecuteAgentAsync(String taskId, RequestContext requestContext, EventQueue queue) { + private EnhancedRunnable registerAndExecuteAgentAsync(String taskId, RequestContext requestContext, EventQueue queue, EnhancedRunnable.DoneCallback doneCallback) { LOGGER.debug("Registering agent execution for task {}, runningAgents.size() before: {}", taskId, runningAgents.size()); logThreadStats("AGENT START"); EnhancedRunnable runnable = new EnhancedRunnable() { @Override public void run() { LOGGER.debug("Agent execution starting for task {}", taskId); - agentExecutor.execute(requestContext, queue); + AgentEmitter emitter = new AgentEmitter(requestContext, queue); + try { + agentExecutor.execute(requestContext, emitter); + } catch (A2AError e) { + // Log A2A errors at WARN level with full stack trace + // These are expected business errors but should be tracked + LOGGER.warn("Agent execution threw A2AError for task {}: {} - {}", + taskId, e.getClass().getSimpleName(), e.getMessage(), e); + emitter.fail(e); + } catch (RuntimeException e) { + // Log unexpected runtime exceptions at ERROR level + // These indicate bugs in agent implementation + LOGGER.error("Agent execution threw unexpected RuntimeException for task {}", taskId, e); + emitter.fail(new io.a2a.spec.InternalError("Agent execution failed: " + e.getMessage())); + } catch (Exception e) { + // Log other exceptions at ERROR level + LOGGER.error("Agent execution threw unexpected Exception for task {}", taskId, e); + emitter.fail(new io.a2a.spec.InternalError("Agent execution failed: " + e.getMessage())); + } LOGGER.debug("Agent execution completed for task {}", taskId); // The consumer (running on the Vert.x worker thread) handles queue lifecycle. // This avoids blocking agent-executor threads waiting for worker threads. } }; + // CRITICAL: Add callback BEFORE starting CompletableFuture to avoid race condition + // If agent completes very fast, whenComplete can fire before caller adds callbacks + runnable.addDoneCallback(doneCallback); + + // Mark as started to prevent further callback additions (enforced by runtime check) + runnable.markStarted(); + CompletableFuture cf = CompletableFuture.runAsync(runnable, executor) .whenComplete((v, err) -> { if (err != null) { diff --git a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java new file mode 100644 index 000000000..57ff6372c --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java @@ -0,0 +1,628 @@ +package io.a2a.server.tasks; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.a2a.server.agentexecution.RequestContext; +import io.a2a.server.events.EventQueue; +import io.a2a.spec.A2AError; +import io.a2a.spec.Artifact; +import io.a2a.spec.Event; +import io.a2a.spec.Message; +import io.a2a.spec.Part; +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.jspecify.annotations.Nullable; + +/** + * Helper for emitting events from AgentExecutor implementations. + * + *

          AgentEmitter provides a simplified API for agents to communicate with clients through + * the A2A protocol. It handles both task lifecycle management and direct message sending, + * automatically populating events with correct task and context IDs from the RequestContext. + * + *

          Core Capabilities

          + *
            + *
          • Task Lifecycle: {@link #submit()}, {@link #startWork()}, {@link #complete()}, + * {@link #fail()}, {@link #cancel()}, {@link #reject()}
          • + *
          • Message Sending: {@link #sendMessage(String)}, {@link #sendMessage(List)}, + * {@link #sendMessage(List, Map)}
          • + *
          • Artifact Streaming: {@link #addArtifact(List)}, {@link #addArtifact(List, String, String, Map)}
          • + *
          • Auth/Input Requirements: {@link #requiresAuth()}, {@link #requiresInput()}
          • + *
          • Custom Events: {@link #taskBuilder()}, {@link #messageBuilder()}, {@link #addTask(Task)}, {@link #emitEvent(Event)}
          • + *
          + * + *

          Usage Patterns

          + * + *

          Simple Message Response (No Task)

          + *
          {@code
          + * public void execute(RequestContext context, AgentEmitter emitter) {
          + *     String response = processRequest(context.getUserInput("\n"));
          + *     emitter.sendMessage(response);
          + * }
          + * }
          + * + *

          Task Lifecycle with Artifacts

          + *
          {@code
          + * public void execute(RequestContext context, AgentEmitter emitter) {
          + *     if (context.getTask() == null) {
          + *         emitter.submit();  // Create task in SUBMITTED state
          + *     }
          + *     emitter.startWork();  // Transition to WORKING
          + *
          + *     // Process and stream results
          + *     List> results = doWork(context.getUserInput("\n"));
          + *     emitter.addArtifact(results);
          + *
          + *     emitter.complete();  // Mark as COMPLETED
          + * }
          + * }
          + * + *

          Streaming Response (LLM)

          + *
          {@code
          + * public void execute(RequestContext context, AgentEmitter emitter) {
          + *     emitter.startWork();
          + *
          + *     for (String chunk : llmService.stream(context.getUserInput("\n"))) {
          + *         emitter.addArtifact(List.of(new TextPart(chunk)));
          + *     }
          + *
          + *     emitter.complete();
          + * }
          + * }
          + * + *

          Event ID Management

          + * All emitted events are automatically populated with: + *
            + *
          • taskId: From RequestContext (may be null for message-only responses)
          • + *
          • contextId: From RequestContext
          • + *
          • messageId: Generated UUID for messages
          • + *
          • artifactId: Generated UUID for artifacts (unless explicitly provided)
          • + *
          + * + * Events are validated by the EventQueue to ensure taskId correctness. + * + * @see io.a2a.server.agentexecution.AgentExecutor + * @see RequestContext + * @see EventQueue + * @since 1.0.0 + */ +public class AgentEmitter { + private final EventQueue eventQueue; + private final @Nullable String taskId; + private final @Nullable String contextId; + private final AtomicBoolean terminalStateReached = new AtomicBoolean(false); + + /** + * Creates a new AgentEmitter for the given request context and event queue. + * + * @param context the request context containing task and context IDs + * @param eventQueue the event queue for enqueueing events + */ + public AgentEmitter(RequestContext context, EventQueue eventQueue) { + this.eventQueue = eventQueue; + this.taskId = context.getTaskId(); + this.contextId = context.getContextId(); + } + + private void updateStatus(TaskState taskState) { + updateStatus(taskState, null, taskState.isFinal()); + } + + /** + * Updates the task status to the given state with an optional message. + * + * @param taskState the new task state + * @param message optional message to include with the status update + */ + public void updateStatus(TaskState taskState, @Nullable Message message) { + updateStatus(taskState, message, taskState.isFinal()); + } + + /** + * Updates the task status to the given state with an optional message and finality flag. + * + * @param state the new task state + * @param message optional message to include with the status update + * @param isFinal whether this is a final status (prevents further updates) + */ + private void updateStatus(TaskState state, @Nullable Message message, boolean isFinal) { + // Check terminal state first (fail fast) + if (terminalStateReached.get()) { + throw new IllegalStateException("Cannot update task status - terminal state already reached"); + } + + // For final states, atomically set the flag + if (isFinal) { + if (!terminalStateReached.compareAndSet(false, true)) { + throw new IllegalStateException("Cannot update task status - terminal state already reached"); + } + } + + TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() + .taskId(taskId) + .contextId(contextId) + .status(new TaskStatus(state, message, null)) + .build(); + eventQueue.enqueueEvent(event); + } + + /** + * Returns the context ID for this emitter. + * + * @return the context ID, or null if not available + */ + public @Nullable String getContextId() { + return this.contextId; + } + + /** + * Returns the task ID for this emitter. + * + * @return the task ID, or null if no task is associated + */ + public @Nullable String getTaskId() { + return this.taskId; + } + + /** + * Adds an artifact with the given parts to the task. + * + * @param parts the parts to include in the artifact + */ + public void addArtifact(List> parts) { + addArtifact(parts, null, null, null); + } + + /** + * Adds an artifact with the given parts, artifact ID, name, and metadata. + * + * @param parts the parts to include in the artifact + * @param artifactId optional artifact ID (generated if null) + * @param name optional artifact name + * @param metadata optional metadata map + */ + public void addArtifact(List> parts, @Nullable String artifactId, @Nullable String name, @Nullable Map metadata) { + addArtifact(parts, artifactId, name, metadata, null, null); + } + + /** + * Adds an artifact with all optional parameters. + * + * @param parts the parts to include in the artifact + * @param artifactId optional artifact ID (generated if null) + * @param name optional artifact name + * @param metadata optional metadata map + * @param append whether to append to an existing artifact + * @param lastChunk whether this is the last chunk in a streaming sequence + */ + public void addArtifact(List> parts, @Nullable String artifactId, @Nullable String name, @Nullable Map metadata, + @Nullable Boolean append, @Nullable Boolean lastChunk) { + if (artifactId == null) { + artifactId = UUID.randomUUID().toString(); + } + TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() + .taskId(taskId) + .contextId(contextId) + .artifact( + Artifact.builder() + .artifactId(artifactId) + .name(name) + .parts(parts) + .metadata(metadata) + .build() + ) + .append(append) + .lastChunk(lastChunk) + .build(); + eventQueue.enqueueEvent(event); + } + + /** + * Marks the task as COMPLETED. + */ + public void complete() { + complete(null); + } + + /** + * Marks the task as COMPLETED with an optional message. + * + * @param message optional message to include with completion + */ + public void complete(@Nullable Message message) { + updateStatus(TaskState.COMPLETED, message); + } + + /** + * Marks the task as FAILED. + */ + public void fail() { + fail((Message) null); + } + + /** + * Marks the task as FAILED with an optional message. + * + * @param message optional message to include with failure + */ + public void fail(@Nullable Message message) { + updateStatus(TaskState.FAILED, message); + } + + /** + * Enqueues an A2A error event which will automatically transition the task to FAILED. + *

          + * Use this when you need to fail the task with a specific A2A error (such as + * {@link io.a2a.spec.UnsupportedOperationError}, {@link io.a2a.spec.InvalidRequestError}, + * {@link io.a2a.spec.TaskNotFoundError}, etc.) that should be sent to the client. + *

          + *

          + * The error event is enqueued and the MainEventBusProcessor will automatically transition + * the task to FAILED state. This ensures thread-safe state transitions without race conditions, + * as the single-threaded MainEventBusProcessor handles all state updates. + *

          + *

          + * Error events are terminal (stop event consumption) and trigger automatic FAILED state transition. + * The error details are sent to the originating client only, while the FAILED status is replicated + * to all nodes in multi-instance deployments. + *

          + *

          Example usage: + *

          {@code
          +     * public void execute(RequestContext context, AgentEmitter emitter) {
          +     *     if (!isSupported(context.getMessage())) {
          +     *         emitter.fail(new UnsupportedOperationError("Feature not supported"));
          +     *         return;
          +     *     }
          +     *     // ... normal processing
          +     * }
          +     * }
          + * + * @param error the A2A error to enqueue and send to the client + * @since 1.0.0 + */ + public void fail(A2AError error) { + // Set terminal state flag BEFORE enqueueing error + // This prevents race conditions where agent calls fail(error) then complete() + if (!terminalStateReached.compareAndSet(false, true)) { + throw new IllegalStateException("Cannot update task status - terminal state already reached"); + } + + eventQueue.enqueueEvent(error); + // Status transition happens automatically in MainEventBusProcessor + // The error event is terminal and will trigger FAILED state transition + } + + /** + * Marks the task as SUBMITTED. + */ + public void submit() { + submit(null); + } + + /** + * Marks the task as SUBMITTED with an optional message. + * + * @param message optional message to include + */ + public void submit(@Nullable Message message) { + updateStatus(TaskState.SUBMITTED, message); + } + + /** + * Marks the task as WORKING (actively being processed). + */ + public void startWork() { + startWork(null); + } + + /** + * Marks the task as WORKING with an optional message. + * + * @param message optional message to include + */ + public void startWork(@Nullable Message message) { + updateStatus(TaskState.WORKING, message); + } + + /** + * Marks the task as CANCELED. + */ + public void cancel() { + cancel(null); + } + + /** + * Marks the task as CANCELED with an optional message. + * + * @param message optional message to include + */ + public void cancel(@Nullable Message message) { + updateStatus(TaskState.CANCELED, message); + } + + /** + * Marks the task as REJECTED. + */ + public void reject() { + reject(null); + } + + /** + * Marks the task as REJECTED with an optional message. + * + * @param message optional message to include + */ + public void reject(@Nullable Message message) { + updateStatus(TaskState.REJECTED, message); + } + + /** + * Marks the task as INPUT_REQUIRED, indicating the agent needs user input to continue. + */ + public void requiresInput() { + requiresInput(null, false); + } + + /** + * Marks the task as INPUT_REQUIRED with an optional message. + * + * @param message optional message to include + */ + public void requiresInput(@Nullable Message message) { + requiresInput(message, false); + } + + /** + * Marks the task as INPUT_REQUIRED with a finality flag. + * + * @param isFinal whether this is a final status (prevents further updates) + */ + public void requiresInput(boolean isFinal) { + requiresInput(null, isFinal); + } + + /** + * Marks the task as INPUT_REQUIRED with an optional message and finality flag. + * + * @param message optional message to include + * @param isFinal whether this is a final status (prevents further updates) + */ + public void requiresInput(@Nullable Message message, boolean isFinal) { + updateStatus(TaskState.INPUT_REQUIRED, message, isFinal); + } + + /** + * Marks the task as AUTH_REQUIRED, indicating the agent needs authentication to continue. + */ + public void requiresAuth() { + requiresAuth(null, false); + } + + /** + * Marks the task as AUTH_REQUIRED with an optional message. + * + * @param message optional message to include + */ + public void requiresAuth(@Nullable Message message) { + requiresAuth(message, false); + } + + /** + * Marks the task as AUTH_REQUIRED with a finality flag. + * + * @param isFinal whether this is a final status (prevents further updates) + */ + public void requiresAuth(boolean isFinal) { + requiresAuth(null, isFinal); + } + + /** + * Marks the task as AUTH_REQUIRED with an optional message and finality flag. + * + * @param message optional message to include + * @param isFinal whether this is a final status (prevents further updates) + */ + public void requiresAuth(@Nullable Message message, boolean isFinal) { + updateStatus(TaskState.AUTH_REQUIRED, message, isFinal); + } + + /** + * Creates a new agent message with the given parts and metadata. + * Pre-populates the message with agent role, task ID, context ID, and a generated message ID. + * + * @param parts the parts to include in the message + * @param metadata optional metadata to attach to the message + * @return a new Message object ready to be sent + */ + public Message newAgentMessage(List> parts, @Nullable Map metadata) { + return Message.builder() + .role(Message.Role.AGENT) + .taskId(taskId) + .contextId(contextId) + .messageId(UUID.randomUUID().toString()) + .metadata(metadata) + .parts(parts) + .build(); + } + + /** + * Sends a simple text message to the client. + * Convenience method for agents that respond with plain text without creating a task. + * + * @param text the text content to send + */ + public void sendMessage(String text) { + sendMessage(List.of(new TextPart(text))); + } + + /** + * Sends a message with custom parts (text, images, etc.) to the client. + * Use this for rich responses that don't require task lifecycle management. + * + * @param parts the message parts to send + */ + public void sendMessage(List> parts) { + sendMessage(parts, null); + } + + /** + * Sends a message with parts and metadata to the client. + * Creates an agent message with the current task and context IDs (if available) + * and enqueues it to the event queue. + * + * @param parts the message parts to send + * @param metadata optional metadata to attach to the message + */ + public void sendMessage(List> parts, @Nullable Map metadata) { + Message message = newAgentMessage(parts, metadata); + eventQueue.enqueueEvent(message); + } + + /** + * Sends an existing Message object directly to the client. + *

          + * Use this when you need to forward or echo an existing message without creating a new one. + * The message is enqueued as-is, preserving its messageId, metadata, and all other fields. + *

          + *

          + * Note: This is typically used for forwarding user messages or preserving specific + * message properties. For most cases, prefer {@link #sendMessage(String)} or + * {@link #sendMessage(List)} which create new agent messages with generated IDs. + *

          + *

          Example usage: + *

          {@code
          +     * public void execute(RequestContext context, AgentEmitter emitter) {
          +     *     // Echo the user's message back
          +     *     emitter.sendMessage(context.getMessage());
          +     * }
          +     * }
          + * + * @param message the message to send to the client + * @since 1.0.0 + */ + public void sendMessage(Message message) { + eventQueue.enqueueEvent(message); + } + + /** + * Adds a custom Task object to be sent to the client. + *

          + * Use this when you need to create a Task with specific fields (history, artifacts, etc.) + * that the convenience methods like {@link #submit()}, {@link #startWork()}, or + * {@link #complete()} don't provide. + *

          + *

          + * Typical usage pattern: Build a task with {@link #taskBuilder()}, customize it, + * then add it with this method. + *

          + *

          Example usage: + *

          {@code
          +     * public void execute(RequestContext context, AgentEmitter emitter) {
          +     *     // Create a task with specific status and history
          +     *     Task task = emitter.taskBuilder()
          +     *         .status(new TaskStatus(TaskState.SUBMITTED))
          +     *         .history(List.of(context.getMessage()))
          +     *         .build();
          +     *     emitter.addTask(task);
          +     * }
          +     * }
          + * + * @param task the task to add + * @since 1.0.0 + */ + public void addTask(Task task) { + eventQueue.enqueueEvent(task); + } + + /** + * Emits a custom Event object to the client. + *

          + * This is a general-purpose method for emitting any Event type. Most agents should use the + * convenience methods ({@link #sendMessage(String)}, {@link #addTask(Task)}, + * {@link #addArtifact(List)}, {@link #complete()}, etc.), but this method provides flexibility + * for agents that need to create and emit custom events using the event builders. + *

          + *

          Example usage: + *

          {@code
          +     * public void execute(RequestContext context, AgentEmitter emitter) {
          +     *     // Create a custom TaskStatusUpdateEvent
          +     *     TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder()
          +     *         .taskId(context.getTaskId())
          +     *         .contextId(context.getContextId())
          +     *         .status(new TaskStatus(TaskState.WORKING))
          +     *         .isFinal(false)
          +     *         .build();
          +     *     emitter.emitEvent(event);
          +     * }
          +     * }
          + * + * @param event the event to emit + * @since 1.0.0 + */ + public void emitEvent(Event event) { + eventQueue.enqueueEvent(event); + } + + /** + * Creates a Task.Builder pre-populated with the correct task and context IDs. + * Agents can customize other Task fields (status, artifacts, etc.) before calling build(). + * + *

          Example usage: + *

          {@code
          +     * Task task = emitter.taskBuilder()
          +     *     .status(new TaskStatus(TaskState.WORKING))
          +     *     .build();
          +     * }
          + * + * @return a Task.Builder with id and contextId already set + */ + public Task.Builder taskBuilder() { + return Task.builder() + .id(taskId) + .contextId(contextId); + } + + /** + * Creates a Message.Builder pre-populated with agent defaults. + * Sets taskId only if non-null (messages can exist independently of tasks). + * + *

          Pre-populated fields: + *

            + *
          • taskId - set only if this AgentEmitter has a non-null taskId
          • + *
          • contextId - current context ID
          • + *
          • role - Message.Role.AGENT
          • + *
          • messageId - generated UUID
          • + *
          + * + *

          Example usage: + *

          {@code
          +     * Message msg = emitter.messageBuilder()
          +     *     .parts(List.of(new TextPart("Hello")))
          +     *     .metadata(Map.of("key", "value"))
          +     *     .build();
          +     * }
          + * + * @return a Message.Builder with common agent fields already set + */ + public Message.Builder messageBuilder() { + Message.Builder builder = Message.builder() + .contextId(contextId) + .role(Message.Role.AGENT) + .messageId(UUID.randomUUID().toString()); + + // Only set taskId if present (messages can exist without tasks) + if (taskId != null) { + builder.taskId(taskId); + } + + return builder; + } + +} 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 506b3f3b6..b36868a63 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 @@ -166,7 +166,8 @@ public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, // Determine interrupt behavior boolean shouldInterrupt = false; boolean isFinalEvent = (event instanceof Task task && task.status().state().isFinal()) - || (event instanceof TaskStatusUpdateEvent tsue && tsue.isFinal()); + || (event instanceof TaskStatusUpdateEvent tsue && tsue.isFinal()) + || (event instanceof A2AError); // A2AError events are terminal boolean isAuthRequired = (event instanceof Task task && task.status().state() == TaskState.AUTH_REQUIRED) || (event instanceof TaskStatusUpdateEvent tsue && tsue.status().state() == TaskState.AUTH_REQUIRED); 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 948ec596c..abb764755 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 @@ -1,5 +1,6 @@ package io.a2a.server.tasks; +import static io.a2a.spec.TaskState.FAILED; import static io.a2a.spec.TaskState.SUBMITTED; import static io.a2a.util.Assert.checkNotNullParam; import static io.a2a.util.Utils.appendArtifactToTask; @@ -10,6 +11,7 @@ import java.util.List; import java.util.Map; +import io.a2a.spec.A2AError; import io.a2a.spec.A2AServerException; import io.a2a.spec.Event; import io.a2a.spec.InternalError; @@ -112,6 +114,42 @@ public boolean process(Event event, boolean isReplicated) throws A2AServerExcept isFinal = saveTaskEvent(taskStatusUpdateEvent, isReplicated); } else if (event instanceof TaskArtifactUpdateEvent taskArtifactUpdateEvent) { isFinal = saveTaskEvent(taskArtifactUpdateEvent, isReplicated); + } else if (event instanceof A2AError) { + // A2AError events trigger automatic transition to FAILED state + // Error details are NOT persisted in TaskStore (client-specific) + // Only the FAILED status is persisted and replicated across nodes + + // A2AError events don't have taskId/contextId fields, so we need to ensure + // we have these from the existing task or TaskManager state + if (taskId == null) { + // No task context - A2AError event will be distributed to clients but no state update + LOGGER.debug("A2AError event without task context - skipping state update"); + return true; // Return true (is final) to stop event consumption + } + + // Ensure we have contextId - get from existing task if not set + String errorContextId = contextId; + if (errorContextId == null) { + Task existingTask = getTask(); + if (existingTask != null) { + errorContextId = existingTask.contextId(); + } + } + + // Only create status update if we have contextId + if (errorContextId != null) { + LOGGER.debug("A2AError event detected, transitioning task {} to FAILED", taskId); + TaskStatusUpdateEvent failedEvent = TaskStatusUpdateEvent.builder() + .taskId(taskId) + .contextId(errorContextId) + .status(new TaskStatus(FAILED)) + .build(); + isFinal = saveTaskEvent(failedEvent, isReplicated); + } else { + // Can't update status without contextId, but error is still terminal + LOGGER.debug("A2AError event for task {} without contextId - skipping state update", taskId); + isFinal = true; + } } return isFinal; } 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 deleted file mode 100644 index c28e55c5c..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskUpdater.java +++ /dev/null @@ -1,190 +0,0 @@ -package io.a2a.server.tasks; - -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; - -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TaskArtifactUpdateEvent; -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; - private final @Nullable String taskId; - private final @Nullable String contextId; - private final AtomicBoolean terminalStateReached = new AtomicBoolean(false); - private final Object stateLock = new Object(); - - public TaskUpdater(RequestContext context, EventQueue eventQueue) { - this.eventQueue = eventQueue; - this.taskId = context.getTaskId(); - this.contextId = context.getContextId(); - } - - private void updateStatus(TaskState taskState) { - updateStatus(taskState, null, taskState.isFinal()); - } - - public void updateStatus(TaskState taskState, @Nullable Message message) { - updateStatus(taskState, message, taskState.isFinal()); - } - - public void updateStatus(TaskState state, @Nullable Message message, boolean isFinal) { - synchronized (stateLock) { - // Check if we're already in a terminal state - if (terminalStateReached.get()) { - throw new IllegalStateException("Cannot update task status - terminal state already reached"); - } - - // If this is a final state, set the flag - if (isFinal) { - terminalStateReached.set(true); - } - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId(contextId) - .status(new TaskStatus(state, message, null)) - .build(); - eventQueue.enqueueEvent(event); - } - } - - public @Nullable String getContextId() { - return this.contextId; - } - - public @Nullable String getTaskId() { - return this.taskId; - } - - public void addArtifact(List> parts) { - addArtifact(parts, null, null, null); - } - - public void addArtifact(List> parts, @Nullable String artifactId, @Nullable String name, @Nullable Map metadata) { - addArtifact(parts, artifactId, name, metadata, null, null); - } - - public void addArtifact(List> parts, @Nullable String artifactId, @Nullable String name, @Nullable Map metadata, - @Nullable Boolean append, @Nullable Boolean lastChunk) { - if (artifactId == null) { - artifactId = UUID.randomUUID().toString(); - } - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId(taskId) - .contextId(contextId) - .artifact( - Artifact.builder() - .artifactId(artifactId) - .name(name) - .parts(parts) - .metadata(metadata) - .build() - ) - .append(append) - .lastChunk(lastChunk) - .build(); - eventQueue.enqueueEvent(event); - } - - public void complete() { - complete(null); - } - - public void complete(@Nullable Message message) { - updateStatus(TaskState.COMPLETED, message); - } - - public void fail() { - fail(null); - } - - public void fail(@Nullable Message message) { - updateStatus(TaskState.FAILED, message); - } - - public void submit() { - submit(null); - } - - public void submit(@Nullable Message message) { - updateStatus(TaskState.SUBMITTED, message); - } - - public void startWork() { - startWork(null); - } - - public void startWork(@Nullable Message message) { - updateStatus(TaskState.WORKING, message); - } - - public void cancel() { - cancel(null); - } - - public void cancel(@Nullable Message message) { - updateStatus(TaskState.CANCELED, message); - } - - public void reject() { - reject(null); - } - - public void reject(@Nullable Message message) { - updateStatus(TaskState.REJECTED, message); - } - - public void requiresInput() { - requiresInput(null, false); - } - - public void requiresInput(@Nullable Message message) { - requiresInput(message, false); - } - - public void requiresInput(boolean isFinal) { - requiresInput(null, isFinal); - } - - public void requiresInput(@Nullable Message message, boolean isFinal) { - updateStatus(TaskState.INPUT_REQUIRED, message, isFinal); - } - - public void requiresAuth() { - requiresAuth(null, false); - } - - public void requiresAuth(@Nullable Message message) { - requiresAuth(message, false); - } - - public void requiresAuth(boolean isFinal) { - requiresAuth(null, isFinal); - } - - public void requiresAuth(@Nullable Message message, boolean isFinal) { - updateStatus(TaskState.AUTH_REQUIRED, message, isFinal); - } - - public Message newAgentMessage(List> parts, @Nullable Map metadata) { - return Message.builder() - .role(Message.Role.AGENT) - .taskId(taskId) - .contextId(contextId) - .messageId(UUID.randomUUID().toString()) - .metadata(metadata) - .parts(parts) - .build(); - } - -} diff --git a/server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java b/server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java new file mode 100644 index 000000000..2b1913355 --- /dev/null +++ b/server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java @@ -0,0 +1,136 @@ +package io.a2a.server.events; + +import org.junit.jupiter.api.Test; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Tests for EnhancedRunnable to verify callback registration enforcement. + * These tests ensure that callbacks cannot be added after execution starts, + * preventing race conditions in agent execution. + */ +public class EnhancedRunnableTest { + + @Test + public void testCannotAddCallbackAfterStart() { + EnhancedRunnable runnable = new EnhancedRunnable() { + @Override + public void run() { + // Empty + } + }; + + // Add callback before start - should succeed + AtomicBoolean called = new AtomicBoolean(false); + runnable.addDoneCallback((r) -> called.set(true)); + + // Mark as started + runnable.markStarted(); + + // Try to add callback after start - should fail + IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> runnable.addDoneCallback((r) -> {})); + + assertTrue(exception.getMessage().contains("Cannot add callback after runnable has started")); + } + + @Test + public void testCallbacksInvokedAfterCompletion() throws Exception { + EnhancedRunnable runnable = new EnhancedRunnable() { + @Override + public void run() { + // Empty + } + }; + + AtomicBoolean callback1Called = new AtomicBoolean(false); + AtomicBoolean callback2Called = new AtomicBoolean(false); + + runnable.addDoneCallback((r) -> callback1Called.set(true)); + runnable.addDoneCallback((r) -> callback2Called.set(true)); + runnable.markStarted(); + + CompletableFuture.runAsync(runnable, Executors.newSingleThreadExecutor()) + .thenRun(runnable::invokeDoneCallbacks) + .get(); + + assertTrue(callback1Called.get()); + assertTrue(callback2Called.get()); + } + + @Test + public void testMultipleCallbacksBeforeStart() { + EnhancedRunnable runnable = new EnhancedRunnable() { + @Override + public void run() { + // Empty + } + }; + + // Should be able to add multiple callbacks before start + assertDoesNotThrow(() -> { + runnable.addDoneCallback((r) -> {}); + runnable.addDoneCallback((r) -> {}); + runnable.addDoneCallback((r) -> {}); + }); + + // Mark as started + runnable.markStarted(); + + // Now adding should fail + assertThrows(IllegalStateException.class, + () -> runnable.addDoneCallback((r) -> {})); + } + + @Test + public void testErrorHandling() { + EnhancedRunnable runnable = new EnhancedRunnable() { + @Override + public void run() { + throw new RuntimeException("Test error"); + } + }; + + AtomicBoolean callbackInvoked = new AtomicBoolean(false); + runnable.addDoneCallback((r) -> { + callbackInvoked.set(true); + assertNotNull(r.getError()); + assertEquals("Test error", r.getError().getMessage()); + }); + + runnable.markStarted(); + + try { + runnable.run(); + } catch (RuntimeException e) { + runnable.setError(e); + } + + runnable.invokeDoneCallbacks(); + assertTrue(callbackInvoked.get()); + } + + @Test + public void testMarkStartedIdempotent() { + EnhancedRunnable runnable = new EnhancedRunnable() { + @Override + public void run() { + // Empty + } + }; + + // Should be able to call markStarted multiple times + assertDoesNotThrow(() -> { + runnable.markStarted(); + runnable.markStarted(); + runnable.markStarted(); + }); + + // But callbacks should still be blocked + assertThrows(IllegalStateException.class, + () -> runnable.addDoneCallback((r) -> {})); + } +} 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 e428c679e..39ff07f09 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 @@ -23,7 +23,7 @@ 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; +import io.a2a.server.tasks.AgentEmitter; import io.a2a.server.events.EventQueueItem; import io.a2a.server.events.EventQueueUtil; import io.a2a.server.events.InMemoryQueueManager; @@ -87,16 +87,16 @@ public class AbstractA2ARequestHandlerTest { public void init() { executor = new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { if (agentExecutorExecute != null) { - agentExecutorExecute.invoke(context, eventQueue); + agentExecutorExecute.invoke(context, agentEmitter); } } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { if (agentExecutorCancel != null) { - agentExecutorCancel.invoke(context, eventQueue); + agentExecutorCancel.invoke(context, agentEmitter); } } }; @@ -166,7 +166,7 @@ private static String loadPreferredTransportFromProperties() { } protected interface AgentExecutorMethod { - void invoke(RequestContext context, EventQueue eventQueue) throws A2AError; + void invoke(RequestContext context, AgentEmitter agentEmitter) throws A2AError; } /** diff --git a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java new file mode 100644 index 000000000..eafcc712a --- /dev/null +++ b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java @@ -0,0 +1,248 @@ +package io.a2a.server.tasks; + +import io.a2a.server.agentexecution.RequestContext; +import io.a2a.server.events.EventQueue; +import io.a2a.spec.UnsupportedOperationError; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * Concurrency tests for AgentEmitter to verify thread-safety of terminal state management. + * These tests ensure that the AtomicBoolean-based terminal state flag prevents race conditions + * when multiple threads attempt to set terminal states concurrently. + */ +public class AgentEmitterConcurrencyTest { + + @Test + public void testConcurrentTerminalStateUpdates() throws InterruptedException { + // Setup + RequestContext context = mock(RequestContext.class); + when(context.getTaskId()).thenReturn("test-task-123"); + when(context.getContextId()).thenReturn("test-context-456"); + + EventQueue eventQueue = mock(EventQueue.class); + AgentEmitter emitter = new AgentEmitter(context, eventQueue); + + // Test concurrent completion attempts + int threadCount = 10; + ExecutorService executor = Executors.newFixedThreadPool(threadCount); + CountDownLatch startLatch = new CountDownLatch(1); + CountDownLatch doneLatch = new CountDownLatch(threadCount); + AtomicInteger successCount = new AtomicInteger(0); + AtomicInteger failureCount = new AtomicInteger(0); + + for (int i = 0; i < threadCount; i++) { + executor.submit(() -> { + try { + startLatch.await(); // Wait for all threads to be ready + emitter.complete(); + successCount.incrementAndGet(); + } catch (IllegalStateException e) { + failureCount.incrementAndGet(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + doneLatch.countDown(); + } + }); + } + + startLatch.countDown(); // Start all threads simultaneously + assertTrue(doneLatch.await(5, TimeUnit.SECONDS), "All threads should complete"); + + // Verify: exactly one success, rest failures + assertEquals(1, successCount.get(), "Exactly one thread should succeed"); + assertEquals(threadCount - 1, failureCount.get(), "All other threads should fail"); + + // Verify: only one event was enqueued + verify(eventQueue, times(1)).enqueueEvent(any()); + + executor.shutdown(); + } + + @Test + public void testConcurrentMixedTerminalStates() throws InterruptedException { + // Setup + RequestContext context = mock(RequestContext.class); + when(context.getTaskId()).thenReturn("test-task-123"); + when(context.getContextId()).thenReturn("test-context-456"); + + EventQueue eventQueue = mock(EventQueue.class); + AgentEmitter emitter = new AgentEmitter(context, eventQueue); + + // Test concurrent different terminal state attempts + ExecutorService executor = Executors.newFixedThreadPool(3); + CountDownLatch startLatch = new CountDownLatch(1); + CountDownLatch doneLatch = new CountDownLatch(3); + AtomicInteger successCount = new AtomicInteger(0); + + // Thread 1: complete + executor.submit(() -> { + try { + startLatch.await(); + emitter.complete(); + successCount.incrementAndGet(); + } catch (Exception e) { + // Expected for 2 out of 3 threads + } finally { + doneLatch.countDown(); + } + }); + + // Thread 2: fail + executor.submit(() -> { + try { + startLatch.await(); + emitter.fail(); + successCount.incrementAndGet(); + } catch (Exception e) { + // Expected for 2 out of 3 threads + } finally { + doneLatch.countDown(); + } + }); + + // Thread 3: cancel + executor.submit(() -> { + try { + startLatch.await(); + emitter.cancel(); + successCount.incrementAndGet(); + } catch (Exception e) { + // Expected for 2 out of 3 threads + } finally { + doneLatch.countDown(); + } + }); + + startLatch.countDown(); + assertTrue(doneLatch.await(5, TimeUnit.SECONDS)); + + // Verify: exactly one success + assertEquals(1, successCount.get(), "Exactly one terminal state should succeed"); + verify(eventQueue, times(1)).enqueueEvent(any()); + + executor.shutdown(); + } + + @Test + public void testConcurrentFailWithErrorAndComplete() throws InterruptedException { + // Setup + RequestContext context = mock(RequestContext.class); + when(context.getTaskId()).thenReturn("test-task-123"); + when(context.getContextId()).thenReturn("test-context-456"); + + EventQueue eventQueue = mock(EventQueue.class); + AgentEmitter emitter = new AgentEmitter(context, eventQueue); + + ExecutorService executor = Executors.newFixedThreadPool(2); + CountDownLatch startLatch = new CountDownLatch(1); + CountDownLatch doneLatch = new CountDownLatch(2); + AtomicInteger successCount = new AtomicInteger(0); + + executor.submit(() -> { + try { + startLatch.await(); + emitter.fail(new UnsupportedOperationError()); + successCount.incrementAndGet(); + } catch (Exception e) { + // Expected for one thread + } finally { + doneLatch.countDown(); + } + }); + + executor.submit(() -> { + try { + startLatch.await(); + emitter.complete(); + successCount.incrementAndGet(); + } catch (Exception e) { + // Expected for one thread + } finally { + doneLatch.countDown(); + } + }); + + startLatch.countDown(); + assertTrue(doneLatch.await(5, TimeUnit.SECONDS)); + assertEquals(1, successCount.get(), "Exactly one terminal operation should succeed"); + + executor.shutdown(); + } + + @Test + public void testFailWithErrorSetsTerminalState() { + // Setup + RequestContext context = mock(RequestContext.class); + when(context.getTaskId()).thenReturn("test-task-123"); + when(context.getContextId()).thenReturn("test-context-456"); + + EventQueue eventQueue = mock(EventQueue.class); + AgentEmitter emitter = new AgentEmitter(context, eventQueue); + + // Call fail with error + emitter.fail(new UnsupportedOperationError()); + + // Verify terminal state is set - subsequent calls should throw + IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> emitter.complete()); + assertEquals("Cannot update task status - terminal state already reached", + exception.getMessage()); + } + + @Test + public void testFailWithErrorThenFailWithMessage() { + // Setup + RequestContext context = mock(RequestContext.class); + when(context.getTaskId()).thenReturn("test-task-123"); + when(context.getContextId()).thenReturn("test-context-456"); + + EventQueue eventQueue = mock(EventQueue.class); + AgentEmitter emitter = new AgentEmitter(context, eventQueue); + + // Call fail with error + emitter.fail(new UnsupportedOperationError()); + + // Second fail should throw + IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> emitter.fail()); + assertEquals("Cannot update task status - terminal state already reached", + exception.getMessage()); + } + + @Test + public void testNonTerminalThenTerminalState() throws InterruptedException { + // Setup + RequestContext context = mock(RequestContext.class); + when(context.getTaskId()).thenReturn("test-task-123"); + when(context.getContextId()).thenReturn("test-context-456"); + + EventQueue eventQueue = mock(EventQueue.class); + AgentEmitter emitter = new AgentEmitter(context, eventQueue); + + // Non-terminal states should work + emitter.submit(); + emitter.startWork(); + + // Terminal state should work + emitter.complete(); + + // Verify events were enqueued + verify(eventQueue, times(3)).enqueueEvent(any()); + + // Further updates should fail + IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> emitter.startWork()); + assertEquals("Cannot update task status - terminal state already reached", + exception.getMessage()); + } +} diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java similarity index 87% rename from server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java rename to server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java index a5ec77f01..853037a9c 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskUpdaterTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java @@ -30,7 +30,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class TaskUpdaterTest { +public class AgentEmitterTest { public static final String TEST_TASK_ID = "test-task-id"; public static final String TEST_TASK_CONTEXT_ID = "test-task-context-id"; @@ -48,7 +48,7 @@ public class TaskUpdaterTest { EventQueue eventQueue; private MainEventBus mainEventBus; private MainEventBusProcessor mainEventBusProcessor; - private TaskUpdater taskUpdater; + private AgentEmitter agentEmitter; @@ -69,7 +69,7 @@ public void init() { .setTaskId(TEST_TASK_ID) .setContextId(TEST_TASK_CONTEXT_ID) .build(); - taskUpdater = new TaskUpdater(context, eventQueue); + agentEmitter = new AgentEmitter(context, eventQueue); } @AfterEach @@ -81,7 +81,7 @@ public void cleanup() { @Test public void testAddArtifactWithCustomIdAndName() throws Exception { - taskUpdater.addArtifact(SAMPLE_PARTS, "custom-artifact-id", "Custom Artifact", null); + agentEmitter.addArtifact(SAMPLE_PARTS, "custom-artifact-id", "Custom Artifact", null); EventQueueItem item = eventQueue.dequeueEventItem(5000); assertNotNull(item); Event event = item.getEvent(); @@ -101,147 +101,147 @@ public void testAddArtifactWithCustomIdAndName() throws Exception { @Test public void testCompleteWithoutMessage() throws Exception { - taskUpdater.complete(); + agentEmitter.complete(); checkTaskStatusUpdateEventOnQueue(true, TaskState.COMPLETED, null); } @Test public void testCompleteWithMessage() throws Exception { - taskUpdater.complete(SAMPLE_MESSAGE); + agentEmitter.complete(SAMPLE_MESSAGE); checkTaskStatusUpdateEventOnQueue(true, TaskState.COMPLETED, SAMPLE_MESSAGE); } @Test public void testSubmitWithoutMessage() throws Exception { - taskUpdater.submit(); + agentEmitter.submit(); checkTaskStatusUpdateEventOnQueue(false, TaskState.SUBMITTED, null); } @Test public void testSubmitWithMessage() throws Exception { - taskUpdater.submit(SAMPLE_MESSAGE); + agentEmitter.submit(SAMPLE_MESSAGE); checkTaskStatusUpdateEventOnQueue(false, TaskState.SUBMITTED, SAMPLE_MESSAGE); } @Test public void testStartWorkWithoutMessage() throws Exception { - taskUpdater.startWork(); + agentEmitter.startWork(); checkTaskStatusUpdateEventOnQueue(false, TaskState.WORKING, null); } @Test public void testStartWorkWithMessage() throws Exception { - taskUpdater.startWork(SAMPLE_MESSAGE); + agentEmitter.startWork(SAMPLE_MESSAGE); checkTaskStatusUpdateEventOnQueue(false, TaskState.WORKING, SAMPLE_MESSAGE); } @Test public void testFailedWithoutMessage() throws Exception { - taskUpdater.fail(); + agentEmitter.fail(); checkTaskStatusUpdateEventOnQueue(true, TaskState.FAILED, null); } @Test public void testFailedWithMessage() throws Exception { - taskUpdater.fail(SAMPLE_MESSAGE); + agentEmitter.fail(SAMPLE_MESSAGE); checkTaskStatusUpdateEventOnQueue(true, TaskState.FAILED, SAMPLE_MESSAGE); } @Test public void testCanceledWithoutMessage() throws Exception { - taskUpdater.cancel(); + agentEmitter.cancel(); checkTaskStatusUpdateEventOnQueue(true, TaskState.CANCELED, null); } @Test public void testCanceledWithMessage() throws Exception { - taskUpdater.cancel(SAMPLE_MESSAGE); + agentEmitter.cancel(SAMPLE_MESSAGE); checkTaskStatusUpdateEventOnQueue(true, TaskState.CANCELED, SAMPLE_MESSAGE); } @Test public void testRejectWithoutMessage() throws Exception { - taskUpdater.reject(); + agentEmitter.reject(); checkTaskStatusUpdateEventOnQueue(true, TaskState.REJECTED, null); } @Test public void testRejectWithMessage() throws Exception { - taskUpdater.reject(SAMPLE_MESSAGE); + agentEmitter.reject(SAMPLE_MESSAGE); checkTaskStatusUpdateEventOnQueue(true, TaskState.REJECTED, SAMPLE_MESSAGE); } @Test public void testRequiresInputWithoutMessage() throws Exception { - taskUpdater.requiresInput(); + agentEmitter.requiresInput(); checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, null); } @Test public void testRequiresInputWithMessage() throws Exception { - taskUpdater.requiresInput(SAMPLE_MESSAGE); + agentEmitter.requiresInput(SAMPLE_MESSAGE); checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, SAMPLE_MESSAGE); } @Test public void testRequiresInputWithFinalTrue() throws Exception { - taskUpdater.requiresInput(true); + agentEmitter.requiresInput(true); checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, null); } @Test public void testRequiresInputWithMessageAndFinalTrue() throws Exception { - taskUpdater.requiresInput(SAMPLE_MESSAGE, true); + agentEmitter.requiresInput(SAMPLE_MESSAGE, true); checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, SAMPLE_MESSAGE); } @Test public void testRequiresAuthWithoutMessage() throws Exception { - taskUpdater.requiresAuth(); + agentEmitter.requiresAuth(); checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, null); } @Test public void testRequiresAuthWithMessage() throws Exception { - taskUpdater.requiresAuth(SAMPLE_MESSAGE); + agentEmitter.requiresAuth(SAMPLE_MESSAGE); checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, SAMPLE_MESSAGE); } @Test public void testRequiresAuthWithFinalTrue() throws Exception { - taskUpdater.requiresAuth(true); + agentEmitter.requiresAuth(true); checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, null); } @Test public void testRequiresAuthWithMessageAndFinalTrue() throws Exception { - taskUpdater.requiresAuth(SAMPLE_MESSAGE, true); + agentEmitter.requiresAuth(SAMPLE_MESSAGE, true); checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, SAMPLE_MESSAGE); } @Test public void testNonTerminalStateUpdatesAllowed() throws Exception { // Non-terminal states should be allowed multiple times - taskUpdater.submit(); + agentEmitter.submit(); checkTaskStatusUpdateEventOnQueue(false, TaskState.SUBMITTED, null); - taskUpdater.startWork(); + agentEmitter.startWork(); checkTaskStatusUpdateEventOnQueue(false, TaskState.WORKING, null); - taskUpdater.requiresInput(); + agentEmitter.requiresInput(); checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, null); - taskUpdater.requiresAuth(); + agentEmitter.requiresAuth(); checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, null); // Should still be able to complete - taskUpdater.complete(); + agentEmitter.complete(); checkTaskStatusUpdateEventOnQueue(true, TaskState.COMPLETED, null); } @Test public void testNewAgentMessage() throws Exception { - Message message = taskUpdater.newAgentMessage(SAMPLE_PARTS, null); + Message message = agentEmitter.newAgentMessage(SAMPLE_PARTS, null); assertEquals(AGENT, message.role()); assertEquals(TEST_TASK_ID, message.taskId()); @@ -254,7 +254,7 @@ public void testNewAgentMessage() throws Exception { @Test public void testNewAgentMessageWithMetadata() throws Exception { Map metadata = Map.of("key", "value"); - Message message = taskUpdater.newAgentMessage(SAMPLE_PARTS, metadata); + Message message = agentEmitter.newAgentMessage(SAMPLE_PARTS, metadata); assertEquals(AGENT, message.role()); assertEquals(TEST_TASK_ID, message.taskId()); @@ -266,7 +266,7 @@ public void testNewAgentMessageWithMetadata() throws Exception { @Test public void testAddArtifactWithAppendTrue() throws Exception { - taskUpdater.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, true, null); + agentEmitter.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, true, null); EventQueueItem item = eventQueue.dequeueEventItem(5000); assertNotNull(item); Event event = item.getEvent(); @@ -287,7 +287,7 @@ public void testAddArtifactWithAppendTrue() throws Exception { @Test public void testAddArtifactWithLastChunkTrue() throws Exception { - taskUpdater.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, null, true); + agentEmitter.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, null, true); EventQueueItem item = eventQueue.dequeueEventItem(5000); assertNotNull(item); Event event = item.getEvent(); @@ -304,7 +304,7 @@ public void testAddArtifactWithLastChunkTrue() throws Exception { @Test public void testAddArtifactWithAppendAndLastChunk() throws Exception { - taskUpdater.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, true, false); + agentEmitter.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, true, false); EventQueueItem item = eventQueue.dequeueEventItem(5000); assertNotNull(item); Event event = item.getEvent(); @@ -320,7 +320,7 @@ public void testAddArtifactWithAppendAndLastChunk() throws Exception { @Test public void testAddArtifactGeneratesIdWhenNull() throws Exception { - taskUpdater.addArtifact(SAMPLE_PARTS, null, "Test Artifact", null); + agentEmitter.addArtifact(SAMPLE_PARTS, null, "Test Artifact", null); EventQueueItem item = eventQueue.dequeueEventItem(5000); assertNotNull(item); Event event = item.getEvent(); @@ -340,11 +340,11 @@ public void testAddArtifactGeneratesIdWhenNull() throws Exception { @Test public void testTerminalStateProtectionAfterComplete() throws Exception { // Complete the task first - taskUpdater.complete(); + agentEmitter.complete(); checkTaskStatusUpdateEventOnQueue(true, TaskState.COMPLETED, null); // Try to update status again - should throw RuntimeException - RuntimeException exception = assertThrows(RuntimeException.class, () -> taskUpdater.startWork()); + RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.startWork()); assertEquals("Cannot update task status - terminal state already reached", exception.getMessage()); // Verify no additional events were queued @@ -354,11 +354,11 @@ public void testTerminalStateProtectionAfterComplete() throws Exception { @Test public void testTerminalStateProtectionAfterFail() throws Exception { // Fail the task first - taskUpdater.fail(); + agentEmitter.fail(); checkTaskStatusUpdateEventOnQueue(true, TaskState.FAILED, null); // Try to update status again - should throw RuntimeException - RuntimeException exception = assertThrows(RuntimeException.class, () -> taskUpdater.complete()); + RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.complete()); assertEquals("Cannot update task status - terminal state already reached", exception.getMessage()); // Verify no additional events were queued @@ -368,11 +368,11 @@ public void testTerminalStateProtectionAfterFail() throws Exception { @Test public void testTerminalStateProtectionAfterReject() throws Exception { // Reject the task first - taskUpdater.reject(); + agentEmitter.reject(); checkTaskStatusUpdateEventOnQueue(true, TaskState.REJECTED, null); // Try to update status again - should throw RuntimeException - RuntimeException exception = assertThrows(RuntimeException.class, () -> taskUpdater.startWork()); + RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.startWork()); assertEquals("Cannot update task status - terminal state already reached", exception.getMessage()); // Verify no additional events were queued @@ -382,11 +382,11 @@ public void testTerminalStateProtectionAfterReject() throws Exception { @Test public void testTerminalStateProtectionAfterCancel() throws Exception { // Cancel the task first - taskUpdater.cancel(); + agentEmitter.cancel(); checkTaskStatusUpdateEventOnQueue(true, TaskState.CANCELED, null); // Try to update status again - should throw RuntimeException - RuntimeException exception = assertThrows(RuntimeException.class, () -> taskUpdater.submit()); + RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.submit()); assertEquals("Cannot update task status - terminal state already reached", exception.getMessage()); // Verify no additional events were queued @@ -398,7 +398,7 @@ public void testConcurrentCompletionAttempts() throws Exception { // This test simulates race condition between multiple completion attempts Thread thread1 = new Thread(() -> { try { - taskUpdater.complete(); + agentEmitter.complete(); } catch (RuntimeException e) { // Expected for one of the threads } @@ -406,7 +406,7 @@ public void testConcurrentCompletionAttempts() throws Exception { Thread thread2 = new Thread(() -> { try { - taskUpdater.fail(); + agentEmitter.fail(); } catch (RuntimeException e) { // Expected for one of the threads } 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 848ced9ec..9d16a86ea 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java @@ -1,20 +1,20 @@ package io.a2a.tck.server; +import java.util.List; + import jakarta.annotation.PreDestroy; 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.server.tasks.AgentEmitter; import io.a2a.spec.A2AError; import io.a2a.spec.Task; import io.a2a.spec.TaskNotCancelableError; import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; -import java.util.List; @ApplicationScoped public class AgentExecutorProducer { @@ -27,7 +27,7 @@ public AgentExecutor agentExecutor() { private static class FireAndForgetAgentExecutor implements AgentExecutor { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { Task task = context.getTask(); if (task == null) { @@ -46,7 +46,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr .status(new TaskStatus(TaskState.SUBMITTED)) .history(List.of(context.getMessage())) .build(); - eventQueue.enqueueEvent(task); + agentEmitter.addTask(task); } // Sleep to allow task state persistence before TCK subscribe test @@ -59,10 +59,9 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr Thread.currentThread().interrupt(); } } - TaskUpdater updater = new TaskUpdater(context, eventQueue); // Immediately set to WORKING state - updater.startWork(); + agentEmitter.startWork(); System.out.println("====> task set to WORKING, starting background execution"); // Method returns immediately - task continues in background @@ -70,7 +69,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { System.out.println("====> task cancel request received"); Task task = context.getTask(); if (task == null) { @@ -87,15 +86,7 @@ public void cancel(RequestContext context, EventQueue eventQueue) throws A2AErro throw new TaskNotCancelableError(); } - TaskUpdater updater = new TaskUpdater(context, eventQueue); - updater.cancel(); - eventQueue.enqueueEvent(new TaskStatusUpdateEvent( - task.id(), - new TaskStatus(TaskState.CANCELED), - task.contextId(), - true, // isFinal - TaskState.CANCELED is a final state - null)); - + agentEmitter.cancel(); System.out.println("====> task canceled"); } 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 364d2275f..40839e7fb 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 @@ -7,8 +7,7 @@ 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.server.tasks.AgentEmitter; import io.a2a.spec.A2AError; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.Message; @@ -25,23 +24,22 @@ public class AgentExecutorProducer { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { - TaskUpdater updater = new TaskUpdater(context, eventQueue); + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { String taskId = context.getTaskId(); // Special handling for multi-event test if (taskId != null && taskId.startsWith("multi-event-test")) { // First call: context.getTask() == null (new task) if (context.getTask() == null) { - updater.startWork(); + agentEmitter.startWork(); // Return immediately - queue stays open because task is in WORKING state return; } else { // Second call: context.getTask() != null (existing task) - updater.addArtifact( + agentEmitter.addArtifact( List.of(new TextPart("Second message artifact")), "artifact-2", "Second Artifact", null); - updater.complete(); + agentEmitter.complete(); return; } } @@ -50,8 +48,8 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr if (taskId != null && taskId.startsWith("input-required-test")) { // First call: context.getTask() == null (new task) if (context.getTask() == null) { - updater.startWork(); - updater.requiresInput(updater.newAgentMessage( + agentEmitter.startWork(); + agentEmitter.requiresInput(agentEmitter.newAgentMessage( List.of(new TextPart("Please provide additional information")), context.getMessage().metadata())); // Return immediately - queue stays open because task is in INPUT_REQUIRED state @@ -62,23 +60,26 @@ public void execute(RequestContext context, EventQueue eventQueue) throws A2AErr throw new InvalidParamsError("We didn't get the expected input"); } // Second call: context.getTask() != null (input provided) - updater.startWork(); - updater.complete(); + agentEmitter.startWork(); + agentEmitter.complete(); return; } } if (context.getTaskId().equals("task-not-supported-123")) { - eventQueue.enqueueEvent(new UnsupportedOperationError()); + throw new UnsupportedOperationError(); + } + if (context.getMessage() != null) { + agentEmitter.sendMessage(context.getMessage()); + } else { + agentEmitter.addTask(context.getTask()); } - eventQueue.enqueueEvent(context.getMessage() != null ? context.getMessage() : context.getTask()); } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { if (context.getTask().id().equals("cancel-task-123")) { - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); - taskUpdater.cancel(); + agentEmitter.cancel(); } else if (context.getTask().id().equals("cancel-task-not-supported-123")) { throw new UnsupportedOperationError(); } 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 350e8b99a..80d7d7f39 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 @@ -23,7 +23,7 @@ import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; import io.a2a.server.requesthandlers.DefaultRequestHandler; import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.tasks.TaskUpdater; +import io.a2a.server.tasks.AgentEmitter; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentExtension; @@ -36,7 +36,6 @@ import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; - import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.internal.testing.StreamRecorder; @@ -102,13 +101,12 @@ public void testOnCancelTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorCancel = (context, eventQueue) -> { + agentExecutorCancel = (context, agentEmitter) -> { // We need to cancel the task or the EventConsumer never finds a 'final' event. // Looking at the Python implementation, they typically use AgentExecutors that // don't support cancellation. So my theory is the Agent updates the task to the CANCEL status io.a2a.spec.Task task = context.getTask(); - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); - taskUpdater.cancel(); + agentEmitter.cancel(); }; CancelTaskRequest request = CancelTaskRequest.newBuilder() @@ -133,7 +131,7 @@ public void testOnCancelTaskNotSupported() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorCancel = (context, eventQueue) -> { + agentExecutorCancel = (context, agentEmitter) -> { throw new UnsupportedOperationError(); }; @@ -163,8 +161,8 @@ public void testOnCancelTaskNotFound() throws Exception { @Test public void testOnMessageNewMessageSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; StreamRecorder streamRecorder = sendMessageRequest(handler); @@ -180,8 +178,8 @@ public void testOnMessageNewMessageSuccess() throws Exception { public void testOnMessageNewMessageWithExistingTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; StreamRecorder streamRecorder = sendMessageRequest(handler); Assertions.assertNull(streamRecorder.getError()); @@ -195,8 +193,8 @@ public void testOnMessageNewMessageWithExistingTaskSuccess() throws Exception { @Test public void testOnMessageError() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(new UnsupportedOperationError()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.fail(new UnsupportedOperationError()); }; StreamRecorder streamRecorder = sendMessageRequest(handler); assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); @@ -225,8 +223,8 @@ public void testSetPushNotificationConfigSuccess() throws Exception { @Test public void testGetPushNotificationConfigSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; // first set the task push notification config @@ -284,8 +282,8 @@ public void testOnSetPushNotificationNoPushNotifierConfig() throws Exception { @Test public void testOnMessageStreamNewMessageSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); @@ -302,8 +300,8 @@ public void testOnMessageStreamNewMessageSuccess() throws Exception { @Test public void testOnMessageStreamNewMessageExistingTaskSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; io.a2a.spec.Task task = io.a2a.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) @@ -426,10 +424,10 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.COMPLETED)) .build()); - agentExecutorExecute = (context, eventQueue) -> { + agentExecutorExecute = (context, agentEmitter) -> { // Hardcode the events to send here for (Event event : events) { - eventQueue.enqueueEvent(event); + agentEmitter.emitEvent(event); } }; @@ -508,8 +506,8 @@ public void testOnSubscribeExistingTaskSuccess() throws Exception { taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); queueManager.createOrTap(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; StreamRecorder streamRecorder = StreamRecorder.create(); @@ -626,8 +624,8 @@ public void testOnMessageStreamInternalError() throws Exception { public void testListPushNotificationConfig() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; StreamRecorder pushRecorder = createTaskPushNotificationConfigRequest(handler, @@ -652,8 +650,8 @@ public void testListPushNotificationConfigNotSupported() throws Exception { AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() @@ -669,8 +667,8 @@ public void testListPushNotificationConfigNoPushConfigStore() { DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() @@ -684,8 +682,8 @@ public void testListPushNotificationConfigNoPushConfigStore() { @Test public void testListPushNotificationConfigTaskNotFound() { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() @@ -700,8 +698,8 @@ public void testListPushNotificationConfigTaskNotFound() { public void testDeletePushNotificationConfig() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; StreamRecorder pushRecorder = createTaskPushNotificationConfigRequest(handler, AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); @@ -723,8 +721,8 @@ public void testDeletePushNotificationConfigNotSupported() throws Exception { AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; DeleteTaskPushNotificationConfigRequest request = DeleteTaskPushNotificationConfigRequest.newBuilder() .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) @@ -762,15 +760,14 @@ public void testStreamingDoesNotBlockMainThread() throws Exception { CountDownLatch streamStarted = new CountDownLatch(1); GrpcHandler.setStreamingSubscribedRunnable(streamStarted::countDown); CountDownLatch eventProcessed = new CountDownLatch(1); - - agentExecutorExecute = (context, eventQueue) -> { + agentExecutorExecute = (context, agentEmitter) -> { // Wait a bit to ensure the main thread continues try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - eventQueue.enqueueEvent(context.getMessage()); + agentEmitter.sendMessage(context.getMessage()); }; // Start streaming with a custom StreamObserver @@ -928,8 +925,8 @@ public ServerCallContext create(StreamObserver streamObserver) { } }; - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; SendMessageRequest request = SendMessageRequest.newBuilder() @@ -1069,8 +1066,8 @@ public ServerCallContext create(StreamObserver streamObserver) { } }; - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; SendMessageRequest request = SendMessageRequest.newBuilder() @@ -1120,8 +1117,8 @@ public ServerCallContext create(StreamObserver streamObserver) { } }; - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; SendMessageRequest request = SendMessageRequest.newBuilder() 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 a97883e5a..ea58beba4 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 @@ -22,6 +22,8 @@ import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; +import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; @@ -39,8 +41,6 @@ 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.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; @@ -48,7 +48,6 @@ import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; import io.a2a.server.requesthandlers.DefaultRequestHandler; import io.a2a.server.tasks.ResultAggregator; -import io.a2a.server.tasks.TaskUpdater; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentExtension; @@ -119,13 +118,12 @@ public void testOnCancelTaskSuccess() throws Exception { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorCancel = (context, eventQueue) -> { + agentExecutorCancel = (context, agentEmitter) -> { // We need to cancel the task or the EventConsumer never finds a 'final' event. // Looking at the Python implementation, they typically use AgentExecutors that // don't support cancellation. So my theory is the Agent updates the task to the CANCEL status Task task = context.getTask(); - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); - taskUpdater.cancel(); + agentEmitter.cancel(); }; CancelTaskRequest request = new CancelTaskRequest("111", new TaskIdParams(MINIMAL_TASK.id())); @@ -144,7 +142,7 @@ public void testOnCancelTaskNotSupported() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorCancel = (context, eventQueue) -> { + agentExecutorCancel = (context, agentEmitter) -> { throw new UnsupportedOperationError(); }; @@ -168,8 +166,8 @@ public void testOnCancelTaskNotFound() { @Test public void testOnMessageNewMessageSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; Message message = Message.builder(MESSAGE) .taskId(MINIMAL_TASK.id()) @@ -185,8 +183,8 @@ public void testOnMessageNewMessageSuccess() { public void testOnMessageNewMessageWithExistingTaskSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; Message message = Message.builder(MESSAGE) .taskId(MINIMAL_TASK.id()) @@ -203,8 +201,8 @@ public void testOnMessageError() { // See testMessageOnErrorMocks() for a test more similar to the Python implementation, using mocks for // EventConsumer.consumeAll() JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(new UnsupportedOperationError()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.fail(new UnsupportedOperationError()); }; Message message = Message.builder(MESSAGE) .taskId(MINIMAL_TASK.id()) @@ -242,8 +240,8 @@ public void testOnMessageErrorMocks() { @Test public void testOnMessageStreamNewMessageSuccess() throws InterruptedException { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; Message message = Message.builder(MESSAGE) @@ -323,13 +321,13 @@ public void testOnMessageStreamNewMessageMultipleEventsSuccess() throws Interrup .build(); // Configure the agent executor to enqueue multiple events - agentExecutorExecute = (context, eventQueue) -> { + agentExecutorExecute = (context, agentEmitter) -> { // Enqueue the task with WORKING state - eventQueue.enqueueEvent(taskEvent); + agentEmitter.emitEvent(taskEvent); // Enqueue an artifact update event - eventQueue.enqueueEvent(artifactEvent); + agentEmitter.emitEvent(artifactEvent); // Enqueue a status update event to complete the task (this is the "final" event) - eventQueue.enqueueEvent(statusEvent); + agentEmitter.emitEvent(statusEvent); }; Message message = Message.builder(MESSAGE) @@ -490,8 +488,8 @@ public void onComplete() { @Test public void testOnMessageStreamNewMessageExistingTaskSuccess() throws Exception { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; Task task = Task.builder(MINIMAL_TASK) @@ -664,8 +662,8 @@ public void testSetPushNotificationConfigSuccess() { public void testGetPushNotificationConfigSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; TaskPushNotificationConfig taskPushConfig @@ -716,10 +714,11 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex .status(new TaskStatus(TaskState.COMPLETED)) .build()); - agentExecutorExecute = (context, eventQueue) -> { + + agentExecutorExecute = (context, agentEmitter) -> { // Hardcode the events to send here for (Event event : events) { - eventQueue.enqueueEvent(event); + agentEmitter.emitEvent(event); } }; @@ -811,10 +810,10 @@ public void testOnSubscribeExistingTaskSuccess() { taskStore.save(MINIMAL_TASK, false); queueManager.createOrTap(MINIMAL_TASK.id()); - agentExecutorExecute = (context, eventQueue) -> { + agentExecutorExecute = (context, agentEmitter) -> { // The only thing hitting the agent is the onMessageSend() and we should use the message - eventQueue.enqueueEvent(context.getMessage()); - //eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentEmitter.sendMessage(context.getMessage()); + //agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); @@ -1267,8 +1266,8 @@ public void testOnMessageSendTaskIdMismatch() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = ((context, eventQueue) -> { - eventQueue.enqueueEvent(MINIMAL_TASK); + agentExecutorExecute = ((context, agentEmitter) -> { + agentEmitter.emitEvent(MINIMAL_TASK); }); SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(MESSAGE, null, null)); @@ -1283,8 +1282,8 @@ public void testOnMessageStreamTaskIdMismatch() throws InterruptedException { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = ((context, eventQueue) -> { - eventQueue.enqueueEvent(MINIMAL_TASK); + agentExecutorExecute = ((context, agentEmitter) -> { + agentEmitter.emitEvent(MINIMAL_TASK); }); SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, null, null)); @@ -1334,8 +1333,8 @@ public void onComplete() { public void testListPushNotificationConfig() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; TaskPushNotificationConfig taskPushConfig @@ -1365,8 +1364,8 @@ public void testListPushNotificationConfigNotSupported() { AgentCard card = createAgentCard(true, false); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; TaskPushNotificationConfig taskPushConfig @@ -1393,8 +1392,8 @@ public void testListPushNotificationConfigNoPushConfigStore() { DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; ListTaskPushNotificationConfigRequest listRequest @@ -1410,8 +1409,8 @@ public void testListPushNotificationConfigNoPushConfigStore() { @Test public void testListPushNotificationConfigTaskNotFound() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; ListTaskPushNotificationConfigRequest listRequest @@ -1428,8 +1427,8 @@ public void testListPushNotificationConfigTaskNotFound() { public void testDeletePushNotificationConfig() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; TaskPushNotificationConfig taskPushConfig @@ -1456,8 +1455,8 @@ public void testDeletePushNotificationConfigNotSupported() { AgentCard card = createAgentCard(true, false); JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; TaskPushNotificationConfig taskPushConfig @@ -1485,8 +1484,8 @@ public void testDeletePushNotificationConfigNoPushConfigStore() { DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; TaskPushNotificationConfig taskPushConfig @@ -1528,14 +1527,14 @@ public void testStreamingDoesNotBlockMainThread() throws Exception { CountDownLatch streamStarted = new CountDownLatch(1); CountDownLatch eventProcessed = new CountDownLatch(1); - agentExecutorExecute = (context, eventQueue) -> { + agentExecutorExecute = (context, agentEmitter) -> { // Wait a bit to ensure the main thread continues try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - eventQueue.enqueueEvent(context.getMessage()); + agentEmitter.sendMessage(context.getMessage()); }; Message message = Message.builder(MESSAGE) @@ -1736,8 +1735,8 @@ public void testRequiredExtensionProvidedSuccess() { requestedExtensions ); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; Message message = Message.builder(MESSAGE) @@ -1894,8 +1893,8 @@ public void testCompatibleVersionSuccess() { "1.1" // Compatible version (same major version) ); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; Message message = Message.builder(MESSAGE) @@ -1930,8 +1929,8 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { JSONRPCHandler handler = new JSONRPCHandler(agentCard, requestHandler, internalExecutor); // Use default callContext (no version - should default to 1.0) - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; Message message = Message.builder(MESSAGE) 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 2d1c19b84..b0dc58141 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 @@ -15,7 +15,7 @@ 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.server.tasks.AgentEmitter; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentExtension; @@ -87,8 +87,8 @@ public void testListTasksInvalidStatus() { @Test public void testSendMessage() throws InvalidProtocolBufferException { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; String requestBody = """ { @@ -167,13 +167,12 @@ public void testCancelTaskSuccess() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - agentExecutorCancel = (context, eventQueue) -> { + agentExecutorCancel = (context, agentEmitter) -> { // We need to cancel the task or the EventConsumer never finds a 'final' event. // Looking at the Python implementation, they typically use AgentExecutors that // don't support cancellation. So my theory is the Agent updates the task to the CANCEL status Task task = context.getTask(); - TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); - taskUpdater.cancel(); + agentEmitter.cancel(); }; RestHandler.HTTPRestResponse response = handler.cancelTask(MINIMAL_TASK.id(), "", callContext); @@ -197,8 +196,8 @@ public void testCancelTaskNotFound() { @Test public void testSendStreamingMessageSuccess() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; String requestBody = """ { @@ -357,14 +356,14 @@ public void testStreamingDoesNotBlockMainThread() throws Exception { AtomicBoolean eventReceived = new AtomicBoolean(false); CountDownLatch streamStarted = new CountDownLatch(1); CountDownLatch eventProcessed = new CountDownLatch(1); - agentExecutorExecute = (context, eventQueue) -> { + agentExecutorExecute = (context, agentEmitter) -> { // Wait a bit to ensure the main thread continues try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - eventQueue.enqueueEvent(context.getMessage()); + agentEmitter.sendMessage(context.getMessage()); }; String requestBody = """ @@ -602,8 +601,8 @@ public void testRequiredExtensionProvidedSuccess() { requestedExtensions ); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; String requestBody = """ @@ -796,8 +795,8 @@ public void testCompatibleVersionSuccess() { "1.1" // Compatible version (same major version) ); - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; String requestBody = """ @@ -844,8 +843,8 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); // Use default callContext (no version - should default to 1.0) - agentExecutorExecute = (context, eventQueue) -> { - eventQueue.enqueueEvent(context.getMessage()); + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.sendMessage(context.getMessage()); }; String requestBody = """ From b9bdf15415cd38fadb988d855939a2a55e0b8fe7 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Wed, 11 Feb 2026 11:00:54 +0100 Subject: [PATCH 025/192] fix: ListTask's statusTimestampAfter only accept ISO 8601 format (#640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #639 🦕 Signed-off-by: Jeff Mesnil --- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 2 +- .../io/a2a/grpc/utils/JSONRPCUtilsTest.java | 37 +++++++++++++++++++ .../transport/rest/handler/RestHandler.java | 25 +++---------- .../rest/handler/RestHandlerTest.java | 10 ++--- 4 files changed, 47 insertions(+), 27 deletions(-) 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 3ac66bfa8..2038b4773 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 @@ -489,7 +489,7 @@ private static JsonProcessingException convertProtoBufExceptionToJsonProcessingE } // Extract field name if present in error message - check common prefixes - String[] prefixes = {"Cannot find field: ", "Invalid value for", "Invalid enum value:"}; + String[] prefixes = {"Cannot find field: ", "Invalid value for", "Invalid enum value:", "Failed to parse"}; for (String prefix : prefixes) { if (message.contains(prefix)) { return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(message.substring(message.indexOf(prefix) + prefix.length())), id); 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 f10692424..e5f75c78a 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 @@ -7,6 +7,7 @@ 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 static org.junit.jupiter.api.Assertions.fail; import com.google.gson.JsonSyntaxException; import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; @@ -143,6 +144,42 @@ public void testParseInvalidProtoStructure_ThrowsInvalidParamsJsonMappingExcepti assertEquals(ERROR_MESSAGE.formatted("invalid_field in message a2a.v1.CreateTaskPushNotificationConfigRequest"), exception.getMessage()); } + @Test + public void testParseNumericalTimestampThrowsInvalidParamsJsonMappingException() { + String valideRequest = """ + { + "jsonrpc": "2.0", + "method": "ListTasks", + "id": "1", + "params": { + "statusTimestampAfter": "2023-10-27T10:00:00Z" + } + } + """; + String invalidRequest = """ + { + "jsonrpc": "2.0", + "method": "ListTasks", + "id": "2", + "params": { + "statusTimestampAfter": "1" + } + } + """; + + try { + A2ARequest request = JSONRPCUtils.parseRequestBody(valideRequest, null); + assertEquals(1, request.getId()); + } catch (JsonProcessingException e) { + fail(e); + } + InvalidParamsJsonMappingException exception = assertThrows( + InvalidParamsJsonMappingException.class, + () -> JSONRPCUtils.parseRequestBody(invalidRequest, null) + ); + assertEquals(2, exception.getId()); + } + @Test public void testParseMissingField_ThrowsInvalidParamsError() throws JsonMappingException { String missingRoleMessage= """ 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 ada8e8170..609c4e0a9 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 @@ -268,25 +268,12 @@ public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String s paramsBuilder.tenant(tenant); if (statusTimestampAfter != null) { try { - // Try parsing as Unix milliseconds first (integer) - long millis = Long.parseLong(statusTimestampAfter); - if (millis < 0L) { - Map errorData = new HashMap<>(); - errorData.put("parameter", "statusTimestampAfter"); - errorData.put("reason", "Must be a non-negative timestamp value, got: " + millis); - throw new InvalidParamsError(null, "Invalid params", errorData); - } - paramsBuilder.statusTimestampAfter(Instant.ofEpochMilli(millis)); - } catch (NumberFormatException nfe) { - // Fall back to ISO-8601 format - try { - paramsBuilder.statusTimestampAfter(Instant.parse(statusTimestampAfter)); - } catch (DateTimeParseException e) { - Map errorData = new HashMap<>(); - errorData.put("parameter", "lastUpdatedAfter"); - errorData.put("reason", "Must be valid Unix milliseconds or ISO-8601 timestamp"); - throw new InvalidParamsError(null, "Invalid params", errorData); - } + paramsBuilder.statusTimestampAfter(Instant.parse(statusTimestampAfter)); + } catch (DateTimeParseException e) { + Map errorData = new HashMap<>(); + errorData.put("parameter", "statusTimestampAfter"); + errorData.put("reason", "Must be an ISO-8601 timestamp"); + throw new InvalidParamsError(null, "Invalid params", errorData); } } if (includeArtifacts != null) { 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 b0dc58141..a151f1288 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 @@ -887,16 +887,12 @@ public void testListTasksNegativeTimestampReturns422() { @Test public void testListTasksUnixMillisecondsTimestamp() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - // Unix milliseconds timestamp should be accepted - String timestampMillis = String.valueOf(System.currentTimeMillis() - 10000); + // Unix milliseconds timestamp are no longer accepted RestHandler.HTTPRestResponse response = handler.listTasks(null, null, null, null, - null, timestampMillis, null, "", callContext); + null, "1234567", null, "", callContext); - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("tasks")); + Assertions.assertEquals(422, response.getStatusCode()); } @Test From 1ad2dc103ac055f9a49437a83ff97a0093e8854f Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 11 Feb 2026 12:22:11 +0100 Subject: [PATCH 026/192] chore: Migrate spec module to JSpecify annotations for null-safety (#638) - Add @NullMarked to io.a2a.spec package - Apply @Nullable annotations to optional fields and parameters - Move builder validation to build() methods using Assert.checkNotNullParam() - Fix null-safety issues in RequestContext ID generation - Add null checks for push notification configuration - Simplify REST route handling for push notification configs - Update tests to provide required MessageSendConfiguration Signed-off-by: Emmanuel Hugonnet --- common/src/main/java/io/a2a/util/Assert.java | 17 ++-- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 4 +- .../server/rest/quarkus/A2AServerRoutes.java | 25 +----- .../server/agentexecution/RequestContext.java | 30 +++---- .../DefaultRequestHandler.java | 4 +- .../io/a2a/server/tasks/AgentEmitter.java | 9 ++- .../tasks/BasePushNotificationSender.java | 11 ++- .../InMemoryPushNotificationConfigStore.java | 2 +- .../agentexecution/RequestContextTest.java | 38 +++++---- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 4 +- spec/src/main/java/io/a2a/spec/A2AError.java | 13 ++- .../java/io/a2a/spec/A2AProtocolError.java | 8 +- .../io/a2a/spec/APIKeySecurityScheme.java | 39 +++++---- .../java/io/a2a/spec/AgentCapabilities.java | 5 +- spec/src/main/java/io/a2a/spec/AgentCard.java | 79 +++++++++++-------- .../java/io/a2a/spec/AgentCardSignature.java | 14 ++-- .../main/java/io/a2a/spec/AgentExtension.java | 11 +-- .../src/main/java/io/a2a/spec/AgentSkill.java | 33 +++++--- spec/src/main/java/io/a2a/spec/Artifact.java | 27 ++++--- .../spec/ContentTypeNotSupportedError.java | 4 +- spec/src/main/java/io/a2a/spec/DataPart.java | 6 +- ...eleteTaskPushNotificationConfigParams.java | 12 ++- .../ExtendedAgentCardNotConfiguredError.java | 7 +- .../spec/ExtensionSupportRequiredError.java | 7 +- .../GetTaskPushNotificationConfigParams.java | 12 ++- .../io/a2a/spec/HTTPAuthSecurityScheme.java | 15 ++-- .../main/java/io/a2a/spec/InternalError.java | 6 +- .../a2a/spec/InvalidAgentResponseError.java | 4 +- .../java/io/a2a/spec/InvalidParamsError.java | 6 +- .../java/io/a2a/spec/InvalidRequestError.java | 4 +- .../main/java/io/a2a/spec/JSONParseError.java | 7 +- .../java/io/a2a/spec/ListTasksParams.java | 24 +++--- spec/src/main/java/io/a2a/spec/Message.java | 38 +++++---- .../io/a2a/spec/MessageSendConfiguration.java | 16 ++-- .../java/io/a2a/spec/MessageSendParams.java | 25 +++--- .../java/io/a2a/spec/MethodNotFoundError.java | 7 +- .../io/a2a/spec/OAuth2SecurityScheme.java | 17 ++-- .../src/main/java/io/a2a/spec/OAuthFlows.java | 12 +-- .../a2a/spec/OpenIdConnectSecurityScheme.java | 12 ++- .../io/a2a/spec/PushNotificationConfig.java | 13 +-- .../PushNotificationNotSupportedError.java | 7 +- spec/src/main/java/io/a2a/spec/Task.java | 35 ++++---- .../io/a2a/spec/TaskArtifactUpdateEvent.java | 35 ++++---- .../io/a2a/spec/TaskNotCancelableError.java | 7 +- .../java/io/a2a/spec/TaskNotFoundError.java | 7 +- .../src/main/java/io/a2a/spec/TaskStatus.java | 31 +++----- .../io/a2a/spec/TaskStatusUpdateEvent.java | 26 +++--- .../a2a/spec/UnsupportedOperationError.java | 7 +- .../io/a2a/spec/VersionNotSupportedError.java | 7 +- .../main/java/io/a2a/spec/package-info.java | 8 ++ .../jsonrpc/handler/JSONRPCHandlerTest.java | 17 +++- .../transport/rest/handler/RestHandler.java | 2 +- 52 files changed, 442 insertions(+), 374 deletions(-) create mode 100644 spec/src/main/java/io/a2a/spec/package-info.java diff --git a/common/src/main/java/io/a2a/util/Assert.java b/common/src/main/java/io/a2a/util/Assert.java index b0077cd23..0c375a36b 100644 --- a/common/src/main/java/io/a2a/util/Assert.java +++ b/common/src/main/java/io/a2a/util/Assert.java @@ -1,5 +1,7 @@ package io.a2a.util; +import org.jspecify.annotations.Nullable; + public final class Assert { /** @@ -11,18 +13,21 @@ public final class Assert { * @return the value that was passed in * @throws IllegalArgumentException if the value is {@code null} */ - @NotNull - public static T checkNotNullParam(String name, T value) throws IllegalArgumentException { + public static @NotNull T checkNotNullParam(String name, @Nullable T value) throws IllegalArgumentException { checkNotNullParamChecked("name", name); - checkNotNullParamChecked(name, value); + if (value == null) { + throw new IllegalArgumentException("Parameter '" + name + "' may not be null"); + } return value; } - private static void checkNotNullParamChecked(final String name, final T value) { - if (value == null) throw new IllegalArgumentException("Parameter '" + name + "' may not be null"); + private static void checkNotNullParamChecked(final String name, final @Nullable T value) { + if (value == null) { + throw new IllegalArgumentException("Parameter '" + name + "' may not be null"); + } } - public static void isNullOrStringOrInteger(Object value) { + public static void isNullOrStringOrInteger(@Nullable Object value) { if (! (value == null || value instanceof String || value instanceof Integer)) { throw new IllegalArgumentException("Id must be null, a String, or an Integer"); } diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index 77452f93e..89fc2d392 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -22,7 +22,6 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; -import java.util.Map; import java.util.Set; import com.google.gson.Gson; @@ -30,7 +29,6 @@ import com.google.gson.JsonSyntaxException; import com.google.gson.ToNumberPolicy; import com.google.gson.TypeAdapter; -import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; @@ -435,7 +433,7 @@ private A2AError createErrorInstance(@Nullable Integer code, @Nullable String me case INVALID_AGENT_RESPONSE_ERROR_CODE -> new InvalidAgentResponseError(code, message, data); default -> - new A2AError(code, message, data); + new A2AError(code, message == null ? "" : message, data); }; } } 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 a41f2d361..c8dc54086 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 @@ -289,7 +289,9 @@ public void getTaskPushNotificationConfiguration(RoutingContext rc) { try { if (taskId == null || taskId.isEmpty()) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else { + } else if (configId == null || configId.isEmpty()) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad configuration id")); + }else { response = jsonRestHandler.getTaskPushNotificationConfiguration(taskId, configId, extractTenant(rc), context); } } catch (Throwable t) { @@ -299,26 +301,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, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - HTTPRestResponse response = null; - try { - if (taskId == null || taskId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else { - // Call get with null configId - trailing slash distinguishes this from list - response = jsonRestHandler.getTaskPushNotificationConfiguration(taskId, null, extractTenant(rc), context); - } - } catch (Throwable t) { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } finally { - sendResponse(rc, response); - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs", order = 3, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) + @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, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); 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 82a8b9e17..c82df7846 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 @@ -99,14 +99,12 @@ public RequestContext( if (params != null) { if (taskId != null && !taskId.equals(params.message().taskId())) { throw new InvalidParamsError("bad task id"); - } else { - checkOrGenerateTaskId(); } + this.taskId = checkOrGenerateTaskId(); if (contextId != null && !contextId.equals(params.message().contextId())) { throw new InvalidParamsError("bad context id"); - } else { - checkOrGenerateContextId(); } + this.contextId = checkOrGenerateContextId(); } } @@ -246,9 +244,9 @@ public void attachRelatedTask(Task task) { relatedTasks.add(task); } - private void checkOrGenerateTaskId() { + private @Nullable String checkOrGenerateTaskId() { if (params == null) { - return; + return taskId; } if (taskId == null && params.message().taskId() == null) { // Message is immutable, create new one with generated taskId @@ -257,15 +255,17 @@ private void checkOrGenerateTaskId() { .taskId(generatedTaskId) .build(); params = new MessageSendParams(updatedMessage, params.configuration(), params.metadata()); - this.taskId = generatedTaskId; - } else if (params.message().taskId() != null) { - this.taskId = params.message().taskId(); + return generatedTaskId; + } + if (params.message().taskId() != null) { + return params.message().taskId(); } + return taskId; } - private void checkOrGenerateContextId() { + private @Nullable String checkOrGenerateContextId() { if (params == null) { - return; + return contextId; } if (contextId == null && params.message().contextId() == null) { // Message is immutable, create new one with generated contextId @@ -274,10 +274,12 @@ private void checkOrGenerateContextId() { .contextId(generatedContextId) .build(); params = new MessageSendParams(updatedMessage, params.configuration(), params.metadata()); - this.contextId = generatedContextId; - } else if (params.message().contextId() != null) { - this.contextId = params.message().contextId(); + return generatedContextId; + } + if (params.message().contextId() != null) { + return params.message().contextId(); } + return contextId; } private String getMessageText(Message message, String delimiter) { 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 974482ce2..0319718ea 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 @@ -422,6 +422,7 @@ public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws } @Override + @SuppressWarnings("NullAway") public EventKind onMessageSend(MessageSendParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onMessageSend - task: {}; context {}", params.message().taskId(), params.message().contextId()); @@ -605,6 +606,7 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte } @Override + @SuppressWarnings("NullAway") public Flow.Publisher onMessageSendStream( MessageSendParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onMessageSendStream START - task: {}; context: {}; runningAgents: {}", @@ -1014,7 +1016,7 @@ private MessageSendSetup initMessageSend(MessageSendParams params, ServerCallCon LOGGER.debug("Found task updating with message {}", params.message()); task = taskManager.updateWithMessage(params.message(), task); - if (shouldAddPushInfo(params)) { + if (pushConfigStore != null && params.configuration() != null && params.configuration().pushNotificationConfig() != null) { LOGGER.debug("Adding push info"); pushConfigStore.setInfo(task.id(), params.configuration().pushNotificationConfig()); } diff --git a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java index 57ff6372c..7c6c97f20 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java +++ b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java @@ -18,6 +18,7 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; +import io.a2a.util.Assert; import org.jspecify.annotations.Nullable; /** @@ -95,8 +96,8 @@ */ public class AgentEmitter { private final EventQueue eventQueue; - private final @Nullable String taskId; - private final @Nullable String contextId; + private final String taskId; + private final String contextId; private final AtomicBoolean terminalStateReached = new AtomicBoolean(false); /** @@ -107,8 +108,8 @@ public class AgentEmitter { */ public AgentEmitter(RequestContext context, EventQueue eventQueue) { this.eventQueue = eventQueue; - this.taskId = context.getTaskId(); - this.contextId = context.getContextId(); + this.taskId = Assert.checkNotNullParam("taskId",context.getTaskId()); + this.contextId = Assert.checkNotNullParam("contextId",context.getContextId()); } private void updateStatus(TaskState taskState) { 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 58c03369d..a9b8093bf 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 @@ -78,7 +78,7 @@ public void sendNotification(StreamingEventKind event) { String nextPageToken = null; do { ListTaskPushNotificationConfigResult pageResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId, - DEFAULT_PAGE_SIZE, nextPageToken, "")); + DEFAULT_PAGE_SIZE, nextPageToken == null ? "" : nextPageToken, "")); if (!pageResult.configs().isEmpty()) { configs.addAll(pageResult.configs()); } @@ -111,11 +111,14 @@ public void sendNotification(StreamingEventKind event) { protected @Nullable String extractTaskId(StreamingEventKind event) { if (event instanceof Task task) { return task.id(); - } else if (event instanceof Message message) { + } + if (event instanceof Message message) { return message.taskId(); - } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { + } + if (event instanceof TaskStatusUpdateEvent statusUpdate) { return statusUpdate.taskId(); - } else if (event instanceof TaskArtifactUpdateEvent artifactUpdate) { + } + if (event instanceof TaskArtifactUpdateEvent artifactUpdate) { return artifactUpdate.taskId(); } throw new IllegalStateException("Unknown StreamingEventKind: " + event); 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 093ff910d..e67ae01eb 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 @@ -41,7 +41,7 @@ public PushNotificationConfig setInfo(String taskId, PushNotificationConfig noti Iterator notificationConfigIterator = notificationConfigList.iterator(); while (notificationConfigIterator.hasNext()) { PushNotificationConfig config = notificationConfigIterator.next(); - if (config.id().equals(notificationConfig.id())) { + if (config.id() != null && config.id().equals(notificationConfig.id())) { notificationConfigIterator.remove(); break; } 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 433ebcac3..ba692d97c 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 @@ -15,6 +15,7 @@ import io.a2a.spec.InvalidParamsError; import io.a2a.spec.Message; +import io.a2a.spec.MessageSendConfiguration; import io.a2a.spec.MessageSendParams; import io.a2a.spec.Task; import io.a2a.spec.TaskState; @@ -25,6 +26,13 @@ public class RequestContextTest { + private static MessageSendConfiguration defaultConfiguration() { + return MessageSendConfiguration.builder() + .acceptedOutputModes(List.of()) + .blocking(false) + .build(); + } + @Test public void testInitWithoutParams() { RequestContext context = new RequestContext(null, null, null, null, null, null); @@ -38,7 +46,7 @@ public void testInitWithoutParams() { @Test public void testInitWithParamsNoIds() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); UUID taskId = UUID.fromString("00000000-0000-0000-0000-000000000001"); UUID contextId = UUID.fromString("00000000-0000-0000-0000-000000000002"); @@ -63,7 +71,7 @@ public void testInitWithParamsNoIds() { public void testInitWithTaskId() { String taskId = "task-123"; var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(taskId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, taskId, null, null, null, null); @@ -75,7 +83,7 @@ public void testInitWithTaskId() { public void testInitWithContextId() { String contextId = "context-456"; var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).contextId(contextId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, null, contextId, null, null, null); assertEquals(contextId, context.getContextId()); @@ -87,7 +95,7 @@ public void testInitWithBothIds() { String taskId = "task-123"; String contextId = "context-456"; var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(taskId).contextId(contextId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, taskId, contextId, null, null, null); assertEquals(taskId, context.getTaskId()); @@ -100,7 +108,7 @@ public void testInitWithBothIds() { public void testInitWithTask() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, null, null, mockTask, null, null); @@ -134,7 +142,7 @@ public void testAttachRelatedTask() { public void testCheckOrGenerateTaskIdWithExistingTaskId() { String existingId = "existing-task-id"; var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(existingId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, null, null, null, null, null); @@ -147,7 +155,7 @@ public void testCheckOrGenerateContextIdWithExistingContextId() { String existingId = "existing-context-id"; var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).contextId(existingId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, null, null, null, null, null); @@ -158,7 +166,7 @@ public void testCheckOrGenerateContextIdWithExistingContextId() { @Test public void testInitRaisesErrorOnTaskIdMismatch() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); InvalidParamsError error = assertThrows(InvalidParamsError.class, () -> @@ -170,7 +178,7 @@ public void testInitRaisesErrorOnTaskIdMismatch() { @Test public void testInitRaisesErrorOnContextIdMismatch() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); InvalidParamsError error = assertThrows(InvalidParamsError.class, () -> @@ -202,7 +210,7 @@ public void testMessagePropertyWithoutParams() { @Test public void testMessagePropertyWithParams() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, null, null, null, null, null); // getMessage() returns a new Message with generated IDs, not the original @@ -218,7 +226,7 @@ public void testInitWithExistingIdsInMessage() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))) .taskId(existingTaskId).contextId(existingContextId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, null, null, null, null, null); @@ -229,7 +237,7 @@ public void testInitWithExistingIdsInMessage() { @Test public void testInitWithTaskIdAndExistingTaskIdMatch() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); @@ -242,7 +250,7 @@ public void testInitWithTaskIdAndExistingTaskIdMatch() { @Test public void testInitWithContextIdAndExistingContextIdMatch() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); @@ -255,7 +263,7 @@ public void testInitWithContextIdAndExistingContextIdMatch() { @Test void testMessageBuilderGeneratesId() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, null, null, null, null, null); assertNotNull(mockMessage.messageId()); @@ -265,7 +273,7 @@ void testMessageBuilderGeneratesId() { @Test void testMessageBuilderUsesProvidedId() { var mockMessage = Message.builder().messageId("123").role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext(mockParams, null, null, null, null, null); assertEquals("123", mockMessage.messageId()); 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 2038b4773..1480ac42a 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 @@ -434,10 +434,10 @@ private static A2AError processError(JsonObject error) { case TASK_NOT_FOUND_ERROR_CODE: return new TaskNotFoundError(code, message, data); default: - return new A2AError(code, message, data); + return new A2AError(code, message == null ? "": message, data); } } - return new A2AError(code, message, data); + return new A2AError(INTERNAL_ERROR_CODE, message == null ? "": message, data); } protected static void parseRequestBody(JsonElement jsonRpc, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException { diff --git a/spec/src/main/java/io/a2a/spec/A2AError.java b/spec/src/main/java/io/a2a/spec/A2AError.java index 4bbc8917b..c81bbbe32 100644 --- a/spec/src/main/java/io/a2a/spec/A2AError.java +++ b/spec/src/main/java/io/a2a/spec/A2AError.java @@ -1,6 +1,7 @@ package io.a2a.spec; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Marker interface for A2A Protocol error events. @@ -36,7 +37,7 @@ public class A2AError extends RuntimeException implements Event { /** * Additional error information (structure defined by the error code). */ - private final Object data; + private final @Nullable Object data; /** * Constructs a JSON-RPC error with the specified code, message, and optional data. @@ -48,11 +49,9 @@ public class A2AError extends RuntimeException implements Event { * @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; + public A2AError(Integer code, String message, @Nullable Object data) { + super(Assert.checkNotNullParam("message", message)); + this.code = Assert.checkNotNullParam("code", code); this.data = data; } @@ -84,7 +83,7 @@ public Integer getCode() { * * @return the error data, or null if not provided */ - public Object getData() { + public @Nullable Object getData() { return data; } } diff --git a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java b/spec/src/main/java/io/a2a/spec/A2AProtocolError.java index e2655175d..b03ba4080 100644 --- a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java +++ b/spec/src/main/java/io/a2a/spec/A2AProtocolError.java @@ -1,5 +1,7 @@ package io.a2a.spec; +import org.jspecify.annotations.Nullable; + /** * Represents a protocol-level error in the A2A Protocol with a reference URL. *

          @@ -15,7 +17,7 @@ public class A2AProtocolError extends A2AError { /** * URL reference for additional information about this protocol error. */ - private final String url; + private final @Nullable String url; /** * Constructs a protocol error with the specified code, message, data, and reference URL. @@ -25,7 +27,7 @@ public class A2AProtocolError extends A2AError { * @param data additional error information, structure defined by the error code (optional) * @param url URL reference providing additional context about this protocol error (optional) */ - public A2AProtocolError(Integer code, String message, Object data, String url) { + public A2AProtocolError(Integer code, String message, @Nullable Object data, @Nullable String url) { super(code, message, data); this.url = url; } @@ -38,7 +40,7 @@ public A2AProtocolError(Integer code, String message, Object data, String url) { * * @return the reference URL, or null if not provided */ - public String getUrl() { + public @Nullable String getUrl() { return url; } } diff --git a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java b/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java index ffa886849..676d43835 100644 --- a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java @@ -1,6 +1,7 @@ package io.a2a.spec; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * API key security scheme for agent authentication. @@ -17,13 +18,12 @@ * @see OpenAPI Security Scheme * @see A2A Protocol Specification */ -public record APIKeySecurityScheme( - Location location, - String name, - String description -) implements SecurityScheme { +public record APIKeySecurityScheme(Location location, String name, @Nullable + String description) implements SecurityScheme { - /** The security scheme type identifier for API key authentication. */ + /** + * The security scheme type identifier for API key authentication. + */ public static final String TYPE = "apiKeySecurityScheme"; @Override @@ -48,13 +48,17 @@ public String type() { * Represents the location of the API key. */ public enum Location { - /** API key sent in a cookie. */ + /** + * API key sent in a cookie. + */ COOKIE("cookie"), - - /** API key sent in an HTTP header. */ + /** + * API key sent in an HTTP header. + */ HEADER("header"), - - /** API key sent as a query parameter. */ + /** + * API key sent as a query parameter. + */ QUERY("query"); private final String location; @@ -90,7 +94,8 @@ public static Location fromString(String location) { case "query" -> { return QUERY; } - default -> throw new IllegalArgumentException("Invalid API key location: " + location); + default -> + throw new IllegalArgumentException("Invalid API key location: " + location); } } } @@ -117,9 +122,10 @@ public static Builder builder() { * }

        */ public static class Builder { - private Location location; - private String name; - private String description; + + private @Nullable Location location; + private @Nullable String name; + private @Nullable String description; /** * Creates a new Builder with all fields unset. @@ -167,7 +173,8 @@ public Builder description(String description) { * @throws IllegalArgumentException if location or name is null */ public APIKeySecurityScheme build() { - return new APIKeySecurityScheme(location, name, description); + return new APIKeySecurityScheme(Assert.checkNotNullParam("location", location), + Assert.checkNotNullParam("name", name), description); } } } diff --git a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java index da166a4e1..e36088a42 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java +++ b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java @@ -1,6 +1,7 @@ package io.a2a.spec; import java.util.List; +import org.jspecify.annotations.Nullable; /** * Defines optional capabilities supported by an agent in the A2A Protocol. @@ -32,7 +33,7 @@ public record AgentCapabilities(boolean streaming, boolean pushNotifications, boolean extendedAgentCard, - List extensions) { + @Nullable List extensions) { /** * Create a new Builder @@ -61,7 +62,7 @@ public static class Builder { private boolean streaming; private boolean pushNotifications; private boolean extendedAgentCard; - private List extensions; + private @Nullable List extensions; /** * Creates a new Builder with all capabilities set to false by default. diff --git a/spec/src/main/java/io/a2a/spec/AgentCard.java b/spec/src/main/java/io/a2a/spec/AgentCard.java index d49dcc862..dec9ce722 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCard.java +++ b/spec/src/main/java/io/a2a/spec/AgentCard.java @@ -5,6 +5,8 @@ import java.util.Map; import io.a2a.util.Assert; +import java.util.Collections; +import org.jspecify.annotations.Nullable; /** * The AgentCard is a self-describing manifest for an agent in the A2A Protocol. @@ -43,18 +45,18 @@ public record AgentCard( String name, String description, - AgentProvider provider, + @Nullable AgentProvider provider, String version, - String documentationUrl, + @Nullable String documentationUrl, AgentCapabilities capabilities, List defaultInputModes, List defaultOutputModes, List skills, - Map securitySchemes, - List>> securityRequirements, - String iconUrl, + @Nullable Map securitySchemes, + @Nullable List>> securityRequirements, + @Nullable String iconUrl, List supportedInterfaces, - List signatures) { + @Nullable List signatures) { /** * Compact constructor that validates required fields. @@ -98,7 +100,7 @@ public static Builder builder() { /** * Create a new Builder initialized with values from an existing AgentCard. *

        - * This builder creates defensive copies of mutable collections to ensure + * This builder creates defensive copies of mutable collections to ensure * that modifications to the builder do not affect the original AgentCard. * * @param card the AgentCard to copy values from @@ -108,7 +110,6 @@ public static Builder builder(AgentCard card) { return new Builder(card); } - /** * Builder for constructing immutable {@link AgentCard} instances. *

        @@ -140,26 +141,26 @@ public static Builder builder(AgentCard card) { * } */ public static class Builder { - private String name; - private String description; - private AgentProvider provider; - private String version; - private String documentationUrl; - private AgentCapabilities capabilities; - private List defaultInputModes; - private List defaultOutputModes; - private List skills; - private Map securitySchemes; - private List>> securityRequirements; - private String iconUrl; - private List supportedInterfaces; - private List signatures; + + private @Nullable String name; + private @Nullable String description; + private @Nullable AgentProvider provider; + private @Nullable String version; + private @Nullable String documentationUrl; + private @Nullable AgentCapabilities capabilities; + private @Nullable List defaultInputModes; + private @Nullable List defaultOutputModes; + private @Nullable List skills; + private @Nullable Map securitySchemes; + private @Nullable List>> securityRequirements; + private @Nullable String iconUrl; + private @Nullable List supportedInterfaces; + private @Nullable List signatures; /** * Creates a new Builder with all fields unset. */ private Builder() { - } /** @@ -177,13 +178,13 @@ private Builder(AgentCard card) { this.version = card.version; this.documentationUrl = card.documentationUrl; this.capabilities = card.capabilities; - this.defaultInputModes = card.defaultInputModes != null ? new ArrayList<>(card.defaultInputModes) : null; - this.defaultOutputModes = card.defaultOutputModes != null ? new ArrayList<>(card.defaultOutputModes) : null; - this.skills = card.skills != null ? new ArrayList<>(card.skills) : null; - this.securitySchemes = card.securitySchemes != null ? Map.copyOf(card.securitySchemes) : null; - this.securityRequirements = card.securityRequirements != null ? new ArrayList<>(card.securityRequirements) : null; + this.defaultInputModes = card.defaultInputModes != null ? new ArrayList<>(card.defaultInputModes) : Collections.emptyList(); + this.defaultOutputModes = card.defaultOutputModes != null ? new ArrayList<>(card.defaultOutputModes) : Collections.emptyList(); + this.skills = card.skills != null ? new ArrayList<>(card.skills) : Collections.emptyList(); + this.securitySchemes = card.securitySchemes != null ? Map.copyOf(card.securitySchemes) : Collections.emptyMap(); + this.securityRequirements = card.securityRequirements != null ? new ArrayList<>(card.securityRequirements) :Collections.emptyList(); this.iconUrl = card.iconUrl; - this.supportedInterfaces = card.supportedInterfaces != null ? new ArrayList<>(card.supportedInterfaces) : null; + this.supportedInterfaces = card.supportedInterfaces != null ? new ArrayList<>(card.supportedInterfaces) : Collections.emptyList(); this.signatures = card.signatures != null ? new ArrayList<>(card.signatures) : null; } @@ -209,7 +210,6 @@ public Builder description(String description) { return this; } - /** * Sets information about the organization or entity providing the agent. * @@ -387,10 +387,21 @@ public Builder signatures(List signatures) { * @throws IllegalArgumentException if any required field is null */ public AgentCard build() { - return new AgentCard(name, description, provider, version, documentationUrl, - capabilities, defaultInputModes, defaultOutputModes, skills, - securitySchemes, securityRequirements, iconUrl, - supportedInterfaces, signatures); + return new AgentCard( + Assert.checkNotNullParam("name", name), + Assert.checkNotNullParam("description", description), + provider, + Assert.checkNotNullParam("version", version), + documentationUrl, + Assert.checkNotNullParam("capabilities", capabilities), + Assert.checkNotNullParam("defaultInputModes", defaultInputModes), + Assert.checkNotNullParam("defaultOutputModes", defaultOutputModes), + Assert.checkNotNullParam("skills", skills), + securitySchemes, + securityRequirements, + iconUrl, + Assert.checkNotNullParam("supportedInterfaces", supportedInterfaces), + signatures); } } } diff --git a/spec/src/main/java/io/a2a/spec/AgentCardSignature.java b/spec/src/main/java/io/a2a/spec/AgentCardSignature.java index cb6bc5c77..f87a9b25a 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCardSignature.java +++ b/spec/src/main/java/io/a2a/spec/AgentCardSignature.java @@ -4,6 +4,7 @@ import com.google.gson.annotations.SerializedName; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a digital signature for an {@link AgentCard} using JSON Web Signature (JWS) format. @@ -31,7 +32,7 @@ * @see RFC 7515 - JSON Web Signature * @see A2A Protocol Specification */ -public record AgentCardSignature(Map header, @SerializedName("protected")String protectedHeader, +public record AgentCardSignature(@Nullable Map header, @SerializedName("protected")String protectedHeader, String signature) { /** @@ -69,9 +70,9 @@ public static Builder builder() { * } */ public static class Builder { - private Map header; - String protectedHeader; - String signature; + private @Nullable Map header; + @Nullable String protectedHeader; + @Nullable String signature; /** * Creates a new Builder with all fields unset. @@ -122,7 +123,10 @@ public Builder signature(String signature) { * @throws IllegalArgumentException if protectedHeader or signature is null */ public AgentCardSignature build() { - return new AgentCardSignature(header, protectedHeader, signature); + return new AgentCardSignature( + header, + Assert.checkNotNullParam("protectedHeader", protectedHeader), + Assert.checkNotNullParam("signature", signature)); } } } diff --git a/spec/src/main/java/io/a2a/spec/AgentExtension.java b/spec/src/main/java/io/a2a/spec/AgentExtension.java index 7faf41d8f..de454efad 100644 --- a/spec/src/main/java/io/a2a/spec/AgentExtension.java +++ b/spec/src/main/java/io/a2a/spec/AgentExtension.java @@ -3,6 +3,7 @@ import java.util.Map; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a protocol extension supported by an agent. @@ -23,7 +24,7 @@ * @see AgentCard * @see A2A Protocol Specification */ -public record AgentExtension (String description, Map params, boolean required, String uri) { +public record AgentExtension (@Nullable String description, @Nullable Map params, boolean required, String uri) { /** * Compact constructor that validates required fields. @@ -61,10 +62,10 @@ public static Builder builder() { * } */ public static class Builder { - String description; - Map params; + @Nullable String description; + @Nullable Map params; boolean required; - String uri; + @Nullable String uri; /** * Creates a new Builder with all fields unset. @@ -123,7 +124,7 @@ public Builder uri(String uri) { * @throws IllegalArgumentException if uri is null */ public AgentExtension build() { - return new AgentExtension(description, params, required, uri); + return new AgentExtension(description, params, required, Assert.checkNotNullParam("uri", uri)); } } diff --git a/spec/src/main/java/io/a2a/spec/AgentSkill.java b/spec/src/main/java/io/a2a/spec/AgentSkill.java index 2ff217f5d..6d60baec4 100644 --- a/spec/src/main/java/io/a2a/spec/AgentSkill.java +++ b/spec/src/main/java/io/a2a/spec/AgentSkill.java @@ -4,6 +4,7 @@ import java.util.Map; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a distinct skill or capability that an agent can perform in the A2A Protocol. @@ -40,8 +41,8 @@ * @see A2A Protocol Specification */ public record AgentSkill(String id, String name, String description, List tags, - List examples, List inputModes, List outputModes, - List>> securityRequirements) { + @Nullable List examples, @Nullable List inputModes, @Nullable List outputModes, + @Nullable List>> securityRequirements) { /** * Compact constructor that validates required fields. @@ -57,9 +58,9 @@ public record AgentSkill(String id, String name, String description, List tags; - private List examples; - private List inputModes; - private List outputModes; - private List>> securityRequirements; + private @Nullable String id; + private @Nullable String name; + private @Nullable String description; + private @Nullable List tags; + private @Nullable List examples; + private @Nullable List inputModes; + private @Nullable List outputModes; + private @Nullable List>> securityRequirements; /** * Creates a new Builder with all fields unset. @@ -231,7 +232,15 @@ public Builder securityRequirements(List>> securityRequ * @throws IllegalArgumentException if any required field (id, name, description, tags) is null */ public AgentSkill build() { - return new AgentSkill(id, name, description, tags, examples, inputModes, outputModes, securityRequirements); + return new AgentSkill( + Assert.checkNotNullParam("id", id), + Assert.checkNotNullParam("name", name), + Assert.checkNotNullParam("description", description), + Assert.checkNotNullParam("tags", tags), + examples, + inputModes, + outputModes, + securityRequirements); } } } diff --git a/spec/src/main/java/io/a2a/spec/Artifact.java b/spec/src/main/java/io/a2a/spec/Artifact.java index fb05f4b00..6f9b5dc68 100644 --- a/spec/src/main/java/io/a2a/spec/Artifact.java +++ b/spec/src/main/java/io/a2a/spec/Artifact.java @@ -4,6 +4,7 @@ import java.util.Map; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a file, data structure, or other resource generated by an agent during task execution. @@ -29,8 +30,8 @@ * @param extensions protocol extensions used in this artifact (optional) * @see A2A Protocol Specification */ -public record Artifact(String artifactId, String name, String description, List> parts, Map metadata, - List extensions) { +public record Artifact(String artifactId, @Nullable String name, @Nullable String description, List> parts, @Nullable Map metadata, + @Nullable List extensions) { /** * Compact constructor that validates required fields. @@ -90,12 +91,12 @@ public static Builder builder(Artifact artifact) { * } */ public static class Builder { - private String artifactId; - private String name; - private String description; - private List> parts; - private Map metadata; - private List extensions; + private @Nullable String artifactId; + private @Nullable String name; + private @Nullable String description; + private @Nullable List> parts; + private @Nullable Map metadata; + private @Nullable List extensions; /** * Creates a new Builder with all fields unset. @@ -134,7 +135,7 @@ public Builder artifactId(String artifactId) { * @param name the artifact name (optional) * @return this builder for method chaining */ - public Builder name(String name) { + public Builder name(@Nullable String name) { this.name = name; return this; } @@ -145,7 +146,7 @@ public Builder name(String name) { * @param description the artifact description (optional) * @return this builder for method chaining */ - public Builder description(String description) { + public Builder description(@Nullable String description) { this.description = description; return this; } @@ -178,7 +179,7 @@ public Builder parts(Part... parts) { * @param metadata map of metadata key-value pairs (optional) * @return this builder for method chaining */ - public Builder metadata(Map metadata) { + public Builder metadata(@Nullable Map metadata) { this.metadata = metadata; return this; } @@ -189,7 +190,7 @@ public Builder metadata(Map metadata) { * @param extensions the list of extension identifiers (optional) * @return this builder for method chaining */ - public Builder extensions(List extensions) { + public Builder extensions(@Nullable List extensions) { this.extensions = (extensions == null) ? null : List.copyOf(extensions); return this; } @@ -201,7 +202,7 @@ public Builder extensions(List extensions) { * @throws IllegalArgumentException if required fields are missing or parts is empty */ public Artifact build() { - return new Artifact(artifactId, name, description, parts, metadata, extensions); + return new Artifact(Assert.checkNotNullParam("artifactId", artifactId), name, description, Assert.checkNotNullParam("parts", parts), metadata, extensions); } } } diff --git a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java index 812d290d2..57a88c17c 100644 --- a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating incompatibility between requested content types and agent capabilities. *

        @@ -45,7 +47,7 @@ public class ContentTypeNotSupportedError extends A2AProtocolError { * @param message the error message * @param data additional error data */ - public ContentTypeNotSupportedError(Integer code, String message, Object data) { + public ContentTypeNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super(defaultIfNull(code, CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE), defaultIfNull(message, "Incompatible content types"), data, diff --git a/spec/src/main/java/io/a2a/spec/DataPart.java b/spec/src/main/java/io/a2a/spec/DataPart.java index b358d14d9..437debd8a 100644 --- a/spec/src/main/java/io/a2a/spec/DataPart.java +++ b/spec/src/main/java/io/a2a/spec/DataPart.java @@ -1,8 +1,8 @@ package io.a2a.spec; -import java.util.Map; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** @@ -77,7 +77,7 @@ public static Builder builder() { * Builder for constructing {@link DataPart} instances. */ public static class Builder { - private Object data; + private @Nullable Object data; /** * Creates a new Builder with all fields unset. @@ -103,7 +103,7 @@ public Builder data(Object data) { * @throws IllegalArgumentException if data is null */ public DataPart build() { - return new DataPart(data); + return new DataPart(Assert.checkNotNullParam("data", data)); } } } diff --git a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java index 75faf2e54..28f438dfb 100644 --- a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java @@ -3,6 +3,7 @@ import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Parameters for deleting a push notification configuration from a task. @@ -57,9 +58,9 @@ public static Builder builder() { * Provides a fluent API for setting parameters with optional metadata. */ public static class Builder { - String id; - String pushNotificationConfigId; - String tenant; + @Nullable String id; + @Nullable String pushNotificationConfigId; + @Nullable String tenant; /** * Creates a new Builder with all fields unset. @@ -107,7 +108,10 @@ public Builder tenant(String tenant) { * @throws IllegalArgumentException if id or pushNotificationConfigId is null */ public DeleteTaskPushNotificationConfigParams build() { - return new DeleteTaskPushNotificationConfigParams(id, pushNotificationConfigId, tenant); + return new DeleteTaskPushNotificationConfigParams( + Assert.checkNotNullParam("id", id), + Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId), + Assert.checkNotNullParam("tenant", tenant)); } } } diff --git a/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java b/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java index c8998fe04..5b961e2bf 100644 --- a/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java +++ b/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating that the agent does not have an authenticated extended card configured. @@ -36,10 +38,7 @@ public class ExtendedAgentCardNotConfiguredError extends A2AProtocolError { * @param message the error message * @param data additional error data */ - public ExtendedAgentCardNotConfiguredError( - Integer code, - String message, - Object data) { + public ExtendedAgentCardNotConfiguredError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE), defaultIfNull(message, "Extended Card not configured"), diff --git a/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java b/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java index ac0ea574d..abb11aa9f 100644 --- a/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java +++ b/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED_ERROR; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating that a client requested use of an extension marked as required @@ -36,10 +38,7 @@ public class ExtensionSupportRequiredError extends A2AProtocolError { * @param message the error message (defaults to standard message if null) * @param data additional error data (optional) */ - public ExtensionSupportRequiredError( - Integer code, - String message, - Object data) { + public ExtensionSupportRequiredError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, EXTENSION_SUPPORT_REQUIRED_ERROR), defaultIfNull(message, "Extension support required but not declared"), diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java index 81537ce97..070042e40 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java @@ -3,6 +3,7 @@ import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Parameters for retrieving push notification configuration for a specific task. @@ -55,9 +56,9 @@ public static Builder builder() { * Builder for constructing GetTaskPushNotificationConfigParams instances. */ public static class Builder { - String id; - String pushNotificationConfigId; - String tenant; + @Nullable String id; + @Nullable String pushNotificationConfigId; + @Nullable String tenant; /** * Creates a new Builder with all fields unset. @@ -104,7 +105,10 @@ public Builder tenant(String tenant) { * @return a new GetTaskPushNotificationConfigParams */ public GetTaskPushNotificationConfigParams build() { - return new GetTaskPushNotificationConfigParams(id, pushNotificationConfigId, tenant == null ? "" : tenant); + return new GetTaskPushNotificationConfigParams( + Assert.checkNotNullParam("id", id), + Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId), + Assert.checkNotNullParam("tenant", tenant)); } } } diff --git a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java b/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java index 996a0c0a6..a34c64239 100644 --- a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java @@ -1,6 +1,7 @@ package io.a2a.spec; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * HTTP authentication security scheme for agent authentication. @@ -35,11 +36,7 @@ * @see RFC 7235 - HTTP Authentication * @see A2A Protocol Specification */ -public record HTTPAuthSecurityScheme( - String bearerFormat, - String scheme, - String description -) implements SecurityScheme { +public record HTTPAuthSecurityScheme(@Nullable String bearerFormat, String scheme, @Nullable String description) implements SecurityScheme { /** The HTTP security scheme type identifier. */ public static final String TYPE = "httpAuthSecurityScheme"; @@ -77,9 +74,9 @@ public static Builder builder() { * The {@code scheme} parameter is required and must be set before calling {@code build()}. */ public static class Builder { - private String bearerFormat; - private String scheme; - private String description; + private @Nullable String bearerFormat; + private @Nullable String scheme; + private @Nullable String description; /** * Creates a new Builder with all fields unset. @@ -127,7 +124,7 @@ public Builder description(String description) { * @throws IllegalArgumentException if required fields are missing */ public HTTPAuthSecurityScheme build() { - return new HTTPAuthSecurityScheme(bearerFormat, scheme, description); + return new HTTPAuthSecurityScheme(bearerFormat, Assert.checkNotNullParam("scheme", scheme), description); } } } diff --git a/spec/src/main/java/io/a2a/spec/InternalError.java b/spec/src/main/java/io/a2a/spec/InternalError.java index 99aa71220..5d9793972 100644 --- a/spec/src/main/java/io/a2a/spec/InternalError.java +++ b/spec/src/main/java/io/a2a/spec/InternalError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * JSON-RPC error indicating an internal error occurred on the server. @@ -34,7 +36,7 @@ public class InternalError extends A2AError { * @param message the error message * @param data additional error data */ - public InternalError(Integer code, String message, Object data) { + public InternalError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, INTERNAL_ERROR_CODE), defaultIfNull(message, "Internal Error"), @@ -46,7 +48,7 @@ public InternalError(Integer code, String message, Object data) { * * @param message the error message */ - public InternalError(String message) { + public InternalError(@Nullable String message) { this(null, message, null); } } diff --git a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java b/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java index d86fb584e..d6d8508d9 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating that an agent returned a response not conforming to protocol specifications. @@ -44,7 +46,7 @@ public class InvalidAgentResponseError extends A2AProtocolError { * @param message the error message * @param data additional error data */ - public InvalidAgentResponseError(Integer code, String message, Object data) { + public InvalidAgentResponseError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, INVALID_AGENT_RESPONSE_ERROR_CODE), defaultIfNull(message, "Invalid agent response"), diff --git a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java index a7f3476c3..a56f1ac91 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.INVALID_PARAMS_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * JSON-RPC error indicating that method parameters are invalid or missing required fields. *

        @@ -37,7 +39,7 @@ public class InvalidParamsError extends A2AError { * @param message the error message * @param data additional error data */ - public InvalidParamsError(Integer code, String message, Object data) { + public InvalidParamsError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, INVALID_PARAMS_ERROR_CODE), defaultIfNull(message, "Invalid parameters"), @@ -49,7 +51,7 @@ public InvalidParamsError(Integer code, String message, Object data) { * * @param message the error message */ - public InvalidParamsError(String message) { + public InvalidParamsError(@Nullable String message) { this(null, message, null); } diff --git a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java index 98d0f65f7..512c21b59 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.INVALID_REQUEST_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * JSON-RPC error indicating that the request payload is not a valid JSON-RPC Request object. @@ -45,7 +47,7 @@ public InvalidRequestError() { * @param message the error message * @param data additional error data */ - public InvalidRequestError(Integer code, String message, Object data) { + public InvalidRequestError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, INVALID_REQUEST_ERROR_CODE), defaultIfNull(message, "Request payload validation error"), diff --git a/spec/src/main/java/io/a2a/spec/JSONParseError.java b/spec/src/main/java/io/a2a/spec/JSONParseError.java index 74da3ddf5..72e4aaf02 100644 --- a/spec/src/main/java/io/a2a/spec/JSONParseError.java +++ b/spec/src/main/java/io/a2a/spec/JSONParseError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * JSON-RPC error indicating that the server received invalid JSON that could not be parsed. *

        @@ -51,10 +53,7 @@ public JSONParseError(String message) { * @param message the error message * @param data additional error data */ - public JSONParseError( - Integer code, - String message, - Object data) { + public JSONParseError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, JSON_PARSE_ERROR_CODE), defaultIfNull(message, "Invalid JSON payload"), diff --git a/spec/src/main/java/io/a2a/spec/ListTasksParams.java b/spec/src/main/java/io/a2a/spec/ListTasksParams.java index d99d25bcf..906fda993 100644 --- a/spec/src/main/java/io/a2a/spec/ListTasksParams.java +++ b/spec/src/main/java/io/a2a/spec/ListTasksParams.java @@ -1,5 +1,6 @@ package io.a2a.spec; +import io.a2a.util.Assert; import java.time.Instant; import org.jspecify.annotations.Nullable; @@ -44,10 +45,7 @@ public record ListTasksParams( * @throws InvalidParamsError if tenant is null or if pageSize or historyLength are out of valid range */ public ListTasksParams { - if (tenant == null) { - throw new InvalidParamsError(null, "Parameter 'tenant' may not be null", null); - } - + Assert.checkNotNullParam("tenant", tenant); // Validate pageSize (1-100) if (pageSize != null && (pageSize < MIN_PAGE_SIZE || pageSize > MAX_PAGE_SIZE)) { throw new InvalidParamsError(null, @@ -119,14 +117,14 @@ public static Builder builder() { * Builder for constructing instances. */ public static class Builder { - private String contextId; - private TaskState status; - private Integer pageSize; - private String pageToken; - private Integer historyLength; - private Instant statusTimestampAfter; - private Boolean includeArtifacts; - private String tenant; + private @Nullable String contextId; + private @Nullable TaskState status; + private @Nullable Integer pageSize; + private @Nullable String pageToken; + private @Nullable Integer historyLength; + private @Nullable Instant statusTimestampAfter; + private @Nullable Boolean includeArtifacts; + private @Nullable String tenant; /** * Creates a new Builder with all fields unset. @@ -229,7 +227,7 @@ public Builder tenant(String tenant) { */ public ListTasksParams build() { return new ListTasksParams(contextId, status, pageSize, pageToken, historyLength, - statusTimestampAfter, includeArtifacts, tenant); + statusTimestampAfter, includeArtifacts, Assert.checkNotNullParam("tenant", tenant)); } } } diff --git a/spec/src/main/java/io/a2a/spec/Message.java b/spec/src/main/java/io/a2a/spec/Message.java index 4383b1e02..1b4c73248 100644 --- a/spec/src/main/java/io/a2a/spec/Message.java +++ b/spec/src/main/java/io/a2a/spec/Message.java @@ -5,6 +5,7 @@ import java.util.UUID; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a single message in the conversation between a user and an agent in the A2A Protocol. @@ -34,9 +35,9 @@ * @see A2A Protocol Specification */ public record Message(Role role, List> parts, - String messageId, String contextId, - String taskId, List referenceTaskIds, - Map metadata, List extensions + String messageId, @Nullable String contextId, + @Nullable String taskId, @Nullable List referenceTaskIds, + @Nullable Map metadata, @Nullable List extensions ) implements EventKind, StreamingEventKind { /** @@ -66,8 +67,8 @@ public record Message(Role role, List> parts, } parts = List.copyOf(parts); referenceTaskIds = referenceTaskIds != null ? List.copyOf(referenceTaskIds) : null; - extensions = extensions != null ? List.copyOf(extensions) : null; metadata = (metadata != null) ? Map.copyOf(metadata) : null; + extensions = extensions != null ? List.copyOf(extensions) : null; } @Override @@ -144,14 +145,14 @@ public String asString() { */ public static class Builder { - private Role role; - private List> parts; - private String messageId; - private String contextId; - private String taskId; - private List referenceTaskIds; - private Map metadata; - private List extensions; + private @Nullable Role role; + private @Nullable List> parts; + private @Nullable String messageId; + private @Nullable String contextId; + private @Nullable String taskId; + private @Nullable List referenceTaskIds; + private @Nullable Map metadata; + private @Nullable List extensions; /** * Creates a new Builder with all fields unset. @@ -260,7 +261,7 @@ public Builder referenceTaskIds(List referenceTaskIds) { * @param metadata map of metadata key-value pairs (optional) * @return this builder for method chaining */ - public Builder metadata(Map metadata) { + public Builder metadata(@Nullable Map metadata) { this.metadata = metadata; return this; } @@ -285,8 +286,15 @@ public Builder extensions(List extensions) { * @throws IllegalArgumentException if required fields are missing or invalid */ public Message build() { - return new Message(role, parts, messageId == null ? UUID.randomUUID().toString() : messageId, - contextId, taskId, referenceTaskIds, metadata, extensions); + return new Message( + Assert.checkNotNullParam("role", role), + Assert.checkNotNullParam("parts", parts), + messageId == null ? UUID.randomUUID().toString() : messageId, + contextId, + taskId, + referenceTaskIds, + metadata, + extensions); } } } diff --git a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java index 4082d2501..d8ea772a9 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java +++ b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java @@ -21,8 +21,8 @@ * @see PushNotificationConfig for push notification options * @see A2A Protocol Specification */ -public record MessageSendConfiguration(List acceptedOutputModes, Integer historyLength, - PushNotificationConfig pushNotificationConfig, Boolean blocking) { +public record MessageSendConfiguration(@Nullable List acceptedOutputModes, @Nullable Integer historyLength, + @Nullable PushNotificationConfig pushNotificationConfig, Boolean blocking) { /** * Compact constructor for validation. @@ -56,9 +56,9 @@ public static Builder builder() { */ public static class Builder { - List acceptedOutputModes; - Integer historyLength; - PushNotificationConfig pushNotificationConfig; + @Nullable List acceptedOutputModes; + @Nullable Integer historyLength; + @Nullable PushNotificationConfig pushNotificationConfig; Boolean blocking = false; /** @@ -121,7 +121,11 @@ public Builder blocking(@NonNull Boolean blocking) { * @return a new message send configuration instance */ public MessageSendConfiguration build() { - return new MessageSendConfiguration(acceptedOutputModes, historyLength, pushNotificationConfig, blocking); + return new MessageSendConfiguration( + acceptedOutputModes, + historyLength, + pushNotificationConfig, + blocking); } } } diff --git a/spec/src/main/java/io/a2a/spec/MessageSendParams.java b/spec/src/main/java/io/a2a/spec/MessageSendParams.java index 1dcb6dd61..e1c75a668 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendParams.java +++ b/spec/src/main/java/io/a2a/spec/MessageSendParams.java @@ -3,6 +3,7 @@ import java.util.Map; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Parameters for sending a message to an agent in the A2A Protocol. @@ -20,8 +21,8 @@ * @see MessageSendConfiguration for available configuration options * @see A2A Protocol Specification */ -public record MessageSendParams(Message message, MessageSendConfiguration configuration, - Map metadata, String tenant) { +public record MessageSendParams(Message message, @Nullable MessageSendConfiguration configuration, + @Nullable Map metadata, String tenant) { /** * Compact constructor for validation. @@ -44,7 +45,7 @@ public record MessageSendParams(Message message, MessageSendConfiguration config * @param configuration optional configuration for message processing * @param metadata optional metadata */ - public MessageSendParams(Message message, MessageSendConfiguration configuration, Map metadata) { + public MessageSendParams(Message message, @Nullable MessageSendConfiguration configuration, @Nullable Map metadata) { this(message, configuration, metadata, ""); } @@ -64,10 +65,10 @@ public static Builder builder() { * configuration and metadata. */ public static class Builder { - Message message; - MessageSendConfiguration configuration; - Map metadata; - String tenant; + @Nullable Message message; + @Nullable MessageSendConfiguration configuration; + @Nullable Map metadata; + @Nullable String tenant; /** * Creates a new Builder with all fields unset. @@ -92,7 +93,7 @@ public Builder message(Message message) { * @param configuration the message send configuration * @return this builder */ - public Builder configuration(MessageSendConfiguration configuration) { + public Builder configuration(@Nullable MessageSendConfiguration configuration) { this.configuration = configuration; return this; } @@ -103,7 +104,7 @@ public Builder configuration(MessageSendConfiguration configuration) { * @param metadata arbitrary key-value metadata * @return this builder */ - public Builder metadata(Map metadata) { + public Builder metadata(@Nullable Map metadata) { this.metadata = metadata; return this; } @@ -126,7 +127,11 @@ public Builder tenant(String tenant) { * @throws IllegalArgumentException if message is null */ public MessageSendParams build() { - return new MessageSendParams(message, configuration, metadata, tenant == null ? "" : tenant); + return new MessageSendParams( + Assert.checkNotNullParam("message", message), + configuration, + metadata, + tenant == null ? "" : tenant); } } } diff --git a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java index e38f7a605..c69aaa572 100644 --- a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.METHOD_NOT_FOUND_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * JSON-RPC error indicating that the requested method does not exist or is not available. *

        @@ -29,10 +31,7 @@ public class MethodNotFoundError extends A2AError { * @param message the error message (defaults to "Method not found" if null) * @param data additional error data (optional) */ - public MethodNotFoundError( - Integer code, - String message, - Object data) { + public MethodNotFoundError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, METHOD_NOT_FOUND_ERROR_CODE), defaultIfNull(message, "Method not found"), diff --git a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java b/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java index ffaa323aa..85e0f76cb 100644 --- a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java @@ -1,6 +1,7 @@ package io.a2a.spec; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * OAuth 2.0 security scheme for agent authentication. @@ -19,11 +20,8 @@ * @see OpenAPI Security Scheme * @see A2A Protocol Specification */ -public record OAuth2SecurityScheme( - OAuthFlows flows, - String description, - String oauth2MetadataUrl -) implements SecurityScheme { +public record OAuth2SecurityScheme(OAuthFlows flows, @Nullable String description, @Nullable String oauth2MetadataUrl) + implements SecurityScheme { /** * The type identifier for OAuth 2.0 security schemes: "oauth2SecurityScheme". @@ -69,9 +67,10 @@ public static Builder builder() { * } */ public static class Builder { - private OAuthFlows flows; - private String description; - private String oauth2MetadataUrl; + + private @Nullable OAuthFlows flows; + private @Nullable String description; + private @Nullable String oauth2MetadataUrl; /** * Creates a new Builder with all fields unset. @@ -119,7 +118,7 @@ public Builder oauth2MetadataUrl(String oauth2MetadataUrl) { * @throws IllegalArgumentException if flows is null */ public OAuth2SecurityScheme build() { - return new OAuth2SecurityScheme(flows, description, oauth2MetadataUrl); + return new OAuth2SecurityScheme(Assert.checkNotNullParam("flows", flows), description, oauth2MetadataUrl); } } } diff --git a/spec/src/main/java/io/a2a/spec/OAuthFlows.java b/spec/src/main/java/io/a2a/spec/OAuthFlows.java index 5cabfcccd..4349c4906 100644 --- a/spec/src/main/java/io/a2a/spec/OAuthFlows.java +++ b/spec/src/main/java/io/a2a/spec/OAuthFlows.java @@ -1,5 +1,7 @@ package io.a2a.spec; +import org.jspecify.annotations.Nullable; + /** * Configuration for supported OAuth 2.0 authorization flows. *

        @@ -15,8 +17,8 @@ * @see OpenAPI OAuth Flows Object * @see A2A Protocol Specification */ -public record OAuthFlows(AuthorizationCodeOAuthFlow authorizationCode, ClientCredentialsOAuthFlow clientCredentials, - DeviceCodeOAuthFlow deviceCode) { +public record OAuthFlows(@Nullable AuthorizationCodeOAuthFlow authorizationCode, @Nullable ClientCredentialsOAuthFlow clientCredentials, + @Nullable DeviceCodeOAuthFlow deviceCode) { /** * Create a new Builder @@ -31,9 +33,9 @@ public static Builder builder() { * Builder for constructing {@link OAuthFlows} instances. */ public static class Builder { - private AuthorizationCodeOAuthFlow authorizationCode; - private ClientCredentialsOAuthFlow clientCredentials; - private DeviceCodeOAuthFlow deviceCode; + private @Nullable AuthorizationCodeOAuthFlow authorizationCode; + private @Nullable ClientCredentialsOAuthFlow clientCredentials; + private @Nullable DeviceCodeOAuthFlow deviceCode; /** * Creates a new Builder with all fields unset. diff --git a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java b/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java index 63700853a..371f18982 100644 --- a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java @@ -1,6 +1,7 @@ package io.a2a.spec; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * OpenID Connect security scheme for agent authentication. @@ -28,10 +29,7 @@ * @see OpenID Connect Discovery * @see A2A Protocol Specification */ -public record OpenIdConnectSecurityScheme( - String openIdConnectUrl, - String description -) implements SecurityScheme { +public record OpenIdConnectSecurityScheme(String openIdConnectUrl, @Nullable String description) implements SecurityScheme { /** * The type identifier for OpenID Connect security schemes: "openIdConnect". @@ -70,8 +68,8 @@ public static Builder builder() { * The {@code openIdConnectUrl} parameter is required. */ public static class Builder { - private String openIdConnectUrl; - private String description; + private @Nullable String openIdConnectUrl; + private @Nullable String description; /** * Creates a new Builder with all fields unset. @@ -108,7 +106,7 @@ public Builder description(String description) { * @throws IllegalArgumentException if openIdConnectUrl is null */ public OpenIdConnectSecurityScheme build() { - return new OpenIdConnectSecurityScheme(openIdConnectUrl, description); + return new OpenIdConnectSecurityScheme(Assert.checkNotNullParam("openIdConnectUrl", openIdConnectUrl), description); } } } diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java index 6fe62ff1c..d6c88dec5 100644 --- a/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java +++ b/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java @@ -1,6 +1,7 @@ package io.a2a.spec; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Configuration for asynchronous push notifications of task updates. @@ -25,7 +26,7 @@ * @see MessageSendConfiguration for configuring push notifications on message send * @see A2A Protocol Specification */ -public record PushNotificationConfig(String url, String token, AuthenticationInfo authentication, String id) { +public record PushNotificationConfig(String url, @Nullable String token, @Nullable AuthenticationInfo authentication, @Nullable String id) { /** * Compact constructor for validation. @@ -66,10 +67,10 @@ public static Builder builder(PushNotificationConfig config) { * authentication and identification. */ public static class Builder { - private String url; - private String token; - private AuthenticationInfo authentication; - private String id; + private @Nullable String url; + private @Nullable String token; + private @Nullable AuthenticationInfo authentication; + private @Nullable String id; /** Creates an empty builder. */ private Builder() { @@ -138,7 +139,7 @@ public Builder id(String id) { * @throws IllegalArgumentException if url is null */ public PushNotificationConfig build() { - return new PushNotificationConfig(url, token, authentication, id); + return new PushNotificationConfig(Assert.checkNotNullParam("url", url), token, authentication, id); } } } diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java b/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java index f8f7747b8..c84f4d79f 100644 --- a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating that the agent does not support push notifications. *

        @@ -42,10 +44,7 @@ public PushNotificationNotSupportedError() { * @param message the error message (defaults to "Push Notification is not supported" if null) * @param data additional error data (optional) */ - public PushNotificationNotSupportedError( - Integer code, - String message, - Object data) { + public PushNotificationNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE), defaultIfNull(message, "Push Notification is not supported"), diff --git a/spec/src/main/java/io/a2a/spec/Task.java b/spec/src/main/java/io/a2a/spec/Task.java index 24336dcd9..fd7cfce01 100644 --- a/spec/src/main/java/io/a2a/spec/Task.java +++ b/spec/src/main/java/io/a2a/spec/Task.java @@ -4,6 +4,7 @@ import java.util.Map; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a single, stateful operation or conversation between a client and an agent in the A2A Protocol. @@ -42,14 +43,8 @@ * @see Message * @see A2A Protocol Specification */ -public record Task( - String id, - String contextId, - TaskStatus status, - List artifacts, - List history, - Map metadata -) implements EventKind, StreamingEventKind { +public record Task(String id, String contextId, TaskStatus status, @Nullable List artifacts, + @Nullable List history, @Nullable Map metadata) implements EventKind, StreamingEventKind { /** * The identifier when used in streaming responses @@ -124,12 +119,12 @@ public static Builder builder(Task task) { * } */ public static class Builder { - private String id; - private String contextId; - private TaskStatus status; - private List artifacts; - private List history; - private Map metadata; + private @Nullable String id; + private @Nullable String contextId; + private @Nullable TaskStatus status; + private @Nullable List artifacts; + private @Nullable List history; + private @Nullable Map metadata; /** * Creates a new Builder with all fields unset. @@ -203,7 +198,7 @@ public Builder status(TaskStatus status) { * @return this builder for method chaining * @see Artifact */ - public Builder artifacts(List artifacts) { + public Builder artifacts(@Nullable List artifacts) { this.artifacts = artifacts; return this; } @@ -218,7 +213,7 @@ public Builder artifacts(List artifacts) { * @return this builder for method chaining * @see Message */ - public Builder history(List history) { + public Builder history(@Nullable List history) { this.history = history; return this; } @@ -258,7 +253,13 @@ public Builder metadata(Map metadata) { * @throws IllegalArgumentException if any required field (id, contextId, status) is null */ public Task build() { - return new Task(id, contextId, status, artifacts, history, metadata); + return new Task( + Assert.checkNotNullParam("id", id), + Assert.checkNotNullParam("contextId", contextId), + Assert.checkNotNullParam("status", status), + artifacts, + history, + metadata); } } } diff --git a/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java b/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java index b2ca5265e..1d009673d 100644 --- a/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java +++ b/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java @@ -3,6 +3,7 @@ import java.util.Map; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * Event notifying that a task artifact has been created, modified, or appended to. @@ -38,14 +39,8 @@ * @see Artifact * @see Task */ -public record TaskArtifactUpdateEvent( - String taskId, - Artifact artifact, - String contextId, - Boolean append, - Boolean lastChunk, - Map metadata -) implements EventKind, StreamingEventKind, UpdateEvent { +public record TaskArtifactUpdateEvent(String taskId, Artifact artifact, String contextId, @Nullable Boolean append, + @Nullable Boolean lastChunk, @Nullable Map metadata) implements EventKind, StreamingEventKind, UpdateEvent { /** * The identifier when used in streaming responses @@ -124,12 +119,12 @@ public static Builder builder(TaskArtifactUpdateEvent event) { */ public static class Builder { - private String taskId; - private Artifact artifact; - private String contextId; - private Boolean append; - private Boolean lastChunk; - private Map metadata; + private @Nullable String taskId; + private @Nullable Artifact artifact; + private @Nullable String contextId; + private @Nullable Boolean append; + private @Nullable Boolean lastChunk; + private @Nullable Map metadata; private Builder() { } @@ -182,7 +177,7 @@ public Builder contextId(String contextId) { * @param append true to append, false or null for new artifact * @return this builder for method chaining */ - public Builder append(Boolean append) { + public Builder append(@Nullable Boolean append) { this.append = append; return this; } @@ -193,7 +188,7 @@ public Builder append(Boolean append) { * @param lastChunk true if final chunk, false or null otherwise * @return this builder for method chaining */ - public Builder lastChunk(Boolean lastChunk) { + public Builder lastChunk(@Nullable Boolean lastChunk) { this.lastChunk = lastChunk; return this; } @@ -216,7 +211,13 @@ public Builder metadata(Map metadata) { * @throws IllegalArgumentException if required fields are missing */ public TaskArtifactUpdateEvent build() { - return new TaskArtifactUpdateEvent(taskId, artifact, contextId, append, lastChunk, metadata); + return new TaskArtifactUpdateEvent( + Assert.checkNotNullParam("taskId", taskId), + Assert.checkNotNullParam("artifact", artifact), + Assert.checkNotNullParam("contextId", contextId), + append, + lastChunk, + metadata); } } } diff --git a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java index 86213eb37..13853a16a 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating that a task cannot be canceled in its current state. *

        @@ -45,10 +47,7 @@ public TaskNotCancelableError() { * @param message the error message (defaults to "Task cannot be canceled" if null) * @param data additional error data (optional) */ - public TaskNotCancelableError( - Integer code, - String message, - Object data) { + public TaskNotCancelableError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, TASK_NOT_CANCELABLE_ERROR_CODE), defaultIfNull(message, "Task cannot be canceled"), diff --git a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java index 252286257..8bb8eea27 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating that the requested task ID does not exist. *

        @@ -46,10 +48,7 @@ public TaskNotFoundError() { * @param message the error message (defaults to "Task not found" if null) * @param data additional error data (optional) */ - public TaskNotFoundError( - Integer code, - String message, - Object data) { + public TaskNotFoundError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, TASK_NOT_FOUND_ERROR_CODE), defaultIfNull(message, "Task not found"), diff --git a/spec/src/main/java/io/a2a/spec/TaskStatus.java b/spec/src/main/java/io/a2a/spec/TaskStatus.java index 0ce67f3df..87055f236 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatus.java +++ b/spec/src/main/java/io/a2a/spec/TaskStatus.java @@ -1,9 +1,10 @@ package io.a2a.spec; import java.time.OffsetDateTime; -import java.time.ZoneOffset; import io.a2a.util.Assert; +import java.time.ZoneOffset; +import org.jspecify.annotations.Nullable; /** * Represents the status of a task at a specific point in time in the A2A Protocol. @@ -37,8 +38,7 @@ * @see Task * @see A2A Protocol Specification */ -public record TaskStatus(TaskState state, Message message, - OffsetDateTime timestamp) { +public record TaskStatus(TaskState state, @Nullable Message message, OffsetDateTime timestamp) { /** * Compact constructor for validation and timestamp initialization. @@ -48,11 +48,15 @@ public record TaskStatus(TaskState state, Message message, * @param message optional status message * @param timestamp the status timestamp */ - public TaskStatus { - Assert.checkNotNullParam("state", state); - timestamp = timestamp == null ? OffsetDateTime.now(ZoneOffset.UTC) : timestamp; + public TaskStatus(TaskState state, @Nullable Message message, @Nullable OffsetDateTime timestamp){ + this.state = Assert.checkNotNullParam("state", state); + this.timestamp = timestamp == null ? OffsetDateTime.now(ZoneOffset.UTC) : timestamp; + this.message = message; } + public OffsetDateTime timestamp() { + return timestamp; + } /** * Creates a TaskStatus with only a state, using the current UTC time as the timestamp. *

        @@ -62,19 +66,6 @@ public record TaskStatus(TaskState state, Message message, * @param state the task state (required) */ public TaskStatus(TaskState state) { - this(state, null, null); - } - - /** - * Creates a TaskStatus with a specific timestamp, primarily for testing purposes. - *

        - * This package-private constructor allows tests to create TaskStatus instances - * with deterministic timestamps for assertions. - * - * @param state the task state (required) - * @param timestamp the timestamp to use (if null, current UTC time is used) - */ - TaskStatus(TaskState state, OffsetDateTime timestamp) { - this(state, null, timestamp); + this(state, null, OffsetDateTime.now(ZoneOffset.UTC)); } } diff --git a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java index 547a6e089..5cc6621cf 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java +++ b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java @@ -10,6 +10,7 @@ import com.google.gson.annotations.SerializedName; import io.a2a.util.Assert; +import org.jspecify.annotations.Nullable; /** * An event sent by the agent to notify the client of a change in a task's status. @@ -21,14 +22,8 @@ * @param isFinal whether this is a final status * @param metadata additional metadata (optional) */ -public record TaskStatusUpdateEvent( - String taskId, - TaskStatus status, - String contextId, - @SerializedName("final") - boolean isFinal, - Map metadata - ) implements EventKind, StreamingEventKind, UpdateEvent { +public record TaskStatusUpdateEvent(String taskId, TaskStatus status, String contextId, + @SerializedName("final") boolean isFinal, @Nullable Map metadata) implements EventKind, StreamingEventKind, UpdateEvent { /** * The identifier when used in streaming responses @@ -91,10 +86,10 @@ public static Builder builder(TaskStatusUpdateEvent event) { */ public static class Builder { - private String taskId; - private TaskStatus status; - private String contextId; - private Map metadata; + private @Nullable String taskId; + private @Nullable TaskStatus status; + private @Nullable String contextId; + private @Nullable Map metadata; private Builder() { } @@ -156,7 +151,12 @@ public Builder metadata(Map metadata) { * @return a new TaskStatusUpdateEvent instance */ public TaskStatusUpdateEvent build() { - return new TaskStatusUpdateEvent(taskId, status, contextId, status.state().isFinal(), metadata); + return new TaskStatusUpdateEvent( + Assert.checkNotNullParam("taskId", taskId), + Assert.checkNotNullParam("status", status), + Assert.checkNotNullParam("contextId", contextId), + Assert.checkNotNullParam("status", status).state().isFinal(), + metadata); } } } diff --git a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java index ac98efa3a..65bdbed9a 100644 --- a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java +++ b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating that the requested operation is not supported by the agent. *

        @@ -40,10 +42,7 @@ public class UnsupportedOperationError extends A2AProtocolError { * @param message the error message (defaults to "This operation is not supported" if null) * @param data additional error data (optional) */ - public UnsupportedOperationError( - Integer code, - String message, - Object data) { + public UnsupportedOperationError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, UNSUPPORTED_OPERATION_ERROR_CODE), defaultIfNull(message, "This operation is not supported"), diff --git a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java index 72a05bc74..f4caf5e77 100644 --- a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java @@ -3,6 +3,8 @@ import static io.a2a.spec.A2AErrorCodes.VERSION_NOT_SUPPORTED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import org.jspecify.annotations.Nullable; + /** * A2A Protocol error indicating that the A2A protocol version specified in the request @@ -35,10 +37,7 @@ public class VersionNotSupportedError extends A2AProtocolError { * @param message the error message (defaults to standard message if null) * @param data additional error data (optional) */ - public VersionNotSupportedError( - Integer code, - String message, - Object data) { + public VersionNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { super( defaultIfNull(code, VERSION_NOT_SUPPORTED_ERROR_CODE), defaultIfNull(message, "Protocol version not supported"), diff --git a/spec/src/main/java/io/a2a/spec/package-info.java b/spec/src/main/java/io/a2a/spec/package-info.java new file mode 100644 index 000000000..f91b3a08c --- /dev/null +++ b/spec/src/main/java/io/a2a/spec/package-info.java @@ -0,0 +1,8 @@ +/** + * JSON processing exceptions for the A2A Java SDK. + *

        + * This package provides custom exceptions that replace Jackson's JSON processing exceptions, + * allowing the SDK to be independent of any specific JSON library implementation. + */ +@org.jspecify.annotations.NullMarked +package io.a2a.spec; 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 ea58beba4..67ac7a2a9 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 @@ -63,6 +63,7 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; +import io.a2a.spec.MessageSendConfiguration; import io.a2a.spec.MessageSendParams; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.PushNotificationNotSupportedError; @@ -92,6 +93,13 @@ public class JSONRPCHandlerTest extends AbstractA2ARequestHandlerTest { private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + private static MessageSendConfiguration defaultConfiguration() { + return MessageSendConfiguration.builder() + .acceptedOutputModes(List.of()) + .blocking(false) + .build(); + } + @Test public void testOnGetTaskSuccess() throws Exception { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); @@ -1008,6 +1016,7 @@ public void testStreamingNotSupportedError() { .id("1") .params(MessageSendParams.builder() .message(MESSAGE) + .configuration(defaultConfiguration()) .build()) .build(); Flow.Publisher response = handler.onMessageSendStream(request, callContext); @@ -1171,7 +1180,7 @@ public void testOnMessageSendInternalError() { JSONRPCHandler handler = new JSONRPCHandler(CARD, mocked, internalExecutor); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(MESSAGE, null, null)); + SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(MESSAGE, defaultConfiguration(), null)); SendMessageResponse response = handler.onMessageSend(request, callContext); assertInstanceOf(InternalError.class, response.getError()); @@ -1185,7 +1194,7 @@ public void testOnMessageStreamInternalError() { JSONRPCHandler handler = new JSONRPCHandler(CARD, mocked, internalExecutor); - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, null, null)); + SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, defaultConfiguration(), null)); Flow.Publisher response = handler.onMessageSendStream(request, callContext); List results = new ArrayList<>(); @@ -1270,7 +1279,7 @@ public void testOnMessageSendTaskIdMismatch() { agentEmitter.emitEvent(MINIMAL_TASK); }); SendMessageRequest request = new SendMessageRequest("1", - new MessageSendParams(MESSAGE, null, null)); + new MessageSendParams(MESSAGE, defaultConfiguration(), null)); SendMessageResponse response = handler.onMessageSend(request, callContext); assertInstanceOf(InternalError.class, response.getError()); @@ -1286,7 +1295,7 @@ public void testOnMessageStreamTaskIdMismatch() throws InterruptedException { agentEmitter.emitEvent(MINIMAL_TASK); }); - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, null, null)); + SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, defaultConfiguration(), null)); Flow.Publisher response = handler.onMessageSendStream(request, callContext); CompletableFuture future = new CompletableFuture<>(); 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 609c4e0a9..7f206d336 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 @@ -290,7 +290,7 @@ public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String s } } - public HTTPRestResponse getTaskPushNotificationConfiguration(String taskId, @Nullable String configId, String tenant, ServerCallContext context) { + public HTTPRestResponse getTaskPushNotificationConfiguration(String taskId, String configId, String tenant, ServerCallContext context) { try { if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); From 3afb15a325462bb74acf3b8d3dba32d824346cbf Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Wed, 11 Feb 2026 13:31:32 +0100 Subject: [PATCH 027/192] fix: rename the HTTP request parameter statusTimestampAfter (#641) Signed-off-by: Jeff Mesnil --- .../java/io/a2a/server/rest/quarkus/A2AServerRoutes.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 c8dc54086..8e8912922 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 @@ -67,6 +67,7 @@ public class A2AServerRoutes { private static final String HISTORY_LENGTH_PARAM = "historyLength"; private static final String PAGE_SIZE_PARAM = "pageSize"; private static final String PAGE_TOKEN_PARAM = "pageToken"; + private static final String STATUS_TIMESTAMP_AFTER = "statusTimestampAfter"; @Inject RestHandler jsonRestHandler; @@ -139,7 +140,7 @@ public void listTasks(RoutingContext rc) { String pageSizeStr = rc.request().params().get(PAGE_SIZE_PARAM); String pageToken = rc.request().params().get(PAGE_TOKEN_PARAM); String historyLengthStr = rc.request().params().get(HISTORY_LENGTH_PARAM); - String lastUpdatedAfter = rc.request().params().get("lastUpdatedAfter"); + String statusTimestampAfter = rc.request().params().get(STATUS_TIMESTAMP_AFTER); String includeArtifactsStr = rc.request().params().get("includeArtifacts"); // Parse optional parameters @@ -159,7 +160,7 @@ public void listTasks(RoutingContext rc) { } response = jsonRestHandler.listTasks(contextId, statusStr, pageSize, pageToken, - historyLength, lastUpdatedAfter, includeArtifacts, extractTenant(rc), context); + historyLength, statusTimestampAfter, includeArtifacts, extractTenant(rc), context); } catch (NumberFormatException e) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("Invalid number format in parameters")); } catch (IllegalArgumentException e) { From 102d26b9f404492f2267d2c0f22e7b6dcfd29764 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 11 Feb 2026 14:06:06 +0000 Subject: [PATCH 028/192] feat: Make RequestContext taskId and contextId nullable. (#642) This is possible by moving the generation of IDs when not set into the builder, and making sure the builder is used. --- .../server/agentexecution/RequestContext.java | 189 ++++++++++------- .../io/a2a/server/tasks/AgentEmitter.java | 5 +- .../agentexecution/RequestContextTest.java | 199 +++++++++++++++--- 3 files changed, 295 insertions(+), 98 deletions(-) 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 c82df7846..beee9bf7e 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 @@ -74,50 +74,52 @@ */ public class RequestContext { - private @Nullable MessageSendParams params; - private @Nullable String taskId; - private @Nullable String contextId; - private @Nullable Task task; - private List relatedTasks; + private final @Nullable MessageSendParams params; + private final String taskId; + private final String contextId; + private final @Nullable Task task; + private final List relatedTasks; private final @Nullable ServerCallContext callContext; - public RequestContext( + /** + * Constructor with all fields already validated and initialized. + *

        + * Note: Use {@link Builder} instead of calling this constructor directly. + * The builder handles ID generation and validation. + *

        + * + * @param params the message send parameters (can be null for cancel operations) + * @param taskId the task identifier (must not be null) + * @param contextId the context identifier (must not be null) + * @param task the existing task state (null for new conversations) + * @param relatedTasks other tasks in the same context (must not be null, can be empty) + * @param callContext the server call context (can be null) + */ + private RequestContext( @Nullable MessageSendParams params, - @Nullable String taskId, - @Nullable String contextId, + String taskId, + String contextId, @Nullable Task task, - @Nullable List relatedTasks, - @Nullable ServerCallContext callContext) throws InvalidParamsError { + List relatedTasks, + @Nullable ServerCallContext callContext) { this.params = params; this.taskId = taskId; this.contextId = contextId; this.task = task; - this.relatedTasks = relatedTasks == null ? new ArrayList<>() : relatedTasks; + this.relatedTasks = relatedTasks; this.callContext = callContext; - - // If the taskId and contextId were specified, they must match the params - if (params != null) { - if (taskId != null && !taskId.equals(params.message().taskId())) { - throw new InvalidParamsError("bad task id"); - } - this.taskId = checkOrGenerateTaskId(); - if (contextId != null && !contextId.equals(params.message().contextId())) { - throw new InvalidParamsError("bad context id"); - } - this.contextId = checkOrGenerateContextId(); - } } /** * Returns the task identifier. *

        - * This is auto-generated (UUID) if not provided by the client in the message parameters. - * It can be null if the context was not created from message parameters. + * This is auto-generated (UUID) by the builder if not provided by the client + * in the message parameters. This value is never null. *

        * - * @return the task ID + * @return the task ID (never null) */ - public @Nullable String getTaskId() { + public String getTaskId() { return taskId; } @@ -125,13 +127,13 @@ public RequestContext( * Returns the conversation context identifier. *

        * Conversation contexts group related tasks together (e.g., multiple tasks - * in the same user session). This is auto-generated (UUID) if not provided by the client - * in the message parameters. It can be null if the context was not created from message parameters. + * in the same user session). This is auto-generated (UUID) by the builder if + * not provided by the client in the message parameters. This value is never null. *

        * - * @return the context ID + * @return the context ID (never null) */ - public @Nullable String getContextId() { + public String getContextId() { return contextId; } @@ -209,6 +211,19 @@ public List getRelatedTasks() { return callContext; } + /** + * Returns the tenant identifier from the request parameters. + *

        + * The tenant is used in multi-tenant environments to identify which + * customer or organization the request belongs to. + *

        + * + * @return the tenant identifier, or null if no params or tenant not set + */ + public @Nullable String getTenant() { + return params != null ? params.tenant() : null; + } + /** * Extracts all text content from the message and joins with the specified delimiter. *

        @@ -240,48 +255,20 @@ public String getUserInput(String delimiter) { return getMessageText(params.message(), delimiter); } + /** + * Attaches a related task to this context. + *

        + * This is primarily used by the framework to populate related tasks after + * construction. Agent implementations should use {@link #getRelatedTasks()} + * to access related tasks. + *

        + * + * @param task the task to attach + */ public void attachRelatedTask(Task task) { relatedTasks.add(task); } - private @Nullable String checkOrGenerateTaskId() { - if (params == null) { - return taskId; - } - if (taskId == null && params.message().taskId() == null) { - // Message is immutable, create new one with generated taskId - String generatedTaskId = UUID.randomUUID().toString(); - Message updatedMessage = Message.builder(params.message()) - .taskId(generatedTaskId) - .build(); - params = new MessageSendParams(updatedMessage, params.configuration(), params.metadata()); - return generatedTaskId; - } - if (params.message().taskId() != null) { - return params.message().taskId(); - } - return taskId; - } - - private @Nullable String checkOrGenerateContextId() { - if (params == null) { - return contextId; - } - if (contextId == null && params.message().contextId() == null) { - // Message is immutable, create new one with generated contextId - String generatedContextId = UUID.randomUUID().toString(); - Message updatedMessage = Message.builder(params.message()) - .contextId(generatedContextId) - .build(); - params = new MessageSendParams(updatedMessage, params.configuration(), params.metadata()); - return generatedContextId; - } - if (params.message().contextId() != null) { - return params.message().contextId(); - } - return contextId; - } - private String getMessageText(Message message, String delimiter) { List textParts = getTextParts(message.parts()); return String.join(delimiter, textParts); @@ -295,6 +282,18 @@ private List getTextParts(List> parts) { .collect(Collectors.toList()); } + /** + * Builder for creating {@link RequestContext} instances. + *

        + * The builder handles ID generation and validation automatically: + *

        + *
          + *
        • TaskId and ContextId are auto-generated (UUID) if not provided
        • + *
        • IDs are validated against message parameters if both are present
        • + *
        • Message parameters are updated with generated IDs
        • + *
        • Related tasks list is initialized to empty list if null
        • + *
        + */ public static class Builder { private @Nullable MessageSendParams params; private @Nullable String taskId; @@ -357,8 +356,56 @@ public Builder setServerCallContext(@Nullable ServerCallContext serverCallContex return serverCallContext; } - public RequestContext build() { - return new RequestContext(params, taskId, contextId, task, relatedTasks, serverCallContext); + /** + * Builds the RequestContext with ID generation and validation. + * + * @return the constructed RequestContext + * @throws InvalidParamsError if taskId or contextId don't match message parameters + */ + public RequestContext build() throws InvalidParamsError { + // 1. Initialize relatedTasks to empty list if null + List finalRelatedTasks = relatedTasks != null ? relatedTasks : new ArrayList<>(); + + // 2. Extract message IDs upfront (or null if no params) + String messageTaskId = params != null ? params.message().taskId() : null; + String messageContextId = params != null ? params.message().contextId() : null; + + // 3. Validate: if both builder and message provide an ID, they must match + if (taskId != null && messageTaskId != null && !taskId.equals(messageTaskId)) { + throw new InvalidParamsError("bad task id"); + } + if (contextId != null && messageContextId != null && !contextId.equals(messageContextId)) { + throw new InvalidParamsError("bad context id"); + } + + // 4. Determine final IDs using coalesce pattern: builder → message → generate + String finalTaskId = taskId != null ? taskId : + messageTaskId != null ? messageTaskId : + UUID.randomUUID().toString(); + + String finalContextId = contextId != null ? contextId : + messageContextId != null ? messageContextId : + UUID.randomUUID().toString(); + + // 5. Update params if message needs to be updated with final IDs + MessageSendParams finalParams = params; + if (params != null && (!finalTaskId.equals(messageTaskId) || !finalContextId.equals(messageContextId))) { + Message updatedMessage = Message.builder(params.message()) + .taskId(finalTaskId) + .contextId(finalContextId) + .build(); + // Preserve all original fields including tenant + finalParams = MessageSendParams.builder() + .message(updatedMessage) + .configuration(params.configuration()) + .metadata(params.metadata()) + .tenant(params.tenant()) + .build(); + } + + // 6. Call constructor with finalized values (IDs guaranteed non-null) + return new RequestContext(finalParams, finalTaskId, finalContextId, + task, finalRelatedTasks, serverCallContext); } } diff --git a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java index 7c6c97f20..6088022b6 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java +++ b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java @@ -18,7 +18,6 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; -import io.a2a.util.Assert; import org.jspecify.annotations.Nullable; /** @@ -108,8 +107,8 @@ public class AgentEmitter { */ public AgentEmitter(RequestContext context, EventQueue eventQueue) { this.eventQueue = eventQueue; - this.taskId = Assert.checkNotNullParam("taskId",context.getTaskId()); - this.contextId = Assert.checkNotNullParam("contextId",context.getContextId()); + this.taskId = context.getTaskId(); + this.contextId = context.getContextId(); } private void updateStatus(TaskState taskState) { 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 ba692d97c..0fc9c16ca 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 @@ -35,10 +35,11 @@ private static MessageSendConfiguration defaultConfiguration() { @Test public void testInitWithoutParams() { - RequestContext context = new RequestContext(null, null, null, null, null, null); + RequestContext context = new RequestContext.Builder().build(); + assertNull(context.getMessage()); - assertNull(context.getTaskId()); - assertNull(context.getContextId()); + assertNotNull(context.getTaskId()); // Generated UUID + assertNotNull(context.getContextId()); // Generated UUID assertNull(context.getTask()); assertTrue(context.getRelatedTasks().isEmpty()); } @@ -56,7 +57,9 @@ public void testInitWithParamsNoIds() { .thenReturn(taskId) .thenReturn(contextId); - RequestContext context = new RequestContext(mockParams, null, null, null, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .build(); // getMessage() returns a new Message with generated IDs, not the original assertNotNull(context.getMessage()); @@ -73,7 +76,10 @@ public void testInitWithTaskId() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(taskId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, taskId, null, null, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setTaskId(taskId) + .build(); assertEquals(taskId, context.getTaskId()); assertEquals(taskId, mockParams.message().taskId()); @@ -84,7 +90,11 @@ public void testInitWithContextId() { String contextId = "context-456"; var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).contextId(contextId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, null, contextId, null, null, null); + + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setContextId(contextId) + .build(); assertEquals(contextId, context.getContextId()); assertEquals(contextId, mockParams.message().contextId()); @@ -96,7 +106,12 @@ public void testInitWithBothIds() { String contextId = "context-456"; var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(taskId).contextId(contextId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, taskId, contextId, null, null, null); + + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setTaskId(taskId) + .setContextId(contextId) + .build(); assertEquals(taskId, context.getTaskId()); assertEquals(taskId, mockParams.message().taskId()); @@ -110,14 +125,17 @@ public void testInitWithTask() { var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, null, null, mockTask, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setTask(mockTask) + .build(); assertEquals(mockTask, context.getTask()); } @Test public void testGetUserInputNoParams() { - RequestContext context = new RequestContext(null, null, null, null, null, null); + RequestContext context = new RequestContext.Builder().build(); assertEquals("", context.getUserInput(null)); } @@ -125,7 +143,7 @@ public void testGetUserInputNoParams() { public void testAttachRelatedTask() { var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); - RequestContext context = new RequestContext(null, null, null, null, null, null); + RequestContext context = new RequestContext.Builder().build(); assertEquals(0, context.getRelatedTasks().size()); context.attachRelatedTask(mockTask); @@ -144,7 +162,9 @@ public void testCheckOrGenerateTaskIdWithExistingTaskId() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(existingId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, null, null, null, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .build(); assertEquals(existingId, context.getTaskId()); assertEquals(existingId, mockParams.message().taskId()); @@ -157,7 +177,9 @@ public void testCheckOrGenerateContextIdWithExistingContextId() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).contextId(existingId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, null, null, null, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .build(); assertEquals(existingId, context.getContextId()); assertEquals(existingId, mockParams.message().contextId()); @@ -170,7 +192,11 @@ public void testInitRaisesErrorOnTaskIdMismatch() { var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); InvalidParamsError error = assertThrows(InvalidParamsError.class, () -> - new RequestContext(mockParams, "wrong-task-id", null, mockTask, null, null)); + new RequestContext.Builder() + .setParams(mockParams) + .setTaskId("wrong-task-id") + .setTask(mockTask) + .build()); assertTrue(error.getMessage().contains("bad task id")); } @@ -182,7 +208,12 @@ public void testInitRaisesErrorOnContextIdMismatch() { var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); InvalidParamsError error = assertThrows(InvalidParamsError.class, () -> - new RequestContext(mockParams, mockTask.id(), "wrong-context-id", mockTask, null, null)); + new RequestContext.Builder() + .setParams(mockParams) + .setTaskId(mockTask.id()) + .setContextId("wrong-context-id") + .setTask(mockTask) + .build()); assertTrue(error.getMessage().contains("bad context id")); } @@ -195,7 +226,9 @@ public void testWithRelatedTasksProvided() { relatedTasks.add(mockTask); relatedTasks.add(mock(Task.class)); - RequestContext context = new RequestContext(null, null, null, null, relatedTasks, null); + RequestContext context = new RequestContext.Builder() + .setRelatedTasks(relatedTasks) + .build(); assertEquals(relatedTasks, context.getRelatedTasks()); assertEquals(2, context.getRelatedTasks().size()); @@ -203,7 +236,7 @@ public void testWithRelatedTasksProvided() { @Test public void testMessagePropertyWithoutParams() { - RequestContext context = new RequestContext(null, null, null, null, null, null); + RequestContext context = new RequestContext.Builder().build(); assertNull(context.getMessage()); } @@ -212,7 +245,10 @@ public void testMessagePropertyWithParams() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, null, null, null, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .build(); + // getMessage() returns a new Message with generated IDs, not the original assertNotNull(context.getMessage()); assertEquals(mockMessage.role(), context.getMessage().role()); @@ -228,7 +264,9 @@ public void testInitWithExistingIdsInMessage() { .taskId(existingTaskId).contextId(existingContextId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, null, null, null, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .build(); assertEquals(existingTaskId, context.getTaskId()); assertEquals(existingContextId, context.getContextId()); @@ -240,8 +278,11 @@ public void testInitWithTaskIdAndExistingTaskIdMatch() { var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); - - RequestContext context = new RequestContext(mockParams, mockTask.id(), null, mockTask, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setTaskId(mockTask.id()) + .setTask(mockTask) + .build(); assertEquals(mockTask.id(), context.getTaskId()); assertEquals(mockTask, context.getTask()); @@ -253,8 +294,12 @@ public void testInitWithContextIdAndExistingContextIdMatch() { var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); - - RequestContext context = new RequestContext(mockParams, mockTask.id(), mockTask.contextId(), mockTask, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setTaskId(mockTask.id()) + .setContextId(mockTask.contextId()) + .setTask(mockTask) + .build(); assertEquals(mockTask.contextId(), context.getContextId()); assertEquals(mockTask, context.getTask()); @@ -265,7 +310,10 @@ void testMessageBuilderGeneratesId() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, null, null, null, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .build(); + assertNotNull(mockMessage.messageId()); assertFalse(mockMessage.messageId().isEmpty()); } @@ -275,7 +323,110 @@ void testMessageBuilderUsesProvidedId() { var mockMessage = Message.builder().messageId("123").role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - RequestContext context = new RequestContext(mockParams, null, null, null, null, null); + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .build(); + assertEquals("123", mockMessage.messageId()); } + + @Test + public void testBuilderGeneratesIdsWhenNoParams() { + RequestContext context = new RequestContext.Builder() + .build(); + + assertNotNull(context.getTaskId()); + assertNotNull(context.getContextId()); + assertFalse(context.getTaskId().isEmpty()); + assertFalse(context.getContextId().isEmpty()); + } + + @Test + public void testBuilderPreservesProvidedIdsWhenNoParams() { + String providedTaskId = "my-task-id"; + String providedContextId = "my-context-id"; + + RequestContext context = new RequestContext.Builder() + .setTaskId(providedTaskId) + .setContextId(providedContextId) + .build(); + + assertEquals(providedTaskId, context.getTaskId()); + assertEquals(providedContextId, context.getContextId()); + } + + @Test + public void testBuilderUpdatesMessageWithBuilderIds() { + // Regression test for Gemini review: ensure message gets updated when builder provides IDs + String builderTaskId = "builder-task-id"; + String builderContextId = "builder-context-id"; + + // Message has no IDs, but builder provides them + var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); + + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setTaskId(builderTaskId) + .setContextId(builderContextId) + .build(); + + // Both context and message should have the builder IDs + assertEquals(builderTaskId, context.getTaskId()); + assertEquals(builderContextId, context.getContextId()); + assertEquals(builderTaskId, context.getMessage().taskId()); // KEY: message must be updated + assertEquals(builderContextId, context.getMessage().contextId()); // KEY: message must be updated + } + + @Test + public void testMessageIdsTakePrecedenceWhenBothPresent() { + // When both builder and message provide IDs, they must match (or throw) + String sharedTaskId = "shared-task-id"; + String sharedContextId = "shared-context-id"; + + var mockMessage = Message.builder() + .role(Message.Role.USER) + .parts(List.of(new TextPart(""))) + .taskId(sharedTaskId) + .contextId(sharedContextId) + .build(); + var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); + + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setTaskId(sharedTaskId) // Same as message + .setContextId(sharedContextId) // Same as message + .build(); + + assertEquals(sharedTaskId, context.getTaskId()); + assertEquals(sharedContextId, context.getContextId()); + assertEquals(sharedTaskId, context.getMessage().taskId()); + assertEquals(sharedContextId, context.getMessage().contextId()); + } + + @Test + public void testBuilderPreservesTenantWhenUpdatingMessage() { + // Regression test for Gemini review: ensure tenant is preserved when message is updated + String tenantId = "customer-123"; + String builderTaskId = "builder-task-id"; + + var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockParams = MessageSendParams.builder() + .message(mockMessage) + .configuration(defaultConfiguration()) + .tenant(tenantId) + .build(); + + RequestContext context = new RequestContext.Builder() + .setParams(mockParams) + .setTaskId(builderTaskId) // Forces message update + .build(); + + // Verify the message was updated with builder's task ID + assertNotNull(context.getMessage()); + assertEquals(builderTaskId, context.getMessage().taskId()); + + // KEY: Verify tenant wasn't lost during message update + assertEquals(tenantId, context.getTenant()); + } } From cb30129c2dae460604a9f35eb471915a795ce7b2 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 11 Feb 2026 15:57:31 +0100 Subject: [PATCH 029/192] feat: Add telemetry support. (#463) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding support for OpenTelemetry Fixes #388 🦕 Signed-off-by: Emmanuel Hugonnet --- .gitignore | 11 +- boms/extras/pom.xml | 20 + boms/extras/src/it/extras-usage-test/pom.xml | 16 + .../java/io/a2a/test/ExtrasBomVerifier.java | 3 +- .../java/io/a2a/client/ClientBuilder.java | 56 +- .../transport/rest/RestTransportConfig.java | 2 +- .../transport/spi/ClientTransportConfig.java | 31 +- .../transport/spi/ClientTransportWrapper.java | 81 +++ examples/helloworld/client/README.md | 196 ++++++- examples/helloworld/client/pom.xml | 45 +- .../examples/helloworld/HelloWorldClient.java | 108 +++- .../examples/helloworld/HelloWorldRunner.java | 21 +- examples/helloworld/pom.xml | 20 - examples/helloworld/server/README.md | 59 +++ examples/helloworld/server/pom.xml | 34 +- .../helloworld/AgentCardProducer.java | 21 +- .../src/main/resources/application.properties | 13 +- .../opentelemetry/client-propagation/pom.xml | 44 ++ ...penTelemetryClientPropagatorTransport.java | 123 +++++ ...metryClientPropagatorTransportWrapper.java | 49 ++ .../client/propagation/package-info.java | 5 + ...lient.transport.spi.ClientTransportWrapper | 1 + extras/opentelemetry/client/pom.xml | 48 ++ .../client/OpenTelemetryClientTransport.java | 491 +++++++++++++++++ .../OpenTelemetryClientTransportWrapper.java | 47 ++ .../opentelemetry/client/package-info.java | 5 + ...lient.transport.spi.ClientTransportWrapper | 1 + .../OpenTelemetryClientTransportTest.java | 489 +++++++++++++++++ extras/opentelemetry/common/pom.xml | 18 + .../opentelemetry/A2AObservabilityNames.java | 23 + .../extras/opentelemetry/package-info.java | 8 + .../opentelemetry/integration-tests/README.md | 160 ++++++ .../opentelemetry/integration-tests/pom.xml | 136 +++++ .../opentelemetry/it/A2ATestRoutes.java | 228 ++++++++ .../opentelemetry/it/SimpleAgentExecutor.java | 41 ++ .../it/TestAgentCardProducer.java | 47 ++ .../opentelemetry/it/TestUtilsBean.java | 46 ++ .../src/main/resources/META-INF/beans.xml | 9 + .../src/main/resources/application.properties | 28 + .../a2a/extras/opentelemetry/it/BaseTest.java | 20 + .../it/OpenTelemetryA2ABaseTest.java | 301 +++++++++++ .../opentelemetry/it/OpenTelemetryA2AIT.java | 11 + .../it/OpenTelemetryA2ATest.java | 11 + .../opentelemetry/it/OpenTelemetryTest.java | 42 ++ .../src/test/resources/application.properties | 25 + extras/opentelemetry/pom.xml | 41 ++ extras/opentelemetry/server/pom.xml | 71 +++ .../OpenTelemetryRequestHandlerDecorator.java | 465 ++++++++++++++++ .../extras/opentelemetry/package-info.java | 5 + .../src/main/resources/META-INF/beans.xml | 9 + ...nTelemetryRequestHandlerDecoratorTest.java | 497 ++++++++++++++++++ pom.xml | 31 ++ .../quarkus/A2AExtensionsInterceptor.java | 19 +- .../server/rest/quarkus/A2AServerRoutes.java | 26 +- .../rest/quarkus/A2AServerRoutesTest.java | 43 +- .../DefaultRequestHandler.java | 2 + .../src/main/java/io/a2a/spec/A2AMethods.java | 1 + spec/src/main/java/io/a2a/spec/Message.java | 44 +- .../grpc/context/GrpcContextKeys.java | 33 +- .../transport/grpc/handler/GrpcHandler.java | 44 +- .../transport/grpc/handler/package-info.java | 9 + .../jsonrpc/handler/JSONRPCHandler.java | 1 - .../transport/rest/handler/RestHandler.java | 27 +- .../rest/handler/RestHandlerTest.java | 85 ++- 64 files changed, 4445 insertions(+), 202 deletions(-) create mode 100644 client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportWrapper.java create mode 100644 extras/opentelemetry/client-propagation/pom.xml create mode 100644 extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java create mode 100644 extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java create mode 100644 extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java create mode 100644 extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper create mode 100644 extras/opentelemetry/client/pom.xml create mode 100644 extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java create mode 100644 extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java create mode 100644 extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java create mode 100644 extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper create mode 100644 extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java create mode 100644 extras/opentelemetry/common/pom.xml create mode 100644 extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java create mode 100644 extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java create mode 100644 extras/opentelemetry/integration-tests/README.md create mode 100644 extras/opentelemetry/integration-tests/pom.xml create mode 100644 extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java create mode 100644 extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java create mode 100644 extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java create mode 100644 extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java create mode 100644 extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml create mode 100644 extras/opentelemetry/integration-tests/src/main/resources/application.properties create mode 100644 extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java create mode 100644 extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java create mode 100644 extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java create mode 100644 extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java create mode 100644 extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java create mode 100644 extras/opentelemetry/integration-tests/src/test/resources/application.properties create mode 100644 extras/opentelemetry/pom.xml create mode 100644 extras/opentelemetry/server/pom.xml create mode 100644 extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java create mode 100644 extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java create mode 100644 extras/opentelemetry/server/src/main/resources/META-INF/beans.xml create mode 100644 extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java create mode 100644 transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java diff --git a/.gitignore b/.gitignore index 143f602c6..3679c8f0c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ release.properties .flattened-pom.xml *.args +#Claude +CLAUDE.md + # Eclipse .project .classpath @@ -19,8 +22,10 @@ bin/ *.iml *.iws -# NetBeans +# Apache NetBeans nb-configuration.xml +nbactions.xml +nbproject/ # Visual Studio Code .vscode @@ -45,10 +50,6 @@ nb-configuration.xml # TLS Certificates .certs/ -#Apache NetBeans -nbproject/ -nbactions.xml - # Private Claude config .claude/ .serena/ diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 7cf7a54a8..c353e91af 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -39,6 +39,26 @@ a2a-java-sdk-http-client-vertx ${project.version} + + ${project.groupId} + a2a-java-sdk-opentelemetry-common + ${project.version} + + + ${project.groupId} + a2a-java-sdk-opentelemetry-client + ${project.version} + + + ${project.groupId} + a2a-java-sdk-opentelemetry-client-propagation + ${project.version} + + + ${project.groupId} + a2a-java-sdk-opentelemetry-server + ${project.version} + ${project.groupId} a2a-java-extras-task-store-database-jpa diff --git a/boms/extras/src/it/extras-usage-test/pom.xml b/boms/extras/src/it/extras-usage-test/pom.xml index cd8b897d9..5ec29b3a6 100644 --- a/boms/extras/src/it/extras-usage-test/pom.xml +++ b/boms/extras/src/it/extras-usage-test/pom.xml @@ -48,6 +48,22 @@ io.github.a2asdk a2a-java-sdk-http-client-vertx + + io.github.a2asdk + a2a-java-sdk-opentelemetry-common + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-client + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-client-propagation + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-server + io.github.a2asdk a2a-java-extras-task-store-database-jpa diff --git a/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java b/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java index 9f7fd092f..81cd0b855 100644 --- a/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java +++ b/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java @@ -17,7 +17,8 @@ public class ExtrasBomVerifier extends DynamicBomVerifier { "tck/", // TCK test suite "tests/", // Integration tests "extras/queue-manager-replicated/tests-multi-instance/", // Test harness applications - "extras/queue-manager-replicated/tests-single-instance/" // Test harness applications + "extras/queue-manager-replicated/tests-single-instance/", // Test harness applications + "extras/opentelemetry/integration-tests/" // Test harness applications // Note: extras/ production modules are NOT in this list - we want to verify those classes load ); 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 c8d2ab6be..81c812c91 100644 --- a/client/base/src/main/java/io/a2a/client/ClientBuilder.java +++ b/client/base/src/main/java/io/a2a/client/ClientBuilder.java @@ -6,14 +6,17 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; +import java.util.ServiceLoader.Provider; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; import io.a2a.client.config.ClientConfig; import io.a2a.client.transport.spi.ClientTransport; import io.a2a.client.transport.spi.ClientTransportConfig; import io.a2a.client.transport.spi.ClientTransportConfigBuilder; import io.a2a.client.transport.spi.ClientTransportProvider; +import io.a2a.client.transport.spi.ClientTransportWrapper; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; @@ -21,6 +24,9 @@ import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Builder for creating instances of {@link Client} to communicate with A2A agents. *

        @@ -96,6 +102,7 @@ public class ClientBuilder { private static final Map>> transportProviderRegistry = new HashMap<>(); private static final Map, String> transportProtocolMapping = new HashMap<>(); + private static final Logger LOGGER = LoggerFactory.getLogger(ClientBuilder.class); static { ServiceLoader loader = ServiceLoader.load(ClientTransportProvider.class); @@ -318,7 +325,7 @@ private ClientTransport buildClientTransport() throws A2AClientException { throw new A2AClientException("Missing required TransportConfig for " + agentInterface.protocolBinding()); } - return clientTransportProvider.create(clientTransportConfig, agentCard, agentInterface); + return wrap(clientTransportProvider.create(clientTransportConfig, agentCard, agentInterface), clientTransportConfig); } private Map getServerPreferredTransports() throws A2AClientException { @@ -373,10 +380,55 @@ private AgentInterface findBestClientTransport() throws A2AClientException { if (transportProtocol == null || transportUrl == null) { throw new A2AClientException("No compatible transport found"); } - if (! transportProviderRegistry.containsKey(transportProtocol)) { + if (!transportProviderRegistry.containsKey(transportProtocol)) { throw new A2AClientException("No client available for " + transportProtocol); } return new AgentInterface(transportProtocol, transportUrl); } + + /** + * Wraps the transport with all available transport wrappers discovered via ServiceLoader. + * Wrappers are applied in reverse priority order (lowest priority first) to build a stack + * where the highest priority wrapper is the outermost layer. + * + * @param transport the base transport to wrap + * @param clientTransportConfig the transport configuration + * @return the wrapped transport (or original if no wrappers are available/applicable) + */ + private ClientTransport wrap(ClientTransport transport, ClientTransportConfig clientTransportConfig) { + ServiceLoader wrapperLoader = ServiceLoader.load(ClientTransportWrapper.class); + + // Collect all wrappers, sort by priority, then reverse for stack application + List wrappers = wrapperLoader.stream().map(Provider::get) + .sorted() + .collect(Collectors.toList()); + + if (wrappers.isEmpty()) { + LOGGER.debug("No client transport wrappers found via ServiceLoader"); + return transport; + } + LOGGER.debug(wrappers.size() + " client transport wrappers found via ServiceLoader"); + + // Reverse to apply lowest priority first (building stack with highest priority outermost) + java.util.Collections.reverse(wrappers); + + // Apply wrappers to build stack + ClientTransport wrapped = transport; + for (ClientTransportWrapper wrapper : wrappers) { + try { + ClientTransport newWrapped = wrapper.wrap(wrapped, clientTransportConfig); + if (newWrapped != wrapped) { + LOGGER.debug("Applied transport wrapper: {} (priority: {})", + wrapper.getClass().getName(), wrapper.priority()); + } + wrapped = newWrapped; + } catch (Exception e) { + LOGGER.warn("Failed to apply transport wrapper {}: {}", + wrapper.getClass().getName(), e.getMessage(), e); + } + } + + return wrapped; + } } diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java index 241541a32..e78c67271 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java +++ b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java @@ -48,7 +48,7 @@ * @see A2AHttpClient * @see io.a2a.client.http.JdkA2AHttpClient */ -public class RestTransportConfig extends ClientTransportConfig { +public class RestTransportConfig extends ClientTransportConfig { private final @Nullable A2AHttpClient httpClient; 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 9c05fac59..f93954b40 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,9 +1,13 @@ package io.a2a.client.transport.spi; import java.util.ArrayList; + +import java.util.HashMap; import java.util.List; +import java.util.Map; import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; +import java.util.Collections; /** * Base configuration class for A2A client transport protocols. @@ -34,7 +38,8 @@ */ public abstract class ClientTransportConfig { - protected List interceptors = new ArrayList<>(); + protected List interceptors = Collections.emptyList(); + protected Map parameters = Collections.emptyMap(); /** * Set the list of request/response interceptors. @@ -63,4 +68,28 @@ public void setInterceptors(List interceptors) { public List getInterceptors() { return java.util.Collections.unmodifiableList(interceptors); } + + /** + * Set the Map of config parameters. + * The provided map is copied to prevent external modifications from affecting + * this configuration. + * + * @param parameters the map of parameters to use (will be copied) + */ + public void setParameters(Map parameters) { + this.parameters = new HashMap<>(parameters); + } + + + /** + * Get the list of configured parameters. + *

        + * Returns an unmodifiable view of the parameters map. Attempting to modify + * the returned map will throw {@link UnsupportedOperationException}. + * + * @return an unmodifiable map of configured parameters (never null, but may be empty) + */ + public Map getParameters() { + return java.util.Collections.unmodifiableMap(parameters); + } } diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportWrapper.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportWrapper.java new file mode 100644 index 000000000..25dba33b9 --- /dev/null +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportWrapper.java @@ -0,0 +1,81 @@ +package io.a2a.client.transport.spi; + +/** + * Service provider interface for wrapping client transports with additional functionality. + * Implementations can add cross-cutting concerns like tracing, metrics, logging, etc. + * + *

        Wrappers are discovered via Java's ServiceLoader mechanism. To register a wrapper, + * create a file {@code META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper} + * containing the fully qualified class name of your implementation. + * + *

        Wrappers are sorted by priority in descending order (highest priority first). + * This interface implements {@link Comparable} to enable natural sorting. + * + *

        Example implementation: + *

        {@code
        + * public class TracingWrapper implements ClientTransportWrapper {
        + *     @Override
        + *     public ClientTransport wrap(ClientTransport transport, ClientTransportConfig config) {
        + *         if (config.getParameters().containsKey("tracer")) {
        + *             return new TracingTransport(transport, (Tracer) config.getParameters().get("tracer"));
        + *         }
        + *         return transport;
        + *     }
        + *
        + *     @Override
        + *     public int priority() {
        + *         return 100; // Higher priority = wraps earlier (outermost)
        + *     }
        + * }
        + * }
        + */ +public interface ClientTransportWrapper extends Comparable { + + /** + * Wraps the given transport with additional functionality. + * + *

        Implementations should check the configuration to determine if they should + * actually wrap the transport. If the wrapper is not applicable (e.g., required + * configuration is missing), return the original transport unchanged. + * + * @param transport the transport to wrap + * @param config the transport configuration, may contain wrapper-specific parameters + * @return the wrapped transport, or the original if wrapping is not applicable + */ + ClientTransport wrap(ClientTransport transport, ClientTransportConfig config); + + /** + * Returns the priority of this wrapper. Higher priority wrappers are applied first + * (wrap the transport earlier, resulting in being the outermost wrapper). + * + *

        Default priority is 0. Suggested ranges: + *

          + *
        • 1000+ : Critical infrastructure (security, authentication) + *
        • 500-999: Observability (tracing, metrics, logging) + *
        • 100-499: Enhancement (caching, retry logic) + *
        • 0-99: Optional features + *
        + * + * @return the priority value, higher values = higher priority + */ + default int priority() { + return 0; + } + + /** + * Compares this wrapper with another based on priority. + * Returns a negative integer, zero, or a positive integer as this wrapper + * has higher priority than, equal to, or lower priority than the specified wrapper. + * + *

        Note: This comparison is reversed (higher priority comes first) to enable + * natural sorting in descending priority order. + * + * @param other the wrapper to compare to + * @return negative if this has higher priority, positive if lower, zero if equal + */ + @Override + default int compareTo(ClientTransportWrapper other) { + // Reverse comparison: higher priority should come first + return Integer.compare(other.priority(), this.priority()); + } +} diff --git a/examples/helloworld/client/README.md b/examples/helloworld/client/README.md index ac01c890f..cd5043f11 100644 --- a/examples/helloworld/client/README.md +++ b/examples/helloworld/client/README.md @@ -41,9 +41,13 @@ The Python A2A server is part of the [a2a-samples](https://github.com/google-a2a The server will start running on `http://localhost:9999`. -## Run the Java A2A Client with JBang +### Using the Java Server Instead -The Java client can be run using JBang, which allows you to run Java source files directly without any manual compilation. +Alternatively, you can use the Java server example instead of the Python server. The Java server supports multiple transport protocols (JSONRPC, GRPC, and HTTP+JSON). See the [server README](../server/README.md) for details on starting the Java server with different transport protocols. + +## Run the Java A2A Client + +The Java client can be run using either Maven or JBang. ### Build the A2A Java SDK @@ -54,38 +58,204 @@ cd /path/to/a2a-java mvn clean install ``` -### Using the JBang script +### Option 1: Using Maven (Recommended) -A JBang script is provided in the example directory to make running the client easy: +Run the client using Maven's exec plugin: -1. Make sure you have JBang installed. If not, follow the [JBang installation guide](https://www.jbang.dev/documentation/guide/latest/installation.html). +```bash +cd examples/helloworld/client +mvn exec:java +``` -2. Navigate to the example directory: - ```bash - cd examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/ - ``` +#### Transport Protocol Selection + +The client supports multiple transport protocols. You can select which protocol to use via the `quarkus.agentcard.protocol` property: + +**Using JSONRPC (default)**: +```bash +mvn exec:java +``` + +**Using GRPC**: +```bash +mvn exec:java -Dquarkus.agentcard.protocol=GRPC +``` + +**Using HTTP+JSON**: +```bash +mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON +``` + +Available protocols: +- `JSONRPC` - Uses JSON-RPC for communication (default) +- `GRPC` - Uses gRPC for communication +- `HTTP+JSON` - Uses HTTP with JSON payloads + +**Note**: The protocol you select on the client must match the protocol configured on the server. + +#### Enabling OpenTelemetry + +To enable OpenTelemetry with Maven: +```bash +mvn exec:java -Dopentelemetry=true +``` + +You can combine protocol selection with OpenTelemetry: +```bash +mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true +``` + +### Option 2: Using JBang + +A JBang script is provided for running the client without Maven: + +1. Make sure you have JBang installed. If not, follow the [JBang installation guide](https://www.jbang.dev/documentation/guide/latest/installation.html). 3. Run the client using the JBang script: ```bash - jbang HelloWorldRunner.java + jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java ``` -This script automatically handles the dependencies and sources for you. +#### Transport Protocol Selection with JBang + +Select the transport protocol using the same `-Dquarkus.agentcard.protocol` property: + +**Using JSONRPC (default)**: +```bash +jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +``` + +**Using GRPC**: +```bash +jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC +``` + +**Using HTTP+JSON**: +```bash +jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON +``` + +#### Enabling OpenTelemetry with JBang + +To enable OpenTelemetry with JBang: +```bash +jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true +``` + +You can combine protocol selection with OpenTelemetry: +```bash +jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC -Dopentelemetry=true +``` ## What the Example Does The Java client (`HelloWorldClient.java`) performs the following actions: 1. Fetches the server's public agent card -2. Fetches the server's extended agent card +2. Fetches the server's extended agent card 3. Creates a client using the extended agent card that connects to the Python server at `http://localhost:9999`. 4. Sends a regular message asking "how much is 10 USD in INR?". 5. Prints the server's response. 6. Sends the same message as a streaming request. 7. Prints each chunk of the server's streaming response as it arrives. +## Enable OpenTelemetry (Optional) + +The client includes support for distributed tracing with OpenTelemetry. To enable it: + +### Prerequisites + +**IMPORTANT**: The client expects an OpenTelemetry collector to be ready and accepting traces. You have two options: + +#### Option 1: Use the Java Server Example (Recommended) + +Instead of the Python server, use the Java server example which has built-in OpenTelemetry support: + +1. **Start the Java server with OpenTelemetry enabled**: + ```bash + mvn quarkus:dev -Popentelemetry -pl examples/helloworld/server/ -Dquarkus.agentcard.protocol=HTTP+JSON + ``` + This will: + - Start the server at `http://localhost:9999` + - Launch Grafana at `http://localhost:3001` + - Start OTLP collectors on ports 5317 (gRPC) and 5318 (HTTP) + +2. **Run the client with OpenTelemetry**: + + Using Maven (from `examples/helloworld/client`): + ```bash + mvn exec:java -Dopentelemetry=true + ``` + + With specific protocol: + ```bash + mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true + ``` + + Or using JBang: + ```bash + jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true + ``` + + With specific protocol: + ```bash + jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true + ``` + +3. **View traces in Grafana**: + - Open `http://localhost:3001` (credentials: admin/admin) + - Go to "Explore" → select "Tempo" data source + - View distributed traces showing the full request flow from client to server + +#### Option 2: Use External OpenTelemetry Collector + +If you want to use the Python server with OpenTelemetry: + +1. **Start an OpenTelemetry collector** on port 5317 (e.g., using Docker): + ```bash + docker run -p 5317:4317 otel/opentelemetry-collector + ``` + +2. **Run the Python server** + +3. **Run the client with OpenTelemetry**: + ```bash + mvn exec:java -Dopentelemetry=true + ``` + + Or with JBang: + ```bash + jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true + ``` + + With specific protocol: + ```bash + mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true + ``` + +### What Gets Traced + +When OpenTelemetry is enabled, the client traces: +- Agent card fetching (public and extended) +- Message sending (blocking and streaming) +- Task operations (get, cancel, list) +- Push notification configuration operations +- Connection and transport layer operations + +Client traces are automatically linked with server traces (when using the Java server), providing end-to-end visibility of the entire A2A protocol flow. + +### Configuration + +The client is configured to send traces to `http://localhost:5317` (OTLP gRPC endpoint). To use a different endpoint, modify the `initOpenTelemetry()` method in `HelloWorldClient.java`: + +```java +OtlpGrpcSpanExporter.builder() + .setEndpoint("http://your-collector:4317") + .build() +``` + ## Notes - Make sure the Python server is running before starting the Java client. - The client will wait for 10 seconds to collect streaming responses before exiting. -- You can modify the message text or server URL in the `HelloWorldClient.java` file if needed. \ No newline at end of file +- You can modify the message text or server URL in the `HelloWorldClient.java` file if needed. diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index a9e0cf0d4..7f18c0ba8 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -12,7 +12,7 @@ a2a-java-sdk-examples-client - Java SDK A2A Examples + Java SDK A2A Examples - HelloWorld Client Examples for the Java SDK for the Agent2Agent Protocol (A2A) @@ -27,7 +27,34 @@ io.github.a2asdk a2a-java-sdk-jsonrpc-common - ${project.version} + + + io.github.a2asdk + a2a-java-sdk-client-transport-grpc + + + io.github.a2asdk + a2a-java-sdk-client-transport-rest + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-client + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-client-propagation + + + io.opentelemetry + opentelemetry-sdk + + + io.opentelemetry + opentelemetry-exporter-otlp + + + io.opentelemetry + opentelemetry-exporter-logging @@ -61,6 +88,20 @@ + + org.codehaus.mojo + exec-maven-plugin + 3.6.2 + + io.a2a.examples.helloworld.HelloWorldClient + + + opentelemetry + ${opentelemetry} + + + + \ No newline at end of file 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 5b8a6d196..332706ccc 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 @@ -1,5 +1,8 @@ package io.a2a.examples.helloworld; +import static io.a2a.extras.opentelemetry.client.OpenTelemetryClientTransportWrapper.OTEL_TRACER_KEY; +import static io.a2a.extras.opentelemetry.client.propagation.OpenTelemetryClientPropagatorTransportWrapper.OTEL_OPEN_TELEMETRY_KEY; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -11,16 +14,32 @@ import io.a2a.A2A; import io.a2a.client.Client; +import io.a2a.client.ClientBuilder; import io.a2a.client.ClientEvent; import io.a2a.client.MessageEvent; import io.a2a.client.http.A2ACardResolver; +import io.a2a.client.transport.grpc.GrpcTransport; +import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; import io.a2a.client.transport.jsonrpc.JSONRPCTransport; import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfig; +import io.a2a.client.transport.rest.RestTransport; +import io.a2a.client.transport.rest.RestTransportConfig; +import io.a2a.client.transport.spi.ClientTransportConfig; import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.AgentCard; import io.a2a.spec.Message; import io.a2a.spec.Part; import io.a2a.spec.TextPart; +import io.grpc.Channel; +import io.grpc.ManagedChannelBuilder; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; +import java.util.function.Function; /** * A simple example of using the A2A Java SDK to communicate with an A2A server. @@ -32,13 +51,13 @@ public class HelloWorldClient { private static final String MESSAGE_TEXT = "how much is 10 USD in INR?"; public static void main(String[] args) { + OpenTelemetrySdk openTelemetrySdk = null; try { - AgentCard finalAgentCard = null; AgentCard publicAgentCard = new A2ACardResolver("http://localhost:9999").getAgentCard(); System.out.println("Successfully fetched public agent card:"); System.out.println(JsonUtil.toJson(publicAgentCard)); System.out.println("Using public agent card for client initialization (default)."); - finalAgentCard = publicAgentCard; + AgentCard finalAgentCard = publicAgentCard; if (publicAgentCard.capabilities().extendedAgentCard()) { System.out.println("Public card supports authenticated extended card. Attempting to fetch from: " + SERVER_URL + "/ExtendedAgentCard"); @@ -81,20 +100,23 @@ public static void main(String[] args) { messageResponse.completeExceptionally(error); }; - Client client = Client + if (Boolean.getBoolean("opentelemetry")) { + openTelemetrySdk = initOpenTelemetry(); + } + + ClientBuilder clientBuilder = Client .builder(finalAgentCard) .addConsumers(consumers) - .streamingErrorHandler(streamingErrorHandler) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) - .build(); + .streamingErrorHandler(streamingErrorHandler); + configureTransport(clientBuilder, openTelemetrySdk); + Client client = clientBuilder.build(); Message message = A2A.toUserMessage(MESSAGE_TEXT); // the message ID will be automatically generated for you - - System.out.println("Sending message: " + MESSAGE_TEXT); - client.sendMessage(message); - System.out.println("Message sent successfully. Responses will be handled by the configured consumers."); - try { + System.out.println("Sending message: " + MESSAGE_TEXT); + client.sendMessage(message); + System.out.println("Message sent successfully. Responses will be handled by the configured consumers."); + String responseText = messageResponse.get(); System.out.println("Response: " + responseText); } catch (Exception e) { @@ -103,7 +125,69 @@ public static void main(String[] args) { } catch (Exception e) { System.err.println("An error occurred: " + e.getMessage()); e.printStackTrace(); + } finally { + // Ensure OpenTelemetry SDK is properly shut down to export all pending spans + if (openTelemetrySdk != null) { + System.out.println("Shutting down OpenTelemetry SDK..."); + openTelemetrySdk.close(); + System.out.println("OpenTelemetry SDK shutdown complete."); + } } } -} \ No newline at end of file + static OpenTelemetrySdk initOpenTelemetry() { + SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() + .addSpanProcessor(BatchSpanProcessor.builder( + OtlpGrpcSpanExporter.builder() + .setEndpoint("http://localhost:5317") + .build() + ).build()) + .setResource(Resource.getDefault().toBuilder() + .put("service.version", "1.0") + .put("service.name", "helloworld-client") + .build()) + .build(); + + return OpenTelemetrySdk.builder() + .setTracerProvider(sdkTracerProvider) + .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) + .build(); + } + private static void configureTransport(ClientBuilder clientBuilder, OpenTelemetrySdk openTelemetrySdk) { + ClientTransportConfig transportConfig; + switch(System.getProperty("quarkus.agentcard.protocol", "JSONRPC")) { + case "GRPC": + Function channelFactory = url -> { + // Extract "localhost:9999" from "http://localhost:9999" + String target = url.replaceAll("^https?://", ""); + return ManagedChannelBuilder.forTarget(target) + .usePlaintext() // No TLS + .build(); + }; + transportConfig = new GrpcTransportConfigBuilder().channelFactory(channelFactory).build(); + updateTransportConfig(transportConfig, openTelemetrySdk); + clientBuilder.withTransport(GrpcTransport.class, transportConfig); + break; + case "HTTP+JSON": + transportConfig = new RestTransportConfig(); + updateTransportConfig(transportConfig, openTelemetrySdk); + clientBuilder.withTransport(RestTransport.class, transportConfig); + break; + case "JSONRPC": + default: + transportConfig = new JSONRPCTransportConfig(); + updateTransportConfig(transportConfig, openTelemetrySdk); + clientBuilder.withTransport(JSONRPCTransport.class, transportConfig); + break; + } + } + + private static void updateTransportConfig(ClientTransportConfig transportConfig, OpenTelemetrySdk openTelemetrySdk) { + if (openTelemetrySdk != null) { + Map parameters = new HashMap<>(transportConfig.getParameters()); + parameters.put(OTEL_TRACER_KEY, openTelemetrySdk.getTracer("helloworld-client")); + parameters.put(OTEL_OPEN_TELEMETRY_KEY, openTelemetrySdk); + transportConfig.setParameters(parameters); + } + } +} diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java index 138f7e4f7..0cd652283 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java @@ -1,6 +1,16 @@ + ///usr/bin/env jbang "$0" "$@" ; exit $? + //DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha2-SNAPSHOT //DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha2-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha2-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha2-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha2-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha2-SNAPSHOT +//DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 +//DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 +//DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 +//DEPS io.grpc:grpc-netty:1.77.0 //SOURCES HelloWorldClient.java /** @@ -17,7 +27,16 @@ * The script will communicate with the A2A server at http://localhost:9999 */ public class HelloWorldRunner { + public static void main(String[] args) { + for (String arg : args) { + if (arg != null && arg.startsWith("-D")) { + int index = arg.indexOf('='); + if (index > 0) { + System.setProperty(arg.substring(2, index), arg.substring(index + 1)); + } + } + } io.a2a.examples.helloworld.HelloWorldClient.main(args); } -} +} diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 589e9c30d..e48e2fdad 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -29,30 +29,10 @@ io.github.a2asdk a2a-java-sdk-client - ${project.version} - - - - io.quarkus - quarkus-maven-plugin - true - - - - build - generate-code - generate-code-tests - - - - - - - client server diff --git a/examples/helloworld/server/README.md b/examples/helloworld/server/README.md index 5573dce09..66f39f7ec 100644 --- a/examples/helloworld/server/README.md +++ b/examples/helloworld/server/README.md @@ -18,6 +18,35 @@ cd examples/helloworld/server mvn quarkus:dev ``` +### Transport Protocol Selection + +The server supports multiple transport protocols. You can select which protocol to use via the `quarkus.agentcard.protocol` property: + +**Using JSONRPC (default)**: +```bash +mvn quarkus:dev +``` + +**Using GRPC**: +```bash +mvn quarkus:dev -Dquarkus.agentcard.protocol=GRPC +``` + +**Using HTTP+JSON**: +```bash +mvn quarkus:dev -Dquarkus.agentcard.protocol=HTTP+JSON +``` + +You can also change the default protocol by editing `src/main/resources/application.properties` and setting: +```properties +quarkus.agentcard.protocol=HTTP+JSON +``` + +Available protocols: +- `JSONRPC` - Uses JSON-RPC for communication (default) +- `GRPC` - Uses gRPC for communication +- `HTTP+JSON` - Uses HTTP with JSON payloads + ## Setup and Run the Python A2A Client The Python A2A client is part of the [a2a-samples](https://github.com/google-a2a/a2a-samples) project. To set it up and run it: @@ -61,6 +90,36 @@ The Python A2A client (`test_client.py`) performs the following actions: 6. Sends the same message as a streaming request. 7. Prints each chunk of the server's streaming response as it arrives. +## Enable OpenTelemetry (Optional) + +The server includes support for distributed tracing with OpenTelemetry. To enable it: + +1. **Run with the OpenTelemetry profile**: + ```bash + mvn quarkus:dev -Popentelemetry + ``` + +2. **Access Grafana dashboard**: + - Quarkus Dev Services will automatically start a Grafana observability stack + - Open Grafana at `http://localhost:3001` (default credentials: admin/admin) + - View traces in the "Explore" section using the Tempo data source + +3. **What gets traced**: + - All A2A protocol operations (send message, get task, cancel task, etc.) + - Streaming message responses + - Task lifecycle events + - Custom operations in your `AgentExecutor` implementation (using `@Trace` annotation) + +4. **Configuration**: + - OpenTelemetry settings are in `application.properties` + - OTLP exporters run on ports 5317 (gRPC) and 5318 (HTTP) + - To use a custom OTLP endpoint, uncomment and modify: + ```properties + quarkus.otel.exporter.otlp.endpoint=http://localhost:4317 + ``` + +For more information, see the [OpenTelemetry extras module documentation](../../../extras/opentelemetry/README.md). + ## Notes - Make sure the Java server is running before starting the Python client. diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 699adf4d4..aea025993 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -12,7 +12,7 @@ a2a-java-sdk-examples-server - Java SDK A2A Examples + Java SDK A2A Examples - HelloWorld Server Examples for the Java SDK for the Agent2Agent Protocol (A2A) @@ -29,6 +29,14 @@ quarkus-resteasy provided + + io.github.a2asdk + a2a-java-sdk-reference-grpc + + + io.github.a2asdk + a2a-java-sdk-reference-rest + jakarta.enterprise jakarta.enterprise.cdi-api @@ -55,7 +63,31 @@ + + --add-opens=java.base/java.lang=ALL-UNNAMED + + + + + opentelemetry + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-server + + + io.quarkus + quarkus-opentelemetry + + + io.quarkus + quarkus-observability-devservices-lgtm + provided + + + + \ No newline at end of file diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java index 3725e1bd7..0f4821290 100644 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java +++ b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java @@ -12,20 +12,24 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.AgentSkill; +import org.eclipse.microprofile.config.inject.ConfigProperty; @ApplicationScoped public class AgentCardProducer { + @ConfigProperty(name = "quarkus.agentcard.protocol", defaultValue="JSONRPC") + String protocol; + @Produces @PublicAgentCard public AgentCard agentCard() { // NOTE: Transport validation will automatically check that transports specified // in this AgentCard match those available on the classpath when handlers are initialized + return AgentCard.builder() .name("Hello World Agent") .description("Just a hello world agent") - .supportedInterfaces(Collections.singletonList( - new AgentInterface("jsonrpc", "http://localhost:9999"))) + .supportedInterfaces(Collections.singletonList(getAgentInterface())) .version("1.0.0") .documentationUrl("http://example.com/docs") .capabilities(AgentCapabilities.builder() @@ -43,5 +47,16 @@ public AgentCard agentCard() { .build())) .build(); } -} + private AgentInterface getAgentInterface() { + switch(protocol) { + case "GRPC": + return new AgentInterface("GRPC", "localhost:9000"); + case "HTTP+JSON": + return new AgentInterface("HTTP+JSON", "http://localhost:9999"); + case "JSONRPC": + default: + return new AgentInterface("JSONRPC", "http://localhost:9999"); + } + } +} diff --git a/examples/helloworld/server/src/main/resources/application.properties b/examples/helloworld/server/src/main/resources/application.properties index a2452b339..eb8aee9ba 100644 --- a/examples/helloworld/server/src/main/resources/application.properties +++ b/examples/helloworld/server/src/main/resources/application.properties @@ -1 +1,12 @@ -%dev.quarkus.http.port=9999 \ No newline at end of file +%dev.quarkus.http.port=9999 + +# Protocol can be JSONRPC, GRPC, or HTTP+JSON +quarkus.agentcard.protocol=JSONRPC + +# OpenTelemetry configuration +quarkus.otel.sdk.disabled=false +quarkus.observability.lgtm.grafana-port=3001 +quarkus.observability.lgtm.otel-grpc-port=5317 +quarkus.observability.lgtm.otel-http-port=5318 +#quarkus.otel.exporter.otlp.endpoint=http://localhost:4317 +#quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{traceId}, parentId=%X{parentId}, spanId=%X{spanId}, sampled=%X{sampled} [%c{2.}] (%t) %s%e%n \ No newline at end of file diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml new file mode 100644 index 000000000..c3eac38f2 --- /dev/null +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-parent + 1.0.0.Alpha2-SNAPSHOT + + + a2a-java-sdk-opentelemetry-client-propagation + + A2A Java SDK :: Extras :: Opentelemetry :: Client Propagation + OpenTelemetry client propagation support for A2A Java SDK + + + + ${project.groupId} + a2a-java-sdk-client-transport-spi + + + org.slf4j + slf4j-api + + + org.junit.jupiter + junit-jupiter + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + + diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java new file mode 100644 index 000000000..53cd134bd --- /dev/null +++ b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java @@ -0,0 +1,123 @@ +package io.a2a.extras.opentelemetry.client.propagation; + +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.A2AClientException; +import io.a2a.spec.AgentCard; +import io.a2a.spec.DeleteTaskPushNotificationConfigParams; +import io.a2a.spec.EventKind; +import io.a2a.spec.GetTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTasksParams; +import io.a2a.spec.MessageSendParams; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.Task; +import io.a2a.spec.TaskIdParams; +import io.a2a.spec.TaskPushNotificationConfig; +import io.a2a.spec.TaskQueryParams; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapSetter; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; +import org.jspecify.annotations.Nullable; + +public class OpenTelemetryClientPropagatorTransport implements ClientTransport { + + private final OpenTelemetry openTelemetry; + private final ClientTransport delegate; + + private static final TextMapSetter> MAP_SETTER = new TextMapSetter>() { + @Override + public void set(@Nullable Map carrier, String key, String value) { + if (carrier != null) { + carrier.put(key, value); + } + } + }; + + public OpenTelemetryClientPropagatorTransport(ClientTransport delegate, OpenTelemetry openTelemetry) { + this.delegate = delegate; + this.openTelemetry = openTelemetry; + } + + private ClientCallContext propagateContext(@Nullable ClientCallContext context) { + ClientCallContext clientContext; + if (context == null) { + clientContext = new ClientCallContext(Map.of(), new HashMap<>()); + } else { + clientContext = new ClientCallContext(context.getState(), new HashMap<>(context.getHeaders())); + } + openTelemetry.getPropagators().getTextMapPropagator().inject(Context.current(), clientContext.getHeaders(), MAP_SETTER); + return clientContext; + } + + @Override + public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) throws A2AClientException { + return delegate.sendMessage(request, propagateContext(context)); + } + + @Override + public void sendMessageStreaming(MessageSendParams request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { + delegate.sendMessageStreaming(request, eventConsumer, errorConsumer, propagateContext(context)); + } + + @Override + public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException { + return delegate.getTask(request, propagateContext(context)); + } + + @Override + public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { + return delegate.cancelTask(request, propagateContext(context)); + } + + @Override + public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException { + return delegate.listTasks(request, propagateContext(context)); + } + + @Override + public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, + @Nullable ClientCallContext context) throws A2AClientException { + return delegate.createTaskPushNotificationConfiguration(request, propagateContext(context)); + } + + @Override + public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams request, + @Nullable ClientCallContext context) throws A2AClientException { + return delegate.getTaskPushNotificationConfiguration(request, propagateContext(context)); + } + + @Override + public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request, + @Nullable ClientCallContext context) throws A2AClientException { + return delegate.listTaskPushNotificationConfigurations(request, propagateContext(context)); + } + + @Override + public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams request, + @Nullable ClientCallContext context) throws A2AClientException { + delegate.deleteTaskPushNotificationConfigurations(request, propagateContext(context)); + } + + @Override + public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { + delegate.subscribeToTask(request, eventConsumer, errorConsumer, propagateContext(context)); + } + + @Override + public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { + return delegate.getExtendedAgentCard(propagateContext(context)); + } + + @Override + public void close() { + delegate.close(); + } +} diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java new file mode 100644 index 000000000..a8c83968c --- /dev/null +++ b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java @@ -0,0 +1,49 @@ +package io.a2a.extras.opentelemetry.client.propagation; + +import io.a2a.client.transport.spi.ClientTransport; +import io.a2a.client.transport.spi.ClientTransportConfig; +import io.a2a.client.transport.spi.ClientTransportWrapper; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Tracer; + +/** + * OpenTelemetry client transport wrapper that adds opentelemetry propagation to A2A client calls. + * + *

        This wrapper is automatically discovered via Java's ServiceLoader mechanism. + * To enable tracing, add a {@link Tracer} instance to the transport configuration: + *

        {@code
        + * ClientTransportConfig config = new JSONRPCTransportConfig();
        + * config.setParameters(Map.of(
        + *     OpenTelemetryClientTransportFactory.OTEL_TRACER_KEY,
        + *     openTelemetry.getTracer("my-service"),
        + *     OpenTelemetryClientTransportFactory.OTEL_OPEN_TELEMETRY_KEY,
        + *     openTelemetry
        + * ));
        + * }
        + */ +public class OpenTelemetryClientPropagatorTransportWrapper implements ClientTransportWrapper { + + /** + * Configuration key for the OpenTelemetry Tracer instance. + * Value must be of type {@link Tracer}. + */ + public static final String OTEL_TRACER_KEY = "io.a2a.extras.opentelemetry.Tracer"; + public static final String OTEL_OPEN_TELEMETRY_KEY = "io.a2a.extras.opentelemetry.OpenTelemetry"; + + @Override + public ClientTransport wrap(ClientTransport transport, ClientTransportConfig config) { + Object openTelemetryObj = config.getParameters().get(OTEL_OPEN_TELEMETRY_KEY); + if (openTelemetryObj != null && openTelemetryObj instanceof OpenTelemetry openTelemetry) { + return new OpenTelemetryClientPropagatorTransport(transport, openTelemetry); + } + // No tracer configured, return unwrapped transport + return transport; + } + + @Override + public int priority() { + // Observability/tracing should be in the middle priority range + // so it can observe other wrappers but doesn't interfere with security + return 500; + } +} diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java new file mode 100644 index 000000000..0ca927df9 --- /dev/null +++ b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package io.a2a.extras.opentelemetry.client.propagation; + +import org.jspecify.annotations.NullMarked; + diff --git a/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper b/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper new file mode 100644 index 000000000..f1cccce71 --- /dev/null +++ b/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper @@ -0,0 +1 @@ +io.a2a.extras.opentelemetry.client.propagation.OpenTelemetryClientPropagatorTransportWrapper diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml new file mode 100644 index 000000000..daf97421c --- /dev/null +++ b/extras/opentelemetry/client/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-parent + 1.0.0.Alpha2-SNAPSHOT + + + a2a-java-sdk-opentelemetry-client + + A2A Java SDK :: Extras :: Opentelemetry :: Client + OpenTelemetry client support for A2A Java SDK + + + + ${project.groupId} + a2a-java-sdk-opentelemetry-common + + + ${project.groupId} + a2a-java-sdk-client-transport-spi + + + org.slf4j + slf4j-api + + + org.junit.jupiter + junit-jupiter + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + + diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java new file mode 100644 index 000000000..ed0db190d --- /dev/null +++ b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java @@ -0,0 +1,491 @@ +package io.a2a.extras.opentelemetry.client; + +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONFIG_ID; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONTEXT_ID; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_EXTENSIONS; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_MESSAGE_ID; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_OPERATION_NAME; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_PARTS_NUMBER; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_ROLE; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_TASK_ID; + +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.A2AClientException; +import io.a2a.spec.A2AMethods; +import io.a2a.spec.AgentCard; +import io.a2a.spec.DeleteTaskPushNotificationConfigParams; +import io.a2a.spec.EventKind; +import io.a2a.spec.GetTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTasksParams; +import io.a2a.spec.MessageSendParams; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.Task; +import io.a2a.spec.TaskIdParams; +import io.a2a.spec.TaskPushNotificationConfig; +import io.a2a.spec.TaskQueryParams; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import org.jspecify.annotations.Nullable; + +public class OpenTelemetryClientTransport implements ClientTransport { + + private final Tracer tracer; + private final ClientTransport delegate; + + public OpenTelemetryClientTransport(ClientTransport delegate, Tracer tracer) { + this.delegate = delegate; + this.tracer = tracer; + } + + private boolean extractRequest() { + return Boolean.getBoolean(EXTRACT_REQUEST_SYS_PROPERTY); + } + + private boolean extractResponse() { + return Boolean.getBoolean(EXTRACT_RESPONSE_SYS_PROPERTY); + } + + @Override + public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.SEND_MESSAGE_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.SEND_MESSAGE_METHOD); + if (request.message() != null) { + if (request.message().taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.message().taskId()); + } + if (request.message().contextId() != null) { + spanBuilder.setAttribute(GENAI_CONTEXT_ID, request.message().contextId()); + } + if (request.message().messageId() != null) { + spanBuilder.setAttribute(GENAI_MESSAGE_ID, request.message().messageId()); + } + if (request.message().role() != null) { + spanBuilder.setAttribute(GENAI_ROLE, request.message().role().asString()); + } + if (request.message().extensions() != null && !request.message().extensions().isEmpty()) { + spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", request.message().extensions())); + } + spanBuilder.setAttribute(GENAI_PARTS_NUMBER, request.message().parts().size()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + EventKind result = delegate.sendMessage(request, clientContext); + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + if (result != null) { + span.setStatus(StatusCode.OK); + } + return result; + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public void sendMessageStreaming(MessageSendParams request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.SEND_STREAMING_MESSAGE_METHOD); + if (request.message() != null) { + if (request.message().taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.message().taskId()); + } + if (request.message().contextId() != null) { + spanBuilder.setAttribute(GENAI_CONTEXT_ID, request.message().contextId()); + } + if (request.message().messageId() != null) { + spanBuilder.setAttribute(GENAI_MESSAGE_ID, request.message().messageId()); + } + if (request.message().role() != null) { + spanBuilder.setAttribute(GENAI_ROLE, request.message().role().asString()); + } + if (request.message().extensions() != null && !request.message().extensions().isEmpty()) { + spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", request.message().extensions())); + } + spanBuilder.setAttribute(GENAI_PARTS_NUMBER, request.message().parts().size()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + delegate.sendMessageStreaming( + request, + new OpenTelemetryEventConsumer(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-event", eventConsumer, tracer, span.getSpanContext()), + new OpenTelemetryErrorConsumer(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-error", errorConsumer, tracer, span.getSpanContext()), + clientContext + ); + span.setStatus(StatusCode.OK); + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_METHOD); + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + Task result = delegate.getTask(request, clientContext); + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + if (result != null) { + span.setStatus(StatusCode.OK); + } + return result; + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.CANCEL_TASK_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.CANCEL_TASK_METHOD); + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + Task result = delegate.cancelTask(request, clientContext); + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + if (result != null) { + span.setStatus(StatusCode.OK); + } + return result; + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_METHOD); + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + if (request.contextId() != null) { + spanBuilder.setAttribute(GENAI_CONTEXT_ID, request.contextId()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + ListTasksResult result = delegate.listTasks(request, clientContext); + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + if (result != null) { + span.setStatus(StatusCode.OK); + } + return result; + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, + @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + if (request.taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.taskId()); + } + if (request.pushNotificationConfig() != null && request.pushNotificationConfig().id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, request.pushNotificationConfig().id()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + TaskPushNotificationConfig result = delegate.createTaskPushNotificationConfiguration(request, clientContext); + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + if (result != null) { + span.setStatus(StatusCode.OK); + } + return result; + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams request, + @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); + } + if (request.pushNotificationConfigId() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, request.pushNotificationConfigId()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + TaskPushNotificationConfig result = delegate.getTaskPushNotificationConfiguration(request, clientContext); + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + if (result != null) { + span.setStatus(StatusCode.OK); + } + return result; + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request, + @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + ListTaskPushNotificationConfigResult result = delegate.listTaskPushNotificationConfigurations(request, clientContext); + if (result != null && extractResponse()) { + String responseValue = result.configs().stream() + .map(TaskPushNotificationConfig::toString) + .collect(Collectors.joining(",")); + span.setAttribute(GENAI_RESPONSE, responseValue); + } + if (result != null) { + span.setStatus(StatusCode.OK); + } + return result; + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams request, + @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); + } + if (request.pushNotificationConfigId() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, request.pushNotificationConfigId()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + delegate.deleteTaskPushNotificationConfigurations(request, clientContext); + span.setStatus(StatusCode.OK); + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.SUBSCRIBE_TO_TASK_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.SUBSCRIBE_TO_TASK_METHOD); + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); + } + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + delegate.subscribeToTask( + request, + new OpenTelemetryEventConsumer(A2AMethods.SUBSCRIBE_TO_TASK_METHOD + "-event", eventConsumer, tracer, span.getSpanContext()), + new OpenTelemetryErrorConsumer(A2AMethods.SUBSCRIBE_TO_TASK_METHOD + "-error", errorConsumer, tracer, span.getSpanContext()), + clientContext + ); + span.setStatus(StatusCode.OK); + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + @Override + public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { + ClientCallContext clientContext = createContext(context); + SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD).setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); + Span span = spanBuilder.startSpan(); + try (Scope scope = span.makeCurrent()) { + AgentCard result = delegate.getExtendedAgentCard(clientContext); + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + if (result != null) { + span.setStatus(StatusCode.OK); + } + return result; + } catch (Exception ex) { + span.setStatus(StatusCode.ERROR, ex.getMessage()); + throw ex; + } finally { + span.end(); + } + } + + private ClientCallContext createContext(@Nullable ClientCallContext context) { + if (context == null) { + return new ClientCallContext(Map.of(), new HashMap<>()); + } + return new ClientCallContext(context.getState(), new HashMap<>(context.getHeaders())); + } + + @Override + public void close() { + delegate.close(); + } + + private static class OpenTelemetryEventConsumer implements Consumer { + + private final Consumer delegate; + private final Tracer tracer; + private final SpanContext context; + private final String name; + + public OpenTelemetryEventConsumer(String name, Consumer delegate, Tracer tracer, SpanContext context) { + this.delegate = delegate; + this.tracer = tracer; + this.context = context; + this.name = name; + } + + @Override + public void accept(StreamingEventKind t) { + SpanBuilder spanBuilder = tracer.spanBuilder(name) + .setSpanKind(SpanKind.CLIENT); + spanBuilder.setAttribute("gen_ai.agent.a2a.streaming-event", t.toString()); + spanBuilder.addLink(context); + Span span = spanBuilder.startSpan(); + try { + delegate.accept(t); + span.setStatus(StatusCode.OK); + } finally { + span.end(); + } + } + } + + private static class OpenTelemetryErrorConsumer implements Consumer { + + private final Consumer delegate; + private final Tracer tracer; + private final SpanContext context; + private final String name; + + public OpenTelemetryErrorConsumer(String name, Consumer delegate, Tracer tracer, SpanContext context) { + this.delegate = delegate; + this.tracer = tracer; + this.context = context; + this.name = name; + } + + @Override + public void accept(Throwable t) { + if (t == null) { + return; + } + SpanBuilder spanBuilder = tracer.spanBuilder(name) + .setSpanKind(SpanKind.CLIENT); + spanBuilder.addLink(context); + Span span = spanBuilder.startSpan(); + try { + span.setStatus(StatusCode.ERROR, t.getMessage()); + delegate.accept(t); + } finally { + span.end(); + } + } + } +} diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java new file mode 100644 index 000000000..2f61bf280 --- /dev/null +++ b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java @@ -0,0 +1,47 @@ +package io.a2a.extras.opentelemetry.client; + +import io.a2a.client.transport.spi.ClientTransport; +import io.a2a.client.transport.spi.ClientTransportConfig; +import io.a2a.client.transport.spi.ClientTransportWrapper; +import io.opentelemetry.api.trace.Tracer; + +/** + * OpenTelemetry client transport wrapper that adds distributed tracing to A2A client calls. + * + *

        This wrapper is automatically discovered via Java's ServiceLoader mechanism. + * To enable tracing, add a {@link Tracer} instance to the transport configuration: + *

        {@code
        + * ClientTransportConfig config = new JSONRPCTransportConfig();
        + * config.setParameters(Map.of(
        + *     OpenTelemetryClientTransportFactory.OTEL_TRACER_KEY,
        + *     openTelemetry.getTracer("my-service"),
        + *     OpenTelemetryClientTransportFactory.OTEL_OPEN_TELEMETRY_KEY,
        + *     openTelemetry
        + * ));
        + * }
        + */ +public class OpenTelemetryClientTransportWrapper implements ClientTransportWrapper { + + /** + * Configuration key for the OpenTelemetry Tracer instance. + * Value must be of type {@link Tracer}. + */ + public static final String OTEL_TRACER_KEY = "io.a2a.extras.opentelemetry.Tracer"; + + @Override + public ClientTransport wrap(ClientTransport transport, ClientTransportConfig config) { + Object tracerObj = config.getParameters().get(OTEL_TRACER_KEY); + if (tracerObj != null && tracerObj instanceof Tracer tracer) { + return new OpenTelemetryClientTransport(transport, tracer); + } + // No tracer configured, return unwrapped transport + return transport; + } + + @Override + public int priority() { + // Observability/tracing should be in the middle priority range + // so it can observe other wrappers but doesn't interfere with security + return 600; + } +} diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java new file mode 100644 index 000000000..0a7d54541 --- /dev/null +++ b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package io.a2a.extras.opentelemetry.client; + +import org.jspecify.annotations.NullMarked; + diff --git a/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper b/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper new file mode 100644 index 000000000..801f7dd3a --- /dev/null +++ b/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper @@ -0,0 +1 @@ +io.a2a.extras.opentelemetry.client.OpenTelemetryClientTransportWrapper diff --git a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java b/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java new file mode 100644 index 000000000..e930c18e1 --- /dev/null +++ b/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java @@ -0,0 +1,489 @@ +package io.a2a.extras.opentelemetry.client; + +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; + +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.A2AClientException; +import io.a2a.spec.AgentCard; +import io.a2a.spec.DeleteTaskPushNotificationConfigParams; +import io.a2a.spec.EventKind; +import io.a2a.spec.GetTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTasksParams; +import io.a2a.spec.Message; +import io.a2a.spec.MessageSendParams; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.TextPart; +import io.a2a.spec.Task; +import io.a2a.spec.TaskIdParams; +import io.a2a.spec.TaskPushNotificationConfig; +import io.a2a.spec.TaskQueryParams; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +import java.util.List; +import java.util.function.Consumer; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import io.a2a.spec.A2AMethods; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class OpenTelemetryClientTransportTest { + + @Mock + private ClientTransport delegate; + + @Mock + private Tracer tracer; + + @Mock + private SpanBuilder spanBuilder; + + @Mock + private Span span; + + @Mock + private Scope scope; + + @Mock + private SpanContext spanContext; + + @Mock + private ClientCallContext context; + + private OpenTelemetryClientTransport transport; + + @BeforeEach + void setUp() { + System.setProperty(EXTRACT_REQUEST_SYS_PROPERTY, "true"); + System.setProperty(EXTRACT_RESPONSE_SYS_PROPERTY, "true"); + when(tracer.spanBuilder(anyString())).thenReturn(spanBuilder); + when(spanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(spanBuilder); + when(spanBuilder.setAttribute(anyString(), anyString())).thenReturn(spanBuilder); + when(spanBuilder.setAttribute(anyString(), anyLong())).thenReturn(spanBuilder); + when(spanBuilder.addLink(any(SpanContext.class))).thenReturn(spanBuilder); + when(spanBuilder.startSpan()).thenReturn(span); + when(span.makeCurrent()).thenReturn(scope); + when(span.getSpanContext()).thenReturn(spanContext); + when(context.getHeaders()).thenReturn(new java.util.HashMap<>()); + + transport = new OpenTelemetryClientTransport(delegate, tracer); + } + + @Test + void testSendMessage_Success() throws A2AClientException { + MessageSendParams request = mock(MessageSendParams.class); + EventKind expectedResult = mock(EventKind.class); + when(request.toString()).thenReturn("request-string"); + when(expectedResult.toString()).thenReturn("response-string"); + when(delegate.sendMessage(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); + + EventKind result = transport.sendMessage(request, context); + + assertEquals(expectedResult, result); + verify(tracer).spanBuilder(A2AMethods.SEND_MESSAGE_METHOD); + verify(spanBuilder).setSpanKind(SpanKind.CLIENT); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setAttribute(GENAI_RESPONSE, "response-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + verify(scope).close(); + } + + @Test + void testSendMessage_NullResponse() throws A2AClientException { + MessageSendParams request = mock(MessageSendParams.class); + when(request.toString()).thenReturn("request-string"); + when(delegate.sendMessage(eq(request), any(ClientCallContext.class))).thenReturn(null); + + EventKind result = transport.sendMessage(request, context); + + assertNull(result); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(spanBuilder, never()).setAttribute(eq(GENAI_RESPONSE), anyString()); + verify(span, never()).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testSendMessage_ThrowsException() throws A2AClientException { + MessageSendParams request = mock(MessageSendParams.class); + when(request.toString()).thenReturn("request-string"); + A2AClientException expectedException = new A2AClientException("Test error"); + when(delegate.sendMessage(eq(request), any(ClientCallContext.class))).thenThrow(expectedException); + + A2AClientException exception = assertThrows(A2AClientException.class, + () -> transport.sendMessage(request, context)); + + assertEquals(expectedException, exception); + verify(span).setStatus(StatusCode.ERROR, "Test error"); + verify(span).end(); + verify(scope).close(); + } + + @Test + void testSendMessageStreaming() throws A2AClientException { + MessageSendParams request = mock(MessageSendParams.class); + when(request.toString()).thenReturn("request-string"); + Consumer eventConsumer = mock(Consumer.class); + Consumer errorConsumer = mock(Consumer.class); + + transport.sendMessageStreaming(request, eventConsumer, errorConsumer, context); + + verify(tracer).spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD); + verify(spanBuilder).setSpanKind(SpanKind.CLIENT); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + + ArgumentCaptor> eventConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> errorConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); + verify(delegate).sendMessageStreaming(eq(request), eventConsumerCaptor.capture(), + errorConsumerCaptor.capture(), any(ClientCallContext.class)); + + assertNotNull(eventConsumerCaptor.getValue()); + assertNotNull(errorConsumerCaptor.getValue()); + } + + @Test + void testGetTask_Success() throws A2AClientException { + TaskQueryParams request = mock(TaskQueryParams.class); + Task expectedResult = mock(Task.class); + when(request.toString()).thenReturn("request-string"); + when(expectedResult.toString()).thenReturn("response-string"); + when(delegate.getTask(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); + + Task result = transport.getTask(request, context); + + assertEquals(expectedResult, result); + verify(tracer).spanBuilder(A2AMethods.GET_TASK_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setAttribute(GENAI_RESPONSE, "response-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testCancelTask_Success() throws A2AClientException { + TaskIdParams request = mock(TaskIdParams.class); + Task expectedResult = mock(Task.class); + when(request.toString()).thenReturn("request-string"); + when(expectedResult.toString()).thenReturn("response-string"); + when(delegate.cancelTask(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); + + Task result = transport.cancelTask(request, context); + + assertEquals(expectedResult, result); + verify(tracer).spanBuilder(A2AMethods.CANCEL_TASK_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setAttribute(GENAI_RESPONSE, "response-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testListTasks_Success() throws A2AClientException { + ListTasksParams request = mock(ListTasksParams.class); + ListTasksResult expectedResult = mock(ListTasksResult.class); + when(request.toString()).thenReturn("request-string"); + when(expectedResult.toString()).thenReturn("response-string"); + when(delegate.listTasks(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); + + ListTasksResult result = transport.listTasks(request, context); + + assertEquals(expectedResult, result); + verify(tracer).spanBuilder(A2AMethods.LIST_TASK_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setAttribute(GENAI_RESPONSE, "response-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testCreateTaskPushNotificationConfiguration_Success() throws A2AClientException { + TaskPushNotificationConfig request = mock(TaskPushNotificationConfig.class); + TaskPushNotificationConfig expectedResult = mock(TaskPushNotificationConfig.class); + when(request.toString()).thenReturn("request-string"); + when(expectedResult.toString()).thenReturn("response-string"); + when(delegate.createTaskPushNotificationConfiguration(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); + + TaskPushNotificationConfig result = transport.createTaskPushNotificationConfiguration(request, context); + + assertEquals(expectedResult, result); + verify(tracer).spanBuilder(A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setAttribute(GENAI_RESPONSE, "response-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testGetTaskPushNotificationConfiguration_Success() throws A2AClientException { + GetTaskPushNotificationConfigParams request = mock(GetTaskPushNotificationConfigParams.class); + TaskPushNotificationConfig expectedResult = mock(TaskPushNotificationConfig.class); + when(request.toString()).thenReturn("request-string"); + when(expectedResult.toString()).thenReturn("response-string"); + when(delegate.getTaskPushNotificationConfiguration(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); + + TaskPushNotificationConfig result = transport.getTaskPushNotificationConfiguration(request, context); + + assertEquals(expectedResult, result); + verify(tracer).spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setAttribute(GENAI_RESPONSE, "response-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testListTaskPushNotificationConfigurations_Success() throws A2AClientException { + ListTaskPushNotificationConfigParams request = mock(ListTaskPushNotificationConfigParams.class); + TaskPushNotificationConfig config1 = mock(TaskPushNotificationConfig.class); + TaskPushNotificationConfig config2 = mock(TaskPushNotificationConfig.class); + when(config1.toString()).thenReturn("config1"); + when(config2.toString()).thenReturn("config2"); + ListTaskPushNotificationConfigResult expectedResult = new ListTaskPushNotificationConfigResult(List.of(config1, config2)); + when(request.toString()).thenReturn("request-string"); + when(delegate.listTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); + + ListTaskPushNotificationConfigResult result = transport.listTaskPushNotificationConfigurations(request, context); + + assertEquals(expectedResult, result); + verify(tracer).spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + verify(spanBuilder).setSpanKind(SpanKind.CLIENT); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setAttribute(GENAI_RESPONSE, "config1,config2"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testDeleteTaskPushNotificationConfigurations_Success() throws A2AClientException { + DeleteTaskPushNotificationConfigParams request = mock(DeleteTaskPushNotificationConfigParams.class); + when(request.toString()).thenReturn("request-string"); + doNothing().when(delegate).deleteTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class)); + + transport.deleteTaskPushNotificationConfigurations(request, context); + + verify(tracer).spanBuilder(A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + verify(delegate).deleteTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class)); + } + + @Test + void testSubscribeToTask() throws A2AClientException { + TaskIdParams request = mock(TaskIdParams.class); + when(request.toString()).thenReturn("request-string"); + Consumer eventConsumer = mock(Consumer.class); + Consumer errorConsumer = mock(Consumer.class); + + transport.subscribeToTask(request, eventConsumer, errorConsumer, context); + + verify(tracer).spanBuilder(A2AMethods.SUBSCRIBE_TO_TASK_METHOD); + verify(spanBuilder).setSpanKind(SpanKind.CLIENT); + verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + + ArgumentCaptor> eventConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> errorConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); + verify(delegate).subscribeToTask(eq(request), eventConsumerCaptor.capture(), + errorConsumerCaptor.capture(), any(ClientCallContext.class)); + + assertNotNull(eventConsumerCaptor.getValue()); + assertNotNull(errorConsumerCaptor.getValue()); + } + + @Test + void testGetAgentCard_Success() throws A2AClientException { + AgentCard expectedResult = mock(AgentCard.class); + when(expectedResult.toString()).thenReturn("response-string"); + when(delegate.getExtendedAgentCard(any(ClientCallContext.class))).thenReturn(expectedResult); + + AgentCard result = transport.getExtendedAgentCard(context); + + assertEquals(expectedResult, result); + verify(tracer).spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); + verify(spanBuilder).setSpanKind(SpanKind.CLIENT); + verify(span).setAttribute(GENAI_RESPONSE, "response-string"); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testGetAgentCard_NullResponse() throws A2AClientException { + when(delegate.getExtendedAgentCard(any(ClientCallContext.class))).thenReturn(null); + + AgentCard result = transport.getExtendedAgentCard(context); + + assertNull(result); + verify(tracer).spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); + verify(spanBuilder).setSpanKind(SpanKind.CLIENT); + verify(span, never()).setAttribute(eq(GENAI_RESPONSE), anyString()); + verify(span, never()).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void testClose() { + transport.close(); + verify(delegate).close(); + } + + @Test + void testEventConsumer_ThroughSendMessageStreaming() throws A2AClientException { + MessageSendParams request = mock(MessageSendParams.class); + when(request.toString()).thenReturn("request-string"); + + SpanBuilder eventSpanBuilder = mock(SpanBuilder.class); + Span eventSpan = mock(Span.class); + when(tracer.spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-event")).thenReturn(eventSpanBuilder); + when(eventSpanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(eventSpanBuilder); + when(eventSpanBuilder.setAttribute(anyString(), anyString())).thenReturn(eventSpanBuilder); + when(eventSpanBuilder.addLink(any(SpanContext.class))).thenReturn(eventSpanBuilder); + when(eventSpanBuilder.startSpan()).thenReturn(eventSpan); + + ArgumentCaptor> eventConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); + Consumer originalConsumer = mock(Consumer.class); + + transport.sendMessageStreaming(request, originalConsumer, mock(Consumer.class), context); + + verify(delegate).sendMessageStreaming(eq(request), eventConsumerCaptor.capture(), any(Consumer.class), any(ClientCallContext.class)); + + Message event = Message.builder() + .messageId("test-id") + .taskId("task-id") + .role(Message.Role.USER) + .parts(List.of(new TextPart("test content"))) + .build(); + + eventConsumerCaptor.getValue().accept(event); + + verify(tracer).spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-event"); + verify(eventSpan).setStatus(StatusCode.OK); + verify(eventSpan).end(); + verify(originalConsumer).accept(event); + } + + @Test + void testErrorConsumer_ThroughSendMessageStreaming() throws A2AClientException { + MessageSendParams request = mock(MessageSendParams.class); + when(request.toString()).thenReturn("request-string"); + + SpanBuilder errorSpanBuilder = mock(SpanBuilder.class); + Span errorSpan = mock(Span.class); + when(tracer.spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-error")).thenReturn(errorSpanBuilder); + when(errorSpanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(errorSpanBuilder); + when(errorSpanBuilder.addLink(any(SpanContext.class))).thenReturn(errorSpanBuilder); + when(errorSpanBuilder.startSpan()).thenReturn(errorSpan); + + ArgumentCaptor> errorConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); + Consumer originalConsumer = mock(Consumer.class); + + transport.sendMessageStreaming(request, mock(Consumer.class), originalConsumer, context); + + verify(delegate).sendMessageStreaming(eq(request), any(Consumer.class), errorConsumerCaptor.capture(), any(ClientCallContext.class)); + + Throwable error = new RuntimeException("Test error"); + + errorConsumerCaptor.getValue().accept(error); + + verify(tracer).spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-error"); + verify(errorSpan).setStatus(StatusCode.ERROR, "Test error"); + verify(errorSpan).end(); + verify(originalConsumer).accept(error); + } + + @Test + void testErrorConsumer_WithNullThrowable() throws A2AClientException { + MessageSendParams request = mock(MessageSendParams.class); + when(request.toString()).thenReturn("request-string"); + + ArgumentCaptor> errorConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); + Consumer originalConsumer = mock(Consumer.class); + + transport.sendMessageStreaming(request, mock(Consumer.class), originalConsumer, context); + + verify(delegate).sendMessageStreaming(eq(request), any(Consumer.class), errorConsumerCaptor.capture(), any(ClientCallContext.class)); + + errorConsumerCaptor.getValue().accept(null); + + verify(originalConsumer, never()).accept(any()); + } + + @Test + void testDeleteTaskPushNotificationConfigurations_ThrowsException() throws A2AClientException { + DeleteTaskPushNotificationConfigParams request = mock(DeleteTaskPushNotificationConfigParams.class); + when(request.toString()).thenReturn("request-string"); + A2AClientException expectedException = new A2AClientException("Delete failed"); + doThrow(expectedException).when(delegate).deleteTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class)); + + A2AClientException exception = assertThrows(A2AClientException.class, + () -> transport.deleteTaskPushNotificationConfigurations(request, context)); + + assertEquals(expectedException, exception); + verify(span).setStatus(StatusCode.ERROR, "Delete failed"); + verify(span).end(); + } + + @Test + void testResubscribe_ThrowsException() throws A2AClientException { + TaskIdParams request = mock(TaskIdParams.class); + when(request.toString()).thenReturn("request-string"); + Consumer eventConsumer = mock(Consumer.class); + Consumer errorConsumer = mock(Consumer.class); + A2AClientException expectedException = new A2AClientException("Resubscribe failed"); + doThrow(expectedException).when(delegate).subscribeToTask(any(TaskIdParams.class), any(Consumer.class), + any(Consumer.class), any(ClientCallContext.class)); + + A2AClientException exception = assertThrows(A2AClientException.class, + () -> transport.subscribeToTask(request, eventConsumer, errorConsumer, context)); + + assertEquals(expectedException, exception); + verify(span).setStatus(StatusCode.ERROR, "Resubscribe failed"); + verify(span).end(); + } + + @Test + void testSendMessageStreaming_ThrowsException() throws A2AClientException { + MessageSendParams request = mock(MessageSendParams.class); + when(request.toString()).thenReturn("request-string"); + Consumer eventConsumer = mock(Consumer.class); + Consumer errorConsumer = mock(Consumer.class); + A2AClientException expectedException = new A2AClientException("Streaming failed"); + doThrow(expectedException).when(delegate).sendMessageStreaming(any(MessageSendParams.class), any(Consumer.class), + any(Consumer.class), any(ClientCallContext.class)); + + A2AClientException exception = assertThrows(A2AClientException.class, + () -> transport.sendMessageStreaming(request, eventConsumer, errorConsumer, context)); + + assertEquals(expectedException, exception); + verify(span).setStatus(StatusCode.ERROR, "Streaming failed"); + verify(span).end(); + } +} diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml new file mode 100644 index 000000000..d21655202 --- /dev/null +++ b/extras/opentelemetry/common/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-parent + 1.0.0.Alpha2-SNAPSHOT + + + a2a-java-sdk-opentelemetry-common + + A2A Java SDK :: Extras :: Opentelemetry :: Common + Common OpenTelemetry utilities for A2A Java SDK + + diff --git a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java b/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java new file mode 100644 index 000000000..c2821d8a7 --- /dev/null +++ b/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java @@ -0,0 +1,23 @@ +package io.a2a.extras.opentelemetry; + +public interface A2AObservabilityNames { + + String EXTRACT_REQUEST_SYS_PROPERTY = "io.a2a.server.extract.request"; + String EXTRACT_RESPONSE_SYS_PROPERTY = "io.a2a.server.extract.response"; + + String ERROR_TYPE = "error.type"; + + String GENAI_PREFIX = "gen_ai.agent.a2a"; + String GENAI_CONFIG_ID = GENAI_PREFIX + ".config_id"; + String GENAI_CONTEXT_ID = GENAI_PREFIX + ".context_id"; //gen_ai.conversation.id + String GENAI_EXTENSIONS = GENAI_PREFIX + ".extensions"; + String GENAI_MESSAGE_ID = GENAI_PREFIX + ".message_id"; + String GENAI_OPERATION_NAME = GENAI_PREFIX + ".operation.name"; //gen_ai.agent.operation.name ? + String GENAI_PARTS_NUMBER = GENAI_PREFIX + ".parts.number"; + String GENAI_PROTOCOL = GENAI_PREFIX + ".protocol"; + String GENAI_STATUS = GENAI_PREFIX + ".status"; + String GENAI_REQUEST = GENAI_PREFIX + ".request"; //gen_ai.input.messages ? + String GENAI_RESPONSE = GENAI_PREFIX + ".response"; // gen_ai.output.messages ? + String GENAI_ROLE = GENAI_PREFIX + ".role"; + String GENAI_TASK_ID = GENAI_PREFIX + ".task_id"; +} diff --git a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java b/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java new file mode 100644 index 000000000..8e7125631 --- /dev/null +++ b/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java @@ -0,0 +1,8 @@ +/** + * Common OpenTelemetry utilities and shared components for A2A Java SDK. + *

        + * This package contains common utilities, constants, and helper classes + * used across both client and server OpenTelemetry integrations. + */ +@org.jspecify.annotations.NullMarked +package io.a2a.extras.opentelemetry; diff --git a/extras/opentelemetry/integration-tests/README.md b/extras/opentelemetry/integration-tests/README.md new file mode 100644 index 000000000..a66fe8f6c --- /dev/null +++ b/extras/opentelemetry/integration-tests/README.md @@ -0,0 +1,160 @@ +# OpenTelemetry Integration Tests (Quarkus-based) + +## Overview + +This module provides **Quarkus-based integration tests** for OpenTelemetry tracing in the A2A Java SDK, similar to the approach used in the [Quarkus OpenTelemetry quickstart](https://github.com/quarkusio/quarkus/tree/main/integration-tests/opentelemetry-quickstart). + +Unlike the previous mock-based tests, these are **real integration tests** that: +- Start an actual Quarkus application +- Expose a REST API with A2A agent endpoints +- Make real HTTP requests +- Validate that OpenTelemetry spans are created correctly + +## Architecture + +### Components + +1. **SimpleAgent** - A basic A2A agent implementation for testing + - Implements all RequestHandler methods + - Stores tasks in memory + - Provides simple echo responses for messages + +2. **AgentResource** - JAX-RS REST resource + - Exposes HTTP endpoints (`/a2a/tasks`, `/a2a/messages`, etc.) + - Delegates to the RequestHandler + - Creates ServerCallContext for each request + +3. **InstrumentedRequestHandler** - CDI Alternative + - Wraps SimpleAgent with OpenTelemetry decorator + - Delegates to the OpenTelemetry decorator for span creation + - Ensures spans are created for each operation + +4. **OpenTelemetryProducer** - CDI bean producer + - Creates the Tracer from Quarkus OpenTelemetry + - Produces the OpenTelemetryRequestHandlerDecorator (CDI decorator) + - Integrates with Quarkus OpenTelemetry extension + +## Test Strategy + +### Functional Tests (`OpenTelemetryIntegrationTest`) +- Use `@QuarkusTest` annotation +- Make real HTTP requests using REST Assured +- Verify HTTP responses are correct +- Ensure the application behaves correctly end-to-end + +### Tracing Tests (`OpenTelemetryTracingTest`) +- Use `InMemorySpanExporter` to capture spans +- Verify that HTTP requests create OpenTelemetry spans +- Validate span names, kinds (CLIENT/SERVER), and status codes +- Check that spans are properly ended + +## Current Status + +### ✅ Completed +- Project structure and POM configuration +- Quarkus dependencies and plugins (including opentelemetry-sdk-testing) +- SimpleAgentExecutor following reference module pattern +- TestAgentCardProducer with proper JSONRPC interface +- InMemorySpanExporter producer for span validation +- OpenTelemetryIntegrationTest using Client API +- Tests compile and run (service loader issues resolved) + +### 🔨 In Progress / Known Issues + +1. **Test Execution Timeouts** + - Tests are timing out during message send operations + - Error: "Timeout waiting for consumption to complete for task test-task-1" + - Likely a configuration issue between client (non-streaming) and server (streaming capable) + - Need to investigate JSONRPC transport configuration + +2. **Span Validation** + - InMemorySpanExporter is configured but needs verification + - Some tests are not finding expected spans + - May need to configure span processor to route to InMemorySpanExporter + +## Running the Tests + +### Prerequisites +```bash +# Build all A2A SDK modules first +mvn clean install -DskipTests +``` + +### Run Integration Tests +```bash +# From the integration-tests directory +mvn clean verify + +# Or from the root +mvn verify -pl extras/opentelemetry/integration-tests -am +``` + +### Run Specific Test +```bash +mvn test -Dtest=OpenTelemetryIntegrationTest +``` + +## Configuration + +### Application Properties +- `src/main/resources/application.properties` - Runtime configuration +- `src/test/resources/application.properties` - Test-specific configuration + +Key settings: +```properties +# OpenTelemetry +quarkus.otel.sdk.disabled=false +quarkus.otel.traces.enabled=true +quarkus.otel.service.name=a2a-opentelemetry-integration-test + +# Test mode: use in-memory exporter +quarkus.otel.traces.exporter=none +``` + +### beans.xml +Located at `src/main/resources/META-INF/beans.xml`: +- Enables CDI bean discovery +- Configures alternatives (InstrumentedRequestHandler) + +## Next Steps + +To complete this integration test module: + +1. **Resolve CDI ambiguity** + - Add `@Named` or custom qualifier to SimpleAgent + - Or exclude DefaultRequestHandler from test classpath + - Or use `@Alternative` more effectively + +2. **Configure span exporter** + - Properly wire InMemorySpanExporter into Quarkus OpenTelemetry + - May need custom OTel SDK configuration + +3. **Add more test scenarios** + - Test error handling and error spans + - Test streaming operations + - Test context propagation across services + - Test span attributes and metadata + +4. **Performance testing** (optional) + - Measure overhead of OpenTelemetry instrumentation + - Verify spans don't impact performance significantly + +## Comparison with Quarkus Quickstart + +This implementation follows the same patterns as the Quarkus OpenTelemetry quickstart: +- ✅ Uses `@QuarkusTest` for integration tests +- ✅ Uses REST Assured for HTTP testing +- ✅ Integrates with Quarkus OpenTelemetry extension +- ✅ Uses in-memory span exporter for validation +- ✅ Tests actual HTTP requests, not mocks + +Unlike the quickstart which is a standalone app, this module: +- Tests A2A SDK-specific functionality +- Validates OpenTelemetry CDI decorator integration +- Focuses on A2A protocol operations (tasks, messages, etc.) + +## References + +- [Quarkus OpenTelemetry Guide](https://quarkus.io/guides/opentelemetry) +- [Quarkus OpenTelemetry Quickstart](https://github.com/quarkusio/quarkus/tree/main/integration-tests/opentelemetry-quickstart) +- [OpenTelemetry Java Documentation](https://opentelemetry.io/docs/languages/java/) diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml new file mode 100644 index 000000000..6d2b4734a --- /dev/null +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -0,0 +1,136 @@ + + + 4.0.0 + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-parent + 1.0.0.Alpha2-SNAPSHOT + + + a2a-java-sdk-opentelemetry-integration-tests + + A2A Java SDK :: Extras :: OpenTelemetry :: Integration Tests + Quarkus-based integration tests for OpenTelemetry support in A2A Java SDK + + + + + ${project.groupId} + a2a-java-sdk-client + + + ${project.groupId} + a2a-java-sdk-reference-jsonrpc + + + ${project.groupId} + a2a-java-sdk-opentelemetry-server + + + ${project.groupId} + a2a-java-sdk-opentelemetry-client + + + + + io.quarkus + quarkus-opentelemetry + + + + + io.quarkus + quarkus-reactive-routes + + + + + jakarta.enterprise + jakarta.enterprise.cdi-api + provided + + + + + com.google.code.gson + gson + + + + + io.quarkus + quarkus-junit5 + test + + + io.opentelemetry + opentelemetry-sdk-testing + + + io.rest-assured + rest-assured + test + + + org.awaitility + awaitility + test + + + + + + + io.quarkus + quarkus-maven-plugin + true + + + + build + generate-code + generate-code-tests + + + + + --add-opens=java.base/java.lang=ALL-UNNAMED + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.jboss.logmanager.LogManager + ${maven.home} + + --add-opens java.base/java.lang=ALL-UNNAMED + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + + + org.jboss.logmanager.LogManager + ${maven.home} + + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java new file mode 100644 index 000000000..f6f84f6e1 --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java @@ -0,0 +1,228 @@ +package io.a2a.extras.opentelemetry.it; + + + +import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.a2a.jsonrpc.common.json.JsonUtil; +import io.a2a.spec.Task; +import io.a2a.spec.TaskArtifactUpdateEvent; +import io.a2a.spec.TaskStatusUpdateEvent; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.quarkus.vertx.web.Body; +import io.quarkus.vertx.web.Param; +import io.quarkus.vertx.web.Route; +import io.vertx.ext.web.RoutingContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Test routes for OpenTelemetry integration testing. + * Exposes test utilities via REST endpoints. + */ +@Singleton +public class A2ATestRoutes { + + private static final String APPLICATION_JSON = "application/json"; + private static final String TEXT_PLAIN = "text/plain"; + private static final Gson gson = new GsonBuilder().create(); + + @Inject + TestUtilsBean testUtilsBean; + @Inject + InMemorySpanExporter inMemorySpanExporter; + + @Inject + Tracer tracer; + + @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + public void saveTask(@Body String body, RoutingContext rc) { + try { + Task task = JsonUtil.fromJson(body, Task.class); + testUtilsBean.saveTask(task); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + public void getTask(@Param String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(JsonUtil.toJson(task)); + + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) + public void deleteTask(@Param String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.deleteTask(taskId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) + public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { + try { + testUtilsBean.ensureQueue(taskId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) + public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + try { + TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) + public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + try { + TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) + public void getChildQueueCount(@Param String taskId, RoutingContext rc) { + int count = testUtilsBean.getChildQueueCount(taskId); + rc.response() + .setStatusCode(200) + .end(String.valueOf(count)); + } + + @Route(path = "/hello", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) + public void hello(RoutingContext rc) { + Span span = tracer.spanBuilder("hello").startSpan(); + try (Scope scope = span.makeCurrent()) { + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, TEXT_PLAIN) + .end("Hello from Quarkus REST"); + } finally { + span.end(); + } + } + + @Route(path = "/export", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}) + public void exportSpans(@Param String taskId, RoutingContext rc) { + List spans = inMemorySpanExporter.getFinishedSpanItems() + .stream() + .filter(sd -> !sd.getName().contains("export") && !sd.getName().contains("reset")) + .collect(Collectors.toList()); + String json = gson.toJson(serialize(spans)); + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(json); + } + + private JsonElement serialize(List spanDatas) { + JsonArray spans = new JsonArray(spanDatas.size()); + for (SpanData spanData : spanDatas) { + JsonObject jsonObject = new JsonObject(); + + jsonObject.addProperty("spanId", spanData.getSpanId()); + jsonObject.addProperty("traceId", spanData.getTraceId()); + jsonObject.addProperty("name", spanData.getName()); + jsonObject.addProperty("kind", spanData.getKind().name()); + jsonObject.addProperty("ended", spanData.hasEnded()); + + jsonObject.addProperty("parentSpanId", spanData.getParentSpanContext().getSpanId()); + jsonObject.addProperty("parent_spanId", spanData.getParentSpanContext().getSpanId()); + jsonObject.addProperty("parent_traceId", spanData.getParentSpanContext().getTraceId()); + jsonObject.addProperty("parent_remote", spanData.getParentSpanContext().isRemote()); + jsonObject.addProperty("parent_valid", spanData.getParentSpanContext().isValid()); + + spanData.getAttributes().forEach((k, v) -> { + jsonObject.addProperty("attr_" + k.getKey(), v.toString()); + }); + + spanData.getResource().getAttributes().forEach((k, v) -> { + jsonObject.addProperty("resource_" + k.getKey(), v.toString()); + }); + spans.add(jsonObject); + } + + return spans; + } + + @Route(path = "/reset", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) + public void reset(@Param String taskId, RoutingContext rc) { + inMemorySpanExporter.reset(); + rc.response().setStatusCode(200).end(); + } + + private void errorResponse(Throwable t, RoutingContext rc) { + t.printStackTrace(); + rc.response() + .setStatusCode(500) + .putHeader(CONTENT_TYPE, TEXT_PLAIN) + .end(); + } + + @ApplicationScoped + static class InMemorySpanExporterProducer { + + @Produces + @Singleton + InMemorySpanExporter inMemorySpanExporter() { + return InMemorySpanExporter.create(); + } + } +} diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java new file mode 100644 index 000000000..6d33dd89c --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java @@ -0,0 +1,41 @@ +package io.a2a.extras.opentelemetry.it; + +import io.a2a.A2A; +import io.a2a.server.agentexecution.AgentExecutor; +import io.a2a.server.agentexecution.RequestContext; +import io.a2a.server.tasks.AgentEmitter; +import io.a2a.spec.A2AError; +import io.a2a.spec.TextPart; +import jakarta.enterprise.context.ApplicationScoped; + +/** + * Simple AgentExecutor for integration testing. + * Echoes back the user's message and completes the task immediately. + */ +@ApplicationScoped +public class SimpleAgentExecutor implements AgentExecutor { + + @Override + public void execute(RequestContext context, AgentEmitter emitter) throws A2AError { + // If task doesn't exist, create it + if (context.getTask() == null) { + emitter.submit(); + } + + // Get the user's message + String userText = context.getMessage().parts().stream() + .filter(part -> part instanceof TextPart) + .map(part -> ((TextPart) part).text()) + .findFirst() + .orElse(""); + + // Echo it back + String response = "Echo: " + userText; + emitter.complete(A2A.toAgentMessage(response)); + } + + @Override + public void cancel(RequestContext context, AgentEmitter emitter) throws A2AError { + emitter.cancel(); + } +} diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java new file mode 100644 index 000000000..373169fac --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java @@ -0,0 +1,47 @@ +package io.a2a.extras.opentelemetry.it; + +import io.a2a.server.PublicAgentCard; +import io.a2a.spec.AgentCapabilities; +import io.a2a.spec.AgentCard; +import io.a2a.spec.AgentInterface; +import io.a2a.spec.AgentSkill; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import java.util.Collections; +import java.util.List; + + +/** + * Produces the AgentCard for integration testing. + */ +@ApplicationScoped +public class TestAgentCardProducer { + + @Produces + @PublicAgentCard + public AgentCard agentCard() { + return AgentCard.builder() + .name("OpenTelemetry Test Agent") + .description("Test agent for OpenTelemetry integration tests") + .supportedInterfaces(Collections.singletonList( + new AgentInterface("JSONRPC", "http://localhost:8081") + )) + .version("1.0.0-TEST") + .documentationUrl("http://example.com/test") + .capabilities(AgentCapabilities.builder() + .streaming(true) + .pushNotifications(false) + .build()) + .defaultInputModes(Collections.singletonList("text")) + .defaultOutputModes(Collections.singletonList("text")) + .skills(Collections.singletonList(AgentSkill.builder() + .id("echo") + .name("Echo") + .description("Echoes back the user's message") + .tags(Collections.singletonList("test")) + .examples(List.of("hello", "test message")) + .build())) + .build(); + } +} diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java new file mode 100644 index 000000000..594063171 --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java @@ -0,0 +1,46 @@ +package io.a2a.extras.opentelemetry.it; + +import io.a2a.server.events.QueueManager; +import io.a2a.server.tasks.TaskStore; +import io.a2a.spec.Event; +import io.a2a.spec.Task; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +/** + * Test utilities for OpenTelemetry integration tests. + * Allows direct manipulation of tasks and queues for testing. + */ +@ApplicationScoped +public class TestUtilsBean { + + @Inject + TaskStore taskStore; + + @Inject + QueueManager queueManager; + + public void saveTask(Task task) { + taskStore.save(task, false); + } + + public Task getTask(String taskId) { + return taskStore.get(taskId); + } + + public void deleteTask(String taskId) { + taskStore.delete(taskId); + } + + public void ensureQueue(String taskId) { + queueManager.createOrTap(taskId); + } + + public void enqueueEvent(String taskId, Event event) { + queueManager.get(taskId).enqueueEvent(event); + } + + public int getChildQueueCount(String taskId) { + return queueManager.getActiveChildQueueCount(taskId); + } +} diff --git a/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml b/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..5badbc80d --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml @@ -0,0 +1,9 @@ + + + + io.a2a.extras.opentelemetry.it.InstrumentedRequestHandler + + diff --git a/extras/opentelemetry/integration-tests/src/main/resources/application.properties b/extras/opentelemetry/integration-tests/src/main/resources/application.properties new file mode 100644 index 000000000..ca0d2c4fd --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/main/resources/application.properties @@ -0,0 +1,28 @@ +# Quarkus configuration +quarkus.application.name=a2a-otel-test + +# HTTP configuration +quarkus.http.port=8081 +quarkus.http.test-port=8081 + +# OpenTelemetry configuration +quarkus.otel.sdk.disabled=false +quarkus.otel.traces.enabled=true +quarkus.otel.metrics.enabled=false +quarkus.otel.logs.enabled=false + +quarkus.otel.instrument.vertx-http=false + +quarkus.otel.bsp.schedule.delay=0 +quarkus.otel.bsp.export.timeout=5s + +# Service name +quarkus.otel.service.name=a2a-opentelemetry-integration-test + +# Propagators +quarkus.otel.propagators=tracecontext + +# Logging +quarkus.log.level=INFO +quarkus.log.category."io.a2a".level=DEBUG +quarkus.log.category."io.opentelemetry".level=DEBUG diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java new file mode 100644 index 000000000..69304e10e --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java @@ -0,0 +1,20 @@ +package io.a2a.extras.opentelemetry.it; + +import static io.restassured.RestAssured.get; + +import java.util.List; +import java.util.Map; + +import io.restassured.common.mapper.TypeRef; + +public class BaseTest { + + protected List> getSpans() { + return get("/export").body().as(new TypeRef<>() { + }); + } + + protected void buildGlobalTelemetryInstance() { + // Do nothing in JVM mode + } +} \ No newline at end of file diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java new file mode 100644 index 000000000..2171b2fc1 --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java @@ -0,0 +1,301 @@ +package io.a2a.extras.opentelemetry.it; + +import static io.quarkus.vertx.web.ReactiveRoutes.APPLICATION_JSON; +import static io.restassured.RestAssured.given; +import static java.net.HttpURLConnection.HTTP_OK; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.*; + +import io.a2a.A2A; +import io.a2a.client.Client; +import io.a2a.client.config.ClientConfig; +import io.a2a.client.transport.jsonrpc.JSONRPCTransport; +import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import io.a2a.jsonrpc.common.json.JsonUtil; +import io.a2a.spec.*; +import io.opentelemetry.api.trace.SpanKind; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Abstract base class for OpenTelemetry A2A integration tests. + * Contains common test logic shared between unit and integration test modes. + */ +abstract class OpenTelemetryA2ABaseTest extends BaseTest { + + protected Client client; + protected final int serverPort = 8081; + + @BeforeEach + void setUp() throws A2AClientException { + ClientConfig clientConfig = new ClientConfig.Builder() + .setStreaming(false) + .build(); + + client = Client.builder(A2A.getAgentCard("http://localhost:" + serverPort)) + .clientConfig(clientConfig) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) + .build(); + } + + @BeforeEach + void reset() { + await().atMost(5, SECONDS).until(() -> { + List> spans = getSpans(); + if (spans.isEmpty()) { + return true; + } else { + given().get("/reset").then().statusCode(HTTP_OK); + return false; + } + }); + } + + @Test + void testGetTaskCreatesSpans() throws Exception { + String taskId = "span-test-task-1"; + String contextId = "span-test-ctx-1"; + + Task task = Task.builder() + .id(taskId) + .contextId(contextId) + .status(new TaskStatus(TaskState.COMPLETED)) + .history(Collections.emptyList()) + .artifacts(Collections.emptyList()) + .build(); + + saveTaskInTaskStore(task); + reset(); + + try { + Task retrievedTask = client.getTask(new TaskQueryParams(taskId), null); + + assertNotNull(retrievedTask); + assertEquals(taskId, retrievedTask.id()); + + Thread.sleep(5000); + + List> spans = getSpans(); + System.out.println("We have created spans " + spans); + assertFalse(spans.isEmpty(), "Should have created spans for getTask operation"); + + long serverSpanCount = spans.stream() + .filter(span -> SpanKind.valueOf((span.get("kind").toString())) == SpanKind.SERVER) + .count(); + assertTrue(serverSpanCount > 0, "Should have at least one SERVER span"); + + Map serverSpan = spans.stream() + .filter(span -> SpanKind.valueOf(span.get("kind").toString()) == SpanKind.SERVER) + .filter(span -> "GetTask".equals(span.get("name"))) + .findFirst() + .orElseThrow(() -> new AssertionError("No SERVER span found for GetTask")); + + assertEquals("GetTask", serverSpan.get("attr_gen_ai.agent.a2a.operation.name"), + "Operation name attribute should be set"); + assertEquals(taskId, serverSpan.get("attr_gen_ai.agent.a2a.task_id"), + "Task ID attribute should be set"); + + } finally { + deleteTaskInTaskStore(taskId); + } + } + + @Test + void testListTasksCreatesSpans() throws Exception { + reset(); + + ListTasksParams params = new ListTasksParams( + null, null, null, null, null, null, null, "" + ); + + io.a2a.jsonrpc.common.wrappers.ListTasksResult result = client.listTasks(params, null); + + assertNotNull(result); + + Thread.sleep(5000); + + List> spans = getSpans(); + System.out.println("We have created spans " + spans); + assertFalse(spans.isEmpty(), "Should have created spans for listTasks"); + + Map serverSpan = spans.stream() + .filter(span -> SpanKind.valueOf(span.get("kind").toString()) == SpanKind.SERVER) + .filter(span -> "ListTasks".equals(span.get("name"))) + .findFirst() + .orElseThrow(() -> new AssertionError("No SERVER span found for ListTasks")); + + assertEquals("ListTasks", serverSpan.get("attr_gen_ai.agent.a2a.operation.name"), + "Operation name attribute should be set"); + } + + @Test + void testCancelTaskCreatesSpans() throws Exception { + String taskId = "cancel-test-task-1"; + String contextId = "cancel-test-ctx-1"; + + Task task = Task.builder() + .id(taskId) + .contextId(contextId) + .status(new TaskStatus(TaskState.WORKING)) + .history(Collections.emptyList()) + .artifacts(Collections.emptyList()) + .build(); + + saveTaskInTaskStore(task); + ensureQueueForTask(taskId); + reset(); + + try { + Task cancelledTask = client.cancelTask(new TaskIdParams(taskId), null); + + assertNotNull(cancelledTask); + assertEquals(TaskState.CANCELED, cancelledTask.status().state()); + + Thread.sleep(5000); + + List> spans = getSpans(); + System.out.println("We have created spans " + spans); + assertFalse(spans.isEmpty(), "Should have created spans for cancelTask"); + + Map serverSpan = spans.stream() + .filter(span -> SpanKind.valueOf(span.get("kind").toString()) == SpanKind.SERVER) + .filter(span -> "CancelTask".equals(span.get("name"))) + .findFirst() + .orElseThrow(() -> new AssertionError("No SERVER span found for CancelTask")); + + assertEquals("CancelTask", serverSpan.get("attr_gen_ai.agent.a2a.operation.name"), + "Operation name attribute should be set"); + assertEquals(taskId, serverSpan.get("attr_gen_ai.agent.a2a.task_id"), + "Task ID attribute should be set"); + + } finally { + deleteTaskInTaskStore(taskId); + } + } + + @Test + void testSpanAttributes() throws Exception { + String taskId = "attr-test-task-1"; + String contextId = "attr-test-ctx-1"; + + Task task = Task.builder() + .id(taskId) + .contextId(contextId) + .status(new TaskStatus(TaskState.COMPLETED)) + .history(Collections.emptyList()) + .artifacts(Collections.emptyList()) + .build(); + + saveTaskInTaskStore(task); + reset(); + + try { + client.getTask(new TaskQueryParams(taskId), null); + + Thread.sleep(5000); + + List> spans = getSpans(); + System.out.println("We have created spans " + spans); + assertFalse(spans.isEmpty()); + + Map serverSpan = spans.stream() + .filter(span -> SpanKind.valueOf(span.get("kind").toString()) == SpanKind.SERVER) + .filter(span -> "GetTask".equals(span.get("name"))) + .findFirst() + .orElseThrow(() -> new AssertionError("No SERVER span found for GetTask")); + + assertNotNull(serverSpan.get("spanId"), "Span should have a span ID"); + assertNotNull(serverSpan.get("traceId"), "Span should have a trace ID"); + assertEquals("GetTask", serverSpan.get("name"), "Span name should be GetTask"); + assertEquals("SERVER", serverSpan.get("kind"), "Span kind should be SERVER"); + assertEquals(Boolean.TRUE, serverSpan.get("ended"), "Span should be ended"); + + assertEquals("GetTask", serverSpan.get("attr_gen_ai.agent.a2a.operation.name"), + "Operation name attribute should be set"); + assertEquals(taskId, serverSpan.get("attr_gen_ai.agent.a2a.task_id"), + "Task ID attribute should be set"); + + assertNotNull(serverSpan.get("resource_service.name"), + "Service name resource attribute should be set"); + System.out.println("Service name: " + serverSpan.get("resource_service.name")); + + assertNotNull(serverSpan.get("parentSpanId"), "Span should have parent span ID field"); + + } finally { + deleteTaskInTaskStore(taskId); + } + } + + protected void saveTaskInTaskStore(Task task) throws Exception { + HttpClient httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task")) + .POST(HttpRequest.BodyPublishers.ofString(JsonUtil.toJson(task))) + .header("Content-Type", APPLICATION_JSON) + .build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(String.format("Saving task failed! Status: %d, Body: %s", response.statusCode(), response.body())); + } + } + + protected Task getTaskFromTaskStore(String taskId) throws Exception { + HttpClient httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task/" + taskId)) + .GET() + .build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() == 404) { + return null; + } + if (response.statusCode() != 200) { + throw new RuntimeException(String.format("Getting task failed! Status: %d, Body: %s", response.statusCode(), response.body())); + } + return JsonUtil.fromJson(response.body(), Task.class); + } + + protected void deleteTaskInTaskStore(String taskId) throws Exception { + HttpClient httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(("http://localhost:" + serverPort + "/test/task/" + taskId))) + .DELETE() + .build(); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(response.statusCode() + ": Deleting task failed!" + response.body()); + } + } + + protected void ensureQueueForTask(String taskId) throws Exception { + HttpClient httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/queue/ensure/" + taskId)) + .POST(HttpRequest.BodyPublishers.noBody()) + .build(); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(String.format("Ensuring queue failed! Status: %d, Body: %s", response.statusCode(), response.body())); + } + } +} diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java new file mode 100644 index 000000000..7701acd23 --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java @@ -0,0 +1,11 @@ +package io.a2a.extras.opentelemetry.it; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +/** + * Integration test for OpenTelemetry tracing in A2A SDK. + * Runs in native mode with @QuarkusIntegrationTest annotation. + */ +@QuarkusIntegrationTest +class OpenTelemetryA2AIT extends OpenTelemetryA2ABaseTest { +} diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java new file mode 100644 index 000000000..d6c73b05c --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java @@ -0,0 +1,11 @@ +package io.a2a.extras.opentelemetry.it; + +import io.quarkus.test.junit.QuarkusTest; + +/** + * Unit test for OpenTelemetry tracing in A2A SDK. + * Runs in JVM mode with @QuarkusTest annotation. + */ +@QuarkusTest +class OpenTelemetryA2ATest extends OpenTelemetryA2ABaseTest { +} diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java new file mode 100644 index 000000000..50011fa81 --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java @@ -0,0 +1,42 @@ +package io.a2a.extras.opentelemetry.it; + +import static io.restassured.RestAssured.given; +import static java.net.HttpURLConnection.HTTP_OK; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; +import static org.hamcrest.CoreMatchers.is; + +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class OpenTelemetryTest extends BaseTest { + + @BeforeEach + void reset() { + await().atMost(5, SECONDS).until(() -> { + List> spans = getSpans(); + if (spans.isEmpty()) { + return true; + } else { + given().get("/reset").then().statusCode(HTTP_OK); + return false; + } + }); + } + + @Test + void buildTimeEnabled() { + given() + .when().get("/hello") + .then() + .statusCode(200) + .body(is("Hello from Quarkus REST")); + await().atMost(5, SECONDS).until(() -> getSpans().size() == 1); + } +} \ No newline at end of file diff --git a/extras/opentelemetry/integration-tests/src/test/resources/application.properties b/extras/opentelemetry/integration-tests/src/test/resources/application.properties new file mode 100644 index 000000000..1e459ea8e --- /dev/null +++ b/extras/opentelemetry/integration-tests/src/test/resources/application.properties @@ -0,0 +1,25 @@ +# Test configuration +quarkus.application.name=a2a-otel-test + +# HTTP configuration +quarkus.http.test-port=8081 + +# OpenTelemetry configuration for testing +quarkus.otel.sdk.disabled=false +quarkus.otel.traces.enabled=true +quarkus.otel.metrics.enabled=false +quarkus.otel.logs.enabled=false +quarkus.otel.instrument.vertx-http=false + +quarkus.otel.bsp.schedule.delay=0 +quarkus.otel.bsp.export.timeout=5s + +# Service name +quarkus.otel.service.name=a2a-opentelemetry-integration-test + +# Propagators +quarkus.otel.propagators=tracecontext + +# Logging +quarkus.log.level=INFO +quarkus.log.category."io.a2a".level=DEBUG diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml new file mode 100644 index 000000000..23e7867de --- /dev/null +++ b/extras/opentelemetry/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + + io.github.a2asdk + a2a-java-sdk-parent + 1.0.0.Alpha2-SNAPSHOT + ../../pom.xml + + + a2a-java-sdk-opentelemetry-parent + pom + + A2A Java SDK :: Extras :: Opentelemetry :: Parent + Java SDK for the Agent2Agent Protocol (A2A) - Extras - Opentelemetry + + + 2.0.1 + + + + org.eclipse.microprofile.telemetry + microprofile-telemetry-api + ${version.org.eclipse.microprofile.telemetry} + pom + provided + + + + + common + client-propagation + client + server + integration-tests + + + \ No newline at end of file diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml new file mode 100644 index 000000000..cef51f092 --- /dev/null +++ b/extras/opentelemetry/server/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-parent + 1.0.0.Alpha2-SNAPSHOT + + + a2a-java-sdk-opentelemetry-server + + A2A Java SDK :: Extras :: Opentelemetry :: Server + OpenTelemetry server support for A2A Java SDK + + + + ${project.groupId} + a2a-java-sdk-opentelemetry-common + + + ${project.groupId} + a2a-java-sdk-server-common + + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + + + ${project.groupId} + a2a-java-sdk-spec-grpc + + + org.eclipse.microprofile.telemetry + microprofile-telemetry-api + ${version.org.eclipse.microprofile.telemetry} + pom + provided + + + jakarta.enterprise + jakarta.enterprise.cdi-api + + + jakarta.inject + jakarta.inject-api + + + org.slf4j + slf4j-api + + + org.junit.jupiter + junit-jupiter + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + + diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java new file mode 100644 index 000000000..f8bbf0745 --- /dev/null +++ b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java @@ -0,0 +1,465 @@ +package io.a2a.extras.opentelemetry; + +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.ERROR_TYPE; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONFIG_ID; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONTEXT_ID; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_EXTENSIONS; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_MESSAGE_ID; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_OPERATION_NAME; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_PARTS_NUMBER; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_ROLE; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_TASK_ID; + +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; +import io.a2a.server.ServerCallContext; +import io.a2a.server.requesthandlers.RequestHandler; +import io.a2a.spec.A2AError; +import io.a2a.spec.A2AMethods; +import io.a2a.spec.DeleteTaskPushNotificationConfigParams; +import io.a2a.spec.EventKind; +import io.a2a.spec.GetTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTasksParams; +import io.a2a.spec.MessageSendParams; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.Task; +import io.a2a.spec.TaskIdParams; +import io.a2a.spec.TaskPushNotificationConfig; +import io.a2a.spec.TaskQueryParams; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import jakarta.annotation.Priority; +import jakarta.decorator.Decorator; +import jakarta.decorator.Delegate; +import jakarta.enterprise.inject.Any; +import jakarta.inject.Inject; +import java.util.concurrent.Flow; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * OpenTelemetry CDI Decorator for {@link RequestHandler}. + *

        + * This decorator adds distributed tracing to A2A server request handlers. + * It creates spans for each request handler method invocation, capturing: + *

          + *
        • Request parameters as span attributes
        • + *
        • Response data as span attributes
        • + *
        • Errors and exceptions with proper status codes
        • + *
        • Timing information for performance monitoring
        • + *
        + *

        + * To enable this decorator, add it to your beans.xml: + *

        {@code
        + * 
        + *     io.a2a.extras.opentelemetry.OpenTelemetryRequestHandlerDecorator
        + * 
        + * }
        + */ +@Decorator +@Priority(100) +public abstract class OpenTelemetryRequestHandlerDecorator implements RequestHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(OpenTelemetryRequestHandlerDecorator.class); + + @Inject + @Delegate + @Any + private RequestHandler delegate; + + @Inject + private Tracer tracer; + + /** + * Default constructor for CDI. + */ + public OpenTelemetryRequestHandlerDecorator() { + } + + /** + * Constructor for testing. + * + * @param delegate the delegate request handler + * @param tracer the tracer to use + */ + public OpenTelemetryRequestHandlerDecorator(RequestHandler delegate, Tracer tracer) { + this.delegate = delegate; + this.tracer = tracer; + } + + @Override + public Task onGetTask(TaskQueryParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_METHOD); + + if (params.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + Task result = delegate.onGetTask(params, context); + + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public ListTasksResult onListTasks(ListTasksParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_METHOD); + + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + if (params.contextId() != null) { + spanBuilder.setAttribute(GENAI_CONTEXT_ID, params.contextId()); + } + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + ListTasksResult result = delegate.onListTasks(params, context); + + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.CANCEL_TASK_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.CANCEL_TASK_METHOD); + + if (params.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + Task result = delegate.onCancelTask(params, context); + + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public EventKind onMessageSend(MessageSendParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.SEND_MESSAGE_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.SEND_MESSAGE_METHOD); + + if (params.message() != null) { + if (params.message().taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.message().taskId()); + } + if (params.message().contextId() != null) { + spanBuilder.setAttribute(GENAI_CONTEXT_ID, params.message().contextId()); + } + if (params.message().messageId() != null) { + spanBuilder.setAttribute(GENAI_MESSAGE_ID, params.message().messageId()); + } + if (params.message().role() != null) { + spanBuilder.setAttribute(GENAI_ROLE, params.message().role().asString()); + } + if (params.message().extensions() != null && !params.message().extensions().isEmpty()) { + spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", params.message().extensions())); + } + spanBuilder.setAttribute(GENAI_PARTS_NUMBER, params.message().parts().size()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + EventKind result = delegate.onMessageSend(params, context); + + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public Flow.Publisher onMessageSendStream(MessageSendParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.SEND_STREAMING_MESSAGE_METHOD); + + if (params.message() != null) { + if (params.message().taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.message().taskId()); + } + if (params.message().contextId() != null) { + spanBuilder.setAttribute(GENAI_CONTEXT_ID, params.message().contextId()); + } + if (params.message().messageId() != null) { + spanBuilder.setAttribute(GENAI_MESSAGE_ID, params.message().messageId()); + } + if (params.message().role() != null) { + spanBuilder.setAttribute(GENAI_ROLE, params.message().role().asString()); + } + if (params.message().extensions() != null && !params.message().extensions().isEmpty()) { + spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", params.message().extensions())); + } + spanBuilder.setAttribute(GENAI_PARTS_NUMBER, params.message().parts().size()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + Flow.Publisher result = delegate.onMessageSendStream(params, context); + + if (extractResponse()) { + span.setAttribute(GENAI_RESPONSE, "Stream publisher created"); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public TaskPushNotificationConfig onCreateTaskPushNotificationConfig(TaskPushNotificationConfig params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + + if (params.taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.taskId()); + } + if (params.pushNotificationConfig() != null && params.pushNotificationConfig().id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, params.pushNotificationConfig().id()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + TaskPushNotificationConfig result = delegate.onCreateTaskPushNotificationConfig(params, context); + + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public TaskPushNotificationConfig onGetTaskPushNotificationConfig(GetTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + + if (params.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); + } + if (params.pushNotificationConfigId() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, params.pushNotificationConfigId()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + TaskPushNotificationConfig result = delegate.onGetTaskPushNotificationConfig(params, context); + + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public Flow.Publisher onSubscribeToTask(TaskIdParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.SUBSCRIBE_TO_TASK_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.SUBSCRIBE_TO_TASK_METHOD); + + if (params.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); + } + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + Flow.Publisher result = delegate.onSubscribeToTask(params, context); + + if (extractResponse()) { + span.setAttribute(GENAI_RESPONSE, "Stream publisher created"); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig(ListTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + if (params.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + ListTaskPushNotificationConfigResult result = delegate.onListTaskPushNotificationConfig(params, context); + + if (result != null && extractResponse()) { + span.setAttribute(GENAI_RESPONSE, result.toString()); + } + + span.setStatus(StatusCode.OK); + return result; + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + @Override + public void onDeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { + var spanBuilder = tracer.spanBuilder(A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD) + .setSpanKind(SpanKind.SERVER) + .setAttribute(GENAI_OPERATION_NAME, A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + + if (extractRequest()) { + spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); + } + if (params.id() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); + } + + Span span = spanBuilder.startSpan(); + + try (Scope scope = span.makeCurrent()) { + delegate.onDeleteTaskPushNotificationConfig(params, context); + + span.setStatus(StatusCode.OK); + } catch (A2AError error) { + span.setAttribute(ERROR_TYPE, error.getMessage()); + span.setStatus(StatusCode.ERROR, error.getMessage()); + throw error; + } finally { + span.end(); + } + } + + private boolean extractRequest() { + return Boolean.getBoolean(EXTRACT_REQUEST_SYS_PROPERTY); + } + + private boolean extractResponse() { + return Boolean.getBoolean(EXTRACT_RESPONSE_SYS_PROPERTY); + } +} diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java new file mode 100644 index 000000000..fdd7057d5 --- /dev/null +++ b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package io.a2a.extras.opentelemetry; + +import org.jspecify.annotations.NullMarked; + diff --git a/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml b/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..dcc4135c8 --- /dev/null +++ b/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml @@ -0,0 +1,9 @@ + + + + io.a2a.extras.opentelemetry.OpenTelemetryRequestHandlerDecorator + + \ No newline at end of file diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java new file mode 100644 index 000000000..2f67e4a05 --- /dev/null +++ b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java @@ -0,0 +1,497 @@ +package io.a2a.extras.opentelemetry; + +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.ERROR_TYPE; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; +import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; +import io.a2a.server.ServerCallContext; +import io.a2a.server.requesthandlers.RequestHandler; +import io.a2a.spec.*; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Flow; + +@ExtendWith(MockitoExtension.class) +class OpenTelemetryRequestHandlerDecoratorTest { + + @Mock + private Tracer tracer; + + @Mock + private Span span; + + @Mock + private SpanBuilder spanBuilder; + + @Mock + private Scope scope; + + @Mock + private ServerCallContext context; + + @Mock + private RequestHandler delegate; + + private TestableOpenTelemetryRequestHandlerDecorator decorator; + + @BeforeEach + void setUp() { + // Set system properties for extracting request/response + System.setProperty(EXTRACT_REQUEST_SYS_PROPERTY, "true"); + System.setProperty(EXTRACT_RESPONSE_SYS_PROPERTY, "true"); + + // Set up the mock chain + lenient().when(tracer.spanBuilder(anyString())).thenReturn(spanBuilder); + lenient().when(spanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(spanBuilder); + lenient().when(spanBuilder.setAttribute(anyString(), anyString())).thenReturn(spanBuilder); + lenient().when(spanBuilder.setAttribute(anyString(), anyLong())).thenReturn(spanBuilder); + lenient().when(spanBuilder.startSpan()).thenReturn(span); + lenient().when(span.makeCurrent()).thenReturn(scope); + lenient().when(span.setAttribute(anyString(), anyString())).thenReturn(span); + lenient().when(span.setStatus(any(StatusCode.class))).thenReturn(span); + lenient().when(span.setStatus(any(StatusCode.class), anyString())).thenReturn(span); + + // Create decorator with mocked dependencies + decorator = new TestableOpenTelemetryRequestHandlerDecorator(delegate, tracer); + } + + /** + * Concrete test implementation of the abstract decorator for testing purposes. + */ + static class TestableOpenTelemetryRequestHandlerDecorator extends OpenTelemetryRequestHandlerDecorator { + public TestableOpenTelemetryRequestHandlerDecorator(RequestHandler delegate, Tracer tracer) { + super(delegate, tracer); + } + } + + @Nested + class GetTaskTests { + @Test + void onGetTask_createsSpanAndDelegatesToHandler() throws A2AError { + TaskQueryParams params = new TaskQueryParams("task-123", null); + Task result = Task.builder() + .id("task-123") + .contextId("ctx-1") + .status(new TaskStatus(TaskState.COMPLETED)) + .history(Collections.emptyList()) + .artifacts(Collections.emptyList()) + .build(); + when(delegate.onGetTask(params, context)).thenReturn(result); + + Task actualResult = decorator.onGetTask(params, context); + + assertEquals(result, actualResult); + verify(tracer).spanBuilder(A2AMethods.GET_TASK_METHOD); + verify(spanBuilder).setSpanKind(SpanKind.SERVER); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(spanBuilder).startSpan(); + verify(span).makeCurrent(); + verify(span).setAttribute(GENAI_RESPONSE, result.toString()); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + verify(delegate).onGetTask(params, context); + } + + @Test + void onGetTask_withError_setsErrorStatusAndRethrows() throws A2AError { + TaskQueryParams params = new TaskQueryParams("task-123", null); + A2AError error = new TaskNotFoundError(); + when(delegate.onGetTask(params, context)).thenThrow(error); + + assertThrows(TaskNotFoundError.class, () -> decorator.onGetTask(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class ListTasksTests { + @Test + void onListTasks_createsSpanAndDelegatesToHandler() throws A2AError { + ListTasksParams params = new ListTasksParams(null, null, null, null, null, null, null, "test-tenant"); + ListTasksResult result = new ListTasksResult(Collections.emptyList(), 0, 0, null); + when(delegate.onListTasks(params, context)).thenReturn(result); + + ListTasksResult actualResult = decorator.onListTasks(params, context); + + assertEquals(result, actualResult); + verify(tracer).spanBuilder(A2AMethods.LIST_TASK_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, result.toString()); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void onListTasks_withError_setsErrorStatus() throws A2AError { + ListTasksParams params = new ListTasksParams(null, null, null, null, null, null, null, "test-tenant"); + A2AError error = new InvalidRequestError("Invalid parameters"); + when(delegate.onListTasks(params, context)).thenThrow(error); + + assertThrows(InvalidRequestError.class, () -> decorator.onListTasks(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class CancelTaskTests { + @Test + void onCancelTask_createsSpanAndDelegatesToHandler() throws A2AError { + TaskIdParams params = new TaskIdParams("task-123"); + Task result = Task.builder() + .id("task-123") + .contextId("ctx-1") + .status(new TaskStatus(TaskState.CANCELED)) + .history(Collections.emptyList()) + .artifacts(Collections.emptyList()) + .build(); + when(delegate.onCancelTask(params, context)).thenReturn(result); + + Task actualResult = decorator.onCancelTask(params, context); + + assertEquals(result, actualResult); + verify(tracer).spanBuilder(A2AMethods.CANCEL_TASK_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, result.toString()); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void onCancelTask_withError_setsErrorStatus() throws A2AError { + TaskIdParams params = new TaskIdParams("task-123"); + A2AError error = new TaskNotFoundError(); + when(delegate.onCancelTask(params, context)).thenThrow(error); + + assertThrows(TaskNotFoundError.class, () -> decorator.onCancelTask(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class MessageSendTests { + @Test + void onMessageSend_createsSpanAndDelegatesToHandler() throws A2AError { + Message message = Message.builder() + .role(Message.Role.USER) + .parts(List.of(new TextPart("test message"))) + .messageId("msg-123") + .contextId("ctx-1") + .taskId("task-123") + .build(); + MessageSendParams params = new MessageSendParams(message, null, null, ""); + EventKind result = Task.builder() + .id("task-123") + .contextId("ctx-1") + .status(new TaskStatus(TaskState.COMPLETED)) + .history(Collections.emptyList()) + .artifacts(Collections.emptyList()) + .build(); + when(delegate.onMessageSend(params, context)).thenReturn(result); + + EventKind actualResult = decorator.onMessageSend(params, context); + + assertEquals(result, actualResult); + verify(tracer).spanBuilder(A2AMethods.SEND_MESSAGE_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, result.toString()); + verify(span).setStatus(StatusCode.OK); + } + + @Test + void onMessageSend_withError_setsErrorStatus() throws A2AError { + Message message = Message.builder() + .role(Message.Role.USER) + .parts(List.of(new TextPart("test message"))) + .messageId("msg-123") + .contextId("ctx-1") + .taskId("task-123") + .build(); + MessageSendParams params = new MessageSendParams(message, null, null, ""); + A2AError error = new InvalidRequestError("Invalid message"); + when(delegate.onMessageSend(params, context)).thenThrow(error); + + assertThrows(InvalidRequestError.class, () -> decorator.onMessageSend(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class MessageSendStreamTests { + @Test + void onMessageSendStream_createsSpanWithSpecialMessage() throws A2AError { + Message message = Message.builder() + .role(Message.Role.USER) + .parts(List.of(new TextPart("test message"))) + .messageId("msg-123") + .contextId("ctx-1") + .taskId("task-123") + .build(); + MessageSendParams params = new MessageSendParams(message, null, null, ""); + Flow.Publisher publisher = mock(Flow.Publisher.class); + when(delegate.onMessageSendStream(params, context)).thenReturn(publisher); + + Flow.Publisher actualResult = decorator.onMessageSendStream(params, context); + + assertEquals(publisher, actualResult); + verify(tracer).spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, "Stream publisher created"); + verify(span).setStatus(StatusCode.OK); + } + + @Test + void onMessageSendStream_withError_setsErrorStatus() throws A2AError { + Message message = Message.builder() + .role(Message.Role.USER) + .parts(List.of(new TextPart("test message"))) + .messageId("msg-123") + .contextId("ctx-1") + .taskId("task-123") + .build(); + MessageSendParams params = new MessageSendParams(message, null, null, ""); + A2AError error = new InvalidRequestError("Stream error"); + when(delegate.onMessageSendStream(params, context)).thenThrow(error); + + assertThrows(InvalidRequestError.class, () -> decorator.onMessageSendStream(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class SetTaskPushNotificationConfigTests { + @Test + void onSetTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { + PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); + TaskPushNotificationConfig params = new TaskPushNotificationConfig("task-123", config, null); + TaskPushNotificationConfig result = new TaskPushNotificationConfig("task-123", config, null); + when(delegate.onCreateTaskPushNotificationConfig(params, context)).thenReturn(result); + + TaskPushNotificationConfig actualResult = decorator.onCreateTaskPushNotificationConfig(params, context); + + assertEquals(result, actualResult); + verify(tracer).spanBuilder(A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, result.toString()); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void onSetTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { + PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); + TaskPushNotificationConfig params = new TaskPushNotificationConfig("task-123", config, null); + A2AError error = new InvalidRequestError("Invalid config"); + when(delegate.onCreateTaskPushNotificationConfig(params, context)).thenThrow(error); + + assertThrows(InvalidRequestError.class, () -> decorator.onCreateTaskPushNotificationConfig(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class GetTaskPushNotificationConfigTests { + @Test + void onGetTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { + GetTaskPushNotificationConfigParams params = new GetTaskPushNotificationConfigParams("task-123", "config-1"); + PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); + TaskPushNotificationConfig result = new TaskPushNotificationConfig("task-123", config, null); + when(delegate.onGetTaskPushNotificationConfig(params, context)).thenReturn(result); + + TaskPushNotificationConfig actualResult = decorator.onGetTaskPushNotificationConfig(params, context); + + assertEquals(result, actualResult); + verify(tracer).spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, result.toString()); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void onGetTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { + GetTaskPushNotificationConfigParams params = new GetTaskPushNotificationConfigParams("task-123", ""); + A2AError error = new TaskNotFoundError(); + when(delegate.onGetTaskPushNotificationConfig(params, context)).thenThrow(error); + + assertThrows(TaskNotFoundError.class, () -> decorator.onGetTaskPushNotificationConfig(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class ResubscribeToTaskTests { + @Test + void onResubscribeToTask_createsSpanWithSpecialMessage() throws A2AError { + TaskIdParams params = new TaskIdParams("task-123"); + Flow.Publisher publisher = mock(Flow.Publisher.class); + when(delegate.onSubscribeToTask(params, context)).thenReturn(publisher); + + Flow.Publisher actualResult = decorator.onSubscribeToTask(params, context); + + assertEquals(publisher, actualResult); + verify(tracer).spanBuilder(A2AMethods.SUBSCRIBE_TO_TASK_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, "Stream publisher created"); + verify(span).setStatus(StatusCode.OK); + } + + @Test + void onResubscribeToTask_withError_setsErrorStatus() throws A2AError { + TaskIdParams params = new TaskIdParams("task-123"); + A2AError error = new TaskNotFoundError(); + when(delegate.onSubscribeToTask(params, context)).thenThrow(error); + + assertThrows(TaskNotFoundError.class, () -> decorator.onSubscribeToTask(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class ListTaskPushNotificationConfigTests { + @Test + void onListTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { + ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-123"); + ListTaskPushNotificationConfigResult result = new ListTaskPushNotificationConfigResult(Collections.emptyList(), null); + when(delegate.onListTaskPushNotificationConfig(params, context)).thenReturn(result); + + ListTaskPushNotificationConfigResult actualResult = decorator.onListTaskPushNotificationConfig(params, context); + + assertEquals(result, actualResult); + verify(tracer).spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, result.toString()); + verify(span).setStatus(StatusCode.OK); + verify(span).end(); + } + + @Test + void onListTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { + ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-123"); + A2AError error = new InvalidRequestError("Invalid request"); + when(delegate.onListTaskPushNotificationConfig(params, context)).thenThrow(error); + + assertThrows(InvalidRequestError.class, () -> decorator.onListTaskPushNotificationConfig(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class DeleteTaskPushNotificationConfigTests { + @Test + void onDeleteTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { + DeleteTaskPushNotificationConfigParams params = new DeleteTaskPushNotificationConfigParams("task-123", "config-123"); + doNothing().when(delegate).onDeleteTaskPushNotificationConfig(params, context); + + decorator.onDeleteTaskPushNotificationConfig(params, context); + + verify(tracer).spanBuilder(A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setStatus(StatusCode.OK); + verify(span, never()).setAttribute(eq(GENAI_RESPONSE), anyString()); + verify(span).end(); + } + + @Test + void onDeleteTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { + DeleteTaskPushNotificationConfigParams params = new DeleteTaskPushNotificationConfigParams("task-123", "config-123"); + A2AError error = new TaskNotFoundError(); + doThrow(error).when(delegate).onDeleteTaskPushNotificationConfig(params, context); + + assertThrows(TaskNotFoundError.class, () -> decorator.onDeleteTaskPushNotificationConfig(params, context)); + + verify(span).setAttribute(ERROR_TYPE, error.getMessage()); + verify(span).setStatus(StatusCode.ERROR, error.getMessage()); + verify(span).end(); + } + } + + @Nested + class SpanLifecycleTests { + @Test + void allMethods_createAndEndSpans() throws A2AError { + TaskQueryParams params = new TaskQueryParams("task-123", null); + Task result = Task.builder() + .id("task-123") + .contextId("ctx-1") + .status(new TaskStatus(TaskState.COMPLETED)) + .history(Collections.emptyList()) + .artifacts(Collections.emptyList()) + .build(); + when(delegate.onGetTask(params, context)).thenReturn(result); + + decorator.onGetTask(params, context); + + verify(span, times(1)).makeCurrent(); + verify(span, times(1)).end(); + } + + @Test + void spanAttributes_setCorrectly() throws A2AError { + TaskQueryParams params = new TaskQueryParams("task-123", null); + Task result = Task.builder() + .id("task-123") + .contextId("ctx-1") + .status(new TaskStatus(TaskState.COMPLETED)) + .history(Collections.emptyList()) + .artifacts(Collections.emptyList()) + .build(); + when(delegate.onGetTask(params, context)).thenReturn(result); + + decorator.onGetTask(params, context); + + verify(tracer).spanBuilder(A2AMethods.GET_TASK_METHOD); + verify(spanBuilder).setSpanKind(SpanKind.SERVER); + verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); + verify(span).setAttribute(GENAI_RESPONSE, result.toString()); + verify(span).setStatus(StatusCode.OK); + } + } +} diff --git a/pom.xml b/pom.xml index 8f3545dba..dcf90ba44 100644 --- a/pom.xml +++ b/pom.xml @@ -189,6 +189,36 @@ a2a-java-sdk-reference-rest ${project.version}
        + + io.github.a2asdk + a2a-java-sdk-opentelemetry + ${project.version} + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-spring + ${project.version} + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-common + ${project.version} + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-client + ${project.version} + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-server + ${project.version} + + + io.github.a2asdk + a2a-java-sdk-opentelemetry-client-propagation + ${project.version} + io.grpc grpc-bom @@ -512,6 +542,7 @@ examples/helloworld examples/cloud-deployment/server extras/common + extras/opentelemetry extras/task-store-database-jpa extras/push-notification-config-store-database-jpa extras/queue-manager-replicated 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 98e40585b..3b0421b44 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 @@ -14,7 +14,7 @@ /** * gRPC server interceptor that captures request metadata and context information, * providing equivalent functionality to Python's grpc.aio.ServicerContext. - * + * * This interceptor: * - Extracts A2A extension headers from incoming requests * - Captures ServerCall and Metadata for rich context access @@ -24,7 +24,6 @@ @ApplicationScoped public class A2AExtensionsInterceptor implements ServerInterceptor { - @Override public ServerCall.Listener interceptCall( ServerCall serverCall, @@ -43,12 +42,14 @@ public ServerCall.Listener interceptCall( // Create enhanced context with rich information (equivalent to Python's ServicerContext) Context context = Context.current() - // Store complete metadata for full header access - .withValue(GrpcContextKeys.METADATA_KEY, metadata) - // Store method name (equivalent to Python's context.method()) - .withValue(GrpcContextKeys.METHOD_NAME_KEY, serverCall.getMethodDescriptor().getFullMethodName()) - // Store peer information for client connection details - .withValue(GrpcContextKeys.PEER_INFO_KEY, getPeerInfo(serverCall)); + // Store complete metadata for full header access + .withValue(GrpcContextKeys.METADATA_KEY, metadata) + // Store Grpc method name + .withValue(GrpcContextKeys.GRPC_METHOD_NAME_KEY, serverCall.getMethodDescriptor().getFullMethodName()) + // Store method name (equivalent to Python's context.method()) + .withValue(GrpcContextKeys.METHOD_NAME_KEY, GrpcContextKeys.METHOD_MAPPING.get(serverCall.getMethodDescriptor().getBareMethodName())) + // Store peer information for client connection details + .withValue(GrpcContextKeys.PEER_INFO_KEY, getPeerInfo(serverCall)); // Store A2A version if present if (version != null) { @@ -66,7 +67,7 @@ public ServerCall.Listener interceptCall( /** * Safely extracts peer information from the ServerCall. - * + * * @param serverCall the gRPC ServerCall * @return peer information string, or "unknown" if not available */ 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 8e8912922..3c664c4b2 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 @@ -50,6 +50,7 @@ import org.jspecify.annotations.Nullable; 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; @@ -89,7 +90,7 @@ public void sendMessage(@Body String body, RoutingContext rc) { ServerCallContext context = createCallContext(rc, SEND_MESSAGE_METHOD); HTTPRestResponse response = null; try { - response = jsonRestHandler.sendMessage(body, extractTenant(rc), context); + response = jsonRestHandler.sendMessage(context, extractTenant(rc), body); } catch (Throwable t) { response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); } finally { @@ -103,7 +104,7 @@ public void sendMessageStreaming(@Body String body, RoutingContext rc) { HTTPRestStreamingResponse streamingResponse = null; HTTPRestResponse error = null; try { - HTTPRestResponse response = jsonRestHandler.sendStreamingMessage(body, extractTenant(rc), context); + HTTPRestResponse response = jsonRestHandler.sendStreamingMessage(context, extractTenant(rc), body); if (response instanceof HTTPRestStreamingResponse hTTPRestStreamingResponse) { streamingResponse = hTTPRestStreamingResponse; } else { @@ -158,9 +159,8 @@ public void listTasks(RoutingContext rc) { if (includeArtifactsStr != null && !includeArtifactsStr.isEmpty()) { includeArtifacts = Boolean.valueOf(includeArtifactsStr); } - - response = jsonRestHandler.listTasks(contextId, statusStr, pageSize, pageToken, - historyLength, statusTimestampAfter, includeArtifacts, extractTenant(rc), context); + response = jsonRestHandler.listTasks(context, extractTenant(rc), contextId, statusStr, pageSize, pageToken, + historyLength, statusTimestampAfter, includeArtifacts); } catch (NumberFormatException e) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("Invalid number format in parameters")); } catch (IllegalArgumentException e) { @@ -185,7 +185,7 @@ public void getTask(RoutingContext rc) { if (rc.request().params().contains(HISTORY_LENGTH_PARAM)) { historyLength = Integer.valueOf(rc.request().params().get(HISTORY_LENGTH_PARAM)); } - response = jsonRestHandler.getTask(taskId, historyLength, extractTenant(rc), context); + response = jsonRestHandler.getTask(context, extractTenant(rc), taskId, historyLength); } } catch (NumberFormatException e) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad historyLength")); @@ -205,7 +205,7 @@ public void cancelTask(RoutingContext rc) { if (taskId == null || taskId.isEmpty()) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); } else { - response = jsonRestHandler.cancelTask(taskId, extractTenant(rc), context); + response = jsonRestHandler.cancelTask(context, extractTenant(rc), taskId); } } catch (Throwable t) { if (t instanceof A2AError error) { @@ -239,7 +239,7 @@ public void subscribeToTask(RoutingContext rc) { if (taskId == null || taskId.isEmpty()) { error = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); } else { - HTTPRestResponse response = jsonRestHandler.subscribeToTask(taskId, extractTenant(rc), context); + HTTPRestResponse response = jsonRestHandler.subscribeToTask(context, extractTenant(rc), taskId); if (response instanceof HTTPRestStreamingResponse hTTPRestStreamingResponse) { streamingResponse = hTTPRestStreamingResponse; } else { @@ -272,7 +272,7 @@ public void CreateTaskPushNotificationConfiguration(@Body String body, RoutingCo if (taskId == null || taskId.isEmpty()) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); } else { - response = jsonRestHandler.CreateTaskPushNotificationConfiguration(taskId, body, extractTenant(rc), context); + response = jsonRestHandler.createTaskPushNotificationConfiguration(context, extractTenant(rc), body, taskId); } } catch (Throwable t) { response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); @@ -293,7 +293,7 @@ public void getTaskPushNotificationConfiguration(RoutingContext rc) { } else if (configId == null || configId.isEmpty()) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad configuration id")); }else { - response = jsonRestHandler.getTaskPushNotificationConfiguration(taskId, configId, extractTenant(rc), context); + response = jsonRestHandler.getTaskPushNotificationConfiguration(context, extractTenant(rc), taskId, configId); } } catch (Throwable t) { response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); @@ -319,7 +319,7 @@ public void listTaskPushNotificationConfigurations(RoutingContext rc) { if (rc.request().params().contains(PAGE_TOKEN_PARAM)) { pageToken = Utils.defaultIfNull(rc.request().params().get(PAGE_TOKEN_PARAM), ""); } - response = jsonRestHandler.listTaskPushNotificationConfigurations(taskId, pageSize, pageToken, extractTenant(rc), context); + response = jsonRestHandler.listTaskPushNotificationConfigurations(context, extractTenant(rc), taskId, pageSize, pageToken); } } catch (NumberFormatException e) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad " + PAGE_SIZE_PARAM)); @@ -342,7 +342,7 @@ public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { } else if (configId == null || configId.isEmpty()) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad config id")); } else { - response = jsonRestHandler.deleteTaskPushNotificationConfiguration(taskId, configId, extractTenant(rc), context); + response = jsonRestHandler.deleteTaskPushNotificationConfiguration(context, extractTenant(rc), taskId, configId); } } catch (Throwable t) { response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); @@ -381,7 +381,7 @@ public void getAgentCard(RoutingContext rc) { @Route(regex = "^\\/(?[^\\/]*\\/?)extendedAgentCard$", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) public void getExtendedAgentCard(RoutingContext rc) { - HTTPRestResponse response = jsonRestHandler.getExtendedAgentCard(extractTenant(rc)); + HTTPRestResponse response = jsonRestHandler.getExtendedAgentCard(createCallContext(rc, GET_EXTENDED_AGENT_CARD_METHOD), extractTenant(rc)); sendResponse(rc, response); } 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 a8ce70f7f..ce3c140cc 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 @@ -94,7 +94,7 @@ public void testSendMessage_MethodNameSetInContext() { when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.sendMessage(anyString(), anyString(), any(ServerCallContext.class))).thenReturn(mockHttpResponse); + when(mockRestHandler.sendMessage(any(ServerCallContext.class), anyString(), anyString())).thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -102,7 +102,7 @@ public void testSendMessage_MethodNameSetInContext() { routes.sendMessage("{}", mockRoutingContext); // Assert - verify(mockRestHandler).sendMessage(eq("{}"), anyString(), contextCaptor.capture()); + verify(mockRestHandler).sendMessage(contextCaptor.capture(), anyString(), eq("{}")); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(SEND_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); @@ -115,7 +115,7 @@ public void testSendMessageStreaming_MethodNameSetInContext() { when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.sendStreamingMessage(anyString(), anyString(), any(ServerCallContext.class))) + when(mockRestHandler.sendStreamingMessage(any(ServerCallContext.class), anyString(), anyString())) .thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -124,7 +124,7 @@ public void testSendMessageStreaming_MethodNameSetInContext() { routes.sendMessageStreaming("{}", mockRoutingContext); // Assert - verify(mockRestHandler).sendStreamingMessage(eq("{}"), anyString(), contextCaptor.capture()); + verify(mockRestHandler).sendStreamingMessage(contextCaptor.capture(), anyString(), eq("{}")); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(SEND_STREAMING_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); @@ -138,7 +138,7 @@ public void testGetTask_MethodNameSetInContext() { when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{test:value}"); - when(mockRestHandler.getTask(anyString(), any(), anyString(), any(ServerCallContext.class))).thenReturn(mockHttpResponse); + when(mockRestHandler.getTask(any(ServerCallContext.class), anyString(), anyString(), any())).thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -146,7 +146,7 @@ public void testGetTask_MethodNameSetInContext() { routes.getTask(mockRoutingContext); // Assert - verify(mockRestHandler).getTask(eq("task123"), any(), anyString(), contextCaptor.capture()); + verify(mockRestHandler).getTask(contextCaptor.capture(), anyString(), eq("task123"), any()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(GET_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); @@ -160,7 +160,7 @@ public void testCancelTask_MethodNameSetInContext() { when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.cancelTask(anyString(), anyString(), any(ServerCallContext.class))).thenReturn(mockHttpResponse); + when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString())).thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -168,7 +168,7 @@ public void testCancelTask_MethodNameSetInContext() { routes.cancelTask(mockRoutingContext); // Assert - verify(mockRestHandler).cancelTask(eq("task123"), anyString(), contextCaptor.capture()); + verify(mockRestHandler).cancelTask(contextCaptor.capture(), anyString(), eq("task123")); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(CANCEL_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); @@ -182,7 +182,7 @@ public void testSubscribeTask_MethodNameSetInContext() { when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.subscribeToTask(anyString(), anyString(), any(ServerCallContext.class))) + when(mockRestHandler.subscribeToTask(any(ServerCallContext.class), anyString(), anyString())) .thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -191,7 +191,7 @@ public void testSubscribeTask_MethodNameSetInContext() { routes.subscribeToTask(mockRoutingContext); // Assert - verify(mockRestHandler).subscribeToTask(eq("task123"), anyString(), contextCaptor.capture()); + verify(mockRestHandler).subscribeToTask(contextCaptor.capture(), anyString(), eq("task123")); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(SUBSCRIBE_TO_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); @@ -205,8 +205,7 @@ public void testCreateTaskPushNotificationConfiguration_MethodNameSetInContext() when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.CreateTaskPushNotificationConfiguration(anyString(), anyString(), anyString(), - any(ServerCallContext.class))).thenReturn(mockHttpResponse); + when(mockRestHandler.createTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -214,7 +213,7 @@ public void testCreateTaskPushNotificationConfiguration_MethodNameSetInContext() routes.CreateTaskPushNotificationConfiguration("{}", mockRoutingContext); // Assert - verify(mockRestHandler).CreateTaskPushNotificationConfiguration(eq("task123"), eq("{}"), anyString(), contextCaptor.capture()); + verify(mockRestHandler).createTaskPushNotificationConfiguration(contextCaptor.capture(), anyString(), eq("{}"), eq("task123")); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); @@ -229,8 +228,7 @@ public void testGetTaskPushNotificationConfiguration_MethodNameSetInContext() { when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.getTaskPushNotificationConfiguration(anyString(), anyString(), anyString(), - any(ServerCallContext.class))).thenReturn(mockHttpResponse); + when(mockRestHandler.getTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -238,8 +236,8 @@ public void testGetTaskPushNotificationConfiguration_MethodNameSetInContext() { routes.getTaskPushNotificationConfiguration(mockRoutingContext); // Assert - verify(mockRestHandler).getTaskPushNotificationConfiguration(eq("task123"), eq("config456"), anyString(), - contextCaptor.capture()); + verify(mockRestHandler).getTaskPushNotificationConfiguration(contextCaptor.capture(), anyString(), eq("task123"), + eq("config456")); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); @@ -253,7 +251,7 @@ public void testListTaskPushNotificationConfigurations_MethodNameSetInContext() when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.listTaskPushNotificationConfigurations(anyString(), anyInt(), anyString(), anyString(), any(ServerCallContext.class))) + when(mockRestHandler.listTaskPushNotificationConfigurations(any(ServerCallContext.class), anyString(), anyString(), anyInt(), anyString())) .thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -262,7 +260,7 @@ public void testListTaskPushNotificationConfigurations_MethodNameSetInContext() routes.listTaskPushNotificationConfigurations(mockRoutingContext); // Assert - verify(mockRestHandler).listTaskPushNotificationConfigurations(eq("task123"), anyInt(), anyString(), anyString(), contextCaptor.capture()); + verify(mockRestHandler).listTaskPushNotificationConfigurations(contextCaptor.capture(), anyString(), eq("task123"), anyInt(), anyString()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); @@ -277,8 +275,7 @@ public void testDeleteTaskPushNotificationConfiguration_MethodNameSetInContext() when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.deleteTaskPushNotificationConfiguration(anyString(), anyString(), anyString(), - any(ServerCallContext.class))).thenReturn(mockHttpResponse); + when(mockRestHandler.deleteTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -286,8 +283,8 @@ public void testDeleteTaskPushNotificationConfiguration_MethodNameSetInContext() routes.deleteTaskPushNotificationConfiguration(mockRoutingContext); // Assert - verify(mockRestHandler).deleteTaskPushNotificationConfiguration(eq("task123"), eq("config456"), anyString(), - contextCaptor.capture()); + verify(mockRestHandler).deleteTaskPushNotificationConfiguration(contextCaptor.capture(), anyString(), eq("task123"), + eq("config456")); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); 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 0319718ea..5fd8836dc 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 @@ -6,6 +6,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import java.time.Instant; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -67,6 +68,7 @@ import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.UnsupportedOperationError; +import java.util.Collections; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; diff --git a/spec/src/main/java/io/a2a/spec/A2AMethods.java b/spec/src/main/java/io/a2a/spec/A2AMethods.java index e270a7d91..1731077fe 100644 --- a/spec/src/main/java/io/a2a/spec/A2AMethods.java +++ b/spec/src/main/java/io/a2a/spec/A2AMethods.java @@ -27,5 +27,6 @@ public interface A2AMethods { String SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "CreateTaskPushNotificationConfig"; /** Method name for subscribing to task events. */ String SUBSCRIBE_TO_TASK_METHOD = "SubscribeToTask"; + } diff --git a/spec/src/main/java/io/a2a/spec/Message.java b/spec/src/main/java/io/a2a/spec/Message.java index 1b4c73248..9191a0fae 100644 --- a/spec/src/main/java/io/a2a/spec/Message.java +++ b/spec/src/main/java/io/a2a/spec/Message.java @@ -35,10 +35,15 @@ * @see A2A Protocol Specification */ public record Message(Role role, List> parts, - String messageId, @Nullable String contextId, - @Nullable String taskId, @Nullable List referenceTaskIds, - @Nullable Map metadata, @Nullable List extensions -) implements EventKind, StreamingEventKind { + String messageId, @Nullable + String contextId, + @Nullable + String taskId, @Nullable + List referenceTaskIds, + @Nullable + Map metadata, @Nullable + List extensions + ) implements EventKind, StreamingEventKind { /** * The identifier when used in streaming responses @@ -106,7 +111,6 @@ public enum Role { * Message originated from the user (client side). */ USER("user"), - /** * Message originated from the agent (server side). */ @@ -145,14 +149,22 @@ public String asString() { */ public static class Builder { - private @Nullable Role role; - private @Nullable List> parts; - private @Nullable String messageId; - private @Nullable String contextId; - private @Nullable String taskId; - private @Nullable List referenceTaskIds; - private @Nullable Map metadata; - private @Nullable List extensions; + private @Nullable + Role role; + private @Nullable + List> parts; + private @Nullable + String messageId; + private @Nullable + String contextId; + private @Nullable + String taskId; + private @Nullable + List referenceTaskIds; + private @Nullable + Map metadata; + private @Nullable + List extensions; /** * Creates a new Builder with all fields unset. @@ -204,7 +216,7 @@ public Builder parts(List> parts) { * @param parts the message parts (required, must not be empty) * @return this builder for method chaining */ - public Builder parts(Part...parts) { + public Builder parts(Part... parts) { this.parts = List.of(parts); return this; } @@ -287,8 +299,8 @@ public Builder extensions(List extensions) { */ public Message build() { return new Message( - Assert.checkNotNullParam("role", role), - Assert.checkNotNullParam("parts", parts), + Assert.checkNotNullParam("role", role), + Assert.checkNotNullParam("parts", parts), messageId == null ? UUID.randomUUID().toString() : messageId, contextId, taskId, diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java index a025236f0..a1392f20a 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java @@ -1,16 +1,20 @@ package io.a2a.transport.grpc.context; + +import java.util.Map; + +import io.a2a.spec.A2AMethods; import io.grpc.Context; /** * Shared gRPC context keys for A2A protocol data. - * + * * These keys provide access to gRPC context information similar to * Python's grpc.aio.ServicerContext, enabling rich context access * in service method implementations. */ public final class GrpcContextKeys { - + /** * Context key for storing the X-A2A-Version header value. * Set by server interceptors and accessed by service handlers. @@ -24,21 +28,28 @@ public final class GrpcContextKeys { */ public static final Context.Key EXTENSIONS_HEADER_KEY = Context.key("x-a2a-extensions"); - + /** * Context key for storing the complete gRPC Metadata object. * Provides access to all request headers and metadata. */ public static final Context.Key METADATA_KEY = Context.key("grpc-metadata"); - + /** * Context key for storing the method name being called. * Equivalent to Python's context.method() functionality. */ - public static final Context.Key METHOD_NAME_KEY = + public static final Context.Key GRPC_METHOD_NAME_KEY = Context.key("grpc-method-name"); + /** + * Context key for storing the method name being called. + * Equivalent to Python's context.method() functionality. + */ + public static final Context.Key METHOD_NAME_KEY = + Context.key("method"); + /** * Context key for storing the peer information. * Provides access to client connection details. @@ -46,6 +57,18 @@ public final class GrpcContextKeys { public static final Context.Key PEER_INFO_KEY = Context.key("grpc-peer-info"); + public static final Map METHOD_MAPPING = Map.of( + "SendMessage", A2AMethods.SEND_MESSAGE_METHOD, + "SendStreamingMessage", A2AMethods.SEND_STREAMING_MESSAGE_METHOD, + "GetTask", A2AMethods.GET_TASK_METHOD, + "ListTask", A2AMethods.LIST_TASK_METHOD, + "CancelTask", A2AMethods.CANCEL_TASK_METHOD, + "SubscribeToTask", A2AMethods.SUBSCRIBE_TO_TASK_METHOD, + "CreateTaskPushNotification", A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, + "GetTaskPushNotification", A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, + "ListTaskPushNotification", A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, + "DeleteTaskPushNotification", A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + private GrpcContextKeys() { // Utility class } 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 979bb5ef4..7a312a5d0 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 @@ -57,15 +57,17 @@ import io.a2a.spec.VersionNotSupportedError; import io.a2a.transport.grpc.context.GrpcContextKeys; import io.grpc.Context; +import io.grpc.Metadata; import io.grpc.Status; import io.grpc.stub.StreamObserver; +import org.jspecify.annotations.Nullable; @Vetoed public abstract class GrpcHandler extends A2AServiceGrpc.A2AServiceImplBase { // Hook so testing can wait until streaming subscriptions are established. // Without this we get intermittent failures - private static volatile Runnable streamingSubscribedRunnable; + private static volatile @Nullable Runnable streamingSubscribedRunnable; private final AtomicBoolean initialised = new AtomicBoolean(false); @@ -279,12 +281,14 @@ private void convertToStreamResponse(Flow.Publisher publishe ServerCallContext context) { CompletableFuture.runAsync(() -> { publisher.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; + private Flow.@Nullable Subscription subscription; @Override public void onSubscribe(Flow.Subscription subscription) { this.subscription = subscription; - subscription.request(1); + if (this.subscription != null) { + this.subscription.request(1); + } // Detect gRPC client disconnect and call EventConsumer.cancel() directly // This stops the polling loop without relying on subscription cancellation propagation @@ -318,17 +322,23 @@ public void onNext(StreamingEventKind event) { if (isFinal) { responseObserver.onCompleted(); } else { - subscription.request(1); + if (this.subscription != null) { + subscription.request(1); + } } } else { - subscription.request(1); + if (this.subscription != null) { + this.subscription.request(1); + } } } @Override public void onError(Throwable throwable) { // Cancel upstream to stop EventConsumer when error occurs - subscription.cancel(); + if (this.subscription != null) { + subscription.cancel(); + } if (throwable instanceof A2AError jsonrpcError) { handleError(responseObserver, jsonrpcError); } else { @@ -412,8 +422,12 @@ private ServerCallContext createCallContext(StreamObserver responseObserv if (grpcMetadata != null) { state.put("grpc_metadata", grpcMetadata); } - - String methodName = GrpcContextKeys.METHOD_NAME_KEY.get(currentContext); + Map headers= new HashMap<>(); + for(String key : grpcMetadata.keys()) { + headers.put(key, grpcMetadata.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER))); + } + state.put("headers", headers); + String methodName = GrpcContextKeys.GRPC_METHOD_NAME_KEY.get(currentContext); if (methodName != null) { state.put("grpc_method_name", methodName); } @@ -582,7 +596,7 @@ public static void setStreamingSubscribedRunnable(Runnable runnable) { * * @return the version header value, or null if not available */ - private String getVersionFromContext() { + private @Nullable String getVersionFromContext() { try { return GrpcContextKeys.VERSION_HEADER_KEY.get(); } catch (Exception e) { @@ -598,7 +612,7 @@ private String getVersionFromContext() { * * @return the extensions header value, or null if not available */ - private String getExtensionsFromContext() { + private @Nullable String getExtensionsFromContext() { try { return GrpcContextKeys.EXTENSIONS_HEADER_KEY.get(); } catch (Exception e) { @@ -618,7 +632,7 @@ private String getExtensionsFromContext() { * @param key the context key to retrieve * @return the context value, or null if not available */ - private static T getFromContext(Context.Key key) { + private static @Nullable T getFromContext(Context.Key key) { try { return key.get(); } catch (Exception e) { @@ -633,7 +647,7 @@ private static T getFromContext(Context.Key key) { * * @return the gRPC Metadata object, or null if not available */ - protected static io.grpc.Metadata getCurrentMetadata() { + protected static io.grpc.@Nullable Metadata getCurrentMetadata() { return getFromContext(GrpcContextKeys.METADATA_KEY); } @@ -643,8 +657,8 @@ protected static io.grpc.Metadata getCurrentMetadata() { * * @return the method name, or null if not available */ - protected static String getCurrentMethodName() { - return getFromContext(GrpcContextKeys.METHOD_NAME_KEY); + protected static @Nullable String getCurrentMethodName() { + return getFromContext(GrpcContextKeys.GRPC_METHOD_NAME_KEY); } /** @@ -653,7 +667,7 @@ protected static String getCurrentMethodName() { * * @return the peer information, or null if not available */ - protected static String getCurrentPeerInfo() { + protected static @Nullable String getCurrentPeerInfo() { return getFromContext(GrpcContextKeys.PEER_INFO_KEY); } } diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java new file mode 100644 index 000000000..0cc667b2d --- /dev/null +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java @@ -0,0 +1,9 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ +@NullMarked +package io.a2a.transport.grpc.handler; + +import org.jspecify.annotations.NullMarked; + 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 da22cf592..aa5ad4493 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 @@ -110,7 +110,6 @@ public SendMessageResponse onMessageSend(SendMessageRequest request, ServerCallC } } - public Flow.Publisher onMessageSendStream( SendStreamingMessageRequest request, ServerCallContext context) { if (!agentCard.capabilities().streaming()) { 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 7f206d336..f15f9af74 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 @@ -108,7 +108,8 @@ public RestHandler(AgentCard agentCard, RequestHandler requestHandler, Executor this.executor = executor; } - public HTTPRestResponse sendMessage(String body, String tenant, ServerCallContext context) { + public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, String body) { + try { A2AVersionValidator.validateProtocolVersion(agentCard, context); A2AExtensions.validateRequiredExtensions(agentCard, context); @@ -124,7 +125,7 @@ public HTTPRestResponse sendMessage(String body, String tenant, ServerCallContex } } - public HTTPRestResponse sendStreamingMessage(String body, String tenant, ServerCallContext context) { + public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String tenant, String body) { try { if (!agentCard.capabilities().streaming()) { return createErrorResponse(new InvalidRequestError("Streaming is not supported by the agent")); @@ -143,7 +144,7 @@ public HTTPRestResponse sendStreamingMessage(String body, String tenant, ServerC } } - public HTTPRestResponse cancelTask(String taskId, String tenant, ServerCallContext context) { + public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, String taskId) { try { if (taskId == null || taskId.isEmpty()) { throw new InvalidParamsError(); @@ -161,7 +162,7 @@ public HTTPRestResponse cancelTask(String taskId, String tenant, ServerCallConte } } - public HTTPRestResponse CreateTaskPushNotificationConfiguration(String taskId, String body, String tenant, ServerCallContext context) { + public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String body, String taskId) { try { if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); @@ -178,7 +179,7 @@ public HTTPRestResponse CreateTaskPushNotificationConfiguration(String taskId, S } } - public HTTPRestResponse subscribeToTask(String taskId, String tenant, ServerCallContext context) { + public HTTPRestResponse subscribeToTask(ServerCallContext context, String tenant, String taskId) { try { if (!agentCard.capabilities().streaming()) { return createErrorResponse(new InvalidRequestError("Streaming is not supported by the agent")); @@ -193,7 +194,7 @@ public HTTPRestResponse subscribeToTask(String taskId, String tenant, ServerCall } } - public HTTPRestResponse getTask(String taskId, @Nullable Integer historyLength, String tenant, ServerCallContext context) { + public HTTPRestResponse getTask(ServerCallContext context, String tenant, String taskId, @Nullable Integer historyLength) { try { TaskQueryParams params = new TaskQueryParams(taskId, historyLength, tenant); Task task = requestHandler.onGetTask(params, context); @@ -208,11 +209,11 @@ public HTTPRestResponse getTask(String taskId, @Nullable Integer historyLength, } } - public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String status, + public HTTPRestResponse listTasks(ServerCallContext context, String tenant, + @Nullable String contextId, @Nullable String status, @Nullable Integer pageSize, @Nullable String pageToken, @Nullable Integer historyLength, @Nullable String statusTimestampAfter, - @Nullable Boolean includeArtifacts, String tenant, - ServerCallContext context) { + @Nullable Boolean includeArtifacts) { try { // Build params ListTasksParams.Builder paramsBuilder = ListTasksParams.builder(); @@ -290,7 +291,7 @@ public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String s } } - public HTTPRestResponse getTaskPushNotificationConfiguration(String taskId, String configId, String tenant, ServerCallContext context) { + public HTTPRestResponse getTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String taskId, String configId) { try { if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); @@ -305,7 +306,7 @@ public HTTPRestResponse getTaskPushNotificationConfiguration(String taskId, Stri } } - public HTTPRestResponse listTaskPushNotificationConfigurations(String taskId, int pageSize, String pageToken, String tenant, ServerCallContext context) { + public HTTPRestResponse listTaskPushNotificationConfigurations(ServerCallContext context, String tenant, String taskId, int pageSize, String pageToken) { try { if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); @@ -320,7 +321,7 @@ public HTTPRestResponse listTaskPushNotificationConfigurations(String taskId, in } } - public HTTPRestResponse deleteTaskPushNotificationConfiguration(String taskId, String configId, String tenant, ServerCallContext context) { + public HTTPRestResponse deleteTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String taskId, String configId) { try { if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); @@ -478,7 +479,7 @@ private int mapErrorToHttpStatus(A2AError error) { return 500; } - public HTTPRestResponse getExtendedAgentCard(String tenant) { + public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String tenant) { try { if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { throw new ExtendedAgentCardNotConfiguredError(null, "Extended Card not configured", null); 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 a151f1288..a1e53d6ea 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 @@ -15,7 +15,6 @@ import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; -import io.a2a.server.tasks.AgentEmitter; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentExtension; @@ -35,13 +34,13 @@ public void testGetTaskSuccess() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - RestHandler.HTTPRestResponse response = handler.getTask(MINIMAL_TASK.id(), 0, "", callContext); + RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", MINIMAL_TASK.id(), 0); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); - response = handler.getTask(MINIMAL_TASK.id(),2 , "",callContext); + response = handler.getTask(callContext, "", MINIMAL_TASK.id(), 2); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -52,7 +51,7 @@ public void testGetTaskSuccess() { public void testGetTaskNotFound() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - RestHandler.HTTPRestResponse response = handler.getTask("nonexistent", 0, "",callContext); + RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", "nonexistent", 0); Assertions.assertEquals(404, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -64,8 +63,8 @@ public void testListTasksStatusWireString() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - RestHandler.HTTPRestResponse response = handler.listTasks(null, "submitted", null, null, - null, null, null, "", callContext); + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "submitted", null, null, + null, null, null); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -76,8 +75,8 @@ public void testListTasksStatusWireString() { public void testListTasksInvalidStatus() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - RestHandler.HTTPRestResponse response = handler.listTasks(null, "not-a-status", null, null, - null, null, null, "", callContext); + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "not-a-status", null, null, + null, null, null); Assertions.assertEquals(422, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -109,7 +108,7 @@ public void testSendMessage() throws InvalidProtocolBufferException { } }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); Assertions.assertEquals(200, response.getStatusCode(), response.toString()); Assertions.assertEquals("application/json", response.getContentType()); Assertions.assertNotNull(response.getBody()); @@ -120,7 +119,7 @@ public void testSendMessageInvalidBody() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); String invalidBody = "invalid json"; - RestHandler.HTTPRestResponse response = handler.sendMessage(invalidBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", invalidBody); Assertions.assertEquals(400, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -144,7 +143,7 @@ public void testSendMessageWrongValueBody() { } } }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); Assertions.assertEquals(422, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -155,7 +154,7 @@ public void testSendMessageWrongValueBody() { public void testSendMessageEmptyBody() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - RestHandler.HTTPRestResponse response = handler.sendMessage("", "", callContext); + RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", ""); Assertions.assertEquals(400, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -175,7 +174,7 @@ public void testCancelTaskSuccess() { agentEmitter.cancel(); }; - RestHandler.HTTPRestResponse response = handler.cancelTask(MINIMAL_TASK.id(), "", callContext); + RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", MINIMAL_TASK.id()); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -186,7 +185,7 @@ public void testCancelTaskSuccess() { public void testCancelTaskNotFound() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - RestHandler.HTTPRestResponse response = handler.cancelTask("nonexistent", "", callContext); + RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", "nonexistent"); Assertions.assertEquals(404, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -216,7 +215,7 @@ public void testSendStreamingMessageSuccess() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); Assertions.assertEquals(200, response.getStatusCode(), response.toString()); Assertions.assertInstanceOf(RestHandler.HTTPRestStreamingResponse.class, response); RestHandler.HTTPRestStreamingResponse streamingResponse = (RestHandler.HTTPRestStreamingResponse) response; @@ -239,7 +238,7 @@ public void testSendStreamingMessageNotSupported() { } """; - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); Assertions.assertEquals(400, response.getStatusCode()); Assertions.assertTrue(response.getBody().contains("InvalidRequestError")); @@ -262,7 +261,7 @@ public void testPushNotificationConfigSuccess() { } }""".formatted(MINIMAL_TASK.id()); - RestHandler.HTTPRestResponse response = handler.CreateTaskPushNotificationConfiguration( MINIMAL_TASK.id(), requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", requestBody, MINIMAL_TASK.id()); Assertions.assertEquals(201, response.getStatusCode(), response.toString()); Assertions.assertEquals("application/json", response.getContentType()); @@ -283,7 +282,7 @@ public void testPushNotificationConfigNotSupported() { } """.formatted(MINIMAL_TASK.id()); - RestHandler.HTTPRestResponse response = handler.CreateTaskPushNotificationConfiguration(MINIMAL_TASK.id(), requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", requestBody, MINIMAL_TASK.id()); Assertions.assertEquals(501, response.getStatusCode()); Assertions.assertTrue(response.getBody().contains("PushNotificationNotSupportedError")); @@ -306,11 +305,11 @@ public void testGetPushNotificationConfig() { } } }""".formatted(MINIMAL_TASK.id()); - RestHandler.HTTPRestResponse response = handler.CreateTaskPushNotificationConfiguration(MINIMAL_TASK.id(), createRequestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", createRequestBody, MINIMAL_TASK.id()); Assertions.assertEquals(201, response.getStatusCode(), response.toString()); Assertions.assertEquals("application/json", response.getContentType()); // Now get it - response = handler.getTaskPushNotificationConfiguration(MINIMAL_TASK.id(), "default-config-id", "", callContext); + response = handler.getTaskPushNotificationConfiguration(callContext, "", MINIMAL_TASK.id(), "default-config-id"); Assertions.assertEquals(200, response.getStatusCode(), response.toString()); Assertions.assertEquals("application/json", response.getContentType()); } @@ -319,7 +318,7 @@ public void testGetPushNotificationConfig() { public void testDeletePushNotificationConfig() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - RestHandler.HTTPRestResponse response = handler.deleteTaskPushNotificationConfiguration(MINIMAL_TASK.id(), "default-config-id", "", callContext); + RestHandler.HTTPRestResponse response = handler.deleteTaskPushNotificationConfiguration(callContext, "", MINIMAL_TASK.id(), "default-config-id"); Assertions.assertEquals(204, response.getStatusCode()); } @@ -328,7 +327,7 @@ public void testListPushNotificationConfigs() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - RestHandler.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(MINIMAL_TASK.id(), 0, "", "", callContext); + RestHandler.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(callContext, "", MINIMAL_TASK.id(), 0, ""); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -340,11 +339,11 @@ public void testHttpStatusCodeMapping() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); // Test 400 for invalid request - RestHandler.HTTPRestResponse response = handler.sendMessage("", "", callContext); + RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", ""); Assertions.assertEquals(400, response.getStatusCode()); // Test 404 for not found - response = handler.getTask("nonexistent", 0, "", callContext); + response = handler.getTask(callContext, "", "nonexistent", 0); Assertions.assertEquals(404, response.getStatusCode()); } @@ -384,7 +383,7 @@ public void testStreamingDoesNotBlockMainThread() throws Exception { }"""; // Start streaming - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertInstanceOf(RestHandler.HTTPRestStreamingResponse.class, response); @@ -472,7 +471,7 @@ public void testExtensionSupportRequiredErrorOnSendMessage() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); Assertions.assertEquals(400, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -520,7 +519,7 @@ public void testExtensionSupportRequiredErrorOnSendStreamingMessage() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); // Streaming responses embed errors in the stream with status 200 Assertions.assertEquals(200, response.getStatusCode()); @@ -621,7 +620,7 @@ public void testRequiredExtensionProvidedSuccess() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(requestBody, "", contextWithExtension); + RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithExtension, "", requestBody); // Should succeed without error Assertions.assertEquals(200, response.getStatusCode()); @@ -672,7 +671,7 @@ public void testVersionNotSupportedErrorOnSendMessage() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(requestBody, "", contextWithVersion); + RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithVersion, "", requestBody); Assertions.assertEquals(501, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -722,7 +721,7 @@ public void testVersionNotSupportedErrorOnSendStreamingMessage() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(requestBody, "", contextWithVersion); + RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(contextWithVersion, "", requestBody); // Streaming responses embed errors in the stream with status 200 Assertions.assertEquals(200, response.getStatusCode()); @@ -815,7 +814,7 @@ public void testCompatibleVersionSuccess() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(requestBody, "", contextWithVersion); + RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithVersion, "", requestBody); // Should succeed without error Assertions.assertEquals(200, response.getStatusCode()); @@ -863,7 +862,7 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(requestBody, "", callContext); + RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); // Should succeed without error (defaults to 1.0) Assertions.assertEquals(200, response.getStatusCode()); @@ -876,8 +875,8 @@ public void testListTasksNegativeTimestampReturns422() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); // Negative timestamp should return 422 (Invalid params) - RestHandler.HTTPRestResponse response = handler.listTasks(null, null, null, null, - null, "-1", null, "", callContext); + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, null, null, null, + null, "-1", null); Assertions.assertEquals(422, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -887,11 +886,9 @@ public void testListTasksNegativeTimestampReturns422() { @Test public void testListTasksUnixMillisecondsTimestamp() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - // Unix milliseconds timestamp are no longer accepted - RestHandler.HTTPRestResponse response = handler.listTasks(null, null, null, null, - null, "1234567", null, "", callContext); - + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, null, null, null, + null, "1234567", null); Assertions.assertEquals(422, response.getStatusCode()); } @@ -901,8 +898,8 @@ public void testListTasksProtobufEnumStatus() { taskStore.save(MINIMAL_TASK, false); // Protobuf enum format (TASK_STATE_SUBMITTED) should be accepted - RestHandler.HTTPRestResponse response = handler.listTasks(null, "TASK_STATE_SUBMITTED", null, null, - null, null, null, "", callContext); + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "TASK_STATE_SUBMITTED", null, null, + null, null, null); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -915,8 +912,8 @@ public void testListTasksEnumConstantStatus() { taskStore.save(MINIMAL_TASK, false); // Enum constant format (SUBMITTED) should be accepted - RestHandler.HTTPRestResponse response = handler.listTasks(null, "SUBMITTED", null, null, - null, null, null, "", callContext); + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "SUBMITTED", null, null, + null, null, null); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -928,8 +925,8 @@ public void testListTasksEmptyResultIncludesAllFields() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); // Query for a context that doesn't exist - should return empty result with all fields - RestHandler.HTTPRestResponse response = handler.listTasks("nonexistent-context-id", null, null, null, - null, null, null, "", callContext); + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", "nonexistent-context-id", null, null, null, + null, null, null); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); From de9355aa349e37579dffe142650da69b1789c1b5 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 11 Feb 2026 15:12:21 +0000 Subject: [PATCH 030/192] chore: Release 1.0.0.Alpha2 (#643) --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../io/a2a/examples/helloworld/HelloWorldRunner.java | 12 ++++++------ examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- extras/opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 2 +- .../tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- .../tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 50 files changed, 55 insertions(+), 55 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index c353e91af..8c3406098 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index f25631bbd..eac29ffcc 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index 963dfc8b5..c44a20428 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 1c241831d..d0e6e6243 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index ecbaaf454..aed0243b3 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 32e077cab..79b59047e 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 4437d4fe1..95eb6fb7e 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index ad4a14d56..30ee5939e 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index abba14137..254eaf707 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index c83d33bf2..a842295dc 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-common diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index d71434b81..e7f8f5415 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index 7f18c0ba8..d9b040527 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java index 0cd652283..4d52dee34 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha2-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha2-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha2-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha2-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha2-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha2-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha2 +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha2 +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha2 +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha2 +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha2 +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha2 //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index e48e2fdad..edc871d77 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index aea025993..88de973bd 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index 55bb98e71..48a8e846c 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 2bb4f1662..6685879a2 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index c3eac38f2..780677a6f 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-opentelemetry-client-propagation diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index daf97421c..bf844a937 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-opentelemetry-client diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index d21655202..d4ed6d04b 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-opentelemetry-common diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index 6d2b4734a..b3a1beb3c 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-opentelemetry-integration-tests diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 23e7867de..194f78504 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index cef51f092..abb0029b1 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-opentelemetry-server diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 4973fd8e8..07804ffd9 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 91646ca0f..ccfbcaddb 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 7ae399aff..e4e24672b 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 72d284cba..3216032ae 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index 31ea048fa..41fb14908 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index 5f7dc9812..06cc3b19d 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index 40c45a964..ecf8d4d2c 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index b45243e7f..f065408ed 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index a269f6c48..717bb4a67 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index c01e2c51e..331361212 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index ff99cf514..1ee50d350 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index af4dcb855..188122ae2 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 3b82074e1..fceba32de 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index dbbbf42cf..f8df3fd4c 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index dcf90ba44..60138b718 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index b9e8e57a7..b488c6dc7 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index b12a68153..b04b0b58c 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index c23c817fd..0441fb4a4 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index 796ff88fe..02ae79a32 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index 9c3d594fe..429391855 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index 3b2f28c0d..eb01f9bbb 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index d79c4fa07..3b44f1880 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-java-sdk-spec diff --git a/tck/pom.xml b/tck/pom.xml index 7b2db1b81..614fb5034 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 a2a-tck-server diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index fc5bbe52a..b5cfe7f14 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index 0c652c1c3..ce61a80b1 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index bb551b930..b852d33ed 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 3722ae44d..572f81863 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2-SNAPSHOT + 1.0.0.Alpha2 ../../pom.xml a2a-java-sdk-transport-rest From 17e5a0947c40ab8c06d0c140c145ead88ca7ffde Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Wed, 11 Feb 2026 18:48:38 +0100 Subject: [PATCH 031/192] chore: Reenable TCK testing for Pull Requests (#645) Signed-off-by: Jeff Mesnil --- .github/workflows/run-tck-1.0-wip.yml | 176 -------------------------- .github/workflows/run-tck.yml | 7 +- 2 files changed, 2 insertions(+), 181 deletions(-) delete mode 100644 .github/workflows/run-tck-1.0-wip.yml diff --git a/.github/workflows/run-tck-1.0-wip.yml b/.github/workflows/run-tck-1.0-wip.yml deleted file mode 100644 index b29c78c2c..000000000 --- a/.github/workflows/run-tck-1.0-wip.yml +++ /dev/null @@ -1,176 +0,0 @@ -name: Run TCK 1.0 (WIP) - -on: - # Handle all branches for now - push: - branches: - - main - #pull_request: - # branches: - # - main - workflow_dispatch: - -env: - # TODO this is currently running the TCK off the main branch which included changes needed for 0.4.0 - # Tag/branch of the TCK - TCK_VERSION: spec_1.0 - # Tell the TCK runner to report failure if the quality tests fail - A2A_TCK_FAIL_ON_QUALITY: 1 - # Tell the TCK runner to report failure if the features tests fail - A2A_TCK_FAIL_ON_FEATURES: 1 - # Tells uv to not need a venv, and instead use system - UV_SYSTEM_PYTHON: 1 - # SUT_JSONRPC_URL to use for the TCK and the server agent - SUT_JSONRPC_URL: http://localhost:9999 - # Slow system on CI - TCK_STREAMING_TIMEOUT: 5.0 - -# Only run the latest job -concurrency: - group: '${{ github.workflow }} @ ${{ github.head_ref || github.ref }}' - cancel-in-progress: true - -jobs: - tck-test: - runs-on: ubuntu-latest - strategy: - matrix: - java-version: [17] - steps: - - name: Checkout a2a-java - uses: actions/checkout@v4 - - name: Checkout a2a-tck - uses: actions/checkout@v4 - with: - repository: a2aproject/a2a-tck - path: tck/a2a-tck - ref: ${{ env.TCK_VERSION }} - - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v5 - with: - java-version: ${{ matrix.java-version }} - distribution: 'temurin' - cache: maven - - name: check java_home - run: echo $JAVA_HOME - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version-file: "tck/a2a-tck/pyproject.toml" - - name: Install uv and Python dependencies - run: | - pip install uv - uv pip install -e . - working-directory: tck/a2a-tck - - name: Build with Maven, skipping tests - run: mvn -B install -DskipTests - - name: Start SUT - run: SUT_GRPC_URL=${{ env.SUT_JSONRPC_URL }} SUT_REST_URL=${{ env.SUT_JSONRPC_URL }} mvn -B quarkus:dev & #SUT_JSONRPC_URL already set - working-directory: tck - - name: Wait for SUT to start - run: | - URL="${{ env.SUT_JSONRPC_URL }}/.well-known/agent-card.json" - EXPECTED_STATUS=200 - TIMEOUT=120 - RETRY_INTERVAL=2 - START_TIME=$(date +%s) - - while true; do - # Calculate elapsed time - CURRENT_TIME=$(date +%s) - ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) - - # Check for timeout - if [ "$ELAPSED_TIME" -ge "$TIMEOUT" ]; then - echo "❌ Timeout: Server did not respond with status $EXPECTED_STATUS within $TIMEOUT seconds." - exit 1 - fi - - # Get HTTP status code. || true is to reporting a failure to connect as an error - HTTP_STATUS=$(curl --output /dev/null --silent --write-out "%{http_code}" "$URL") || true - echo "STATUS: ${HTTP_STATUS}" - - # Check if we got the correct status code - if [ "$HTTP_STATUS" -eq "$EXPECTED_STATUS" ]; then - echo "✅ Server is up! Received status $HTTP_STATUS after $ELAPSED_TIME seconds." - break; - fi - - # Wait before retrying - echo "⏳ Server not ready (status: $HTTP_STATUS). Retrying in $RETRY_INTERVAL seconds..." - sleep "$RETRY_INTERVAL" - done - - - name: Run TCK (JSONRPC) - id: run-tck - timeout-minutes: 5 - run: | - set -o pipefail - ./run_tck.py --sut-url ${{ env.SUT_JSONRPC_URL }} --category all --transports jsonrpc --compliance-report report.json 2>&1 | tee tck-output.log - working-directory: tck/a2a-tck - - name: Capture Diagnostics on Failure - if: failure() - run: | - echo "=== Capturing diagnostic information ===" - - # Create diagnostics directory - mkdir -p tck/target/diagnostics - - # Capture process list - echo "📋 Capturing process list..." - ps auxww > tck/target/diagnostics/processes.txt - - # Find the actual Quarkus JVM (child of Maven process), not the Maven parent - # Look for the dev.jar process which is the actual application - QUARKUS_PID=$(pgrep -f "a2a-tck-server-dev.jar" || echo "") - if [ -n "$QUARKUS_PID" ]; then - echo "📊 Capturing thread dump for Quarkus JVM PID $QUARKUS_PID" - jstack $QUARKUS_PID > tck/target/diagnostics/thread-dump.txt || echo "Failed to capture thread dump" - if [ -f tck/target/diagnostics/thread-dump.txt ]; then - echo "✅ Thread dump captured ($(wc -l < tck/target/diagnostics/thread-dump.txt) lines)" - fi - else - echo "⚠️ No Quarkus JVM process found for thread dump" - echo "Available Java processes:" - ps aux | grep java | tee -a tck/target/diagnostics/processes.txt || true - fi - - # Capture Quarkus application logs (if available) - echo "📝 Checking for Quarkus logs..." - if [ -f tck/target/quarkus.log ]; then - cp tck/target/quarkus.log tck/target/diagnostics/ - echo "✅ Copied quarkus.log ($(wc -l < tck/target/quarkus.log) lines)" - fi - - # Copy TCK server logs - if [ -f tck/target/tck-test.log ]; then - cp tck/target/tck-test.log tck/target/diagnostics/ - echo "✅ Copied tck-test.log ($(wc -l < tck/target/tck-test.log) lines)" - fi - - echo "" - echo "=== Diagnostic capture complete ===" - - name: Stop Quarkus Server - if: always() - run: | - # Find and kill the Quarkus process to ensure logs are flushed - pkill -f "quarkus:dev" || true - sleep 2 - - name: Upload TCK Diagnostics - if: failure() - uses: actions/upload-artifact@v4 - with: - name: tck-diagnostics-java-${{ matrix.java-version }} - path: | - tck/target/diagnostics/ - tck/a2a-tck/tck-output.log - retention-days: 7 - if-no-files-found: warn - - name: Upload TCK Compliance Report - if: always() - uses: actions/upload-artifact@v4 - with: - name: tck-compliance-report-java-${{ matrix.java-version }} - path: tck/a2a-tck/report.json - retention-days: 14 - if-no-files-found: ignore diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index 5b14e4adb..babf6242a 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -5,18 +5,15 @@ on: push: branches: - main - - 0.3.x pull_request: branches: -# Disable TCK runs on main PRs for now, since we are making spec and TCK updates for 1.0.0 -# - main - - 0.3.x + - main workflow_dispatch: env: # TODO this is currently running the TCK off the main branch which included changes needed for 0.4.0 # Tag/branch of the TCK - TCK_VERSION: main + TCK_VERSION: spec_1.0 # Tell the TCK runner to report failure if the quality tests fail A2A_TCK_FAIL_ON_QUALITY: 1 # Tell the TCK runner to report failure if the features tests fail From c03a1d69f53b5bc038cd61a5e70ccaaee4130112 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 11 Feb 2026 17:51:30 +0000 Subject: [PATCH 032/192] chore: Next SNAPSHOT version (#644) --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../io/a2a/examples/helloworld/HelloWorldRunner.java | 12 ++++++------ examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- extras/opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 2 +- .../tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- .../tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 50 files changed, 55 insertions(+), 55 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 8c3406098..91cda330a 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index eac29ffcc..460074c89 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index c44a20428..9cdc502eb 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index d0e6e6243..557920c68 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index aed0243b3..927f23757 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 79b59047e..a8ce057a5 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 95eb6fb7e..2427ee501 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index 30ee5939e..9d9ac16bd 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index 254eaf707..9b8d75103 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index a842295dc..3778324c6 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-common diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index e7f8f5415..d789e5f63 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index d9b040527..1a70ed6e4 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java index 4d52dee34..c6aa974b6 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha2 -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha2 -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha2 -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha2 -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha2 -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha2 +//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha3-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha3-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha3-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha3-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha3-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha3-SNAPSHOT //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index edc871d77..53c397240 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 88de973bd..51fadf6fe 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index 48a8e846c..db773c8fa 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 6685879a2..98cc81a9b 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index 780677a6f..efa94d90d 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-opentelemetry-client-propagation diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index bf844a937..6793543d2 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-opentelemetry-client diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index d4ed6d04b..637bf8a04 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-opentelemetry-common diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index b3a1beb3c..6fd4fcc2e 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-opentelemetry-integration-tests diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 194f78504..710e94b44 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index abb0029b1..e94cc131a 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-opentelemetry-server diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 07804ffd9..3b57b9623 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index ccfbcaddb..93c70ba5e 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index e4e24672b..9a513118d 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 3216032ae..401d08c1c 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index 41fb14908..fdb60573f 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index 06cc3b19d..13b657d4e 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index ecf8d4d2c..d6c1d591c 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index f065408ed..ecccd7cb0 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index 717bb4a67..5b01c60fd 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index 331361212..77c3a217b 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 1ee50d350..34a214ed4 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index 188122ae2..3726fb4bb 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index fceba32de..59223d361 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index f8df3fd4c..0c44979d9 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index 60138b718..5ed76528b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index b488c6dc7..644baf44e 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index b04b0b58c..b54494747 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 0441fb4a4..e099711a3 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index 02ae79a32..a82b2278f 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index 429391855..909ba9bc0 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index eb01f9bbb..acb5222a8 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index 3b44f1880..3b70a3405 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-java-sdk-spec diff --git a/tck/pom.xml b/tck/pom.xml index 614fb5034..4c65f1fda 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT a2a-tck-server diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index b5cfe7f14..e7426469e 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index ce61a80b1..e0a8e2fe1 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index b852d33ed..cbd3cd912 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 572f81863..50c5c4389 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha2 + 1.0.0.Alpha3-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-rest From 7bf82c694a33ef8538c73db23d7aa42e84da3abb Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Thu, 12 Feb 2026 10:20:15 +0100 Subject: [PATCH 033/192] chore: Switch to the TCK main branch for 1.0 (#646) Signed-off-by: Jeff Mesnil --- .github/workflows/run-tck.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index babf6242a..75ed7819f 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -11,9 +11,8 @@ on: workflow_dispatch: env: - # TODO this is currently running the TCK off the main branch which included changes needed for 0.4.0 # Tag/branch of the TCK - TCK_VERSION: spec_1.0 + TCK_VERSION: main # Tell the TCK runner to report failure if the quality tests fail A2A_TCK_FAIL_ON_QUALITY: 1 # Tell the TCK runner to report failure if the features tests fail From 7c10908010e71165d973284794f0060ce6af3e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiberiu=20Sab=C4=83u?= <96194994+tibisabau@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:51:05 +0100 Subject: [PATCH 034/192] chore: Add tests for ClientTaskManager (#650) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #305 🦕 --- .../java/io/a2a/client/ClientTaskManager.java | 5 +- .../io/a2a/client/ClientTaskManagerTest.java | 323 ++++++++++++++++++ 2 files changed, 324 insertions(+), 4 deletions(-) create mode 100644 client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java diff --git a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java b/client/base/src/main/java/io/a2a/client/ClientTaskManager.java index ca29c2f6a..75e74743e 100644 --- a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java +++ b/client/base/src/main/java/io/a2a/client/ClientTaskManager.java @@ -115,10 +115,7 @@ public Task saveTaskEvent(TaskArtifactUpdateEvent taskArtifactUpdateEvent) { */ public Task updateWithMessage(Message message, Task task) { Task.Builder taskBuilder = Task.builder(task); - List history = task.history(); - if (history == null) { - history = new ArrayList<>(); - } + List history = new ArrayList<>(task.history()); if (task.status().message() != null) { history.add(task.status().message()); taskBuilder.status(new TaskStatus(task.status().state(), null, task.status().timestamp())); diff --git a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java b/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java new file mode 100644 index 000000000..c48237c46 --- /dev/null +++ b/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java @@ -0,0 +1,323 @@ +package io.a2a.client; + +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 static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.a2a.spec.A2AClientInvalidArgsError; +import io.a2a.spec.A2AClientInvalidStateError; +import io.a2a.spec.Artifact; +import io.a2a.spec.Message; +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.BeforeEach; +import org.junit.jupiter.api.Test; + +public class ClientTaskManagerTest { + + private ClientTaskManager taskManager; + private Task sampleTask; + private Message sampleMessage; + + @BeforeEach + public void setUp() { + taskManager = new ClientTaskManager(); + + sampleTask = Task.builder() + .id("task123") + .contextId("context456") + .status(new TaskStatus(TaskState.WORKING)) + .build(); + + sampleMessage = Message.builder() + .messageId("msg1") + .role(Message.Role.USER) + .parts(Collections.singletonList(new TextPart("Hello"))) + .build(); + } + + @Test + public void testGetCurrentTaskNoTaskRaisesError() { + A2AClientInvalidStateError exception = assertThrows( + A2AClientInvalidStateError.class, + () -> taskManager.getCurrentTask() + ); + assertTrue(exception.getMessage().contains("No current task")); + } + + @Test + public void testSaveTaskEventWithTask() throws Exception { + Task result = taskManager.saveTaskEvent(sampleTask); + + assertEquals(sampleTask, taskManager.getCurrentTask()); + assertEquals(sampleTask, result); + } + + @Test + public void testSaveTaskEventWithTaskAlreadySetRaisesError() throws Exception { + taskManager.saveTaskEvent(sampleTask); + + A2AClientInvalidArgsError exception = assertThrows( + A2AClientInvalidArgsError.class, + () -> taskManager.saveTaskEvent(sampleTask) + ); + assertTrue(exception.getMessage().contains("Task is already set, create new manager for new tasks.")); + } + + @Test + public void testSaveTaskEventWithStatusUpdate() throws Exception { + taskManager.saveTaskEvent(sampleTask); + + TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() + .taskId(sampleTask.id()) + .contextId(sampleTask.contextId()) + .status(new TaskStatus(TaskState.COMPLETED, sampleMessage, null)) + .build(); + + Task updatedTask = taskManager.saveTaskEvent(statusUpdate); + + assertEquals(TaskState.COMPLETED, updatedTask.status().state()); + assertNotNull(updatedTask.history()); + assertEquals(1, updatedTask.history().size()); + assertEquals(sampleMessage, updatedTask.history().get(0)); + } + + @Test + public void testSaveTaskEventWithStatusUpdateAndMetadata() throws Exception { + taskManager.saveTaskEvent(sampleTask); + + Map metadata = new HashMap<>(); + metadata.put("key1", "value1"); + metadata.put("key2", 42); + + TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() + .taskId(sampleTask.id()) + .contextId(sampleTask.contextId()) + .status(new TaskStatus(TaskState.WORKING)) + .metadata(metadata) + .build(); + + Task updatedTask = taskManager.saveTaskEvent(statusUpdate); + + assertNotNull(updatedTask.metadata()); + assertEquals("value1", updatedTask.metadata().get("key1")); + assertEquals(42, updatedTask.metadata().get("key2")); + } + + @Test + public void testSaveTaskEventWithArtifactUpdate() throws Exception { + taskManager.saveTaskEvent(sampleTask); + + Artifact artifact = Artifact.builder() + .artifactId("art1") + .parts(Collections.singletonList(new TextPart("artifact content"))) + .build(); + + TaskArtifactUpdateEvent artifactUpdate = TaskArtifactUpdateEvent.builder() + .taskId(sampleTask.id()) + .contextId(sampleTask.contextId()) + .artifact(artifact) + .build(); + + Task updatedTask = taskManager.saveTaskEvent(artifactUpdate); + + assertNotNull(updatedTask); + assertNotNull(updatedTask.artifacts()); + assertEquals(1, updatedTask.artifacts().size()); + assertEquals("art1", updatedTask.artifacts().get(0).artifactId()); + } + + @Test + public void testSaveTaskEventCreatesTaskIfNotExists() throws Exception { + TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() + .taskId("new_task") + .contextId("new_context") + .status(new TaskStatus(TaskState.WORKING)) + .build(); + + Task updatedTask = taskManager.saveTaskEvent(statusUpdate); + + assertNotNull(updatedTask); + assertEquals("new_task", updatedTask.id()); + assertEquals("new_context", updatedTask.contextId()); + assertEquals(TaskState.WORKING, updatedTask.status().state()); + } + + @Test + public void testSaveTaskEventCreatesTaskFromArtifactUpdateIfNotExists() { + Artifact artifact = Artifact.builder() + .artifactId("art1") + .parts(Collections.singletonList(new TextPart("artifact content"))) + .build(); + + TaskArtifactUpdateEvent artifactUpdate = TaskArtifactUpdateEvent.builder() + .taskId("new_task_id") + .contextId("new_context_id") + .artifact(artifact) + .build(); + + Task updatedTask = taskManager.saveTaskEvent(artifactUpdate); + + assertNotNull(updatedTask); + assertEquals("new_task_id", updatedTask.id()); + assertEquals("new_context_id", updatedTask.contextId()); + assertNotNull(updatedTask.artifacts()); + assertEquals(1, updatedTask.artifacts().size()); + } + + @Test + public void testUpdateWithMessage() { + // Use a task with mutable history list initialized properly + Task taskWithHistory = Task.builder() + .id("task123") + .contextId("context456") + .status(new TaskStatus(TaskState.WORKING)) + .build(); + + Task updatedTask = taskManager.updateWithMessage(sampleMessage, taskWithHistory); + + assertNotNull(updatedTask.history()); + assertEquals(1, updatedTask.history().size()); + assertEquals(sampleMessage, updatedTask.history().get(0)); + } + + @Test + public void testUpdateWithMessageMovesStatusMessage() { + Message statusMessage = Message.builder() + .messageId("status_msg") + .role(Message.Role.AGENT) + .parts(Collections.singletonList(new TextPart("Status"))) + .build(); + + Task taskWithStatusMessage = Task.builder() + .id("task123") + .contextId("context456") + .status(new TaskStatus(TaskState.WORKING, statusMessage, null)) + .build(); + + Task updatedTask = taskManager.updateWithMessage(sampleMessage, taskWithStatusMessage); + + assertNotNull(updatedTask.history()); + assertEquals(2, updatedTask.history().size()); + assertEquals(statusMessage, updatedTask.history().get(0)); + assertEquals(sampleMessage, updatedTask.history().get(1)); + assertNull(updatedTask.status().message()); + } + + @Test + public void testUpdateWithMessagePreservesExistingHistory() { + Message existingMessage = Message.builder() + .messageId("existing_msg") + .role(Message.Role.USER) + .parts(Collections.singletonList(new TextPart("Existing"))) + .build(); + + Task taskWithHistory = Task.builder() + .id("task123") + .contextId("context456") + .status(new TaskStatus(TaskState.WORKING)) + .history(List.of(existingMessage)) + .build(); + + Task updatedTask = taskManager.updateWithMessage(sampleMessage, taskWithHistory); + + assertNotNull(updatedTask.history()); + assertEquals(2, updatedTask.history().size()); + assertEquals(existingMessage, updatedTask.history().get(0)); + assertEquals(sampleMessage, updatedTask.history().get(1)); + } + + @Test + public void testSaveTaskEventMultipleStatusUpdates() throws Exception { + taskManager.saveTaskEvent(sampleTask); + + // First status update + TaskStatusUpdateEvent statusUpdate1 = TaskStatusUpdateEvent.builder() + .taskId(sampleTask.id()) + .contextId(sampleTask.contextId()) + .status(new TaskStatus(TaskState.WORKING, sampleMessage, null)) + .build(); + + Task updatedTask1 = taskManager.saveTaskEvent(statusUpdate1); + assertEquals(TaskState.WORKING, updatedTask1.status().state()); + assertEquals(1, updatedTask1.history().size()); + + // Second status update + Message secondMessage = Message.builder() + .messageId("msg2") + .role(Message.Role.AGENT) + .parts(Collections.singletonList(new TextPart("Second message"))) + .build(); + + TaskStatusUpdateEvent statusUpdate2 = TaskStatusUpdateEvent.builder() + .taskId(sampleTask.id()) + .contextId(sampleTask.contextId()) + .status(new TaskStatus(TaskState.COMPLETED, secondMessage, null)) + .build(); + + Task updatedTask2 = taskManager.saveTaskEvent(statusUpdate2); + assertEquals(TaskState.COMPLETED, updatedTask2.status().state()); + assertEquals(2, updatedTask2.history().size()); + } + + @Test + public void testSaveTaskEventMultipleArtifactUpdates() throws Exception { + taskManager.saveTaskEvent(sampleTask); + + // First artifact update + Artifact artifact1 = Artifact.builder() + .artifactId("art1") + .parts(Collections.singletonList(new TextPart("First artifact"))) + .build(); + + TaskArtifactUpdateEvent artifactUpdate1 = TaskArtifactUpdateEvent.builder() + .taskId(sampleTask.id()) + .contextId(sampleTask.contextId()) + .artifact(artifact1) + .build(); + + Task updatedTask1 = taskManager.saveTaskEvent(artifactUpdate1); + assertEquals(1, updatedTask1.artifacts().size()); + + // Second artifact update + Artifact artifact2 = Artifact.builder() + .artifactId("art2") + .parts(Collections.singletonList(new TextPart("Second artifact"))) + .build(); + + TaskArtifactUpdateEvent artifactUpdate2 = TaskArtifactUpdateEvent.builder() + .taskId(sampleTask.id()) + .contextId(sampleTask.contextId()) + .artifact(artifact2) + .build(); + + Task updatedTask2 = taskManager.saveTaskEvent(artifactUpdate2); + assertEquals(2, updatedTask2.artifacts().size()); + } + + @Test + public void testSaveTaskEventWithEmptyContextId() throws Exception { + TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() + .taskId("task_with_empty_context") + .contextId("") + .status(new TaskStatus(TaskState.SUBMITTED)) + .build(); + + Task updatedTask = taskManager.saveTaskEvent(statusUpdate); + + assertNotNull(updatedTask); + assertEquals("task_with_empty_context", updatedTask.id()); + assertEquals("", updatedTask.contextId()); + } +} From 14e5eeb373082850cbbd6ecc23b2f5fb5a00bf20 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 16 Feb 2026 16:26:37 +0100 Subject: [PATCH 035/192] chore: add workaround for container tests (#659) Signed-off-by: Jeff Mesnil --- .../queue-manager-replicated/tests-multi-instance/tests/pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index 5b01c60fd..c780ce02d 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -84,6 +84,8 @@ org.jboss.logmanager.LogManager + + 1.44 From b0e1255784a173b1a9514e568ecbc89806b81251 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Tue, 17 Feb 2026 08:57:52 +0100 Subject: [PATCH 036/192] feat!: Update TaskState enums (#660) Use the protobuf names for the TaskState enums and remove their textual representations so that the enum names are consistent with their String name. Rename UNKNOWN to UNRECOGNIZED to be consistent with the Protobuf definitions. TaskState.TASK_STATE_SUBMITTED is a mouthful but we have static imports for a reason :) This impacts the JPA serialization but I think it's worth having the same textual representation for the task state on the wire and the DB. Remove the TaskStateAdapter that is no longer needed for the JSON serialization. This fixes #652. Signed-off-by: Jeff Mesnil --- .../java/io/a2a/client/ClientTaskManager.java | 4 +- .../io/a2a/client/ClientTaskManagerTest.java | 28 +++---- .../JSONRPCTransportStreamingTest.java | 2 +- .../jsonrpc/JSONRPCTransportTest.java | 12 +-- .../jsonrpc/sse/SSEEventListenerTest.java | 8 +- .../client/transport/rest/RestTransport.java | 2 +- .../transport/rest/RestTransportTest.java | 8 +- .../rest/sse/SSEEventListenerTest.java | 8 +- .../spi/sse/SSEEventListenerTest.java | 17 ++-- .../it/OpenTelemetryA2ABaseTest.java | 8 +- ...nTelemetryRequestHandlerDecoratorTest.java | 10 +-- ...otificationConfigStoreIntegrationTest.java | 2 +- .../JpaPushNotificationConfigStoreTest.java | 10 +-- .../core/EventSerializationTest.java | 8 +- .../core/ReplicatedQueueManagerTest.java | 14 ++-- ...ctiveMessagingReplicationStrategyTest.java | 4 +- .../MultiInstanceReplicationTest.java | 2 +- .../KafkaReplicationIntegrationTest.java | 14 ++-- .../database/jpa/JpaDatabaseTaskStore.java | 4 +- .../taskstore/database/jpa/JpaTask.java | 21 ++--- .../JpaDatabaseTaskStoreIntegrationTest.java | 10 +-- .../jpa/JpaDatabaseTaskStoreTest.java | 78 ++++++++--------- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 43 ---------- .../common/wrappers/CancelTaskRequest.java | 2 +- .../common/wrappers/CancelTaskResponse.java | 2 +- .../StreamingEventKindSerializationTest.java | 16 ++-- .../common/json/TaskSerializationTest.java | 58 ++++++------- .../apps/quarkus/A2AServerRoutesTest.java | 14 ++-- .../io/a2a/server/events/EventConsumer.java | 2 +- .../DefaultRequestHandler.java | 9 +- .../io/a2a/server/tasks/AgentEmitter.java | 16 ++-- .../io/a2a/server/tasks/ResultAggregator.java | 4 +- .../java/io/a2a/server/tasks/TaskManager.java | 8 +- .../agentexecution/RequestContextTest.java | 14 ++-- .../a2a/server/events/EventConsumerTest.java | 10 +-- .../io/a2a/server/events/EventQueueTest.java | 4 +- .../AbstractA2ARequestHandlerTest.java | 2 +- .../io/a2a/server/tasks/AgentEmitterTest.java | 60 ++++++------- ...MemoryPushNotificationConfigStoreTest.java | 16 ++-- .../tasks/PushNotificationSenderTest.java | 17 ++-- .../server/tasks/ResultAggregatorTest.java | 21 +++-- .../io/a2a/server/tasks/TaskManagerTest.java | 36 ++++---- .../a2a/grpc/mapper/A2ACommonFieldMapper.java | 2 +- .../io/a2a/grpc/mapper/TaskStateMapper.java | 38 ++++----- .../grpc/mapper/StreamResponseMapperTest.java | 10 +-- .../java/io/a2a/grpc/utils/ToProtoTest.java | 10 +-- .../io/a2a/spec/TaskNotCancelableError.java | 8 +- spec/src/main/java/io/a2a/spec/TaskState.java | 84 +++++-------------- .../io/a2a/spec/TaskStatusUpdateEvent.java | 12 +-- .../a2a/tck/server/AgentExecutorProducer.java | 7 +- .../apps/common/AbstractA2AServerTest.java | 62 +++++++------- .../grpc/handler/GrpcHandlerTest.java | 10 +-- .../jsonrpc/handler/JSONRPCHandlerTest.java | 22 ++--- .../transport/rest/handler/RestHandler.java | 26 +----- .../rest/handler/RestHandlerTest.java | 6 +- 55 files changed, 400 insertions(+), 525 deletions(-) diff --git a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java b/client/base/src/main/java/io/a2a/client/ClientTaskManager.java index 75e74743e..0e49fc4f7 100644 --- a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java +++ b/client/base/src/main/java/io/a2a/client/ClientTaskManager.java @@ -60,7 +60,7 @@ public Task saveTaskEvent(TaskStatusUpdateEvent taskStatusUpdateEvent) throws A2 Task task = currentTask; if (task == null) { task = Task.builder() - .status(new TaskStatus(TaskState.UNKNOWN)) + .status(new TaskStatus(TaskState.UNRECOGNIZED)) .id(taskId) .contextId(contextId == null ? "" : contextId) .build(); @@ -96,7 +96,7 @@ public Task saveTaskEvent(TaskArtifactUpdateEvent taskArtifactUpdateEvent) { Task task = currentTask; if (task == null) { task = Task.builder() - .status(new TaskStatus(TaskState.UNKNOWN)) + .status(new TaskStatus(TaskState.UNRECOGNIZED)) .id(taskId) .contextId(contextId == null ? "" : contextId) .build(); diff --git a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java b/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java index c48237c46..44ecc7bb6 100644 --- a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java +++ b/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java @@ -37,7 +37,7 @@ public void setUp() { sampleTask = Task.builder() .id("task123") .contextId("context456") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); sampleMessage = Message.builder() @@ -82,12 +82,12 @@ public void testSaveTaskEventWithStatusUpdate() throws Exception { TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() .taskId(sampleTask.id()) .contextId(sampleTask.contextId()) - .status(new TaskStatus(TaskState.COMPLETED, sampleMessage, null)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED, sampleMessage, null)) .build(); Task updatedTask = taskManager.saveTaskEvent(statusUpdate); - assertEquals(TaskState.COMPLETED, updatedTask.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, updatedTask.status().state()); assertNotNull(updatedTask.history()); assertEquals(1, updatedTask.history().size()); assertEquals(sampleMessage, updatedTask.history().get(0)); @@ -104,7 +104,7 @@ public void testSaveTaskEventWithStatusUpdateAndMetadata() throws Exception { TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() .taskId(sampleTask.id()) .contextId(sampleTask.contextId()) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .metadata(metadata) .build(); @@ -143,7 +143,7 @@ public void testSaveTaskEventCreatesTaskIfNotExists() throws Exception { TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() .taskId("new_task") .contextId("new_context") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task updatedTask = taskManager.saveTaskEvent(statusUpdate); @@ -151,7 +151,7 @@ public void testSaveTaskEventCreatesTaskIfNotExists() throws Exception { assertNotNull(updatedTask); assertEquals("new_task", updatedTask.id()); assertEquals("new_context", updatedTask.contextId()); - assertEquals(TaskState.WORKING, updatedTask.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, updatedTask.status().state()); } @Test @@ -182,7 +182,7 @@ public void testUpdateWithMessage() { Task taskWithHistory = Task.builder() .id("task123") .contextId("context456") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task updatedTask = taskManager.updateWithMessage(sampleMessage, taskWithHistory); @@ -203,7 +203,7 @@ public void testUpdateWithMessageMovesStatusMessage() { Task taskWithStatusMessage = Task.builder() .id("task123") .contextId("context456") - .status(new TaskStatus(TaskState.WORKING, statusMessage, null)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, statusMessage, null)) .build(); Task updatedTask = taskManager.updateWithMessage(sampleMessage, taskWithStatusMessage); @@ -226,7 +226,7 @@ public void testUpdateWithMessagePreservesExistingHistory() { Task taskWithHistory = Task.builder() .id("task123") .contextId("context456") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .history(List.of(existingMessage)) .build(); @@ -246,11 +246,11 @@ public void testSaveTaskEventMultipleStatusUpdates() throws Exception { TaskStatusUpdateEvent statusUpdate1 = TaskStatusUpdateEvent.builder() .taskId(sampleTask.id()) .contextId(sampleTask.contextId()) - .status(new TaskStatus(TaskState.WORKING, sampleMessage, null)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, sampleMessage, null)) .build(); Task updatedTask1 = taskManager.saveTaskEvent(statusUpdate1); - assertEquals(TaskState.WORKING, updatedTask1.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, updatedTask1.status().state()); assertEquals(1, updatedTask1.history().size()); // Second status update @@ -263,11 +263,11 @@ public void testSaveTaskEventMultipleStatusUpdates() throws Exception { TaskStatusUpdateEvent statusUpdate2 = TaskStatusUpdateEvent.builder() .taskId(sampleTask.id()) .contextId(sampleTask.contextId()) - .status(new TaskStatus(TaskState.COMPLETED, secondMessage, null)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED, secondMessage, null)) .build(); Task updatedTask2 = taskManager.saveTaskEvent(statusUpdate2); - assertEquals(TaskState.COMPLETED, updatedTask2.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, updatedTask2.status().state()); assertEquals(2, updatedTask2.history().size()); } @@ -311,7 +311,7 @@ public void testSaveTaskEventWithEmptyContextId() throws Exception { TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() .taskId("task_with_empty_context") .contextId("") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); Task updatedTask = taskManager.saveTaskEvent(statusUpdate); 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 b06d07648..60805c2de 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 @@ -158,7 +158,7 @@ public void testA2AClientSubscribeToTask() throws Exception { Task task = (Task) eventKind; assertEquals("2", task.id()); assertEquals("context-1234", task.contextId()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); List artifacts = task.artifacts(); assertEquals(1, artifacts.size()); Artifact artifact = artifacts.get(0); diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index f6677ff13..e4983142b 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -122,7 +122,7 @@ public void testA2AClientSendMessage() throws Exception { Task task = (Task) result; assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); assertNotNull(task.contextId()); - assertEquals(TaskState.COMPLETED,task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED,task.status().state()); assertEquals(1, task.artifacts().size()); Artifact artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); @@ -235,7 +235,7 @@ public void testA2AClientGetTask() throws Exception { 10), null); assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.contextId()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); assertEquals(1, task.artifacts().size()); Artifact artifact = task.artifacts().get(0); assertEquals(1, artifact.parts().size()); @@ -287,7 +287,7 @@ public void testA2AClientCancelTask() throws Exception { Task task = client.cancelTask(new TaskIdParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null); assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.contextId()); - assertEquals(TaskState.CANCELED, task.status().state()); + assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); assertTrue(task.metadata().isEmpty()); } @@ -457,7 +457,7 @@ public void testA2AClientSendMessageWithFilePart() throws Exception { Task task = (Task) result; assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); assertNotNull(task.contextId()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); assertEquals(1, task.artifacts().size()); Artifact artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); @@ -517,7 +517,7 @@ public void testA2AClientSendMessageWithDataPart() throws Exception { Task task = (Task) result; assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); assertNotNull(task.contextId()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); assertEquals(1, task.artifacts().size()); Artifact artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); @@ -575,7 +575,7 @@ public void testA2AClientSendMessageWithMixedParts() throws Exception { Task task = (Task) result; assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); assertNotNull(task.contextId()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); assertEquals(1, task.artifacts().size()); Artifact artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); 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 23e162e7c..8bcf3ddad 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 @@ -50,7 +50,7 @@ public void testOnEventWithTaskResult() throws Exception { Task task = (Task) receivedEvent.get(); assertEquals("task-123", task.id()); assertEquals("context-456", task.contextId()); - assertEquals(TaskState.WORKING, task.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, task.status().state()); } @Test @@ -104,7 +104,7 @@ public void testOnEventWithTaskStatusUpdateEventEvent() throws Exception { assertEquals("1", taskStatusUpdateEvent.taskId()); assertEquals("2", taskStatusUpdateEvent.contextId()); assertFalse(taskStatusUpdateEvent.isFinal()); - assertEquals(TaskState.SUBMITTED, taskStatusUpdateEvent.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, taskStatusUpdateEvent.status().state()); } @Test @@ -184,7 +184,7 @@ public void testOnFailure() { @Test public void testFinalTaskStatusUpdateEventCancels() { - TaskStatus completedStatus = new TaskStatus(TaskState.COMPLETED); + TaskStatus completedStatus = new TaskStatus(TaskState.TASK_STATE_COMPLETED); // Use constructor since Builder doesn't have isFinal method TaskStatusUpdateEvent tsue = new TaskStatusUpdateEvent( "1234", @@ -243,7 +243,7 @@ public void testOnEventWithFinalTaskStatusUpdateEventEventCancels() throws Excep assertEquals("1", taskStatusUpdateEvent.taskId()); assertEquals("2", taskStatusUpdateEvent.contextId()); assertTrue(taskStatusUpdateEvent.isFinal()); - assertEquals(TaskState.COMPLETED, taskStatusUpdateEvent.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, taskStatusUpdateEvent.status().state()); assertTrue(future.cancelHandlerCalled); } 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 61fb29428..09e68b88a 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 @@ -250,7 +250,7 @@ private String buildListTasksQueryString(ListTasksParams request) { queryParts.add("contextId=" + URLEncoder.encode(request.contextId(), StandardCharsets.UTF_8)); } if (request.status() != null) { - queryParts.add("status=" + request.status().asString()); + queryParts.add("status=" + request.status()); } if (request.pageSize() != null) { queryParts.add("pageSize=" + request.pageSize()); diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index 476a93ba2..3e96a7b09 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -136,7 +136,7 @@ public void testSendMessage() throws Exception { Task task = (Task) result; assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", task.id()); assertEquals("context-1234", task.contextId()); - assertEquals(TaskState.SUBMITTED, task.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, task.status().state()); assertNull(task.status().message()); assertNull(task.metadata()); assertEquals(true, task.artifacts().isEmpty()); @@ -174,7 +174,7 @@ public void testCancelTask() throws Exception { RestTransport instance = new RestTransport(CARD); Task task = instance.cancelTask(new TaskIdParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), context); assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertEquals(TaskState.CANCELED, task.status().state()); + assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); assertNull(task.status().message()); assertNotNull(task.metadata()); assertTrue(task.metadata().isEmpty()); @@ -200,7 +200,7 @@ public void testGetTask() throws Exception { RestTransport instance = new RestTransport(CARD); Task task = instance.getTask(request, context); assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); assertNull(task.status().message()); assertNotNull(task.metadata()); assertTrue(task.metadata().isEmpty()); @@ -438,7 +438,7 @@ public void testSubscribe() throws Exception { Task task = (Task) eventKind; assertEquals("2", task.id()); assertEquals("context-1234", task.contextId()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); List artifacts = task.artifacts(); assertEquals(1, artifacts.size()); Artifact artifact = artifacts.get(0); diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java index eed199ab3..5ed15a631 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java @@ -91,7 +91,7 @@ public void testOnMessageWithTaskResult() { Task task = (Task) receivedEvent.get(); assertEquals("task-123", task.id()); assertEquals("context-456", task.contextId()); - assertEquals(TaskState.WORKING, task.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, task.status().state()); } @Test @@ -165,7 +165,7 @@ public void testOnMessageWithStatusUpdateEvent() { TaskStatusUpdateEvent taskStatusUpdateEvent = (TaskStatusUpdateEvent) receivedEvent.get(); assertEquals("1", taskStatusUpdateEvent.taskId()); assertEquals("2", taskStatusUpdateEvent.contextId()); - assertEquals(TaskState.SUBMITTED, taskStatusUpdateEvent.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, taskStatusUpdateEvent.status().state()); assertEquals(false, taskStatusUpdateEvent.isFinal()); } @@ -200,7 +200,7 @@ public void testOnMessageWithFinalStatusUpdateEventCancels() { assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); TaskStatusUpdateEvent received = (TaskStatusUpdateEvent) receivedEvent.get(); assertTrue(received.isFinal()); - assertEquals(TaskState.COMPLETED, received.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, received.status().state()); // Verify the future was cancelled (auto-close on final event) assertTrue(future.wasCancelled()); @@ -236,7 +236,7 @@ public void testOnMessageWithCompletedTaskCancels() { assertNotNull(receivedEvent.get()); assertTrue(receivedEvent.get() instanceof Task); Task task = (Task) receivedEvent.get(); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); // Verify the future was cancelled (auto-close on final task state) assertTrue(future.wasCancelled()); diff --git a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java index ac1392c5e..f09670d55 100644 --- a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java +++ b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java @@ -10,7 +10,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import java.util.stream.Stream; import io.a2a.spec.Message; import io.a2a.spec.StreamingEventKind; @@ -22,9 +21,7 @@ import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.MethodSource; /** * Tests for BaseSSEEventListener abstract class. @@ -161,7 +158,7 @@ public void testHandleEventWithNullErrorHandler() { AtomicReference receivedEvent = new AtomicReference<>(); TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - Task task = createTask(TaskState.WORKING); + Task task = createTask(TaskState.TASK_STATE_WORKING); listener.setEventToHandle(task); listener.onMessage(TEST_TEXT, null); @@ -209,7 +206,7 @@ public void testOnErrorCancelsFuture() { @Test public void testShouldAutoCloseWithFinalTaskStatusUpdateEvent() { TestSSEEventListener listener = createBasicListener(); - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.COMPLETED, true); + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); assertTrue(listener.shouldAutoClose(finalEvent)); } @@ -217,13 +214,13 @@ public void testShouldAutoCloseWithFinalTaskStatusUpdateEvent() { @Test public void testShouldAutoCloseWithNonFinalTaskStatusUpdateEvent() { TestSSEEventListener listener = createBasicListener(); - TaskStatusUpdateEvent nonFinalEvent = createTaskStatusUpdateEvent(TaskState.WORKING, false); + TaskStatusUpdateEvent nonFinalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_WORKING, false); assertFalse(listener.shouldAutoClose(nonFinalEvent)); } @ParameterizedTest - @EnumSource(value = TaskState.class, names = {"COMPLETED", "FAILED", "CANCELED"}) + @EnumSource(value = TaskState.class, names = {"TASK_STATE_COMPLETED", "TASK_STATE_FAILED", "TASK_STATE_CANCELED"}) public void testShouldAutoCloseWithFinalTaskStates(TaskState finalState) { TestSSEEventListener listener = createBasicListener(); Task task = createTask(finalState); @@ -233,7 +230,7 @@ public void testShouldAutoCloseWithFinalTaskStates(TaskState finalState) { } @ParameterizedTest - @EnumSource(value = TaskState.class, names = {"WORKING", "SUBMITTED"}) + @EnumSource(value = TaskState.class, names = {"TASK_STATE_WORKING", "TASK_STATE_SUBMITTED"}) public void testShouldAutoCloseWithNonFinalTaskStates(TaskState nonFinalState) { TestSSEEventListener listener = createBasicListener(); Task task = createTask(nonFinalState); @@ -255,7 +252,7 @@ public void testAutoCloseCancelsFutureForFinalEvent() { AtomicReference receivedEvent = new AtomicReference<>(); TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.COMPLETED, true); + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); CancelCapturingFuture future = new CancelCapturingFuture(); listener.setEventToHandle(finalEvent); @@ -286,7 +283,7 @@ public void testAutoCloseWithNullFuture() { AtomicReference receivedEvent = new AtomicReference<>(); TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.COMPLETED, true); + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); // Should not throw with null future listener.setEventToHandle(finalEvent); diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java index 2171b2fc1..50c8c82ed 100644 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java +++ b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java @@ -69,7 +69,7 @@ void testGetTaskCreatesSpans() throws Exception { Task task = Task.builder() .id(taskId) .contextId(contextId) - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .history(Collections.emptyList()) .artifacts(Collections.emptyList()) .build(); @@ -146,7 +146,7 @@ void testCancelTaskCreatesSpans() throws Exception { Task task = Task.builder() .id(taskId) .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .history(Collections.emptyList()) .artifacts(Collections.emptyList()) .build(); @@ -159,7 +159,7 @@ void testCancelTaskCreatesSpans() throws Exception { Task cancelledTask = client.cancelTask(new TaskIdParams(taskId), null); assertNotNull(cancelledTask); - assertEquals(TaskState.CANCELED, cancelledTask.status().state()); + assertEquals(TaskState.TASK_STATE_CANCELED, cancelledTask.status().state()); Thread.sleep(5000); @@ -191,7 +191,7 @@ void testSpanAttributes() throws Exception { Task task = Task.builder() .id(taskId) .contextId(contextId) - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .history(Collections.emptyList()) .artifacts(Collections.emptyList()) .build(); diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java index 2f67e4a05..47c791976 100644 --- a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java +++ b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java @@ -93,7 +93,7 @@ void onGetTask_createsSpanAndDelegatesToHandler() throws A2AError { Task result = Task.builder() .id("task-123") .contextId("ctx-1") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .history(Collections.emptyList()) .artifacts(Collections.emptyList()) .build(); @@ -167,7 +167,7 @@ void onCancelTask_createsSpanAndDelegatesToHandler() throws A2AError { Task result = Task.builder() .id("task-123") .contextId("ctx-1") - .status(new TaskStatus(TaskState.CANCELED)) + .status(new TaskStatus(TaskState.TASK_STATE_CANCELED)) .history(Collections.emptyList()) .artifacts(Collections.emptyList()) .build(); @@ -212,7 +212,7 @@ void onMessageSend_createsSpanAndDelegatesToHandler() throws A2AError { EventKind result = Task.builder() .id("task-123") .contextId("ctx-1") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .history(Collections.emptyList()) .artifacts(Collections.emptyList()) .build(); @@ -461,7 +461,7 @@ void allMethods_createAndEndSpans() throws A2AError { Task result = Task.builder() .id("task-123") .contextId("ctx-1") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .history(Collections.emptyList()) .artifacts(Collections.emptyList()) .build(); @@ -479,7 +479,7 @@ void spanAttributes_setCorrectly() throws A2AError { Task result = Task.builder() .id("task-123") .contextId("ctx-1") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .history(Collections.emptyList()) .artifacts(Collections.emptyList()) .build(); 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 96f8f3adc..059806780 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 @@ -85,7 +85,7 @@ public void testDirectNotificationTrigger() { Task testTask = Task.builder() .id("direct-test-task") .contextId("test-context") - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.SUBMITTED)) + .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_SUBMITTED)) .build(); // Directly trigger the mock 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 6ecf045eb..79f422b27 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 @@ -234,7 +234,7 @@ public void testDeleteInfoWithNullConfigId() { @Transactional public void testSendNotificationSuccess() throws Exception { String taskId = "task_send_success"; - Task task = createSampleTask(taskId, TaskState.COMPLETED); + Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); configStore.setInfo(taskId, config); @@ -259,7 +259,7 @@ public void testSendNotificationSuccess() throws Exception { // Verify the request body contains the task data String sentBody = bodyCaptor.getValue(); assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().asString())); + assertTrue(sentBody.contains(task.status().state().name())); } @Test @@ -267,7 +267,7 @@ public void testSendNotificationSuccess() throws Exception { @Disabled("Token authentication is not yet implemented in BasePushNotificationSender (TODO auth)") public void testSendNotificationWithToken() throws Exception { String taskId = "task_send_with_token"; - Task task = createSampleTask(taskId, TaskState.COMPLETED); + Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); configStore.setInfo(taskId, config); @@ -295,14 +295,14 @@ public void testSendNotificationWithToken() throws Exception { // Verify the request body contains the task data String sentBody = bodyCaptor.getValue(); assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().asString())); + assertTrue(sentBody.contains(task.status().state().name())); } @Test @Transactional public void testSendNotificationNoConfig() throws Exception { String taskId = "task_send_no_config"; - Task task = createSampleTask(taskId, TaskState.COMPLETED); + Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); notificationSender.sendNotification(task); 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 33eaa908f..ce45b6d51 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 @@ -44,7 +44,7 @@ public class EventSerializationTest { @Test public void testTaskSerialization() throws JsonProcessingException { // Create a Task - TaskStatus status = new TaskStatus(TaskState.SUBMITTED); + TaskStatus status = new TaskStatus(TaskState.TASK_STATE_SUBMITTED); Task originalTask = Task.builder() .id("test-task-123") .contextId("test-context-456") @@ -105,7 +105,7 @@ public void testMessageSerialization() throws JsonProcessingException { @Test public void testTaskStatusUpdateEventSerialization() throws JsonProcessingException { // Create a TaskStatusUpdateEvent - TaskStatus status = new TaskStatus(TaskState.COMPLETED); + TaskStatus status = new TaskStatus(TaskState.TASK_STATE_COMPLETED); TaskStatusUpdateEvent originalEvent = TaskStatusUpdateEvent.builder() .taskId("test-task-abc") .contextId("test-context-def") @@ -204,7 +204,7 @@ public void testReplicatedEventWithStreamingEventSerialization() throws JsonProc TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() .taskId("replicated-test-task") .contextId("replicated-test-context") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); // Create ReplicatedEventQueueItem with StreamingEventKind @@ -277,7 +277,7 @@ public void testReplicatedEventBackwardCompatibility() throws JsonProcessingExce TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() .taskId("backward-compat-task") .contextId("backward-compat-context") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); // Use the backward compatibility constructor 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 e69971adc..7c830fb64 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 @@ -66,7 +66,7 @@ void setUp() { testEvent = TaskStatusUpdateEvent.builder() .taskId("test-task") .contextId("test-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); } @@ -78,7 +78,7 @@ private TaskStatusUpdateEvent createEventForTask(String taskId) { return TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId("test-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); } @@ -274,7 +274,7 @@ void testReplicatedEventJsonSerialization() throws Exception { TaskStatusUpdateEvent originalEvent = TaskStatusUpdateEvent.builder() .taskId("json-test-task") .contextId("json-test-context") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); ReplicatedEventQueueItem original = new ReplicatedEventQueueItem("json-test-task", originalEvent); @@ -346,7 +346,7 @@ public void onTaskFinalized(String tid) { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId(taskId) // Use same taskId as queue .contextId("test-context") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); queue.enqueueEvent(event); } @@ -371,7 +371,7 @@ public void onTaskFinalized(String tid) { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId(taskId) // Use same taskId as queue .contextId("test-context") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, event); queueManager.onReplicatedEvent(replicatedEvent); @@ -499,7 +499,7 @@ void testReplicatedEventToExistingQueueWhenTaskBecomesInactive() throws Interrup TaskStatusUpdateEvent newEvent = TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId("test-context") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, newEvent); queueManager.onReplicatedEvent(replicatedEvent); @@ -534,7 +534,7 @@ void testPoisonPillSentViaTransactionAwareEvent() throws InterruptedException { Task finalTask = Task.builder() .id(taskId) .contextId("test-context") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); TaskFinalizedEvent taskFinalizedEvent = new TaskFinalizedEvent(taskId, finalTask); 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 81bb9ffe0..d1f48aeb4 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 @@ -43,7 +43,7 @@ public void setUp() { testEvent = TaskStatusUpdateEvent.builder() .taskId("test-task") .contextId("test-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); } @@ -52,7 +52,7 @@ private String createValidJsonMessage(String taskId, String contextId) throws Ex TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, event); return JsonUtil.toJson(replicatedEvent); diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java index 81bc23af3..44b8d88b8 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java @@ -280,7 +280,7 @@ public void testMultiInstanceEventReplication() throws Exception { // Task should be in a non-final state (SUBMITTED or WORKING are both valid) TaskState state = createdTask.status().state(); - assertTrue(state == TaskState.SUBMITTED || state == TaskState.WORKING, + assertTrue(state == TaskState.TASK_STATE_SUBMITTED || state == TaskState.TASK_STATE_WORKING, "Task should be in SUBMITTED or WORKING state, but was: " + state); nonStreamingClient.close(); } catch (Exception e) { 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 26fd1bb2d..43716a040 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 @@ -165,7 +165,7 @@ public void testA2AMessageReplicatedToKafka() throws Exception { Task task = createdTask.get(); assertNotNull(task, "Task should be created"); assertEquals(taskId, task.id()); - assertEquals(TaskState.SUBMITTED, task.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, task.status().state()); // Wait for the event to be replicated to Kafka ReplicatedEventQueueItem replicatedEvent = testConsumer.waitForEvent(taskId, 30); @@ -184,7 +184,7 @@ public void testA2AMessageReplicatedToKafka() throws Exception { // Verify the event data is consistent with the task returned from the client assertEquals(taskId, statusUpdateEvent.taskId(), "Event task ID should match original task ID"); assertEquals(contextId, statusUpdateEvent.contextId(), "Event context ID should match original context ID"); - assertEquals(TaskState.SUBMITTED, statusUpdateEvent.status().state(), "Event should show SUBMITTED state"); + assertEquals(TaskState.TASK_STATE_SUBMITTED, statusUpdateEvent.status().state(), "Event should show SUBMITTED state"); assertFalse(statusUpdateEvent.isFinal(), "Event should show final:false"); assertEquals(TaskStatusUpdateEvent.STREAMING_EVENT_ID, statusUpdateEvent.kind(), "Event should indicate status-update type"); } @@ -221,7 +221,7 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { assertTrue(createLatch.await(15, TimeUnit.SECONDS), "Task creation timed out"); Task initialTask = createdTask.get(); assertNotNull(initialTask, "Task should be created"); - assertEquals(TaskState.SUBMITTED, initialTask.status().state(), "Initial task should be in SUBMITTED state"); + assertEquals(TaskState.TASK_STATE_SUBMITTED, initialTask.status().state(), "Initial task should be in SUBMITTED state"); // Add a small delay to ensure the task is fully processed before resubscription Thread.sleep(1000); @@ -248,7 +248,7 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { // Process subsequent events if (event instanceof TaskUpdateEvent taskUpdateEvent) { if (taskUpdateEvent.getUpdateEvent() instanceof TaskStatusUpdateEvent statusEvent) { - if (statusEvent.status().state() == TaskState.COMPLETED) { + if (statusEvent.status().state() == TaskState.TASK_STATE_COMPLETED) { receivedCompletedEvent.set(statusEvent); subscribeLatch.countDown(); } @@ -277,7 +277,7 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId(contextId) - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, statusEvent); @@ -297,7 +297,7 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { // Verify the received event TaskStatusUpdateEvent completedEvent = receivedCompletedEvent.get(); assertNotNull(completedEvent, "Should have received a TaskStatusUpdateEvent"); - assertEquals(TaskState.COMPLETED, completedEvent.status().state(), "Event should show COMPLETED state"); + assertEquals(TaskState.TASK_STATE_COMPLETED, completedEvent.status().state(), "Event should show COMPLETED state"); assertTrue(completedEvent.isFinal(), "Event should be marked as final"); assertEquals(taskId, completedEvent.taskId(), "Event should have correct task ID"); assertEquals(contextId, completedEvent.contextId(), "Event should have correct context ID"); @@ -334,7 +334,7 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { taskIdRef.set(taskEvent.getTask().id()); workingLatch.countDown(); } else if (event instanceof TaskUpdateEvent tue && tue.getUpdateEvent() instanceof TaskStatusUpdateEvent status) { - if (status.status().state() == TaskState.WORKING) { + if (status.status().state() == TaskState.TASK_STATE_WORKING) { taskIdRef.set(status.taskId()); workingLatch.countDown(); } 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 a4afa8588..086e640e3 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 @@ -275,7 +275,7 @@ public ListTasksResult list(ListTasksParams params) { query.setParameter("contextId", params.contextId()); } if (params.status() != null) { - query.setParameter("state", params.status().asString()); + query.setParameter("state", params.status().name()); } if (params.statusTimestampAfter() != null) { query.setParameter("statusTimestampAfter", params.statusTimestampAfter()); @@ -304,7 +304,7 @@ public ListTasksResult list(ListTasksParams params) { countQuery.setParameter("contextId", params.contextId()); } if (params.status() != null) { - countQuery.setParameter("state", params.status().asString()); + countQuery.setParameter("state", params.status().name()); } if (params.statusTimestampAfter() != null) { countQuery.setParameter("statusTimestampAfter", params.statusTimestampAfter()); 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 021a693e3..5a9477f2f 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 @@ -141,18 +141,11 @@ static JpaTask createFromTask(Task task) throws JsonProcessingException { */ private void updateDenormalizedFields(Task task) { this.contextId = task.contextId(); - if (task.status() != null) { - io.a2a.spec.TaskState taskState = task.status().state(); - this.state = (taskState != null) ? taskState.asString() : null; - // Extract status timestamp for efficient querying and sorting - // Truncate to milliseconds for keyset pagination consistency (pageToken uses millis) - this.statusTimestamp = (task.status().timestamp() != null) - ? task.status().timestamp().toInstant().truncatedTo(java.time.temporal.ChronoUnit.MILLIS) - : null; - } else { - this.state = null; - this.statusTimestamp = null; - } + io.a2a.spec.TaskState taskState = task.status().state(); + this.state = taskState.name(); + // Extract status timestamp for efficient querying and sorting + // Truncate to milliseconds for keyset pagination consistency (pageToken uses millis) + this.statusTimestamp = task.status().timestamp().toInstant().truncatedTo(java.time.temporal.ChronoUnit.MILLIS); } /** @@ -162,8 +155,6 @@ private void updateDenormalizedFields(Task task) { * @param task the task to check for finalization */ private void updateFinalizedTimestamp(Task task) { - if (task.status() != null && task.status().state() != null) { - setFinalizedAt(Instant.now(), task.status().state().isFinal()); - } + setFinalizedAt(Instant.now(), task.status().state().isFinal()); } } diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java index 1fa3c3e99..010c6abf7 100644 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java +++ b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java @@ -100,7 +100,7 @@ public void testJpaDatabaseTaskStore() throws Exception { Task createdTask = taskRef.get(); assertNotNull(createdTask); assertEquals(0, createdTask.artifacts().size()); - assertEquals(TaskState.SUBMITTED, createdTask.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, createdTask.status().state()); // Send a message updating the Task userMessage = Message.builder() @@ -129,23 +129,23 @@ public void testJpaDatabaseTaskStore() throws Exception { Task updatedTask = taskRef2.get(); assertNotNull(updatedTask); assertEquals(1, updatedTask.artifacts().size()); - assertEquals(TaskState.SUBMITTED, updatedTask.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, updatedTask.status().state()); Task retrievedTask = client.getTask(new TaskQueryParams(taskId), null); assertNotNull(retrievedTask); assertEquals(1, retrievedTask.artifacts().size()); - assertEquals(TaskState.SUBMITTED, retrievedTask.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, retrievedTask.status().state()); // Cancel the task Task cancelledTask = client.cancelTask(new TaskIdParams(taskId), null); assertNotNull(cancelledTask); assertEquals(1, cancelledTask.artifacts().size()); - assertEquals(TaskState.CANCELED, cancelledTask.status().state()); + assertEquals(TaskState.TASK_STATE_CANCELED, cancelledTask.status().state()); Task retrievedCancelledTask = client.getTask(new TaskQueryParams(taskId), null); assertNotNull(retrievedCancelledTask); assertEquals(1, retrievedCancelledTask.artifacts().size()); - assertEquals(TaskState.CANCELED, retrievedCancelledTask.status().state()); + assertEquals(TaskState.TASK_STATE_CANCELED, retrievedCancelledTask.status().state()); // None of the framework code deletes tasks, so just do this manually taskStore.delete(taskId); 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 15c01a626..2902b7d7d 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 @@ -49,7 +49,7 @@ public void testSaveAndRetrieveTask() { Task task = Task.builder() .id("test-task-1") .contextId("test-context-1") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .metadata(new HashMap<>()) .build(); @@ -62,7 +62,7 @@ public void testSaveAndRetrieveTask() { assertNotNull(retrieved); assertEquals("test-task-1", retrieved.id()); assertEquals("test-context-1", retrieved.contextId()); - assertEquals(TaskState.SUBMITTED, retrieved.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, retrieved.status().state()); } @Test @@ -79,7 +79,7 @@ public void testSaveAndRetrieveTaskWithHistory() { Task task = Task.builder() .id("test-task-2") .contextId("test-context-2") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .history(Collections.singletonList(message)) .build(); @@ -92,7 +92,7 @@ public void testSaveAndRetrieveTaskWithHistory() { assertNotNull(retrieved); assertEquals("test-task-2", retrieved.id()); assertEquals("test-context-2", retrieved.contextId()); - assertEquals(TaskState.WORKING, retrieved.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, retrieved.status().state()); assertEquals(1, retrieved.history().size()); assertEquals("msg-1", retrieved.history().get(0).messageId()); assertEquals("Hello, agent!", ((TextPart) retrieved.history().get(0).parts().get(0)).text()); @@ -105,7 +105,7 @@ public void testUpdateExistingTask() { Task initialTask = Task.builder() .id("test-task-3") .contextId("test-context-3") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); taskStore.save(initialTask, false); @@ -114,7 +114,7 @@ public void testUpdateExistingTask() { Task updatedTask = Task.builder() .id("test-task-3") .contextId("test-context-3") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); taskStore.save(updatedTask, false); @@ -124,7 +124,7 @@ public void testUpdateExistingTask() { assertNotNull(retrieved); assertEquals("test-task-3", retrieved.id()); - assertEquals(TaskState.COMPLETED, retrieved.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, retrieved.status().state()); } @Test @@ -141,7 +141,7 @@ public void testDeleteTask() { Task task = Task.builder() .id("test-task-4") .contextId("test-context-4") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); taskStore.save(task, false); @@ -175,7 +175,7 @@ public void testTaskWithComplexMetadata() { Task task = Task.builder() .id("test-task-5") .contextId("test-context-5") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .metadata(metadata) .build(); @@ -198,7 +198,7 @@ public void testIsTaskActiveForNonFinalTask() { Task task = Task.builder() .id("test-task-active-1") .contextId("test-context") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); taskStore.save(task, false); @@ -217,7 +217,7 @@ public void testIsTaskActiveForFinalTaskWithinGracePeriod() { Task task = Task.builder() .id("test-task-active-2") .contextId("test-context") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); taskStore.save(task, false); @@ -226,7 +226,7 @@ public void testIsTaskActiveForFinalTaskWithinGracePeriod() { Task finalTask = Task.builder() .id("test-task-active-2") .contextId("test-context") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); taskStore.save(finalTask, false); @@ -245,7 +245,7 @@ public void testIsTaskActiveForFinalTaskBeyondGracePeriod() { Task task = Task.builder() .id("test-task-active-3") .contextId("test-context") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); taskStore.save(task, false); @@ -307,19 +307,19 @@ public void testListTasksFilterByContextId() { Task task1 = Task.builder() .id("task-context-1") .contextId("context-A") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); Task task2 = Task.builder() .id("task-context-2") .contextId("context-A") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task task3 = Task.builder() .id("task-context-3") .contextId("context-B") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); taskStore.save(task1, false); @@ -346,19 +346,19 @@ public void testListTasksFilterByStatus() { Task task1 = Task.builder() .id("task-status-filter-1") .contextId("context-status-filter-test") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); Task task2 = Task.builder() .id("task-status-filter-2") .contextId("context-status-filter-test") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task task3 = Task.builder() .id("task-status-filter-3") .contextId("context-status-filter-test") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); taskStore.save(task1, false); @@ -369,14 +369,14 @@ public void testListTasksFilterByStatus() { ListTasksParams params = ListTasksParams.builder() .contextId("context-status-filter-test") .tenant("tenant") - .status(TaskState.WORKING) + .status(TaskState.TASK_STATE_WORKING) .build(); ListTasksResult result = taskStore.list(params); assertEquals(1, result.totalSize()); assertEquals(1, result.pageSize()); assertEquals(1, result.tasks().size()); - assertEquals(TaskState.WORKING, result.tasks().get(0).status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, result.tasks().get(0).status().state()); } @Test @@ -386,19 +386,19 @@ public void testListTasksCombinedFilters() { Task task1 = Task.builder() .id("task-combined-1") .contextId("context-X") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); Task task2 = Task.builder() .id("task-combined-2") .contextId("context-X") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task task3 = Task.builder() .id("task-combined-3") .contextId("context-Y") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); taskStore.save(task1, false); @@ -409,7 +409,7 @@ public void testListTasksCombinedFilters() { ListTasksParams params = ListTasksParams.builder() .contextId("context-X") .tenant("tenant") - .status(TaskState.WORKING) + .status(TaskState.TASK_STATE_WORKING) .build(); ListTasksResult result = taskStore.list(params); @@ -417,7 +417,7 @@ public void testListTasksCombinedFilters() { assertEquals(1, result.pageSize()); assertEquals("task-combined-2", result.tasks().get(0).id()); assertEquals("context-X", result.tasks().get(0).contextId()); - assertEquals(TaskState.WORKING, result.tasks().get(0).status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, result.tasks().get(0).status().state()); } @Test @@ -430,7 +430,7 @@ public void testListTasksPagination() { Task task = Task.builder() .id("task-page-" + i) .contextId("context-pagination") - .status(new TaskStatus(TaskState.SUBMITTED, null, sameTimestamp)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, null, sameTimestamp)) .build(); taskStore.save(task, false); } @@ -486,7 +486,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { Task task1 = Task.builder() .id("task-diff-a") .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.WORKING, null, now.minusMinutes(10))) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now.minusMinutes(10))) .build(); taskStore.save(task1, false); @@ -494,7 +494,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { Task task2 = Task.builder() .id("task-diff-b") .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.WORKING, null, now.minusMinutes(5))) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now.minusMinutes(5))) .build(); taskStore.save(task2, false); @@ -502,7 +502,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { Task task3 = Task.builder() .id("task-diff-c") .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.WORKING, null, now.minusMinutes(5))) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now.minusMinutes(5))) .build(); taskStore.save(task3, false); @@ -510,7 +510,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { Task task4 = Task.builder() .id("task-diff-d") .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.WORKING, null, now)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now)) .build(); taskStore.save(task4, false); @@ -518,7 +518,7 @@ public void testListTasksPaginationWithDifferentTimestamps() { Task task5 = Task.builder() .id("task-diff-e") .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.WORKING, null, now.minusMinutes(1))) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now.minusMinutes(1))) .build(); taskStore.save(task5, false); @@ -612,7 +612,7 @@ public void testListTasksHistoryLimiting() { Task task = Task.builder() .id("task-history-limit-unique-1") .contextId("context-history-limit-unique") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .history(longHistory) .build(); @@ -650,7 +650,7 @@ public void testListTasksArtifactInclusion() { Task task = Task.builder() .id("task-artifact-unique-1") .contextId("context-artifact-unique") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .artifacts(artifacts) .build(); @@ -689,7 +689,7 @@ public void testListTasksDefaultPageSize() { Task task = Task.builder() .id("task-default-pagesize-" + String.format("%03d", i)) .contextId("context-default-pagesize") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); taskStore.save(task, false); } @@ -713,7 +713,7 @@ public void testListTasksInvalidPageTokenFormat() { Task task = Task.builder() .id("task-invalid-token") .contextId("context-invalid-token") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); taskStore.save(task, false); @@ -761,19 +761,19 @@ public void testListTasksOrderingById() { Task task1 = Task.builder() .id("task-order-a") .contextId("context-order") - .status(new TaskStatus(TaskState.SUBMITTED, null, sameTimestamp)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, null, sameTimestamp)) .build(); Task task2 = Task.builder() .id("task-order-b") .contextId("context-order") - .status(new TaskStatus(TaskState.SUBMITTED, null, sameTimestamp)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, null, sameTimestamp)) .build(); Task task3 = Task.builder() .id("task-order-c") .contextId("context-order") - .status(new TaskStatus(TaskState.SUBMITTED, null, sameTimestamp)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, null, sameTimestamp)) .build(); // Save in reverse order diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index 89fc2d392..35beb82d6 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -76,7 +76,6 @@ private static GsonBuilder createBaseGsonBuilder() { .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) .registerTypeHierarchyAdapter(A2AError.class, new A2AErrorTypeAdapter()) - .registerTypeAdapter(TaskState.class, new TaskStateTypeAdapter()) .registerTypeAdapter(Message.Role.class, new RoleTypeAdapter()) .registerTypeHierarchyAdapter(FileContent.class, new FileContentTypeAdapter()); } @@ -438,48 +437,6 @@ private A2AError createErrorInstance(@Nullable Integer code, @Nullable String me } } - /** - * Gson TypeAdapter for serializing and deserializing {@link TaskState} enum. - *

        - * This adapter ensures that TaskState enum values are serialized using their - * wire format string representation (e.g., "completed", "working") rather than - * the Java enum constant name (e.g., "COMPLETED", "WORKING"). - *

        - * For serialization, it uses {@link TaskState#asString()} to get the wire format. - * For deserialization, it uses {@link TaskState#fromString(String)} to parse the - * wire format back to the enum constant. - * - * @see TaskState - * @see TaskState#asString() - * @see TaskState#fromString(String) - */ - static class TaskStateTypeAdapter extends TypeAdapter { - - @Override - public void write(JsonWriter out, TaskState value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - } else { - out.value(value.asString()); - } - } - - @Override - public @Nullable - TaskState read(JsonReader in) throws java.io.IOException { - if (in.peek() == com.google.gson.stream.JsonToken.NULL) { - in.nextNull(); - return null; - } - String stateString = in.nextString(); - try { - return TaskState.fromString(stateString); - } catch (IllegalArgumentException e) { - throw new JsonSyntaxException("Invalid TaskState: " + stateString, e); - } - } - } - /** * Gson TypeAdapter for serializing and deserializing {@link Message.Role} enum. *

        diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java index 836cb6e06..463279705 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java @@ -13,7 +13,7 @@ *

        * This request instructs the agent to cancel execution of a specific task identified by ID. * The agent should stop processing, clean up resources, and transition the task to - * {@link TaskState#CANCELED} state if cancellation is possible. + * {@link TaskState#TASK_STATE_CANCELED} state if cancellation is possible. *

        * Not all tasks can be canceled (e.g., already completed tasks), which may result in * a {@link TaskNotCancelableError}. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java index d4296fd49..8a7ca6413 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java @@ -10,7 +10,7 @@ * JSON-RPC response for task cancellation requests. *

        * This response contains the updated {@link Task} object after cancellation, typically - * showing {@link TaskState#CANCELED} status if the cancellation was successful. + * showing {@link TaskState#TASK_STATE_CANCELED} status if the cancellation was successful. *

        * If the task cannot be canceled (e.g., already completed) or is not found, the error * field will contain a {@link io.a2a.spec.A2AError} such as {@link TaskNotCancelableError} or diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java index e7dcdc670..219fbde8e 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java @@ -33,7 +33,7 @@ void testTaskSerialization() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); // Serialize as StreamingEventKind @@ -43,7 +43,7 @@ void testTaskSerialization() throws JsonProcessingException { assertNotNull(json); assertTrue(json.contains("\"task\"")); assertTrue(json.contains("\"id\":\"task-123\"")); - assertTrue(json.contains("\"state\":\"submitted\"")); + assertTrue(json.contains("\"state\":\"TASK_STATE_SUBMITTED\"")); assertFalse(json.contains("\"kind\"")); // Deserialize back to StreamingEventKind @@ -96,7 +96,7 @@ void testTaskStatusUpdateEventSerialization() throws JsonProcessingException { TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() .taskId("task-abc") .contextId("context-def") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); // Serialize as StreamingEventKind @@ -106,7 +106,7 @@ void testTaskStatusUpdateEventSerialization() throws JsonProcessingException { assertNotNull(json); assertTrue(json.contains("\"statusUpdate\"")); assertTrue(json.contains("\"taskId\":\"task-abc\"")); - assertTrue(json.contains("\"state\":\"working\"")); + assertTrue(json.contains("\"state\":\"TASK_STATE_WORKING\"")); assertTrue(json.contains("\"final\":false")); assertFalse(json.contains("\"kind\"")); @@ -165,7 +165,7 @@ void testUnwrappedTaskDeserialization() throws JsonProcessingException { "id": "task-unwrapped", "contextId": "context-999", "status": { - "state": "completed" + "state": "TASK_STATE_COMPLETED" } } """; @@ -178,7 +178,7 @@ void testUnwrappedTaskDeserialization() throws JsonProcessingException { Task task = (Task) deserialized; assertEquals("task-unwrapped", task.id()); assertEquals("context-999", task.contextId()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); } @Test @@ -216,7 +216,7 @@ void testUnwrappedTaskStatusUpdateEventDeserialization() throws JsonProcessingEx "taskId": "task-status-unwrapped", "contextId": "context-999", "status": { - "state": "working" + "state": "TASK_STATE_WORKING" }, "final": false } @@ -229,7 +229,7 @@ void testUnwrappedTaskStatusUpdateEventDeserialization() throws JsonProcessingEx assertInstanceOf(TaskStatusUpdateEvent.class, deserialized); TaskStatusUpdateEvent event = (TaskStatusUpdateEvent) deserialized; assertEquals("task-status-unwrapped", event.taskId()); - assertEquals(TaskState.WORKING, event.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, event.status().state()); assertFalse(event.isFinal()); } diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java index 940fe4531..8133dd0fc 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java @@ -34,7 +34,7 @@ void testBasicTaskSerialization() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); // Serialize to JSON @@ -43,7 +43,7 @@ void testBasicTaskSerialization() throws JsonProcessingException { // Verify JSON contains expected fields assertNotNull(json); assertTrue(json.contains("\"id\":\"task-123\"")); - assertTrue(json.contains("\"state\":\"submitted\"")); + assertTrue(json.contains("\"state\":\"TASK_STATE_SUBMITTED\"")); // Deserialize back to Task Task deserialized = JsonUtil.fromJson(json, Task.class); @@ -60,7 +60,7 @@ void testTaskWithTimestamp() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.WORKING, null, timestamp)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, timestamp)) .build(); // Serialize @@ -89,7 +89,7 @@ void testTaskWithArtifacts() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .artifacts(List.of(artifact)) .build(); @@ -121,7 +121,7 @@ void testTaskWithHistory() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .history(List.of(message)) .build(); @@ -149,7 +149,7 @@ void testTaskWithAllFields() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-789") - .status(new TaskStatus(TaskState.WORKING, null, timestamp)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, timestamp)) .history(List.of( Message.builder() .role(Message.Role.USER) @@ -190,7 +190,7 @@ void testTaskWithAllFields() throws JsonProcessingException { void testTaskWithDifferentStates() throws JsonProcessingException { for (TaskState state : TaskState.values()) { Task task = Task.builder() - .id("task-" + state.asString()) + .id("task-" + state) .contextId("context-123") .status(new TaskStatus(state)) .build(); @@ -199,7 +199,7 @@ void testTaskWithDifferentStates() throws JsonProcessingException { String json = JsonUtil.toJson(task); // Verify state is serialized correctly - assertTrue(json.contains("\"state\":\"" + state.asString() + "\"")); + assertTrue(json.contains("\"state\":\"" + state + "\"")); // Deserialize Task deserialized = JsonUtil.fromJson(json, Task.class); @@ -214,7 +214,7 @@ void testTaskWithNullOptionalFields() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) // artifacts, history, metadata not set .build(); @@ -227,7 +227,7 @@ void testTaskWithNullOptionalFields() throws JsonProcessingException { // Verify required fields are present assertEquals("task-123", deserialized.id()); assertEquals("context-456", deserialized.contextId()); - assertEquals(TaskState.SUBMITTED, deserialized.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, deserialized.status().state()); // Verify optional lists default to empty assertNotNull(deserialized.artifacts()); @@ -248,7 +248,7 @@ void testTaskWithFilePartBytes() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .artifacts(List.of(artifact)) .build(); @@ -286,7 +286,7 @@ void testTaskWithFilePartUri() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .artifacts(List.of(artifact)) .build(); @@ -321,7 +321,7 @@ void testTaskWithDataPart() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .artifacts(List.of(artifact)) .build(); @@ -351,7 +351,7 @@ void testTaskRoundTrip() throws JsonProcessingException { Task original = Task.builder() .id("task-123") .contextId("context-789") - .status(new TaskStatus(TaskState.WORKING, null, timestamp)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, timestamp)) .history(List.of( Message.builder() .role(Message.Role.USER) @@ -401,21 +401,21 @@ void testTaskStatusWithMessage() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.COMPLETED, statusMessage, null)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED, statusMessage, null)) .build(); // Serialize String json = JsonUtil.toJson(task); // Verify JSON contains status message - assertTrue(json.contains("\"state\":\"completed\"")); + assertTrue(json.contains("\"state\":\"TASK_STATE_COMPLETED\"")); assertTrue(json.contains("Processing complete")); // Deserialize Task deserialized = JsonUtil.fromJson(json, Task.class); // Verify status message is preserved - assertEquals(TaskState.COMPLETED, deserialized.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, deserialized.status().state()); assertNotNull(deserialized.status().message()); assertEquals(Message.Role.AGENT, deserialized.status().message().role()); assertTrue(deserialized.status().message().parts().get(0) instanceof TextPart); @@ -428,7 +428,7 @@ void testDeserializeTaskFromJson() throws JsonProcessingException { "id": "task-123", "contextId": "context-456", "status": { - "state": "submitted" + "state": "TASK_STATE_SUBMITTED" } } """; @@ -437,7 +437,7 @@ void testDeserializeTaskFromJson() throws JsonProcessingException { assertEquals("task-123", task.id()); assertEquals("context-456", task.contextId()); - assertEquals(TaskState.SUBMITTED, task.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, task.status().state()); assertNull(task.status().message()); // TaskStatus automatically sets timestamp to current time if not provided assertNotNull(task.status().timestamp()); @@ -450,7 +450,7 @@ void testDeserializeTaskWithArtifactsFromJson() throws JsonProcessingException { "id": "task-123", "contextId": "context-456", "status": { - "state": "completed" + "state": "TASK_STATE_COMPLETED" }, "artifacts": [ { @@ -469,7 +469,7 @@ void testDeserializeTaskWithArtifactsFromJson() throws JsonProcessingException { Task task = JsonUtil.fromJson(json, Task.class); assertEquals("task-123", task.id()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); assertEquals(1, task.artifacts().size()); assertEquals("artifact-1", task.artifacts().get(0).artifactId()); assertEquals("Result", task.artifacts().get(0).name()); @@ -485,7 +485,7 @@ void testDeserializeTaskWithFilePartBytesFromJson() throws JsonProcessingExcepti "id": "task-123", "contextId": "context-456", "status": { - "state": "completed" + "state": "TASK_STATE_COMPLETED" }, "artifacts": [ { @@ -525,7 +525,7 @@ void testDeserializeTaskWithFilePartUriFromJson() throws JsonProcessingException "id": "task-123", "contextId": "context-456", "status": { - "state": "completed" + "state": "TASK_STATE_COMPLETED" }, "artifacts": [ { @@ -564,7 +564,7 @@ void testDeserializeTaskWithDataPartFromJson() throws JsonProcessingException { "id": "task-123", "contextId": "context-456", "status": { - "state": "completed" + "state": "TASK_STATE_COMPLETED" }, "artifacts": [ { @@ -598,7 +598,7 @@ void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException { "id": "task-123", "contextId": "context-456", "status": { - "state": "working" + "state": "TASK_STATE_WORKING" }, "history": [ { @@ -640,7 +640,7 @@ void testDeserializeTaskWithTimestampFromJson() throws JsonProcessingException { "id": "task-123", "contextId": "context-456", "status": { - "state": "working", + "state": "TASK_STATE_WORKING", "timestamp": "2023-10-01T12:00:00.234-05:00" } } @@ -649,7 +649,7 @@ void testDeserializeTaskWithTimestampFromJson() throws JsonProcessingException { Task task = JsonUtil.fromJson(json, Task.class); assertEquals("task-123", task.id()); - assertEquals(TaskState.WORKING, task.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, task.status().state()); assertNotNull(task.status().timestamp()); assertEquals("2023-10-01T12:00:00.234-05:00", task.status().timestamp().toString()); } @@ -661,7 +661,7 @@ void testDeserializeTaskWithMetadataFromJson() throws JsonProcessingException { "id": "task-123", "contextId": "context-456", "status": { - "state": "completed" + "state": "TASK_STATE_COMPLETED" }, "metadata": { "key1": "value1", @@ -692,7 +692,7 @@ void testTaskWithMixedPartTypes() throws JsonProcessingException { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .artifacts(List.of(artifact)) .build(); 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 25b7cc708..9d600f53d 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 @@ -151,7 +151,7 @@ public void testSendMessage_MethodNameSetInContext() { Task responseTask = Task.builder() .id("task-123") .contextId("context-1234") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); SendMessageResponse realResponse = new SendMessageResponse("1", responseTask); when(mockJsonRpcHandler.onMessageSend(any(SendMessageRequest.class), any(ServerCallContext.class))) @@ -235,7 +235,7 @@ public void testGetTask_MethodNameSetInContext() { Task responseTask = Task.builder() .id("de38c76d-d54c-436c-8b9f-4c2703648d64") .contextId("context-1234") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) @@ -271,7 +271,7 @@ public void testCancelTask_MethodNameSetInContext() { Task responseTask = Task.builder() .id("de38c76d-d54c-436c-8b9f-4c2703648d64") .contextId("context-1234") - .status(new TaskStatus(TaskState.CANCELED)) + .status(new TaskStatus(TaskState.TASK_STATE_CANCELED)) .build(); CancelTaskResponse realResponse = new CancelTaskResponse("1", responseTask); when(mockJsonRpcHandler.onCancelTask(any(CancelTaskRequest.class), any(ServerCallContext.class))) @@ -540,7 +540,7 @@ public void testTenantExtraction_MultiSegmentPath() { Task responseTask = Task.builder() .id("de38c76d-d54c-436c-8b9f-4c2703648d64") .contextId("context-1234") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) @@ -577,7 +577,7 @@ public void testTenantExtraction_RootPath() { Task responseTask = Task.builder() .id("de38c76d-d54c-436c-8b9f-4c2703648d64") .contextId("context-1234") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) @@ -614,7 +614,7 @@ public void testTenantExtraction_SingleSegmentPath() { Task responseTask = Task.builder() .id("de38c76d-d54c-436c-8b9f-4c2703648d64") .contextId("context-1234") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) @@ -651,7 +651,7 @@ public void testTenantExtraction_ThreeSegmentPath() { Task responseTask = Task.builder() .id("de38c76d-d54c-436c-8b9f-4c2703648d64") .contextId("context-1234") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) 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 239385a39..6fdfe8ea4 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 @@ -205,7 +205,7 @@ public Flow.Publisher consumeAll() { */ private boolean isStreamTerminatingTask(Task task) { TaskState state = task.status().state(); - return state.isFinal() || state == TaskState.INPUT_REQUIRED; + return state.isFinal() || state == TaskState.TASK_STATE_INPUT_REQUIRED; } public EnhancedRunnable.DoneCallback createAgentRunnableDoneCallback() { 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 5fd8836dc..80d003d5d 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 @@ -6,7 +6,6 @@ import static java.util.concurrent.TimeUnit.SECONDS; import java.time.Instant; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -68,7 +67,7 @@ import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.UnsupportedOperationError; -import java.util.Collections; + import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; @@ -369,7 +368,7 @@ public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws // Check if task is in a non-cancelable state (completed, canceled, failed, rejected) if (task.status().state().isFinal()) { throw new TaskNotCancelableError( - "Task cannot be canceled - current state: " + task.status().state().asString()); + "Task cannot be canceled - current state: " + task.status().state()); } TaskManager taskManager = new TaskManager( @@ -415,9 +414,9 @@ public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws } // Verify task was actually canceled (not completed concurrently) - if (tempTask.status().state() != TaskState.CANCELED) { + if (tempTask.status().state() != TaskState.TASK_STATE_CANCELED) { throw new TaskNotCancelableError( - "Task cannot be canceled - current state: " + tempTask.status().state().asString()); + "Task cannot be canceled - current state: " + tempTask.status().state()); } return tempTask; diff --git a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java index 6088022b6..d3aa3d115 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java +++ b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java @@ -237,7 +237,7 @@ public void complete() { * @param message optional message to include with completion */ public void complete(@Nullable Message message) { - updateStatus(TaskState.COMPLETED, message); + updateStatus(TaskState.TASK_STATE_COMPLETED, message); } /** @@ -253,7 +253,7 @@ public void fail() { * @param message optional message to include with failure */ public void fail(@Nullable Message message) { - updateStatus(TaskState.FAILED, message); + updateStatus(TaskState.TASK_STATE_FAILED, message); } /** @@ -312,7 +312,7 @@ public void submit() { * @param message optional message to include */ public void submit(@Nullable Message message) { - updateStatus(TaskState.SUBMITTED, message); + updateStatus(TaskState.TASK_STATE_SUBMITTED, message); } /** @@ -328,7 +328,7 @@ public void startWork() { * @param message optional message to include */ public void startWork(@Nullable Message message) { - updateStatus(TaskState.WORKING, message); + updateStatus(TaskState.TASK_STATE_WORKING, message); } /** @@ -344,7 +344,7 @@ public void cancel() { * @param message optional message to include */ public void cancel(@Nullable Message message) { - updateStatus(TaskState.CANCELED, message); + updateStatus(TaskState.TASK_STATE_CANCELED, message); } /** @@ -360,7 +360,7 @@ public void reject() { * @param message optional message to include */ public void reject(@Nullable Message message) { - updateStatus(TaskState.REJECTED, message); + updateStatus(TaskState.TASK_STATE_REJECTED, message); } /** @@ -395,7 +395,7 @@ public void requiresInput(boolean isFinal) { * @param isFinal whether this is a final status (prevents further updates) */ public void requiresInput(@Nullable Message message, boolean isFinal) { - updateStatus(TaskState.INPUT_REQUIRED, message, isFinal); + updateStatus(TaskState.TASK_STATE_INPUT_REQUIRED, message, isFinal); } /** @@ -430,7 +430,7 @@ public void requiresAuth(boolean isFinal) { * @param isFinal whether this is a final status (prevents further updates) */ public void requiresAuth(@Nullable Message message, boolean isFinal) { - updateStatus(TaskState.AUTH_REQUIRED, message, isFinal); + updateStatus(TaskState.TASK_STATE_AUTH_REQUIRED, message, isFinal); } /** 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 b36868a63..06c689eb2 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 @@ -168,8 +168,8 @@ public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, boolean isFinalEvent = (event instanceof Task task && task.status().state().isFinal()) || (event instanceof TaskStatusUpdateEvent tsue && tsue.isFinal()) || (event instanceof A2AError); // A2AError events are terminal - boolean isAuthRequired = (event instanceof Task task && task.status().state() == TaskState.AUTH_REQUIRED) - || (event instanceof TaskStatusUpdateEvent tsue && tsue.status().state() == TaskState.AUTH_REQUIRED); + boolean isAuthRequired = (event instanceof Task task && task.status().state() == TaskState.TASK_STATE_AUTH_REQUIRED) + || (event instanceof TaskStatusUpdateEvent tsue && tsue.status().state() == TaskState.TASK_STATE_AUTH_REQUIRED); LOGGER.debug("ResultAggregator: Evaluating interrupt (blocking={}, isFinal={}, isAuth={}, eventType={})", blocking, isFinalEvent, isAuthRequired, event.getClass().getSimpleName()); 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 abb764755..bba80bf53 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 @@ -1,7 +1,7 @@ package io.a2a.server.tasks; -import static io.a2a.spec.TaskState.FAILED; -import static io.a2a.spec.TaskState.SUBMITTED; +import static io.a2a.spec.TaskState.TASK_STATE_FAILED; +import static io.a2a.spec.TaskState.TASK_STATE_SUBMITTED; import static io.a2a.util.Assert.checkNotNullParam; import static io.a2a.util.Utils.appendArtifactToTask; @@ -142,7 +142,7 @@ public boolean process(Event event, boolean isReplicated) throws A2AServerExcept TaskStatusUpdateEvent failedEvent = TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId(errorContextId) - .status(new TaskStatus(FAILED)) + .status(new TaskStatus(TASK_STATE_FAILED)) .build(); isFinal = saveTaskEvent(failedEvent, isReplicated); } else { @@ -207,7 +207,7 @@ private Task createTask(String taskId, String contextId) { return Task.builder() .id(taskId) .contextId(contextId) - .status(new TaskStatus(SUBMITTED)) + .status(new TaskStatus(TASK_STATE_SUBMITTED)) .history(history) .build(); } 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 0fc9c16ca..daf178203 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 @@ -122,7 +122,7 @@ public void testInitWithBothIds() { @Test public void testInitWithTask() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); + var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -141,7 +141,7 @@ public void testGetUserInputNoParams() { @Test public void testAttachRelatedTask() { - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); + var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); RequestContext context = new RequestContext.Builder().build(); assertEquals(0, context.getRelatedTasks().size()); @@ -189,7 +189,7 @@ public void testCheckOrGenerateContextIdWithExistingContextId() { public void testInitRaisesErrorOnTaskIdMismatch() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); + var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); InvalidParamsError error = assertThrows(InvalidParamsError.class, () -> new RequestContext.Builder() @@ -205,7 +205,7 @@ public void testInitRaisesErrorOnTaskIdMismatch() { public void testInitRaisesErrorOnContextIdMismatch() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); + var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); InvalidParamsError error = assertThrows(InvalidParamsError.class, () -> new RequestContext.Builder() @@ -220,7 +220,7 @@ public void testInitRaisesErrorOnContextIdMismatch() { @Test public void testWithRelatedTasksProvided() { - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); + var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); List relatedTasks = new ArrayList<>(); relatedTasks.add(mockTask); @@ -276,7 +276,7 @@ public void testInitWithExistingIdsInMessage() { public void testInitWithTaskIdAndExistingTaskIdMatch() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); + var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); RequestContext context = new RequestContext.Builder() .setParams(mockParams) @@ -292,7 +292,7 @@ public void testInitWithTaskIdAndExistingTaskIdMatch() { public void testInitWithContextIdAndExistingContextIdMatch() { var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.COMPLETED)).build(); + var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); RequestContext context = new RequestContext.Builder() .setParams(mockParams) 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 2dcf7c4b1..6202e2f75 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 @@ -47,7 +47,7 @@ public class EventConsumerTest { { "id": "123", "contextId": "session-xyz", - "status": {"state": "submitted"} + "status": {"state": "TASK_STATE_SUBMITTED"} } """; @@ -158,7 +158,7 @@ public void testConsumeAllMultipleEvents() throws JsonProcessingException { TaskStatusUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build()); for (Event event : events) { @@ -193,7 +193,7 @@ public void testConsumeUntilMessage() throws Exception { TaskStatusUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build()); for (Event event : events) { @@ -241,7 +241,7 @@ public void testConsumeTaskInputRequired() { Task task = Task.builder() .id(TASK_ID) .contextId("session-xyz") - .status(new TaskStatus(TaskState.INPUT_REQUIRED)) + .status(new TaskStatus(TaskState.TASK_STATE_INPUT_REQUIRED)) .build(); List events = List.of( task, @@ -256,7 +256,7 @@ public void testConsumeTaskInputRequired() { TaskStatusUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build()); for (Event event : events) { eventQueue.enqueueEvent(event); 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 1adcc57ca..c9761f66d 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 @@ -43,7 +43,7 @@ public class EventQueueTest { { "id": "123", "contextId": "session-xyz", - "status": {"state": "submitted"} + "status": {"state": "TASK_STATE_SUBMITTED"} } """; @@ -351,7 +351,7 @@ public void testDequeueEventWait() throws Exception { Event event = TaskStatusUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); eventQueue.enqueueEvent(event); 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 39ff07f09..0529f51f9 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 @@ -58,7 +58,7 @@ public class AbstractA2ARequestHandlerTest { protected static final Task MINIMAL_TASK = Task.builder() .id("task-123") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); protected static final Message MESSAGE = Message.builder() diff --git a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java index 853037a9c..8693f32cf 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java @@ -102,141 +102,141 @@ public void testAddArtifactWithCustomIdAndName() throws Exception { @Test public void testCompleteWithoutMessage() throws Exception { agentEmitter.complete(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.COMPLETED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_COMPLETED, null); } @Test public void testCompleteWithMessage() throws Exception { agentEmitter.complete(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(true, TaskState.COMPLETED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_COMPLETED, SAMPLE_MESSAGE); } @Test public void testSubmitWithoutMessage() throws Exception { agentEmitter.submit(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.SUBMITTED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_SUBMITTED, null); } @Test public void testSubmitWithMessage() throws Exception { agentEmitter.submit(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(false, TaskState.SUBMITTED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_SUBMITTED, SAMPLE_MESSAGE); } @Test public void testStartWorkWithoutMessage() throws Exception { agentEmitter.startWork(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.WORKING, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_WORKING, null); } @Test public void testStartWorkWithMessage() throws Exception { agentEmitter.startWork(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(false, TaskState.WORKING, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_WORKING, SAMPLE_MESSAGE); } @Test public void testFailedWithoutMessage() throws Exception { agentEmitter.fail(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.FAILED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_FAILED, null); } @Test public void testFailedWithMessage() throws Exception { agentEmitter.fail(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(true, TaskState.FAILED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_FAILED, SAMPLE_MESSAGE); } @Test public void testCanceledWithoutMessage() throws Exception { agentEmitter.cancel(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.CANCELED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_CANCELED, null); } @Test public void testCanceledWithMessage() throws Exception { agentEmitter.cancel(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(true, TaskState.CANCELED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_CANCELED, SAMPLE_MESSAGE); } @Test public void testRejectWithoutMessage() throws Exception { agentEmitter.reject(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.REJECTED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_REJECTED, null); } @Test public void testRejectWithMessage() throws Exception { agentEmitter.reject(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(true, TaskState.REJECTED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_REJECTED, SAMPLE_MESSAGE); } @Test public void testRequiresInputWithoutMessage() throws Exception { agentEmitter.requiresInput(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, null); } @Test public void testRequiresInputWithMessage() throws Exception { agentEmitter.requiresInput(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, SAMPLE_MESSAGE); } @Test public void testRequiresInputWithFinalTrue() throws Exception { agentEmitter.requiresInput(true); - checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, null); } @Test public void testRequiresInputWithMessageAndFinalTrue() throws Exception { agentEmitter.requiresInput(SAMPLE_MESSAGE, true); - checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, SAMPLE_MESSAGE); } @Test public void testRequiresAuthWithoutMessage() throws Exception { agentEmitter.requiresAuth(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, null); } @Test public void testRequiresAuthWithMessage() throws Exception { agentEmitter.requiresAuth(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, SAMPLE_MESSAGE); } @Test public void testRequiresAuthWithFinalTrue() throws Exception { agentEmitter.requiresAuth(true); - checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, null); } @Test public void testRequiresAuthWithMessageAndFinalTrue() throws Exception { agentEmitter.requiresAuth(SAMPLE_MESSAGE, true); - checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, SAMPLE_MESSAGE); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, SAMPLE_MESSAGE); } @Test public void testNonTerminalStateUpdatesAllowed() throws Exception { // Non-terminal states should be allowed multiple times agentEmitter.submit(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.SUBMITTED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_SUBMITTED, null); agentEmitter.startWork(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.WORKING, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_WORKING, null); agentEmitter.requiresInput(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.INPUT_REQUIRED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, null); agentEmitter.requiresAuth(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.AUTH_REQUIRED, null); + checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, null); // Should still be able to complete agentEmitter.complete(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.COMPLETED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_COMPLETED, null); } @Test @@ -341,7 +341,7 @@ public void testAddArtifactGeneratesIdWhenNull() throws Exception { public void testTerminalStateProtectionAfterComplete() throws Exception { // Complete the task first agentEmitter.complete(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.COMPLETED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_COMPLETED, null); // Try to update status again - should throw RuntimeException RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.startWork()); @@ -355,7 +355,7 @@ public void testTerminalStateProtectionAfterComplete() throws Exception { public void testTerminalStateProtectionAfterFail() throws Exception { // Fail the task first agentEmitter.fail(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.FAILED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_FAILED, null); // Try to update status again - should throw RuntimeException RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.complete()); @@ -369,7 +369,7 @@ public void testTerminalStateProtectionAfterFail() throws Exception { public void testTerminalStateProtectionAfterReject() throws Exception { // Reject the task first agentEmitter.reject(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.REJECTED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_REJECTED, null); // Try to update status again - should throw RuntimeException RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.startWork()); @@ -383,7 +383,7 @@ public void testTerminalStateProtectionAfterReject() throws Exception { public void testTerminalStateProtectionAfterCancel() throws Exception { // Cancel the task first agentEmitter.cancel(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.CANCELED, null); + checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_CANCELED, null); // Try to update status again - should throw RuntimeException RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.submit()); @@ -427,7 +427,7 @@ public void testConcurrentCompletionAttempts() throws Exception { TaskStatusUpdateEvent tsue = (TaskStatusUpdateEvent) event; assertTrue(tsue.isFinal()); - assertTrue(tsue.status().state() == TaskState.COMPLETED || tsue.status().state() == TaskState.FAILED); + assertTrue(tsue.status().state() == TaskState.TASK_STATE_COMPLETED || tsue.status().state() == TaskState.TASK_STATE_FAILED); // No additional events should be queued assertNull(eventQueue.dequeueEventItem(0)); diff --git a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java b/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java index c8ccd669f..6b1faf711 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java @@ -71,7 +71,7 @@ private void verifyHttpCallWithoutToken(PushNotificationConfig config, Task task // Verify the request body contains the task data String sentBody = bodyCaptor.getValue(); assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().asString())); + assertTrue(sentBody.contains(task.status().state().name())); } private Task createSampleTask(String taskId, TaskState state) { @@ -236,7 +236,7 @@ public void testDeleteInfoWithNullConfigId() { @Test public void testSendNotificationSuccess() throws Exception { String taskId = "task_send_success"; - Task task = createSampleTask(taskId, TaskState.COMPLETED); + Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); configStore.setInfo(taskId, config); @@ -255,13 +255,13 @@ public void testSendNotificationSuccess() throws Exception { // Verify the request body contains the task data String sentBody = bodyCaptor.getValue(); assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().asString())); + assertTrue(sentBody.contains(task.status().state().name())); } @Test public void testSendNotificationWithToken() throws Exception { String taskId = "task_send_with_token"; - Task task = createSampleTask(taskId, TaskState.COMPLETED); + Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); configStore.setInfo(taskId, config); @@ -287,13 +287,13 @@ public void testSendNotificationWithToken() throws Exception { // Verify the request body contains the task data String sentBody = bodyCaptor.getValue(); assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().asString())); + assertTrue(sentBody.contains(task.status().state().name())); } @Test public void testSendNotificationNoConfig() throws Exception { String taskId = "task_send_no_config"; - Task task = createSampleTask(taskId, TaskState.COMPLETED); + Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); notificationSender.sendNotification(task); @@ -304,7 +304,7 @@ public void testSendNotificationNoConfig() throws Exception { @Test public void testSendNotificationWithEmptyToken() throws Exception { String taskId = "task_send_empty_token"; - Task task = createSampleTask(taskId, TaskState.COMPLETED); + Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", ""); configStore.setInfo(taskId, config); @@ -316,7 +316,7 @@ public void testSendNotificationWithEmptyToken() throws Exception { @Test public void testSendNotificationWithBlankToken() throws Exception { String taskId = "task_send_blank_token"; - Task task = createSampleTask(taskId, TaskState.COMPLETED); + Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", " "); configStore.setInfo(taskId, config); 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 e58ad384b..bde4db4d5 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 @@ -23,7 +23,6 @@ import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.Artifact; import io.a2a.spec.Message; -import io.a2a.spec.Part; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; @@ -155,7 +154,7 @@ public void setUp() { private void testSendNotificationWithInvalidToken(String token, String testName) throws InterruptedException { String taskId = testName; - Task taskData = createSampleTask(taskId, TaskState.COMPLETED); + Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", token); // Set up the configuration in the store @@ -206,7 +205,7 @@ private PushNotificationConfig createSamplePushConfig(String url, String configI @Test public void testSendNotificationSuccess() throws InterruptedException { String taskId = "task_send_success"; - Task taskData = createSampleTask(taskId, TaskState.COMPLETED); + Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); // Set up the configuration in the store @@ -237,7 +236,7 @@ public void testSendNotificationSuccess() throws InterruptedException { @Test public void testSendNotificationWithTokenSuccess() throws InterruptedException { String taskId = "task_send_with_token"; - Task taskData = createSampleTask(taskId, TaskState.COMPLETED); + Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); // Set up the configuration in the store @@ -273,7 +272,7 @@ public void testSendNotificationWithTokenSuccess() throws InterruptedException { @Test public void testSendNotificationNoConfig() { String taskId = "task_send_no_config"; - Task taskData = createSampleTask(taskId, TaskState.COMPLETED); + Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); // Don't set any configuration in the store sender.sendNotification(taskData); @@ -295,7 +294,7 @@ public void testSendNotificationWithBlankToken() throws InterruptedException { @Test public void testSendNotificationMultipleConfigs() throws InterruptedException { String taskId = "task_multiple_configs"; - Task taskData = createSampleTask(taskId, TaskState.COMPLETED); + Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config1 = createSamplePushConfig("http://notify.me/cfg1", "cfg1", null); PushNotificationConfig config2 = createSamplePushConfig("http://notify.me/cfg2", "cfg2", null); @@ -329,7 +328,7 @@ public void testSendNotificationMultipleConfigs() throws InterruptedException { @Test public void testSendNotificationHttpError() { String taskId = "task_send_http_err"; - Task taskData = createSampleTask(taskId, TaskState.COMPLETED); + Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); PushNotificationConfig config = createSamplePushConfig("http://notify.me/http_error", "cfg1", null); // Set up the configuration in the store @@ -384,7 +383,7 @@ public void testSendNotificationTaskStatusUpdate() throws InterruptedException { TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId("ctx456") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); @@ -405,7 +404,7 @@ public void testSendNotificationTaskStatusUpdate() throws InterruptedException { assertTrue(sentEvent instanceof TaskStatusUpdateEvent, "Event should be a TaskStatusUpdateEvent"); TaskStatusUpdateEvent sentUpdate = (TaskStatusUpdateEvent) sentEvent; assertEquals(taskId, sentUpdate.taskId()); - assertEquals(TaskState.WORKING, sentUpdate.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, sentUpdate.status().state()); // Verify StreamResponse wrapper with 'statusUpdate' discriminator String rawBody = testHttpClient.rawBodies.get(0); diff --git a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java index 0e25e9aad..bdf7311a2 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java @@ -3,7 +3,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atMost; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -29,7 +28,7 @@ import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; import io.a2a.spec.TextPart; -import org.junit.jupiter.api.AfterEach; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; @@ -136,7 +135,7 @@ void testGetCurrentResultWithMessageSet() { @Test void testGetCurrentResultWithMessageNull() { - Task expectedTask = createSampleTask("task_from_tm", TaskState.SUBMITTED, "ctx1"); + Task expectedTask = createSampleTask("task_from_tm", TaskState.TASK_STATE_SUBMITTED, "ctx1"); when(mockTaskManager.getTask()).thenReturn(expectedTask); EventKind result = aggregator.getCurrentResult(); @@ -149,7 +148,7 @@ void testGetCurrentResultWithMessageNull() { void testConstructorStoresTaskManagerCorrectly() { // Test that constructor properly initializes the aggregator // We can't access the private field directly, but we can test behavior - Task expectedTask = createSampleTask("test_task", TaskState.SUBMITTED, "ctx1"); + Task expectedTask = createSampleTask("test_task", TaskState.TASK_STATE_SUBMITTED, "ctx1"); when(mockTaskManager.getTask()).thenReturn(expectedTask); EventKind result = aggregator.getCurrentResult(); @@ -161,7 +160,7 @@ void testConstructorStoresTaskManagerCorrectly() { @Test void testConstructorWithNullMessage() { ResultAggregator aggregatorWithNullMessage = new ResultAggregator(mockTaskManager, null, testExecutor, testExecutor); - Task expectedTask = createSampleTask("null_msg_task", TaskState.WORKING, "ctx1"); + Task expectedTask = createSampleTask("null_msg_task", TaskState.TASK_STATE_WORKING, "ctx1"); when(mockTaskManager.getTask()).thenReturn(expectedTask); EventKind result = aggregatorWithNullMessage.getCurrentResult(); @@ -172,7 +171,7 @@ void testConstructorWithNullMessage() { @Test void testGetCurrentResultReturnsTaskWhenNoMessage() { - Task expectedTask = createSampleTask("no_message_task", TaskState.COMPLETED, "ctx1"); + Task expectedTask = createSampleTask("no_message_task", TaskState.TASK_STATE_COMPLETED, "ctx1"); when(mockTaskManager.getTask()).thenReturn(expectedTask); EventKind result = aggregator.getCurrentResult(); @@ -185,8 +184,8 @@ void testGetCurrentResultReturnsTaskWhenNoMessage() { @Test void testGetCurrentResultWithDifferentTaskStates() { // Test with WORKING and COMPLETED states using chained returns - Task workingTask = createSampleTask("working_task", TaskState.WORKING, "ctx1"); - Task completedTask = createSampleTask("completed_task", TaskState.COMPLETED, "ctx1"); + Task workingTask = createSampleTask("working_task", TaskState.TASK_STATE_WORKING, "ctx1"); + Task completedTask = createSampleTask("completed_task", TaskState.TASK_STATE_COMPLETED, "ctx1"); when(mockTaskManager.getTask()).thenReturn(workingTask, completedTask); // First call returns WORKING task @@ -201,7 +200,7 @@ void testGetCurrentResultWithDifferentTaskStates() { @Test void testMultipleGetCurrentResultCalls() { // Test that multiple calls to getCurrentResult behave consistently - Task expectedTask = createSampleTask("multi_call_task", TaskState.SUBMITTED, "ctx1"); + Task expectedTask = createSampleTask("multi_call_task", TaskState.TASK_STATE_SUBMITTED, "ctx1"); when(mockTaskManager.getTask()).thenReturn(expectedTask); EventKind result1 = aggregator.getCurrentResult(); @@ -223,7 +222,7 @@ void testGetCurrentResultWithMessageTakesPrecedence() { ResultAggregator messageAggregator = new ResultAggregator(mockTaskManager, message, testExecutor, testExecutor); // Even if we set up the task manager to return something, message should take precedence - Task task = createSampleTask("should_not_be_returned", TaskState.WORKING, "ctx1"); + Task task = createSampleTask("should_not_be_returned", TaskState.TASK_STATE_WORKING, "ctx1"); when(mockTaskManager.getTask()).thenReturn(task); EventKind result = messageAggregator.getCurrentResult(); @@ -237,7 +236,7 @@ void testGetCurrentResultWithMessageTakesPrecedence() { void testConsumeAndBreakNonBlocking() throws Exception { // Test that with blocking=false, the method returns after the first event String taskId = "test-task"; - Task firstEvent = createSampleTask(taskId, TaskState.WORKING, "ctx1"); + Task firstEvent = createSampleTask(taskId, TaskState.TASK_STATE_WORKING, "ctx1"); // After processing firstEvent, the current result will be that task when(mockTaskManager.getTask()).thenReturn(firstEvent); 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 c058ee22e..627fd81d5 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 @@ -31,7 +31,7 @@ public class TaskManagerTest { { "id": "task-abc", "contextId" : "session-xyz", - "status": {"state": "submitted"} + "status": {"state": "TASK_STATE_SUBMITTED"} }"""; Task minimalTask; @@ -73,7 +73,7 @@ public void testSaveTaskEventStatusUpdate() throws A2AServerException { taskStore.save(initialTask, false); TaskStatus newStatus = new TaskStatus( - TaskState.WORKING, + TaskState.TASK_STATE_WORKING, Message.builder() .role(Message.Role.AGENT) .parts(Collections.singletonList(new TextPart("content"))) @@ -140,7 +140,7 @@ public void testEnsureTaskNonExistentForStatusUpdate() throws A2AServerException TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId("new-task") .contextId("some-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); taskManagerWithoutId.saveTaskEvent(event, false); @@ -151,7 +151,7 @@ public void testEnsureTaskNonExistentForStatusUpdate() throws A2AServerException Task newTask = taskManagerWithoutId.getTask(); assertEquals(event.taskId(), newTask.id()); assertEquals(event.contextId(), newTask.contextId()); - assertEquals(TaskState.SUBMITTED, newTask.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, newTask.status().state()); assertSame(newTask, task); } @@ -161,7 +161,7 @@ public void testSaveTaskEventNewTaskNoTaskId() throws A2AServerException { Task task = Task.builder() .id("new-task-id") .contextId("some-context") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); taskManagerWithoutId.saveTaskEvent(task, false); @@ -335,7 +335,7 @@ public void testAddingTaskWithDifferentIdFails() { Task differentTask = Task.builder() .id("different-task-id") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); assertThrows(A2AServerException.class, () -> { @@ -351,7 +351,7 @@ public void testAddingTaskWithDifferentIdViaStatusUpdateFails() { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId("different-task-id") .contextId("session-xyz") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); assertThrows(A2AServerException.class, () -> { @@ -396,7 +396,7 @@ public void testTaskWithNoMessageUsesInitialMessage() throws A2AServerException TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId("new-task-id") .contextId("some-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); taskManagerWithInitialMessage.saveTaskEvent(event, false); @@ -433,7 +433,7 @@ public void testTaskWithMessageDoesNotUseInitialMessage() throws A2AServerExcept TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId("new-task-id") .contextId("some-context") - .status(new TaskStatus(TaskState.SUBMITTED, taskMessage, null)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, taskMessage, null)) .build(); taskManagerWithInitialMessage.saveTaskEvent(event, false); @@ -561,7 +561,7 @@ public void testSaveTaskEventMetadataUpdate() throws A2AServerException { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId(minimalTask.id()) .contextId(minimalTask.contextId()) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .metadata(newMetadata) .build(); @@ -580,7 +580,7 @@ public void testSaveTaskEventMetadataUpdateNull() throws A2AServerException { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId(minimalTask.id()) .contextId(minimalTask.contextId()) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .metadata(null) .build(); @@ -608,7 +608,7 @@ public void testSaveTaskEventMetadataMergeExisting() throws A2AServerException { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId(minimalTask.id()) .contextId(minimalTask.contextId()) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .metadata(newMetadata) .build(); @@ -635,7 +635,7 @@ public void testCreateTaskWithInitialMessage() throws A2AServerException { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId("new-task-id") .contextId("some-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); taskManagerWithMessage.saveTaskEvent(event, false); @@ -645,7 +645,7 @@ public void testCreateTaskWithInitialMessage() throws A2AServerException { assertNotNull(savedTask); assertEquals("new-task-id", savedTask.id()); assertEquals("some-context", savedTask.contextId()); - assertEquals(TaskState.SUBMITTED, savedTask.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, savedTask.status().state()); // Verify initial message is in history assertNotNull(savedTask.history()); @@ -663,7 +663,7 @@ public void testCreateTaskWithoutInitialMessage() throws A2AServerException { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId("new-task-id") .contextId("some-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); taskManagerWithoutMessage.saveTaskEvent(event, false); @@ -673,7 +673,7 @@ public void testCreateTaskWithoutInitialMessage() throws A2AServerException { assertNotNull(savedTask); assertEquals("new-task-id", savedTask.id()); assertEquals("some-context", savedTask.contextId()); - assertEquals(TaskState.SUBMITTED, savedTask.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, savedTask.status().state()); // Verify no history since there was no initial message assertTrue(savedTask.history().isEmpty()); @@ -687,7 +687,7 @@ public void testSaveTaskInternal() throws A2AServerException { Task newTask = Task.builder() .id("test-task-id") .contextId("test-context") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); taskManagerWithoutId.saveTaskEvent(newTask, false); @@ -718,7 +718,7 @@ public void testUpdateWithMessage() throws A2AServerException { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId("new-task-id") .contextId("some-context") - .status(new TaskStatus(TaskState.SUBMITTED, taskMessage, null)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, taskMessage, null)) .build(); taskManagerWithInitialMessage.saveTaskEvent(event, false); 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 45063b3ed..0067223dd 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 @@ -439,7 +439,7 @@ default io.a2a.spec.TaskState taskStateOrNull(io.a2a.grpc.TaskState state) { // Reject invalid enum values (e.g., "INVALID_STATUS" from JSON) if (state == io.a2a.grpc.TaskState.UNRECOGNIZED) { String validStates = java.util.Arrays.stream(io.a2a.spec.TaskState.values()) - .filter(s -> s != io.a2a.spec.TaskState.UNKNOWN) + .filter(s -> s != io.a2a.spec.TaskState.UNRECOGNIZED) .map(Enum::name) .collect(java.util.stream.Collectors.joining(", ")); throw new InvalidParamsError(null, diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java index 80e260a61..dcafce7ee 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java @@ -30,15 +30,15 @@ default io.a2a.grpc.TaskState toProto(io.a2a.spec.TaskState domain) { } return switch (domain) { - case SUBMITTED -> io.a2a.grpc.TaskState.TASK_STATE_SUBMITTED; - case WORKING -> io.a2a.grpc.TaskState.TASK_STATE_WORKING; - case INPUT_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_INPUT_REQUIRED; - case AUTH_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_AUTH_REQUIRED; - case COMPLETED -> io.a2a.grpc.TaskState.TASK_STATE_COMPLETED; - case CANCELED -> io.a2a.grpc.TaskState.TASK_STATE_CANCELED; - case FAILED -> io.a2a.grpc.TaskState.TASK_STATE_FAILED; - case REJECTED -> io.a2a.grpc.TaskState.TASK_STATE_REJECTED; - case UNKNOWN -> io.a2a.grpc.TaskState.UNRECOGNIZED; + case TASK_STATE_SUBMITTED -> io.a2a.grpc.TaskState.TASK_STATE_SUBMITTED; + case TASK_STATE_WORKING -> io.a2a.grpc.TaskState.TASK_STATE_WORKING; + case TASK_STATE_INPUT_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_INPUT_REQUIRED; + case TASK_STATE_AUTH_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_AUTH_REQUIRED; + case TASK_STATE_COMPLETED -> io.a2a.grpc.TaskState.TASK_STATE_COMPLETED; + case TASK_STATE_CANCELED -> io.a2a.grpc.TaskState.TASK_STATE_CANCELED; + case TASK_STATE_FAILED -> io.a2a.grpc.TaskState.TASK_STATE_FAILED; + case TASK_STATE_REJECTED -> io.a2a.grpc.TaskState.TASK_STATE_REJECTED; + case UNRECOGNIZED -> io.a2a.grpc.TaskState.UNRECOGNIZED; }; } @@ -50,19 +50,19 @@ default io.a2a.grpc.TaskState toProto(io.a2a.spec.TaskState domain) { */ default io.a2a.spec.TaskState fromProto(io.a2a.grpc.TaskState proto) { if (proto == null) { - return io.a2a.spec.TaskState.UNKNOWN; + return io.a2a.spec.TaskState.UNRECOGNIZED; } return switch (proto) { - case TASK_STATE_SUBMITTED -> io.a2a.spec.TaskState.SUBMITTED; - case TASK_STATE_WORKING -> io.a2a.spec.TaskState.WORKING; - case TASK_STATE_INPUT_REQUIRED -> io.a2a.spec.TaskState.INPUT_REQUIRED; - case TASK_STATE_AUTH_REQUIRED -> io.a2a.spec.TaskState.AUTH_REQUIRED; - case TASK_STATE_COMPLETED -> io.a2a.spec.TaskState.COMPLETED; - case TASK_STATE_CANCELED -> io.a2a.spec.TaskState.CANCELED; - case TASK_STATE_FAILED -> io.a2a.spec.TaskState.FAILED; - case TASK_STATE_REJECTED -> io.a2a.spec.TaskState.REJECTED; - case TASK_STATE_UNSPECIFIED, UNRECOGNIZED -> io.a2a.spec.TaskState.UNKNOWN; + case TASK_STATE_SUBMITTED -> io.a2a.spec.TaskState.TASK_STATE_SUBMITTED; + case TASK_STATE_WORKING -> io.a2a.spec.TaskState.TASK_STATE_WORKING; + case TASK_STATE_INPUT_REQUIRED -> io.a2a.spec.TaskState.TASK_STATE_INPUT_REQUIRED; + case TASK_STATE_AUTH_REQUIRED -> io.a2a.spec.TaskState.TASK_STATE_AUTH_REQUIRED; + case TASK_STATE_COMPLETED -> io.a2a.spec.TaskState.TASK_STATE_COMPLETED; + case TASK_STATE_CANCELED -> io.a2a.spec.TaskState.TASK_STATE_CANCELED; + case TASK_STATE_FAILED -> io.a2a.spec.TaskState.TASK_STATE_FAILED; + case TASK_STATE_REJECTED -> io.a2a.spec.TaskState.TASK_STATE_REJECTED; + case TASK_STATE_UNSPECIFIED, UNRECOGNIZED -> io.a2a.spec.TaskState.UNRECOGNIZED; }; } } 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 4fad9f91e..88d1e79f2 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 @@ -26,7 +26,7 @@ void testConvertTask_ToProto() { Task task = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); // Act @@ -62,7 +62,7 @@ void testConvertTask_FromProto() { Task task = (Task) result; assertEquals("task-123", task.id()); assertEquals("context-456", task.contextId()); - assertEquals(TaskState.COMPLETED, task.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); } @Test @@ -118,7 +118,7 @@ void testConvertTaskStatusUpdateEvent_ToProto() { TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() .taskId("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); // Act @@ -154,7 +154,7 @@ void testConvertTaskStatusUpdateEvent_FromProto() { TaskStatusUpdateEvent event = (TaskStatusUpdateEvent) result; assertEquals("task-123", event.taskId()); assertEquals("context-456", event.contextId()); - assertEquals(TaskState.WORKING, event.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, event.status().state()); assertEquals(false, event.isFinal()); } @@ -231,7 +231,7 @@ void testConvertStreamResponse_Roundtrip_Task() { Task originalTask = Task.builder() .id("task-123") .contextId("context-456") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); // Act diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index 4a3b1e2c6..d948f2f3a 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -133,7 +133,7 @@ public void convertAgentCard() { public void convertTask() { Task task = Task.builder().id("cancel-task-123") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); io.a2a.grpc.Task result = ProtoUtils.ToProto.task(task); assertEquals("session-xyz", result.getContextId()); @@ -143,7 +143,7 @@ public void convertTask() { assertEquals(0, result.getHistoryCount()); task = Task.builder().id("cancel-task-123") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .artifacts(List.of(Artifact.builder() .artifactId("11") .name("artefact") @@ -257,7 +257,7 @@ public void convertTaskArtifactUpdateEvent() { @Test public void convertTaskStatusUpdateEvent() { - TaskStatus completedStatus = new TaskStatus(TaskState.COMPLETED); + TaskStatus completedStatus = new TaskStatus(TaskState.TASK_STATE_COMPLETED); // Use constructor since Builder doesn't have isFinal method TaskStatusUpdateEvent tsue = new TaskStatusUpdateEvent( "1234", @@ -288,7 +288,7 @@ public void convertSendMessageConfiguration() { @Test public void convertTaskTimestampStatus() { OffsetDateTime expectedTimestamp = OffsetDateTime.parse("2024-10-05T12:34:56Z"); - TaskStatus testStatus = new TaskStatus(TaskState.COMPLETED, null, expectedTimestamp); + TaskStatus testStatus = new TaskStatus(TaskState.TASK_STATE_COMPLETED, null, expectedTimestamp); Task task = Task.builder() .id("task-123") .contextId("context-456") @@ -298,7 +298,7 @@ public void convertTaskTimestampStatus() { io.a2a.grpc.Task grpcTask = ProtoUtils.ToProto.task(task); task = ProtoUtils.FromProto.task(grpcTask); TaskStatus status = task.status(); - assertEquals(TaskState.COMPLETED, status.state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, status.state()); assertNotNull(status.timestamp()); assertEquals(expectedTimestamp, status.timestamp()); } diff --git a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java index 13853a16a..83e19ec54 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java @@ -9,11 +9,11 @@ * 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 - * but the task is in a terminal state ({@link TaskState#COMPLETED}, {@link TaskState#FAILED}, - * {@link TaskState#CANCELED}) where cancellation is not applicable. + * but the task is in a terminal state ({@link TaskState#TASK_STATE_COMPLETED}, {@link TaskState#TASK_STATE_FAILED}, + * {@link TaskState#TASK_STATE_CANCELED}) where cancellation is not applicable. *

        - * Tasks can only be canceled when they are in non-terminal states such as {@link TaskState#SUBMITTED} - * or {@link TaskState#WORKING}. + * Tasks can only be canceled when they are in non-terminal states such as {@link TaskState#TASK_STATE_SUBMITTED} + * or {@link TaskState#TASK_STATE_WORKING}. *

        * Corresponds to A2A-specific error code {@code -32002}. *

        diff --git a/spec/src/main/java/io/a2a/spec/TaskState.java b/spec/src/main/java/io/a2a/spec/TaskState.java index 742e74488..ca5354167 100644 --- a/spec/src/main/java/io/a2a/spec/TaskState.java +++ b/spec/src/main/java/io/a2a/spec/TaskState.java @@ -9,19 +9,19 @@ *

        * Transitional States: *

          - *
        • SUBMITTED: Task has been received by the agent and is queued for processing
        • - *
        • WORKING: Agent is actively processing the task and may produce incremental results
        • - *
        • INPUT_REQUIRED: Agent needs additional input from the user to continue
        • - *
        • AUTH_REQUIRED: Agent requires authentication or authorization before proceeding
        • + *
        • TASK_STATE_SUBMITTED: Task has been received by the agent and is queued for processing
        • + *
        • TASK_STATE_WORKING: Agent is actively processing the task and may produce incremental results
        • + *
        • TASK_STATE_INPUT_REQUIRED: Agent needs additional input from the user to continue
        • + *
        • TASK_STATE_AUTH_REQUIRED: Agent requires authentication or authorization before proceeding
        • *
        *

        * Terminal States: *

          - *
        • COMPLETED: Task finished successfully with all requested work done
        • - *
        • CANCELED: Task was explicitly canceled by the user or system
        • - *
        • FAILED: Task failed due to an error during execution
        • - *
        • REJECTED: Task was rejected by the agent (e.g., invalid request, policy violation)
        • - *
        • UNKNOWN: Task state cannot be determined (error recovery state)
        • + *
        • TASK_STATE_COMPLETED: Task finished successfully with all requested work done
        • + *
        • TASK_STATE_CANCELED: Task was explicitly canceled by the user or system
        • + *
        • TASK_STATE_FAILED: Task failed due to an error during execution
        • + *
        • TASK_STATE_REJECTED: Task was rejected by the agent (e.g., invalid request, policy violation)
        • + *
        • UNRECOGNIZED: Task state cannot be determined (error recovery state)
        • *
        *

        * The {@link #isFinal()} method can be used to determine if a state is terminal, which is @@ -33,56 +33,38 @@ */ public enum TaskState { /** Task has been received and is queued for processing (transitional state). */ - SUBMITTED("submitted"), + TASK_STATE_SUBMITTED(false), /** Agent is actively processing the task (transitional state). */ - WORKING("working"), + TASK_STATE_WORKING(false), /** Agent requires additional input from the user to continue (transitional state). */ - INPUT_REQUIRED("input-required"), + TASK_STATE_INPUT_REQUIRED(false), /** Agent requires authentication or authorization to proceed (transitional state). */ - AUTH_REQUIRED("auth-required"), + TASK_STATE_AUTH_REQUIRED(false), /** Task completed successfully (terminal state). */ - COMPLETED("completed", true), + TASK_STATE_COMPLETED(true), /** Task was canceled by user or system (terminal state). */ - CANCELED("canceled", true), + TASK_STATE_CANCELED(true), /** Task failed due to an error (terminal state). */ - FAILED("failed", true), + TASK_STATE_FAILED(true), /** Task was rejected by the agent (terminal state). */ - REJECTED("rejected", true), + TASK_STATE_REJECTED(true), /** Task state is unknown or cannot be determined (terminal state). */ - UNKNOWN("unknown", true); + UNRECOGNIZED(true); - private final String state; private final boolean isFinal; - TaskState(String state) { - this(state, false); - } - - TaskState(String state, boolean isFinal) { - this.state = state; + TaskState(boolean isFinal) { this.isFinal = isFinal; } - /** - * Returns the string representation of this task state for JSON serialization. - *

        - * This method is used to serialize TaskState values to their - * wire format (e.g., "working", "completed"). - * - * @return the string representation of this state - */ - public String asString() { - return state; - } - /** * Determines whether this state is a terminal (final) state. *

        @@ -90,35 +72,9 @@ public String asString() { * not transition to any other state. This is used by the event queue system * to determine when to close queues and by clients to know when to stop polling. * - * @return true if this is a terminal state (COMPLETED, CANCELED, FAILED, REJECTED, UNKNOWN), - * false for transitional states (SUBMITTED, WORKING, INPUT_REQUIRED, AUTH_REQUIRED) + * @return {@code true} if this is a terminal state, {@code false} else. */ public boolean isFinal(){ return isFinal; } - - /** - * Deserializes a string value into a TaskState enum constant. - *

        - * This method is used to deserialize TaskState values from their - * wire format during JSON parsing. - * - * @param state the string representation of the state - * @return the corresponding TaskState enum constant - * @throws IllegalArgumentException if the state string is not recognized - */ - public static TaskState fromString(String state) { - return switch (state) { - case "submitted" -> SUBMITTED; - case "working" -> WORKING; - case "input-required" -> INPUT_REQUIRED; - case "auth-required" -> AUTH_REQUIRED; - case "completed" -> COMPLETED; - case "canceled" -> CANCELED; - case "failed" -> FAILED; - case "rejected" -> REJECTED; - case "unknown" -> UNKNOWN; - default -> throw new IllegalArgumentException("Invalid TaskState: " + state); - }; - } } \ No newline at end of file diff --git a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java index 5cc6621cf..bacf9afc6 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java +++ b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java @@ -1,10 +1,10 @@ package io.a2a.spec; -import static io.a2a.spec.TaskState.CANCELED; -import static io.a2a.spec.TaskState.COMPLETED; -import static io.a2a.spec.TaskState.FAILED; -import static io.a2a.spec.TaskState.INPUT_REQUIRED; -import static io.a2a.spec.TaskState.REJECTED; +import static io.a2a.spec.TaskState.TASK_STATE_CANCELED; +import static io.a2a.spec.TaskState.TASK_STATE_COMPLETED; +import static io.a2a.spec.TaskState.TASK_STATE_FAILED; +import static io.a2a.spec.TaskState.TASK_STATE_INPUT_REQUIRED; +import static io.a2a.spec.TaskState.TASK_STATE_REJECTED; import java.util.Map; @@ -59,7 +59,7 @@ public String kind() { * @return true if the task is fianl or waiting for some inputs from the client - false otherwise. */ public boolean isFinalOrInterrupted() { - return status.state() == COMPLETED || status.state() == FAILED || status.state() == CANCELED || status.state() == REJECTED || status.state() == INPUT_REQUIRED; + return status.state() == TASK_STATE_COMPLETED || status.state() == TASK_STATE_FAILED || status.state() == TASK_STATE_CANCELED || status.state() == TASK_STATE_REJECTED || status.state() == TASK_STATE_INPUT_REQUIRED; } /** 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 9d16a86ea..b69a902e4 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java @@ -14,7 +14,6 @@ import io.a2a.spec.TaskNotCancelableError; import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; @ApplicationScoped public class AgentExecutorProducer { @@ -43,7 +42,7 @@ public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2 task = Task.builder() .id(context.getTaskId()) .contextId(context.getContextId()) - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .history(List.of(context.getMessage())) .build(); agentEmitter.addTask(task); @@ -76,12 +75,12 @@ public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2A System.out.println("====> No task found"); throw new TaskNotCancelableError(); } - if (task.status().state() == TaskState.CANCELED) { + if (task.status().state() == TaskState.TASK_STATE_CANCELED) { System.out.println("====> task already canceled"); throw new TaskNotCancelableError(); } - if (task.status().state() == TaskState.COMPLETED) { + if (task.status().state() == TaskState.TASK_STATE_COMPLETED) { System.out.println("====> task already completed"); throw new TaskNotCancelableError(); } 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 1c6dcdde4..f2da8de15 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 @@ -97,25 +97,25 @@ public abstract class AbstractA2AServerTest { protected static final Task MINIMAL_TASK = Task.builder() .id("task-123") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); private static final Task CANCEL_TASK = Task.builder() .id("cancel-task-123") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); private static final Task CANCEL_TASK_NOT_SUPPORTED = Task.builder() .id("cancel-task-not-supported-123") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); private static final Task SEND_MESSAGE_NOT_SUPPORTED = Task.builder() .id("task-not-supported-123") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); protected static final Message MESSAGE = Message.builder() @@ -185,7 +185,7 @@ private void testGetTask(String mediaType) throws Exception { Task response = getClient().getTask(new TaskQueryParams(MINIMAL_TASK.id())); assertEquals("task-123", response.id()); assertEquals("session-xyz", response.contextId()); - assertEquals(TaskState.SUBMITTED, response.status().state()); + assertEquals(TaskState.TASK_STATE_SUBMITTED, response.status().state()); } catch (A2AClientException e) { fail("Unexpected exception during getTask: " + e.getMessage(), e); } finally { @@ -212,7 +212,7 @@ public void testCancelTaskSuccess() throws Exception { Task task = getClient().cancelTask(new TaskIdParams(CANCEL_TASK.id())); assertEquals(CANCEL_TASK.id(), task.id()); assertEquals(CANCEL_TASK.contextId(), task.contextId()); - assertEquals(TaskState.CANCELED, task.status().state()); + assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); } catch (A2AClientException e) { fail("Unexpected exception during cancel task: " + e.getMessage(), e); } finally { @@ -251,17 +251,17 @@ public void testListTasksSuccess() throws Exception { Task task1 = Task.builder() .id("list-task-1") .contextId("context-1") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); Task task2 = Task.builder() .id("list-task-2") .contextId("context-1") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task task3 = Task.builder() .id("list-task-3") .contextId("context-2") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); saveTaskInTaskStore(task1); @@ -290,17 +290,17 @@ public void testListTasksFilterByContextId() throws Exception { Task task1 = Task.builder() .id("list-task-ctx-1") .contextId("context-filter-1") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); Task task2 = Task.builder() .id("list-task-ctx-2") .contextId("context-filter-1") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task task3 = Task.builder() .id("list-task-ctx-3") .contextId("context-filter-2") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); saveTaskInTaskStore(task1); @@ -331,17 +331,17 @@ public void testListTasksFilterByStatus() throws Exception { Task task1 = Task.builder() .id("list-task-status-1") .contextId("context-status") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task task2 = Task.builder() .id("list-task-status-2") .contextId("context-status") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); Task task3 = Task.builder() .id("list-task-status-3") .contextId("context-status") - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); saveTaskInTaskStore(task1); @@ -351,7 +351,7 @@ public void testListTasksFilterByStatus() throws Exception { try { // Filter by status WORKING io.a2a.spec.ListTasksParams params = ListTasksParams.builder() - .status(TaskState.WORKING) + .status(TaskState.TASK_STATE_WORKING) .tenant("") .build(); ListTasksResult result = getClient().listTasks(params); @@ -361,7 +361,7 @@ public void testListTasksFilterByStatus() throws Exception { assertTrue(result.tasks().size() >= 2, "Should have at least 2 WORKING tasks"); assertTrue(result.tasks().stream() .filter(t -> t.id().startsWith("list-task-status-")) - .allMatch(t -> TaskState.WORKING.equals(t.status().state()))); + .allMatch(t -> TaskState.TASK_STATE_WORKING.equals(t.status().state()))); } finally { deleteTaskInTaskStore(task1.id()); deleteTaskInTaskStore(task2.id()); @@ -375,17 +375,17 @@ public void testListTasksWithPagination() throws Exception { Task task1 = Task.builder() .id("page-task-1") .contextId("page-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); Task task2 = Task.builder() .id("page-task-2") .contextId("page-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); Task task3 = Task.builder() .id("page-task-3") .contextId("page-context") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); saveTaskInTaskStore(task1); @@ -436,7 +436,7 @@ public void testListTasksWithHistoryLimit() throws Exception { Task taskWithHistory = Task.builder() .id("list-task-history") .contextId("context-history") - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .history(history) .build(); @@ -715,7 +715,7 @@ public void testSubscribeExistingTaskSuccess() throws Exception { TaskStatusUpdateEvent.builder() .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build()); for (Event event : events) { @@ -741,7 +741,7 @@ public void testSubscribeExistingTaskSuccess() throws Exception { assertNotNull(receivedStatusEvent); assertEquals(MINIMAL_TASK.id(), receivedStatusEvent.taskId()); assertEquals(MINIMAL_TASK.contextId(), receivedStatusEvent.contextId()); - assertEquals(TaskState.COMPLETED, receivedStatusEvent.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, receivedStatusEvent.status().state()); assertNotNull(receivedStatusEvent.status().timestamp()); } finally { deleteTaskInTaskStore(MINIMAL_TASK.id()); @@ -833,7 +833,7 @@ public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Excepti TaskStatusUpdateEvent.builder() .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build()); for (Event event : events) { @@ -859,7 +859,7 @@ public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Excepti assertNotNull(receivedStatusEvent); assertEquals(MINIMAL_TASK.id(), receivedStatusEvent.taskId()); assertEquals(MINIMAL_TASK.contextId(), receivedStatusEvent.contextId()); - assertEquals(TaskState.COMPLETED, receivedStatusEvent.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, receivedStatusEvent.status().state()); assertNotNull(receivedStatusEvent.status().timestamp()); } finally { deleteTaskInTaskStore(MINIMAL_TASK.id()); @@ -1204,7 +1204,7 @@ public void testDeletePushNotificationConfigWithValidConfigId() throws Exception saveTaskInTaskStore(Task.builder() .id("task-456") .contextId("session-xyz") - .status(new TaskStatus(TaskState.SUBMITTED)) + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build()); PushNotificationConfig notificationConfig1 @@ -1558,7 +1558,7 @@ public void testInputRequiredWorkflow() throws Exception { TaskState state = te.getTask().status().state(); initialState.set(state); // Only count down when we receive INPUT_REQUIRED, not intermediate states like WORKING - if (state == TaskState.INPUT_REQUIRED) { + if (state == TaskState.TASK_STATE_INPUT_REQUIRED) { initialLatch.countDown(); } } else { @@ -1570,7 +1570,7 @@ public void testInputRequiredWorkflow() throws Exception { getNonStreamingClient().sendMessage(initialMessage, List.of(initialConsumer), null); assertTrue(initialLatch.await(10, TimeUnit.SECONDS)); assertFalse(initialUnexpectedEvent.get()); - assertEquals(TaskState.INPUT_REQUIRED, initialState.get()); + assertEquals(TaskState.TASK_STATE_INPUT_REQUIRED, initialState.get()); // 2. Send input message - AgentExecutor will complete the task Message inputMessage = Message.builder(MESSAGE) @@ -1592,7 +1592,7 @@ public void testInputRequiredWorkflow() throws Exception { TaskState state = te.getTask().status().state(); completedState.set(state); // Only count down when we receive COMPLETED, not intermediate states like WORKING - if (state == TaskState.COMPLETED) { + if (state == TaskState.TASK_STATE_COMPLETED) { completionLatch.countDown(); } } else { @@ -1604,7 +1604,7 @@ public void testInputRequiredWorkflow() throws Exception { getNonStreamingClient().sendMessage(inputMessage, List.of(completionConsumer), null); assertTrue(completionLatch.await(10, TimeUnit.SECONDS)); assertFalse(completionUnexpectedEvent.get()); - assertEquals(TaskState.COMPLETED, completedState.get()); + assertEquals(TaskState.TASK_STATE_COMPLETED, completedState.get()); } finally { deleteTaskInTaskStore(inputRequiredTaskId); @@ -2237,7 +2237,7 @@ public void testMainQueueStaysOpenForNonFinalTasks() throws Exception { Task workingTask = Task.builder() .id(taskId) .contextId(contextId) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); saveTaskInTaskStore(workingTask); 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 80d7d7f39..cc09a48af 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 @@ -1,6 +1,5 @@ package io.a2a.transport.grpc.handler; -import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; @@ -23,7 +22,6 @@ import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; import io.a2a.server.requesthandlers.DefaultRequestHandler; import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.tasks.AgentEmitter; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentExtension; @@ -371,7 +369,7 @@ public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() throws Excep TaskStatusUpdateEvent.builder() .taskId(task.id()) .contextId(task.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.WORKING)) + .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_WORKING)) .build()); StreamRecorder streamRecorder; @@ -421,7 +419,7 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex TaskStatusUpdateEvent.builder() .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.COMPLETED)) + .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_COMPLETED)) .build()); agentExecutorExecute = (context, agentEmitter) -> { @@ -482,7 +480,7 @@ public void onCompleted() { TaskStatusUpdateEvent statusUpdate = (TaskStatusUpdateEvent) httpClient.events.get(2); Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), statusUpdate.taskId()); Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), statusUpdate.contextId()); - Assertions.assertEquals(io.a2a.spec.TaskState.COMPLETED, statusUpdate.status().state()); + Assertions.assertEquals(io.a2a.spec.TaskState.TASK_STATE_COMPLETED, statusUpdate.status().state()); } finally { mainEventBusProcessor.setPushNotificationExecutor(null); } @@ -562,7 +560,7 @@ public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { TaskStatusUpdateEvent.builder() .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.WORKING)) + .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_WORKING)) .build()); StreamRecorder streamRecorder = StreamRecorder.create(); 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 67ac7a2a9..5b04b9428 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 @@ -142,7 +142,7 @@ public void testOnCancelTaskSuccess() throws Exception { Task task = response.getResult(); assertEquals(MINIMAL_TASK.id(), task.id()); assertEquals(MINIMAL_TASK.contextId(), task.contextId()); - assertEquals(TaskState.CANCELED, task.status().state()); + assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); } @Test @@ -310,7 +310,7 @@ public void testOnMessageStreamNewMessageMultipleEventsSuccess() throws Interrup // Create multiple events to be sent during streaming Task taskEvent = Task.builder(MINIMAL_TASK) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); TaskArtifactUpdateEvent artifactEvent = TaskArtifactUpdateEvent.builder() @@ -325,7 +325,7 @@ public void testOnMessageStreamNewMessageMultipleEventsSuccess() throws Interrup TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build(); // Configure the agent executor to enqueue multiple events @@ -397,7 +397,7 @@ public void onComplete() { Task receivedTask = assertInstanceOf(Task.class, results.get(0), "First event should be a Task"); assertEquals(MINIMAL_TASK.id(), receivedTask.id()); assertEquals(MINIMAL_TASK.contextId(), receivedTask.contextId()); - assertEquals(TaskState.WORKING, receivedTask.status().state()); + assertEquals(TaskState.TASK_STATE_WORKING, receivedTask.status().state()); // Verify the second event is the artifact update TaskArtifactUpdateEvent receivedArtifact = assertInstanceOf(TaskArtifactUpdateEvent.class, results.get(1), @@ -409,13 +409,13 @@ public void onComplete() { TaskStatusUpdateEvent receivedStatus = assertInstanceOf(TaskStatusUpdateEvent.class, results.get(2), "Third event should be a TaskStatusUpdateEvent"); assertEquals(MINIMAL_TASK.id(), receivedStatus.taskId()); - assertEquals(TaskState.COMPLETED, receivedStatus.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, receivedStatus.status().state()); // Verify events were persisted to TaskStore (poll for final state) for (int i = 0; i < 50; i++) { Task storedTask = taskStore.get(MINIMAL_TASK.id()); if (storedTask != null && storedTask.status() != null - && TaskState.COMPLETED.equals(storedTask.status().state())) { + && TaskState.TASK_STATE_COMPLETED.equals(storedTask.status().state())) { return; // Success - task finalized in TaskStore } Thread.sleep(100); @@ -441,7 +441,7 @@ public void testOnMessageStreamNewMessageSuccessMocks() { TaskStatusUpdateEvent.builder() .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build()); Message message = Message.builder(MESSAGE) @@ -588,7 +588,7 @@ public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() { TaskStatusUpdateEvent.builder() .taskId(task.id()) .contextId(task.contextId()) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build()); Message message = Message.builder(MESSAGE) @@ -719,7 +719,7 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex TaskStatusUpdateEvent.builder() .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.COMPLETED)) + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) .build()); @@ -806,7 +806,7 @@ public void onComplete() { TaskStatusUpdateEvent statusUpdate = (TaskStatusUpdateEvent) httpClient.events.get(2); assertEquals(MINIMAL_TASK.id(), statusUpdate.taskId()); assertEquals(MINIMAL_TASK.contextId(), statusUpdate.contextId()); - assertEquals(TaskState.COMPLETED, statusUpdate.status().state()); + assertEquals(TaskState.TASK_STATE_COMPLETED, statusUpdate.status().state()); } finally { mainEventBusProcessor.setPushNotificationExecutor(null); } @@ -910,7 +910,7 @@ public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { TaskStatusUpdateEvent.builder() .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.WORKING)) + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build()); SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); 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 f15f9af74..7312824c2 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 @@ -221,33 +221,13 @@ public HTTPRestResponse listTasks(ServerCallContext context, String tenant, paramsBuilder.contextId(contextId); } if (status != null) { - TaskState taskState = null; + TaskState taskState; - // Try JSON format first (e.g., "working", "completed") try { - taskState = TaskState.fromString(status); + taskState = TaskState.valueOf(status); } catch (IllegalArgumentException e) { - // Try protobuf enum format (e.g., "TASK_STATE_WORKING") - if (status.startsWith(TASK_STATE_PREFIX)) { - String enumName = status.substring(TASK_STATE_PREFIX.length()); - try { - taskState = TaskState.valueOf(enumName); - } catch (IllegalArgumentException protoError) { - // Fall through to error handling below - } - } else { - // Try enum constant name directly (e.g., "WORKING") - try { - taskState = TaskState.valueOf(status); - } catch (IllegalArgumentException valueOfError) { - // Fall through to error handling below - } - } - } - - if (taskState == null) { String validStates = Arrays.stream(TaskState.values()) - .map(TaskState::asString) + .map(TaskState::name) .collect(Collectors.joining(", ")); Map errorData = new HashMap<>(); errorData.put("parameter", "status"); 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 a1e53d6ea..cc0e8c303 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 @@ -63,7 +63,7 @@ public void testListTasksStatusWireString() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "submitted", null, null, + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "TASK_STATE_SUBMITTED", null, null, null, null, null); Assertions.assertEquals(200, response.getStatusCode()); @@ -911,8 +911,8 @@ public void testListTasksEnumConstantStatus() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - // Enum constant format (SUBMITTED) should be accepted - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "SUBMITTED", null, null, + // Enum constant format (TASK_STATE_SUBMITTED) should be accepted + RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "TASK_STATE_SUBMITTED", null, null, null, null, null); Assertions.assertEquals(200, response.getStatusCode()); From d60cf0bfe51c2489e3ba4454f1009f55a6de075b Mon Sep 17 00:00:00 2001 From: LiZongbo Date: Tue, 17 Feb 2026 18:25:00 +0800 Subject: [PATCH 037/192] fix: handle empty Struct in valueToObject to prevent NullPointerException (#619) When processing a protobuf Value containing an empty Struct, the valueToObject method would call structToMap which returns null for empty structs. This caused a NullPointerException when the result was used in stream collection operations. The fix adds a null/empty check for STRUCT_VALUE case, returning an empty HashMap instead of delegating to structToMap when the struct has no fields. Fixes #618 --------- Co-authored-by: Claude Opus 4.5 Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../a2a/grpc/mapper/A2ACommonFieldMapper.java | 6 + .../grpc/mapper/A2ACommonFieldMapperTest.java | 108 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java 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 0067223dd..15ba5f48f 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 @@ -216,6 +216,12 @@ default Value objectToValue(Object value) { default Object valueToObject(Value value) { switch (value.getKindCase()) { case STRUCT_VALUE: + if (value.getStructValue() == null) { + return null; + } + if (value.getStructValue().getFieldsCount() == 0) { + return java.util.Collections.emptyMap(); + } return structToMap(value.getStructValue()); case LIST_VALUE: return value.getListValue().getValuesList().stream() diff --git a/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java b/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java new file mode 100644 index 000000000..67b2a0ffd --- /dev/null +++ b/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java @@ -0,0 +1,108 @@ +package io.a2a.grpc.mapper; + +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 java.util.Map; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; + +import io.a2a.grpc.utils.ProtoUtils; +import io.a2a.spec.MessageSendParams; +import org.junit.jupiter.api.Test; + +public class A2ACommonFieldMapperTest { + + /** + * Test that valueToObject handles empty struct correctly without throwing NullPointerException. + * + * This test verifies the fix for the bug where an empty struct in the JSON + * (e.g., "response": {}) would cause a NullPointerException because structToMap + * returns null for empty structs. + */ + @Test + void testValueToObject_WithEmptyStruct_ReturnsEmptyMap() throws InvalidProtocolBufferException { + // JSON containing an empty struct in "response" field + String json = "{\n" + + " \"message\": {\n" + + " \"messageId\": \"b3b1ab58-c3d0-4e6d-9e47-9d8a12fe0809\",\n" + + " \"role\": \"ROLE_USER\",\n" + + " \"parts\": [{\n" + + " \"text\": \"Hello\"\n" + + " }, {\n" + + " \"data\": {\n" + + " \"data\": {\n" + + " \"id\": \"call_94yo5ymj3qi5glbpkw5eicfd\",\n" + + " \"args\": {\n" + + " \"agent_name\": \"Default Agent\"\n" + + " },\n" + + " \"name\": \"transfer_to_agent\"\n" + + " }\n" + + " }\n" + + " }, {\n" + + " \"data\": {\n" + + " \"data\": {\n" + + " \"response\": {\n" + + " },\n" + + " \"id\": \"call_94yo5ymj3qi5glbpkw5eicfd\",\n" + + " \"name\": \"transfer_to_agent\"\n" + + " }\n" + + " }\n" + + " }, {\n" + + " \"text\": \"World\"\n" + + " }],\n" + + " \"metadata\": {\n" + + " }\n" + + " },\n" + + " \"configuration\": {\n" + + " \"blocking\": true\n" + + " },\n" + + " \"metadata\": {\n" + + " }\n" + + "}"; + + io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); + JsonFormat.parser().merge(json, builder); + + // This should not throw NullPointerException + MessageSendParams messageSendParams = ProtoUtils.FromProto.messageSendParams(builder); + + assertNotNull(messageSendParams); + assertNotNull(messageSendParams.message()); + assertEquals(4, messageSendParams.message().parts().size()); + } + + /** + * Test that valueToObject handles nested empty struct correctly. + */ + @Test + void testValueToObject_WithNestedEmptyStruct_ReturnsEmptyMap() throws InvalidProtocolBufferException { + String json = "{\n" + + " \"message\": {\n" + + " \"messageId\": \"test-id\",\n" + + " \"role\": \"ROLE_USER\",\n" + + " \"parts\": [{\n" + + " \"data\": {\n" + + " \"data\": {\n" + + " \"nested\": {\n" + + " \"empty\": {\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }]\n" + + " }\n" + + "}"; + + io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); + JsonFormat.parser().merge(json, builder); + + // This should not throw NullPointerException + MessageSendParams messageSendParams = ProtoUtils.FromProto.messageSendParams(builder); + + assertNotNull(messageSendParams); + assertNotNull(messageSendParams.message()); + } +} From 760b6a812e1a7874766bcedb8775577cfa5ad800 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 17 Feb 2026 14:44:15 +0100 Subject: [PATCH 038/192] feat: Add metadata support to Part types (#658) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add optional metadata field to TextPart, FilePart, and DataPart records to support additional contextual information for message and artifact content parts as specified in the A2A protocol v1.0. Changes: - Add metadata parameter to Part constructors (TextPart, FilePart, DataPart) - Update PartMapper to convert metadata between domain and gRPC proto - Update JsonUtil PartTypeAdapter to serialize/deserialize metadata Fixes #649 🦕 --------- Signed-off-by: Emmanuel Hugonnet --- .../tests-multi-instance/tests/pom.xml | 2 - .../io/a2a/jsonrpc/common/json/JsonUtil.java | 35 ++++++++++--- pom.xml | 8 +++ .../io/a2a/server/util/ArtifactUtils.java | 1 - .../java/io/a2a/grpc/mapper/PartMapper.java | 14 +++-- spec/src/main/java/io/a2a/spec/DataPart.java | 51 ++++--------------- spec/src/main/java/io/a2a/spec/FilePart.java | 19 ++++++- spec/src/main/java/io/a2a/spec/Message.java | 14 +++-- spec/src/main/java/io/a2a/spec/TextPart.java | 19 ++++++- .../grpc/handler/GrpcHandlerTest.java | 5 +- 10 files changed, 101 insertions(+), 67 deletions(-) diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index c780ce02d..5b01c60fd 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -84,8 +84,6 @@ org.jboss.logmanager.LogManager - - 1.44 diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index 35beb82d6..e2d3b751b 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -22,6 +22,7 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.util.Map; import java.util.Set; import com.google.gson.Gson; @@ -29,6 +30,7 @@ import com.google.gson.JsonSyntaxException; import com.google.gson.ToNumberPolicy; import com.google.gson.TypeAdapter; +import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; @@ -500,10 +502,18 @@ public void write(JsonWriter out, Message.Role value) throws java.io.IOException static class PartTypeAdapter extends TypeAdapter> { private static final Set VALID_KEYS = Set.of(TEXT, FILE, DATA); + private static final Type MAP_TYPE = new TypeToken>(){}.getType(); // Create separate Gson instance without the Part adapter to avoid recursion private final Gson delegateGson = createBaseGsonBuilder().create(); + private void writeMetadata(JsonWriter out, @Nullable Map metadata) throws java.io.IOException { + if (metadata != null && !metadata.isEmpty()) { + out.name("metadata"); + delegateGson.toJson(metadata, MAP_TYPE, out); + } + } + @Override public void write(JsonWriter out, Part value) throws java.io.IOException { if (value == null) { @@ -517,14 +527,17 @@ public void write(JsonWriter out, Part value) throws java.io.IOException { // TextPart: { "text": "value" } - direct string value out.name(TEXT); out.value(textPart.text()); + writeMetadata(out, textPart.metadata()); } else if (value instanceof FilePart filePart) { // FilePart: { "file": {...} } out.name(FILE); delegateGson.toJson(filePart.file(), FileContent.class, out); + writeMetadata(out, filePart.metadata()); } else if (value instanceof DataPart dataPart) { // DataPart: { "data": } out.name(DATA); delegateGson.toJson(dataPart.data(), Object.class, out); + writeMetadata(out, dataPart.metadata()); } else { throw new JsonSyntaxException("Unknown Part subclass: " + value.getClass().getName()); } @@ -548,24 +561,34 @@ Part read(JsonReader in) throws java.io.IOException { com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); + // Extract metadata if present + Map metadata = null; + if (jsonObject.has("metadata")) { + metadata = delegateGson.fromJson(jsonObject.get("metadata"), new TypeToken>(){}.getType()); + } + // Check for member name discriminators (v1.0 protocol) Set keys = jsonObject.keySet(); - if (keys.size() != 1) { - throw new JsonSyntaxException(format("Part object must have exactly one key, which must be one of: %s (found: %s)", VALID_KEYS, keys)); + if (keys.size() < 1 || keys.size() > 2) { + throw new JsonSyntaxException(format("Part object must have one content key from %s and optionally 'metadata' (found: %s)", VALID_KEYS, keys)); } - String discriminator = keys.iterator().next(); + // Find the discriminator (should be one of TEXT, FILE, DATA) + String discriminator = keys.stream() + .filter(VALID_KEYS::contains) + .findFirst() + .orElseThrow(() -> new JsonSyntaxException(format("Part must have one of: %s (found: %s)", VALID_KEYS, keys))); return switch (discriminator) { - case TEXT -> new TextPart(jsonObject.get(TEXT).getAsString()); - case FILE -> new FilePart(delegateGson.fromJson(jsonObject.get(FILE), FileContent.class)); + case TEXT -> new TextPart(jsonObject.get(TEXT).getAsString(), metadata); + case FILE -> new FilePart(delegateGson.fromJson(jsonObject.get(FILE), FileContent.class), metadata); case DATA -> { // DataPart supports any JSON value: object, array, primitive, or null Object data = delegateGson.fromJson( jsonObject.get(DATA), Object.class ); - yield new DataPart(data); + yield new DataPart(data, metadata); } default -> throw new JsonSyntaxException(format("Part must have one of: %s (found: %s)", VALID_KEYS, discriminator)); diff --git a/pom.xml b/pom.xml index 5ed76528b..29cdd730c 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,7 @@ 5.5.1 2.0.17 1.5.18 + 1.21.4 2.47.0 0.13.1 -XDaddTypeAnnotationsToSymbol=true @@ -226,6 +227,13 @@ pom import + + org.testcontainers + testcontainers-bom + ${version.testcontainers} + pom + import + io.quarkus quarkus-bom 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 df49a7c8a..4cb1f82b5 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 @@ -1,7 +1,6 @@ package io.a2a.server.util; import java.util.List; -import java.util.Map; import java.util.UUID; import io.a2a.spec.Artifact; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java index 41cef1a8d..8704f4699 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java @@ -12,6 +12,7 @@ import io.a2a.spec.InvalidRequestError; import io.a2a.spec.Part; import io.a2a.spec.TextPart; +import java.util.Map; import org.mapstruct.Mapper; /** @@ -46,6 +47,7 @@ default io.a2a.grpc.Part toProto(Part domain) { if (domain instanceof TextPart textPart) { builder.setText(textPart.text()); + builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(textPart.metadata())); } else if (domain instanceof FilePart filePart) { FileContent fileContent = filePart.file(); @@ -68,10 +70,12 @@ default io.a2a.grpc.Part toProto(Part domain) { builder.setMediaType(fileWithUri.mimeType()); } } + builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(filePart.metadata())); } else if (domain instanceof DataPart dataPart) { // Map data to google.protobuf.Value (supports object, array, primitive, or null) Value dataValue = A2ACommonFieldMapper.INSTANCE.objectToValue(dataPart.data()); builder.setData(dataValue); + builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(dataPart.metadata())); } return builder.build(); @@ -85,26 +89,26 @@ default Part fromProto(io.a2a.grpc.Part proto) { if (proto == null) { return null; } - + Map metadata = A2ACommonFieldMapper.INSTANCE.metadataFromProto(proto.getMetadata()); if (proto.hasText()) { - return new TextPart(proto.getText()); + return new TextPart(proto.getText(), metadata); } else if (proto.hasRaw()) { // raw bytes → FilePart(FileWithBytes) String bytes = Base64.getEncoder().encodeToString(proto.getRaw().toByteArray()); String mimeType = proto.getMediaType().isEmpty() ? null : proto.getMediaType(); String name = proto.getFilename().isEmpty() ? null : proto.getFilename(); - return new FilePart(new FileWithBytes(mimeType, name, bytes)); + return new FilePart(new FileWithBytes(mimeType, name, bytes), metadata); } else if (proto.hasUrl()) { // url → FilePart(FileWithUri) String uri = proto.getUrl(); String mimeType = proto.getMediaType().isEmpty() ? null : proto.getMediaType(); String name = proto.getFilename().isEmpty() ? null : proto.getFilename(); - return new FilePart(new FileWithUri(mimeType, name, uri)); + return new FilePart(new FileWithUri(mimeType, name, uri), metadata); } else if (proto.hasData()) { // data (google.protobuf.Value containing any JSON value) → DataPart Value dataValue = proto.getData(); Object data = A2ACommonFieldMapper.INSTANCE.valueToObject(dataValue); - return new DataPart(data); + return new DataPart(data, metadata); } throw new InvalidRequestError(); diff --git a/spec/src/main/java/io/a2a/spec/DataPart.java b/spec/src/main/java/io/a2a/spec/DataPart.java index 437debd8a..0e41bec23 100644 --- a/spec/src/main/java/io/a2a/spec/DataPart.java +++ b/spec/src/main/java/io/a2a/spec/DataPart.java @@ -2,6 +2,7 @@ import io.a2a.util.Assert; +import java.util.Map; import org.jspecify.annotations.Nullable; @@ -37,11 +38,12 @@ * } * * @param data the structured data (required, supports JSON objects, arrays, primitives, and null) + * @param metadata additional metadata for the part * @see Part * @see Message * @see Artifact */ -public record DataPart(Object data) implements Part { +public record DataPart(Object data, @Nullable Map metadata) implements Part { /** * The JSON member name discriminator for data parts: "data". @@ -60,50 +62,19 @@ public record DataPart(Object data) implements Part { * @param data the structured data (supports JSON objects, arrays, primitives, and null) * @throws IllegalArgumentException if data is null */ - public DataPart { + public DataPart (Object data, @Nullable Map metadata) { Assert.checkNotNullParam("data", data); + this.metadata = metadata == null ? null : Map.copyOf(metadata); + this.data = data; } /** - * Create a new Builder + * Constructor. * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link DataPart} instances. + * @param data the structured data (supports JSON objects, arrays, primitives, and not null) + * @throws IllegalArgumentException if data is null */ - public static class Builder { - private @Nullable Object data; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the structured data. - * - * @param data the structured data (required, supports JSON objects, arrays, primitives, and null) - * @return this builder for method chaining - */ - public Builder data(Object data) { - this.data = data; - return this; - } - - /** - * Builds a new {@link DataPart} from the current builder state. - * - * @return a new DataPart instance - * @throws IllegalArgumentException if data is null - */ - public DataPart build() { - return new DataPart(Assert.checkNotNullParam("data", data)); - } + public DataPart(Object data) { + this(data, null); } } diff --git a/spec/src/main/java/io/a2a/spec/FilePart.java b/spec/src/main/java/io/a2a/spec/FilePart.java index ac18393c6..8deec1e7d 100644 --- a/spec/src/main/java/io/a2a/spec/FilePart.java +++ b/spec/src/main/java/io/a2a/spec/FilePart.java @@ -2,6 +2,8 @@ import io.a2a.util.Assert; +import java.util.Map; +import org.jspecify.annotations.Nullable; /** @@ -31,12 +33,13 @@ * } * * @param file the file content (required, either FileWithBytes or FileWithUri) + * @param metadata additional metadata for the part * @see Part * @see FileContent * @see FileWithBytes * @see FileWithUri */ -public record FilePart(FileContent file) implements Part { +public record FilePart(FileContent file, @Nullable Map metadata) implements Part { /** * The JSON member name discriminator for file parts: "file". @@ -52,7 +55,19 @@ public record FilePart(FileContent file) implements Part { * @param file the file content (required, either FileWithBytes or FileWithUri) * @throws IllegalArgumentException if file is null */ - public FilePart { + public FilePart (FileContent file, @Nullable Map metadata) { Assert.checkNotNullParam("file", file); + this.metadata = metadata == null ? null : Map.copyOf(metadata); + this.file = file; + } + + /** + * Constructor. + * + * @param file the file content (required, either FileWithBytes or FileWithUri) + * @throws IllegalArgumentException if file is null + */ + public FilePart (FileContent file) { + this(file, null); } } diff --git a/spec/src/main/java/io/a2a/spec/Message.java b/spec/src/main/java/io/a2a/spec/Message.java index 9191a0fae..cc4b1cf12 100644 --- a/spec/src/main/java/io/a2a/spec/Message.java +++ b/spec/src/main/java/io/a2a/spec/Message.java @@ -35,14 +35,12 @@ * @see A2A Protocol Specification */ public record Message(Role role, List> parts, - String messageId, @Nullable - String contextId, - @Nullable - String taskId, @Nullable - List referenceTaskIds, - @Nullable - Map metadata, @Nullable - List extensions + String messageId, + @Nullable String contextId, + @Nullable String taskId, + @Nullable List referenceTaskIds, + @Nullable Map metadata, + @Nullable List extensions ) implements EventKind, StreamingEventKind { /** diff --git a/spec/src/main/java/io/a2a/spec/TextPart.java b/spec/src/main/java/io/a2a/spec/TextPart.java index 8fa4e8e83..e76cdd19d 100644 --- a/spec/src/main/java/io/a2a/spec/TextPart.java +++ b/spec/src/main/java/io/a2a/spec/TextPart.java @@ -2,6 +2,8 @@ import io.a2a.util.Assert; +import java.util.Map; +import org.jspecify.annotations.Nullable; /** @@ -20,11 +22,12 @@ * } * * @param text the text content (required, must not be null) + * @param metadata additional metadata for the part * @see Part * @see Message * @see Artifact */ -public record TextPart(String text) implements Part { +public record TextPart(String text, @Nullable Map metadata) implements Part { /** * The JSON member name discriminator for text parts: "text". @@ -40,7 +43,19 @@ public record TextPart(String text) implements Part { * @param text the text content (required, must not be null) * @throws IllegalArgumentException if text is null */ - public TextPart { + public TextPart (String text, @Nullable Map metadata) { Assert.checkNotNullParam("text", text); + this.metadata = metadata == null ? null : Map.copyOf(metadata); + this.text = text; + } + + /** + * Constructor. + * + * @param text the text content (required, must not be null) + * @throws IllegalArgumentException if data is null + */ + public TextPart (String text){ + this(text, null); } } 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 cc09a48af..fac5ce02c 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 @@ -54,7 +54,10 @@ public class GrpcHandlerTest extends AbstractA2ARequestHandlerTest { .setContextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) .setMessageId(AbstractA2ARequestHandlerTest.MESSAGE.messageId()) .setRole(Role.ROLE_AGENT) - .addParts(Part.newBuilder().setText(((TextPart) AbstractA2ARequestHandlerTest.MESSAGE.parts().get(0)).text()).build()) + .addParts(Part.newBuilder() + .setText(((TextPart) AbstractA2ARequestHandlerTest.MESSAGE.parts().get(0)).text()) + .setMetadata(Struct.newBuilder().build()) + .build()) .setMetadata(Struct.newBuilder().build()) .build(); From 4aa71070d287f72b1eab192f93478ef7159edefa Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 17 Feb 2026 14:57:35 +0100 Subject: [PATCH 039/192] fix: Why not set tenant to "" in ListTasksParams$Builder? (#657) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ListTasksParams.Builder should set the tenant to "" when it is not defined. Fixes #653 🦕 Signed-off-by: Emmanuel Hugonnet --- ...eleteTaskPushNotificationConfigParams.java | 3 +- .../GetTaskPushNotificationConfigParams.java | 3 +- .../ListTaskPushNotificationConfigParams.java | 86 +++++++++++++++++++ .../java/io/a2a/spec/ListTasksParams.java | 2 +- .../main/java/io/a2a/spec/TaskIdParams.java | 60 +++++++++++++ .../java/io/a2a/spec/TaskQueryParams.java | 72 ++++++++++++++++ 6 files changed, 223 insertions(+), 3 deletions(-) diff --git a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java index 28f438dfb..024663766 100644 --- a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java @@ -3,6 +3,7 @@ import io.a2a.util.Assert; +import io.a2a.util.Utils; import org.jspecify.annotations.Nullable; /** @@ -111,7 +112,7 @@ public DeleteTaskPushNotificationConfigParams build() { return new DeleteTaskPushNotificationConfigParams( Assert.checkNotNullParam("id", id), Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId), - Assert.checkNotNullParam("tenant", tenant)); + Utils.defaultIfNull(tenant,"")); } } } diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java index 070042e40..241c599e7 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java @@ -3,6 +3,7 @@ import io.a2a.util.Assert; +import io.a2a.util.Utils; import org.jspecify.annotations.Nullable; /** @@ -108,7 +109,7 @@ public GetTaskPushNotificationConfigParams build() { return new GetTaskPushNotificationConfigParams( Assert.checkNotNullParam("id", id), Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId), - Assert.checkNotNullParam("tenant", tenant)); + Utils.defaultIfNull(tenant,"")); } } } diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java index 766945603..f24f3c4ce 100644 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java @@ -1,6 +1,8 @@ package io.a2a.spec; import io.a2a.util.Assert; +import io.a2a.util.Utils; +import org.jspecify.annotations.Nullable; /** * Parameters for listing all push notification configurations for a task. @@ -51,4 +53,88 @@ public int getEffectivePageSize() { } return pageSize; } + + /** + * Create a new Builder + * + * @return the builder + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for constructing instances. + */ + public static class Builder { + private @Nullable String id; + private @Nullable Integer pageSize; + private @Nullable String pageToken; + private @Nullable String tenant; + + /** + * Creates a new Builder with all fields unset. + */ + private Builder() { + } + + /** + * Sets the id. + * + * @param id the task identifier (required) + * @return this builder for method chaining + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * Sets the pageSize. + * + * @param pageSize the maximum number of items to return per page + * @return this builder for method chaining + */ + public Builder pageSize(Integer pageSize) { + this.pageSize = pageSize; + return this; + } + + /** + * Sets the pageToken. + * + * @param pageToken the pagination token for the next page + * @return this builder for method chaining + */ + public Builder pageToken(String pageToken) { + this.pageToken = pageToken; + return this; + } + + /** + * Sets the tenant. + * + * @param tenant the tenant identifier + * @return this builder for method chaining + */ + public Builder tenant(String tenant) { + this.tenant = tenant; + return this; + } + + /** + * Builds the ListTaskPushNotificationConfigParams. + * + * @return a new ListTaskPushNotificationConfigParams instance + * @throws IllegalArgumentException if id is null + */ + public ListTaskPushNotificationConfigParams build() { + return new ListTaskPushNotificationConfigParams( + Assert.checkNotNullParam("id", id), + pageSize != null ? pageSize : 0, + pageToken != null ? pageToken : "", + Utils.defaultIfNull(tenant,"") + ); + } + } } diff --git a/spec/src/main/java/io/a2a/spec/ListTasksParams.java b/spec/src/main/java/io/a2a/spec/ListTasksParams.java index 906fda993..3a1680af9 100644 --- a/spec/src/main/java/io/a2a/spec/ListTasksParams.java +++ b/spec/src/main/java/io/a2a/spec/ListTasksParams.java @@ -227,7 +227,7 @@ public Builder tenant(String tenant) { */ public ListTasksParams build() { return new ListTasksParams(contextId, status, pageSize, pageToken, historyLength, - statusTimestampAfter, includeArtifacts, Assert.checkNotNullParam("tenant", tenant)); + statusTimestampAfter, includeArtifacts, tenant == null ? "" : tenant); } } } diff --git a/spec/src/main/java/io/a2a/spec/TaskIdParams.java b/spec/src/main/java/io/a2a/spec/TaskIdParams.java index d35eb37d9..972bb4a22 100644 --- a/spec/src/main/java/io/a2a/spec/TaskIdParams.java +++ b/spec/src/main/java/io/a2a/spec/TaskIdParams.java @@ -1,6 +1,8 @@ package io.a2a.spec; import io.a2a.util.Assert; +import io.a2a.util.Utils; +import org.jspecify.annotations.Nullable; /** * Parameters containing a task identifier for task-related operations. @@ -34,4 +36,62 @@ public record TaskIdParams(String id, String tenant) { public TaskIdParams(String id) { this(id, ""); } + + /** + * Create a new Builder + * + * @return the builder + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for constructing instances. + */ + public static class Builder { + private @Nullable String id; + private @Nullable String tenant; + + /** + * Creates a new Builder with all fields unset. + */ + private Builder() { + } + + /** + * Sets the id. + * + * @param id the task identifier (required) + * @return this builder for method chaining + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * Sets the tenant. + * + * @param tenant the tenant identifier + * @return this builder for method chaining + */ + public Builder tenant(String tenant) { + this.tenant = tenant; + return this; + } + + /** + * Builds the TaskIdParams. + * + * @return a new TaskIdParams instance + * @throws IllegalArgumentException if id is null + */ + public TaskIdParams build() { + return new TaskIdParams( + Assert.checkNotNullParam("id", id), + Utils.defaultIfNull(tenant,"") + ); + } + } } diff --git a/spec/src/main/java/io/a2a/spec/TaskQueryParams.java b/spec/src/main/java/io/a2a/spec/TaskQueryParams.java index 15717ee3b..9f5805f98 100644 --- a/spec/src/main/java/io/a2a/spec/TaskQueryParams.java +++ b/spec/src/main/java/io/a2a/spec/TaskQueryParams.java @@ -1,6 +1,7 @@ package io.a2a.spec; import io.a2a.util.Assert; +import io.a2a.util.Utils; import org.jspecify.annotations.Nullable; /** @@ -47,4 +48,75 @@ public TaskQueryParams(String id, @Nullable Integer historyLength) { public TaskQueryParams(String id) { this(id, null, ""); } + + /** + * Create a new Builder + * + * @return the builder + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for constructing instances. + */ + public static class Builder { + private @Nullable String id; + private @Nullable Integer historyLength; + private @Nullable String tenant; + + /** + * Creates a new Builder with all fields unset. + */ + private Builder() { + } + + /** + * Sets the id. + * + * @param id the task identifier (required) + * @return this builder for method chaining + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * Sets the historyLength. + * + * @param historyLength the maximum number of history items to include + * @return this builder for method chaining + */ + public Builder historyLength(Integer historyLength) { + this.historyLength = historyLength; + return this; + } + + /** + * Sets the tenant. + * + * @param tenant the tenant identifier + * @return this builder for method chaining + */ + public Builder tenant(String tenant) { + this.tenant = tenant; + return this; + } + + /** + * Builds the TaskQueryParams. + * + * @return a new TaskQueryParams instance + * @throws IllegalArgumentException if id is null or historyLength is negative + */ + public TaskQueryParams build() { + return new TaskQueryParams( + Assert.checkNotNullParam("id", id), + historyLength, + Utils.defaultIfNull(tenant,"") + ); + } + } } From 9366743ebf81c70e9f6caa8757283055b2a250b0 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 17 Feb 2026 18:10:19 +0100 Subject: [PATCH 040/192] chore: Renaming attributes in spec modules to align with the new names (#647) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit in the a2a.proto - io.a2a.spec.TaskPushNotificationConfig pushNotificationConfig to config - io.a2a.spec.DeleteTaskPushNotificationConfigParams id to taskId and pushNotificationConfigId to id - io.a2a.spec.GetTaskPushNotificationConfigParams id to taskId and pushNotificationConfigId to id - io.a2a.spec.ListTaskPushNotificationConfigParam s taskId to id Fixing issue #634 Fixes #634 🦕 Signed-off-by: Emmanuel Hugonnet --- .../client/transport/grpc/GrpcTransport.java | 14 +++---- .../jsonrpc/JSONRPCTransportTest.java | 4 +- .../client/transport/rest/RestTransport.java | 16 ++++---- .../transport/rest/RestTransportTest.java | 8 ++-- .../client/OpenTelemetryClientTransport.java | 20 +++++----- .../OpenTelemetryRequestHandlerDecorator.java | 16 ++++---- ...otificationConfigStoreIntegrationTest.java | 16 ++++---- .../JpaPushNotificationConfigStoreTest.java | 20 +++++----- .../DefaultRequestHandler.java | 29 ++++++-------- .../tasks/BasePushNotificationSender.java | 2 +- ...MemoryPushNotificationConfigStoreTest.java | 24 +++++------ ...reateTaskPushNotificationConfigMapper.java | 9 +---- ...askPushNotificationConfigParamsMapper.java | 8 ++-- ...askPushNotificationConfigParamsMapper.java | 8 ++-- .../TaskPushNotificationConfigMapper.java | 14 +++---- .../io/a2a/grpc/utils/JSONRPCUtilsTest.java | 10 ++--- .../java/io/a2a/grpc/utils/ToProtoTest.java | 4 +- ...eleteTaskPushNotificationConfigParams.java | 40 +++++++++---------- .../GetTaskPushNotificationConfigParams.java | 36 ++++++++--------- .../a2a/spec/TaskPushNotificationConfig.java | 11 ++--- .../src/main/java/io/a2a/spec/TaskStatus.java | 5 +++ spec/src/main/java/io/a2a/util/Utils.java | 7 ++++ .../apps/common/AbstractA2AServerTest.java | 6 +-- 23 files changed, 166 insertions(+), 161 deletions(-) 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 7824e83c0..ca849d99c 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 @@ -233,7 +233,7 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPu @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - String configId = request.pushNotificationConfig().id(); + String configId = request.config().id(); io.a2a.grpc.CreateTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() .setTaskId(request.taskId()) .setConfig(ToProto.taskPushNotificationConfig(request).getPushNotificationConfig()) @@ -254,15 +254,15 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPu public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - checkNotNullParam("taskId", request.id()); - if(request.pushNotificationConfigId() == null) { + checkNotNullParam("taskId", request.taskId()); + if(request.id() == null) { throw new IllegalArgumentException("Id must not be null"); } io.a2a.grpc.GetTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(request.id()) + .setTaskId(request.taskId()) .setTenant(resolveTenant(request.tenant())) - .setId(request.pushNotificationConfigId()) + .setId(request.id()) .build(); PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); @@ -304,8 +304,8 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC checkNotNullParam("request", request); io.a2a.grpc.DeleteTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(request.id()) - .setId(request.pushNotificationConfigId()) + .setTaskId(request.taskId()) + .setId(request.id()) .setTenant(resolveTenant(request.tenant())) .build(); PayloadAndHeaders payloadAndHeaders = applyInterceptors(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index e4983142b..849ac8fde 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -309,7 +309,7 @@ public void testA2AClientGetTaskPushNotificationConfig() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); TaskPushNotificationConfig taskPushNotificationConfig = client.getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64", "c295ea44-7543-4f78-b524-7a38915ad6e4"), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); + PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); @@ -339,7 +339,7 @@ public void testA2AClientCreateTaskPushNotificationConfig() throws Exception { .url("https://example.com/callback") .authentication(new AuthenticationInfo("jwt", null)) .build(), ""), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); + PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); 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 09e68b88a..0ec8f2eb1 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 @@ -274,8 +274,8 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPu = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); builder.setConfig(ProtoUtils.ToProto.taskPushNotificationConfig(request).getPushNotificationConfig()) .setTaskId(request.taskId()); - if (request.pushNotificationConfig().id() != null) { - builder.setConfigId(request.pushNotificationConfig().id()); + if (request.config().id() != null) { + builder.setConfigId(request.config().id()); } PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, agentCard, context); try { @@ -296,14 +296,14 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); StringBuilder url = new StringBuilder(Utils.buildBaseUrl(agentInterface, request.tenant())); - String configId = request.pushNotificationConfigId(); + String configId = request.id(); if (configId != null && !configId.isEmpty()) { - builder.setId(configId).setTaskId(request.id()); - url.append(String.format("/tasks/%1s/pushNotificationConfigs/%2s", request.id(), configId)); + builder.setId(configId).setTaskId(request.taskId()); + url.append(String.format("/tasks/%1s/pushNotificationConfigs/%2s", request.taskId(), configId)); } else { // Use trailing slash to distinguish GET from LIST - builder.setTaskId(request.id()); - url.append(String.format("/tasks/%1s/pushNotificationConfigs/", request.id())); + builder.setTaskId(request.taskId()); + url.append(String.format("/tasks/%1s/pushNotificationConfigs/", request.taskId())); } PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, agentCard, context); @@ -367,7 +367,7 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC 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()); + String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs/%2s", request.taskId(), request.id()); A2AHttpClient.DeleteBuilder deleteBuilder = httpClient.createDelete().url(url); if (payloadAndHeaders.getHeaders() != null) { for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index 3e96a7b09..9252c0525 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -310,7 +310,7 @@ public void testCreateTaskPushNotificationConfiguration() throws Exception { new AuthenticationInfo("jwt", null)) .build(), "tenant"); TaskPushNotificationConfig taskPushNotificationConfig = client.createTaskPushNotificationConfiguration(pushedConfig, null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); + PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); @@ -336,7 +336,7 @@ public void testGetTaskPushNotificationConfiguration() throws Exception { RestTransport client = new RestTransport(CARD); TaskPushNotificationConfig taskPushNotificationConfig = client.getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64", "10"), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); + PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); @@ -363,14 +363,14 @@ public void testListTaskPushNotificationConfigurations() throws Exception { ListTaskPushNotificationConfigResult result = client.listTaskPushNotificationConfigurations( new ListTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null); assertEquals(2, result.configs().size()); - PushNotificationConfig pushNotificationConfig = result.configs().get(0).pushNotificationConfig(); + PushNotificationConfig pushNotificationConfig = result.configs().get(0).config(); assertNotNull(pushNotificationConfig); assertEquals("https://example.com/callback", pushNotificationConfig.url()); assertEquals("10", pushNotificationConfig.id()); AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); assertEquals("jwt", authenticationInfo.scheme()); assertEquals("", authenticationInfo.credentials()); - pushNotificationConfig = result.configs().get(1).pushNotificationConfig(); + pushNotificationConfig = result.configs().get(1).config(); assertNotNull(pushNotificationConfig); assertEquals("https://test.com/callback", pushNotificationConfig.url()); assertEquals("5", pushNotificationConfig.id()); diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java index ed0db190d..640fb757d 100644 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java +++ b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java @@ -246,8 +246,8 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPu if (request.taskId() != null) { spanBuilder.setAttribute(GENAI_TASK_ID, request.taskId()); } - if (request.pushNotificationConfig() != null && request.pushNotificationConfig().id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, request.pushNotificationConfig().id()); + if (request.config() != null && request.config().id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, request.config().id()); } if (extractRequest()) { spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); @@ -276,11 +276,11 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu ClientCallContext clientContext = createContext(context); SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - if (request.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); + if (request.taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.taskId()); } - if (request.pushNotificationConfigId() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, request.pushNotificationConfigId()); + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, request.id()); } if (extractRequest()) { spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); @@ -345,11 +345,11 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC if (extractRequest()) { spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); } - if (request.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); + if (request.taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, request.taskId()); } - if (request.pushNotificationConfigId() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, request.pushNotificationConfigId()); + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, request.id()); } Span span = spanBuilder.startSpan(); try (Scope scope = span.makeCurrent()) { diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java index f8bbf0745..b1bf3d680 100644 --- a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java +++ b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java @@ -298,8 +298,8 @@ public TaskPushNotificationConfig onCreateTaskPushNotificationConfig(TaskPushNot if (params.taskId() != null) { spanBuilder.setAttribute(GENAI_TASK_ID, params.taskId()); } - if (params.pushNotificationConfig() != null && params.pushNotificationConfig().id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, params.pushNotificationConfig().id()); + if (params.config() != null && params.config().id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, params.config().id()); } if (extractRequest()) { spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); @@ -331,11 +331,11 @@ public TaskPushNotificationConfig onGetTaskPushNotificationConfig(GetTaskPushNot .setSpanKind(SpanKind.SERVER) .setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - if (params.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); + if (params.taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.taskId()); } - if (params.pushNotificationConfigId() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, params.pushNotificationConfigId()); + if (params.id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, params.id()); } if (extractRequest()) { spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); @@ -436,8 +436,8 @@ public void onDeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigP if (extractRequest()) { spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); } - if (params.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); + if (params.taskId() != null) { + spanBuilder.setAttribute(GENAI_TASK_ID, params.taskId()); } Span span = spanBuilder.startSpan(); 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 059806780..06d4531b0 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 @@ -133,9 +133,9 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep assertNotNull(storedConfig); assertEquals(taskId, storedConfig.taskId()); - assertEquals("test-config-1", storedConfig.pushNotificationConfig().id()); - assertEquals("http://localhost:9999/mock-endpoint", storedConfig.pushNotificationConfig().url()); - assertEquals("test-token-123", storedConfig.pushNotificationConfig().token()); + assertEquals("test-config-1", storedConfig.config().id()); + assertEquals("http://localhost:9999/mock-endpoint", storedConfig.config().url()); + assertEquals("test-token-123", storedConfig.config().token()); // Step 4: Update the task to trigger the notification Message updateMessage = Message.builder() @@ -239,10 +239,10 @@ public void testPaginationWithPageToken() { // Verify NO overlap between pages - collect all IDs from both pages List firstPageIds = firstPage.configs().stream() - .map(c -> c.pushNotificationConfig().id()) + .map(c -> c.config().id()) .toList(); List secondPageIds = secondPage.configs().stream() - .map(c -> c.pushNotificationConfig().id()) + .map(c -> c.config().id()) .toList(); // Check that no ID from first page appears in second page @@ -471,10 +471,10 @@ public void testMultipleTasksDoNotInterfere() { assertEquals(2, result2.configs().size(), "Task2 should have 2 configs"); List task1Ids = result1.configs().stream() - .map(c -> taskId1 + c.pushNotificationConfig().id()) + .map(c -> taskId1 + c.config().id()) .toList(); List task2Ids = result2.configs().stream() - .map(c -> taskId2 + c.pushNotificationConfig().id()) + .map(c -> taskId2 + c.config().id()) .toList(); for (String id : task1Ids) { @@ -535,7 +535,7 @@ public void testPaginationOrderingConsistency() { ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); result.configs().forEach(c -> - allConfigIds.add(c.pushNotificationConfig().id())); + allConfigIds.add(c.config().id())); pageToken = result.nextPageToken(); pageCount++; 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 79f422b27..6023a74b9 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 @@ -94,8 +94,8 @@ public void testSetInfoAddsNewConfig() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).pushNotificationConfig().url()); - assertEquals(config.id(), configResult.configs().get(0).pushNotificationConfig().id()); + assertEquals(config.url(), configResult.configs().get(0).config().url()); + assertEquals(config.id(), configResult.configs().get(0).config().id()); } @Test @@ -116,7 +116,7 @@ public void testSetInfoAppendsToExistingConfig() { // Find the configs by ID since order might vary List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::pushNotificationConfig) + .map(TaskPushNotificationConfig::config) .toList(); PushNotificationConfig foundInitial = configs.stream() .filter(c -> "cfg_initial".equals(c.id())) @@ -146,7 +146,7 @@ public void testSetInfoWithoutConfigId() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size()); - assertEquals(taskId, configResult.configs().get(0).pushNotificationConfig().id()); + assertEquals(taskId, configResult.configs().get(0).config().id()); PushNotificationConfig updatedConfig = PushNotificationConfig.builder() .url("http://initial.url/callback_new") @@ -157,7 +157,7 @@ public void testSetInfoWithoutConfigId() { configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size(), "Should replace existing config with same ID rather than adding new one"); - assertEquals(updatedConfig.url(), configResult.configs().get(0).pushNotificationConfig().url()); + assertEquals(updatedConfig.url(), configResult.configs().get(0).config().url()); } @Test @@ -170,8 +170,8 @@ public void testGetInfoExistingConfig() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).pushNotificationConfig().url()); - assertEquals(config.id(), configResult.configs().get(0).pushNotificationConfig().id()); + assertEquals(config.url(), configResult.configs().get(0).config().url()); + assertEquals(config.id(), configResult.configs().get(0).config().id()); } @Test @@ -326,7 +326,7 @@ public void testMultipleConfigsForSameTask() { // Verify both configs are present List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::pushNotificationConfig) + .map(TaskPushNotificationConfig::config) .toList(); assertTrue(configs.stream().anyMatch(c -> "cfg1".equals(c.id()))); assertTrue(configs.stream().anyMatch(c -> "cfg2".equals(c.id()))); @@ -348,7 +348,7 @@ public void testDeleteSpecificConfigFromMultiple() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals("cfg2", configResult.configs().get(0).pushNotificationConfig().id()); + assertEquals("cfg2", configResult.configs().get(0).config().id()); } @Test @@ -364,7 +364,7 @@ public void testConfigStoreIntegration() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).pushNotificationConfig().url()); + assertEquals(config.url(), configResult.configs().get(0).config().url()); // Test deletion configStore.deleteInfo(taskId, storedConfig.id()); 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 80d003d5d..2023fc7ac 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 @@ -764,7 +764,7 @@ public TaskPushNotificationConfig onCreateTaskPushNotificationConfig( throw new TaskNotFoundError(); } - PushNotificationConfig pushNotificationConfig = pushConfigStore.setInfo(params.taskId(), params.pushNotificationConfig()); + PushNotificationConfig pushNotificationConfig = pushConfigStore.setInfo(params.taskId(), params.config()); return new TaskPushNotificationConfig(params.taskId(), pushNotificationConfig, params.tenant()); } @@ -774,35 +774,32 @@ public TaskPushNotificationConfig onGetTaskPushNotificationConfig( if (pushConfigStore == null) { throw new UnsupportedOperationError(); } - Task task = taskStore.get(params.id()); + Task task = taskStore.get(params.taskId()); if (task == null) { throw new TaskNotFoundError(); } - ListTaskPushNotificationConfigResult listTaskPushNotificationConfigResult = pushConfigStore.getInfo(new ListTaskPushNotificationConfigParams(params.id())); + ListTaskPushNotificationConfigResult listTaskPushNotificationConfigResult = pushConfigStore.getInfo(new ListTaskPushNotificationConfigParams(params.taskId())); if (listTaskPushNotificationConfigResult == null || listTaskPushNotificationConfigResult.isEmpty()) { throw new InternalError("No push notification config found"); } - @Nullable String configId = params.pushNotificationConfigId(); - return new TaskPushNotificationConfig(params.id(), getPushNotificationConfig(listTaskPushNotificationConfigResult, configId), params.tenant()); + String configId = params.id(); + return new TaskPushNotificationConfig(params.taskId(), getPushNotificationConfig(listTaskPushNotificationConfigResult, configId), params.tenant()); } private PushNotificationConfig getPushNotificationConfig(ListTaskPushNotificationConfigResult notificationConfigList, - @Nullable String configId) { - if (configId != null) { - for (TaskPushNotificationConfig notificationConfig : notificationConfigList.configs()) { - if (configId.equals(notificationConfig.pushNotificationConfig().id())) { - return notificationConfig.pushNotificationConfig(); - } + String configId) { + for (TaskPushNotificationConfig notificationConfig : notificationConfigList.configs()) { + if (configId.equals(notificationConfig.config().id())) { + return notificationConfig.config(); } } - return notificationConfigList.configs().get(0).pushNotificationConfig(); + return notificationConfigList.configs().get(0).config(); } @Override - public Flow.Publisher onSubscribeToTask( - TaskIdParams params, ServerCallContext context) throws A2AError { + public Flow.Publisher onSubscribeToTask(TaskIdParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onSubscribeToTask - taskId: {}", params.id()); Task task = taskStore.get(params.id()); if (task == null) { @@ -858,12 +855,12 @@ public void onDeleteTaskPushNotificationConfig( throw new UnsupportedOperationError(); } - Task task = taskStore.get(params.id()); + Task task = taskStore.get(params.taskId()); if (task == null) { throw new TaskNotFoundError(); } - pushConfigStore.deleteInfo(params.id(), params.pushNotificationConfigId()); + pushConfigStore.deleteInfo(params.taskId(), params.id()); } private boolean shouldAddPushInfo(MessageSendParams params) { 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 a9b8093bf..0d6bdcf3b 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 @@ -87,7 +87,7 @@ public void sendNotification(StreamingEventKind event) { List> dispatchResults = configs .stream() - .map(pushConfig -> dispatch(event, pushConfig.pushNotificationConfig())) + .map(pushConfig -> dispatch(event, pushConfig.config())) .toList(); CompletableFuture allFutures = CompletableFuture.allOf(dispatchResults.toArray(new CompletableFuture[0])); CompletableFuture dispatchResult = allFutures.thenApply(v -> dispatchResults.stream() diff --git a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java b/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java index 6b1faf711..bc96b36ac 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java @@ -104,8 +104,8 @@ public void testSetInfoAddsNewConfig() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).pushNotificationConfig().url()); - assertEquals(config.id(), configResult.configs().get(0).pushNotificationConfig().id()); + assertEquals(config.url(), configResult.configs().get(0).config().url()); + assertEquals(config.id(), configResult.configs().get(0).config().id()); } @Test @@ -125,7 +125,7 @@ public void testSetInfoAppendsToExistingConfig() { // Find the configs by ID since order might vary List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::pushNotificationConfig) + .map(TaskPushNotificationConfig::config) .toList(); PushNotificationConfig foundInitial = configs.stream() .filter(c -> "cfg_initial".equals(c.id())) @@ -154,7 +154,7 @@ public void testSetInfoWithoutConfigId() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size()); - assertEquals(taskId, configResult.configs().get(0).pushNotificationConfig().id()); + assertEquals(taskId, configResult.configs().get(0).config().id()); PushNotificationConfig updatedConfig = PushNotificationConfig.builder() .url("http://initial.url/callback_new") @@ -165,7 +165,7 @@ public void testSetInfoWithoutConfigId() { configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size(), "Should replace existing config with same ID rather than adding new one"); - assertEquals(updatedConfig.url(), configResult.configs().get(0).pushNotificationConfig().url()); + assertEquals(updatedConfig.url(), configResult.configs().get(0).config().url()); } @Test @@ -177,8 +177,8 @@ public void testGetInfoExistingConfig() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).pushNotificationConfig().url()); - assertEquals(config.id(), configResult.configs().get(0).pushNotificationConfig().id()); + assertEquals(config.url(), configResult.configs().get(0).config().url()); + assertEquals(config.id(), configResult.configs().get(0).config().id()); } @Test @@ -340,7 +340,7 @@ public void testMultipleConfigsForSameTask() { // Verify both configs are present List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::pushNotificationConfig) + .map(TaskPushNotificationConfig::config) .toList(); assertTrue(configs.stream().anyMatch(c -> "cfg1".equals(c.id()))); assertTrue(configs.stream().anyMatch(c -> "cfg2".equals(c.id()))); @@ -361,7 +361,7 @@ public void testDeleteSpecificConfigFromMultiple() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals("cfg2", configResult.configs().get(0).pushNotificationConfig().id()); + assertEquals("cfg2", configResult.configs().get(0).config().id()); } @Test @@ -376,7 +376,7 @@ public void testConfigStoreIntegration() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).pushNotificationConfig().url()); + assertEquals(config.url(), configResult.configs().get(0).config().url()); // Test deletion configStore.deleteInfo(taskId, storedConfig.id()); @@ -430,10 +430,10 @@ public void testPaginationWithPageToken() { // Verify NO overlap between pages - collect all IDs from both pages List firstPageIds = firstPage.configs().stream() - .map(c -> c.pushNotificationConfig().id()) + .map(c -> c.config().id()) .toList(); List secondPageIds = secondPage.configs().stream() - .map(c -> c.pushNotificationConfig().id()) + .map(c -> c.config().id()) .toList(); // Check that no ID from first page appears in second page diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java index ed15e7500..d33c04711 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java @@ -20,9 +20,7 @@ public interface CreateTaskPushNotificationConfigMapper { * @param request the protobuf CreateTaskPushNotificationConfigRequest * @return domain TaskPushNotificationConfig */ - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "pushNotificationConfig", expression = "java(mapPushNotificationConfigWithId(request))") - @Mapping(target = "tenant", source = "tenant") + @Mapping(target = "config", expression = "java(mapPushNotificationConfigWithId(request))") TaskPushNotificationConfig fromProto(CreateTaskPushNotificationConfigRequest request); /** @@ -31,10 +29,7 @@ public interface CreateTaskPushNotificationConfigMapper { * @param config the domain TaskPushNotificationConfig * @return proto CreateTaskPushNotificationConfigRequest */ - @Mapping(target = "taskId", source = "taskId") @Mapping(target = "configId", expression = "java(extractConfigId(config))") - @Mapping(target = "config", source = "pushNotificationConfig") - @Mapping(target = "tenant", source = "tenant") CreateTaskPushNotificationConfigRequest toProto(TaskPushNotificationConfig config); /** @@ -44,7 +39,7 @@ public interface CreateTaskPushNotificationConfigMapper { * @return the extracted config ID */ default String extractConfigId(TaskPushNotificationConfig config) { - return config.pushNotificationConfig() != null ? config.pushNotificationConfig().id() : null; + return config.config() != null ? config.config().id() : null; } /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java index f7ddd3ce4..6e30f6eb9 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java @@ -18,16 +18,16 @@ public interface DeleteTaskPushNotificationConfigParamsMapper { * Converts proto DeleteTaskPushNotificationConfigRequest to domain DeleteTaskPushNotificationConfigParams. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "taskId") - @Mapping(target = "pushNotificationConfigId", source = "id") + @Mapping(target = "taskId", source = "taskId") + @Mapping(target = "id", source = "id") @Mapping(target = "tenant", source = "tenant") DeleteTaskPushNotificationConfigParams fromProto(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest proto); /** * Converts domain DeleteTaskPushNotificationConfigParams to proto DeleteTaskPushNotificationConfigRequest. */ - @Mapping(target = "taskId", source = "id") - @Mapping(target = "id", source = "pushNotificationConfigId") + @Mapping(target = "taskId", source = "taskId") + @Mapping(target = "id", source = "id") @Mapping(target = "tenant", source = "tenant") io.a2a.grpc.DeleteTaskPushNotificationConfigRequest toProto(DeleteTaskPushNotificationConfigParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java index 5a74ac2cc..b9a8cad1b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java @@ -18,16 +18,16 @@ public interface GetTaskPushNotificationConfigParamsMapper { * Converts proto GetTaskPushNotificationConfigRequest to domain GetTaskPushNotificationConfigParams. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "taskId") - @Mapping(target = "pushNotificationConfigId", source = "id") + @Mapping(target = "taskId", source = "taskId") + @Mapping(target = "id", source = "id") @Mapping(target = "tenant", source = "tenant") GetTaskPushNotificationConfigParams fromProto(io.a2a.grpc.GetTaskPushNotificationConfigRequest proto); /** * Converts domain GetTaskPushNotificationConfigParams to proto GetTaskPushNotificationConfigRequest. */ - @Mapping(target = "taskId", source = "id") - @Mapping(target = "id", source = "pushNotificationConfigId", conditionExpression = "java(domain.pushNotificationConfigId() != null)") + @Mapping(target = "taskId", source = "taskId") + @Mapping(target = "id", source = "id", conditionExpression = "java(domain.id() != null)") @Mapping(target = "tenant", source = "tenant") io.a2a.grpc.GetTaskPushNotificationConfigRequest toProto(GetTaskPushNotificationConfigParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java index 996bda0ac..5e3a6e669 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java @@ -19,14 +19,14 @@ public interface TaskPushNotificationConfigMapper { /** * Converts domain TaskPushNotificationConfig to protobuf TaskPushNotificationConfig. * - * @param config the domain TaskPushNotificationConfig + * @param domain the domain TaskPushNotificationConfig * @return protobuf TaskPushNotificationConfig */ - @Mapping(target = "id", expression = "java(extractId(config))") + @Mapping(target = "id", expression = "java(extractId(domain))") @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "pushNotificationConfig", source = "pushNotificationConfig") - @Mapping(target = "tenant", source = "tenant", conditionExpression = "java(config.tenant() != null)") - io.a2a.grpc.TaskPushNotificationConfig toProto(TaskPushNotificationConfig config); + @Mapping(target = "pushNotificationConfig", source = "config") + @Mapping(target = "tenant", source = "tenant", conditionExpression = "java(domain.tenant() != null)") + io.a2a.grpc.TaskPushNotificationConfig toProto(TaskPushNotificationConfig domain); /** * Converts protobuf TaskPushNotificationConfig to domain TaskPushNotificationConfig. @@ -35,7 +35,7 @@ public interface TaskPushNotificationConfigMapper { * @return domain TaskPushNotificationConfig */ @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "pushNotificationConfig", expression = "java(mapPushNotificationConfigWithId(proto))") + @Mapping(target = "config", expression = "java(mapPushNotificationConfigWithId(proto))") @Mapping(target = "tenant", expression = "java(proto.getTenant().isEmpty() ? null : proto.getTenant())") TaskPushNotificationConfig fromProto(io.a2a.grpc.TaskPushNotificationConfig proto); @@ -46,7 +46,7 @@ public interface TaskPushNotificationConfigMapper { * @return the config ID */ default String extractId(TaskPushNotificationConfig config) { - return config.pushNotificationConfig() != null ? config.pushNotificationConfig().id() : null; + return config.config()!= null ? config.config().id() : null; } /** 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 e5f75c78a..ecfab4beb 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 @@ -59,8 +59,8 @@ public void testParseCreateTaskPushNotificationConfigRequest_ValidProtoFormat() TaskPushNotificationConfig config = setRequest.getParams(); assertNotNull(config); assertEquals("task-123", config.taskId()); - assertNotNull(config.pushNotificationConfig()); - assertEquals("https://example.com/callback", config.pushNotificationConfig().url()); + assertNotNull(config.config()); + assertEquals("https://example.com/callback", config.config().url()); } @Test @@ -86,7 +86,7 @@ public void testParseGetTaskPushNotificationConfigRequest_ValidProtoFormat() thr assertEquals(2, getRequest.getId()); assertEquals("GetTaskPushNotificationConfig", getRequest.getMethod()); assertNotNull(getRequest.getParams()); - assertEquals("task-123", getRequest.getParams().id()); + assertEquals("task-123", getRequest.getParams().taskId()); } @Test @@ -329,7 +329,7 @@ public void testGenerateCreateTaskPushNotificationConfigResponse_Success() throw assertEquals(1, response.getId()); assertNotNull(response.getResult()); assertEquals("task-123", response.getResult().taskId()); - assertEquals("https://example.com/callback", response.getResult().pushNotificationConfig().url()); + assertEquals("https://example.com/callback", response.getResult().config().url()); } @Test @@ -356,7 +356,7 @@ public void testGenerateGetTaskPushNotificationConfigResponse_Success() throws E assertEquals(2, response.getId()); assertNotNull(response.getResult()); assertEquals("task-123", response.getResult().taskId()); - assertEquals("https://example.com/callback", response.getResult().pushNotificationConfig().url()); + assertEquals("https://example.com/callback", response.getResult().config().url()); } @Test diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index d948f2f3a..d17ce58bc 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -319,8 +319,8 @@ public void convertDeleteTaskPushNotificationConfigRequest() { // Test round-trip conversion DeleteTaskPushNotificationConfigParams convertedBack = ProtoUtils.FromProto.deleteTaskPushNotificationConfigParams(result); - assertEquals("task-123", convertedBack.id()); - assertEquals("config-456", convertedBack.pushNotificationConfigId()); + assertEquals("task-123", convertedBack.taskId()); + assertEquals("config-456", convertedBack.id()); } @Test diff --git a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java index 024663766..12d6c0624 100644 --- a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java @@ -12,36 +12,36 @@ * This record specifies which task and which specific push notification configuration * to remove, allowing cleanup of notification endpoints that are no longer needed. * - * @param id the task identifier (required) - * @param pushNotificationConfigId the specific configuration ID to delete (required) + * @param taskId the task identifier (required) + * @param id the specific configuration ID to delete (required) * @param tenant optional tenant, provided as a path parameter. * @see A2A Protocol Specification */ -public record DeleteTaskPushNotificationConfigParams(String id, String pushNotificationConfigId, String tenant) { +public record DeleteTaskPushNotificationConfigParams(String taskId, String id, String tenant) { /** * Compact constructor that validates required fields. * + * @param taskId the taskId parameter (see class-level JavaDoc) * @param id the id parameter (see class-level JavaDoc) - * @param pushNotificationConfigId the pushNotificationConfigId parameter (see class-level JavaDoc) * @param tenant the tenant parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if id or pushNotificationConfigId is null + * @throws IllegalArgumentException if taskId or id is null */ public DeleteTaskPushNotificationConfigParams { + Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId); Assert.checkNotNullParam("tenant", tenant); } /** * Creates parameters without optional metadata. * - * @param id the task identifier (required) - * @param pushNotificationConfigId the configuration ID to delete (required) - * @throws IllegalArgumentException if id or pushNotificationConfigId is null + * @param taskId the task identifier (required) + * @param id the configuration ID to delete (required) + * @throws IllegalArgumentException if taskId or id is null */ - public DeleteTaskPushNotificationConfigParams(String id, String pushNotificationConfigId) { - this(id, pushNotificationConfigId, ""); + public DeleteTaskPushNotificationConfigParams(String taskId, String id) { + this(taskId, id, ""); } /** @@ -59,8 +59,8 @@ public static Builder builder() { * Provides a fluent API for setting parameters with optional metadata. */ public static class Builder { + @Nullable String taskId; @Nullable String id; - @Nullable String pushNotificationConfigId; @Nullable String tenant; /** @@ -72,22 +72,22 @@ private Builder() { /** * Sets the task identifier. * - * @param id the task ID (required) + * @param taskId the task ID (required) * @return this builder for method chaining */ - public Builder id(String id) { - this.id = id; + public Builder taskId(String taskId) { + this.taskId = taskId; return this; } /** * Sets the push notification configuration ID to delete. * - * @param pushNotificationConfigId the configuration ID (required) + * @param id the configuration ID (required) * @return this builder for method chaining */ - public Builder pushNotificationConfigId(String pushNotificationConfigId) { - this.pushNotificationConfigId = pushNotificationConfigId; + public Builder id(String id) { + this.id = id; return this; } @@ -106,12 +106,12 @@ public Builder tenant(String tenant) { * Builds a new {@link DeleteTaskPushNotificationConfigParams} from the current builder state. * * @return a new DeleteTaskPushNotificationConfigParams instance - * @throws IllegalArgumentException if id or pushNotificationConfigId is null + * @throws IllegalArgumentException if taskId or id is null */ public DeleteTaskPushNotificationConfigParams build() { return new DeleteTaskPushNotificationConfigParams( + Assert.checkNotNullParam("taskId", taskId), Assert.checkNotNullParam("id", id), - Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId), Utils.defaultIfNull(tenant,"")); } } diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java index 241c599e7..f51063bcf 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java @@ -12,36 +12,36 @@ * This record specifies which task's push notification configuration to retrieve, with * an optional filter by configuration ID if multiple configurations exist for the task. * - * @param id the task identifier (required) - * @param pushNotificationConfigId optional specific configuration ID to retrieve + * @param taskId the task identifier (required) + * @param id optional specific configuration ID to retrieve * @param tenant optional tenant, provided as a path parameter. * @see TaskPushNotificationConfig for the returned configuration structure * @see A2A Protocol Specification */ -public record GetTaskPushNotificationConfigParams(String id, String pushNotificationConfigId, String tenant) { +public record GetTaskPushNotificationConfigParams(String taskId, String id, String tenant) { /** * Compact constructor that validates required fields. * + * @param taskId the taskId parameter (see class-level JavaDoc) * @param id the id parameter (see class-level JavaDoc) - * @param pushNotificationConfigId the pushNotificationConfigId parameter (see class-level JavaDoc) * @param tenant the tenant parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if id or tenant is null + * @throws IllegalArgumentException if taskId or tenant is null */ public GetTaskPushNotificationConfigParams { + Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId); Assert.checkNotNullParam("tenant", tenant); } /** * Convenience constructor for creating parameters without tenant. * - * @param id the task identifier (required) - * @param pushNotificationConfigId optional configuration ID to retrieve + * @param taskId the task identifier (required) + * @param id optional configuration ID to retrieve */ - public GetTaskPushNotificationConfigParams(String id, String pushNotificationConfigId) { - this(id, pushNotificationConfigId, ""); + public GetTaskPushNotificationConfigParams(String taskId, String id) { + this(taskId, id, ""); } /** @@ -57,8 +57,8 @@ public static Builder builder() { * Builder for constructing GetTaskPushNotificationConfigParams instances. */ public static class Builder { + @Nullable String taskId; @Nullable String id; - @Nullable String pushNotificationConfigId; @Nullable String tenant; /** @@ -70,22 +70,22 @@ private Builder() { /** * Sets the task ID. * - * @param id the task ID + * @param taskId the task ID * @return this builder for method chaining */ - public Builder id(String id) { - this.id = id; + public Builder taskId(String taskId) { + this.taskId = taskId; return this; } /** * Sets the push notification configuration ID. * - * @param pushNotificationConfigId the configuration ID + * @param id the configuration ID * @return this builder for method chaining */ - public Builder pushNotificationConfigId(String pushNotificationConfigId) { - this.pushNotificationConfigId = pushNotificationConfigId; + public Builder id(String id) { + this.id = id; return this; } @@ -107,8 +107,8 @@ public Builder tenant(String tenant) { */ public GetTaskPushNotificationConfigParams build() { return new GetTaskPushNotificationConfigParams( + Assert.checkNotNullParam("taskId", taskId), Assert.checkNotNullParam("id", id), - Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId), Utils.defaultIfNull(tenant,"")); } } diff --git a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java index cf57a6f3c..9f973e897 100644 --- a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java +++ b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java @@ -15,23 +15,24 @@ * management methods ({@code tasks/pushNotificationConfig/set}, {@code tasks/pushNotificationConfig/get}, etc.). * * @param taskId the unique identifier of the task to receive push notifications for (required) - * @param pushNotificationConfig the push notification endpoint and authentication configuration (required) + * @param config the push notification endpoint and authentication configuration (required) + * @param tenant optional tenant identifier, provided as a path parameter * @see PushNotificationConfig for notification endpoint details * @see A2A Protocol Specification */ -public record TaskPushNotificationConfig(String taskId, PushNotificationConfig pushNotificationConfig, @Nullable String tenant) { +public record TaskPushNotificationConfig(String taskId, PushNotificationConfig config, @Nullable String tenant) { /** * Compact constructor for validation. * Validates that required parameters are not null. * * @param taskId the task identifier - * @param pushNotificationConfig the push notification configuration + * @param config the push notification configuration * @param tenant the tenant identifier */ public TaskPushNotificationConfig { Assert.checkNotNullParam("taskId", taskId); - Assert.checkNotNullParam("pushNotificationConfig", pushNotificationConfig); - Assert.checkNotNullParam("configId", pushNotificationConfig.id()); + Assert.checkNotNullParam("config", config); + Assert.checkNotNullParam("configId", config.id()); } } diff --git a/spec/src/main/java/io/a2a/spec/TaskStatus.java b/spec/src/main/java/io/a2a/spec/TaskStatus.java index 87055f236..95e70da0d 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatus.java +++ b/spec/src/main/java/io/a2a/spec/TaskStatus.java @@ -54,6 +54,11 @@ public TaskStatus(TaskState state, @Nullable Message message, @Nullable OffsetDa this.message = message; } + /** + * Returns the timestamp when this status was created. + * + * @return the UTC timestamp of the status + */ public OffsetDateTime timestamp() { return timestamp; } diff --git a/spec/src/main/java/io/a2a/util/Utils.java b/spec/src/main/java/io/a2a/util/Utils.java index 44d713f75..68fe2bef7 100644 --- a/spec/src/main/java/io/a2a/util/Utils.java +++ b/spec/src/main/java/io/a2a/util/Utils.java @@ -40,6 +40,13 @@ public class Utils { private static final Logger log = Logger.getLogger(Utils.class.getName()); + /** + * Private constructor to prevent instantiation of this utility class. + */ + private Utils() { + // Utility class - no instances + } + /** * Returns the provided value if non-null, otherwise returns the default value. *

        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 f2da8de15..911945fa0 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 @@ -554,8 +554,8 @@ public void testSetPushNotificationSuccess() throws Exception { MINIMAL_TASK.id(), PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); TaskPushNotificationConfig config = getClient().createTaskPushNotificationConfiguration(taskPushConfig); assertEquals(MINIMAL_TASK.id(), config.taskId()); - assertEquals("http://example.com", config.pushNotificationConfig().url()); - assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", config.pushNotificationConfig().id()); + assertEquals("http://example.com", config.config().url()); + assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", config.config().id()); } catch (A2AClientException e) { fail("Unexpected exception during set push notification test: " + e.getMessage(), e); } finally { @@ -578,7 +578,7 @@ public void testGetPushNotificationSuccess() throws Exception { TaskPushNotificationConfig config = getClient().getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams(MINIMAL_TASK.id(), "c295ea44-7543-4f78-b524-7a38915ad6e4")); assertEquals(MINIMAL_TASK.id(), config.taskId()); - assertEquals("http://example.com", config.pushNotificationConfig().url()); + assertEquals("http://example.com", config.config().url()); } catch (A2AClientException e) { fail("Unexpected exception during get push notification test: " + e.getMessage(), e); } finally { From 841675b71863133744b4e4ea6999fc23e43698c1 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Tue, 17 Feb 2026 18:10:33 +0100 Subject: [PATCH 041/192] feat!: Update Message.Role enum (#662) Align the enum values with the protobuf definition to simplify the serialiazition. Remove the string representation to rely directly on the enum textual serialization. Remove the nullabitily of the Message role fied. If not present, it will be mapped to the ROLE_UNSPECIFIED. Remove the RoleTypeAdapter as the GSON serialization is handled automatically from the enum. This fixes #661 Signed-off-by: Jeff Mesnil --- client/base/src/main/java/io/a2a/A2A.java | 14 +++--- client/base/src/test/java/io/a2a/A2ATest.java | 16 +++---- .../AuthenticationAuthorizationTest.java | 2 +- .../io/a2a/client/ClientTaskManagerTest.java | 8 ++-- .../JSONRPCTransportStreamingTest.java | 6 +-- .../jsonrpc/JSONRPCTransportTest.java | 20 ++++---- .../jsonrpc/sse/SSEEventListenerTest.java | 2 +- .../transport/rest/RestTransportTest.java | 14 +++--- .../rest/sse/SSEEventListenerTest.java | 2 +- .../spi/sse/SSEEventListenerTest.java | 6 +-- .../examples/cloud/A2ACloudExampleClient.java | 4 +- .../client/OpenTelemetryClientTransport.java | 4 +- .../OpenTelemetryClientTransportTest.java | 2 +- .../OpenTelemetryRequestHandlerDecorator.java | 4 +- ...nTelemetryRequestHandlerDecoratorTest.java | 8 ++-- ...otificationConfigStoreIntegrationTest.java | 4 +- .../core/EventSerializationTest.java | 2 +- .../KafkaReplicationIntegrationTest.java | 8 ++-- .../JpaDatabaseTaskStoreIntegrationTest.java | 4 +- .../jpa/JpaDatabaseTaskStoreTest.java | 4 +- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 48 ------------------- .../StreamingEventKindSerializationTest.java | 8 ++-- .../common/json/TaskSerializationTest.java | 24 +++++----- .../io/a2a/server/tasks/AgentEmitter.java | 4 +- .../agentexecution/RequestContextTest.java | 36 +++++++------- .../a2a/server/events/EventConsumerTest.java | 2 +- .../io/a2a/server/events/EventQueueTest.java | 2 +- .../AbstractA2ARequestHandlerTest.java | 2 +- .../io/a2a/server/tasks/AgentEmitterTest.java | 8 ++-- .../tasks/PushNotificationSenderTest.java | 2 +- .../server/tasks/ResultAggregatorTest.java | 6 +-- .../io/a2a/server/tasks/TaskManagerTest.java | 16 +++---- .../java/io/a2a/grpc/mapper/RoleMapper.java | 20 ++++---- .../grpc/mapper/StreamResponseMapperTest.java | 6 +-- .../io/a2a/grpc/utils/JSONRPCUtilsTest.java | 9 +++- .../java/io/a2a/grpc/utils/ToProtoTest.java | 4 +- spec/src/main/java/io/a2a/spec/Message.java | 19 ++------ .../apps/common/AbstractA2AServerTest.java | 2 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 2 +- 39 files changed, 150 insertions(+), 204 deletions(-) diff --git a/client/base/src/main/java/io/a2a/A2A.java b/client/base/src/main/java/io/a2a/A2A.java index b04b85df4..14101b678 100644 --- a/client/base/src/main/java/io/a2a/A2A.java +++ b/client/base/src/main/java/io/a2a/A2A.java @@ -74,7 +74,7 @@ public class A2A { * @see #createUserTextMessage(String, String, String) */ public static Message toUserMessage(String text) { - return toMessage(text, Message.Role.USER, null); + return toMessage(text, Message.Role.ROLE_USER, null); } /** @@ -96,7 +96,7 @@ public static Message toUserMessage(String text) { * @see #toUserMessage(String) */ public static Message toUserMessage(String text, String messageId) { - return toMessage(text, Message.Role.USER, messageId); + return toMessage(text, Message.Role.ROLE_USER, messageId); } /** @@ -117,7 +117,7 @@ public static Message toUserMessage(String text, String messageId) { * @see #toAgentMessage(String, String) */ public static Message toAgentMessage(String text) { - return toMessage(text, Message.Role.AGENT, null); + return toMessage(text, Message.Role.ROLE_AGENT, null); } /** @@ -133,7 +133,7 @@ public static Message toAgentMessage(String text) { * @return an agent message with the specified text and ID */ public static Message toAgentMessage(String text, String messageId) { - return toMessage(text, Message.Role.AGENT, messageId); + return toMessage(text, Message.Role.ROLE_AGENT, messageId); } /** @@ -180,7 +180,7 @@ public static Message toAgentMessage(String text, String messageId) { * @see Message#taskId() */ public static Message createUserTextMessage(String text, String contextId, String taskId) { - return toMessage(text, Message.Role.USER, null, contextId, taskId); + return toMessage(text, Message.Role.ROLE_USER, null, contextId, taskId); } /** @@ -195,7 +195,7 @@ public static Message createUserTextMessage(String text, String contextId, Strin * @see #createUserTextMessage(String, String, String) */ public static Message createAgentTextMessage(String text, String contextId, String taskId) { - return toMessage(text, Message.Role.AGENT, null, contextId, taskId); + return toMessage(text, Message.Role.ROLE_AGENT, null, contextId, taskId); } /** @@ -225,7 +225,7 @@ public static Message createAgentPartsMessage(List> parts, String contex if (parts == null || parts.isEmpty()) { throw new IllegalArgumentException("Parts cannot be null or empty"); } - return toMessage(parts, Message.Role.AGENT, null, contextId, taskId); + return toMessage(parts, Message.Role.ROLE_AGENT, null, contextId, taskId); } private static Message toMessage(String text, Message.Role role, String messageId) { diff --git a/client/base/src/test/java/io/a2a/A2ATest.java b/client/base/src/test/java/io/a2a/A2ATest.java index 0f4d3eaa5..1052ad76d 100644 --- a/client/base/src/test/java/io/a2a/A2ATest.java +++ b/client/base/src/test/java/io/a2a/A2ATest.java @@ -20,7 +20,7 @@ public void testToUserMessage() { String text = "Hello, world!"; Message message = A2A.toUserMessage(text); - assertEquals(Message.Role.USER, message.role()); + assertEquals(Message.Role.ROLE_USER, message.role()); assertEquals(1, message.parts().size()); assertEquals(text, ((TextPart) message.parts().get(0)).text()); assertNotNull(message.messageId()); @@ -34,7 +34,7 @@ public void testToUserMessageWithId() { String messageId = "test-message-id"; Message message = A2A.toUserMessage(text, messageId); - assertEquals(Message.Role.USER, message.role()); + assertEquals(Message.Role.ROLE_USER, message.role()); assertEquals(messageId, message.messageId()); } @@ -43,7 +43,7 @@ public void testToAgentMessage() { String text = "Hello, I'm an agent!"; Message message = A2A.toAgentMessage(text); - assertEquals(Message.Role.AGENT, message.role()); + assertEquals(Message.Role.ROLE_AGENT, message.role()); assertEquals(1, message.parts().size()); assertEquals(text, ((TextPart) message.parts().get(0)).text()); assertNotNull(message.messageId()); @@ -55,7 +55,7 @@ public void testToAgentMessageWithId() { String messageId = "agent-message-id"; Message message = A2A.toAgentMessage(text, messageId); - assertEquals(Message.Role.AGENT, message.role()); + assertEquals(Message.Role.ROLE_AGENT, message.role()); assertEquals(messageId, message.messageId()); } @@ -67,7 +67,7 @@ public void testCreateUserTextMessage() { Message message = A2A.createUserTextMessage(text, contextId, taskId); - assertEquals(Message.Role.USER, message.role()); + assertEquals(Message.Role.ROLE_USER, message.role()); assertEquals(contextId, message.contextId()); assertEquals(taskId, message.taskId()); assertEquals(1, message.parts().size()); @@ -83,7 +83,7 @@ public void testCreateUserTextMessageWithNullParams() { Message message = A2A.createUserTextMessage(text, null, null); - assertEquals(Message.Role.USER, message.role()); + assertEquals(Message.Role.ROLE_USER, message.role()); assertNull(message.contextId()); assertNull(message.taskId()); assertEquals(1, message.parts().size()); @@ -98,7 +98,7 @@ public void testCreateAgentTextMessage() { Message message = A2A.createAgentTextMessage(text, contextId, taskId); - assertEquals(Message.Role.AGENT, message.role()); + assertEquals(Message.Role.ROLE_AGENT, message.role()); assertEquals(contextId, message.contextId()); assertEquals(taskId, message.taskId()); assertEquals(1, message.parts().size()); @@ -117,7 +117,7 @@ public void testCreateAgentPartsMessage() { Message message = A2A.createAgentPartsMessage(parts, contextId, taskId); - assertEquals(Message.Role.AGENT, message.role()); + assertEquals(Message.Role.ROLE_AGENT, message.role()); assertEquals(contextId, message.contextId()); assertEquals(taskId, message.taskId()); assertEquals(2, message.parts().size()); diff --git a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java b/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java index 5b8d9c94a..5d0e9b8e9 100644 --- a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java +++ b/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java @@ -66,7 +66,7 @@ public class AuthenticationAuthorizationTest { public void setUp() { server = new ClientAndServer(4001); MESSAGE = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("test message"))) .contextId("context-1234") .messageId("message-1234") diff --git a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java b/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java index 44ecc7bb6..74699b97e 100644 --- a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java +++ b/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java @@ -42,7 +42,7 @@ public void setUp() { sampleMessage = Message.builder() .messageId("msg1") - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("Hello"))) .build(); } @@ -196,7 +196,7 @@ public void testUpdateWithMessage() { public void testUpdateWithMessageMovesStatusMessage() { Message statusMessage = Message.builder() .messageId("status_msg") - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(Collections.singletonList(new TextPart("Status"))) .build(); @@ -219,7 +219,7 @@ public void testUpdateWithMessageMovesStatusMessage() { public void testUpdateWithMessagePreservesExistingHistory() { Message existingMessage = Message.builder() .messageId("existing_msg") - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("Existing"))) .build(); @@ -256,7 +256,7 @@ public void testSaveTaskEventMultipleStatusUpdates() throws Exception { // Second status update Message secondMessage = Message.builder() .messageId("msg2") - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(Collections.singletonList(new TextPart("Second message"))) .build(); 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 60805c2de..1f28d9201 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 @@ -54,7 +54,7 @@ public void testSendStreamingMessageParams() { // The goal here is just to verify the correct parameters are being used // This is a unit test of the parameter construction, not the streaming itself Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("test message"))) .contextId("context-test") .messageId("message-test") @@ -73,7 +73,7 @@ public void testSendStreamingMessageParams() { assertNotNull(params); assertEquals(message, params.message()); assertEquals(configuration, params.configuration()); - assertEquals(Message.Role.USER, params.message().role()); + assertEquals(Message.Role.ROLE_USER, params.message().role()); assertEquals("test message", ((TextPart) params.message().parts().get(0)).text()); } @@ -95,7 +95,7 @@ public void testA2AClientSendStreamingMessage() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("tell me some jokes"))) .contextId("context-1234") .messageId("message-1234") diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 849ac8fde..012b373ff 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -103,7 +103,7 @@ public void testA2AClientSendMessage() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("tell me a joke"))) .contextId("context-1234") .messageId("message-1234") @@ -151,7 +151,7 @@ public void testA2AClientSendMessageWithMessageResponse() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("tell me a joke"))) .contextId("context-1234") .messageId("message-1234") @@ -168,7 +168,7 @@ public void testA2AClientSendMessageWithMessageResponse() throws Exception { EventKind result = client.sendMessage(params, null); assertInstanceOf(Message.class, result); Message agentMessage = (Message) result; - assertEquals(Message.Role.AGENT, agentMessage.role()); + assertEquals(Message.Role.ROLE_AGENT, agentMessage.role()); Part part = agentMessage.parts().get(0); assertTrue(part instanceof TextPart); assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) part).text()); @@ -193,7 +193,7 @@ public void testA2AClientSendMessageWithError() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("tell me a joke"))) .contextId("context-1234") .messageId("message-1234") @@ -248,7 +248,7 @@ public void testA2AClientGetTask() throws Exception { assertNotNull(history); assertEquals(1, history.size()); Message message = history.get(0); - assertEquals(Message.Role.USER, message.role()); + assertEquals(Message.Role.ROLE_USER, message.role()); List> parts = message.parts(); assertNotNull(parts); assertEquals(3, parts.size()); @@ -435,7 +435,7 @@ public void testA2AClientSendMessageWithFilePart() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of( new TextPart("analyze this image"), new FilePart(new FileWithUri("image/jpeg", null, "file:///path/to/image.jpg")) @@ -495,7 +495,7 @@ public void testA2AClientSendMessageWithDataPart() throws Exception { data.put("timestamp", "2024-01-15T10:30:00Z"); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of( new TextPart("process this data"), new DataPart(data) @@ -552,7 +552,7 @@ public void testA2AClientSendMessageWithMixedParts() throws Exception { data.put("labels", List.of("Q1", "Q2", "Q3", "Q4")); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of( new TextPart("analyze this data and image"), new FilePart(new FileWithBytes("image/png", "chart.png", "aGVsbG8=")), @@ -617,7 +617,7 @@ public void testExtensionSupportRequiredErrorUnmarshalling() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("test message"))) .contextId("context-test") .messageId("message-test") @@ -673,7 +673,7 @@ public void testVersionNotSupportedErrorUnmarshalling() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("test message"))) .contextId("context-test") .messageId("message-test") 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 8bcf3ddad..e9e74d12f 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 @@ -73,7 +73,7 @@ public void testOnEventWithMessageResult() throws Exception { assertNotNull(receivedEvent.get()); assertTrue(receivedEvent.get() instanceof Message); Message message = (Message) receivedEvent.get(); - assertEquals(Message.Role.AGENT, message.role()); + assertEquals(Message.Role.ROLE_AGENT, message.role()); assertEquals("msg-123", message.messageId()); assertEquals("context-456", message.contextId()); assertEquals(1, message.parts().size()); diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index 9252c0525..2f3ae18db 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -110,7 +110,7 @@ public RestTransportTest() { @Test public void testSendMessage() throws Exception { Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("tell me a joke"))) .contextId("context-1234") .messageId("message-1234") @@ -143,7 +143,7 @@ public void testSendMessage() throws Exception { assertEquals(1, task.history().size()); Message history = task.history().get(0); assertEquals("message", history.kind()); - assertEquals(Message.Role.USER, history.role()); + assertEquals(Message.Role.ROLE_USER, history.role()); assertEquals("context-1234", history.contextId()); assertEquals("message-1234", history.messageId()); assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", history.taskId()); @@ -215,7 +215,7 @@ public void testGetTask() throws Exception { assertEquals(1, task.history().size()); Message history = task.history().get(0); assertEquals("message", history.kind()); - assertEquals(Message.Role.USER, history.role()); + assertEquals(Message.Role.ROLE_USER, history.role()); assertEquals("message-123", history.messageId()); assertEquals(3, history.parts().size()); assertTrue(history.parts().get(0) instanceof io.a2a.spec.TextPart); @@ -252,7 +252,7 @@ public void testSendMessageStreaming() throws Exception { RestTransport client = new RestTransport(CARD); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("tell me some jokes"))) .contextId("context-1234") .messageId("message-1234") @@ -478,7 +478,7 @@ public void testExtensionSupportRequiredErrorUnmarshalling() throws Exception { RestTransport client = new RestTransport(CARD); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("test message"))) .contextId("context-test") .messageId("message-test") @@ -526,7 +526,7 @@ public void testVersionNotSupportedErrorUnmarshalling() throws Exception { RestTransport client = new RestTransport(CARD); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("test message"))) .contextId("context-test") .messageId("message-test") @@ -573,7 +573,7 @@ public void testVersionNotSupportedErrorUnmarshallingStreaming() throws Exceptio RestTransport client = new RestTransport(CARD); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("test message"))) .contextId("context-test") .messageId("message-test") diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java index 5ed15a631..d208f25c3 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java @@ -126,7 +126,7 @@ public void testOnMessageWithMessageResult() { assertNotNull(receivedEvent.get()); assertTrue(receivedEvent.get() instanceof Message); Message message = (Message) receivedEvent.get(); - assertEquals(Message.Role.AGENT, message.role()); + assertEquals(Message.Role.ROLE_AGENT, message.role()); assertEquals("msg-123", message.messageId()); assertEquals("context-456", message.contextId()); assertEquals(1, message.parts().size()); diff --git a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java index f09670d55..9dd643df3 100644 --- a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java +++ b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java @@ -144,7 +144,7 @@ public void testHandleEventCallsEventHandler() { AtomicReference receivedEvent = new AtomicReference<>(); TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - Message message = createMessage(Message.Role.USER); + Message message = createMessage(Message.Role.ROLE_USER); listener.setEventToHandle(message); listener.onMessage(TEST_TEXT, null); @@ -242,7 +242,7 @@ public void testShouldAutoCloseWithNonFinalTaskStates(TaskState nonFinalState) { @Test public void testShouldAutoCloseWithMessage() { TestSSEEventListener listener = createBasicListener(); - Message message = createMessage(Message.Role.AGENT); + Message message = createMessage(Message.Role.ROLE_AGENT); assertFalse(listener.shouldAutoClose(message)); } @@ -268,7 +268,7 @@ public void testAutoCloseDoesNotCancelFutureForNonFinalEvent() { AtomicReference receivedEvent = new AtomicReference<>(); TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - Message message = createMessage(Message.Role.AGENT); + Message message = createMessage(Message.Role.ROLE_AGENT); CancelCapturingFuture future = new CancelCapturingFuture(); listener.setEventToHandle(message); diff --git a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java b/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java index 0dce363df..871affb4e 100644 --- a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java +++ b/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java @@ -281,7 +281,7 @@ private void sendProcessMessages() throws InterruptedException { .build(); Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(new TextPart("process")) .taskId(serverTaskId) .build(); @@ -326,7 +326,7 @@ private void sendCompleteMessage() { .build(); Message completeMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(new TextPart("complete")) .taskId(serverTaskId) .build(); diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java index 640fb757d..af36f3ffd 100644 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java +++ b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java @@ -78,7 +78,7 @@ public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallCont spanBuilder.setAttribute(GENAI_MESSAGE_ID, request.message().messageId()); } if (request.message().role() != null) { - spanBuilder.setAttribute(GENAI_ROLE, request.message().role().asString()); + spanBuilder.setAttribute(GENAI_ROLE, request.message().role().name()); } if (request.message().extensions() != null && !request.message().extensions().isEmpty()) { spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", request.message().extensions())); @@ -123,7 +123,7 @@ public void sendMessageStreaming(MessageSendParams request, Consumer onMessageSendStream(MessageSendParams spanBuilder.setAttribute(GENAI_MESSAGE_ID, params.message().messageId()); } if (params.message().role() != null) { - spanBuilder.setAttribute(GENAI_ROLE, params.message().role().asString()); + spanBuilder.setAttribute(GENAI_ROLE, params.message().role().name()); } if (params.message().extensions() != null && !params.message().extensions().isEmpty()) { spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", params.message().extensions())); diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java index 47c791976..4378fdbb8 100644 --- a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java +++ b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java @@ -202,7 +202,7 @@ class MessageSendTests { @Test void onMessageSend_createsSpanAndDelegatesToHandler() throws A2AError { Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("test message"))) .messageId("msg-123") .contextId("ctx-1") @@ -230,7 +230,7 @@ void onMessageSend_createsSpanAndDelegatesToHandler() throws A2AError { @Test void onMessageSend_withError_setsErrorStatus() throws A2AError { Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("test message"))) .messageId("msg-123") .contextId("ctx-1") @@ -253,7 +253,7 @@ class MessageSendStreamTests { @Test void onMessageSendStream_createsSpanWithSpecialMessage() throws A2AError { Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("test message"))) .messageId("msg-123") .contextId("ctx-1") @@ -275,7 +275,7 @@ void onMessageSendStream_createsSpanWithSpecialMessage() throws A2AError { @Test void onMessageSendStream_withError_setsErrorStatus() throws A2AError { Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("test message"))) .messageId("msg-123") .contextId("ctx-1") 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 06d4531b0..75a0df5de 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 @@ -104,7 +104,7 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep // Step 1: Create the task Message createMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("create"))) // Send the "create" command .taskId(taskId) .messageId("test-msg-1") @@ -139,7 +139,7 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep // Step 4: Update the task to trigger the notification Message updateMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("update"))) // Send the "update" command .taskId(taskId) .messageId("test-msg-2") 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 ce45b6d51..04fa5d024 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 @@ -75,7 +75,7 @@ public void testTaskSerialization() throws JsonProcessingException { public void testMessageSerialization() throws JsonProcessingException { // Create a Message Message originalMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("Hello, world!"))) .taskId("test-task-789") .messageId("test-msg-456") 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 43716a040..4add5540b 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 @@ -136,7 +136,7 @@ public void testA2AMessageReplicatedToKafka() throws Exception { // Send A2A message that should trigger events and replication Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("create"))) .taskId(taskId) .messageId("test-msg-" + System.currentTimeMillis()) @@ -199,7 +199,7 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { // First create a task in the A2A system using non-streaming client Message createMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("create"))) .taskId(taskId) .messageId("create-msg-" + System.currentTimeMillis()) @@ -319,7 +319,7 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { // Use polling (non-blocking) client with "working" command // This creates task in WORKING state (non-final) and keeps queue alive Message workingMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("working"))) .taskId(taskId) .messageId("working-msg-" + System.currentTimeMillis()) @@ -414,7 +414,7 @@ public void testPoisonPillGenerationOnTaskFinalization() throws Exception { // Create a task that will be completed (finalized) Message completeMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("complete"))) .taskId(taskId) .messageId("complete-msg-" + System.currentTimeMillis()) diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java index 010c6abf7..9b716c705 100644 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java +++ b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java @@ -75,7 +75,7 @@ public void testJpaDatabaseTaskStore() throws Exception { // Send a message creating the Task assertNull(taskStore.get(taskId)); Message userMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("create"))) .taskId(taskId) .messageId("test-msg-1") @@ -104,7 +104,7 @@ public void testJpaDatabaseTaskStore() throws Exception { // Send a message updating the Task userMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("add-artifact"))) .taskId(taskId) .messageId("test-msg-2") 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 2902b7d7d..74164e39e 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 @@ -70,7 +70,7 @@ public void testSaveAndRetrieveTask() { public void testSaveAndRetrieveTaskWithHistory() { // Create a message for the task history Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("Hello, agent!"))) .messageId("msg-1") .build(); @@ -601,7 +601,7 @@ public void testListTasksHistoryLimiting() { List longHistory = new ArrayList<>(); for (int i = 1; i <= 10; i++) { Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("Message " + i))) .messageId("msg-history-limit-" + i) .build(); diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index e2d3b751b..29aa36ae8 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -61,7 +61,6 @@ import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskNotCancelableError; import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; @@ -78,7 +77,6 @@ private static GsonBuilder createBaseGsonBuilder() { .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) .registerTypeHierarchyAdapter(A2AError.class, new A2AErrorTypeAdapter()) - .registerTypeAdapter(Message.Role.class, new RoleTypeAdapter()) .registerTypeHierarchyAdapter(FileContent.class, new FileContentTypeAdapter()); } @@ -439,52 +437,6 @@ private A2AError createErrorInstance(@Nullable Integer code, @Nullable String me } } - /** - * Gson TypeAdapter for serializing and deserializing {@link Message.Role} enum. - *

        - * This adapter ensures that Message.Role enum values are serialized using their - * wire format string representation (e.g., "user", "agent") rather than the Java - * enum constant name (e.g., "USER", "AGENT"). - *

        - * For serialization, it uses {@link Message.Role#asString()} to get the wire format. - * For deserialization, it parses the string to the enum constant. - * - * @see Message.Role - * @see Message.Role#asString() - */ - static class RoleTypeAdapter extends TypeAdapter { - - @Override - public void write(JsonWriter out, Message.Role value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - } else { - out.value(value.asString()); - } - } - - @Override - public Message.@Nullable Role read(JsonReader in) throws java.io.IOException { - if (in.peek() == com.google.gson.stream.JsonToken.NULL) { - in.nextNull(); - return null; - } - String roleString = in.nextString(); - try { - return switch (roleString) { - case "user" -> - Message.Role.USER; - case "agent" -> - Message.Role.AGENT; - default -> - throw new IllegalArgumentException("Invalid Role: " + roleString); - }; - } catch (IllegalArgumentException e) { - throw new JsonSyntaxException("Invalid Message.Role: " + roleString, e); - } - } - } - /** * Gson TypeAdapter for serializing and deserializing {@link Part} and its subclasses. *

        diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java index 219fbde8e..d0bf98090 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java @@ -61,7 +61,7 @@ void testTaskSerialization() throws JsonProcessingException { void testMessageSerialization() throws JsonProcessingException { // Create a Message Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("Hello, agent!"))) .taskId("task-789") .messageId("msg-123") @@ -75,7 +75,7 @@ void testMessageSerialization() throws JsonProcessingException { assertNotNull(json); assertTrue(json.contains("\"message\"")); assertTrue(json.contains("\"taskId\":\"task-789\"")); - assertTrue(json.contains("\"role\":\"user\"")); + assertTrue(json.contains("\"role\":\"ROLE_USER\"")); assertTrue(json.contains("Hello, agent!")); assertFalse(json.contains("\"kind\"")); @@ -186,7 +186,7 @@ void testUnwrappedMessageDeserialization() throws JsonProcessingException { // Test that unwrapped Message format (direct deserialization) still works String json = """ { - "role": "agent", + "role": "ROLE_AGENT", "parts": [ { "text": "Unwrapped message" @@ -205,7 +205,7 @@ void testUnwrappedMessageDeserialization() throws JsonProcessingException { Message message = (Message) deserialized; assertEquals("msg-unwrapped", message.messageId()); assertEquals("task-999", message.taskId()); - assertEquals(Message.Role.AGENT, message.role()); + assertEquals(Message.Role.ROLE_AGENT, message.role()); } @Test diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java index 8133dd0fc..9c0fd2610 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java @@ -114,7 +114,7 @@ void testTaskWithArtifacts() throws JsonProcessingException { @Test void testTaskWithHistory() throws JsonProcessingException { Message message = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("Test message"))) .build(); @@ -129,7 +129,7 @@ void testTaskWithHistory() throws JsonProcessingException { String json = JsonUtil.toJson(task); // Verify JSON contains history data - assertTrue(json.contains("\"role\":\"user\"")); + assertTrue(json.contains("\"role\":\"ROLE_USER\"")); assertTrue(json.contains("Test message")); // Deserialize @@ -138,7 +138,7 @@ void testTaskWithHistory() throws JsonProcessingException { // Verify history is preserved assertNotNull(deserialized.history()); assertEquals(1, deserialized.history().size()); - assertEquals(Message.Role.USER, deserialized.history().get(0).role()); + assertEquals(Message.Role.ROLE_USER, deserialized.history().get(0).role()); assertEquals(1, deserialized.history().get(0).parts().size()); } @@ -152,11 +152,11 @@ void testTaskWithAllFields() throws JsonProcessingException { .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, timestamp)) .history(List.of( Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("User message"))) .build(), Message.builder() - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(List.of(new TextPart("Agent response"))) .build() )) @@ -354,7 +354,7 @@ void testTaskRoundTrip() throws JsonProcessingException { .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, timestamp)) .history(List.of( Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of( new TextPart("Text"), new FilePart(new FileWithBytes("text/plain", "file.txt", "data")), @@ -394,7 +394,7 @@ void testTaskRoundTrip() throws JsonProcessingException { @Test void testTaskStatusWithMessage() throws JsonProcessingException { Message statusMessage = Message.builder() - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(List.of(new TextPart("Processing complete"))) .build(); @@ -417,7 +417,7 @@ void testTaskStatusWithMessage() throws JsonProcessingException { // Verify status message is preserved assertEquals(TaskState.TASK_STATE_COMPLETED, deserialized.status().state()); assertNotNull(deserialized.status().message()); - assertEquals(Message.Role.AGENT, deserialized.status().message().role()); + assertEquals(Message.Role.ROLE_AGENT, deserialized.status().message().role()); assertTrue(deserialized.status().message().parts().get(0) instanceof TextPart); } @@ -602,7 +602,7 @@ void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException { }, "history": [ { - "role": "user", + "role": "ROLE_USER", "parts": [ { "text": "User message" @@ -611,7 +611,7 @@ void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException { "messageId": "msg-1" }, { - "role": "agent", + "role": "ROLE_AGENT", "parts": [ { "text": "Agent response" @@ -627,8 +627,8 @@ void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException { assertEquals("task-123", task.id()); assertEquals(2, task.history().size()); - assertEquals(Message.Role.USER, task.history().get(0).role()); - assertEquals(Message.Role.AGENT, task.history().get(1).role()); + assertEquals(Message.Role.ROLE_USER, task.history().get(0).role()); + assertEquals(Message.Role.ROLE_AGENT, task.history().get(1).role()); assertTrue(task.history().get(0).parts().get(0) instanceof TextPart); assertEquals("User message", ((TextPart) task.history().get(0).parts().get(0)).text()); } diff --git a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java index d3aa3d115..d300cbca2 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java +++ b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java @@ -443,7 +443,7 @@ public void requiresAuth(@Nullable Message message, boolean isFinal) { */ public Message newAgentMessage(List> parts, @Nullable Map metadata) { return Message.builder() - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .taskId(taskId) .contextId(contextId) .messageId(UUID.randomUUID().toString()) @@ -614,7 +614,7 @@ public Task.Builder taskBuilder() { public Message.Builder messageBuilder() { Message.Builder builder = Message.builder() .contextId(contextId) - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .messageId(UUID.randomUUID().toString()); // Only set taskId if present (messages can exist without tasks) 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 daf178203..2fc0c62e9 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 @@ -46,7 +46,7 @@ public void testInitWithoutParams() { @Test public void testInitWithParamsNoIds() { - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); UUID taskId = UUID.fromString("00000000-0000-0000-0000-000000000001"); @@ -73,7 +73,7 @@ public void testInitWithParamsNoIds() { @Test public void testInitWithTaskId() { String taskId = "task-123"; - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(taskId).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId(taskId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -88,7 +88,7 @@ public void testInitWithTaskId() { @Test public void testInitWithContextId() { String contextId = "context-456"; - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).contextId(contextId).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).contextId(contextId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -104,7 +104,7 @@ public void testInitWithContextId() { public void testInitWithBothIds() { String taskId = "task-123"; String contextId = "context-456"; - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(taskId).contextId(contextId).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId(taskId).contextId(contextId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -121,7 +121,7 @@ public void testInitWithBothIds() { @Test public void testInitWithTask() { - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); @@ -159,7 +159,7 @@ public void testAttachRelatedTask() { @Test public void testCheckOrGenerateTaskIdWithExistingTaskId() { String existingId = "existing-task-id"; - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId(existingId).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId(existingId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -174,7 +174,7 @@ public void testCheckOrGenerateTaskIdWithExistingTaskId() { public void testCheckOrGenerateContextIdWithExistingContextId() { String existingId = "existing-context-id"; - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).contextId(existingId).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).contextId(existingId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -187,7 +187,7 @@ public void testCheckOrGenerateContextIdWithExistingContextId() { @Test public void testInitRaisesErrorOnTaskIdMismatch() { - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId("task-123").build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); @@ -203,7 +203,7 @@ public void testInitRaisesErrorOnTaskIdMismatch() { @Test public void testInitRaisesErrorOnContextIdMismatch() { - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); @@ -242,7 +242,7 @@ public void testMessagePropertyWithoutParams() { @Test public void testMessagePropertyWithParams() { - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -260,7 +260,7 @@ public void testInitWithExistingIdsInMessage() { String existingTaskId = "existing-task-id"; String existingContextId = "existing-context-id"; - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))) + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))) .taskId(existingTaskId).contextId(existingContextId).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); @@ -274,7 +274,7 @@ public void testInitWithExistingIdsInMessage() { @Test public void testInitWithTaskIdAndExistingTaskIdMatch() { - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); @@ -290,7 +290,7 @@ public void testInitWithTaskIdAndExistingTaskIdMatch() { @Test public void testInitWithContextIdAndExistingContextIdMatch() { - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); @@ -307,7 +307,7 @@ public void testInitWithContextIdAndExistingContextIdMatch() { @Test void testMessageBuilderGeneratesId() { - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -320,7 +320,7 @@ void testMessageBuilderGeneratesId() { @Test void testMessageBuilderUsesProvidedId() { - var mockMessage = Message.builder().messageId("123").role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockMessage = Message.builder().messageId("123").role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -362,7 +362,7 @@ public void testBuilderUpdatesMessageWithBuilderIds() { String builderContextId = "builder-context-id"; // Message has no IDs, but builder provides them - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); RequestContext context = new RequestContext.Builder() @@ -385,7 +385,7 @@ public void testMessageIdsTakePrecedenceWhenBothPresent() { String sharedContextId = "shared-context-id"; var mockMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart(""))) .taskId(sharedTaskId) .contextId(sharedContextId) @@ -410,7 +410,7 @@ public void testBuilderPreservesTenantWhenUpdatingMessage() { String tenantId = "customer-123"; String builderTaskId = "builder-task-id"; - var mockMessage = Message.builder().role(Message.Role.USER).parts(List.of(new TextPart(""))).build(); + var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); var mockParams = MessageSendParams.builder() .message(mockMessage) .configuration(defaultConfiguration()) 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 6202e2f75..e31fa9b4b 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 @@ -53,7 +53,7 @@ public class EventConsumerTest { private static final String MESSAGE_PAYLOAD = """ { - "role": "agent", + "role": "ROLE_AGENT", "parts": [{"text": "test message"}], "messageId": "111" } 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 c9761f66d..e59d66d88 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 @@ -49,7 +49,7 @@ public class EventQueueTest { private static final String MESSAGE_PAYLOAD = """ { - "role": "agent", + "role": "ROLE_AGENT", "parts": [{"text": "test message"}], "messageId": "111" } 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 0529f51f9..c553de317 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 @@ -63,7 +63,7 @@ public class AbstractA2ARequestHandlerTest { protected static final Message MESSAGE = Message.builder() .messageId("111") - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(new TextPart("test message")) .build(); private static final String PREFERRED_TRANSPORT = "preferred-transport"; diff --git a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java index 8693f32cf..7c85b9004 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java @@ -1,6 +1,6 @@ package io.a2a.server.tasks; -import static io.a2a.spec.Message.Role.AGENT; +import static io.a2a.spec.Message.Role.ROLE_AGENT; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -38,7 +38,7 @@ public class AgentEmitterTest { .taskId(TEST_TASK_ID) .contextId(TEST_TASK_CONTEXT_ID) .parts(new TextPart("Test message")) - .role(AGENT) + .role(ROLE_AGENT) .build(); private static final List> SAMPLE_PARTS = List.of(new TextPart("Test message")); @@ -243,7 +243,7 @@ public void testNonTerminalStateUpdatesAllowed() throws Exception { public void testNewAgentMessage() throws Exception { Message message = agentEmitter.newAgentMessage(SAMPLE_PARTS, null); - assertEquals(AGENT, message.role()); + assertEquals(ROLE_AGENT, message.role()); assertEquals(TEST_TASK_ID, message.taskId()); assertEquals(TEST_TASK_CONTEXT_ID, message.contextId()); assertNotNull(message.messageId()); @@ -256,7 +256,7 @@ public void testNewAgentMessageWithMetadata() throws Exception { Map metadata = Map.of("key", "value"); Message message = agentEmitter.newAgentMessage(SAMPLE_PARTS, metadata); - assertEquals(AGENT, message.role()); + assertEquals(ROLE_AGENT, message.role()); assertEquals(TEST_TASK_ID, message.taskId()); assertEquals(TEST_TASK_CONTEXT_ID, message.contextId()); assertNotNull(message.messageId()); 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 bde4db4d5..4a68d849a 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 @@ -349,7 +349,7 @@ public void testSendNotificationMessage() throws InterruptedException { String taskId = "task_send_message"; Message message = Message.builder() .taskId(taskId) - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(new TextPart("Hello from agent")) .build(); PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); diff --git a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java index bdf7311a2..fa4eb8ef5 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java @@ -112,7 +112,7 @@ public void onTaskFinalized(String taskId) { @Test void testConstructorWithMessage() { - Message initialMessage = createSampleMessage("initial", "msg1", Message.Role.USER); + Message initialMessage = createSampleMessage("initial", "msg1", Message.Role.ROLE_USER); ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, initialMessage, testExecutor, testExecutor); // Test that the message is properly stored by checking getCurrentResult @@ -123,7 +123,7 @@ void testConstructorWithMessage() { @Test void testGetCurrentResultWithMessageSet() { - Message sampleMessage = createSampleMessage("hola", "msg1", Message.Role.USER); + Message sampleMessage = createSampleMessage("hola", "msg1", Message.Role.ROLE_USER); ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, sampleMessage, testExecutor, testExecutor); EventKind result = aggregatorWithMessage.getCurrentResult(); @@ -218,7 +218,7 @@ void testMultipleGetCurrentResultCalls() { @Test void testGetCurrentResultWithMessageTakesPrecedence() { // Test that when both message and task are available, message takes precedence - Message message = createSampleMessage("priority message", "pri1", Message.Role.USER); + Message message = createSampleMessage("priority message", "pri1", Message.Role.ROLE_USER); ResultAggregator messageAggregator = new ResultAggregator(mockTaskManager, message, testExecutor, testExecutor); // Even if we set up the task manager to return something, message should take precedence 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 627fd81d5..0c502fd3a 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 @@ -75,7 +75,7 @@ public void testSaveTaskEventStatusUpdate() throws A2AServerException { TaskStatus newStatus = new TaskStatus( TaskState.TASK_STATE_WORKING, Message.builder() - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(Collections.singletonList(new TextPart("content"))) .messageId("messageId") .build(), @@ -385,7 +385,7 @@ public void testTaskWithNoMessageUsesInitialMessage() throws A2AServerException // Test that adding a task with no message, and there is a TaskManager.initialMessage, // the initialMessage gets used Message initialMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("initial message"))) .messageId("initial-msg-id") .build(); @@ -416,7 +416,7 @@ public void testTaskWithNoMessageUsesInitialMessage() throws A2AServerException public void testTaskWithMessageDoesNotUseInitialMessage() throws A2AServerException { // Test that adding a task with a message does not use the initial message Message initialMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("initial message"))) .messageId("initial-msg-id") .build(); @@ -424,7 +424,7 @@ public void testTaskWithMessageDoesNotUseInitialMessage() throws A2AServerExcept TaskManager taskManagerWithInitialMessage = new TaskManager(null, null, taskStore, initialMessage); Message taskMessage = Message.builder() - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(Collections.singletonList(new TextPart("task message"))) .messageId("task-msg-id") .build(); @@ -625,7 +625,7 @@ public void testSaveTaskEventMetadataMergeExisting() throws A2AServerException { public void testCreateTaskWithInitialMessage() throws A2AServerException { // Test equivalent of _init_task_obj functionality Message initialMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("initial message"))) .messageId("initial-msg-id") .build(); @@ -702,7 +702,7 @@ public void testSaveTaskInternal() throws A2AServerException { @Test public void testUpdateWithMessage() throws A2AServerException { Message initialMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("initial message"))) .messageId("initial-msg-id") .build(); @@ -710,7 +710,7 @@ public void testUpdateWithMessage() throws A2AServerException { TaskManager taskManagerWithInitialMessage = new TaskManager(null, null, taskStore, initialMessage); Message taskMessage = Message.builder() - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(Collections.singletonList(new TextPart("task message"))) .messageId("task-msg-id") .build(); @@ -725,7 +725,7 @@ public void testUpdateWithMessage() throws A2AServerException { Task saved = taskManagerWithInitialMessage.getTask(); Message updateMessage = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("update message"))) .messageId("update-msg-id") .build(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java index 13e003a6f..8ff59552c 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java @@ -1,5 +1,6 @@ package io.a2a.grpc.mapper; +import io.a2a.grpc.Role; import io.a2a.spec.Message; import org.mapstruct.Mapper; @@ -8,8 +9,9 @@ *

        * Handles enum conversion between domain and protobuf role representations: *

          - *
        • USER (domain) ↔ ROLE_USER (proto)
        • - *
        • AGENT (domain) ↔ ROLE_AGENT (proto)
        • + *
        • ROLE_USER (domain) ↔ ROLE_USER (proto)
        • + *
        • ROLE_AGENT (domain) ↔ ROLE_AGENT (proto)
        • + *
        • ROLE_UNSPECIFIED (domain) ↔ ROLE_UNSPECIFIED (proto)
        • *
        *

        * Manual Implementation Required: Uses manual switch statements instead of @ValueMapping @@ -22,31 +24,29 @@ public interface RoleMapper { /** * Converts domain Role to proto Role. - * Maps USER → ROLE_USER, AGENT → ROLE_AGENT. */ default io.a2a.grpc.Role toProto(Message.Role domain) { if (domain == null) { return io.a2a.grpc.Role.ROLE_UNSPECIFIED; } return switch (domain) { - case USER -> io.a2a.grpc.Role.ROLE_USER; - case AGENT -> io.a2a.grpc.Role.ROLE_AGENT; + case ROLE_USER -> io.a2a.grpc.Role.ROLE_USER; + case ROLE_AGENT -> io.a2a.grpc.Role.ROLE_AGENT; + case ROLE_UNSPECIFIED -> Role.ROLE_UNSPECIFIED; }; } /** * Converts proto Role to domain Role. - * Maps ROLE_USER → USER, ROLE_AGENT → AGENT. - * ROLE_UNSPECIFIED returns null. */ default Message.Role fromProto(io.a2a.grpc.Role proto) { if (proto == null || proto == io.a2a.grpc.Role.ROLE_UNSPECIFIED) { return null; } return switch (proto) { - case ROLE_USER -> Message.Role.USER; - case ROLE_AGENT -> Message.Role.AGENT; - default -> null; + case ROLE_USER -> Message.Role.ROLE_USER; + case ROLE_AGENT -> Message.Role.ROLE_AGENT; + default -> Message.Role.ROLE_UNSPECIFIED; }; } } 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 88d1e79f2..99ff1ad39 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 @@ -71,7 +71,7 @@ void testConvertMessage_ToProto() { Message message = Message.builder() .messageId("msg-123") .contextId("context-456") - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("Hello"))) .build(); @@ -109,7 +109,7 @@ void testConvertMessage_FromProto() { Message message = (Message) result; assertEquals("msg-123", message.messageId()); assertEquals("context-456", message.contextId()); - assertEquals(Message.Role.USER, message.role()); + assertEquals(Message.Role.ROLE_USER, message.role()); } @Test @@ -253,7 +253,7 @@ void testConvertStreamResponse_Roundtrip_Message() { Message originalMessage = Message.builder() .messageId("msg-123") .contextId("context-456") - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(Collections.singletonList(new TextPart("Response"))) .build(); 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 ecfab4beb..569d77981 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 @@ -10,6 +10,8 @@ import static org.junit.jupiter.api.Assertions.fail; import com.google.gson.JsonSyntaxException; + +import io.a2a.grpc.Role; import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; import io.a2a.jsonrpc.common.json.JsonMappingException; import io.a2a.jsonrpc.common.json.JsonProcessingException; @@ -18,8 +20,10 @@ import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.JSONParseError; +import io.a2a.spec.Message; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; import org.junit.jupiter.api.Test; @@ -203,11 +207,12 @@ public void testParseMissingField_ThrowsInvalidParamsError() throws JsonMappingE } }"""; InvalidParamsJsonMappingException exception = assertThrows( - InvalidParamsJsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(missingRoleMessage, null) + InvalidParamsJsonMappingException.class, + () -> JSONRPCUtils.parseRequestBody(missingRoleMessage, null) ); assertEquals(18, exception.getId()); } + @Test public void testParseUnknownField_ThrowsJsonMappingException() throws JsonMappingException { String unkownFieldMessage= """ diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index d17ce58bc..fc8771736 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -37,7 +37,7 @@ public class ToProtoTest { private static final Message SIMPLE_MESSAGE = Message.builder() - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("tell me a joke"))) .contextId("context-1234") .messageId("message-1234") @@ -188,7 +188,7 @@ public void convertMessage() { assertEquals(false, result.getParts(0).hasUrl()); assertEquals(false, result.getParts(0).hasData()); Message message = Message.builder() - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(Collections.singletonList(new TextPart("tell me a joke"))) .messageId("message-1234") .build(); diff --git a/spec/src/main/java/io/a2a/spec/Message.java b/spec/src/main/java/io/a2a/spec/Message.java index cc4b1cf12..4459fd5b7 100644 --- a/spec/src/main/java/io/a2a/spec/Message.java +++ b/spec/src/main/java/io/a2a/spec/Message.java @@ -108,26 +108,15 @@ public enum Role { /** * Message originated from the user (client side). */ - USER("user"), + ROLE_USER, /** * Message originated from the agent (server side). */ - AGENT("agent"); - - private final String role; - - Role(String role) { - this.role = role; - } - + ROLE_AGENT, /** - * Returns the string representation of the role for JSON serialization. - * - * @return the role as a string ("user" or "agent") + * Unspecified role. */ - public String asString() { - return this.role; - } + ROLE_UNSPECIFIED; } /** 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 911945fa0..acd9e97b0 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 @@ -120,7 +120,7 @@ public abstract class AbstractA2AServerTest { protected static final Message MESSAGE = Message.builder() .messageId("111") - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(new TextPart("test message")) .build(); public static final String APPLICATION_JSON = "application/json"; 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 5b04b9428..9087a1864 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 @@ -831,7 +831,7 @@ public void testOnSubscribeExistingTaskSuccess() { Message message = Message.builder() .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) - .role(Message.Role.AGENT) + .role(Message.Role.ROLE_AGENT) .parts(new TextPart("text")) .build(); SendMessageResponse smr From 6a222438eb37f76b1ffc57138a6fb9ece8d91266 Mon Sep 17 00:00:00 2001 From: Lee Chae Min Date: Wed, 18 Feb 2026 07:09:13 +0900 Subject: [PATCH 042/192] fix: use SERVER_URL constant in A2ACardResolver constructor in HelloWorldClient #664 (#666) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Replace the hardcoded string literal `"http://localhost:9999"` with the existing `SERVER_URL` constant in the `A2ACardResolver` constructor call inside `HelloWorldClient`. Fixes #664 🦕 --- .../main/java/io/a2a/examples/helloworld/HelloWorldClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 332706ccc..6634898c7 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 @@ -53,7 +53,7 @@ public class HelloWorldClient { public static void main(String[] args) { OpenTelemetrySdk openTelemetrySdk = null; try { - AgentCard publicAgentCard = new A2ACardResolver("http://localhost:9999").getAgentCard(); + AgentCard publicAgentCard = new A2ACardResolver(SERVER_URL).getAgentCard(); System.out.println("Successfully fetched public agent card:"); System.out.println(JsonUtil.toJson(publicAgentCard)); System.out.println("Using public agent card for client initialization (default)."); From e4902036c6e958e89c5d91948bebf6b9c35fd89d Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 18 Feb 2026 10:52:22 +0000 Subject: [PATCH 043/192] feat: Add agent-to-agent communication testing (#654) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements server-side agent-to-agent communication where an AgentExecutor can use a client to connect back to the same server, enabling agents to delegate work to other agents. Fixes #625 🦕 --- reference/jsonrpc/pom.xml | 6 + .../server/apps/quarkus/A2AServerRoutes.java | 3 + .../server/rest/quarkus/A2AServerRoutes.java | 3 + .../java/io/a2a/server/ServerCallContext.java | 6 + .../apps/common/AbstractA2AServerTest.java | 141 ++++++++++++++- .../apps/common/AgentExecutorProducer.java | 168 ++++++++++++++++++ .../common/AgentToAgentClientFactory.java | 119 +++++++++++++ .../transport/grpc/handler/GrpcHandler.java | 5 +- 8 files changed, 449 insertions(+), 2 deletions(-) create mode 100644 tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index e099711a3..e7172fde7 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -51,6 +51,12 @@ test-jar test + + + ${project.groupId} + a2a-java-sdk-client-transport-jsonrpc + test + io.quarkus quarkus-reactive-routes 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 548f88da3..971a0cc77 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 @@ -1,5 +1,6 @@ package io.a2a.server.apps.quarkus; +import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; @@ -62,6 +63,7 @@ import io.a2a.spec.A2AError; import io.a2a.spec.InternalError; import io.a2a.spec.JSONParseError; +import io.a2a.spec.TransportProtocol; import io.a2a.spec.UnsupportedOperationError; import io.a2a.transport.jsonrpc.handler.JSONRPCHandler; import io.quarkus.security.Authenticated; @@ -246,6 +248,7 @@ public String getUsername() { headerNames.forEach(name -> headers.put(name, rc.request().getHeader(name))); state.put(HEADERS_KEY, headers); state.put(TENANT_KEY, extractTenant(rc)); + state.put(TRANSPORT_KEY, TransportProtocol.JSONRPC); // Extract requested protocol version from X-A2A-Version header String requestedVersion = rc.request().getHeader(A2AHeaders.X_A2A_VERSION); 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 3c664c4b2..9b6bf510a 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,5 +1,6 @@ package io.a2a.server.rest.quarkus; +import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; 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; @@ -33,6 +34,7 @@ import io.a2a.spec.InternalError; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.MethodNotFoundError; +import io.a2a.spec.TransportProtocol; import io.a2a.transport.rest.handler.RestHandler; import io.a2a.transport.rest.handler.RestHandler.HTTPRestResponse; import io.a2a.transport.rest.handler.RestHandler.HTTPRestStreamingResponse; @@ -430,6 +432,7 @@ public String getUsername() { state.put(HEADERS_KEY, headers); state.put(METHOD_NAME_KEY, jsonRpcMethodName); state.put(TENANT_KEY, extractTenant(rc)); + state.put(TRANSPORT_KEY, TransportProtocol.HTTP_JSON); // Extract requested protocol version from X-A2A-Version header String requestedVersion = rc.request().getHeader(A2AHeaders.X_A2A_VERSION); diff --git a/server-common/src/main/java/io/a2a/server/ServerCallContext.java b/server-common/src/main/java/io/a2a/server/ServerCallContext.java index c12c60c21..21a9e790b 100644 --- a/server-common/src/main/java/io/a2a/server/ServerCallContext.java +++ b/server-common/src/main/java/io/a2a/server/ServerCallContext.java @@ -9,6 +9,12 @@ import org.jspecify.annotations.Nullable; public class ServerCallContext { + /** + * Key for transport protocol type in the state map. + * Value should be a {@link io.a2a.spec.TransportProtocol} instance. + */ + public static final String TRANSPORT_KEY = "transport"; + // TODO Not totally sure yet about these field types private final Map modelConfig = new ConcurrentHashMap<>(); private final Map state; 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 acd9e97b0..646451d6d 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 @@ -19,6 +19,7 @@ import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Optional; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; @@ -28,6 +29,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; import java.util.stream.Stream; import jakarta.ws.rs.core.MediaType; @@ -617,7 +619,6 @@ public void testGetExtendedAgentCard() throws A2AClientException { .filter(i -> getTransportProtocol().equals(i.protocolBinding())) .findFirst(); assertTrue(transportInterface.isPresent()); - System.out.println("transportInterface = " + transportInterface); assertEquals(getTransportUrl(),transportInterface.get().url()); assertEquals("1.0", agentCard.version()); assertEquals("http://example.com/docs", agentCard.documentationUrl()); @@ -2451,4 +2452,142 @@ public void testMainQueueClosesForFinalizedTasks() throws Exception { } } + /** + * Test agent-to-agent communication with delegation pattern. + *

        + * Verifies that an AgentExecutor can use a client to delegate work to another agent + * by using the "delegate:" prefix. The delegated request is forwarded to another agent + * on the same server, and the artifacts from the delegated task are extracted and returned. + *

        + * This test verifies: + *

          + *
        • Transport type is correctly passed via ServerCallContext state
        • + *
        • AgentExecutor can create a client with matching transport
        • + *
        • Delegation pattern ("delegate:" prefix) is recognized
        • + *
        • Client successfully communicates with same server
        • + *
        • Artifacts from delegated task are extracted and returned
        • + *
        • Original task ID is preserved (not replaced by delegated task ID)
        • + *
        + */ + @Test + public void testAgentToAgentDelegation() throws Exception { + String delegationTaskId = "agent-to-agent-test-" + UUID.randomUUID(); + + Message delegationMessage = Message.builder() + .taskId(delegationTaskId) + .contextId("agent-to-agent-context") + .role(Message.Role.USER) + .parts(new TextPart("delegate:What is 2+2?")) + .build(); + + CountDownLatch delegationLatch = new CountDownLatch(1); + AtomicReference delegationResultRef = new AtomicReference<>(); + AtomicReference delegationErrorRef = new AtomicReference<>(); + + BiConsumer delegationConsumer = + AgentToAgentClientFactory.createTaskCaptureConsumer(delegationResultRef, delegationLatch); + + getClient().sendMessage(delegationMessage, List.of(delegationConsumer), error -> { + delegationErrorRef.set(error); + delegationLatch.countDown(); + }); + + assertTrue(delegationLatch.await(30, TimeUnit.SECONDS), "Delegation should complete within timeout"); + + Task delegationResult = delegationResultRef.get(); + + // Only fail on errors if we didn't get a successful result + // (errors can occur after completion due to stream cleanup) + if (delegationResult == null && delegationErrorRef.get() != null) { + fail("Delegation failed: " + delegationErrorRef.get().getMessage()); + } + + assertNotNull(delegationResult, "Delegation task should not be null"); + assertEquals(TaskState.TASK_STATE_COMPLETED, delegationResult.status().state(), + "Delegation task should be completed"); + assertNotNull(delegationResult.artifacts(), "Delegation should have artifacts"); + assertFalse(delegationResult.artifacts().isEmpty(), "Delegation should have at least one artifact"); + + // Extract text from result + String delegatedText = extractTextFromTask(delegationResult); + assertTrue(delegatedText.contains("Handled locally:"), + "Delegated content should have been handled locally by target agent. Got: " + delegatedText); + + // Verify the task ID is the original one (not the delegated task's ID) + assertEquals(delegationTaskId, delegationResult.id(), + "Task ID should be the original task ID, not the delegated task's ID"); + } + + /** + * Test agent-to-agent communication with local handling (no delegation). + *

        + * Verifies that requests without the "delegate:" prefix are handled locally + * by the agent without creating a client connection. + *

        + * This test verifies: + *

          + *
        • Requests without "delegate:" prefix are handled locally
        • + *
        • No client-to-client communication occurs for local handling
        • + *
        • Task completes successfully with expected content
        • + *
        + */ + @Test + public void testAgentToAgentLocalHandling() throws Exception { + String localTaskId = "agent-to-agent-test-" + UUID.randomUUID(); + + Message localMessage = Message.builder() + .taskId(localTaskId) + .contextId("agent-to-agent-context") + .role(Message.Role.USER) + .parts(new TextPart("Hello directly")) + .build(); + + CountDownLatch localLatch = new CountDownLatch(1); + AtomicReference localResultRef = new AtomicReference<>(); + AtomicReference localErrorRef = new AtomicReference<>(); + + BiConsumer localConsumer = + AgentToAgentClientFactory.createTaskCaptureConsumer(localResultRef, localLatch); + + getClient().sendMessage(localMessage, List.of(localConsumer), error -> { + localErrorRef.set(error); + localLatch.countDown(); + }); + + assertTrue(localLatch.await(30, TimeUnit.SECONDS), "Local handling should complete within timeout"); + + Task localResult = localResultRef.get(); + + // Only fail on errors if we didn't get a successful result + // (errors can occur after completion due to stream cleanup) + if (localResult == null && localErrorRef.get() != null) { + fail("Local handling failed: " + localErrorRef.get().getMessage()); + } + + assertNotNull(localResult, "Local task should not be null"); + assertEquals(TaskState.TASK_STATE_COMPLETED, localResult.status().state(), + "Local task should be completed"); + + String localText = extractTextFromTask(localResult); + assertTrue(localText.contains("Handled locally: Hello directly"), + "Should be handled locally without delegation. Got: " + localText); + } + + /** + * Extracts all text from a task's artifacts. + * + * @param task the task containing artifacts + * @return concatenated text from all TextParts in all artifacts + */ + private String extractTextFromTask(Task task) { + if (task.artifacts() == null || task.artifacts().isEmpty()) { + return ""; + } + return task.artifacts().stream() + .flatMap(artifact -> artifact.parts().stream()) + .filter(part -> part instanceof TextPart) + .map(part -> ((TextPart) part).text()) + .collect(Collectors.joining("\n")); + } + } 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 40839e7fb..d62391bf8 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,18 +1,38 @@ package io.a2a.server.apps.common; +import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; + import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import io.a2a.A2A; +import io.a2a.client.Client; +import io.a2a.client.ClientEvent; +import io.a2a.client.TaskEvent; +import io.a2a.client.TaskUpdateEvent; +import io.a2a.server.PublicAgentCard; +import io.a2a.server.ServerCallContext; import io.a2a.server.agentexecution.AgentExecutor; import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.tasks.AgentEmitter; +import io.a2a.spec.A2AClientException; import io.a2a.spec.A2AError; +import io.a2a.spec.AgentCard; +import io.a2a.spec.Artifact; +import io.a2a.spec.InternalError; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.Message; import io.a2a.spec.Part; +import io.a2a.spec.Task; import io.a2a.spec.TextPart; +import io.a2a.spec.TransportProtocol; import io.a2a.spec.UnsupportedOperationError; import io.quarkus.arc.profile.IfBuildProfile; @@ -20,6 +40,11 @@ @IfBuildProfile("test") public class AgentExecutorProducer { + // Inject the existing AgentCard to avoid special handling for grpc + @Inject + @PublicAgentCard + AgentCard agentCard; + @Produces public AgentExecutor agentExecutor() { return new AgentExecutor() { @@ -27,6 +52,12 @@ public AgentExecutor agentExecutor() { public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { String taskId = context.getTaskId(); + // Agent-to-agent communication test + if (taskId != null && taskId.startsWith("agent-to-agent-test")) { + handleAgentToAgentTest(context, agentEmitter); + return; + } + // Special handling for multi-event test if (taskId != null && taskId.startsWith("multi-event-test")) { // First call: context.getTask() == null (new task) @@ -69,6 +100,22 @@ public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2 if (context.getTaskId().equals("task-not-supported-123")) { throw new UnsupportedOperationError(); } + + // Check for delegated agent-to-agent messages (marked with special prefix) + if (context.getMessage() != null) { + String userInput = extractTextFromMessage(context.getMessage()); + if (userInput.startsWith("#a2a-delegated#")) { + // This is a delegated message from agent-to-agent test - complete it + String actualContent = userInput.substring("#a2a-delegated#".length()); + agentEmitter.startWork(); + String response = "Handled locally: " + actualContent; + agentEmitter.addArtifact(List.of(new TextPart(response))); + agentEmitter.complete(); + return; + } + } + + // Default handler: echo back message or task if (context.getMessage() != null) { agentEmitter.sendMessage(context.getMessage()); } else { @@ -84,6 +131,127 @@ public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2A throw new UnsupportedOperationError(); } } + + /** + * Handles agent-to-agent communication testing. + * Detects "delegate:" prefix and forwards requests to another agent via client. + */ + private void handleAgentToAgentTest(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + try { + // Get transport protocol from ServerCallContext + ServerCallContext callContext = context.getCallContext(); + if (callContext == null) { + agentEmitter.fail(new InternalError("No call context available for agent-to-agent test")); + return; + } + + TransportProtocol transportProtocol = (TransportProtocol) callContext.getState().get(TRANSPORT_KEY); + if (transportProtocol == null) { + agentEmitter.fail(new InternalError("Transport type not set in call context")); + return; + } + + // Extract user message + String userInput = context.getUserInput("\n"); + if (userInput == null || userInput.isEmpty()) { + agentEmitter.fail(new InternalError("No user input received")); + return; + } + + // Check for delegation pattern + if (userInput.startsWith("delegate:")) { + handleDelegation(userInput, transportProtocol, agentEmitter); + } else { + handleLocally(userInput, agentEmitter); + } + } catch (Exception e) { + // Log the full stack trace to help debug intermittent failures + e.printStackTrace(); + agentEmitter.fail(new InternalError("Agent-to-agent test failed: " + e.getMessage())); + } + } + + /** + * Handles delegation by forwarding to another agent via client. + */ + private void handleDelegation(String userInput, TransportProtocol transportProtocol, + AgentEmitter agentEmitter) { + // Strip "delegate:" prefix + String delegatedContent = userInput.substring("delegate:".length()).trim(); + + // Create client for same transport + try (Client client = AgentToAgentClientFactory.createClient(agentCard, transportProtocol)) { + agentEmitter.startWork(); + + // Set up consumer to capture task result + CountDownLatch latch = new CountDownLatch(1); + AtomicReference resultRef = new AtomicReference<>(); + AtomicReference errorRef = new AtomicReference<>(); + + BiConsumer consumer = + AgentToAgentClientFactory.createTaskCaptureConsumer(resultRef, latch); + + // Delegate to another agent (new task on same server) + // Add a marker so the receiving agent knows to complete the task + Message delegatedMessage = A2A.toUserMessage("#a2a-delegated#" + delegatedContent); + client.sendMessage(delegatedMessage, List.of(consumer), error -> { + errorRef.set(error); + latch.countDown(); + }); + + // Wait for response + if (!latch.await(30, TimeUnit.SECONDS)) { + agentEmitter.fail(new InternalError("Timeout waiting for delegated response")); + return; + } + + Task delegatedResult = resultRef.get(); + + // Check for error only if we didn't get a successful result + // (errors can occur after completion due to stream cleanup) + if (delegatedResult == null && errorRef.get() != null) { + agentEmitter.fail(new InternalError("Delegation failed: " + errorRef.get().getMessage())); + return; + } + + if (delegatedResult == null) { + agentEmitter.fail(new InternalError("No result received from delegation")); + return; + } + + // Extract artifacts from delegated task and add to current task + // NOTE: We cannot use emitter.addTask(delegatedResult) because it has a different taskId + if (delegatedResult.artifacts() != null && !delegatedResult.artifacts().isEmpty()) { + for (Artifact artifact : delegatedResult.artifacts()) { + agentEmitter.addArtifact(artifact.parts()); + } + } + + // Complete current task + agentEmitter.complete(); + } catch (A2AClientException e) { + agentEmitter.fail(new InternalError("Failed to create client: " + e.getMessage())); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + agentEmitter.fail(new InternalError("Interrupted while waiting for response")); + } + } + + /** + * Handles request locally without delegation. + */ + private void handleLocally(String userInput, AgentEmitter agentEmitter) { + try { + agentEmitter.startWork(); + String response = "Handled locally: " + userInput; + agentEmitter.addArtifact(List.of(new TextPart(response))); + agentEmitter.complete(); + } catch (Exception e) { + // Defensive catch to ensure we always emit a final state + e.printStackTrace(); + agentEmitter.fail(new InternalError("Local handling failed: " + e.getMessage())); + } + } }; } diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java new file mode 100644 index 000000000..f3c06eb66 --- /dev/null +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java @@ -0,0 +1,119 @@ +package io.a2a.server.apps.common; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; + +import io.a2a.client.Client; +import io.a2a.client.ClientBuilder; +import io.a2a.client.ClientEvent; +import io.a2a.client.TaskEvent; +import io.a2a.client.TaskUpdateEvent; +import io.a2a.client.config.ClientConfig; +import io.a2a.client.transport.grpc.GrpcTransport; +import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; +import io.a2a.client.transport.jsonrpc.JSONRPCTransport; +import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import io.a2a.client.transport.rest.RestTransport; +import io.a2a.client.transport.rest.RestTransportConfigBuilder; +import io.a2a.spec.A2AClientException; +import io.a2a.spec.AgentCard; +import io.a2a.spec.Task; +import io.a2a.spec.TransportProtocol; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; + +/** + * Helper class for creating A2A clients for agent-to-agent communication testing. + * Uses inner classes to avoid class loading issues when transport dependencies aren't on the classpath. + */ +public class AgentToAgentClientFactory { + + /** + * Creates a BiConsumer that captures the final task state. + * This utility method is used by both test classes and agent executors to avoid code duplication. + * + * @param taskRef the AtomicReference to store the final task + * @param latch the CountDownLatch to signal completion + * @return a BiConsumer that captures completed tasks + */ + public static BiConsumer createTaskCaptureConsumer( + AtomicReference taskRef, CountDownLatch latch) { + return (event, agentCard) -> { + Task task = null; + if (event instanceof TaskEvent taskEvent) { + task = taskEvent.getTask(); + } else if (event instanceof TaskUpdateEvent taskUpdateEvent) { + task = taskUpdateEvent.getTask(); + } + + if (task != null && task.status().state().isFinal()) { + taskRef.set(task); + latch.countDown(); + } + }; + } + + /** + * Creates a client for the specified transport protocol. + * The agent card parameter already contains the correct local endpoint URLs + * configured by the test's AgentCardProducer. + * + * @param agentCard the agent card with correct local endpoints + * @param transportProtocol the transport protocol to use + * @return configured client + * @throws A2AClientException if client creation fails + */ + public static Client createClient(AgentCard agentCard, TransportProtocol transportProtocol) + throws A2AClientException { + ClientConfig clientConfig = ClientConfig.builder() + .setStreaming(false) + .build(); + + ClientBuilder clientBuilder = Client.builder(agentCard) + .clientConfig(clientConfig); + + ClientTransportEnhancer enhancer = switch (transportProtocol) { + case JSONRPC -> new JsonRpcClientEnhancer(); + case GRPC -> new GrpcClientEnhancer(); + case HTTP_JSON -> new RestClientEnhancer(); + default -> throw new IllegalArgumentException("Unsupported transport: " + transportProtocol); + }; + + enhancer.enhance(clientBuilder); + return clientBuilder.build(); + } + + /** + * The implementations of this interface are needed to avoid ClassNotFoundErrors for client transports that are + * not on the classpath. + */ + interface ClientTransportEnhancer { + void enhance(ClientBuilder clientBuilder); + } + + private static class GrpcClientEnhancer implements AgentToAgentClientFactory.ClientTransportEnhancer { + @Override + public void enhance(ClientBuilder clientBuilder) { + clientBuilder.withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder().channelFactory(target -> { + ManagedChannel channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build(); + return channel; + })); + } + } + + private static class JsonRpcClientEnhancer implements AgentToAgentClientFactory.ClientTransportEnhancer { + @Override + public void enhance(ClientBuilder clientBuilder) { + clientBuilder.withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()); + } + } + + private static class RestClientEnhancer implements AgentToAgentClientFactory.ClientTransportEnhancer { + @Override + public void enhance(ClientBuilder clientBuilder) { + clientBuilder.withTransport(RestTransport.class, new RestTransportConfigBuilder()); + } + } +} + 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 7a312a5d0..277a763cd 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 @@ -2,6 +2,7 @@ import static io.a2a.grpc.utils.ProtoUtils.FromProto; import static io.a2a.grpc.utils.ProtoUtils.ToProto; +import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; import java.util.HashMap; import java.util.HashSet; @@ -53,6 +54,7 @@ import io.a2a.spec.TaskNotFoundError; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskQueryParams; +import io.a2a.spec.TransportProtocol; import io.a2a.spec.UnsupportedOperationError; import io.a2a.spec.VersionNotSupportedError; import io.a2a.transport.grpc.context.GrpcContextKeys; @@ -403,7 +405,8 @@ private ServerCallContext createCallContext(StreamObserver responseObserv // This handles both CDI injection scenarios and test scenarios where callContextFactory is null User user = UnauthenticatedUser.INSTANCE; Map state = new HashMap<>(); - + state.put(TRANSPORT_KEY, TransportProtocol.GRPC); + // Enhanced gRPC context access - equivalent to Python's grpc.aio.ServicerContext // The A2AExtensionsInterceptor captures ServerCall + Metadata and stores them in gRPC Context // This provides proper equivalence to Python's ServicerContext for metadata access From 4808aff1cac2cea2e0ae5e2265cbb50712d369e8 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 18 Feb 2026 11:44:59 +0000 Subject: [PATCH 044/192] chore: Fix compile errors (#669) These were caused by opening https://github.com/a2aproject/a2a-java/pull/654 before https://github.com/a2aproject/a2a-java/pull/662 but merging 654 after 662 --- .../java/io/a2a/server/apps/common/AbstractA2AServerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 646451d6d..ae6b8443a 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 @@ -2476,7 +2476,7 @@ public void testAgentToAgentDelegation() throws Exception { Message delegationMessage = Message.builder() .taskId(delegationTaskId) .contextId("agent-to-agent-context") - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(new TextPart("delegate:What is 2+2?")) .build(); @@ -2538,7 +2538,7 @@ public void testAgentToAgentLocalHandling() throws Exception { Message localMessage = Message.builder() .taskId(localTaskId) .contextId("agent-to-agent-context") - .role(Message.Role.USER) + .role(Message.Role.ROLE_USER) .parts(new TextPart("Hello directly")) .build(); From 8946760077a332c595122baea7ee04cd8c023794 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Wed, 18 Feb 2026 14:16:06 +0100 Subject: [PATCH 045/192] feat!: Add SecurityRequirement to the domain API (#670) This replaces the `List>>` that was not properly serialized to JSON. Rename spec-grpc SecurityMapper to SecurityRequirementMapper.java This fixes #667 Signed-off-by: Jeff Mesnil --- .../jsonrpc/JSONRPCTransportTest.java | 5 +- .../interceptors/auth/AuthInterceptor.java | 8 +- .../auth/AuthInterceptorTest.java | 5 +- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 127 ++++++++++++++++++ .../SecurityRequirementSerializationTest.java | 85 ++++++++++++ .../io/a2a/grpc/mapper/AgentCardMapper.java | 2 +- .../io/a2a/grpc/mapper/AgentSkillMapper.java | 2 +- .../io/a2a/grpc/mapper/SecurityMapper.java | 110 --------------- .../mapper/SecurityRequirementMapper.java | 112 +++++++++++++++ .../java/io/a2a/grpc/utils/ToProtoTest.java | 6 +- spec/src/main/java/io/a2a/spec/AgentCard.java | 14 +- .../src/main/java/io/a2a/spec/AgentSkill.java | 11 +- .../java/io/a2a/spec/SecurityRequirement.java | 110 +++++++++++++++ 13 files changed, 465 insertions(+), 132 deletions(-) create mode 100644 jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityMapper.java create mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java create mode 100644 spec/src/main/java/io/a2a/spec/SecurityRequirement.java diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 012b373ff..0bd42a978 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -57,6 +57,7 @@ import io.a2a.spec.OpenIdConnectSecurityScheme; import io.a2a.spec.Part; import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.SecurityRequirement; import io.a2a.spec.SecurityScheme; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; @@ -376,9 +377,9 @@ public void testA2AClientGetExtendedAgentCard() throws Exception { assertNotNull(securitySchemes); OpenIdConnectSecurityScheme google = (OpenIdConnectSecurityScheme) securitySchemes.get("google"); assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.openIdConnectUrl()); - List>> security = agentCard.securityRequirements(); + List security = agentCard.securityRequirements(); assertEquals(1, security.size()); - Map> securityMap = security.get(0); + Map> securityMap = security.get(0).schemes(); List scopes = securityMap.get("google"); List expectedScopes = List.of("openid", "profile", "email"); assertEquals(expectedScopes, scopes); diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java index 6cfc322da..2b073d413 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java @@ -13,6 +13,7 @@ import io.a2a.spec.HTTPAuthSecurityScheme; import io.a2a.spec.OAuth2SecurityScheme; import io.a2a.spec.OpenIdConnectSecurityScheme; +import io.a2a.spec.SecurityRequirement; import io.a2a.spec.SecurityScheme; import org.jspecify.annotations.Nullable; @@ -38,8 +39,11 @@ public PayloadAndHeaders intercept(String methodName, @Nullable Object payload, if (agentCard == null || agentCard.securityRequirements()== null || agentCard.securitySchemes() == null) { return new PayloadAndHeaders(payload, updatedHeaders); } - for (Map> requirement : agentCard.securityRequirements()) { - for (String securitySchemeName : requirement.keySet()) { + for (SecurityRequirement requirement : agentCard.securityRequirements()) { + if (requirement == null) { + continue; + } + for (String securitySchemeName : requirement.schemes().keySet()) { String credential = credentialService.getCredential(securitySchemeName, clientCallContext); if (credential != null && agentCard.securitySchemes().containsKey(securitySchemeName)) { SecurityScheme securityScheme = agentCard.securitySchemes().get(securitySchemeName); 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 9ea69f354..ed29dafab 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 @@ -18,6 +18,7 @@ import io.a2a.spec.OAuth2SecurityScheme; import io.a2a.spec.OAuthFlows; import io.a2a.spec.OpenIdConnectSecurityScheme; +import io.a2a.spec.SecurityRequirement; import io.a2a.spec.SecurityScheme; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -235,7 +236,7 @@ void testAvailableSecuritySchemeNotInAgentCardSecuritySchemes() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .securityRequirements(List.of(Map.of(schemeName, List.of()))) + .securityRequirements(List.of(SecurityRequirement.builder().scheme(schemeName, List.of()).build())) .securitySchemes(Map.of()) // no security schemes .build(); @@ -321,7 +322,7 @@ private AgentCard createAgentCard(String schemeName, SecurityScheme securitySche .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .securityRequirements(List.of(Map.of(schemeName, List.of()))) + .securityRequirements(List.of(SecurityRequirement.builder().scheme(schemeName, List.of()).build())) .securitySchemes(Map.of(schemeName, securityScheme)) .build(); } diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index 29aa36ae8..4b473712d 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -16,12 +16,17 @@ import static io.a2a.spec.FilePart.FILE; import static io.a2a.spec.TextPart.TEXT; import static java.lang.String.format; +import static java.util.Collections.emptyMap; 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.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -55,6 +60,7 @@ import io.a2a.spec.OpenIdConnectSecurityScheme; import io.a2a.spec.Part; import io.a2a.spec.PushNotificationNotSupportedError; +import io.a2a.spec.SecurityRequirement; import io.a2a.spec.SecurityScheme; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; @@ -76,8 +82,10 @@ private static GsonBuilder createBaseGsonBuilder() { return new GsonBuilder() .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) + .registerTypeAdapter(SecurityRequirement.class, new SecurityRequirementTypeAdapter()) .registerTypeHierarchyAdapter(A2AError.class, new A2AErrorTypeAdapter()) .registerTypeHierarchyAdapter(FileContent.class, new FileContentTypeAdapter()); + } /** @@ -841,4 +849,123 @@ SecurityScheme read(JsonReader in) throws java.io.IOException { }; } } + + /** + * Gson TypeAdapter for serializing and deserializing {@link SecurityRequirement}. + *

        + * This adapter handles the JSON structure where a SecurityRequirement is represented + * as an object with a "schemes" field containing a map of security scheme names to + * StringList objects (matching the protobuf representation). + *

        + * Serialization format: + *

        {@code
        +     * {
        +     *   "schemes": {
        +     *     "oauth2": { "list": ["read", "write"] },
        +     *     "apiKey": { "list": [] }
        +     *   }
        +     * }
        +     * }
        + * + * @see SecurityRequirement + */ + static class SecurityRequirementTypeAdapter extends TypeAdapter { + + private static final String SCHEMES_FIELD = "schemes"; + private static final String LIST_FIELD = "list"; + + @Override + public void write(JsonWriter out, SecurityRequirement value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + + out.beginObject(); + out.name(SCHEMES_FIELD); + + Map> schemes = value.schemes(); + if (schemes == null || schemes.isEmpty()) { + out.beginObject(); + out.endObject(); + } else { + out.beginObject(); + for (Map.Entry> entry : schemes.entrySet()) { + out.name(entry.getKey()); + out.beginObject(); + out.name(LIST_FIELD); + out.beginArray(); + List scopes = entry.getValue(); + if (scopes != null) { + for (String scope : scopes) { + out.value(scope); + } + } + out.endArray(); + out.endObject(); + } + out.endObject(); + } + + out.endObject(); + } + + @Override + public @Nullable SecurityRequirement read(JsonReader in) throws java.io.IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + Map> schemes = emptyMap(); + + in.beginObject(); + while (in.hasNext()) { + String fieldName = in.nextName(); + if (SCHEMES_FIELD.equals(fieldName)) { + schemes = readSchemesMap(in); + } else { + in.skipValue(); + } + } + in.endObject(); + + return new SecurityRequirement(schemes); + } + + private Map> readSchemesMap(JsonReader in) throws java.io.IOException { + Map> schemes = new LinkedHashMap<>(); + + in.beginObject(); + while (in.hasNext()) { + String schemeName = in.nextName(); + List scopes = readStringList(in); + schemes.put(schemeName, scopes); + } + in.endObject(); + + return schemes; + } + + private List readStringList(JsonReader in) throws java.io.IOException { + List scopes = new ArrayList<>(); + + in.beginObject(); + while (in.hasNext()) { + String fieldName = in.nextName(); + if (LIST_FIELD.equals(fieldName)) { + in.beginArray(); + while (in.hasNext()) { + scopes.add(in.nextString()); + } + in.endArray(); + } else { + in.skipValue(); + } + } + in.endObject(); + + return scopes; + } + } } diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java new file mode 100644 index 000000000..b71809367 --- /dev/null +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java @@ -0,0 +1,85 @@ +package io.a2a.jsonrpc.common.json; + +import static java.util.Collections.emptyMap; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import io.a2a.spec.SecurityRequirement; + +/** + * Tests for SecurityRequirement serialization and deserialization with JSON. + */ +class SecurityRequirementSerializationTest { + + @Test + void testSecurityRequirementSerializationWithSingleScheme() throws JsonProcessingException { + SecurityRequirement requirement = SecurityRequirement.builder() + .scheme("oauth2", List.of("read", "write")) + .build(); + + String json = JsonUtil.toJson(requirement); + assertNotNull(json); + + String expected = """ + {"schemes":{"oauth2":{"list":["read","write"]}}}"""; + assertEquals(expected, json); + + SecurityRequirement deserialized = JsonUtil.fromJson(json, SecurityRequirement.class); + assertEquals(requirement, deserialized); + } + + @Test + void testSecurityRequirementSerializationWithMultipleSchemes() throws JsonProcessingException { + SecurityRequirement requirement = SecurityRequirement.builder() + .scheme("oauth2", List.of("profile")) + .scheme("apiKey", List.of()) + .build(); + + String json = JsonUtil.toJson(requirement); + assertNotNull(json); + + String expected = """ + {"schemes":{"oauth2":{"list":["profile"]},"apiKey":{"list":[]}}}"""; + assertEquals(expected, json); + + SecurityRequirement deserialized = JsonUtil.fromJson(json, SecurityRequirement.class); + assertEquals(requirement, deserialized); + } + + @Test + void testSecurityRequirementSerializationWithEmptyScopes() throws JsonProcessingException { + SecurityRequirement requirement = SecurityRequirement.builder() + .scheme("apiKey", List.of()) + .build(); + + String json = JsonUtil.toJson(requirement); + assertNotNull(json); + + String expected = """ + {"schemes":{"apiKey":{"list":[]}}}"""; + assertEquals(expected, json); + + SecurityRequirement deserialized = JsonUtil.fromJson(json, SecurityRequirement.class); + assertEquals(requirement, deserialized); + } + + @Test + void testSecurityRequirementSerializationWithNullSchemes() throws JsonProcessingException { + SecurityRequirement requirement = new SecurityRequirement(emptyMap()); + + String json = JsonUtil.toJson(requirement); + + assertNotNull(json); + String expected = """ + {"schemes":{}}"""; + assertEquals(expected, json); + + SecurityRequirement deserialized = JsonUtil.fromJson(json, SecurityRequirement.class); + assertNotNull(deserialized); + assertEquals(requirement, deserialized); + } +} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java index 97b9ed0a1..268d54714 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java @@ -14,7 +14,7 @@ AgentCapabilitiesMapper.class, AgentSkillMapper.class, SecuritySchemeMapper.class, - SecurityMapper.class, + SecurityRequirementMapper.class, AgentInterfaceMapper.class, AgentCardSignatureMapper.class }) diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java index daa911867..d56c572b8 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java @@ -8,7 +8,7 @@ */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = SecurityMapper.class) + uses = SecurityRequirementMapper.class) public interface AgentSkillMapper { AgentSkillMapper INSTANCE = A2AMappers.getMapper(AgentSkillMapper.class); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityMapper.java deleted file mode 100644 index e00e5f70f..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityMapper.java +++ /dev/null @@ -1,110 +0,0 @@ -package io.a2a.grpc.mapper; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.google.protobuf.ProtocolStringList; -import io.a2a.grpc.SecurityRequirement; -import io.a2a.grpc.StringList; -import org.mapstruct.Mapper; - -/** - * Mapper between domain security requirements and protobuf SecurityRequirement messages. - *

        - * Domain representation: {@code List>>} where each map represents - * one security option with scheme names as keys and scopes as values. - *

        - * Proto representation: {@code repeated SecurityRequirement} where each SecurityRequirement has - * {@code map schemes}. - *

        - * Example: A security requirement that allows either OAuth2 with read/write scopes OR API Key: - *

        - * Domain: [
        - *   {"oauth2": ["read", "write"]},
        - *   {"apiKey": []}
        - * ]
        - * Proto: [
        - *   SecurityRequirement{schemes: {"oauth2": StringList{values: ["read", "write"]}}},
        - *   SecurityRequirement{schemes: {"apiKey": StringList{values: []}}}
        - * ]
        - * 
        - *

        - * Manual Implementation Required: Handles complex nested structure ({@code List>>} ↔ - * {@code repeated SecurityRequirement} with {@code map}) requiring manual iteration and StringList wrapper handling. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface SecurityMapper { - - SecurityMapper INSTANCE = A2AMappers.getMapper(SecurityMapper.class); - - /** - * Converts a single domain security requirement map to a proto SecurityRequirement message. - *

        - * MapStruct will call this method for each element when mapping the list. - * - * @param schemeMap map of scheme names to scopes - * @return SecurityRequirement proto message, or null if input is null - */ - default SecurityRequirement mapSecurityItem(Map> schemeMap) { - if (schemeMap == null) { - return null; - } - - SecurityRequirement.Builder securityBuilder = SecurityRequirement.newBuilder(); - for (Map.Entry> entry : schemeMap.entrySet()) { - StringList.Builder stringListBuilder = StringList.newBuilder(); - if (entry.getValue() != null) { - stringListBuilder.addAllList(entry.getValue()); - } - securityBuilder.putSchemes(entry.getKey(), stringListBuilder.build()); - } - return securityBuilder.build(); - } - - /** - * Converts domain security requirements to proto SecurityRequirement messages. - *

        - * Each Map in the domain list becomes one SecurityRequirement message in proto, representing - * one way to satisfy the security requirements (OR relationship between list items). - * - * @param domainSecurity list of maps representing security requirement options - * @return list of SecurityRequirement proto messages, or null if input is null - */ - default List toProto(List>> domainSecurity) { - if (domainSecurity == null) { - return null; - } - - List protoList = new ArrayList<>(domainSecurity.size()); - for (Map> schemeMap : domainSecurity) { - protoList.add(mapSecurityItem(schemeMap)); - } - return protoList; - } - - /** - * Converts proto SecurityRequirement messages to domain security requirements. - * - * @param protoSecurity list of SecurityRequirement proto messages - * @return list of maps representing security requirement options, or null if input is null - */ - default List>> fromProto(List protoSecurity) { - if (protoSecurity == null) { - return null; - } - - List>> domainList = new ArrayList<>(protoSecurity.size()); - for (SecurityRequirement security : protoSecurity) { - Map> schemeMap = new LinkedHashMap<>(); - for (Map.Entry entry : security.getSchemesMap().entrySet()) { - ProtocolStringList listList = entry.getValue().getListList(); - List values = new ArrayList<>(listList); - schemeMap.put(entry.getKey(), values); - } - domainList.add(schemeMap); - } - return domainList; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java new file mode 100644 index 000000000..8f9f98fe6 --- /dev/null +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java @@ -0,0 +1,112 @@ +package io.a2a.grpc.mapper; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.google.protobuf.ProtocolStringList; +import io.a2a.grpc.StringList; +import org.mapstruct.Mapper; + +/** + * Mapper between domain security requirements and protobuf SecurityRequirement messages. + *

        + * Domain representation: {@code List} where each SecurityRequirement contains + * a schemes map with scheme names as keys and scopes as values. + *

        + * Proto representation: {@code repeated SecurityRequirement} where each SecurityRequirement has + * {@code map schemes}. + *

        + * Example: A security requirement that allows either OAuth2 with read/write scopes OR API Key: + *

        + * Domain: [
        + *   SecurityRequirement{schemes: {"oauth2": ["read", "write"]}},
        + *   SecurityRequirement{schemes: {"apiKey": []}}
        + * ]
        + * Proto: [
        + *   SecurityRequirement{schemes: {"oauth2": StringList{values: ["read", "write"]}}},
        + *   SecurityRequirement{schemes: {"apiKey": StringList{values: []}}}
        + * ]
        + * 
        + *

        + * Manual Implementation Required: Handles complex nested structure ({@code List} ↔ + * {@code repeated SecurityRequirement} with {@code map}) requiring manual iteration and StringList wrapper handling. + */ +@Mapper(config = A2AProtoMapperConfig.class) +public interface SecurityRequirementMapper { + + SecurityRequirementMapper INSTANCE = A2AMappers.getMapper(SecurityRequirementMapper.class); + + /** + * Converts a single domain SecurityRequirement to a proto SecurityRequirement message. + *

        + * MapStruct will call this method for each element when mapping the list. + * + * @param domainRequirement domain SecurityRequirement with schemes map + * @return SecurityRequirement proto message, or null if input is null + */ + default io.a2a.grpc.SecurityRequirement mapSecurityRequirement(io.a2a.spec.SecurityRequirement domainRequirement) { + if (domainRequirement == null) { + return null; + } + + io.a2a.grpc.SecurityRequirement.Builder securityBuilder = io.a2a.grpc.SecurityRequirement.newBuilder(); + Map> schemes = domainRequirement.schemes(); + if (schemes != null) { + for (Map.Entry> entry : schemes.entrySet()) { + StringList.Builder stringListBuilder = StringList.newBuilder(); + if (entry.getValue() != null) { + stringListBuilder.addAllList(entry.getValue()); + } + securityBuilder.putSchemes(entry.getKey(), stringListBuilder.build()); + } + } + return securityBuilder.build(); + } + + /** + * Converts domain security requirements to proto SecurityRequirement messages. + *

        + * Each SecurityRequirement in the domain list becomes one SecurityRequirement message in proto, + * representing one way to satisfy the security requirements (OR relationship between list items). + * + * @param domainSecurity list of SecurityRequirement domain objects + * @return list of SecurityRequirement proto messages, or null if input is null + */ + default List toProto(List domainSecurity) { + if (domainSecurity == null) { + return null; + } + + List protoList = new ArrayList<>(domainSecurity.size()); + for (io.a2a.spec.SecurityRequirement requirement : domainSecurity) { + protoList.add(mapSecurityRequirement(requirement)); + } + return protoList; + } + + /** + * Converts proto SecurityRequirement messages to domain security requirements. + * + * @param protoSecurity list of SecurityRequirement proto messages + * @return list of SecurityRequirement domain objects, or null if input is null + */ + default List fromProto(List protoSecurity) { + if (protoSecurity == null) { + return null; + } + + List domainList = new ArrayList<>(protoSecurity.size()); + for (io.a2a.grpc.SecurityRequirement security : protoSecurity) { + Map> schemeMap = new LinkedHashMap<>(); + for (Map.Entry entry : security.getSchemesMap().entrySet()) { + ProtocolStringList listList = entry.getValue().getListList(); + List values = new ArrayList<>(listList); + schemeMap.put(entry.getKey(), values); + } + domainList.add(new io.a2a.spec.SecurityRequirement(schemeMap)); + } + return domainList; + } +} diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index fc8771736..b857cb6b1 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -17,6 +17,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.AgentSkill; +import io.a2a.spec.SecurityRequirement; import io.a2a.spec.Artifact; import io.a2a.spec.AuthenticationInfo; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; @@ -100,7 +101,10 @@ public void convertAgentCard() { .build())) // .iconUrl("http://example.com/icon.svg") .securitySchemes(Map.of("basic", HTTPAuthSecurityScheme.builder().scheme("basic").description("Basic Auth").build())) - .securityRequirements(List.of(Map.of("oauth", List.of("read")))) + .securityRequirements(List.of(SecurityRequirement.builder() + .scheme("oauth", + List.of("read")) + .build())) .build(); result = ProtoUtils.ToProto.agentCard(agentCard); assertEquals("Hello World Agent", result.getName()); diff --git a/spec/src/main/java/io/a2a/spec/AgentCard.java b/spec/src/main/java/io/a2a/spec/AgentCard.java index dec9ce722..4bfca0284 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCard.java +++ b/spec/src/main/java/io/a2a/spec/AgentCard.java @@ -1,11 +1,11 @@ package io.a2a.spec; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import io.a2a.util.Assert; -import java.util.Collections; import org.jspecify.annotations.Nullable; /** @@ -53,7 +53,7 @@ public record AgentCard( List defaultOutputModes, List skills, @Nullable Map securitySchemes, - @Nullable List>> securityRequirements, + @Nullable List securityRequirements, @Nullable String iconUrl, List supportedInterfaces, @Nullable List signatures) { @@ -152,7 +152,7 @@ public static class Builder { private @Nullable List defaultOutputModes; private @Nullable List skills; private @Nullable Map securitySchemes; - private @Nullable List>> securityRequirements; + private @Nullable List securityRequirements; private @Nullable String iconUrl; private @Nullable List supportedInterfaces; private @Nullable List signatures; @@ -182,7 +182,7 @@ private Builder(AgentCard card) { this.defaultOutputModes = card.defaultOutputModes != null ? new ArrayList<>(card.defaultOutputModes) : Collections.emptyList(); this.skills = card.skills != null ? new ArrayList<>(card.skills) : Collections.emptyList(); this.securitySchemes = card.securitySchemes != null ? Map.copyOf(card.securitySchemes) : Collections.emptyMap(); - this.securityRequirements = card.securityRequirements != null ? new ArrayList<>(card.securityRequirements) :Collections.emptyList(); + this.securityRequirements = card.securityRequirements != null ? new ArrayList<>(card.securityRequirements) : Collections.emptyList(); this.iconUrl = card.iconUrl; this.supportedInterfaces = card.supportedInterfaces != null ? new ArrayList<>(card.supportedInterfaces) : Collections.emptyList(); this.signatures = card.signatures != null ? new ArrayList<>(card.signatures) : null; @@ -316,14 +316,12 @@ public Builder securitySchemes(Map securitySchemes) { /** * Sets the list of security requirements for accessing the agent. - *

        - * Each entry in the list represents an alternative security requirement, - * where each map contains scheme names and their required scopes. * * @param securityRequirements the list of security requirements (optional) * @return this builder for method chaining + * @see SecurityRequirement */ - public Builder securityRequirements(List>> securityRequirements) { + public Builder securityRequirements(List securityRequirements) { this.securityRequirements = securityRequirements; return this; } diff --git a/spec/src/main/java/io/a2a/spec/AgentSkill.java b/spec/src/main/java/io/a2a/spec/AgentSkill.java index 6d60baec4..2bddf57bf 100644 --- a/spec/src/main/java/io/a2a/spec/AgentSkill.java +++ b/spec/src/main/java/io/a2a/spec/AgentSkill.java @@ -1,7 +1,6 @@ package io.a2a.spec; import java.util.List; -import java.util.Map; import io.a2a.util.Assert; import org.jspecify.annotations.Nullable; @@ -42,7 +41,7 @@ */ public record AgentSkill(String id, String name, String description, List tags, @Nullable List examples, @Nullable List inputModes, @Nullable List outputModes, - @Nullable List>> securityRequirements) { + @Nullable List securityRequirements) { /** * Compact constructor that validates required fields. @@ -105,7 +104,7 @@ public static class Builder { private @Nullable List examples; private @Nullable List inputModes; private @Nullable List outputModes; - private @Nullable List>> securityRequirements; + private @Nullable List securityRequirements; /** * Creates a new Builder with all fields unset. @@ -215,12 +214,14 @@ public Builder outputModes(List outputModes) { *

        * Security requirements override or supplement the agent-level security * defined in the AgentCard. Each entry represents an alternative security - * requirement, where each map contains scheme names and their required scopes. + * requirement (OR relationship). Schemes within a single SecurityRequirement + * must all be satisfied (AND relationship). * * @param securityRequirements list of security requirements (optional) * @return this builder for method chaining + * @see SecurityRequirement */ - public Builder securityRequirements(List>> securityRequirements) { + public Builder securityRequirements(List securityRequirements) { this.securityRequirements = securityRequirements; return this; } diff --git a/spec/src/main/java/io/a2a/spec/SecurityRequirement.java b/spec/src/main/java/io/a2a/spec/SecurityRequirement.java new file mode 100644 index 000000000..1a3729369 --- /dev/null +++ b/spec/src/main/java/io/a2a/spec/SecurityRequirement.java @@ -0,0 +1,110 @@ +package io.a2a.spec; + +import static java.util.Collections.unmodifiableMap; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import io.a2a.util.Assert; + +/** + * Represents a security requirement in the A2A Protocol. + *

        + * A SecurityRequirement defines which security schemes must be satisfied to access an agent or skill. + * It maps security scheme names to lists of required scopes. When multiple scheme entries are present + * in a single SecurityRequirement, ALL must be satisfied (AND relationship). When multiple + * SecurityRequirements are present in a list, any ONE may be satisfied (OR relationship). + *

        + * This class corresponds to the {@code SecurityRequirement} type in the A2A Protocol specification, + * which contains a {@code schemes} field mapping scheme names to scope arrays. + *

        + * Example usage: + *

        {@code
        + * // Single OAuth2 requirement with specific scopes
        + * SecurityRequirement oauth2Req = SecurityRequirement.builder()
        + *     .scheme("oauth2", List.of("read", "write"))
        + *     .build();
        + *
        + * // API key requirement with no scopes
        + * SecurityRequirement apiKeyReq = SecurityRequirement.builder()
        + *     .scheme("apiKey", List.of())
        + *     .build();
        + *
        + * // Combined requirement: both OAuth2 AND API key required
        + * SecurityRequirement combinedReq = SecurityRequirement.builder()
        + *     .scheme("oauth2", List.of("profile"))
        + *     .scheme("apiKey", List.of())
        + *     .build();
        + * }
        + * + * @param schemes map of security scheme names to lists of required scopes + * @see SecurityScheme + * @see AgentCard#securityRequirements() + * @see AgentSkill#securityRequirements() + * @see A2A Protocol Specification + */ +public record SecurityRequirement(Map> schemes) { + + /** + * Creates a SecurityRequirement with the specified schemes map. + * + * @param schemes map of security scheme names to lists of required scopes + */ + public SecurityRequirement { + Assert.checkNotNullParam("schemes", schemes); + schemes = unmodifiableMap(new LinkedHashMap<>(schemes)); + } + + /** + * Creates a new Builder for constructing SecurityRequirement instances. + * + * @return a new builder instance + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for constructing immutable {@link SecurityRequirement} instances. + *

        + * Example usage: + *

        {@code
        +     * SecurityRequirement requirement = SecurityRequirement.builder()
        +     *     .scheme("oauth2", List.of("read", "write"))
        +     *     .scheme("apiKey", List.of())
        +     *     .build();
        +     * }
        + */ + public static class Builder { + + private final Map> schemes = new LinkedHashMap<>(); + + /** + * Creates a new Builder with an empty schemes map. + */ + private Builder() { + } + + /** + * Adds a security scheme with its required scopes. + * + * @param schemeName the name of the security scheme (must match a key in securitySchemes) + * @param scopes the list of required scopes for this scheme (empty list for no specific scopes) + * @return this builder for method chaining + */ + public Builder scheme(String schemeName, List scopes) { + this.schemes.put(schemeName, List.copyOf(scopes)); + return this; + } + + /** + * Builds an immutable {@link SecurityRequirement} from the current builder state. + * + * @return a new SecurityRequirement instance + */ + public SecurityRequirement build() { + return new SecurityRequirement(schemes); + } + } +} From e8fd7f235b4ceaea9f83e6e7c390e456f610c20f Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 18 Feb 2026 14:02:03 +0000 Subject: [PATCH 046/192] fix: flaky testInputRequiredWorkflow test (#671) --- .../io/a2a/server/apps/common/AbstractA2AServerTest.java | 6 +++++- .../io/a2a/server/apps/common/AgentExecutorProducer.java | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) 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 ae6b8443a..7ecd64cac 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 @@ -1538,6 +1538,7 @@ private boolean awaitChildQueueCountStable(String taskId, int expectedCount, lon @Timeout(value = 1, unit = TimeUnit.MINUTES) public void testInputRequiredWorkflow() throws Exception { String inputRequiredTaskId = "input-required-test-" + java.util.UUID.randomUUID(); + boolean taskCreated = false; try { // 1. Send initial message - AgentExecutor will transition task to INPUT_REQUIRED Message initialMessage = Message.builder(MESSAGE) @@ -1572,6 +1573,7 @@ public void testInputRequiredWorkflow() throws Exception { assertTrue(initialLatch.await(10, TimeUnit.SECONDS)); assertFalse(initialUnexpectedEvent.get()); assertEquals(TaskState.TASK_STATE_INPUT_REQUIRED, initialState.get()); + taskCreated = true; // 2. Send input message - AgentExecutor will complete the task Message inputMessage = Message.builder(MESSAGE) @@ -1608,7 +1610,9 @@ public void testInputRequiredWorkflow() throws Exception { assertEquals(TaskState.TASK_STATE_COMPLETED, completedState.get()); } finally { - deleteTaskInTaskStore(inputRequiredTaskId); + if (taskCreated) { + deleteTaskInTaskStore(inputRequiredTaskId); + } } } 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 d62391bf8..b82041143 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 @@ -79,7 +79,9 @@ public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2 if (taskId != null && taskId.startsWith("input-required-test")) { // First call: context.getTask() == null (new task) if (context.getTask() == null) { - agentEmitter.startWork(); + // Go directly to INPUT_REQUIRED without intermediate WORKING state + // This avoids race condition where blocking call interrupts on WORKING + // before INPUT_REQUIRED is persisted to TaskStore agentEmitter.requiresInput(agentEmitter.newAgentMessage( List.of(new TextPart("Please provide additional information")), context.getMessage().metadata())); @@ -91,7 +93,8 @@ public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2 throw new InvalidParamsError("We didn't get the expected input"); } // Second call: context.getTask() != null (input provided) - agentEmitter.startWork(); + // Go directly to COMPLETED without intermediate WORKING state + // This avoids the same race condition as the first call agentEmitter.complete(); return; } From 5a48d7b6e8baaf4db0780afb74c5ea7d4a76919c Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 18 Feb 2026 17:11:05 +0000 Subject: [PATCH 047/192] fix: flaky Agent to Agent tests (#672) --- .../apps/common/AbstractA2AServerTest.java | 2 +- .../apps/common/AgentExecutorProducer.java | 61 ++++++++++--------- 2 files changed, 32 insertions(+), 31 deletions(-) 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 7ecd64cac..75ba229ea 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 @@ -2491,7 +2491,7 @@ public void testAgentToAgentDelegation() throws Exception { BiConsumer delegationConsumer = AgentToAgentClientFactory.createTaskCaptureConsumer(delegationResultRef, delegationLatch); - getClient().sendMessage(delegationMessage, List.of(delegationConsumer), error -> { + getNonStreamingClient().sendMessage(delegationMessage, List.of(delegationConsumer), error -> { delegationErrorRef.set(error); delegationLatch.countDown(); }); 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 b82041143..1db5f2d78 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 @@ -3,10 +3,7 @@ import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; @@ -176,49 +173,56 @@ private void handleAgentToAgentTest(RequestContext context, AgentEmitter agentEm /** * Handles delegation by forwarding to another agent via client. + *

        + * Uses blocking client call (streaming=false) which should return the final task state + * synchronously without requiring async callbacks and latches. This simplified approach + * avoids race conditions between event consumption and callback invocation. */ private void handleDelegation(String userInput, TransportProtocol transportProtocol, AgentEmitter agentEmitter) { // Strip "delegate:" prefix String delegatedContent = userInput.substring("delegate:".length()).trim(); - // Create client for same transport + // Create client for same transport (streaming=false for blocking behavior) try (Client client = AgentToAgentClientFactory.createClient(agentCard, transportProtocol)) { agentEmitter.startWork(); - // Set up consumer to capture task result - CountDownLatch latch = new CountDownLatch(1); - AtomicReference resultRef = new AtomicReference<>(); - AtomicReference errorRef = new AtomicReference<>(); - - BiConsumer consumer = - AgentToAgentClientFactory.createTaskCaptureConsumer(resultRef, latch); + // Store the result task from blocking call + AtomicReference taskRef = new AtomicReference<>(); // Delegate to another agent (new task on same server) // Add a marker so the receiving agent knows to complete the task Message delegatedMessage = A2A.toUserMessage("#a2a-delegated#" + delegatedContent); - client.sendMessage(delegatedMessage, List.of(consumer), error -> { - errorRef.set(error); - latch.countDown(); - }); - // Wait for response - if (!latch.await(30, TimeUnit.SECONDS)) { - agentEmitter.fail(new InternalError("Timeout waiting for delegated response")); - return; - } + // Blocking call should return final task synchronously + client.sendMessage(delegatedMessage, List.of((event, card) -> { + if (event instanceof TaskEvent te) { + taskRef.set(te.getTask()); + } else if (event instanceof TaskUpdateEvent tue) { + taskRef.set(tue.getTask()); + } + }), null); - Task delegatedResult = resultRef.get(); + // Blocking call should have completed before returning + Task delegatedResult = taskRef.get(); - // Check for error only if we didn't get a successful result - // (errors can occur after completion due to stream cleanup) - if (delegatedResult == null && errorRef.get() != null) { - agentEmitter.fail(new InternalError("Delegation failed: " + errorRef.get().getMessage())); + if (delegatedResult == null) { + agentEmitter.fail(new InternalError("No result received from blocking delegation call")); return; } - if (delegatedResult == null) { - agentEmitter.fail(new InternalError("No result received from delegation")); + // DIAGNOSTIC: Check if task is actually final + // If blocking call returns non-final task, it indicates a server-side race condition + if (!delegatedResult.status().state().isFinal()) { + String diagnostic = String.format( + "RACE CONDITION DETECTED: Blocking call returned non-final task! " + + "State: %s, TaskId: %s, Artifacts: %d. " + + "This indicates DefaultRequestHandler wait logic failed to synchronize with MainEventBusProcessor.", + delegatedResult.status().state(), + delegatedResult.id(), + delegatedResult.artifacts() != null ? delegatedResult.artifacts().size() : 0); + System.err.println(diagnostic); // Also print to stderr for CI visibility + agentEmitter.fail(new InternalError(diagnostic)); return; } @@ -234,9 +238,6 @@ private void handleDelegation(String userInput, TransportProtocol transportProto agentEmitter.complete(); } catch (A2AClientException e) { agentEmitter.fail(new InternalError("Failed to create client: " + e.getMessage())); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - agentEmitter.fail(new InternalError("Interrupted while waiting for response")); } } From c6a3406e8f5e3b8ccfd491db11531d0fa7499d30 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Wed, 18 Feb 2026 18:11:40 +0100 Subject: [PATCH 048/192] feat: Move the sendMessage with a MessageSendParams to the AbstractClient (#665) and made it public. Thought it might not be widely used, it allows full control of the parameters sent by the request (including the tenant). This fixes #663 Signed-off-by: Jeff Mesnil --- .../java/io/a2a/client/AbstractClient.java | 21 +++++ .../src/main/java/io/a2a/client/Client.java | 77 +++++++++---------- 2 files changed, 59 insertions(+), 39 deletions(-) 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 c3c8c648f..27cbadc7d 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java @@ -17,6 +17,7 @@ import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; +import io.a2a.spec.MessageSendParams; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; @@ -160,6 +161,26 @@ public abstract void sendMessage(@NonNull Message request, @Nullable Map metadata, @Nullable ClientCallContext context) throws A2AClientException; + /** + * Send a message to the remote agent. This method will automatically use + * the streaming or non-streaming approach as determined by the server's + * agent card and the client configuration. The specified client consumers + * will be used to handle messages, tasks, and update events received + * from the remote agent. The specified streaming error handler will be used + * if an error occurs during streaming. The configured client push notification + * configuration will get used for streaming. + * + * @param params the request parameters + * @param consumers a list of consumers to pass responses from the remote agent to + * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs + * @param context optional client call context for the request + * @throws A2AClientException if sending the message fails for any reason + */ + public abstract void sendMessage(@NonNull MessageSendParams params, + @NonNull List> consumers, + @Nullable Consumer streamingErrorHandler, + @Nullable ClientCallContext context) throws A2AClientException; + /** * Retrieve the current state and history of a specific 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 e60cac4e5..70ed9cf18 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -234,7 +234,13 @@ public void sendMessage(@NonNull Message request, @NonNull List> consumers, @Nullable Consumer streamingErrorHandler, @Nullable ClientCallContext context) throws A2AClientException { - MessageSendParams messageSendParams = getMessageSendParams(request, clientConfig); + MessageSendConfiguration messageSendConfiguration = createMessageSendConfiguration(clientConfig.getPushNotificationConfig()); + + MessageSendParams messageSendParams = MessageSendParams.builder() + .message(request) + .configuration(messageSendConfiguration) + .metadata(clientConfig.getMetadata()) + .build(); sendMessage(messageSendParams, consumers, streamingErrorHandler, context); } @@ -289,7 +295,6 @@ public void sendMessage(@NonNull Message request, @Nullable Map metadata, @Nullable ClientCallContext context) throws A2AClientException { MessageSendConfiguration messageSendConfiguration = createMessageSendConfiguration(pushNotificationConfiguration); - MessageSendParams messageSendParams = MessageSendParams.builder() .message(request) .configuration(messageSendConfiguration) @@ -299,6 +304,37 @@ public void sendMessage(@NonNull Message request, sendMessage(messageSendParams, consumers, streamingErrorHandler, context); } + @Override + public void sendMessage(@NonNull MessageSendParams messageSendParams, + @NonNull List> consumers, + @Nullable Consumer streamingErrorHandler, + @Nullable ClientCallContext context) throws A2AClientException { + if (! clientConfig.isStreaming() || ! agentCard.capabilities().streaming()) { + EventKind eventKind = clientTransport.sendMessage(messageSendParams, context); + ClientEvent clientEvent; + if (eventKind instanceof Task task) { + clientEvent = new TaskEvent(task); + } else { + // must be a message + clientEvent = new MessageEvent((Message) eventKind); + } + consume(clientEvent, agentCard, consumers); + } else { + ClientTaskManager tracker = new ClientTaskManager(); + Consumer overriddenErrorHandler = getOverriddenErrorHandler(streamingErrorHandler); + Consumer eventHandler = event -> { + try { + ClientEvent clientEvent = getClientEvent(event, tracker); + consume(clientEvent, agentCard, consumers); + } catch (A2AClientError e) { + overriddenErrorHandler.accept(e); + } + }; + clientTransport.sendMessageStreaming(messageSendParams, eventHandler, overriddenErrorHandler, context); + } + } + + /** * Retrieve a specific task by ID. *

        @@ -666,33 +702,6 @@ private MessageSendConfiguration createMessageSendConfiguration(@Nullable PushNo .build(); } - private void sendMessage(@NonNull MessageSendParams messageSendParams, @NonNull List> consumers, - @Nullable Consumer errorHandler, @Nullable ClientCallContext context) throws A2AClientException { - if (! clientConfig.isStreaming() || ! agentCard.capabilities().streaming()) { - EventKind eventKind = clientTransport.sendMessage(messageSendParams, context); - ClientEvent clientEvent; - if (eventKind instanceof Task task) { - clientEvent = new TaskEvent(task); - } else { - // must be a message - clientEvent = new MessageEvent((Message) eventKind); - } - consume(clientEvent, agentCard, consumers); - } else { - ClientTaskManager tracker = new ClientTaskManager(); - Consumer overriddenErrorHandler = getOverriddenErrorHandler(errorHandler); - Consumer eventHandler = event -> { - try { - ClientEvent clientEvent = getClientEvent(event, tracker); - consume(clientEvent, agentCard, consumers); - } catch (A2AClientError e) { - overriddenErrorHandler.accept(e); - } - }; - clientTransport.sendMessageStreaming(messageSendParams, eventHandler, overriddenErrorHandler, context); - } - } - private @NonNull Consumer getOverriddenErrorHandler(@Nullable Consumer errorHandler) { return e -> { if (errorHandler != null) { @@ -710,14 +719,4 @@ private void consume(ClientEvent clientEvent, AgentCard agentCard, @NonNull List consumer.accept(clientEvent, agentCard); } } - - private MessageSendParams getMessageSendParams(Message request, ClientConfig clientConfig) { - MessageSendConfiguration messageSendConfiguration = createMessageSendConfiguration(clientConfig.getPushNotificationConfig()); - - return MessageSendParams.builder() - .message(request) - .configuration(messageSendConfiguration) - .metadata(clientConfig.getMetadata()) - .build(); - } } From c97b8ccfcd514dc1cac9f1435a954d755cd1dc20 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 19 Feb 2026 14:55:36 +0000 Subject: [PATCH 049/192] chore: release 1.0.0.Alpha3 (#674) --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../io/a2a/examples/helloworld/HelloWorldRunner.java | 12 ++++++------ examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- extras/opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 2 +- .../tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- .../tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 50 files changed, 55 insertions(+), 55 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 91cda330a..341284f35 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 460074c89..2c2e6d704 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index 9cdc502eb..fa7c03e08 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 557920c68..51f84098f 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index 927f23757..6df871dbe 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index a8ce057a5..2f3df5fb6 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 2427ee501..1188a9433 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index 9d9ac16bd..3a5b5d5ed 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index 9b8d75103..48f9fb0bf 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index 3778324c6..89076dfc6 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-common diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index d789e5f63..84667e29d 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index 1a70ed6e4..29e51487b 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java index c6aa974b6..819e74c9c 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha3-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha3-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha3-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha3-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha3-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha3-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha3 +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha3 +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha3 +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha3 +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha3 +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha3 //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 53c397240..5fe31093c 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 51fadf6fe..3b38b2619 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index db773c8fa..ebd7fd095 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 98cc81a9b..15c8d7269 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index efa94d90d..c64ba9809 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-opentelemetry-client-propagation diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index 6793543d2..2f0a9484f 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-opentelemetry-client diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index 637bf8a04..e60db6205 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-opentelemetry-common diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index 6fd4fcc2e..d72898410 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-opentelemetry-integration-tests diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 710e94b44..2665a4b3f 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index e94cc131a..21c8c1ff7 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-opentelemetry-server diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 3b57b9623..1dfc4a047 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 93c70ba5e..8857ab417 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 9a513118d..4437c2463 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 401d08c1c..81f45baf5 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index fdb60573f..8477ef636 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index 13b657d4e..ac4859158 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index d6c1d591c..a22d7b0aa 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index ecccd7cb0..a3db68b47 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index 5b01c60fd..34cc97104 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index 77c3a217b..e4c86908f 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 34a214ed4..f83d911ef 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index 3726fb4bb..735cadd30 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 59223d361..8048aa40d 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index 0c44979d9..aaa43b5d9 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index 29cdd730c..6c125d1cf 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index 644baf44e..9b01fd0ea 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index b54494747..eda09bbd5 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index e7172fde7..f85ceffcc 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index a82b2278f..a6cae8137 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index 909ba9bc0..0bb925ef8 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index acb5222a8..175a5004e 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index 3b70a3405..8d0bc52fd 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-java-sdk-spec diff --git a/tck/pom.xml b/tck/pom.xml index 4c65f1fda..697746d5b 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 a2a-tck-server diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index e7426469e..a240fe35c 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index e0a8e2fe1..ac9a6599e 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index cbd3cd912..5a6283759 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 50c5c4389..48f0dfaac 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3-SNAPSHOT + 1.0.0.Alpha3 ../../pom.xml a2a-java-sdk-transport-rest From f4f0991da5b79599377932140071c1d57108f019 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 19 Feb 2026 15:53:02 +0000 Subject: [PATCH 050/192] chore: Next SNAPSHOT version (#675) --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../io/a2a/examples/helloworld/HelloWorldRunner.java | 12 ++++++------ examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- extras/opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 2 +- .../tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- .../tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 50 files changed, 55 insertions(+), 55 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 341284f35..05549454a 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 2c2e6d704..7a70b7f61 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index fa7c03e08..c89cdc836 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 51f84098f..4e67b3374 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index 6df871dbe..6de5dc8b9 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 2f3df5fb6..8ca49f274 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 1188a9433..f0ffd3407 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index 3a5b5d5ed..ecdf7befd 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index 48f9fb0bf..393d044d6 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index 89076dfc6..9ceff362f 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-common diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index 84667e29d..a1e080420 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index 29e51487b..73932409c 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java index 819e74c9c..9616b8da6 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha3 -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha3 -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha3 -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha3 -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha3 -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha3 +//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha4-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha4-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha4-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha4-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha4-SNAPSHOT +//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha4-SNAPSHOT //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 5fe31093c..4401ccbe6 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 3b38b2619..381704fb9 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-examples-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index ebd7fd095..0b829fac0 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 15c8d7269..38d745f91 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index c64ba9809..f4a802155 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-opentelemetry-client-propagation diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index 2f0a9484f..e4039385f 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-opentelemetry-client diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index e60db6205..41d3f50eb 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-opentelemetry-common diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index d72898410..14ea7f8f9 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-opentelemetry-integration-tests diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 2665a4b3f..0741ff55a 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index 21c8c1ff7..afc62d631 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-opentelemetry-server diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 1dfc4a047..41bae5d6b 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 8857ab417..cdb383d52 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 4437c2463..7503e1340 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 81f45baf5..e756812f7 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index 8477ef636..ed8731542 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index ac4859158..c6b46b7a4 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index a22d7b0aa..39cf7e944 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index a3db68b47..c1b6d6a6a 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index 34cc97104..f3c2491e8 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index e4c86908f..93c6d88e5 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index f83d911ef..9bfbd8a15 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index 735cadd30..394ab2a0d 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 8048aa40d..1578f5c58 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index aaa43b5d9..4ffaaefde 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index 6c125d1cf..7b94e7b4b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index 9b01fd0ea..1a88d7dd4 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index eda09bbd5..50cf450c3 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index f85ceffcc..8f4c5fb87 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index a6cae8137..412a11239 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index 0bb925ef8..378337b9d 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index 175a5004e..2aaaf8760 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index 8d0bc52fd..89a06c9ce 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-java-sdk-spec diff --git a/tck/pom.xml b/tck/pom.xml index 697746d5b..e7f7cefcd 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT a2a-tck-server diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index a240fe35c..5d091ee23 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index ac9a6599e..a84002823 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index 5a6283759..b8a285572 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 48f0dfaac..4bc82fb52 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ io.github.a2asdk a2a-java-sdk-parent - 1.0.0.Alpha3 + 1.0.0.Alpha4-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-rest From e4e844f0049fbcf3f57787711b14f3a58484f7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=AA=85=ED=98=84?= <117622409+flex-myeonghyeon@users.noreply.github.com> Date: Tue, 24 Feb 2026 21:34:01 +0900 Subject: [PATCH 051/192] feat: add getMetadata method for RequestContext (#677) --- .../server/agentexecution/RequestContext.java | 10 +++++++++ .../agentexecution/RequestContextTest.java | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+) 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 beee9bf7e..a7f0ec184 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 @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; @@ -198,6 +199,15 @@ public List getRelatedTasks() { return params != null ? params.configuration() : null; } + /** + * Returns the request metadata. + * + * @return the metadata, or null if not available + */ + public @Nullable Map getMetadata() { + return (params != null && params.metadata() != null) ? Collections.unmodifiableMap(params.metadata()) : null; + } + /** * Returns the server call context. *

        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 2fc0c62e9..7e05ea739 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 @@ -10,6 +10,7 @@ import static org.mockito.Mockito.mockStatic; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.UUID; @@ -38,6 +39,7 @@ public void testInitWithoutParams() { RequestContext context = new RequestContext.Builder().build(); assertNull(context.getMessage()); + assertNull(context.getMetadata()); assertNotNull(context.getTaskId()); // Generated UUID assertNotNull(context.getContextId()); // Generated UUID assertNull(context.getTask()); @@ -70,6 +72,25 @@ public void testInitWithParamsNoIds() { } } + @Test + public void testInitWithParamsMetadata() { + var message = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); + var metadata = new HashMap(); + metadata.put("key", "value"); + + var params = MessageSendParams.builder() + .message(message) + .metadata(metadata) + .build(); + + RequestContext context = new RequestContext.Builder() + .setParams(params) + .build(); + + assertEquals(metadata, context.getMetadata()); + assertThrows(UnsupportedOperationException.class, () -> context.getMetadata().put("anotherKey", "anotherValue")); + } + @Test public void testInitWithTaskId() { String taskId = "task-123"; From b32e8c763b45d17a5a1474b12d49dec572ebb887 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 25 Feb 2026 18:14:40 +0100 Subject: [PATCH 052/192] fix: Add no-arg overload for getUserInput() in RequestContext to avoid (#673) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit passing null for default delimiter. Fixes issue #668 Fixes #668 🦕 Signed-off-by: Emmanuel Hugonnet --- .../server/agentexecution/RequestContext.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) 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 a7f0ec184..9d4798a05 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 @@ -234,6 +234,24 @@ public List getRelatedTasks() { return params != null ? params.tenant() : null; } + /** + * Extracts all text content from the message and joins with the newline delimiter. + *

        + * This is a convenience method for getting text input from messages that may contain + * multiple text parts. Non-text parts (images, etc.) are ignored. + *

        + * Examples: + *

        {@code
        +     * // Join with newlines (common for multi-paragraph input)
        +     * String text = context.getUserInput();
        +     * }
        + * + * @return all text parts joined with newline, or empty string if no message + */ + public String getUserInput() { + return getUserInput("\n"); + } + /** * Extracts all text content from the message and joins with the specified delimiter. *

        @@ -243,7 +261,7 @@ public List getRelatedTasks() { * Examples: *

        {@code
              * // Join with newlines (common for multi-paragraph input)
        -     * String text = context.getUserInput("\n");
        +     * String text = context.getUserInput();
              *
              * // Join with spaces (common for single-line input)
              * String text = context.getUserInput(" ");
        @@ -255,14 +273,11 @@ public List getRelatedTasks() {
              * @param delimiter the string to insert between text parts (null defaults to "\n")
              * @return all text parts joined with delimiter, or empty string if no message
              */
        -    public String getUserInput(String delimiter) {
        +    public String getUserInput(@Nullable String delimiter) {
                 if (params == null) {
                     return "";
                 }
        -        if (delimiter == null) {
        -            delimiter = "\n";
        -        }
        -        return getMessageText(params.message(), delimiter);
        +        return getMessageText(params.message(), delimiter == null ? "\n" : delimiter);
             }
         
             /**
        
        From c5950719c5793e58f5e0fecc2077c6ac0b674f7e Mon Sep 17 00:00:00 2001
        From: Jeff Mesnil 
        Date: Thu, 26 Feb 2026 16:31:56 +0100
        Subject: [PATCH 053/192] feat: Add an optional tenant parameter to the
         getExtendedAgentCard operation (#610)
        MIME-Version: 1.0
        Content-Type: text/plain; charset=UTF-8
        Content-Transfer-Encoding: 8bit
        
        Fixes #608 🦕
        
        Signed-off-by: Jeff Mesnil 
        ---
         .../java/io/a2a/client/AbstractClient.java    | 28 +++++++++++++++++--
         .../src/main/java/io/a2a/client/Client.java   |  9 ++++--
         .../client/transport/grpc/GrpcTransport.java  | 10 +++++--
         .../transport/jsonrpc/JSONRPCTransport.java   |  7 +++--
         .../jsonrpc/JSONRPCTransportTest.java         |  4 ++-
         .../client/transport/rest/RestTransport.java  |  9 +++---
         .../client/transport/spi/ClientTransport.java |  4 ++-
         ...penTelemetryClientPropagatorTransport.java |  5 ++--
         .../client/OpenTelemetryClientTransport.java  |  5 ++--
         .../OpenTelemetryClientTransportTest.java     | 11 +++++---
         .../java/io/a2a/grpc/utils/ProtoUtils.java    |  9 ++++--
         .../a2a/spec/GetExtendedAgentCardParams.java  | 12 ++++++++
         12 files changed, 85 insertions(+), 28 deletions(-)
         create mode 100644 spec/src/main/java/io/a2a/spec/GetExtendedAgentCardParams.java
        
        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 27cbadc7d..d9b6f829a 100644
        --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java
        +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java
        @@ -411,17 +411,41 @@ public abstract void subscribeToTask(@NonNull TaskIdParams request,
              * @throws A2AClientException if retrieving the extended agent card fails for any reason
              */
             public AgentCard getExtendedAgentCard() throws A2AClientException {
        -        return getExtendedAgentCard(null);
        +        return getExtendedAgentCard(null, null);
             }
         
             /**
              * Retrieve the extended AgentCard.
              *
        +     * @param tenant Optional tenant
        +     * @return the extended AgentCard
        +     * @throws A2AClientException if retrieving the extended agent card fails for any reason
        +     */
        +    public AgentCard getExtendedAgentCard(@Nullable String tenant) throws A2AClientException {
        +        return getExtendedAgentCard(tenant, null);
        +    }
        +
        +    /**
        +     * Retrieve the extended AgentCard.
        +     *
        +     * @param context optional client call context for the request (may be {@code null})
        +     * @return the extended AgentCard
        +     * @throws A2AClientException if retrieving the extended agent card fails for any reason
        +     */
        +    public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException {
        +        return getExtendedAgentCard(null, context);
        +    }
        +
        +    /**
        +     * Retrieve the extended AgentCard.
        +     *
        +     * @param tenant Optional tenant
              * @param context optional client call context for the request (may be {@code null})
              * @return the extended AgentCard
              * @throws A2AClientException if retrieving the extended agent card fails for any reason
              */
        -    public abstract AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException;
        +    public abstract AgentCard getExtendedAgentCard(@Nullable String tenant,
        +                                                   @Nullable ClientCallContext context) throws A2AClientException;
         
             /**
              * Close the transport and release any associated resources.
        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 70ed9cf18..8518d5207 100644
        --- a/client/base/src/main/java/io/a2a/client/Client.java
        +++ b/client/base/src/main/java/io/a2a/client/Client.java
        @@ -17,6 +17,7 @@
         import io.a2a.spec.AgentCard;
         import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
         import io.a2a.spec.EventKind;
        +import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
         import io.a2a.spec.ListTaskPushNotificationConfigParams;
         import io.a2a.spec.ListTaskPushNotificationConfigResult;
        @@ -637,19 +638,21 @@ public void subscribeToTask(@NonNull TaskIdParams request,
              * 

        * Example: *

        {@code
        -     * AgentCard updatedCard = client.getExtendedAgentCard(null);
        +     * AgentCard updatedCard = client.getExtendedAgentCard();
              * System.out.println("Agent version: " + updatedCard.version());
              * System.out.println("Skills: " + updatedCard.skills().size());
              * }
        * + * @param tenant Optional tenant * @param context custom call context for request interceptors (optional) * @return the agent's extended agent card * @throws A2AClientException if the extended agent card cannot be retrieved * @see AgentCard */ @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - agentCard = clientTransport.getExtendedAgentCard(context); + public AgentCard getExtendedAgentCard(@Nullable String tenant, @Nullable ClientCallContext context) throws A2AClientException { + GetExtendedAgentCardParams params = new GetExtendedAgentCardParams(tenant); + agentCard = clientTransport.getExtendedAgentCard(params, context); return agentCard; } 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 ca849d99c..6c75594ca 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 @@ -35,6 +35,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; @@ -356,9 +357,12 @@ private MessageSendParams createRequestWithTenant(MessageSendParams request) { } @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - GetExtendedAgentCardRequest request = GetExtendedAgentCardRequest.newBuilder() - .build(); + public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException { + GetExtendedAgentCardRequest.Builder builder = GetExtendedAgentCardRequest.newBuilder(); + if (params.tenant() != null) { + builder.setTenant(params.tenant()); + } + GetExtendedAgentCardRequest request = builder.build(); PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, request, agentCard, context); try { 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 9b8af4ea2..a26600fe3 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 @@ -51,6 +51,7 @@ import io.a2a.spec.AgentInterface; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; @@ -284,13 +285,13 @@ public void subscribeToTask(TaskIdParams request, Consumer e } @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { + public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException { try { PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, - ProtoUtils.ToProto.extendedAgentCard(), agentCard, context); + ProtoUtils.ToProto.extendedAgentCard(params), agentCard, context); try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, ""), payloadAndHeaders, GET_EXTENDED_AGENT_CARD_METHOD); + String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, params.tenant()), payloadAndHeaders, GET_EXTENDED_AGENT_CARD_METHOD); GetExtendedAgentCardResponse response = unmarshalResponse(httpResponseBody, GET_EXTENDED_AGENT_CARD_METHOD); return response.getResult(); } catch (IOException | InterruptedException | JsonProcessingException e) { diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 0bd42a978..4423e58b1 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -50,6 +50,7 @@ import io.a2a.spec.FilePart; import io.a2a.spec.FileWithBytes; import io.a2a.spec.FileWithUri; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; @@ -362,7 +363,8 @@ public void testA2AClientGetExtendedAgentCard() throws Exception { ); JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - AgentCard agentCard = client.getExtendedAgentCard(null); + GetExtendedAgentCardParams params = new GetExtendedAgentCardParams(null); + AgentCard agentCard = client.getExtendedAgentCard(params, null); assertEquals("GeoSpatial Route Planner Agent Extended", agentCard.name()); assertEquals("Extended description", agentCard.description()); assertEquals("https://georoute-agent.example.com/a2a/v1", Utils.getFavoriteInterface(agentCard).url()); 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 0ec8f2eb1..11c5f2fc6 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 @@ -45,6 +45,7 @@ import io.a2a.spec.AgentInterface; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; @@ -414,15 +415,13 @@ public void subscribeToTask(TaskIdParams request, Consumer e } @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { + public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException { try { PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, null, agentCard, context); - String url = Utils.buildBaseUrl(agentInterface, "") + "/extendedAgentCard"; + String url = Utils.buildBaseUrl(agentInterface, params.tenant()) + "/extendedAgentCard"; A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { getBuilder.addHeader(entry.getKey(), entry.getValue()); - } } A2AHttpResponse response = getBuilder.get(); if (!response.success()) { 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 82fe40996..3ecad6019 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 @@ -8,6 +8,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; @@ -139,11 +140,12 @@ void subscribeToTask(TaskIdParams request, Consumer eventCon /** * Retrieve the extended AgentCard. * + * @param params the parameters to get the extended agent card. * @param context optional client call context for the request (may be {@code null}) * @return the extended agent card * @throws A2AClientException if retrieving the agent card fails for any reason */ - AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException; + AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException; /** * Close the transport and release any associated resources. diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java index 53cd134bd..52854d3ef 100644 --- a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java +++ b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java @@ -7,6 +7,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; @@ -112,8 +113,8 @@ public void subscribeToTask(TaskIdParams request, Consumer e } @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - return delegate.getExtendedAgentCard(propagateContext(context)); + public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams request, @Nullable ClientCallContext context) throws A2AClientException { + return delegate.getExtendedAgentCard(request, propagateContext(context)); } @Override diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java index af36f3ffd..dbf8476d8 100644 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java +++ b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java @@ -21,6 +21,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; @@ -393,13 +394,13 @@ public void subscribeToTask(TaskIdParams request, Consumer e } @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { + public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException { ClientCallContext clientContext = createContext(context); SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD).setSpanKind(SpanKind.CLIENT); spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); Span span = spanBuilder.startSpan(); try (Scope scope = span.makeCurrent()) { - AgentCard result = delegate.getExtendedAgentCard(clientContext); + AgentCard result = delegate.getExtendedAgentCard(params, clientContext); if (result != null && extractResponse()) { span.setAttribute(GENAI_RESPONSE, result.toString()); } diff --git a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java b/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java index 945ca84ad..f9d0fbdbb 100644 --- a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java +++ b/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java @@ -12,6 +12,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; @@ -323,9 +324,10 @@ void testSubscribeToTask() throws A2AClientException { void testGetAgentCard_Success() throws A2AClientException { AgentCard expectedResult = mock(AgentCard.class); when(expectedResult.toString()).thenReturn("response-string"); - when(delegate.getExtendedAgentCard(any(ClientCallContext.class))).thenReturn(expectedResult); + when(delegate.getExtendedAgentCard(any(GetExtendedAgentCardParams.class), any(ClientCallContext.class))).thenReturn(expectedResult); - AgentCard result = transport.getExtendedAgentCard(context); + GetExtendedAgentCardParams params = mock(GetExtendedAgentCardParams.class); + AgentCard result = transport.getExtendedAgentCard(params, context); assertEquals(expectedResult, result); verify(tracer).spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); @@ -337,9 +339,10 @@ void testGetAgentCard_Success() throws A2AClientException { @Test void testGetAgentCard_NullResponse() throws A2AClientException { - when(delegate.getExtendedAgentCard(any(ClientCallContext.class))).thenReturn(null); + when(delegate.getExtendedAgentCard(any(GetExtendedAgentCardParams.class), any(ClientCallContext.class))).thenReturn(null); - AgentCard result = transport.getExtendedAgentCard(context); + GetExtendedAgentCardParams params = mock(GetExtendedAgentCardParams.class); + AgentCard result = transport.getExtendedAgentCard(params, context); assertNull(result); verify(tracer).spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); 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 d4b1ca55f..ebd859909 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 @@ -27,6 +27,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.ListTaskPushNotificationConfigParams; @@ -55,8 +56,12 @@ public static io.a2a.grpc.AgentCard agentCard(AgentCard agentCard) { return AgentCardMapper.INSTANCE.toProto(agentCard); } - public static io.a2a.grpc.GetExtendedAgentCardRequest extendedAgentCard() { - return GetExtendedAgentCardRequest.newBuilder().build(); + public static io.a2a.grpc.GetExtendedAgentCardRequest extendedAgentCard(GetExtendedAgentCardParams params) { + GetExtendedAgentCardRequest.Builder builder = GetExtendedAgentCardRequest.newBuilder(); + if (params.tenant() != null) { + builder.setTenant(params.tenant()); + } + return builder.build(); } public static io.a2a.grpc.GetTaskRequest getTaskRequest(TaskQueryParams params) { diff --git a/spec/src/main/java/io/a2a/spec/GetExtendedAgentCardParams.java b/spec/src/main/java/io/a2a/spec/GetExtendedAgentCardParams.java new file mode 100644 index 000000000..c103c6a2a --- /dev/null +++ b/spec/src/main/java/io/a2a/spec/GetExtendedAgentCardParams.java @@ -0,0 +1,12 @@ +package io.a2a.spec; + +import org.jspecify.annotations.Nullable; + +/** + * Parameters to get the extended agent card. + * + * @param tenant optional tenant, provided as a path parameter. + * @see A2A Protocol Specification + */ +public record GetExtendedAgentCardParams(@Nullable String tenant) { +} From 05597d2e266b5966db685be31327b34dba9860e6 Mon Sep 17 00:00:00 2001 From: Lee Chae Min Date: Mon, 2 Mar 2026 21:56:21 +0900 Subject: [PATCH 054/192] fix: correct AgentCard example in README (#691) # Description Replace non-existent `.url()` and `.protocolVersion()` builder calls with the correct `.supportedInterfaces()` method, and add the missing `AgentInterface` import. --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 48d28a8cd..6b363d664 100644 --- a/README.md +++ b/README.md @@ -104,19 +104,24 @@ you'd like to support. import io.a2a.server.PublicAgentCard; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; +import io.a2a.spec.AgentInterface; import io.a2a.spec.AgentSkill; +import io.a2a.spec.TransportProtocol; ... @ApplicationScoped public class WeatherAgentCardProducer { - + + private static final String AGENT_URL = "http://localhost:10001"; + @Produces @PublicAgentCard public AgentCard agentCard() { return AgentCard.builder() .name("Weather Agent") .description("Helps with weather") - .url("http://localhost:10001") + .supportedInterfaces(List.of( + new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_URL))) .version("1.0.0") .capabilities(AgentCapabilities.builder() .streaming(true) @@ -131,7 +136,6 @@ public class WeatherAgentCardProducer { .tags(Collections.singletonList("weather")) .examples(List.of("weather in LA, CA")) .build())) - .protocolVersion(io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION) .build(); } } From 719ca9365a9eb1436238a32a02e1479be09119da Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 4 Mar 2026 17:41:59 +0100 Subject: [PATCH 055/192] fix!: Update a2a.proto changes (#687) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Aligning to the latest version of a2a.proto - Update tests to match a2a.proto changes: Fixes test failures after proto update - adjusts JSON structures and package references to align with new proto definitions. Fixes #686 🦕 --------- Signed-off-by: Emmanuel Hugonnet --- .../java/io/a2a/client/AbstractClient.java | 5 +- .../src/main/java/io/a2a/client/Client.java | 3 +- .../client/transport/grpc/GrpcTransport.java | 8 +- .../transport/jsonrpc/JSONRPCTransport.java | 7 +- .../jsonrpc/JSONRPCTransportTest.java | 4 +- .../transport/jsonrpc/JsonMessages.java | 6 +- .../client/transport/rest/RestTransport.java | 15 +- .../transport/rest/JsonRestMessages.java | 10 +- .../transport/rest/RestTransportTest.java | 3 +- .../client/transport/spi/ClientTransport.java | 3 +- ...penTelemetryClientPropagatorTransport.java | 3 +- .../client/OpenTelemetryClientTransport.java | 3 +- .../OpenTelemetryClientTransportTest.java | 3 +- .../it/OpenTelemetryA2ABaseTest.java | 2 +- .../OpenTelemetryRequestHandlerDecorator.java | 3 +- ...nTelemetryRequestHandlerDecoratorTest.java | 4 +- .../JpaDatabaseTaskStoreIntegrationTest.java | 4 +- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 78 +- .../jsonrpc/common/wrappers/A2AResponse.java | 2 +- .../common/wrappers/CancelTaskRequest.java | 11 +- ...stTaskPushNotificationConfigsRequest.java} | 12 +- ...tTaskPushNotificationConfigsResponse.java} | 10 +- .../wrappers/NonStreamingJSONRPCRequest.java | 2 +- .../a2a/jsonrpc/common/json/JsonUtilTest.java | 61 + .../server/apps/quarkus/A2AServerRoutes.java | 8 +- .../apps/quarkus/A2AServerRoutesTest.java | 14 +- .../server/rest/quarkus/A2AServerRoutes.java | 4 +- .../rest/quarkus/A2AServerRoutesTest.java | 154 ++- .../DefaultRequestHandler.java | 3 +- .../requesthandlers/RequestHandler.java | 3 +- .../io/a2a/server/util/sse/SseFormatter.java | 4 +- spec-grpc/src/main/java/io/a2a/grpc/A2A.java | 1053 +++++++++-------- .../main/java/io/a2a/grpc/A2AServiceGrpc.java | 217 ++-- .../io/a2a/grpc/APIKeySecurityScheme.java | 24 +- .../grpc/APIKeySecuritySchemeOrBuilder.java | 2 +- .../java/io/a2a/grpc/AgentCapabilities.java | 92 +- .../a2a/grpc/AgentCapabilitiesOrBuilder.java | 16 +- .../src/main/java/io/a2a/grpc/AgentCard.java | 626 +++++----- .../java/io/a2a/grpc/AgentCardOrBuilder.java | 122 +- .../java/io/a2a/grpc/AgentCardSignature.java | 80 +- .../a2a/grpc/AgentCardSignatureOrBuilder.java | 18 +- .../main/java/io/a2a/grpc/AgentExtension.java | 48 +- .../io/a2a/grpc/AgentExtensionOrBuilder.java | 8 +- .../main/java/io/a2a/grpc/AgentInterface.java | 38 +- .../io/a2a/grpc/AgentInterfaceOrBuilder.java | 6 +- .../main/java/io/a2a/grpc/AgentProvider.java | 24 +- .../io/a2a/grpc/AgentProviderOrBuilder.java | 2 +- .../src/main/java/io/a2a/grpc/AgentSkill.java | 70 +- .../java/io/a2a/grpc/AgentSkillOrBuilder.java | 12 +- .../src/main/java/io/a2a/grpc/Artifact.java | 255 ++-- .../java/io/a2a/grpc/ArtifactOrBuilder.java | 50 +- .../java/io/a2a/grpc/AuthenticationInfo.java | 45 +- .../a2a/grpc/AuthenticationInfoOrBuilder.java | 8 +- .../a2a/grpc/AuthorizationCodeOAuthFlow.java | 26 +- .../AuthorizationCodeOAuthFlowOrBuilder.java | 2 +- .../java/io/a2a/grpc/CancelTaskRequest.java | 349 +++++- .../a2a/grpc/CancelTaskRequestOrBuilder.java | 45 +- .../a2a/grpc/ClientCredentialsOAuthFlow.java | 26 +- .../ClientCredentialsOAuthFlowOrBuilder.java | 2 +- ...eateTaskPushNotificationConfigRequest.java | 324 ++--- ...ushNotificationConfigRequestOrBuilder.java | 44 +- ...leteTaskPushNotificationConfigRequest.java | 146 ++- ...ushNotificationConfigRequestOrBuilder.java | 26 +- .../java/io/a2a/grpc/DeviceCodeOAuthFlow.java | 26 +- .../grpc/DeviceCodeOAuthFlowOrBuilder.java | 2 +- .../a2a/grpc/GetExtendedAgentCardRequest.java | 40 +- .../GetExtendedAgentCardRequestOrBuilder.java | 6 +- .../GetTaskPushNotificationConfigRequest.java | 148 +-- ...ushNotificationConfigRequestOrBuilder.java | 26 +- .../main/java/io/a2a/grpc/GetTaskRequest.java | 134 ++- .../io/a2a/grpc/GetTaskRequestOrBuilder.java | 22 +- .../io/a2a/grpc/HTTPAuthSecurityScheme.java | 38 +- .../grpc/HTTPAuthSecuritySchemeOrBuilder.java | 6 +- .../java/io/a2a/grpc/ImplicitOAuthFlow.java | 28 +- .../a2a/grpc/ImplicitOAuthFlowOrBuilder.java | 2 +- ...stTaskPushNotificationConfigsRequest.java} | 158 +-- ...hNotificationConfigsRequestOrBuilder.java} | 16 +- ...tTaskPushNotificationConfigsResponse.java} | 187 ++- ...NotificationConfigsResponseOrBuilder.java} | 20 +- .../java/io/a2a/grpc/ListTasksRequest.java | 310 ++--- .../a2a/grpc/ListTasksRequestOrBuilder.java | 60 +- .../java/io/a2a/grpc/ListTasksResponse.java | 96 +- .../a2a/grpc/ListTasksResponseOrBuilder.java | 18 +- .../src/main/java/io/a2a/grpc/Message.java | 226 ++-- .../java/io/a2a/grpc/MessageOrBuilder.java | 48 +- .../io/a2a/grpc/MutualTlsSecurityScheme.java | 24 +- .../MutualTlsSecuritySchemeOrBuilder.java | 2 +- .../io/a2a/grpc/OAuth2SecurityScheme.java | 76 +- .../grpc/OAuth2SecuritySchemeOrBuilder.java | 16 +- .../src/main/java/io/a2a/grpc/OAuthFlows.java | 272 +++-- .../java/io/a2a/grpc/OAuthFlowsOrBuilder.java | 72 +- .../a2a/grpc/OpenIdConnectSecurityScheme.java | 45 +- .../OpenIdConnectSecuritySchemeOrBuilder.java | 8 +- spec-grpc/src/main/java/io/a2a/grpc/Part.java | 152 ++- .../main/java/io/a2a/grpc/PartOrBuilder.java | 38 +- .../java/io/a2a/grpc/PasswordOAuthFlow.java | 28 +- .../a2a/grpc/PasswordOAuthFlowOrBuilder.java | 2 +- .../io/a2a/grpc/PushNotificationConfig.java | 114 +- .../grpc/PushNotificationConfigOrBuilder.java | 26 +- spec-grpc/src/main/java/io/a2a/grpc/Role.java | 21 +- .../java/io/a2a/grpc/SecurityRequirement.java | 104 +- .../grpc/SecurityRequirementOrBuilder.java | 32 +- .../main/java/io/a2a/grpc/SecurityScheme.java | 144 ++- .../io/a2a/grpc/SecuritySchemeOrBuilder.java | 32 +- .../io/a2a/grpc/SendMessageConfiguration.java | 103 +- .../SendMessageConfigurationOrBuilder.java | 24 +- .../java/io/a2a/grpc/SendMessageRequest.java | 176 ++- .../a2a/grpc/SendMessageRequestOrBuilder.java | 28 +- .../java/io/a2a/grpc/SendMessageResponse.java | 172 ++- .../grpc/SendMessageResponseOrBuilder.java | 38 +- .../main/java/io/a2a/grpc/StreamResponse.java | 120 +- .../io/a2a/grpc/StreamResponseOrBuilder.java | 26 +- .../src/main/java/io/a2a/grpc/StringList.java | 76 +- .../java/io/a2a/grpc/StringListOrBuilder.java | 18 +- .../io/a2a/grpc/SubscribeToTaskRequest.java | 110 +- .../grpc/SubscribeToTaskRequestOrBuilder.java | 18 +- spec-grpc/src/main/java/io/a2a/grpc/Task.java | 260 ++-- .../io/a2a/grpc/TaskArtifactUpdateEvent.java | 106 +- .../TaskArtifactUpdateEventOrBuilder.java | 22 +- .../main/java/io/a2a/grpc/TaskOrBuilder.java | 54 +- .../a2a/grpc/TaskPushNotificationConfig.java | 340 ++---- .../TaskPushNotificationConfigOrBuilder.java | 44 +- .../src/main/java/io/a2a/grpc/TaskState.java | 45 +- .../src/main/java/io/a2a/grpc/TaskStatus.java | 62 +- .../java/io/a2a/grpc/TaskStatusOrBuilder.java | 12 +- .../io/a2a/grpc/TaskStatusUpdateEvent.java | 140 ++- .../grpc/TaskStatusUpdateEventOrBuilder.java | 28 +- ...reateTaskPushNotificationConfigMapper.java | 3 +- ...askPushNotificationConfigParamsMapper.java | 10 +- .../a2a/grpc/mapper/TaskIdParamsMapper.java | 9 +- .../TaskPushNotificationConfigMapper.java | 3 +- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 16 +- .../java/io/a2a/grpc/utils/ProtoUtils.java | 21 +- spec-grpc/src/main/proto/a2a.proto | 472 +++----- .../io/a2a/grpc/utils/JSONRPCUtilsTest.java | 17 +- .../java/io/a2a/grpc/utils/ToProtoTest.java | 8 +- .../src/main/java/io/a2a/spec/A2AMethods.java | 2 +- .../java/io/a2a/spec/CancelTaskParams.java | 113 ++ .../main/java/io/a2a/spec/TaskIdParams.java | 1 + .../apps/common/AbstractA2AServerTest.java | 7 +- .../transport/grpc/handler/GrpcHandler.java | 9 +- .../grpc/handler/GrpcHandlerTest.java | 29 +- .../jsonrpc/handler/JSONRPCHandler.java | 16 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 35 +- .../transport/rest/handler/RestHandler.java | 11 +- .../rest/handler/RestHandlerTest.java | 103 +- 146 files changed, 5299 insertions(+), 4691 deletions(-) rename jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/{ListTaskPushNotificationConfigRequest.java => ListTaskPushNotificationConfigsRequest.java} (82%) rename jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/{ListTaskPushNotificationConfigResponse.java => ListTaskPushNotificationConfigsResponse.java} (75%) create mode 100644 jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/JsonUtilTest.java rename spec-grpc/src/main/java/io/a2a/grpc/{ListTaskPushNotificationConfigRequest.java => ListTaskPushNotificationConfigsRequest.java} (81%) rename spec-grpc/src/main/java/io/a2a/grpc/{ListTaskPushNotificationConfigRequestOrBuilder.java => ListTaskPushNotificationConfigsRequestOrBuilder.java} (73%) rename spec-grpc/src/main/java/io/a2a/grpc/{ListTaskPushNotificationConfigResponse.java => ListTaskPushNotificationConfigsResponse.java} (78%) rename spec-grpc/src/main/java/io/a2a/grpc/{ListTaskPushNotificationConfigResponseOrBuilder.java => ListTaskPushNotificationConfigsResponseOrBuilder.java} (63%) create mode 100644 spec/src/main/java/io/a2a/spec/CancelTaskParams.java 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 d9b6f829a..4f7964832 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java @@ -11,6 +11,7 @@ import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigParams; @@ -230,7 +231,7 @@ public ListTasksResult listTasks(ListTasksParams request) throws A2AClientExcept * @return the cancelled task * @throws A2AClientException if cancelling the task fails for any reason */ - public Task cancelTask(TaskIdParams request) throws A2AClientException { + public Task cancelTask(CancelTaskParams request) throws A2AClientException { return cancelTask(request, null); } @@ -242,7 +243,7 @@ public Task cancelTask(TaskIdParams request) throws A2AClientException { * @return the cancelled task * @throws A2AClientException if cancelling the task fails for any reason */ - public abstract Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException; + public abstract Task cancelTask(CancelTaskParams request, @Nullable ClientCallContext context) throws A2AClientException; /** * Create or update the push notification configuration for a specific 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 8518d5207..515190c95 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -15,6 +15,7 @@ import io.a2a.spec.A2AClientException; import io.a2a.spec.A2AClientInvalidStateError; import io.a2a.spec.AgentCard; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetExtendedAgentCardParams; @@ -445,7 +446,7 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo * @see io.a2a.spec.TaskNotFoundError */ @Override - public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { + public Task cancelTask(CancelTaskParams request, @Nullable ClientCallContext context) throws A2AClientException { return clientTransport.cancelTask(request, context); } 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 6c75594ca..cb0fef677 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 @@ -33,6 +33,7 @@ import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetExtendedAgentCardParams; @@ -161,7 +162,7 @@ public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context } @Override - public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { + public Task cancelTask(CancelTaskParams request, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); io.a2a.grpc.CancelTaskRequest cancelTaskRequest = io.a2a.grpc.CancelTaskRequest.newBuilder() @@ -238,7 +239,6 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPu io.a2a.grpc.CreateTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() .setTaskId(request.taskId()) .setConfig(ToProto.taskPushNotificationConfig(request).getPushNotificationConfig()) - .setConfigId(configId != null ? configId : request.taskId()) .setTenant(resolveTenant(request.tenant())) .build(); PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); @@ -281,7 +281,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - io.a2a.grpc.ListTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder() + io.a2a.grpc.ListTaskPushNotificationConfigsRequest grpcRequest = io.a2a.grpc.ListTaskPushNotificationConfigsRequest.newBuilder() .setTaskId(request.id()) .setTenant(resolveTenant(request.tenant())) .setPageSize(request.pageSize()) @@ -292,7 +292,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - io.a2a.grpc.ListTaskPushNotificationConfigResponse grpcResponse = stubWithMetadata.listTaskPushNotificationConfig(grpcRequest); + io.a2a.grpc.ListTaskPushNotificationConfigsResponse grpcResponse = stubWithMetadata.listTaskPushNotificationConfigs(grpcRequest); return FromProto.listTaskPushNotificationConfigResult(grpcResponse); } catch (StatusRuntimeException | StatusException e) { throw GrpcErrorMapper.mapGrpcError(e, "Failed to list task push notification config: "); 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 a26600fe3..3530dffea 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 @@ -39,7 +39,7 @@ import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; 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.ListTaskPushNotificationConfigsResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; @@ -49,6 +49,7 @@ import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetExtendedAgentCardParams; @@ -152,7 +153,7 @@ public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context } @Override - public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { + public Task cancelTask(CancelTaskParams request, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); PayloadAndHeaders payloadAndHeaders = applyInterceptors(CANCEL_TASK_METHOD, ProtoUtils.ToProto.cancelTaskRequest(request), agentCard, context); @@ -228,7 +229,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio try { String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - ListTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + ListTaskPushNotificationConfigsResponse response = unmarshalResponse(httpResponseBody, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); return response.getResult(); } catch (A2AClientException e) { throw e; diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 4423e58b1..bf341a118 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -44,6 +44,7 @@ import io.a2a.spec.AgentSkill; import io.a2a.spec.Artifact; import io.a2a.spec.AuthenticationInfo; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DataPart; import io.a2a.spec.EventKind; import io.a2a.spec.FileContent; @@ -61,7 +62,6 @@ import io.a2a.spec.SecurityRequirement; import io.a2a.spec.SecurityScheme; import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TaskState; @@ -286,7 +286,7 @@ public void testA2AClientCancelTask() throws Exception { ); JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Task task = client.cancelTask(new TaskIdParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null); + Task task = client.cancelTask(new CancelTaskParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null); assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.contextId()); assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); 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 b55c0f9d1..f2a5977d4 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 @@ -322,8 +322,8 @@ public class JsonMessages { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "result": { "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "c295ea44-7543-4f78-b524-7a38915ad6e4", "pushNotificationConfig": { + "id": "c295ea44-7543-4f78-b524-7a38915ad6e4", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" @@ -339,8 +339,8 @@ public class JsonMessages { "method":"CreateTaskPushNotificationConfig", "params":{ "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "configId":"c295ea44-7543-4f78-b524-7a38915ad6e4", "config":{ + "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", "url":"https://example.com/callback", "authentication":{ "scheme":"jwt" @@ -355,8 +355,8 @@ public class JsonMessages { "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "result": { "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", "pushNotificationConfig": { + "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" 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 11c5f2fc6..695c2e5ab 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 @@ -43,6 +43,7 @@ import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetExtendedAgentCardParams; @@ -163,10 +164,9 @@ public Task getTask(TaskQueryParams taskQueryParams, @Nullable ClientCallContext } @Override - public Task cancelTask(TaskIdParams taskIdParams, @Nullable ClientCallContext context) throws A2AClientException { + public Task cancelTask(CancelTaskParams taskIdParams, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("taskIdParams", taskIdParams); - io.a2a.grpc.CancelTaskRequest.Builder builder = io.a2a.grpc.CancelTaskRequest.newBuilder(); - builder.setId(taskIdParams.id()); + io.a2a.grpc.CancelTaskRequest.Builder builder = io.a2a.grpc.CancelTaskRequest.newBuilder(ProtoUtils.ToProto.cancelTaskRequest(taskIdParams)); 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); @@ -275,9 +275,6 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPu = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); builder.setConfig(ProtoUtils.ToProto.taskPushNotificationConfig(request).getPushNotificationConfig()) .setTaskId(request.taskId()); - if (request.config().id() != null) { - builder.setConfigId(request.config().id()); - } 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); @@ -333,8 +330,8 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu @Override public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder builder - = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder(); + io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder builder + = io.a2a.grpc.ListTaskPushNotificationConfigsRequest.newBuilder(); builder.setTaskId(request.id()); PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, agentCard, context); @@ -351,7 +348,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio throw RestErrorMapper.mapRestError(response); } String httpResponseBody = response.body(); - io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder responseBuilder = io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder(); + io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder responseBuilder = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(); JsonFormat.parser().merge(httpResponseBody, responseBuilder); return ProtoUtils.FromProto.listTaskPushNotificationConfigResult(responseBuilder); } catch (A2AClientException e) { diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java index 35ac4a9c5..aa54d4b86 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java @@ -308,8 +308,8 @@ public class JsonRestMessages { static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ { "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "10", "pushNotificationConfig": { + "id": "10", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" @@ -321,8 +321,8 @@ public class JsonRestMessages { "configs":[ { "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "10", "pushNotificationConfig": { + "id": "10", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" @@ -331,8 +331,8 @@ public class JsonRestMessages { }, { "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "5", "pushNotificationConfig": { + "id": "5", "url": "https://test.com/callback" } } @@ -343,8 +343,8 @@ public class JsonRestMessages { static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ { "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "configId": "default-config-id", "config": { + "id": "default-config-id", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" @@ -355,8 +355,8 @@ public class JsonRestMessages { static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ { "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "10", "pushNotificationConfig": { + "id": "10", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index 2f3ae18db..70f6e24d4 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -37,6 +37,7 @@ import io.a2a.spec.AgentSkill; import io.a2a.spec.Artifact; import io.a2a.spec.AuthenticationInfo; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.ExtensionSupportRequiredError; @@ -172,7 +173,7 @@ public void testCancelTask() throws Exception { ); ClientCallContext context = null; RestTransport instance = new RestTransport(CARD); - Task task = instance.cancelTask(new TaskIdParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), context); + Task task = instance.cancelTask(new CancelTaskParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), context); assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); assertNull(task.status().message()); 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 3ecad6019..ee85c1dca 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 @@ -6,6 +6,7 @@ import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetExtendedAgentCardParams; @@ -67,7 +68,7 @@ void sendMessageStreaming(MessageSendParams request, Consumer metadata) throws java.io.IOException { + if (metadata != null && !metadata.isEmpty()) { + out.name("metadata"); + OBJECT_MAPPER.toJson(metadata, new TypeToken>(){}.getType(), out); + } + } + + /** + * Serializes a metadata map to a JSON string. + * + * @param metadata the metadata map to serialize + * @return JSON string representation of the metadata, or an empty string if the map is null or empty + */ + public static String writeMetadata(@Nullable Map metadata) { + if (metadata == null || metadata.isEmpty()) { + return ""; + } + return OBJECT_MAPPER.toJson(metadata, new TypeToken>(){}.getType()); + } + + /** + * Reads the "metadata" field from a JSON object, if present. + * + * @param jsonObject the JSON object to read from + * @return the metadata map, or {@code null} if no "metadata" field is present + */ + public static Map readMetadata(com.google.gson.JsonObject jsonObject) { + if (jsonObject.has("metadata")) { + return OBJECT_MAPPER.fromJson(jsonObject.get("metadata"), new TypeToken>(){}.getType()); + } + return Collections.emptyMap(); + } + + /** + * Reads the "metadata" field from a JSON body string, if present. + * + * @param json the JSON body string to parse + * @return the metadata map, or an empty map if the input is null, blank, or has no "metadata" field + * @throws JsonProcessingException if the JSON is invalid + */ + public static Map readMetadata(@Nullable String json) throws JsonProcessingException { + if (json == null || json.isBlank()) { + return Collections.emptyMap(); + } + try { + return readMetadata(JsonParser.parseString(json).getAsJsonObject()); + } catch (JsonSyntaxException e) { + throw new JsonProcessingException("Failed to parse metadata JSON", e); + } + } + /** * Gson TypeAdapter for serializing and deserializing {@link Part} and its subclasses. *

        @@ -467,13 +527,6 @@ static class PartTypeAdapter extends TypeAdapter> { // Create separate Gson instance without the Part adapter to avoid recursion private final Gson delegateGson = createBaseGsonBuilder().create(); - private void writeMetadata(JsonWriter out, @Nullable Map metadata) throws java.io.IOException { - if (metadata != null && !metadata.isEmpty()) { - out.name("metadata"); - delegateGson.toJson(metadata, MAP_TYPE, out); - } - } - @Override public void write(JsonWriter out, Part value) throws java.io.IOException { if (value == null) { @@ -487,17 +540,17 @@ public void write(JsonWriter out, Part value) throws java.io.IOException { // TextPart: { "text": "value" } - direct string value out.name(TEXT); out.value(textPart.text()); - writeMetadata(out, textPart.metadata()); + JsonUtil.writeMetadata(out, textPart.metadata()); } else if (value instanceof FilePart filePart) { // FilePart: { "file": {...} } out.name(FILE); delegateGson.toJson(filePart.file(), FileContent.class, out); - writeMetadata(out, filePart.metadata()); + JsonUtil.writeMetadata(out, filePart.metadata()); } else if (value instanceof DataPart dataPart) { // DataPart: { "data": } out.name(DATA); delegateGson.toJson(dataPart.data(), Object.class, out); - writeMetadata(out, dataPart.metadata()); + JsonUtil.writeMetadata(out, dataPart.metadata()); } else { throw new JsonSyntaxException("Unknown Part subclass: " + value.getClass().getName()); } @@ -522,10 +575,7 @@ Part read(JsonReader in) throws java.io.IOException { com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); // Extract metadata if present - Map metadata = null; - if (jsonObject.has("metadata")) { - metadata = delegateGson.fromJson(jsonObject.get("metadata"), new TypeToken>(){}.getType()); - } + Map metadata = JsonUtil.readMetadata(jsonObject); // Check for member name discriminators (v1.0 protocol) Set keys = jsonObject.keySet(); diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java index 20fc4bd42..c318f2166 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java @@ -10,7 +10,7 @@ * * @param the type of the result value returned in successful responses */ -public abstract sealed class A2AResponse implements A2AMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetExtendedAgentCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, A2AErrorResponse, ListTaskPushNotificationConfigResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, CreateTaskPushNotificationConfigResponse { +public abstract sealed class A2AResponse implements A2AMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetExtendedAgentCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, A2AErrorResponse, ListTaskPushNotificationConfigsResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, CreateTaskPushNotificationConfigResponse { /** The JSON-RPC protocol version. */ protected String jsonrpc; diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java index 463279705..a0c48b0df 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java @@ -2,6 +2,7 @@ import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import io.a2a.spec.CancelTaskParams; import java.util.UUID; import io.a2a.spec.TaskIdParams; @@ -25,7 +26,7 @@ * @see TaskNotCancelableError for the error when cancellation is not possible * @see A2A Protocol Specification */ -public final class CancelTaskRequest extends NonStreamingJSONRPCRequest { +public final class CancelTaskRequest extends NonStreamingJSONRPCRequest { /** * Creates a new CancelTaskRequest with the specified JSON-RPC parameters. @@ -35,7 +36,7 @@ public final class CancelTaskRequest extends NonStreamingJSONRPCRequest * This class implements the JSON-RPC {@code tasks/pushNotificationConfig/list} method. * - * @see ListTaskPushNotificationConfigResponse for the response + * @see ListTaskPushNotificationConfigsResponse for the response * @see ListTaskPushNotificationConfigParams for the parameter structure * @see TaskPushNotificationConfig for the configuration structure * @see A2A Protocol Specification */ -public final class ListTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { +public final class ListTaskPushNotificationConfigsRequest extends NonStreamingJSONRPCRequest { /** * Constructs request with all parameters. @@ -30,7 +30,7 @@ public final class ListTaskPushNotificationConfigRequest extends NonStreamingJSO * @param id the request ID * @param params the request parameters */ - public ListTaskPushNotificationConfigRequest(String jsonrpc, Object id, ListTaskPushNotificationConfigParams params) { + public ListTaskPushNotificationConfigsRequest(String jsonrpc, Object id, ListTaskPushNotificationConfigParams params) { super(jsonrpc, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); } @@ -40,7 +40,7 @@ public ListTaskPushNotificationConfigRequest(String jsonrpc, Object id, ListTask * @param id the request ID * @param params the request parameters */ - public ListTaskPushNotificationConfigRequest(String id, ListTaskPushNotificationConfigParams params) { + public ListTaskPushNotificationConfigsRequest(String id, ListTaskPushNotificationConfigParams params) { this(null, id, params); } @@ -105,11 +105,11 @@ public Builder params(ListTaskPushNotificationConfigParams params) { * * @return a new instance */ - public ListTaskPushNotificationConfigRequest build() { + public ListTaskPushNotificationConfigsRequest build() { if (id == null) { id = UUID.randomUUID().toString(); } - return new ListTaskPushNotificationConfigRequest(jsonrpc, id, params); + return new ListTaskPushNotificationConfigsRequest(jsonrpc, id, params); } } } diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java similarity index 75% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java index e5e24739f..30b983c06 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java @@ -13,12 +13,12 @@ *

        * If an error occurs, the error field will contain a {@link A2AError}. * - * @see ListTaskPushNotificationConfigRequest for the corresponding request + * @see ListTaskPushNotificationConfigsRequest 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 A2AResponse { +public final class ListTaskPushNotificationConfigsResponse extends A2AResponse { /** * Constructs response with all parameters. @@ -28,7 +28,7 @@ public final class ListTaskPushNotificationConfigResponse extends A2AResponse

      • extends A2ARequest permits GetTaskRequest, CancelTaskRequest, CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, - SendMessageRequest, DeleteTaskPushNotificationConfigRequest, ListTaskPushNotificationConfigRequest, + SendMessageRequest, DeleteTaskPushNotificationConfigRequest, ListTaskPushNotificationConfigsRequest, GetExtendedAgentCardRequest, ListTasksRequest { NonStreamingJSONRPCRequest(String jsonrpc, String method, Object id, T params) { diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/JsonUtilTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/JsonUtilTest.java new file mode 100644 index 000000000..0584bfb7d --- /dev/null +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/JsonUtilTest.java @@ -0,0 +1,61 @@ +package io.a2a.jsonrpc.common.json; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Map; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.jupiter.api.Test; + +public class JsonUtilTest { + + // readMetadata(String) tests + + @Test + public void testReadMetadataStringExtractsMetadataField() throws Exception { + String body = "{\"id\":\"task-1\",\"metadata\":{\"reason\":\"user_requested\",\"source\":\"web_ui\"}}"; + Map metadata = JsonUtil.readMetadata(body); + assertEquals(2, metadata.size()); + assertEquals("user_requested", metadata.get("reason")); + assertEquals("web_ui", metadata.get("source")); + } + + @Test + public void testReadMetadataStringReturnsEmptyMapWhenNoMetadataField() throws Exception { + String body = "{\"id\":\"task-1\"}"; + Map metadata = JsonUtil.readMetadata(body); + assertTrue(metadata.isEmpty()); + } + + @Test + public void testReadMetadataStringReturnsEmptyMapForEmptyMetadataObject() throws Exception { + String body = "{\"metadata\":{}}"; + Map metadata = JsonUtil.readMetadata(body); + assertTrue(metadata.isEmpty()); + } + + @Test + public void testReadMetadataStringReturnsEmptyMapForNullInput() throws Exception { + assertTrue(JsonUtil.readMetadata((String) null).isEmpty()); + } + + @Test + public void testReadMetadataStringReturnsEmptyMapForBlankInput() throws Exception { + assertTrue(JsonUtil.readMetadata(" ").isEmpty()); + } + + // readMetadata(JsonObject) tests — verify String overload is consistent with it + + @Test + public void testReadMetadataStringConsistentWithJsonObjectOverload() throws Exception { + String body = "{\"metadata\":{\"key\":\"value\"}}"; + JsonObject jsonObject = JsonParser.parseString(body).getAsJsonObject(); + + Map fromString = JsonUtil.readMetadata(body); + Map fromJsonObject = JsonUtil.readMetadata(jsonObject); + + assertEquals(fromJsonObject, fromString); + } +} 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 971a0cc77..ceded1fc4 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 @@ -43,8 +43,8 @@ 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.ListTaskPushNotificationConfigsRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.NonStreamingJSONRPCRequest; @@ -187,7 +187,7 @@ private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest if (request instanceof SendMessageRequest req) { return jsonRpcHandler.onMessageSend(req, context); } - if (request instanceof ListTaskPushNotificationConfigRequest req) { + if (request instanceof ListTaskPushNotificationConfigsRequest req) { return jsonRpcHandler.listPushNotificationConfig(req, context); } if (request instanceof DeleteTaskPushNotificationConfigRequest req) { @@ -304,7 +304,7 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -445,7 +445,7 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() { routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); // Assert - verify(mockJsonRpcHandler).listPushNotificationConfig(any(ListTaskPushNotificationConfigRequest.class), + verify(mockJsonRpcHandler).listPushNotificationConfig(any(ListTaskPushNotificationConfigsRequest.class), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); 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 9b6bf510a..074cd5ec6 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 @@ -199,7 +199,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) { + public void cancelTask(@Body String body, RoutingContext rc) { String taskId = rc.pathParam("taskId"); ServerCallContext context = createCallContext(rc, CANCEL_TASK_METHOD); HTTPRestResponse response = null; @@ -207,7 +207,7 @@ public void cancelTask(RoutingContext rc) { if (taskId == null || taskId.isEmpty()) { response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); } else { - response = jsonRestHandler.cancelTask(context, extractTenant(rc), taskId); + response = jsonRestHandler.cancelTask(context, extractTenant(rc), body, taskId); } } catch (Throwable t) { if (t instanceof A2AError error) { 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 ce3c140cc..c3bc2e644 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 @@ -12,6 +12,7 @@ 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; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -160,20 +161,167 @@ public void testCancelTask_MethodNameSetInContext() { when(mockHttpResponse.getStatusCode()).thenReturn(200); when(mockHttpResponse.getContentType()).thenReturn("application/json"); when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString())).thenReturn(mockHttpResponse); + when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); // Act - routes.cancelTask(mockRoutingContext); + routes.cancelTask("{\"id\":\"task123\"}", mockRoutingContext); // Assert - verify(mockRestHandler).cancelTask(contextCaptor.capture(), anyString(), eq("task123")); + verify(mockRestHandler).cancelTask(contextCaptor.capture(), anyString(), eq("{\"id\":\"task123\"}"), eq("task123")); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(CANCEL_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } + @Test + public void testCancelTask_WithMetadata() { + // Arrange + when(mockRoutingContext.pathParam("taskId")).thenReturn("task456"); + HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); + when(mockHttpResponse.getStatusCode()).thenReturn(200); + when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task456\",\"status\":\"cancelled\"}"); + + String requestBody = """ + { + "metadata": { + "reason": "user_requested", + "source": "web_ui", + "priority": "high" + } + } + """; + + ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); + when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString(), anyString())) + .thenReturn(mockHttpResponse); + + // Act + routes.cancelTask(requestBody, mockRoutingContext); + + // Assert + verify(mockRestHandler).cancelTask(any(ServerCallContext.class), anyString(), bodyCaptor.capture(), eq("task456")); + String capturedBody = bodyCaptor.getValue(); + assertNotNull(capturedBody); + assertEquals(requestBody, capturedBody); + } + + @Test + public void testCancelTask_WithEmptyMetadata() { + // Arrange + when(mockRoutingContext.pathParam("taskId")).thenReturn("task789"); + HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); + when(mockHttpResponse.getStatusCode()).thenReturn(200); + when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task789\"}"); + + String requestBody = """ + { + "metadata": {} + } + """; + + ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); + when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString(), anyString())) + .thenReturn(mockHttpResponse); + + // Act + routes.cancelTask(requestBody, mockRoutingContext); + + // Assert + verify(mockRestHandler).cancelTask(any(ServerCallContext.class), anyString(), bodyCaptor.capture(), eq("task789")); + String capturedBody = bodyCaptor.getValue(); + assertNotNull(capturedBody); + assertEquals(requestBody, capturedBody); + } + + @Test + public void testCancelTask_WithNoMetadataField() { + // Arrange + when(mockRoutingContext.pathParam("taskId")).thenReturn("task999"); + HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); + when(mockHttpResponse.getStatusCode()).thenReturn(200); + when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task999\"}"); + + String requestBody = "{}"; + + ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); + when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString(), anyString())) + .thenReturn(mockHttpResponse); + + // Act + routes.cancelTask(requestBody, mockRoutingContext); + + // Assert + verify(mockRestHandler).cancelTask(any(ServerCallContext.class), anyString(), bodyCaptor.capture(), eq("task999")); + String capturedBody = bodyCaptor.getValue(); + assertNotNull(capturedBody); + assertEquals(requestBody, capturedBody); + } + + @Test + public void testCancelTask_WithNullBody() { + // Arrange + when(mockRoutingContext.pathParam("taskId")).thenReturn("task111"); + HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); + when(mockHttpResponse.getStatusCode()).thenReturn(200); + when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task111\"}"); + + ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); + when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString(), anyString())) + .thenReturn(mockHttpResponse); + + // Act + routes.cancelTask(null, mockRoutingContext); + + // Assert + verify(mockRestHandler).cancelTask(any(ServerCallContext.class), anyString(), bodyCaptor.capture(), eq("task111")); + String capturedBody = bodyCaptor.getValue(); + assertNull(capturedBody); + } + + @Test + public void testCancelTask_WithComplexMetadata() { + // Arrange + when(mockRoutingContext.pathParam("taskId")).thenReturn("task222"); + HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); + when(mockHttpResponse.getStatusCode()).thenReturn(200); + when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task222\"}"); + + String requestBody = """ + { + "metadata": { + "cancellation_reason": "timeout", + "retry_count": 3, + "user_id": "user_abc123", + "timestamp": "2024-01-01T00:00:00Z", + "nested": { + "key1": "value1", + "key2": "value2" + } + } + } + """; + + ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); + when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString(), anyString())) + .thenReturn(mockHttpResponse); + + // Act + routes.cancelTask(requestBody, mockRoutingContext); + + // Assert + verify(mockRestHandler).cancelTask(any(ServerCallContext.class), anyString(), bodyCaptor.capture(), eq("task222")); + String capturedBody = bodyCaptor.getValue(); + assertNotNull(capturedBody); + assertEquals(requestBody, capturedBody); + } + @Test public void testSubscribeTask_MethodNameSetInContext() { // Arrange 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 2023fc7ac..65d622f5d 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 @@ -45,6 +45,7 @@ import io.a2a.server.util.async.EventConsumerExecutorProducer.EventConsumerExecutor; import io.a2a.server.util.async.Internal; import io.a2a.spec.A2AError; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.Event; import io.a2a.spec.EventKind; @@ -359,7 +360,7 @@ public ListTasksResult onListTasks(ListTasksParams params, ServerCallContext con } @Override - public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws A2AError { + public Task onCancelTask(CancelTaskParams params, ServerCallContext context) throws A2AError { Task task = taskStore.get(params.id()); if (task == null) { throw new TaskNotFoundError(); 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 ff6139654..b41a8ac76 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 @@ -5,6 +5,7 @@ import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.ServerCallContext; import io.a2a.spec.A2AError; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetTaskPushNotificationConfigParams; @@ -28,7 +29,7 @@ ListTasksResult onListTasks( ServerCallContext context) throws A2AError; Task onCancelTask( - TaskIdParams params, + CancelTaskParams params, ServerCallContext context) throws A2AError; EventKind onMessageSend( diff --git a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java index ba02222e6..fec2386cc 100644 --- a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java +++ b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java @@ -9,7 +9,7 @@ import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; 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.ListTaskPushNotificationConfigsResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; @@ -120,7 +120,7 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse\n\022AuthenticationInfo\022\023\n\006scheme\030\001 \001(" + - "\tB\003\340A\002\022\023\n\013credentials\030\002 \001(\t\"p\n\016AgentInte" + - "rface\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\035\n\020protocol_bind" + - "ing\030\002 \001(\tB\003\340A\002\022\016\n\006tenant\030\003 \001(\t\022\035\n\020protoc" + - "ol_version\030\004 \001(\tB\003\340A\002\"\314\005\n\tAgentCard\022\021\n\004n" + - "ame\030\001 \001(\tB\003\340A\002\022\030\n\013description\030\002 \001(\tB\003\340A\002" + - "\0229\n\024supported_interfaces\030\023 \003(\0132\026.a2a.v1." + - "AgentInterfaceB\003\340A\002\022\'\n\010provider\030\004 \001(\0132\025." + - "a2a.v1.AgentProvider\022\024\n\007version\030\005 \001(\tB\003\340" + - "A\002\022\036\n\021documentation_url\030\006 \001(\tH\000\210\001\001\0224\n\014ca" + - "pabilities\030\007 \001(\0132\031.a2a.v1.AgentCapabilit" + - "iesB\003\340A\002\022@\n\020security_schemes\030\010 \003(\0132&.a2a" + - ".v1.AgentCard.SecuritySchemesEntry\022:\n\025se" + - "curity_requirements\030\r \003(\0132\033.a2a.v1.Secur" + - "ityRequirement\022 \n\023default_input_modes\030\n " + - "\003(\tB\003\340A\002\022!\n\024default_output_modes\030\013 \003(\tB\003" + - "\340A\002\022\'\n\006skills\030\014 \003(\0132\022.a2a.v1.AgentSkillB" + - "\003\340A\002\022.\n\nsignatures\030\021 \003(\0132\032.a2a.v1.AgentC" + - "ardSignature\022\025\n\010icon_url\030\022 \001(\tH\001\210\001\001\032N\n\024S" + - "ecuritySchemesEntry\022\013\n\003key\030\001 \001(\t\022%\n\005valu" + - "e\030\002 \001(\0132\026.a2a.v1.SecurityScheme:\0028\001B\024\n\022_" + - "documentation_urlB\013\n\t_icon_urlJ\004\010\003\020\004J\004\010\t" + - "\020\nJ\004\010\016\020\017J\004\010\017\020\020J\004\010\020\020\021\"<\n\rAgentProvider\022\020\n" + - "\003url\030\001 \001(\tB\003\340A\002\022\031\n\014organization\030\002 \001(\tB\003\340" + - "A\002\"\335\001\n\021AgentCapabilities\022\026\n\tstreaming\030\001 " + - "\001(\010H\000\210\001\001\022\037\n\022push_notifications\030\002 \001(\010H\001\210\001" + - "\001\022*\n\nextensions\030\003 \003(\0132\026.a2a.v1.AgentExte" + - "nsion\022 \n\023extended_agent_card\030\005 \001(\010H\002\210\001\001B" + - "\014\n\n_streamingB\025\n\023_push_notificationsB\026\n\024" + - "_extended_agent_cardJ\004\010\004\020\005\"m\n\016AgentExten" + - "sion\022\013\n\003uri\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022\020" + - "\n\010required\030\003 \001(\010\022\'\n\006params\030\004 \001(\0132\027.googl" + - "e.protobuf.Struct\"\326\001\n\nAgentSkill\022\017\n\002id\030\001" + - " \001(\tB\003\340A\002\022\021\n\004name\030\002 \001(\tB\003\340A\002\022\030\n\013descript" + - "ion\030\003 \001(\tB\003\340A\002\022\021\n\004tags\030\004 \003(\tB\003\340A\002\022\020\n\010exa" + - "mples\030\005 \003(\t\022\023\n\013input_modes\030\006 \003(\t\022\024\n\014outp" + - "ut_modes\030\007 \003(\t\022:\n\025security_requirements\030" + - "\010 \003(\0132\033.a2a.v1.SecurityRequirement\"m\n\022Ag" + - "entCardSignature\022\026\n\tprotected\030\001 \001(\tB\003\340A\002" + - "\022\026\n\tsignature\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\013" + - "2\027.google.protobuf.Struct\"\232\001\n\032TaskPushNo" + - "tificationConfig\022\016\n\006tenant\030\004 \001(\t\022\017\n\002id\030\001" + - " \001(\tB\003\340A\002\022\024\n\007task_id\030\003 \001(\tB\003\340A\002\022E\n\030push_" + - "notification_config\030\002 \001(\0132\036.a2a.v1.PushN" + - "otificationConfigB\003\340A\002\"\032\n\nStringList\022\014\n\004" + - "list\030\001 \003(\t\"\224\001\n\023SecurityRequirement\0229\n\007sc" + - "hemes\030\001 \003(\0132(.a2a.v1.SecurityRequirement" + - ".SchemesEntry\032B\n\014SchemesEntry\022\013\n\003key\030\001 \001" + - "(\t\022!\n\005value\030\002 \001(\0132\022.a2a.v1.StringList:\0028" + - "\001\"\361\002\n\016SecurityScheme\022?\n\027api_key_security" + - "_scheme\030\001 \001(\0132\034.a2a.v1.APIKeySecuritySch" + - "emeH\000\022C\n\031http_auth_security_scheme\030\002 \001(\013" + - "2\036.a2a.v1.HTTPAuthSecuritySchemeH\000\022>\n\026oa" + - "uth2_security_scheme\030\003 \001(\0132\034.a2a.v1.OAut" + - "h2SecuritySchemeH\000\022N\n\037open_id_connect_se" + - "curity_scheme\030\004 \001(\0132#.a2a.v1.OpenIdConne" + - "ctSecuritySchemeH\000\022?\n\024mtls_security_sche" + - "me\030\005 \001(\0132\037.a2a.v1.MutualTlsSecuritySchem" + - "eH\000B\010\n\006scheme\"U\n\024APIKeySecurityScheme\022\023\n" + - "\013description\030\001 \001(\t\022\025\n\010location\030\002 \001(\tB\003\340A" + - "\002\022\021\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026HTTPAuthSecurity" + - "Scheme\022\023\n\013description\030\001 \001(\t\022\023\n\006scheme\030\002 " + - "\001(\tB\003\340A\002\022\025\n\rbearer_format\030\003 \001(\t\"p\n\024OAuth" + - "2SecurityScheme\022\023\n\013description\030\001 \001(\t\022&\n\005" + - "flows\030\002 \001(\0132\022.a2a.v1.OAuthFlowsB\003\340A\002\022\033\n\023" + - "oauth2_metadata_url\030\003 \001(\t\"T\n\033OpenIdConne" + - "ctSecurityScheme\022\023\n\013description\030\001 \001(\t\022 \n" + - "\023open_id_connect_url\030\002 \001(\tB\003\340A\002\".\n\027Mutua" + - "lTlsSecurityScheme\022\023\n\013description\030\001 \001(\t\"" + - "\262\002\n\nOAuthFlows\022@\n\022authorization_code\030\001 \001" + - "(\0132\".a2a.v1.AuthorizationCodeOAuthFlowH\000" + - "\022@\n\022client_credentials\030\002 \001(\0132\".a2a.v1.Cl" + - "ientCredentialsOAuthFlowH\000\0221\n\010implicit\030\003" + - " \001(\0132\031.a2a.v1.ImplicitOAuthFlowB\002\030\001H\000\0221\n" + - "\010password\030\004 \001(\0132\031.a2a.v1.PasswordOAuthFl" + - "owB\002\030\001H\000\0222\n\013device_code\030\005 \001(\0132\033.a2a.v1.D" + - "eviceCodeOAuthFlowH\000B\006\n\004flow\"\364\001\n\032Authori" + - "zationCodeOAuthFlow\022\036\n\021authorization_url" + - "\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013r" + - "efresh_url\030\003 \001(\t\022C\n\006scopes\030\004 \003(\0132..a2a.v" + - "1.AuthorizationCodeOAuthFlow.ScopesEntry" + - "B\003\340A\002\022\025\n\rpkce_required\030\005 \001(\010\032-\n\013ScopesEn" + - "try\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\275\001\n\032" + - "ClientCredentialsOAuthFlow\022\026\n\ttoken_url\030" + - "\001 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022C\n\006scope" + - "s\030\003 \003(\0132..a2a.v1.ClientCredentialsOAuthF" + - "low.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003k" + - "ey\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\251\001\n\021Implicit" + - "OAuthFlow\022\031\n\021authorization_url\030\001 \001(\t\022\023\n\013" + - "refresh_url\030\002 \001(\t\0225\n\006scopes\030\003 \003(\0132%.a2a." + - "v1.ImplicitOAuthFlow.ScopesEntry\032-\n\013Scop" + - "esEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"" + - "\241\001\n\021PasswordOAuthFlow\022\021\n\ttoken_url\030\001 \001(\t" + - "\022\023\n\013refresh_url\030\002 \001(\t\0225\n\006scopes\030\003 \003(\0132%." + - "a2a.v1.PasswordOAuthFlow.ScopesEntry\032-\n\013" + - "ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:" + - "\0028\001\"\326\001\n\023DeviceCodeOAuthFlow\022%\n\030device_au" + - "thorization_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030" + - "\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001(\t\022<\n\006scope" + - "s\030\004 \003(\0132\'.a2a.v1.DeviceCodeOAuthFlow.Sco" + - "pesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(" + - "\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\257\001\n\022SendMessageRequ" + - "est\022\016\n\006tenant\030\004 \001(\t\022%\n\007message\030\001 \001(\0132\017.a" + - "2a.v1.MessageB\003\340A\002\0227\n\rconfiguration\030\002 \001(" + - "\0132 .a2a.v1.SendMessageConfiguration\022)\n\010m" + - "etadata\030\003 \001(\0132\027.google.protobuf.Struct\"a" + - "\n\016GetTaskRequest\022\016\n\006tenant\030\003 \001(\t\022\017\n\002id\030\001" + - " \001(\tB\003\340A\002\022\033\n\016history_length\030\002 \001(\005H\000\210\001\001B\021" + - "\n\017_history_length\"\265\002\n\020ListTasksRequest\022\016" + - "\n\006tenant\030\t \001(\t\022\022\n\ncontext_id\030\001 \001(\t\022!\n\006st" + - "atus\030\002 \001(\0162\021.a2a.v1.TaskState\022\026\n\tpage_si" + - "ze\030\003 \001(\005H\000\210\001\001\022\022\n\npage_token\030\004 \001(\t\022\033\n\016his" + - "tory_length\030\005 \001(\005H\001\210\001\001\022:\n\026status_timesta" + - "mp_after\030\006 \001(\0132\032.google.protobuf.Timesta" + - "mp\022\036\n\021include_artifacts\030\007 \001(\010H\002\210\001\001B\014\n\n_p" + - "age_sizeB\021\n\017_history_lengthB\024\n\022_include_" + - "artifacts\"\204\001\n\021ListTasksResponse\022 \n\005tasks" + - "\030\001 \003(\0132\014.a2a.v1.TaskB\003\340A\002\022\034\n\017next_page_t" + - "oken\030\002 \001(\tB\003\340A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022" + - "\027\n\ntotal_size\030\004 \001(\005B\003\340A\002\"4\n\021CancelTaskRe" + - "quest\022\016\n\006tenant\030\002 \001(\t\022\017\n\002id\030\001 \001(\tB\003\340A\002\"]" + - "\n$GetTaskPushNotificationConfigRequest\022\016" + - "\n\006tenant\030\002 \001(\t\022\024\n\007task_id\030\003 \001(\tB\003\340A\002\022\017\n\002" + - "id\030\001 \001(\tB\003\340A\002\"`\n\'DeleteTaskPushNotificat" + - "ionConfigRequest\022\016\n\006tenant\030\002 \001(\t\022\024\n\007task" + - "_id\030\003 \001(\tB\003\340A\002\022\017\n\002id\030\001 \001(\tB\003\340A\002\"\242\001\n\'Crea" + - "teTaskPushNotificationConfigRequest\022\016\n\006t" + - "enant\030\004 \001(\t\022\024\n\007task_id\030\001 \001(\tB\003\340A\002\022\026\n\tcon" + - "fig_id\030\002 \001(\tB\003\340A\002\0223\n\006config\030\005 \001(\0132\036.a2a." + - "v1.PushNotificationConfigB\003\340A\002J\004\010\003\020\004\"9\n\026" + - "SubscribeToTaskRequest\022\016\n\006tenant\030\002 \001(\t\022\017" + - "\n\002id\030\001 \001(\tB\003\340A\002\"t\n%ListTaskPushNotificat" + - "ionConfigRequest\022\016\n\006tenant\030\004 \001(\t\022\024\n\007task" + - "_id\030\001 \001(\tB\003\340A\002\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npag" + - "e_token\030\003 \001(\t\"-\n\033GetExtendedAgentCardReq" + - "uest\022\016\n\006tenant\030\001 \001(\t\"b\n\023SendMessageRespo" + - "nse\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022\"\n\007mes" + - "sage\030\002 \001(\0132\017.a2a.v1.MessageH\000B\t\n\007payload" + - "\"\321\001\n\016StreamResponse\022\034\n\004task\030\001 \001(\0132\014.a2a." + - "v1.TaskH\000\022\"\n\007message\030\002 \001(\0132\017.a2a.v1.Mess" + - "ageH\000\0226\n\rstatus_update\030\003 \001(\0132\035.a2a.v1.Ta" + - "skStatusUpdateEventH\000\022:\n\017artifact_update" + - "\030\004 \001(\0132\037.a2a.v1.TaskArtifactUpdateEventH" + - "\000B\t\n\007payload\"v\n&ListTaskPushNotification" + - "ConfigResponse\0223\n\007configs\030\001 \003(\0132\".a2a.v1" + - ".TaskPushNotificationConfig\022\027\n\017next_page" + - "_token\030\002 \001(\t*\371\001\n\tTaskState\022\032\n\026TASK_STATE" + - "_UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMITTED\020\001" + - "\022\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_STATE_C" + - "OMPLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022\027\n\023TAS" + - "K_STATE_CANCELED\020\005\022\035\n\031TASK_STATE_INPUT_R" + - "EQUIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020\007\022\034\n\030TA" + - "SK_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE" + - "_UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AG" + - "ENT\020\0022\352\016\n\nA2AService\022}\n\013SendMessage\022\032.a2" + - "a.v1.SendMessageRequest\032\033.a2a.v1.SendMes" + - "sageResponse\"5\202\323\344\223\002/\"\r/message:send:\001*Z\033" + - "\"\026/{tenant}/message:send:\001*\022\207\001\n\024SendStre" + - "amingMessage\022\032.a2a.v1.SendMessageRequest" + - "\032\026.a2a.v1.StreamResponse\"9\202\323\344\223\0023\"\017/messa" + - "ge:stream:\001*Z\035\"\030/{tenant}/message:stream" + - ":\001*0\001\022e\n\007GetTask\022\026.a2a.v1.GetTaskRequest" + - "\032\014.a2a.v1.Task\"4\332A\002id\202\323\344\223\002)\022\r/tasks/{id=" + - "*}Z\030\022\026/{tenant}/tasks/{id=*}\022c\n\tListTask" + - "s\022\030.a2a.v1.ListTasksRequest\032\031.a2a.v1.Lis" + - "tTasksResponse\"!\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tena" + - "nt}/tasks\022z\n\nCancelTask\022\031.a2a.v1.CancelT" + - "askRequest\032\014.a2a.v1.Task\"C\202\323\344\223\002=\"\024/tasks" + - "/{id=*}:cancel:\001*Z\"\"\035/{tenant}/tasks/{id" + - "=*}:cancel:\001*\022\220\001\n\017SubscribeToTask\022\036.a2a." + - "v1.SubscribeToTaskRequest\032\026.a2a.v1.Strea" + - "mResponse\"C\202\323\344\223\002=\022\027/tasks/{id=*}:subscri" + - "beZ\"\022 /{tenant}/tasks/{id=*}:subscribe0\001" + - "\022\204\002\n CreateTaskPushNotificationConfig\022/." + - "a2a.v1.CreateTaskPushNotificationConfigR" + - "equest\032\".a2a.v1.TaskPushNotificationConf" + - "ig\"\212\001\332A\016task_id,config\202\323\344\223\002s\"*/tasks/{ta" + - "sk_id=*}/pushNotificationConfigs:\006config" + - "Z=\"3/{tenant}/tasks/{task_id=*}/pushNoti" + - "ficationConfigs:\006config\022\370\001\n\035GetTaskPushN" + - "otificationConfig\022,.a2a.v1.GetTaskPushNo" + - "tificationConfigRequest\032\".a2a.v1.TaskPus" + - "hNotificationConfig\"\204\001\332A\ntask_id,id\202\323\344\223\002" + - "q\0221/tasks/{task_id=*}/pushNotificationCo" + - "nfigs/{id=*}Z<\022:/{tenant}/tasks/{task_id" + - "=*}/pushNotificationConfigs/{id=*}\022\364\001\n\036L" + - "istTaskPushNotificationConfig\022-.a2a.v1.L" + - "istTaskPushNotificationConfigRequest\032..a" + - "2a.v1.ListTaskPushNotificationConfigResp" + - "onse\"s\332A\007task_id\202\323\344\223\002c\022*/tasks/{task_id=" + - "*}/pushNotificationConfigsZ5\0223/{tenant}/" + - "tasks/{task_id=*}/pushNotificationConfig" + - "s\022\211\001\n\024GetExtendedAgentCard\022#.a2a.v1.GetE" + - "xtendedAgentCardRequest\032\021.a2a.v1.AgentCa" + - "rd\"9\202\323\344\223\0023\022\022/extendedAgentCardZ\035\022\033/{tena" + - "nt}/extendedAgentCard\022\362\001\n DeleteTaskPush" + - "NotificationConfig\022/.a2a.v1.DeleteTaskPu" + - "shNotificationConfigRequest\032\026.google.pro" + - "tobuf.Empty\"\204\001\332A\ntask_id,id\202\323\344\223\002q*1/task" + - "s/{task_id=*}/pushNotificationConfigs/{i" + - "d=*}Z<*:/{tenant}/tasks/{task_id=*}/push" + - "NotificationConfigs/{id=*}B7\n\013io.a2a.grp" + - "cB\003A2AP\001Z\030google.golang.org/a2a/v1\252\002\006A2a" + - ".V1b\006proto3" + "\n\ta2a.proto\022\tlf.a2a.v1\032\034google/api/annot" + + "ations.proto\032\027google/api/client.proto\032\037g" + + "oogle/api/field_behavior.proto\032\033google/p" + + "rotobuf/empty.proto\032\034google/protobuf/str" + + "uct.proto\032\037google/protobuf/timestamp.pro" + + "to\"\300\001\n\030SendMessageConfiguration\022\035\n\025accep" + + "ted_output_modes\030\001 \003(\t\022C\n\030push_notificat" + + "ion_config\030\002 \001(\0132!.lf.a2a.v1.PushNotific" + + "ationConfig\022\033\n\016history_length\030\003 \001(\005H\000\210\001\001" + + "\022\020\n\010blocking\030\004 \001(\010B\021\n\017_history_length\"\324\001" + + "\n\004Task\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 " + + "\001(\tB\003\340A\002\022*\n\006status\030\003 \001(\0132\025.lf.a2a.v1.Tas" + + "kStatusB\003\340A\002\022&\n\tartifacts\030\004 \003(\0132\023.lf.a2a" + + ".v1.Artifact\022#\n\007history\030\005 \003(\0132\022.lf.a2a.v" + + "1.Message\022)\n\010metadata\030\006 \001(\0132\027.google.pro" + + "tobuf.Struct\"\212\001\n\nTaskStatus\022(\n\005state\030\001 \001" + + "(\0162\024.lf.a2a.v1.TaskStateB\003\340A\002\022#\n\007message" + + "\030\002 \001(\0132\022.lf.a2a.v1.Message\022-\n\ttimestamp\030" + + "\003 \001(\0132\032.google.protobuf.Timestamp\"\270\001\n\004Pa" + + "rt\022\016\n\004text\030\001 \001(\tH\000\022\r\n\003raw\030\002 \001(\014H\000\022\r\n\003url" + + "\030\003 \001(\tH\000\022&\n\004data\030\004 \001(\0132\026.google.protobuf" + + ".ValueH\000\022)\n\010metadata\030\005 \001(\0132\027.google.prot" + + "obuf.Struct\022\020\n\010filename\030\006 \001(\t\022\022\n\nmedia_t" + + "ype\030\007 \001(\tB\t\n\007content\"\353\001\n\007Message\022\027\n\nmess" + + "age_id\030\001 \001(\tB\003\340A\002\022\022\n\ncontext_id\030\002 \001(\t\022\017\n" + + "\007task_id\030\003 \001(\t\022\"\n\004role\030\004 \001(\0162\017.lf.a2a.v1" + + ".RoleB\003\340A\002\022#\n\005parts\030\005 \003(\0132\017.lf.a2a.v1.Pa" + + "rtB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027.google.proto" + + "buf.Struct\022\022\n\nextensions\030\007 \003(\t\022\032\n\022refere" + + "nce_task_ids\030\010 \003(\t\"\253\001\n\010Artifact\022\030\n\013artif" + + "act_id\030\001 \001(\tB\003\340A\002\022\014\n\004name\030\002 \001(\t\022\023\n\013descr" + + "iption\030\003 \001(\t\022#\n\005parts\030\004 \003(\0132\017.lf.a2a.v1." + + "PartB\003\340A\002\022)\n\010metadata\030\005 \001(\0132\027.google.pro" + + "tobuf.Struct\022\022\n\nextensions\030\006 \003(\t\"\235\001\n\025Tas" + + "kStatusUpdateEvent\022\024\n\007task_id\030\001 \001(\tB\003\340A\002" + + "\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022*\n\006status\030\003 \001(" + + "\0132\025.lf.a2a.v1.TaskStatusB\003\340A\002\022)\n\010metadat" + + "a\030\004 \001(\0132\027.google.protobuf.Struct\"\303\001\n\027Tas" + + "kArtifactUpdateEvent\022\024\n\007task_id\030\001 \001(\tB\003\340" + + "A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022*\n\010artifact\030" + + "\003 \001(\0132\023.lf.a2a.v1.ArtifactB\003\340A\002\022\016\n\006appen" + + "d\030\004 \001(\010\022\022\n\nlast_chunk\030\005 \001(\010\022)\n\010metadata\030" + + "\006 \001(\0132\027.google.protobuf.Struct\"|\n\026PushNo" + + "tificationConfig\022\n\n\002id\030\001 \001(\t\022\020\n\003url\030\002 \001(" + + "\tB\003\340A\002\022\r\n\005token\030\003 \001(\t\0225\n\016authentication\030" + + "\004 \001(\0132\035.lf.a2a.v1.AuthenticationInfo\">\n\022" + + "AuthenticationInfo\022\023\n\006scheme\030\001 \001(\tB\003\340A\002\022" + + "\023\n\013credentials\030\002 \001(\t\"p\n\016AgentInterface\022\020" + + "\n\003url\030\001 \001(\tB\003\340A\002\022\035\n\020protocol_binding\030\002 \001" + + "(\tB\003\340A\002\022\016\n\006tenant\030\003 \001(\t\022\035\n\020protocol_vers" + + "ion\030\004 \001(\tB\003\340A\002\"\306\005\n\tAgentCard\022\021\n\004name\030\001 \001" + + "(\tB\003\340A\002\022\030\n\013description\030\002 \001(\tB\003\340A\002\022<\n\024sup" + + "ported_interfaces\030\003 \003(\0132\031.lf.a2a.v1.Agen" + + "tInterfaceB\003\340A\002\022*\n\010provider\030\004 \001(\0132\030.lf.a" + + "2a.v1.AgentProvider\022\024\n\007version\030\005 \001(\tB\003\340A" + + "\002\022\036\n\021documentation_url\030\006 \001(\tH\000\210\001\001\0227\n\014cap" + + "abilities\030\007 \001(\0132\034.lf.a2a.v1.AgentCapabil" + + "itiesB\003\340A\002\022C\n\020security_schemes\030\010 \003(\0132).l" + + "f.a2a.v1.AgentCard.SecuritySchemesEntry\022" + + "=\n\025security_requirements\030\t \003(\0132\036.lf.a2a." + + "v1.SecurityRequirement\022 \n\023default_input_" + + "modes\030\n \003(\tB\003\340A\002\022!\n\024default_output_modes" + + "\030\013 \003(\tB\003\340A\002\022*\n\006skills\030\014 \003(\0132\025.lf.a2a.v1." + + "AgentSkillB\003\340A\002\0221\n\nsignatures\030\r \003(\0132\035.lf" + + ".a2a.v1.AgentCardSignature\022\025\n\010icon_url\030\016" + + " \001(\tH\001\210\001\001\032Q\n\024SecuritySchemesEntry\022\013\n\003key" + + "\030\001 \001(\t\022(\n\005value\030\002 \001(\0132\031.lf.a2a.v1.Securi" + + "tyScheme:\0028\001B\024\n\022_documentation_urlB\013\n\t_i" + + "con_url\"<\n\rAgentProvider\022\020\n\003url\030\001 \001(\tB\003\340" + + "A\002\022\031\n\014organization\030\002 \001(\tB\003\340A\002\"\332\001\n\021AgentC" + + "apabilities\022\026\n\tstreaming\030\001 \001(\010H\000\210\001\001\022\037\n\022p" + + "ush_notifications\030\002 \001(\010H\001\210\001\001\022-\n\nextensio" + + "ns\030\003 \003(\0132\031.lf.a2a.v1.AgentExtension\022 \n\023e" + + "xtended_agent_card\030\004 \001(\010H\002\210\001\001B\014\n\n_stream" + + "ingB\025\n\023_push_notificationsB\026\n\024_extended_" + + "agent_card\"m\n\016AgentExtension\022\013\n\003uri\030\001 \001(" + + "\t\022\023\n\013description\030\002 \001(\t\022\020\n\010required\030\003 \001(\010" + + "\022\'\n\006params\030\004 \001(\0132\027.google.protobuf.Struc" + + "t\"\331\001\n\nAgentSkill\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\021\n\004nam" + + "e\030\002 \001(\tB\003\340A\002\022\030\n\013description\030\003 \001(\tB\003\340A\002\022\021" + + "\n\004tags\030\004 \003(\tB\003\340A\002\022\020\n\010examples\030\005 \003(\t\022\023\n\013i" + + "nput_modes\030\006 \003(\t\022\024\n\014output_modes\030\007 \003(\t\022=" + + "\n\025security_requirements\030\010 \003(\0132\036.lf.a2a.v" + + "1.SecurityRequirement\"m\n\022AgentCardSignat" + + "ure\022\026\n\tprotected\030\001 \001(\tB\003\340A\002\022\026\n\tsignature" + + "\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\0132\027.google.pro" + + "tobuf.Struct\"\214\001\n\032TaskPushNotificationCon" + + "fig\022\016\n\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A" + + "\002\022H\n\030push_notification_config\030\003 \001(\0132!.lf" + + ".a2a.v1.PushNotificationConfigB\003\340A\002\"\032\n\nS" + + "tringList\022\014\n\004list\030\001 \003(\t\"\232\001\n\023SecurityRequ" + + "irement\022<\n\007schemes\030\001 \003(\0132+.lf.a2a.v1.Sec" + + "urityRequirement.SchemesEntry\032E\n\014Schemes" + + "Entry\022\013\n\003key\030\001 \001(\t\022$\n\005value\030\002 \001(\0132\025.lf.a" + + "2a.v1.StringList:\0028\001\"\200\003\n\016SecurityScheme\022" + + "B\n\027api_key_security_scheme\030\001 \001(\0132\037.lf.a2" + + "a.v1.APIKeySecuritySchemeH\000\022F\n\031http_auth" + + "_security_scheme\030\002 \001(\0132!.lf.a2a.v1.HTTPA" + + "uthSecuritySchemeH\000\022A\n\026oauth2_security_s" + + "cheme\030\003 \001(\0132\037.lf.a2a.v1.OAuth2SecuritySc" + + "hemeH\000\022Q\n\037open_id_connect_security_schem" + + "e\030\004 \001(\0132&.lf.a2a.v1.OpenIdConnectSecurit" + + "ySchemeH\000\022B\n\024mtls_security_scheme\030\005 \001(\0132" + + "\".lf.a2a.v1.MutualTlsSecuritySchemeH\000B\010\n" + + "\006scheme\"U\n\024APIKeySecurityScheme\022\023\n\013descr" + + "iption\030\001 \001(\t\022\025\n\010location\030\002 \001(\tB\003\340A\002\022\021\n\004n" + + "ame\030\003 \001(\tB\003\340A\002\"Y\n\026HTTPAuthSecurityScheme" + + "\022\023\n\013description\030\001 \001(\t\022\023\n\006scheme\030\002 \001(\tB\003\340" + + "A\002\022\025\n\rbearer_format\030\003 \001(\t\"s\n\024OAuth2Secur" + + "ityScheme\022\023\n\013description\030\001 \001(\t\022)\n\005flows\030" + + "\002 \001(\0132\025.lf.a2a.v1.OAuthFlowsB\003\340A\002\022\033\n\023oau" + + "th2_metadata_url\030\003 \001(\t\"T\n\033OpenIdConnectS" + + "ecurityScheme\022\023\n\013description\030\001 \001(\t\022 \n\023op" + + "en_id_connect_url\030\002 \001(\tB\003\340A\002\".\n\027MutualTl" + + "sSecurityScheme\022\023\n\013description\030\001 \001(\t\"\301\002\n" + + "\nOAuthFlows\022C\n\022authorization_code\030\001 \001(\0132" + + "%.lf.a2a.v1.AuthorizationCodeOAuthFlowH\000" + + "\022C\n\022client_credentials\030\002 \001(\0132%.lf.a2a.v1" + + ".ClientCredentialsOAuthFlowH\000\0224\n\010implici" + + "t\030\003 \001(\0132\034.lf.a2a.v1.ImplicitOAuthFlowB\002\030" + + "\001H\000\0224\n\010password\030\004 \001(\0132\034.lf.a2a.v1.Passwo" + + "rdOAuthFlowB\002\030\001H\000\0225\n\013device_code\030\005 \001(\0132\036" + + ".lf.a2a.v1.DeviceCodeOAuthFlowH\000B\006\n\004flow" + + "\"\367\001\n\032AuthorizationCodeOAuthFlow\022\036\n\021autho" + + "rization_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001" + + "(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001(\t\022F\n\006scopes\030\004" + + " \003(\01321.lf.a2a.v1.AuthorizationCodeOAuthF" + + "low.ScopesEntryB\003\340A\002\022\025\n\rpkce_required\030\005 " + + "\001(\010\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value" + + "\030\002 \001(\t:\0028\001\"\300\001\n\032ClientCredentialsOAuthFlo" + + "w\022\026\n\ttoken_url\030\001 \001(\tB\003\340A\002\022\023\n\013refresh_url" + + "\030\002 \001(\t\022F\n\006scopes\030\003 \003(\01321.lf.a2a.v1.Clien" + + "tCredentialsOAuthFlow.ScopesEntryB\003\340A\002\032-" + + "\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(" + + "\t:\0028\001\"\254\001\n\021ImplicitOAuthFlow\022\031\n\021authoriza" + + "tion_url\030\001 \001(\t\022\023\n\013refresh_url\030\002 \001(\t\0228\n\006s" + + "copes\030\003 \003(\0132(.lf.a2a.v1.ImplicitOAuthFlo" + + "w.ScopesEntry\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(" + + "\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\244\001\n\021PasswordOAuthFl" + + "ow\022\021\n\ttoken_url\030\001 \001(\t\022\023\n\013refresh_url\030\002 \001" + + "(\t\0228\n\006scopes\030\003 \003(\0132(.lf.a2a.v1.PasswordO" + + "AuthFlow.ScopesEntry\032-\n\013ScopesEntry\022\013\n\003k" + + "ey\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\331\001\n\023DeviceCo" + + "deOAuthFlow\022%\n\030device_authorization_url\030" + + "\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013re" + + "fresh_url\030\003 \001(\t\022?\n\006scopes\030\004 \003(\0132*.lf.a2a" + + ".v1.DeviceCodeOAuthFlow.ScopesEntryB\003\340A\002" + + "\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 " + + "\001(\t:\0028\001\"\265\001\n\022SendMessageRequest\022\016\n\006tenant" + + "\030\001 \001(\t\022(\n\007message\030\002 \001(\0132\022.lf.a2a.v1.Mess" + + "ageB\003\340A\002\022:\n\rconfiguration\030\003 \001(\0132#.lf.a2a" + + ".v1.SendMessageConfiguration\022)\n\010metadata" + + "\030\004 \001(\0132\027.google.protobuf.Struct\"a\n\016GetTa" + + "skRequest\022\016\n\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340" + + "A\002\022\033\n\016history_length\030\003 \001(\005H\000\210\001\001B\021\n\017_hist" + + "ory_length\"\270\002\n\020ListTasksRequest\022\016\n\006tenan" + + "t\030\001 \001(\t\022\022\n\ncontext_id\030\002 \001(\t\022$\n\006status\030\003 " + + "\001(\0162\024.lf.a2a.v1.TaskState\022\026\n\tpage_size\030\004" + + " \001(\005H\000\210\001\001\022\022\n\npage_token\030\005 \001(\t\022\033\n\016history" + + "_length\030\006 \001(\005H\001\210\001\001\022:\n\026status_timestamp_a" + + "fter\030\007 \001(\0132\032.google.protobuf.Timestamp\022\036" + + "\n\021include_artifacts\030\010 \001(\010H\002\210\001\001B\014\n\n_page_" + + "sizeB\021\n\017_history_lengthB\024\n\022_include_arti" + + "facts\"\207\001\n\021ListTasksResponse\022#\n\005tasks\030\001 \003" + + "(\0132\017.lf.a2a.v1.TaskB\003\340A\002\022\034\n\017next_page_to" + + "ken\030\002 \001(\tB\003\340A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022\027" + + "\n\ntotal_size\030\004 \001(\005B\003\340A\002\"_\n\021CancelTaskReq" + + "uest\022\016\n\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\022)\n" + + "\010metadata\030\003 \001(\0132\027.google.protobuf.Struct" + + "\"]\n$GetTaskPushNotificationConfigRequest" + + "\022\016\n\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A\002\022\017" + + "\n\002id\030\003 \001(\tB\003\340A\002\"`\n\'DeleteTaskPushNotific" + + "ationConfigRequest\022\016\n\006tenant\030\001 \001(\t\022\024\n\007ta" + + "sk_id\030\002 \001(\tB\003\340A\002\022\017\n\002id\030\003 \001(\tB\003\340A\002\"\207\001\n\'Cr" + + "eateTaskPushNotificationConfigRequest\022\016\n" + + "\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A\002\0226\n\006c" + + "onfig\030\003 \001(\0132!.lf.a2a.v1.PushNotification" + + "ConfigB\003\340A\002\"9\n\026SubscribeToTaskRequest\022\016\n" + + "\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\"u\n&ListTa" + + "skPushNotificationConfigsRequest\022\016\n\006tena" + + "nt\030\004 \001(\t\022\024\n\007task_id\030\001 \001(\tB\003\340A\002\022\021\n\tpage_s" + + "ize\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t\"-\n\033GetExte" + + "ndedAgentCardRequest\022\016\n\006tenant\030\001 \001(\t\"h\n\023" + + "SendMessageResponse\022\037\n\004task\030\001 \001(\0132\017.lf.a" + + "2a.v1.TaskH\000\022%\n\007message\030\002 \001(\0132\022.lf.a2a.v" + + "1.MessageH\000B\t\n\007payload\"\335\001\n\016StreamRespons" + + "e\022\037\n\004task\030\001 \001(\0132\017.lf.a2a.v1.TaskH\000\022%\n\007me" + + "ssage\030\002 \001(\0132\022.lf.a2a.v1.MessageH\000\0229\n\rsta" + + "tus_update\030\003 \001(\0132 .lf.a2a.v1.TaskStatusU" + + "pdateEventH\000\022=\n\017artifact_update\030\004 \001(\0132\"." + + "lf.a2a.v1.TaskArtifactUpdateEventH\000B\t\n\007p" + + "ayload\"z\n\'ListTaskPushNotificationConfig" + + "sResponse\0226\n\007configs\030\001 \003(\0132%.lf.a2a.v1.T" + + "askPushNotificationConfig\022\027\n\017next_page_t" + + "oken\030\002 \001(\t*\371\001\n\tTaskState\022\032\n\026TASK_STATE_U" + + "NSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMITTED\020\001\022\026" + + "\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_STATE_COM" + + "PLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022\027\n\023TASK_" + + "STATE_CANCELED\020\005\022\035\n\031TASK_STATE_INPUT_REQ" + + "UIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020\007\022\034\n\030TASK" + + "_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE_U" + + "NSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AGEN" + + "T\020\0022\256\017\n\nA2AService\022\203\001\n\013SendMessage\022\035.lf." + + "a2a.v1.SendMessageRequest\032\036.lf.a2a.v1.Se" + + "ndMessageResponse\"5\202\323\344\223\002/\"\r/message:send" + + ":\001*Z\033\"\026/{tenant}/message:send:\001*\022\215\001\n\024Sen" + + "dStreamingMessage\022\035.lf.a2a.v1.SendMessag" + + "eRequest\032\031.lf.a2a.v1.StreamResponse\"9\202\323\344" + + "\223\0023\"\017/message:stream:\001*Z\035\"\030/{tenant}/mes" + + "sage:stream:\001*0\001\022k\n\007GetTask\022\031.lf.a2a.v1." + + "GetTaskRequest\032\017.lf.a2a.v1.Task\"4\332A\002id\202\323" + + "\344\223\002)\022\r/tasks/{id=*}Z\030\022\026/{tenant}/tasks/{" + + "id=*}\022i\n\tListTasks\022\033.lf.a2a.v1.ListTasks" + + "Request\032\034.lf.a2a.v1.ListTasksResponse\"!\202" + + "\323\344\223\002\033\022\006/tasksZ\021\022\017/{tenant}/tasks\022\200\001\n\nCan" + + "celTask\022\034.lf.a2a.v1.CancelTaskRequest\032\017." + + "lf.a2a.v1.Task\"C\202\323\344\223\002=\"\024/tasks/{id=*}:ca" + + "ncel:\001*Z\"\"\035/{tenant}/tasks/{id=*}:cancel" + + ":\001*\022\226\001\n\017SubscribeToTask\022!.lf.a2a.v1.Subs" + + "cribeToTaskRequest\032\031.lf.a2a.v1.StreamRes" + + "ponse\"C\202\323\344\223\002=\022\027/tasks/{id=*}:subscribeZ\"" + + "\022 /{tenant}/tasks/{id=*}:subscribe0\001\022\212\002\n" + + " CreateTaskPushNotificationConfig\0222.lf.a" + + "2a.v1.CreateTaskPushNotificationConfigRe" + + "quest\032%.lf.a2a.v1.TaskPushNotificationCo" + + "nfig\"\212\001\332A\016task_id,config\202\323\344\223\002s\"*/tasks/{" + + "task_id=*}/pushNotificationConfigs:\006conf" + + "igZ=\"3/{tenant}/tasks/{task_id=*}/pushNo" + + "tificationConfigs:\006config\022\376\001\n\035GetTaskPus" + + "hNotificationConfig\022/.lf.a2a.v1.GetTaskP" + + "ushNotificationConfigRequest\032%.lf.a2a.v1" + + ".TaskPushNotificationConfig\"\204\001\332A\ntask_id" + + ",id\202\323\344\223\002q\0221/tasks/{task_id=*}/pushNotifi" + + "cationConfigs/{id=*}Z<\022:/{tenant}/tasks/" + + "{task_id=*}/pushNotificationConfigs/{id=" + + "*}\022\375\001\n\037ListTaskPushNotificationConfigs\0221" + + ".lf.a2a.v1.ListTaskPushNotificationConfi" + + "gsRequest\0322.lf.a2a.v1.ListTaskPushNotifi" + + "cationConfigsResponse\"s\332A\007task_id\202\323\344\223\002c\022" + + "*/tasks/{task_id=*}/pushNotificationConf" + + "igsZ5\0223/{tenant}/tasks/{task_id=*}/pushN" + + "otificationConfigs\022\217\001\n\024GetExtendedAgentC" + + "ard\022&.lf.a2a.v1.GetExtendedAgentCardRequ" + + "est\032\024.lf.a2a.v1.AgentCard\"9\202\323\344\223\0023\022\022/exte" + + "ndedAgentCardZ\035\022\033/{tenant}/extendedAgent" + + "Card\022\365\001\n DeleteTaskPushNotificationConfi" + + "g\0222.lf.a2a.v1.DeleteTaskPushNotification" + + "ConfigRequest\032\026.google.protobuf.Empty\"\204\001" + + "\332A\ntask_id,id\202\323\344\223\002q*1/tasks/{task_id=*}/" + + "pushNotificationConfigs/{id=*}Z<*:/{tena" + + "nt}/tasks/{task_id=*}/pushNotificationCo" + + "nfigs/{id=*}B=\n\013io.a2a.grpcB\003A2AP\001Z\033goog" + + "le.golang.org/lf/a2a/v1\252\002\tLf.A2a.V1b\006pro" + + "to3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -560,323 +565,323 @@ public static void registerAllExtensions( com.google.protobuf.StructProto.getDescriptor(), com.google.protobuf.TimestampProto.getDescriptor(), }); - internal_static_a2a_v1_SendMessageConfiguration_descriptor = + internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor = getDescriptor().getMessageType(0); - internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable = new + internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SendMessageConfiguration_descriptor, + internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor, new java.lang.String[] { "AcceptedOutputModes", "PushNotificationConfig", "HistoryLength", "Blocking", }); - internal_static_a2a_v1_Task_descriptor = + internal_static_lf_a2a_v1_Task_descriptor = getDescriptor().getMessageType(1); - internal_static_a2a_v1_Task_fieldAccessorTable = new + internal_static_lf_a2a_v1_Task_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Task_descriptor, + internal_static_lf_a2a_v1_Task_descriptor, new java.lang.String[] { "Id", "ContextId", "Status", "Artifacts", "History", "Metadata", }); - internal_static_a2a_v1_TaskStatus_descriptor = + internal_static_lf_a2a_v1_TaskStatus_descriptor = getDescriptor().getMessageType(2); - internal_static_a2a_v1_TaskStatus_fieldAccessorTable = new + internal_static_lf_a2a_v1_TaskStatus_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_TaskStatus_descriptor, + internal_static_lf_a2a_v1_TaskStatus_descriptor, new java.lang.String[] { "State", "Message", "Timestamp", }); - internal_static_a2a_v1_Part_descriptor = + internal_static_lf_a2a_v1_Part_descriptor = getDescriptor().getMessageType(3); - internal_static_a2a_v1_Part_fieldAccessorTable = new + internal_static_lf_a2a_v1_Part_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Part_descriptor, + internal_static_lf_a2a_v1_Part_descriptor, new java.lang.String[] { "Text", "Raw", "Url", "Data", "Metadata", "Filename", "MediaType", "Content", }); - internal_static_a2a_v1_Message_descriptor = + internal_static_lf_a2a_v1_Message_descriptor = getDescriptor().getMessageType(4); - internal_static_a2a_v1_Message_fieldAccessorTable = new + internal_static_lf_a2a_v1_Message_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Message_descriptor, + internal_static_lf_a2a_v1_Message_descriptor, new java.lang.String[] { "MessageId", "ContextId", "TaskId", "Role", "Parts", "Metadata", "Extensions", "ReferenceTaskIds", }); - internal_static_a2a_v1_Artifact_descriptor = + internal_static_lf_a2a_v1_Artifact_descriptor = getDescriptor().getMessageType(5); - internal_static_a2a_v1_Artifact_fieldAccessorTable = new + internal_static_lf_a2a_v1_Artifact_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Artifact_descriptor, + internal_static_lf_a2a_v1_Artifact_descriptor, new java.lang.String[] { "ArtifactId", "Name", "Description", "Parts", "Metadata", "Extensions", }); - internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor = + internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor = getDescriptor().getMessageType(6); - internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable = new + internal_static_lf_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor, + internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor, new java.lang.String[] { "TaskId", "ContextId", "Status", "Metadata", }); - internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor = + internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor = getDescriptor().getMessageType(7); - internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable = new + internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor, + internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor, new java.lang.String[] { "TaskId", "ContextId", "Artifact", "Append", "LastChunk", "Metadata", }); - internal_static_a2a_v1_PushNotificationConfig_descriptor = + internal_static_lf_a2a_v1_PushNotificationConfig_descriptor = getDescriptor().getMessageType(8); - internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable = new + internal_static_lf_a2a_v1_PushNotificationConfig_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_PushNotificationConfig_descriptor, + internal_static_lf_a2a_v1_PushNotificationConfig_descriptor, new java.lang.String[] { "Id", "Url", "Token", "Authentication", }); - internal_static_a2a_v1_AuthenticationInfo_descriptor = + internal_static_lf_a2a_v1_AuthenticationInfo_descriptor = getDescriptor().getMessageType(9); - internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable = new + internal_static_lf_a2a_v1_AuthenticationInfo_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AuthenticationInfo_descriptor, + internal_static_lf_a2a_v1_AuthenticationInfo_descriptor, new java.lang.String[] { "Scheme", "Credentials", }); - internal_static_a2a_v1_AgentInterface_descriptor = + internal_static_lf_a2a_v1_AgentInterface_descriptor = getDescriptor().getMessageType(10); - internal_static_a2a_v1_AgentInterface_fieldAccessorTable = new + internal_static_lf_a2a_v1_AgentInterface_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentInterface_descriptor, + internal_static_lf_a2a_v1_AgentInterface_descriptor, new java.lang.String[] { "Url", "ProtocolBinding", "Tenant", "ProtocolVersion", }); - internal_static_a2a_v1_AgentCard_descriptor = + internal_static_lf_a2a_v1_AgentCard_descriptor = getDescriptor().getMessageType(11); - internal_static_a2a_v1_AgentCard_fieldAccessorTable = new + internal_static_lf_a2a_v1_AgentCard_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentCard_descriptor, + internal_static_lf_a2a_v1_AgentCard_descriptor, new java.lang.String[] { "Name", "Description", "SupportedInterfaces", "Provider", "Version", "DocumentationUrl", "Capabilities", "SecuritySchemes", "SecurityRequirements", "DefaultInputModes", "DefaultOutputModes", "Skills", "Signatures", "IconUrl", }); - internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor = - internal_static_a2a_v1_AgentCard_descriptor.getNestedType(0); - internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_fieldAccessorTable = new + internal_static_lf_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor = + internal_static_lf_a2a_v1_AgentCard_descriptor.getNestedType(0); + internal_static_lf_a2a_v1_AgentCard_SecuritySchemesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, + internal_static_lf_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_AgentProvider_descriptor = + internal_static_lf_a2a_v1_AgentProvider_descriptor = getDescriptor().getMessageType(12); - internal_static_a2a_v1_AgentProvider_fieldAccessorTable = new + internal_static_lf_a2a_v1_AgentProvider_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentProvider_descriptor, + internal_static_lf_a2a_v1_AgentProvider_descriptor, new java.lang.String[] { "Url", "Organization", }); - internal_static_a2a_v1_AgentCapabilities_descriptor = + internal_static_lf_a2a_v1_AgentCapabilities_descriptor = getDescriptor().getMessageType(13); - internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable = new + internal_static_lf_a2a_v1_AgentCapabilities_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentCapabilities_descriptor, + internal_static_lf_a2a_v1_AgentCapabilities_descriptor, new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", "ExtendedAgentCard", }); - internal_static_a2a_v1_AgentExtension_descriptor = + internal_static_lf_a2a_v1_AgentExtension_descriptor = getDescriptor().getMessageType(14); - internal_static_a2a_v1_AgentExtension_fieldAccessorTable = new + internal_static_lf_a2a_v1_AgentExtension_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentExtension_descriptor, + internal_static_lf_a2a_v1_AgentExtension_descriptor, new java.lang.String[] { "Uri", "Description", "Required", "Params", }); - internal_static_a2a_v1_AgentSkill_descriptor = + internal_static_lf_a2a_v1_AgentSkill_descriptor = getDescriptor().getMessageType(15); - internal_static_a2a_v1_AgentSkill_fieldAccessorTable = new + internal_static_lf_a2a_v1_AgentSkill_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentSkill_descriptor, + internal_static_lf_a2a_v1_AgentSkill_descriptor, new java.lang.String[] { "Id", "Name", "Description", "Tags", "Examples", "InputModes", "OutputModes", "SecurityRequirements", }); - internal_static_a2a_v1_AgentCardSignature_descriptor = + internal_static_lf_a2a_v1_AgentCardSignature_descriptor = getDescriptor().getMessageType(16); - internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable = new + internal_static_lf_a2a_v1_AgentCardSignature_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentCardSignature_descriptor, + internal_static_lf_a2a_v1_AgentCardSignature_descriptor, new java.lang.String[] { "Protected", "Signature", "Header", }); - internal_static_a2a_v1_TaskPushNotificationConfig_descriptor = + internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor = getDescriptor().getMessageType(17); - internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable = new + internal_static_lf_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_TaskPushNotificationConfig_descriptor, - new java.lang.String[] { "Tenant", "Id", "TaskId", "PushNotificationConfig", }); - internal_static_a2a_v1_StringList_descriptor = + internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor, + new java.lang.String[] { "Tenant", "TaskId", "PushNotificationConfig", }); + internal_static_lf_a2a_v1_StringList_descriptor = getDescriptor().getMessageType(18); - internal_static_a2a_v1_StringList_fieldAccessorTable = new + internal_static_lf_a2a_v1_StringList_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_StringList_descriptor, + internal_static_lf_a2a_v1_StringList_descriptor, new java.lang.String[] { "List", }); - internal_static_a2a_v1_SecurityRequirement_descriptor = + internal_static_lf_a2a_v1_SecurityRequirement_descriptor = getDescriptor().getMessageType(19); - internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable = new + internal_static_lf_a2a_v1_SecurityRequirement_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SecurityRequirement_descriptor, + internal_static_lf_a2a_v1_SecurityRequirement_descriptor, new java.lang.String[] { "Schemes", }); - internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor = - internal_static_a2a_v1_SecurityRequirement_descriptor.getNestedType(0); - internal_static_a2a_v1_SecurityRequirement_SchemesEntry_fieldAccessorTable = new + internal_static_lf_a2a_v1_SecurityRequirement_SchemesEntry_descriptor = + internal_static_lf_a2a_v1_SecurityRequirement_descriptor.getNestedType(0); + internal_static_lf_a2a_v1_SecurityRequirement_SchemesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, + internal_static_lf_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_SecurityScheme_descriptor = + internal_static_lf_a2a_v1_SecurityScheme_descriptor = getDescriptor().getMessageType(20); - internal_static_a2a_v1_SecurityScheme_fieldAccessorTable = new + internal_static_lf_a2a_v1_SecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SecurityScheme_descriptor, + internal_static_lf_a2a_v1_SecurityScheme_descriptor, new java.lang.String[] { "ApiKeySecurityScheme", "HttpAuthSecurityScheme", "Oauth2SecurityScheme", "OpenIdConnectSecurityScheme", "MtlsSecurityScheme", "Scheme", }); - internal_static_a2a_v1_APIKeySecurityScheme_descriptor = + internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor = getDescriptor().getMessageType(21); - internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable = new + internal_static_lf_a2a_v1_APIKeySecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_APIKeySecurityScheme_descriptor, + internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor, new java.lang.String[] { "Description", "Location", "Name", }); - internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor = + internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor = getDescriptor().getMessageType(22); - internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable = new + internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor, + internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor, new java.lang.String[] { "Description", "Scheme", "BearerFormat", }); - internal_static_a2a_v1_OAuth2SecurityScheme_descriptor = + internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor = getDescriptor().getMessageType(23); - internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable = new + internal_static_lf_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_OAuth2SecurityScheme_descriptor, + internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor, new java.lang.String[] { "Description", "Flows", "Oauth2MetadataUrl", }); - internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor = + internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor = getDescriptor().getMessageType(24); - internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable = new + internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor, + internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor, new java.lang.String[] { "Description", "OpenIdConnectUrl", }); - internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor = + internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor = getDescriptor().getMessageType(25); - internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable = new + internal_static_lf_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor, + internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor, new java.lang.String[] { "Description", }); - internal_static_a2a_v1_OAuthFlows_descriptor = + internal_static_lf_a2a_v1_OAuthFlows_descriptor = getDescriptor().getMessageType(26); - internal_static_a2a_v1_OAuthFlows_fieldAccessorTable = new + internal_static_lf_a2a_v1_OAuthFlows_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_OAuthFlows_descriptor, + internal_static_lf_a2a_v1_OAuthFlows_descriptor, new java.lang.String[] { "AuthorizationCode", "ClientCredentials", "Implicit", "Password", "DeviceCode", "Flow", }); - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor = + internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor = getDescriptor().getMessageType(27); - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable = new + internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor, + internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor, new java.lang.String[] { "AuthorizationUrl", "TokenUrl", "RefreshUrl", "Scopes", "PkceRequired", }); - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new + internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor = + internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor.getNestedType(0); + internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, + internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor = + internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor = getDescriptor().getMessageType(28); - internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable = new + internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor, + internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor, new java.lang.String[] { "TokenUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_fieldAccessorTable = new + internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor = + internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor.getNestedType(0); + internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, + internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor = + internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor = getDescriptor().getMessageType(29); - internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable = new + internal_static_lf_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor, + internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor, new java.lang.String[] { "AuthorizationUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable = new + internal_static_lf_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor = + internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor.getNestedType(0); + internal_static_lf_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, + internal_static_lf_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_PasswordOAuthFlow_descriptor = + internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor = getDescriptor().getMessageType(30); - internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable = new + internal_static_lf_a2a_v1_PasswordOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_PasswordOAuthFlow_descriptor, + internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor, new java.lang.String[] { "TokenUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_PasswordOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable = new + internal_static_lf_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor = + internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor.getNestedType(0); + internal_static_lf_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, + internal_static_lf_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor = + internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor = getDescriptor().getMessageType(31); - internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable = new + internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor, + internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor, new java.lang.String[] { "DeviceAuthorizationUrl", "TokenUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new + internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor = + internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor.getNestedType(0); + internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, + internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_SendMessageRequest_descriptor = + internal_static_lf_a2a_v1_SendMessageRequest_descriptor = getDescriptor().getMessageType(32); - internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_SendMessageRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SendMessageRequest_descriptor, + internal_static_lf_a2a_v1_SendMessageRequest_descriptor, new java.lang.String[] { "Tenant", "Message", "Configuration", "Metadata", }); - internal_static_a2a_v1_GetTaskRequest_descriptor = + internal_static_lf_a2a_v1_GetTaskRequest_descriptor = getDescriptor().getMessageType(33); - internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_GetTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_GetTaskRequest_descriptor, + internal_static_lf_a2a_v1_GetTaskRequest_descriptor, new java.lang.String[] { "Tenant", "Id", "HistoryLength", }); - internal_static_a2a_v1_ListTasksRequest_descriptor = + internal_static_lf_a2a_v1_ListTasksRequest_descriptor = getDescriptor().getMessageType(34); - internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_ListTasksRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ListTasksRequest_descriptor, + internal_static_lf_a2a_v1_ListTasksRequest_descriptor, new java.lang.String[] { "Tenant", "ContextId", "Status", "PageSize", "PageToken", "HistoryLength", "StatusTimestampAfter", "IncludeArtifacts", }); - internal_static_a2a_v1_ListTasksResponse_descriptor = + internal_static_lf_a2a_v1_ListTasksResponse_descriptor = getDescriptor().getMessageType(35); - internal_static_a2a_v1_ListTasksResponse_fieldAccessorTable = new + internal_static_lf_a2a_v1_ListTasksResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ListTasksResponse_descriptor, + internal_static_lf_a2a_v1_ListTasksResponse_descriptor, new java.lang.String[] { "Tasks", "NextPageToken", "PageSize", "TotalSize", }); - internal_static_a2a_v1_CancelTaskRequest_descriptor = + internal_static_lf_a2a_v1_CancelTaskRequest_descriptor = getDescriptor().getMessageType(36); - internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_CancelTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_CancelTaskRequest_descriptor, - new java.lang.String[] { "Tenant", "Id", }); - internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor = + internal_static_lf_a2a_v1_CancelTaskRequest_descriptor, + new java.lang.String[] { "Tenant", "Id", "Metadata", }); + internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor = getDescriptor().getMessageType(37); - internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor, + internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "TaskId", "Id", }); - internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor = + internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor = getDescriptor().getMessageType(38); - internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor, + internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "TaskId", "Id", }); - internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor = + internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor = getDescriptor().getMessageType(39); - internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "TaskId", "ConfigId", "Config", }); - internal_static_a2a_v1_SubscribeToTaskRequest_descriptor = + internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor, + new java.lang.String[] { "Tenant", "TaskId", "Config", }); + internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor = getDescriptor().getMessageType(40); - internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SubscribeToTaskRequest_descriptor, + internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor, new java.lang.String[] { "Tenant", "Id", }); - internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor = + internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor = getDescriptor().getMessageType(41); - internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor, + internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor, new java.lang.String[] { "Tenant", "TaskId", "PageSize", "PageToken", }); - internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor = + internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor = getDescriptor().getMessageType(42); - internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable = new + internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor, + internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor, new java.lang.String[] { "Tenant", }); - internal_static_a2a_v1_SendMessageResponse_descriptor = + internal_static_lf_a2a_v1_SendMessageResponse_descriptor = getDescriptor().getMessageType(43); - internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable = new + internal_static_lf_a2a_v1_SendMessageResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SendMessageResponse_descriptor, + internal_static_lf_a2a_v1_SendMessageResponse_descriptor, new java.lang.String[] { "Task", "Message", "Payload", }); - internal_static_a2a_v1_StreamResponse_descriptor = + internal_static_lf_a2a_v1_StreamResponse_descriptor = getDescriptor().getMessageType(44); - internal_static_a2a_v1_StreamResponse_fieldAccessorTable = new + internal_static_lf_a2a_v1_StreamResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_StreamResponse_descriptor, + internal_static_lf_a2a_v1_StreamResponse_descriptor, new java.lang.String[] { "Task", "Message", "StatusUpdate", "ArtifactUpdate", "Payload", }); - internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor = + internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor = getDescriptor().getMessageType(45); - internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable = new + internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor, + internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor, new java.lang.String[] { "Configs", "NextPageToken", }); descriptor.resolveAllFeaturesImmutable(); com.google.api.AnnotationsProto.getDescriptor(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java index 6d179b674..b1e719d33 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java @@ -4,7 +4,7 @@ /** *
        - * A2AService defines the operations of the A2A protocol.
        + * Provides operations for interacting with agents using the A2A protocol.
          * 
        */ @io.grpc.stub.annotations.GrpcGenerated @@ -12,7 +12,7 @@ public final class A2AServiceGrpc { private A2AServiceGrpc() {} - public static final java.lang.String SERVICE_NAME = "a2a.v1.A2AService"; + public static final java.lang.String SERVICE_NAME = "lf.a2a.v1.A2AService"; // Static method descriptors that strictly reflect the proto. private static volatile io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod() return getGetTaskPushNotificationConfigMethod; } - private static volatile io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod; + private static volatile io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod; @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "ListTaskPushNotificationConfig", - requestType = io.a2a.grpc.ListTaskPushNotificationConfigRequest.class, - responseType = io.a2a.grpc.ListTaskPushNotificationConfigResponse.class, + fullMethodName = SERVICE_NAME + '/' + "ListTaskPushNotificationConfigs", + requestType = io.a2a.grpc.ListTaskPushNotificationConfigsRequest.class, + responseType = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod; - if ((getListTaskPushNotificationConfigMethod = A2AServiceGrpc.getListTaskPushNotificationConfigMethod) == null) { + public static io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod() { + io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod; + if ((getListTaskPushNotificationConfigsMethod = A2AServiceGrpc.getListTaskPushNotificationConfigsMethod) == null) { synchronized (A2AServiceGrpc.class) { - if ((getListTaskPushNotificationConfigMethod = A2AServiceGrpc.getListTaskPushNotificationConfigMethod) == null) { - A2AServiceGrpc.getListTaskPushNotificationConfigMethod = getListTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() + if ((getListTaskPushNotificationConfigsMethod = A2AServiceGrpc.getListTaskPushNotificationConfigsMethod) == null) { + A2AServiceGrpc.getListTaskPushNotificationConfigsMethod = getListTaskPushNotificationConfigsMethod = + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListTaskPushNotificationConfig")) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListTaskPushNotificationConfigs")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance())) + io.a2a.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("ListTaskPushNotificationConfig")) + io.a2a.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("ListTaskPushNotificationConfigs")) .build(); } } } - return getListTaskPushNotificationConfigMethod; + return getListTaskPushNotificationConfigsMethod; } private static volatile io.grpc.MethodDescriptor - * A2AService defines the operations of the A2A protocol. + * Provides operations for interacting with agents using the A2A protocol. *
      • */ public interface AsyncService { /** *
        -     * Send a message to the agent.
        +     * Sends a message to an agent.
              * 
        */ default void sendMessage(io.a2a.grpc.SendMessageRequest request, @@ -434,7 +434,8 @@ default void sendMessage(io.a2a.grpc.SendMessageRequest request, /** *
        -     * SendStreamingMessage is a streaming version of SendMessage.
        +     * Sends a streaming message to an agent, allowing for real-time interaction and status updates.
        +     * Streaming version of `SendMessage`
              * 
        */ default void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, @@ -444,7 +445,7 @@ default void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, /** *
        -     * Get the current state of a task from the agent.
        +     * Gets the latest state of a task.
              * 
        */ default void getTask(io.a2a.grpc.GetTaskRequest request, @@ -454,7 +455,7 @@ default void getTask(io.a2a.grpc.GetTaskRequest request, /** *
        -     * List tasks with optional filtering and pagination.
        +     * Lists tasks that match the specified filter.
              * 
        */ default void listTasks(io.a2a.grpc.ListTasksRequest request, @@ -464,7 +465,7 @@ default void listTasks(io.a2a.grpc.ListTasksRequest request, /** *
        -     * Cancel a task.
        +     * Cancels a task in progress.
              * 
        */ default void cancelTask(io.a2a.grpc.CancelTaskRequest request, @@ -474,8 +475,8 @@ default void cancelTask(io.a2a.grpc.CancelTaskRequest request, /** *
        -     * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
        -     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
        +     * Subscribes to task updates for tasks not in a terminal state.
        +     * Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected).
              * 
        */ default void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, @@ -485,7 +486,10 @@ default void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, /** *
        -     * Create a push notification config for a task.
        +     * (-- api-linter: client-libraries::4232::required-fields=disabled
        +     *     api-linter: core::0133::method-signature=disabled
        +     *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
        +     * Creates a push notification config for a task.
              * 
        */ default void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, @@ -495,7 +499,7 @@ default void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotifica /** *
        -     * Get a push notification config for a task.
        +     * Gets a push notification config for a task.
              * 
        */ default void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request, @@ -508,14 +512,14 @@ default void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationCo * Get a list of push notifications configured for a task. * */ - default void listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListTaskPushNotificationConfigMethod(), responseObserver); + default void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListTaskPushNotificationConfigsMethod(), responseObserver); } /** *
        -     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
        +     * Gets the extended agent card for the authenticated agent.
              * 
        */ default void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, @@ -525,7 +529,7 @@ default void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest reques /** *
        -     * Delete a push notification config for a task.
        +     * Deletes a push notification config for a task.
              * 
        */ default void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request, @@ -537,7 +541,7 @@ default void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotifica /** * Base class for the server implementation of the service A2AService. *
        -   * A2AService defines the operations of the A2A protocol.
        +   * Provides operations for interacting with agents using the A2A protocol.
            * 
        */ public static abstract class A2AServiceImplBase @@ -551,7 +555,7 @@ public static abstract class A2AServiceImplBase /** * A stub to allow clients to do asynchronous rpc calls to service A2AService. *
        -   * A2AService defines the operations of the A2A protocol.
        +   * Provides operations for interacting with agents using the A2A protocol.
            * 
        */ public static final class A2AServiceStub @@ -569,7 +573,7 @@ protected A2AServiceStub build( /** *
        -     * Send a message to the agent.
        +     * Sends a message to an agent.
              * 
        */ public void sendMessage(io.a2a.grpc.SendMessageRequest request, @@ -580,7 +584,8 @@ public void sendMessage(io.a2a.grpc.SendMessageRequest request, /** *
        -     * SendStreamingMessage is a streaming version of SendMessage.
        +     * Sends a streaming message to an agent, allowing for real-time interaction and status updates.
        +     * Streaming version of `SendMessage`
              * 
        */ public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, @@ -591,7 +596,7 @@ public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, /** *
        -     * Get the current state of a task from the agent.
        +     * Gets the latest state of a task.
              * 
        */ public void getTask(io.a2a.grpc.GetTaskRequest request, @@ -602,7 +607,7 @@ public void getTask(io.a2a.grpc.GetTaskRequest request, /** *
        -     * List tasks with optional filtering and pagination.
        +     * Lists tasks that match the specified filter.
              * 
        */ public void listTasks(io.a2a.grpc.ListTasksRequest request, @@ -613,7 +618,7 @@ public void listTasks(io.a2a.grpc.ListTasksRequest request, /** *
        -     * Cancel a task.
        +     * Cancels a task in progress.
              * 
        */ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, @@ -624,8 +629,8 @@ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, /** *
        -     * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
        -     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
        +     * Subscribes to task updates for tasks not in a terminal state.
        +     * Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected).
              * 
        */ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, @@ -636,7 +641,10 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, /** *
        -     * Create a push notification config for a task.
        +     * (-- api-linter: client-libraries::4232::required-fields=disabled
        +     *     api-linter: core::0133::method-signature=disabled
        +     *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
        +     * Creates a push notification config for a task.
              * 
        */ public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, @@ -647,7 +655,7 @@ public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificat /** *
        -     * Get a push notification config for a task.
        +     * Gets a push notification config for a task.
              * 
        */ public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request, @@ -661,15 +669,15 @@ public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationCon * Get a list of push notifications configured for a task. * */ - public void listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getListTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); + getChannel().newCall(getListTaskPushNotificationConfigsMethod(), getCallOptions()), request, responseObserver); } /** *
        -     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
        +     * Gets the extended agent card for the authenticated agent.
              * 
        */ public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, @@ -680,7 +688,7 @@ public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request /** *
        -     * Delete a push notification config for a task.
        +     * Deletes a push notification config for a task.
              * 
        */ public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request, @@ -693,7 +701,7 @@ public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificat /** * A stub to allow clients to do synchronous rpc calls to service A2AService. *
        -   * A2AService defines the operations of the A2A protocol.
        +   * Provides operations for interacting with agents using the A2A protocol.
            * 
        */ public static final class A2AServiceBlockingV2Stub @@ -711,7 +719,7 @@ protected A2AServiceBlockingV2Stub build( /** *
        -     * Send a message to the agent.
        +     * Sends a message to an agent.
              * 
        */ public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageRequest request) throws io.grpc.StatusException { @@ -721,7 +729,8 @@ public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageReques /** *
        -     * SendStreamingMessage is a streaming version of SendMessage.
        +     * Sends a streaming message to an agent, allowing for real-time interaction and status updates.
        +     * Streaming version of `SendMessage`
              * 
        */ @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") @@ -733,7 +742,7 @@ public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageReques /** *
        -     * Get the current state of a task from the agent.
        +     * Gets the latest state of a task.
              * 
        */ public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) throws io.grpc.StatusException { @@ -743,7 +752,7 @@ public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) throws io.gr /** *
        -     * List tasks with optional filtering and pagination.
        +     * Lists tasks that match the specified filter.
              * 
        */ public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest request) throws io.grpc.StatusException { @@ -753,7 +762,7 @@ public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest requ /** *
        -     * Cancel a task.
        +     * Cancels a task in progress.
              * 
        */ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws io.grpc.StatusException { @@ -763,8 +772,8 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws /** *
        -     * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
        -     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
        +     * Subscribes to task updates for tasks not in a terminal state.
        +     * Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected).
              * 
        */ @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") @@ -776,7 +785,10 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws /** *
        -     * Create a push notification config for a task.
        +     * (-- api-linter: client-libraries::4232::required-fields=disabled
        +     *     api-linter: core::0133::method-signature=disabled
        +     *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
        +     * Creates a push notification config for a task.
              * 
        */ public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { @@ -786,7 +798,7 @@ public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(i /** *
        -     * Get a push notification config for a task.
        +     * Gets a push notification config for a task.
              * 
        */ public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { @@ -799,14 +811,14 @@ public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a * Get a list of push notifications configured for a task. * */ - public io.a2a.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + public io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getListTaskPushNotificationConfigMethod(), getCallOptions(), request); + getChannel(), getListTaskPushNotificationConfigsMethod(), getCallOptions(), request); } /** *
        -     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
        +     * Gets the extended agent card for the authenticated agent.
              * 
        */ public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request) throws io.grpc.StatusException { @@ -816,7 +828,7 @@ public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCa /** *
        -     * Delete a push notification config for a task.
        +     * Deletes a push notification config for a task.
              * 
        */ public com.google.protobuf.Empty deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { @@ -828,7 +840,7 @@ public com.google.protobuf.Empty deleteTaskPushNotificationConfig(io.a2a.grpc.De /** * A stub to allow clients to do limited synchronous rpc calls to service A2AService. *
        -   * A2AService defines the operations of the A2A protocol.
        +   * Provides operations for interacting with agents using the A2A protocol.
            * 
        */ public static final class A2AServiceBlockingStub @@ -846,7 +858,7 @@ protected A2AServiceBlockingStub build( /** *
        -     * Send a message to the agent.
        +     * Sends a message to an agent.
              * 
        */ public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageRequest request) { @@ -856,7 +868,8 @@ public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageReques /** *
        -     * SendStreamingMessage is a streaming version of SendMessage.
        +     * Sends a streaming message to an agent, allowing for real-time interaction and status updates.
        +     * Streaming version of `SendMessage`
              * 
        */ public java.util.Iterator sendStreamingMessage( @@ -867,7 +880,7 @@ public java.util.Iterator sendStreamingMessage( /** *
        -     * Get the current state of a task from the agent.
        +     * Gets the latest state of a task.
              * 
        */ public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) { @@ -877,7 +890,7 @@ public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) { /** *
        -     * List tasks with optional filtering and pagination.
        +     * Lists tasks that match the specified filter.
              * 
        */ public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest request) { @@ -887,7 +900,7 @@ public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest requ /** *
        -     * Cancel a task.
        +     * Cancels a task in progress.
              * 
        */ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) { @@ -897,8 +910,8 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) { /** *
        -     * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
        -     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
        +     * Subscribes to task updates for tasks not in a terminal state.
        +     * Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected).
              * 
        */ public java.util.Iterator subscribeToTask( @@ -909,7 +922,10 @@ public java.util.Iterator subscribeToTask( /** *
        -     * Create a push notification config for a task.
        +     * (-- api-linter: client-libraries::4232::required-fields=disabled
        +     *     api-linter: core::0133::method-signature=disabled
        +     *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
        +     * Creates a push notification config for a task.
              * 
        */ public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) { @@ -919,7 +935,7 @@ public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(i /** *
        -     * Get a push notification config for a task.
        +     * Gets a push notification config for a task.
              * 
        */ public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request) { @@ -932,14 +948,14 @@ public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a * Get a list of push notifications configured for a task. * */ - public io.a2a.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request) { + public io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getListTaskPushNotificationConfigMethod(), getCallOptions(), request); + getChannel(), getListTaskPushNotificationConfigsMethod(), getCallOptions(), request); } /** *
        -     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
        +     * Gets the extended agent card for the authenticated agent.
              * 
        */ public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request) { @@ -949,7 +965,7 @@ public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCa /** *
        -     * Delete a push notification config for a task.
        +     * Deletes a push notification config for a task.
              * 
        */ public com.google.protobuf.Empty deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request) { @@ -961,7 +977,7 @@ public com.google.protobuf.Empty deleteTaskPushNotificationConfig(io.a2a.grpc.De /** * A stub to allow clients to do ListenableFuture-style rpc calls to service A2AService. *
        -   * A2AService defines the operations of the A2A protocol.
        +   * Provides operations for interacting with agents using the A2A protocol.
            * 
        */ public static final class A2AServiceFutureStub @@ -979,7 +995,7 @@ protected A2AServiceFutureStub build( /** *
        -     * Send a message to the agent.
        +     * Sends a message to an agent.
              * 
        */ public com.google.common.util.concurrent.ListenableFuture sendMessage( @@ -990,7 +1006,7 @@ public com.google.common.util.concurrent.ListenableFuture - * Get the current state of a task from the agent. + * Gets the latest state of a task. * */ public com.google.common.util.concurrent.ListenableFuture getTask( @@ -1001,7 +1017,7 @@ public com.google.common.util.concurrent.ListenableFuture getT /** *
        -     * List tasks with optional filtering and pagination.
        +     * Lists tasks that match the specified filter.
              * 
        */ public com.google.common.util.concurrent.ListenableFuture listTasks( @@ -1012,7 +1028,7 @@ public com.google.common.util.concurrent.ListenableFuture - * Cancel a task. + * Cancels a task in progress. * */ public com.google.common.util.concurrent.ListenableFuture cancelTask( @@ -1023,7 +1039,10 @@ public com.google.common.util.concurrent.ListenableFuture canc /** *
        -     * Create a push notification config for a task.
        +     * (-- api-linter: client-libraries::4232::required-fields=disabled
        +     *     api-linter: core::0133::method-signature=disabled
        +     *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
        +     * Creates a push notification config for a task.
              * 
        */ public com.google.common.util.concurrent.ListenableFuture createTaskPushNotificationConfig( @@ -1034,7 +1053,7 @@ public com.google.common.util.concurrent.ListenableFuture - * Get a push notification config for a task. + * Gets a push notification config for a task. * */ public com.google.common.util.concurrent.ListenableFuture getTaskPushNotificationConfig( @@ -1048,15 +1067,15 @@ public com.google.common.util.concurrent.ListenableFuture */ - public com.google.common.util.concurrent.ListenableFuture listTaskPushNotificationConfig( - io.a2a.grpc.ListTaskPushNotificationConfigRequest request) { + public com.google.common.util.concurrent.ListenableFuture listTaskPushNotificationConfigs( + io.a2a.grpc.ListTaskPushNotificationConfigsRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getListTaskPushNotificationConfigMethod(), getCallOptions()), request); + getChannel().newCall(getListTaskPushNotificationConfigsMethod(), getCallOptions()), request); } /** *
        -     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
        +     * Gets the extended agent card for the authenticated agent.
              * 
        */ public com.google.common.util.concurrent.ListenableFuture getExtendedAgentCard( @@ -1067,7 +1086,7 @@ public com.google.common.util.concurrent.ListenableFuture /** *
        -     * Delete a push notification config for a task.
        +     * Deletes a push notification config for a task.
              * 
        */ public com.google.common.util.concurrent.ListenableFuture deleteTaskPushNotificationConfig( @@ -1085,7 +1104,7 @@ public com.google.common.util.concurrent.ListenableFuture responseObserv serviceImpl.getTaskPushNotificationConfig((io.a2a.grpc.GetTaskPushNotificationConfigRequest) request, (io.grpc.stub.StreamObserver) responseObserver); break; - case METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.listTaskPushNotificationConfig((io.a2a.grpc.ListTaskPushNotificationConfigRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + case METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIGS: + serviceImpl.listTaskPushNotificationConfigs((io.a2a.grpc.ListTaskPushNotificationConfigsRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_GET_EXTENDED_AGENT_CARD: serviceImpl.getExtendedAgentCard((io.a2a.grpc.GetExtendedAgentCardRequest) request, @@ -1225,12 +1244,12 @@ public static final io.grpc.ServerServiceDefinition bindService(AsyncService ser io.a2a.grpc.TaskPushNotificationConfig>( service, METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG))) .addMethod( - getListTaskPushNotificationConfigMethod(), + getListTaskPushNotificationConfigsMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.ListTaskPushNotificationConfigRequest, - io.a2a.grpc.ListTaskPushNotificationConfigResponse>( - service, METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIG))) + io.a2a.grpc.ListTaskPushNotificationConfigsRequest, + io.a2a.grpc.ListTaskPushNotificationConfigsResponse>( + service, METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIGS))) .addMethod( getGetExtendedAgentCardMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( @@ -1301,7 +1320,7 @@ public static io.grpc.ServiceDescriptor getServiceDescriptor() { .addMethod(getSubscribeToTaskMethod()) .addMethod(getCreateTaskPushNotificationConfigMethod()) .addMethod(getGetTaskPushNotificationConfigMethod()) - .addMethod(getListTaskPushNotificationConfigMethod()) + .addMethod(getListTaskPushNotificationConfigsMethod()) .addMethod(getGetExtendedAgentCardMethod()) .addMethod(getDeleteTaskPushNotificationConfigMethod()) .build(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java index a189729df..d7c950934 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:APIKeySecurityScheme]
          * Defines a security scheme using an API key.
          * 
        * - * Protobuf type {@code a2a.v1.APIKeySecurityScheme} + * Protobuf type {@code lf.a2a.v1.APIKeySecurityScheme} */ @com.google.protobuf.Generated public final class APIKeySecurityScheme extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.APIKeySecurityScheme) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.APIKeySecurityScheme) APIKeySecuritySchemeOrBuilder { private static final long serialVersionUID = 0L; static { @@ -40,13 +39,13 @@ private APIKeySecurityScheme() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.APIKeySecurityScheme.class, io.a2a.grpc.APIKeySecurityScheme.Builder.class); } @@ -370,25 +369,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:APIKeySecurityScheme]
            * Defines a security scheme using an API key.
            * 
        * - * Protobuf type {@code a2a.v1.APIKeySecurityScheme} + * Protobuf type {@code lf.a2a.v1.APIKeySecurityScheme} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.APIKeySecurityScheme) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.APIKeySecurityScheme) io.a2a.grpc.APIKeySecuritySchemeOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.APIKeySecurityScheme.class, io.a2a.grpc.APIKeySecurityScheme.Builder.class); } @@ -416,7 +414,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor; } @java.lang.Override @@ -815,10 +813,10 @@ public Builder setNameBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.APIKeySecurityScheme) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.APIKeySecurityScheme) } - // @@protoc_insertion_point(class_scope:a2a.v1.APIKeySecurityScheme) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.APIKeySecurityScheme) private static final io.a2a.grpc.APIKeySecurityScheme DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.APIKeySecurityScheme(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java index 757464225..402c95c3c 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface APIKeySecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.APIKeySecurityScheme) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.APIKeySecurityScheme) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java index 84796af69..f01517fa3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:AgentCapabilities]
          * Defines optional capabilities supported by an agent.
          * 
        * - * Protobuf type {@code a2a.v1.AgentCapabilities} + * Protobuf type {@code lf.a2a.v1.AgentCapabilities} */ @com.google.protobuf.Generated public final class AgentCapabilities extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentCapabilities) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AgentCapabilities) AgentCapabilitiesOrBuilder { private static final long serialVersionUID = 0L; static { @@ -38,13 +37,13 @@ private AgentCapabilities() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentCapabilities.class, io.a2a.grpc.AgentCapabilities.Builder.class); } @@ -112,7 +111,7 @@ public boolean getPushNotifications() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ @java.lang.Override public java.util.List getExtensionsList() { @@ -123,7 +122,7 @@ public java.util.List getExtensionsList() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ @java.lang.Override public java.util.List @@ -135,7 +134,7 @@ public java.util.List getExtensionsList() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ @java.lang.Override public int getExtensionsCount() { @@ -146,7 +145,7 @@ public int getExtensionsCount() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ @java.lang.Override public io.a2a.grpc.AgentExtension getExtensions(int index) { @@ -157,7 +156,7 @@ public io.a2a.grpc.AgentExtension getExtensions(int index) { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ @java.lang.Override public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( @@ -165,14 +164,14 @@ public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( return extensions_.get(index); } - public static final int EXTENDED_AGENT_CARD_FIELD_NUMBER = 5; + public static final int EXTENDED_AGENT_CARD_FIELD_NUMBER = 4; private boolean extendedAgentCard_ = false; /** *
            * Indicates if the agent supports providing an extended agent card when authenticated.
            * 
        * - * optional bool extended_agent_card = 5; + * optional bool extended_agent_card = 4; * @return Whether the extendedAgentCard field is set. */ @java.lang.Override @@ -184,7 +183,7 @@ public boolean hasExtendedAgentCard() { * Indicates if the agent supports providing an extended agent card when authenticated. * * - * optional bool extended_agent_card = 5; + * optional bool extended_agent_card = 4; * @return The extendedAgentCard. */ @java.lang.Override @@ -216,7 +215,7 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) output.writeMessage(3, extensions_.get(i)); } if (((bitField0_ & 0x00000004) != 0)) { - output.writeBool(5, extendedAgentCard_); + output.writeBool(4, extendedAgentCard_); } getUnknownFields().writeTo(output); } @@ -241,7 +240,7 @@ public int getSerializedSize() { } if (((bitField0_ & 0x00000004) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeBoolSize(5, extendedAgentCard_); + .computeBoolSize(4, extendedAgentCard_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -404,25 +403,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:AgentCapabilities]
            * Defines optional capabilities supported by an agent.
            * 
        * - * Protobuf type {@code a2a.v1.AgentCapabilities} + * Protobuf type {@code lf.a2a.v1.AgentCapabilities} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCapabilities) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentCapabilities) io.a2a.grpc.AgentCapabilitiesOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentCapabilities.class, io.a2a.grpc.AgentCapabilities.Builder.class); } @@ -457,7 +455,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor; } @java.lang.Override @@ -609,11 +607,11 @@ public Builder mergeFrom( } break; } // case 26 - case 40: { + case 32: { extendedAgentCard_ = input.readBool(); bitField0_ |= 0x00000008; break; - } // case 40 + } // case 32 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -760,7 +758,7 @@ private void ensureExtensionsIsMutable() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public java.util.List getExtensionsList() { if (extensionsBuilder_ == null) { @@ -774,7 +772,7 @@ public java.util.List getExtensionsList() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public int getExtensionsCount() { if (extensionsBuilder_ == null) { @@ -788,7 +786,7 @@ public int getExtensionsCount() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public io.a2a.grpc.AgentExtension getExtensions(int index) { if (extensionsBuilder_ == null) { @@ -802,7 +800,7 @@ public io.a2a.grpc.AgentExtension getExtensions(int index) { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder setExtensions( int index, io.a2a.grpc.AgentExtension value) { @@ -823,7 +821,7 @@ public Builder setExtensions( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder setExtensions( int index, io.a2a.grpc.AgentExtension.Builder builderForValue) { @@ -841,7 +839,7 @@ public Builder setExtensions( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder addExtensions(io.a2a.grpc.AgentExtension value) { if (extensionsBuilder_ == null) { @@ -861,7 +859,7 @@ public Builder addExtensions(io.a2a.grpc.AgentExtension value) { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder addExtensions( int index, io.a2a.grpc.AgentExtension value) { @@ -882,7 +880,7 @@ public Builder addExtensions( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder addExtensions( io.a2a.grpc.AgentExtension.Builder builderForValue) { @@ -900,7 +898,7 @@ public Builder addExtensions( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder addExtensions( int index, io.a2a.grpc.AgentExtension.Builder builderForValue) { @@ -918,7 +916,7 @@ public Builder addExtensions( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder addAllExtensions( java.lang.Iterable values) { @@ -937,7 +935,7 @@ public Builder addAllExtensions( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder clearExtensions() { if (extensionsBuilder_ == null) { @@ -954,7 +952,7 @@ public Builder clearExtensions() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public Builder removeExtensions(int index) { if (extensionsBuilder_ == null) { @@ -971,7 +969,7 @@ public Builder removeExtensions(int index) { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public io.a2a.grpc.AgentExtension.Builder getExtensionsBuilder( int index) { @@ -982,7 +980,7 @@ public io.a2a.grpc.AgentExtension.Builder getExtensionsBuilder( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( int index) { @@ -996,7 +994,7 @@ public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public java.util.List getExtensionsOrBuilderList() { @@ -1011,7 +1009,7 @@ public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder() { return internalGetExtensionsFieldBuilder().addBuilder( @@ -1022,7 +1020,7 @@ public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder() { * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder( int index) { @@ -1034,7 +1032,7 @@ public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder( * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ public java.util.List getExtensionsBuilderList() { @@ -1061,7 +1059,7 @@ public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder( * Indicates if the agent supports providing an extended agent card when authenticated. * * - * optional bool extended_agent_card = 5; + * optional bool extended_agent_card = 4; * @return Whether the extendedAgentCard field is set. */ @java.lang.Override @@ -1073,7 +1071,7 @@ public boolean hasExtendedAgentCard() { * Indicates if the agent supports providing an extended agent card when authenticated. * * - * optional bool extended_agent_card = 5; + * optional bool extended_agent_card = 4; * @return The extendedAgentCard. */ @java.lang.Override @@ -1085,7 +1083,7 @@ public boolean getExtendedAgentCard() { * Indicates if the agent supports providing an extended agent card when authenticated. * * - * optional bool extended_agent_card = 5; + * optional bool extended_agent_card = 4; * @param value The extendedAgentCard to set. * @return This builder for chaining. */ @@ -1101,7 +1099,7 @@ public Builder setExtendedAgentCard(boolean value) { * Indicates if the agent supports providing an extended agent card when authenticated. * * - * optional bool extended_agent_card = 5; + * optional bool extended_agent_card = 4; * @return This builder for chaining. */ public Builder clearExtendedAgentCard() { @@ -1111,10 +1109,10 @@ public Builder clearExtendedAgentCard() { return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCapabilities) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AgentCapabilities) } - // @@protoc_insertion_point(class_scope:a2a.v1.AgentCapabilities) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentCapabilities) private static final io.a2a.grpc.AgentCapabilities DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AgentCapabilities(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java index 05c90e4d2..112329f21 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface AgentCapabilitiesOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCapabilities) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AgentCapabilities) com.google.protobuf.MessageOrBuilder { /** @@ -53,7 +53,7 @@ public interface AgentCapabilitiesOrBuilder extends * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ java.util.List getExtensionsList(); @@ -62,7 +62,7 @@ public interface AgentCapabilitiesOrBuilder extends * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ io.a2a.grpc.AgentExtension getExtensions(int index); /** @@ -70,7 +70,7 @@ public interface AgentCapabilitiesOrBuilder extends * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ int getExtensionsCount(); /** @@ -78,7 +78,7 @@ public interface AgentCapabilitiesOrBuilder extends * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ java.util.List getExtensionsOrBuilderList(); @@ -87,7 +87,7 @@ public interface AgentCapabilitiesOrBuilder extends * A list of protocol extensions supported by the agent. * * - * repeated .a2a.v1.AgentExtension extensions = 3; + * repeated .lf.a2a.v1.AgentExtension extensions = 3; */ io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( int index); @@ -97,7 +97,7 @@ io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( * Indicates if the agent supports providing an extended agent card when authenticated. * * - * optional bool extended_agent_card = 5; + * optional bool extended_agent_card = 4; * @return Whether the extendedAgentCard field is set. */ boolean hasExtendedAgentCard(); @@ -106,7 +106,7 @@ io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( * Indicates if the agent supports providing an extended agent card when authenticated. * * - * optional bool extended_agent_card = 5; + * optional bool extended_agent_card = 4; * @return The extendedAgentCard. */ boolean getExtendedAgentCard(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java index 2b06f54b8..7e75ae6a0 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java @@ -7,19 +7,18 @@ /** *
        - * --8<-- [start:AgentCard]
        - * AgentCard is a self-describing manifest for an agent. It provides essential
        + * A self-describing manifest for an agent. It provides essential
          * metadata including the agent's identity, capabilities, skills, supported
          * communication methods, and security requirements.
          * Next ID: 20
          * 
        * - * Protobuf type {@code a2a.v1.AgentCard} + * Protobuf type {@code lf.a2a.v1.AgentCard} */ @com.google.protobuf.Generated public final class AgentCard extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentCard) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AgentCard) AgentCardOrBuilder { private static final long serialVersionUID = 0L; static { @@ -53,7 +52,7 @@ private AgentCard() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -71,7 +70,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentCard.class, io.a2a.grpc.AgentCard.Builder.class); } @@ -177,15 +176,15 @@ public java.lang.String getDescription() { } } - public static final int SUPPORTED_INTERFACES_FIELD_NUMBER = 19; + public static final int SUPPORTED_INTERFACES_FIELD_NUMBER = 3; @SuppressWarnings("serial") private java.util.List supportedInterfaces_; /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List getSupportedInterfacesList() { @@ -193,10 +192,10 @@ public java.util.List getSupportedInterfacesList() { } /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List @@ -205,10 +204,10 @@ public java.util.List getSupportedInterfacesList() { } /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public int getSupportedInterfacesCount() { @@ -216,10 +215,10 @@ public int getSupportedInterfacesCount() { } /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { @@ -227,10 +226,10 @@ public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { } /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( @@ -245,7 +244,7 @@ public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; * @return Whether the provider field is set. */ @java.lang.Override @@ -257,7 +256,7 @@ public boolean hasProvider() { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; * @return The provider. */ @java.lang.Override @@ -269,7 +268,7 @@ public io.a2a.grpc.AgentProvider getProvider() { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ @java.lang.Override public io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder() { @@ -330,7 +329,7 @@ public java.lang.String getVersion() { private volatile java.lang.Object documentationUrl_ = ""; /** *
        -   * A url to provide additional documentation about the agent.
        +   * A URL providing additional documentation about the agent.
            * 
        * * optional string documentation_url = 6; @@ -342,7 +341,7 @@ public boolean hasDocumentationUrl() { } /** *
        -   * A url to provide additional documentation about the agent.
        +   * A URL providing additional documentation about the agent.
            * 
        * * optional string documentation_url = 6; @@ -363,7 +362,7 @@ public java.lang.String getDocumentationUrl() { } /** *
        -   * A url to provide additional documentation about the agent.
        +   * A URL providing additional documentation about the agent.
            * 
        * * optional string documentation_url = 6; @@ -391,7 +390,7 @@ public java.lang.String getDocumentationUrl() { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the capabilities field is set. */ @java.lang.Override @@ -403,7 +402,7 @@ public boolean hasCapabilities() { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; * @return The capabilities. */ @java.lang.Override @@ -415,7 +414,7 @@ public io.a2a.grpc.AgentCapabilities getCapabilities() { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() { @@ -428,7 +427,7 @@ private static final class SecuritySchemesDefaultEntryHolder { java.lang.String, io.a2a.grpc.SecurityScheme> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.MESSAGE, @@ -453,7 +452,7 @@ public int getSecuritySchemesCount() { * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ @java.lang.Override public boolean containsSecuritySchemes( @@ -474,7 +473,7 @@ public java.util.Map getSecuritySc * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ @java.lang.Override public java.util.Map getSecuritySchemesMap() { @@ -485,7 +484,7 @@ public java.util.Map getSecuritySc * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ @java.lang.Override public /* nullable */ @@ -503,7 +502,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ @java.lang.Override public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( @@ -517,7 +516,7 @@ public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( return map.get(key); } - public static final int SECURITY_REQUIREMENTS_FIELD_NUMBER = 13; + public static final int SECURITY_REQUIREMENTS_FIELD_NUMBER = 9; @SuppressWarnings("serial") private java.util.List securityRequirements_; /** @@ -525,7 +524,7 @@ public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ @java.lang.Override public java.util.List getSecurityRequirementsList() { @@ -536,7 +535,7 @@ public java.util.List getSecurityRequirementsLi * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ @java.lang.Override public java.util.List @@ -548,7 +547,7 @@ public java.util.List getSecurityRequirementsLi * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ @java.lang.Override public int getSecurityRequirementsCount() { @@ -559,7 +558,7 @@ public int getSecurityRequirementsCount() { * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ @java.lang.Override public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { @@ -570,7 +569,7 @@ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ @java.lang.Override public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( @@ -697,12 +696,12 @@ public java.lang.String getDefaultOutputModes(int index) { private java.util.List skills_; /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List getSkillsList() { @@ -710,12 +709,12 @@ public java.util.List getSkillsList() { } /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List @@ -724,12 +723,12 @@ public java.util.List getSkillsList() { } /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public int getSkillsCount() { @@ -737,12 +736,12 @@ public int getSkillsCount() { } /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.AgentSkill getSkills(int index) { @@ -750,12 +749,12 @@ public io.a2a.grpc.AgentSkill getSkills(int index) { } /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( @@ -763,15 +762,15 @@ public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( return skills_.get(index); } - public static final int SIGNATURES_FIELD_NUMBER = 17; + public static final int SIGNATURES_FIELD_NUMBER = 13; @SuppressWarnings("serial") private java.util.List signatures_; /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ @java.lang.Override public java.util.List getSignaturesList() { @@ -779,10 +778,10 @@ public java.util.List getSignaturesList() { } /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ @java.lang.Override public java.util.List @@ -791,10 +790,10 @@ public java.util.List getSignaturesList() { } /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ @java.lang.Override public int getSignaturesCount() { @@ -802,10 +801,10 @@ public int getSignaturesCount() { } /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ @java.lang.Override public io.a2a.grpc.AgentCardSignature getSignatures(int index) { @@ -813,10 +812,10 @@ public io.a2a.grpc.AgentCardSignature getSignatures(int index) { } /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ @java.lang.Override public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( @@ -824,15 +823,15 @@ public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( return signatures_.get(index); } - public static final int ICON_URL_FIELD_NUMBER = 18; + public static final int ICON_URL_FIELD_NUMBER = 14; @SuppressWarnings("serial") private volatile java.lang.Object iconUrl_ = ""; /** *
        -   * An optional URL to an icon for the agent.
        +   * Optional. A URL to an icon for the agent.
            * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return Whether the iconUrl field is set. */ @java.lang.Override @@ -841,10 +840,10 @@ public boolean hasIconUrl() { } /** *
        -   * An optional URL to an icon for the agent.
        +   * Optional. A URL to an icon for the agent.
            * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return The iconUrl. */ @java.lang.Override @@ -862,10 +861,10 @@ public java.lang.String getIconUrl() { } /** *
        -   * An optional URL to an icon for the agent.
        +   * Optional. A URL to an icon for the agent.
            * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return The bytes for iconUrl. */ @java.lang.Override @@ -903,6 +902,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { com.google.protobuf.GeneratedMessage.writeString(output, 2, description_); } + for (int i = 0; i < supportedInterfaces_.size(); i++) { + output.writeMessage(3, supportedInterfaces_.get(i)); + } if (((bitField0_ & 0x00000001) != 0)) { output.writeMessage(4, getProvider()); } @@ -921,6 +923,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) internalGetSecuritySchemes(), SecuritySchemesDefaultEntryHolder.defaultEntry, 8); + for (int i = 0; i < securityRequirements_.size(); i++) { + output.writeMessage(9, securityRequirements_.get(i)); + } for (int i = 0; i < defaultInputModes_.size(); i++) { com.google.protobuf.GeneratedMessage.writeString(output, 10, defaultInputModes_.getRaw(i)); } @@ -930,17 +935,11 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) for (int i = 0; i < skills_.size(); i++) { output.writeMessage(12, skills_.get(i)); } - for (int i = 0; i < securityRequirements_.size(); i++) { - output.writeMessage(13, securityRequirements_.get(i)); - } for (int i = 0; i < signatures_.size(); i++) { - output.writeMessage(17, signatures_.get(i)); + output.writeMessage(13, signatures_.get(i)); } if (((bitField0_ & 0x00000008) != 0)) { - com.google.protobuf.GeneratedMessage.writeString(output, 18, iconUrl_); - } - for (int i = 0; i < supportedInterfaces_.size(); i++) { - output.writeMessage(19, supportedInterfaces_.get(i)); + com.google.protobuf.GeneratedMessage.writeString(output, 14, iconUrl_); } getUnknownFields().writeTo(output); } @@ -957,6 +956,10 @@ public int getSerializedSize() { if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(2, description_); } + for (int i = 0; i < supportedInterfaces_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, supportedInterfaces_.get(i)); + } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream .computeMessageSize(4, getProvider()); @@ -981,6 +984,10 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(8, securitySchemes__); } + for (int i = 0; i < securityRequirements_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, securityRequirements_.get(i)); + } { int dataSize = 0; for (int i = 0; i < defaultInputModes_.size(); i++) { @@ -1001,20 +1008,12 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(12, skills_.get(i)); } - for (int i = 0; i < securityRequirements_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(13, securityRequirements_.get(i)); - } for (int i = 0; i < signatures_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(17, signatures_.get(i)); + .computeMessageSize(13, signatures_.get(i)); } if (((bitField0_ & 0x00000008) != 0)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(18, iconUrl_); - } - for (int i = 0; i < supportedInterfaces_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(19, supportedInterfaces_.get(i)); + size += com.google.protobuf.GeneratedMessage.computeStringSize(14, iconUrl_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -1231,22 +1230,21 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:AgentCard]
        -   * AgentCard is a self-describing manifest for an agent. It provides essential
        +   * A self-describing manifest for an agent. It provides essential
            * metadata including the agent's identity, capabilities, skills, supported
            * communication methods, and security requirements.
            * Next ID: 20
            * 
        * - * Protobuf type {@code a2a.v1.AgentCard} + * Protobuf type {@code lf.a2a.v1.AgentCard} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCard) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentCard) io.a2a.grpc.AgentCardOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -1274,7 +1272,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentCard.class, io.a2a.grpc.AgentCard.Builder.class); } @@ -1358,7 +1356,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor; } @java.lang.Override @@ -1675,6 +1673,19 @@ public Builder mergeFrom( bitField0_ |= 0x00000002; break; } // case 18 + case 26: { + io.a2a.grpc.AgentInterface m = + input.readMessage( + io.a2a.grpc.AgentInterface.parser(), + extensionRegistry); + if (supportedInterfacesBuilder_ == null) { + ensureSupportedInterfacesIsMutable(); + supportedInterfaces_.add(m); + } else { + supportedInterfacesBuilder_.addMessage(m); + } + break; + } // case 26 case 34: { input.readMessage( internalGetProviderFieldBuilder().getBuilder(), @@ -1708,6 +1719,19 @@ public Builder mergeFrom( bitField0_ |= 0x00000080; break; } // case 66 + case 74: { + io.a2a.grpc.SecurityRequirement m = + input.readMessage( + io.a2a.grpc.SecurityRequirement.parser(), + extensionRegistry); + if (securityRequirementsBuilder_ == null) { + ensureSecurityRequirementsIsMutable(); + securityRequirements_.add(m); + } else { + securityRequirementsBuilder_.addMessage(m); + } + break; + } // case 74 case 82: { java.lang.String s = input.readStringRequireUtf8(); ensureDefaultInputModesIsMutable(); @@ -1734,19 +1758,6 @@ public Builder mergeFrom( break; } // case 98 case 106: { - io.a2a.grpc.SecurityRequirement m = - input.readMessage( - io.a2a.grpc.SecurityRequirement.parser(), - extensionRegistry); - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(m); - } else { - securityRequirementsBuilder_.addMessage(m); - } - break; - } // case 106 - case 138: { io.a2a.grpc.AgentCardSignature m = input.readMessage( io.a2a.grpc.AgentCardSignature.parser(), @@ -1758,25 +1769,12 @@ public Builder mergeFrom( signaturesBuilder_.addMessage(m); } break; - } // case 138 - case 146: { + } // case 106 + case 114: { iconUrl_ = input.readStringRequireUtf8(); bitField0_ |= 0x00002000; break; - } // case 146 - case 154: { - io.a2a.grpc.AgentInterface m = - input.readMessage( - io.a2a.grpc.AgentInterface.parser(), - extensionRegistry); - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(m); - } else { - supportedInterfacesBuilder_.addMessage(m); - } - break; - } // case 154 + } // case 114 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -2007,10 +2005,10 @@ private void ensureSupportedInterfacesIsMutable() { /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getSupportedInterfacesList() { if (supportedInterfacesBuilder_ == null) { @@ -2021,10 +2019,10 @@ public java.util.List getSupportedInterfacesList() { } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public int getSupportedInterfacesCount() { if (supportedInterfacesBuilder_ == null) { @@ -2035,10 +2033,10 @@ public int getSupportedInterfacesCount() { } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { if (supportedInterfacesBuilder_ == null) { @@ -2049,10 +2047,10 @@ public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setSupportedInterfaces( int index, io.a2a.grpc.AgentInterface value) { @@ -2070,10 +2068,10 @@ public Builder setSupportedInterfaces( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setSupportedInterfaces( int index, io.a2a.grpc.AgentInterface.Builder builderForValue) { @@ -2088,10 +2086,10 @@ public Builder setSupportedInterfaces( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addSupportedInterfaces(io.a2a.grpc.AgentInterface value) { if (supportedInterfacesBuilder_ == null) { @@ -2108,10 +2106,10 @@ public Builder addSupportedInterfaces(io.a2a.grpc.AgentInterface value) { } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addSupportedInterfaces( int index, io.a2a.grpc.AgentInterface value) { @@ -2129,10 +2127,10 @@ public Builder addSupportedInterfaces( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addSupportedInterfaces( io.a2a.grpc.AgentInterface.Builder builderForValue) { @@ -2147,10 +2145,10 @@ public Builder addSupportedInterfaces( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addSupportedInterfaces( int index, io.a2a.grpc.AgentInterface.Builder builderForValue) { @@ -2165,10 +2163,10 @@ public Builder addSupportedInterfaces( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addAllSupportedInterfaces( java.lang.Iterable values) { @@ -2184,10 +2182,10 @@ public Builder addAllSupportedInterfaces( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearSupportedInterfaces() { if (supportedInterfacesBuilder_ == null) { @@ -2201,10 +2199,10 @@ public Builder clearSupportedInterfaces() { } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder removeSupportedInterfaces(int index) { if (supportedInterfacesBuilder_ == null) { @@ -2218,10 +2216,10 @@ public Builder removeSupportedInterfaces(int index) { } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentInterface.Builder getSupportedInterfacesBuilder( int index) { @@ -2229,10 +2227,10 @@ public io.a2a.grpc.AgentInterface.Builder getSupportedInterfacesBuilder( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( int index) { @@ -2243,10 +2241,10 @@ public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getSupportedInterfacesOrBuilderList() { @@ -2258,10 +2256,10 @@ public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder() { return internalGetSupportedInterfacesFieldBuilder().addBuilder( @@ -2269,10 +2267,10 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder() { } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder( int index) { @@ -2281,10 +2279,10 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder( } /** *
        -     * Ordered list of supported interfaces. First entry is preferred.
        +     * Ordered list of supported interfaces. The first entry is preferred.
              * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getSupportedInterfacesBuilderList() { @@ -2313,7 +2311,7 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder( * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; * @return Whether the provider field is set. */ public boolean hasProvider() { @@ -2324,7 +2322,7 @@ public boolean hasProvider() { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; * @return The provider. */ public io.a2a.grpc.AgentProvider getProvider() { @@ -2339,7 +2337,7 @@ public io.a2a.grpc.AgentProvider getProvider() { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ public Builder setProvider(io.a2a.grpc.AgentProvider value) { if (providerBuilder_ == null) { @@ -2359,7 +2357,7 @@ public Builder setProvider(io.a2a.grpc.AgentProvider value) { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ public Builder setProvider( io.a2a.grpc.AgentProvider.Builder builderForValue) { @@ -2377,7 +2375,7 @@ public Builder setProvider( * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ public Builder mergeProvider(io.a2a.grpc.AgentProvider value) { if (providerBuilder_ == null) { @@ -2402,7 +2400,7 @@ public Builder mergeProvider(io.a2a.grpc.AgentProvider value) { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ public Builder clearProvider() { bitField0_ = (bitField0_ & ~0x00000008); @@ -2419,7 +2417,7 @@ public Builder clearProvider() { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ public io.a2a.grpc.AgentProvider.Builder getProviderBuilder() { bitField0_ |= 0x00000008; @@ -2431,7 +2429,7 @@ public io.a2a.grpc.AgentProvider.Builder getProviderBuilder() { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ public io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder() { if (providerBuilder_ != null) { @@ -2446,7 +2444,7 @@ public io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder() { * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.AgentProvider, io.a2a.grpc.AgentProvider.Builder, io.a2a.grpc.AgentProviderOrBuilder> @@ -2562,7 +2560,7 @@ public Builder setVersionBytes( private java.lang.Object documentationUrl_ = ""; /** *
        -     * A url to provide additional documentation about the agent.
        +     * A URL providing additional documentation about the agent.
              * 
        * * optional string documentation_url = 6; @@ -2573,7 +2571,7 @@ public boolean hasDocumentationUrl() { } /** *
        -     * A url to provide additional documentation about the agent.
        +     * A URL providing additional documentation about the agent.
              * 
        * * optional string documentation_url = 6; @@ -2593,7 +2591,7 @@ public java.lang.String getDocumentationUrl() { } /** *
        -     * A url to provide additional documentation about the agent.
        +     * A URL providing additional documentation about the agent.
              * 
        * * optional string documentation_url = 6; @@ -2614,7 +2612,7 @@ public java.lang.String getDocumentationUrl() { } /** *
        -     * A url to provide additional documentation about the agent.
        +     * A URL providing additional documentation about the agent.
              * 
        * * optional string documentation_url = 6; @@ -2631,7 +2629,7 @@ public Builder setDocumentationUrl( } /** *
        -     * A url to provide additional documentation about the agent.
        +     * A URL providing additional documentation about the agent.
              * 
        * * optional string documentation_url = 6; @@ -2645,7 +2643,7 @@ public Builder clearDocumentationUrl() { } /** *
        -     * A url to provide additional documentation about the agent.
        +     * A URL providing additional documentation about the agent.
              * 
        * * optional string documentation_url = 6; @@ -2670,7 +2668,7 @@ public Builder setDocumentationUrlBytes( * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the capabilities field is set. */ public boolean hasCapabilities() { @@ -2681,7 +2679,7 @@ public boolean hasCapabilities() { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; * @return The capabilities. */ public io.a2a.grpc.AgentCapabilities getCapabilities() { @@ -2696,7 +2694,7 @@ public io.a2a.grpc.AgentCapabilities getCapabilities() { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setCapabilities(io.a2a.grpc.AgentCapabilities value) { if (capabilitiesBuilder_ == null) { @@ -2716,7 +2714,7 @@ public Builder setCapabilities(io.a2a.grpc.AgentCapabilities value) { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setCapabilities( io.a2a.grpc.AgentCapabilities.Builder builderForValue) { @@ -2734,7 +2732,7 @@ public Builder setCapabilities( * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) { if (capabilitiesBuilder_ == null) { @@ -2759,7 +2757,7 @@ public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearCapabilities() { bitField0_ = (bitField0_ & ~0x00000040); @@ -2776,7 +2774,7 @@ public Builder clearCapabilities() { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() { bitField0_ |= 0x00000040; @@ -2788,7 +2786,7 @@ public io.a2a.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() { if (capabilitiesBuilder_ != null) { @@ -2803,7 +2801,7 @@ public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() { * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.AgentCapabilities, io.a2a.grpc.AgentCapabilities.Builder, io.a2a.grpc.AgentCapabilitiesOrBuilder> @@ -2859,7 +2857,7 @@ public int getSecuritySchemesCount() { * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ @java.lang.Override public boolean containsSecuritySchemes( @@ -2880,7 +2878,7 @@ public java.util.Map getSecuritySc * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ @java.lang.Override public java.util.Map getSecuritySchemesMap() { @@ -2891,7 +2889,7 @@ public java.util.Map getSecuritySc * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ @java.lang.Override public /* nullable */ @@ -2908,7 +2906,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ @java.lang.Override public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( @@ -2930,7 +2928,7 @@ public Builder clearSecuritySchemes() { * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ public Builder removeSecuritySchemes( java.lang.String key) { @@ -2953,7 +2951,7 @@ public Builder removeSecuritySchemes( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ public Builder putSecuritySchemes( java.lang.String key, @@ -2970,7 +2968,7 @@ public Builder putSecuritySchemes( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ public Builder putAllSecuritySchemes( java.util.Map values) { @@ -2989,7 +2987,7 @@ public Builder putAllSecuritySchemes( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ public io.a2a.grpc.SecurityScheme.Builder putSecuritySchemesBuilderIfAbsent( java.lang.String key) { @@ -3023,7 +3021,7 @@ private void ensureSecurityRequirementsIsMutable() { * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public java.util.List getSecurityRequirementsList() { if (securityRequirementsBuilder_ == null) { @@ -3037,7 +3035,7 @@ public java.util.List getSecurityRequirementsLi * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public int getSecurityRequirementsCount() { if (securityRequirementsBuilder_ == null) { @@ -3051,7 +3049,7 @@ public int getSecurityRequirementsCount() { * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { if (securityRequirementsBuilder_ == null) { @@ -3065,7 +3063,7 @@ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder setSecurityRequirements( int index, io.a2a.grpc.SecurityRequirement value) { @@ -3086,7 +3084,7 @@ public Builder setSecurityRequirements( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder setSecurityRequirements( int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { @@ -3104,7 +3102,7 @@ public Builder setSecurityRequirements( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) { if (securityRequirementsBuilder_ == null) { @@ -3124,7 +3122,7 @@ public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) { * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder addSecurityRequirements( int index, io.a2a.grpc.SecurityRequirement value) { @@ -3145,7 +3143,7 @@ public Builder addSecurityRequirements( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder addSecurityRequirements( io.a2a.grpc.SecurityRequirement.Builder builderForValue) { @@ -3163,7 +3161,7 @@ public Builder addSecurityRequirements( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder addSecurityRequirements( int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { @@ -3181,7 +3179,7 @@ public Builder addSecurityRequirements( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder addAllSecurityRequirements( java.lang.Iterable values) { @@ -3200,7 +3198,7 @@ public Builder addAllSecurityRequirements( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder clearSecurityRequirements() { if (securityRequirementsBuilder_ == null) { @@ -3217,7 +3215,7 @@ public Builder clearSecurityRequirements() { * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public Builder removeSecurityRequirements(int index) { if (securityRequirementsBuilder_ == null) { @@ -3234,7 +3232,7 @@ public Builder removeSecurityRequirements(int index) { * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder( int index) { @@ -3245,7 +3243,7 @@ public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index) { @@ -3259,7 +3257,7 @@ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public java.util.List getSecurityRequirementsOrBuilderList() { @@ -3274,7 +3272,7 @@ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() { return internalGetSecurityRequirementsFieldBuilder().addBuilder( @@ -3285,7 +3283,7 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( int index) { @@ -3297,7 +3295,7 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ public java.util.List getSecurityRequirementsBuilderList() { @@ -3644,12 +3642,12 @@ private void ensureSkillsIsMutable() { /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getSkillsList() { if (skillsBuilder_ == null) { @@ -3660,12 +3658,12 @@ public java.util.List getSkillsList() { } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public int getSkillsCount() { if (skillsBuilder_ == null) { @@ -3676,12 +3674,12 @@ public int getSkillsCount() { } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentSkill getSkills(int index) { if (skillsBuilder_ == null) { @@ -3692,12 +3690,12 @@ public io.a2a.grpc.AgentSkill getSkills(int index) { } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setSkills( int index, io.a2a.grpc.AgentSkill value) { @@ -3715,12 +3713,12 @@ public Builder setSkills( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setSkills( int index, io.a2a.grpc.AgentSkill.Builder builderForValue) { @@ -3735,12 +3733,12 @@ public Builder setSkills( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addSkills(io.a2a.grpc.AgentSkill value) { if (skillsBuilder_ == null) { @@ -3757,12 +3755,12 @@ public Builder addSkills(io.a2a.grpc.AgentSkill value) { } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addSkills( int index, io.a2a.grpc.AgentSkill value) { @@ -3780,12 +3778,12 @@ public Builder addSkills( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addSkills( io.a2a.grpc.AgentSkill.Builder builderForValue) { @@ -3800,12 +3798,12 @@ public Builder addSkills( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addSkills( int index, io.a2a.grpc.AgentSkill.Builder builderForValue) { @@ -3820,12 +3818,12 @@ public Builder addSkills( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addAllSkills( java.lang.Iterable values) { @@ -3841,12 +3839,12 @@ public Builder addAllSkills( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearSkills() { if (skillsBuilder_ == null) { @@ -3860,12 +3858,12 @@ public Builder clearSkills() { } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public Builder removeSkills(int index) { if (skillsBuilder_ == null) { @@ -3879,12 +3877,12 @@ public Builder removeSkills(int index) { } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentSkill.Builder getSkillsBuilder( int index) { @@ -3892,12 +3890,12 @@ public io.a2a.grpc.AgentSkill.Builder getSkillsBuilder( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( int index) { @@ -3908,12 +3906,12 @@ public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getSkillsOrBuilderList() { @@ -3925,12 +3923,12 @@ public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder() { return internalGetSkillsFieldBuilder().addBuilder( @@ -3938,12 +3936,12 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder() { } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder( int index) { @@ -3952,12 +3950,12 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder( } /** *
        -     * Skills represent an ability of an agent. It is largely
        -     * a descriptive concept but represents a more focused set of behaviors that the
        +     * Skills represent the abilities of an agent.
        +     * It is largely a descriptive concept but represents a more focused set of behaviors that the
              * agent is likely to succeed at.
              * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getSkillsBuilderList() { @@ -3992,10 +3990,10 @@ private void ensureSignaturesIsMutable() { /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public java.util.List getSignaturesList() { if (signaturesBuilder_ == null) { @@ -4006,10 +4004,10 @@ public java.util.List getSignaturesList() { } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public int getSignaturesCount() { if (signaturesBuilder_ == null) { @@ -4020,10 +4018,10 @@ public int getSignaturesCount() { } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public io.a2a.grpc.AgentCardSignature getSignatures(int index) { if (signaturesBuilder_ == null) { @@ -4034,10 +4032,10 @@ public io.a2a.grpc.AgentCardSignature getSignatures(int index) { } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder setSignatures( int index, io.a2a.grpc.AgentCardSignature value) { @@ -4055,10 +4053,10 @@ public Builder setSignatures( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder setSignatures( int index, io.a2a.grpc.AgentCardSignature.Builder builderForValue) { @@ -4073,10 +4071,10 @@ public Builder setSignatures( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder addSignatures(io.a2a.grpc.AgentCardSignature value) { if (signaturesBuilder_ == null) { @@ -4093,10 +4091,10 @@ public Builder addSignatures(io.a2a.grpc.AgentCardSignature value) { } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder addSignatures( int index, io.a2a.grpc.AgentCardSignature value) { @@ -4114,10 +4112,10 @@ public Builder addSignatures( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder addSignatures( io.a2a.grpc.AgentCardSignature.Builder builderForValue) { @@ -4132,10 +4130,10 @@ public Builder addSignatures( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder addSignatures( int index, io.a2a.grpc.AgentCardSignature.Builder builderForValue) { @@ -4150,10 +4148,10 @@ public Builder addSignatures( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder addAllSignatures( java.lang.Iterable values) { @@ -4169,10 +4167,10 @@ public Builder addAllSignatures( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder clearSignatures() { if (signaturesBuilder_ == null) { @@ -4186,10 +4184,10 @@ public Builder clearSignatures() { } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public Builder removeSignatures(int index) { if (signaturesBuilder_ == null) { @@ -4203,10 +4201,10 @@ public Builder removeSignatures(int index) { } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public io.a2a.grpc.AgentCardSignature.Builder getSignaturesBuilder( int index) { @@ -4214,10 +4212,10 @@ public io.a2a.grpc.AgentCardSignature.Builder getSignaturesBuilder( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( int index) { @@ -4228,10 +4226,10 @@ public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public java.util.List getSignaturesOrBuilderList() { @@ -4243,10 +4241,10 @@ public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder() { return internalGetSignaturesFieldBuilder().addBuilder( @@ -4254,10 +4252,10 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder() { } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder( int index) { @@ -4266,10 +4264,10 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder( } /** *
        -     * JSON Web Signatures computed for this AgentCard.
        +     * JSON Web Signatures computed for this `AgentCard`.
              * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ public java.util.List getSignaturesBuilderList() { @@ -4293,10 +4291,10 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder( private java.lang.Object iconUrl_ = ""; /** *
        -     * An optional URL to an icon for the agent.
        +     * Optional. A URL to an icon for the agent.
              * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return Whether the iconUrl field is set. */ public boolean hasIconUrl() { @@ -4304,10 +4302,10 @@ public boolean hasIconUrl() { } /** *
        -     * An optional URL to an icon for the agent.
        +     * Optional. A URL to an icon for the agent.
              * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return The iconUrl. */ public java.lang.String getIconUrl() { @@ -4324,10 +4322,10 @@ public java.lang.String getIconUrl() { } /** *
        -     * An optional URL to an icon for the agent.
        +     * Optional. A URL to an icon for the agent.
              * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return The bytes for iconUrl. */ public com.google.protobuf.ByteString @@ -4345,10 +4343,10 @@ public java.lang.String getIconUrl() { } /** *
        -     * An optional URL to an icon for the agent.
        +     * Optional. A URL to an icon for the agent.
              * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @param value The iconUrl to set. * @return This builder for chaining. */ @@ -4362,10 +4360,10 @@ public Builder setIconUrl( } /** *
        -     * An optional URL to an icon for the agent.
        +     * Optional. A URL to an icon for the agent.
              * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return This builder for chaining. */ public Builder clearIconUrl() { @@ -4376,10 +4374,10 @@ public Builder clearIconUrl() { } /** *
        -     * An optional URL to an icon for the agent.
        +     * Optional. A URL to an icon for the agent.
              * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @param value The bytes for iconUrl to set. * @return This builder for chaining. */ @@ -4393,10 +4391,10 @@ public Builder setIconUrlBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCard) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AgentCard) } - // @@protoc_insertion_point(class_scope:a2a.v1.AgentCard) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentCard) private static final io.a2a.grpc.AgentCard DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AgentCard(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java index 379ec0282..8e19c6bd8 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface AgentCardOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCard) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AgentCard) com.google.protobuf.MessageOrBuilder { /** @@ -58,44 +58,44 @@ public interface AgentCardOrBuilder extends /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getSupportedInterfacesList(); /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.AgentInterface getSupportedInterfaces(int index); /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ int getSupportedInterfacesCount(); /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getSupportedInterfacesOrBuilderList(); /** *
        -   * Ordered list of supported interfaces. First entry is preferred.
        +   * Ordered list of supported interfaces. The first entry is preferred.
            * 
        * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( int index); @@ -105,7 +105,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; * @return Whether the provider field is set. */ boolean hasProvider(); @@ -114,7 +114,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; * @return The provider. */ io.a2a.grpc.AgentProvider getProvider(); @@ -123,7 +123,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * The service provider of the agent. * * - * .a2a.v1.AgentProvider provider = 4; + * .lf.a2a.v1.AgentProvider provider = 4; */ io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder(); @@ -151,7 +151,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( /** *
        -   * A url to provide additional documentation about the agent.
        +   * A URL providing additional documentation about the agent.
            * 
        * * optional string documentation_url = 6; @@ -160,7 +160,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( boolean hasDocumentationUrl(); /** *
        -   * A url to provide additional documentation about the agent.
        +   * A URL providing additional documentation about the agent.
            * 
        * * optional string documentation_url = 6; @@ -169,7 +169,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( java.lang.String getDocumentationUrl(); /** *
        -   * A url to provide additional documentation about the agent.
        +   * A URL providing additional documentation about the agent.
            * 
        * * optional string documentation_url = 6; @@ -183,7 +183,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the capabilities field is set. */ boolean hasCapabilities(); @@ -192,7 +192,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; * @return The capabilities. */ io.a2a.grpc.AgentCapabilities getCapabilities(); @@ -201,7 +201,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * A2A Capability set supported by the agent. * * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder(); @@ -210,7 +210,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ int getSecuritySchemesCount(); /** @@ -218,7 +218,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ boolean containsSecuritySchemes( java.lang.String key); @@ -233,7 +233,7 @@ boolean containsSecuritySchemes( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ java.util.Map getSecuritySchemesMap(); @@ -242,7 +242,7 @@ boolean containsSecuritySchemes( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ /* nullable */ io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault( @@ -254,7 +254,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault( * The security scheme details used for authenticating with this agent. * * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8; */ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( java.lang.String key); @@ -264,7 +264,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ java.util.List getSecurityRequirementsList(); @@ -273,7 +273,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index); /** @@ -281,7 +281,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ int getSecurityRequirementsCount(); /** @@ -289,7 +289,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ java.util.List getSecurityRequirementsOrBuilderList(); @@ -298,7 +298,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( * Security requirements for contacting the agent. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9; */ io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index); @@ -395,126 +395,126 @@ io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getSkillsList(); /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.AgentSkill getSkills(int index); /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ int getSkillsCount(); /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getSkillsOrBuilderList(); /** *
        -   * Skills represent an ability of an agent. It is largely
        -   * a descriptive concept but represents a more focused set of behaviors that the
        +   * Skills represent the abilities of an agent.
        +   * It is largely a descriptive concept but represents a more focused set of behaviors that the
            * agent is likely to succeed at.
            * 
        * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( int index); /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ java.util.List getSignaturesList(); /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ io.a2a.grpc.AgentCardSignature getSignatures(int index); /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ int getSignaturesCount(); /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ java.util.List getSignaturesOrBuilderList(); /** *
        -   * JSON Web Signatures computed for this AgentCard.
        +   * JSON Web Signatures computed for this `AgentCard`.
            * 
        * - * repeated .a2a.v1.AgentCardSignature signatures = 17; + * repeated .lf.a2a.v1.AgentCardSignature signatures = 13; */ io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( int index); /** *
        -   * An optional URL to an icon for the agent.
        +   * Optional. A URL to an icon for the agent.
            * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return Whether the iconUrl field is set. */ boolean hasIconUrl(); /** *
        -   * An optional URL to an icon for the agent.
        +   * Optional. A URL to an icon for the agent.
            * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return The iconUrl. */ java.lang.String getIconUrl(); /** *
        -   * An optional URL to an icon for the agent.
        +   * Optional. A URL to an icon for the agent.
            * 
        * - * optional string icon_url = 18; + * optional string icon_url = 14; * @return The bytes for iconUrl. */ com.google.protobuf.ByteString diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java index eef107309..567d94c50 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java @@ -7,17 +7,16 @@ /** *
        - * --8<-- [start:AgentCardSignature]
          * AgentCardSignature represents a JWS signature of an AgentCard.
          * This follows the JSON format of an RFC 7515 JSON Web Signature (JWS).
          * 
        * - * Protobuf type {@code a2a.v1.AgentCardSignature} + * Protobuf type {@code lf.a2a.v1.AgentCardSignature} */ @com.google.protobuf.Generated public final class AgentCardSignature extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentCardSignature) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AgentCardSignature) AgentCardSignatureOrBuilder { private static final long serialVersionUID = 0L; static { @@ -40,13 +39,13 @@ private AgentCardSignature() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentCardSignature.class, io.a2a.grpc.AgentCardSignature.Builder.class); } @@ -57,8 +56,10 @@ private AgentCardSignature() { private volatile java.lang.Object protected_ = ""; /** *
        -   * The protected JWS header for the signature. This is always a
        -   * base64url-encoded JSON object. Required.
        +   * (-- api-linter: core::0140::reserved-words=disabled
        +   * aip.dev/not-precedent: Backwards compatibility --)
        +   * Required. The protected JWS header for the signature. This is always a
        +   * base64url-encoded JSON object.
            * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -79,8 +80,10 @@ public java.lang.String getProtected() { } /** *
        -   * The protected JWS header for the signature. This is always a
        -   * base64url-encoded JSON object. Required.
        +   * (-- api-linter: core::0140::reserved-words=disabled
        +   * aip.dev/not-precedent: Backwards compatibility --)
        +   * Required. The protected JWS header for the signature. This is always a
        +   * base64url-encoded JSON object.
            * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -106,7 +109,7 @@ public java.lang.String getProtected() { private volatile java.lang.Object signature_ = ""; /** *
        -   * The computed signature, base64url-encoded. Required.
        +   * Required. The computed signature, base64url-encoded.
            * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -127,7 +130,7 @@ public java.lang.String getSignature() { } /** *
        -   * The computed signature, base64url-encoded. Required.
        +   * Required. The computed signature, base64url-encoded.
            * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -370,26 +373,25 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:AgentCardSignature]
            * AgentCardSignature represents a JWS signature of an AgentCard.
            * This follows the JSON format of an RFC 7515 JSON Web Signature (JWS).
            * 
        * - * Protobuf type {@code a2a.v1.AgentCardSignature} + * Protobuf type {@code lf.a2a.v1.AgentCardSignature} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCardSignature) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentCardSignature) io.a2a.grpc.AgentCardSignatureOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentCardSignature.class, io.a2a.grpc.AgentCardSignature.Builder.class); } @@ -427,7 +429,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor; } @java.lang.Override @@ -558,8 +560,10 @@ public Builder mergeFrom( private java.lang.Object protected_ = ""; /** *
        -     * The protected JWS header for the signature. This is always a
        -     * base64url-encoded JSON object. Required.
        +     * (-- api-linter: core::0140::reserved-words=disabled
        +     * aip.dev/not-precedent: Backwards compatibility --)
        +     * Required. The protected JWS header for the signature. This is always a
        +     * base64url-encoded JSON object.
              * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -579,8 +583,10 @@ public java.lang.String getProtected() { } /** *
        -     * The protected JWS header for the signature. This is always a
        -     * base64url-encoded JSON object. Required.
        +     * (-- api-linter: core::0140::reserved-words=disabled
        +     * aip.dev/not-precedent: Backwards compatibility --)
        +     * Required. The protected JWS header for the signature. This is always a
        +     * base64url-encoded JSON object.
              * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -601,8 +607,10 @@ public java.lang.String getProtected() { } /** *
        -     * The protected JWS header for the signature. This is always a
        -     * base64url-encoded JSON object. Required.
        +     * (-- api-linter: core::0140::reserved-words=disabled
        +     * aip.dev/not-precedent: Backwards compatibility --)
        +     * Required. The protected JWS header for the signature. This is always a
        +     * base64url-encoded JSON object.
              * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -619,8 +627,10 @@ public Builder setProtected( } /** *
        -     * The protected JWS header for the signature. This is always a
        -     * base64url-encoded JSON object. Required.
        +     * (-- api-linter: core::0140::reserved-words=disabled
        +     * aip.dev/not-precedent: Backwards compatibility --)
        +     * Required. The protected JWS header for the signature. This is always a
        +     * base64url-encoded JSON object.
              * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -634,8 +644,10 @@ public Builder clearProtected() { } /** *
        -     * The protected JWS header for the signature. This is always a
        -     * base64url-encoded JSON object. Required.
        +     * (-- api-linter: core::0140::reserved-words=disabled
        +     * aip.dev/not-precedent: Backwards compatibility --)
        +     * Required. The protected JWS header for the signature. This is always a
        +     * base64url-encoded JSON object.
              * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -655,7 +667,7 @@ public Builder setProtectedBytes( private java.lang.Object signature_ = ""; /** *
        -     * The computed signature, base64url-encoded. Required.
        +     * Required. The computed signature, base64url-encoded.
              * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -675,7 +687,7 @@ public java.lang.String getSignature() { } /** *
        -     * The computed signature, base64url-encoded. Required.
        +     * Required. The computed signature, base64url-encoded.
              * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -696,7 +708,7 @@ public java.lang.String getSignature() { } /** *
        -     * The computed signature, base64url-encoded. Required.
        +     * Required. The computed signature, base64url-encoded.
              * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -713,7 +725,7 @@ public Builder setSignature( } /** *
        -     * The computed signature, base64url-encoded. Required.
        +     * Required. The computed signature, base64url-encoded.
              * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -727,7 +739,7 @@ public Builder clearSignature() { } /** *
        -     * The computed signature, base64url-encoded. Required.
        +     * Required. The computed signature, base64url-encoded.
              * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -901,10 +913,10 @@ public com.google.protobuf.StructOrBuilder getHeaderOrBuilder() { return headerBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCardSignature) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AgentCardSignature) } - // @@protoc_insertion_point(class_scope:a2a.v1.AgentCardSignature) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentCardSignature) private static final io.a2a.grpc.AgentCardSignature DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AgentCardSignature(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java index 1d05b9c6d..ecd7ff95d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java @@ -7,13 +7,15 @@ @com.google.protobuf.Generated public interface AgentCardSignatureOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCardSignature) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AgentCardSignature) com.google.protobuf.MessageOrBuilder { /** *
        -   * The protected JWS header for the signature. This is always a
        -   * base64url-encoded JSON object. Required.
        +   * (-- api-linter: core::0140::reserved-words=disabled
        +   * aip.dev/not-precedent: Backwards compatibility --)
        +   * Required. The protected JWS header for the signature. This is always a
        +   * base64url-encoded JSON object.
            * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -22,8 +24,10 @@ public interface AgentCardSignatureOrBuilder extends java.lang.String getProtected(); /** *
        -   * The protected JWS header for the signature. This is always a
        -   * base64url-encoded JSON object. Required.
        +   * (-- api-linter: core::0140::reserved-words=disabled
        +   * aip.dev/not-precedent: Backwards compatibility --)
        +   * Required. The protected JWS header for the signature. This is always a
        +   * base64url-encoded JSON object.
            * 
        * * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -34,7 +38,7 @@ public interface AgentCardSignatureOrBuilder extends /** *
        -   * The computed signature, base64url-encoded. Required.
        +   * Required. The computed signature, base64url-encoded.
            * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -43,7 +47,7 @@ public interface AgentCardSignatureOrBuilder extends java.lang.String getSignature(); /** *
        -   * The computed signature, base64url-encoded. Required.
        +   * Required. The computed signature, base64url-encoded.
            * 
        * * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java index 6f942268e..e623157f3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:AgentExtension]
          * A declaration of a protocol extension supported by an Agent.
          * 
        * - * Protobuf type {@code a2a.v1.AgentExtension} + * Protobuf type {@code lf.a2a.v1.AgentExtension} */ @com.google.protobuf.Generated public final class AgentExtension extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentExtension) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AgentExtension) AgentExtensionOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,13 +38,13 @@ private AgentExtension() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentExtension.class, io.a2a.grpc.AgentExtension.Builder.class); } @@ -164,7 +163,7 @@ public boolean getRequired() { private com.google.protobuf.Struct params_; /** *
        -   * Optional, extension-specific configuration parameters.
        +   * Optional. Extension-specific configuration parameters.
            * 
        * * .google.protobuf.Struct params = 4; @@ -176,7 +175,7 @@ public boolean hasParams() { } /** *
        -   * Optional, extension-specific configuration parameters.
        +   * Optional. Extension-specific configuration parameters.
            * 
        * * .google.protobuf.Struct params = 4; @@ -188,7 +187,7 @@ public com.google.protobuf.Struct getParams() { } /** *
        -   * Optional, extension-specific configuration parameters.
        +   * Optional. Extension-specific configuration parameters.
            * 
        * * .google.protobuf.Struct params = 4; @@ -394,25 +393,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:AgentExtension]
            * A declaration of a protocol extension supported by an Agent.
            * 
        * - * Protobuf type {@code a2a.v1.AgentExtension} + * Protobuf type {@code lf.a2a.v1.AgentExtension} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentExtension) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentExtension) io.a2a.grpc.AgentExtensionOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentExtension.class, io.a2a.grpc.AgentExtension.Builder.class); } @@ -451,7 +449,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor; } @java.lang.Override @@ -823,7 +821,7 @@ public Builder clearRequired() { com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> paramsBuilder_; /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -834,7 +832,7 @@ public boolean hasParams() { } /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -849,7 +847,7 @@ public com.google.protobuf.Struct getParams() { } /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -869,7 +867,7 @@ public Builder setParams(com.google.protobuf.Struct value) { } /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -887,7 +885,7 @@ public Builder setParams( } /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -912,7 +910,7 @@ public Builder mergeParams(com.google.protobuf.Struct value) { } /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -929,7 +927,7 @@ public Builder clearParams() { } /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -941,7 +939,7 @@ public com.google.protobuf.Struct.Builder getParamsBuilder() { } /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -956,7 +954,7 @@ public com.google.protobuf.StructOrBuilder getParamsOrBuilder() { } /** *
        -     * Optional, extension-specific configuration parameters.
        +     * Optional. Extension-specific configuration parameters.
              * 
        * * .google.protobuf.Struct params = 4; @@ -975,10 +973,10 @@ public com.google.protobuf.StructOrBuilder getParamsOrBuilder() { return paramsBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentExtension) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AgentExtension) } - // @@protoc_insertion_point(class_scope:a2a.v1.AgentExtension) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentExtension) private static final io.a2a.grpc.AgentExtension DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AgentExtension(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java index e5df98bb1..42cb9594b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface AgentExtensionOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentExtension) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AgentExtension) com.google.protobuf.MessageOrBuilder { /** @@ -62,7 +62,7 @@ public interface AgentExtensionOrBuilder extends /** *
        -   * Optional, extension-specific configuration parameters.
        +   * Optional. Extension-specific configuration parameters.
            * 
        * * .google.protobuf.Struct params = 4; @@ -71,7 +71,7 @@ public interface AgentExtensionOrBuilder extends boolean hasParams(); /** *
        -   * Optional, extension-specific configuration parameters.
        +   * Optional. Extension-specific configuration parameters.
            * 
        * * .google.protobuf.Struct params = 4; @@ -80,7 +80,7 @@ public interface AgentExtensionOrBuilder extends com.google.protobuf.Struct getParams(); /** *
        -   * Optional, extension-specific configuration parameters.
        +   * Optional. Extension-specific configuration parameters.
            * 
        * * .google.protobuf.Struct params = 4; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java index ac8001a8e..4d6fb828e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java @@ -7,17 +7,16 @@ /** *
        - * --8<-- [start:AgentInterface]
          * Declares a combination of a target URL, transport and protocol version for interacting with the agent.
          * This allows agents to expose the same functionality over multiple protocol binding mechanisms.
          * 
        * - * Protobuf type {@code a2a.v1.AgentInterface} + * Protobuf type {@code lf.a2a.v1.AgentInterface} */ @com.google.protobuf.Generated public final class AgentInterface extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentInterface) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AgentInterface) AgentInterfaceOrBuilder { private static final long serialVersionUID = 0L; static { @@ -42,13 +41,13 @@ private AgentInterface() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentInterface.class, io.a2a.grpc.AgentInterface.Builder.class); } @@ -158,7 +157,7 @@ public java.lang.String getProtocolBinding() { private volatile java.lang.Object tenant_ = ""; /** *
        -   * Tenant to be set in the request when calling the agent.
        +   * Tenant ID to be used in the request when calling the agent.
            * 
        * * string tenant = 3; @@ -179,7 +178,7 @@ public java.lang.String getTenant() { } /** *
        -   * Tenant to be set in the request when calling the agent.
        +   * Tenant ID to be used in the request when calling the agent.
            * 
        * * string tenant = 3; @@ -439,26 +438,25 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:AgentInterface]
            * Declares a combination of a target URL, transport and protocol version for interacting with the agent.
            * This allows agents to expose the same functionality over multiple protocol binding mechanisms.
            * 
        * - * Protobuf type {@code a2a.v1.AgentInterface} + * Protobuf type {@code lf.a2a.v1.AgentInterface} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentInterface) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentInterface) io.a2a.grpc.AgentInterfaceOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentInterface.class, io.a2a.grpc.AgentInterface.Builder.class); } @@ -487,7 +485,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor; } @java.lang.Override @@ -825,7 +823,7 @@ public Builder setProtocolBindingBytes( private java.lang.Object tenant_ = ""; /** *
        -     * Tenant to be set in the request when calling the agent.
        +     * Tenant ID to be used in the request when calling the agent.
              * 
        * * string tenant = 3; @@ -845,7 +843,7 @@ public java.lang.String getTenant() { } /** *
        -     * Tenant to be set in the request when calling the agent.
        +     * Tenant ID to be used in the request when calling the agent.
              * 
        * * string tenant = 3; @@ -866,7 +864,7 @@ public java.lang.String getTenant() { } /** *
        -     * Tenant to be set in the request when calling the agent.
        +     * Tenant ID to be used in the request when calling the agent.
              * 
        * * string tenant = 3; @@ -883,7 +881,7 @@ public Builder setTenant( } /** *
        -     * Tenant to be set in the request when calling the agent.
        +     * Tenant ID to be used in the request when calling the agent.
              * 
        * * string tenant = 3; @@ -897,7 +895,7 @@ public Builder clearTenant() { } /** *
        -     * Tenant to be set in the request when calling the agent.
        +     * Tenant ID to be used in the request when calling the agent.
              * 
        * * string tenant = 3; @@ -1016,10 +1014,10 @@ public Builder setProtocolVersionBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentInterface) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AgentInterface) } - // @@protoc_insertion_point(class_scope:a2a.v1.AgentInterface) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentInterface) private static final io.a2a.grpc.AgentInterface DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AgentInterface(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java index 3dfe76f41..3f31901c7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface AgentInterfaceOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentInterface) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AgentInterface) com.google.protobuf.MessageOrBuilder { /** @@ -58,7 +58,7 @@ public interface AgentInterfaceOrBuilder extends /** *
        -   * Tenant to be set in the request when calling the agent.
        +   * Tenant ID to be used in the request when calling the agent.
            * 
        * * string tenant = 3; @@ -67,7 +67,7 @@ public interface AgentInterfaceOrBuilder extends java.lang.String getTenant(); /** *
        -   * Tenant to be set in the request when calling the agent.
        +   * Tenant ID to be used in the request when calling the agent.
            * 
        * * string tenant = 3; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java index fdd9402a3..dc484c549 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:AgentProvider]
          * Represents the service provider of an agent.
          * 
        * - * Protobuf type {@code a2a.v1.AgentProvider} + * Protobuf type {@code lf.a2a.v1.AgentProvider} */ @com.google.protobuf.Generated public final class AgentProvider extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentProvider) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AgentProvider) AgentProviderOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,13 +38,13 @@ private AgentProvider() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentProvider.class, io.a2a.grpc.AgentProvider.Builder.class); } @@ -316,25 +315,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:AgentProvider]
            * Represents the service provider of an agent.
            * 
        * - * Protobuf type {@code a2a.v1.AgentProvider} + * Protobuf type {@code lf.a2a.v1.AgentProvider} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentProvider) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentProvider) io.a2a.grpc.AgentProviderOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentProvider.class, io.a2a.grpc.AgentProvider.Builder.class); } @@ -361,7 +359,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor; } @java.lang.Override @@ -665,10 +663,10 @@ public Builder setOrganizationBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentProvider) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AgentProvider) } - // @@protoc_insertion_point(class_scope:a2a.v1.AgentProvider) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentProvider) private static final io.a2a.grpc.AgentProvider DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AgentProvider(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java index a0e2efefa..cfff51140 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface AgentProviderOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentProvider) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AgentProvider) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java index 087596019..304775e4c 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:AgentSkill]
          * Represents a distinct capability or function that an agent can perform.
          * 
        * - * Protobuf type {@code a2a.v1.AgentSkill} + * Protobuf type {@code lf.a2a.v1.AgentSkill} */ @com.google.protobuf.Generated public final class AgentSkill extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentSkill) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AgentSkill) AgentSkillOrBuilder { private static final long serialVersionUID = 0L; static { @@ -49,13 +48,13 @@ private AgentSkill() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentSkill.class, io.a2a.grpc.AgentSkill.Builder.class); } @@ -421,7 +420,7 @@ public java.lang.String getOutputModes(int index) { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override public java.util.List getSecurityRequirementsList() { @@ -432,7 +431,7 @@ public java.util.List getSecurityRequirementsLi * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override public java.util.List @@ -444,7 +443,7 @@ public java.util.List getSecurityRequirementsLi * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override public int getSecurityRequirementsCount() { @@ -455,7 +454,7 @@ public int getSecurityRequirementsCount() { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { @@ -466,7 +465,7 @@ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ @java.lang.Override public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( @@ -733,25 +732,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:AgentSkill]
            * Represents a distinct capability or function that an agent can perform.
            * 
        * - * Protobuf type {@code a2a.v1.AgentSkill} + * Protobuf type {@code lf.a2a.v1.AgentSkill} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentSkill) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentSkill) io.a2a.grpc.AgentSkillOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AgentSkill.class, io.a2a.grpc.AgentSkill.Builder.class); } @@ -794,7 +792,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor; } @java.lang.Override @@ -1930,7 +1928,7 @@ private void ensureSecurityRequirementsIsMutable() { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public java.util.List getSecurityRequirementsList() { if (securityRequirementsBuilder_ == null) { @@ -1944,7 +1942,7 @@ public java.util.List getSecurityRequirementsLi * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public int getSecurityRequirementsCount() { if (securityRequirementsBuilder_ == null) { @@ -1958,7 +1956,7 @@ public int getSecurityRequirementsCount() { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { if (securityRequirementsBuilder_ == null) { @@ -1972,7 +1970,7 @@ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder setSecurityRequirements( int index, io.a2a.grpc.SecurityRequirement value) { @@ -1993,7 +1991,7 @@ public Builder setSecurityRequirements( * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder setSecurityRequirements( int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { @@ -2011,7 +2009,7 @@ public Builder setSecurityRequirements( * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) { if (securityRequirementsBuilder_ == null) { @@ -2031,7 +2029,7 @@ public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder addSecurityRequirements( int index, io.a2a.grpc.SecurityRequirement value) { @@ -2052,7 +2050,7 @@ public Builder addSecurityRequirements( * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder addSecurityRequirements( io.a2a.grpc.SecurityRequirement.Builder builderForValue) { @@ -2070,7 +2068,7 @@ public Builder addSecurityRequirements( * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder addSecurityRequirements( int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { @@ -2088,7 +2086,7 @@ public Builder addSecurityRequirements( * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder addAllSecurityRequirements( java.lang.Iterable values) { @@ -2107,7 +2105,7 @@ public Builder addAllSecurityRequirements( * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder clearSecurityRequirements() { if (securityRequirementsBuilder_ == null) { @@ -2124,7 +2122,7 @@ public Builder clearSecurityRequirements() { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public Builder removeSecurityRequirements(int index) { if (securityRequirementsBuilder_ == null) { @@ -2141,7 +2139,7 @@ public Builder removeSecurityRequirements(int index) { * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder( int index) { @@ -2152,7 +2150,7 @@ public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder( * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index) { @@ -2166,7 +2164,7 @@ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public java.util.List getSecurityRequirementsOrBuilderList() { @@ -2181,7 +2179,7 @@ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() { return internalGetSecurityRequirementsFieldBuilder().addBuilder( @@ -2192,7 +2190,7 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( int index) { @@ -2204,7 +2202,7 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ public java.util.List getSecurityRequirementsBuilderList() { @@ -2225,10 +2223,10 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( return securityRequirementsBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentSkill) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AgentSkill) } - // @@protoc_insertion_point(class_scope:a2a.v1.AgentSkill) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentSkill) private static final io.a2a.grpc.AgentSkill DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AgentSkill(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java index 8cb65a6c5..c982233c5 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface AgentSkillOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentSkill) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AgentSkill) com.google.protobuf.MessageOrBuilder { /** @@ -239,7 +239,7 @@ public interface AgentSkillOrBuilder extends * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ java.util.List getSecurityRequirementsList(); @@ -248,7 +248,7 @@ public interface AgentSkillOrBuilder extends * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index); /** @@ -256,7 +256,7 @@ public interface AgentSkillOrBuilder extends * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ int getSecurityRequirementsCount(); /** @@ -264,7 +264,7 @@ public interface AgentSkillOrBuilder extends * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ java.util.List getSecurityRequirementsOrBuilderList(); @@ -273,7 +273,7 @@ public interface AgentSkillOrBuilder extends * Security schemes necessary for this skill. * * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; + * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8; */ io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( int index); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java b/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java index 6716e86e2..d49d2184f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:Artifact]
          * Artifacts represent task outputs.
          * 
        * - * Protobuf type {@code a2a.v1.Artifact} + * Protobuf type {@code lf.a2a.v1.Artifact} */ @com.google.protobuf.Generated public final class Artifact extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Artifact) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.Artifact) ArtifactOrBuilder { private static final long serialVersionUID = 0L; static { @@ -43,13 +42,13 @@ private Artifact() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.Artifact.class, io.a2a.grpc.Artifact.Builder.class); } @@ -60,8 +59,7 @@ private Artifact() { private volatile java.lang.Object artifactId_ = ""; /** *
        -   * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -   * within a task.
        +   * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
            * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -82,8 +80,7 @@ public java.lang.String getArtifactId() { } /** *
        -   * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -   * within a task.
        +   * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
            * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -104,7 +101,7 @@ public java.lang.String getArtifactId() { } } - public static final int NAME_FIELD_NUMBER = 3; + public static final int NAME_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object name_ = ""; /** @@ -112,7 +109,7 @@ public java.lang.String getArtifactId() { * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @return The name. */ @java.lang.Override @@ -133,7 +130,7 @@ public java.lang.String getName() { * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @return The bytes for name. */ @java.lang.Override @@ -151,15 +148,15 @@ public java.lang.String getName() { } } - public static final int DESCRIPTION_FIELD_NUMBER = 4; + public static final int DESCRIPTION_FIELD_NUMBER = 3; @SuppressWarnings("serial") private volatile java.lang.Object description_ = ""; /** *
        -   * A human readable description of the artifact, optional.
        +   * Optional. A human readable description of the artifact.
            * 
        * - * string description = 4; + * string description = 3; * @return The description. */ @java.lang.Override @@ -177,10 +174,10 @@ public java.lang.String getDescription() { } /** *
        -   * A human readable description of the artifact, optional.
        +   * Optional. A human readable description of the artifact.
            * 
        * - * string description = 4; + * string description = 3; * @return The bytes for description. */ @java.lang.Override @@ -198,7 +195,7 @@ public java.lang.String getDescription() { } } - public static final int PARTS_FIELD_NUMBER = 5; + public static final int PARTS_FIELD_NUMBER = 4; @SuppressWarnings("serial") private java.util.List parts_; /** @@ -206,7 +203,7 @@ public java.lang.String getDescription() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List getPartsList() { @@ -217,7 +214,7 @@ public java.util.List getPartsList() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List @@ -229,7 +226,7 @@ public java.util.List getPartsList() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public int getPartsCount() { @@ -240,7 +237,7 @@ public int getPartsCount() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.Part getParts(int index) { @@ -251,7 +248,7 @@ public io.a2a.grpc.Part getParts(int index) { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( @@ -259,14 +256,14 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( return parts_.get(index); } - public static final int METADATA_FIELD_NUMBER = 6; + public static final int METADATA_FIELD_NUMBER = 5; private com.google.protobuf.Struct metadata_; /** *
        -   * Optional metadata included with the artifact.
        +   * Optional. Metadata included with the artifact.
            * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; * @return Whether the metadata field is set. */ @java.lang.Override @@ -275,10 +272,10 @@ public boolean hasMetadata() { } /** *
        -   * Optional metadata included with the artifact.
        +   * Optional. Metadata included with the artifact.
            * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; * @return The metadata. */ @java.lang.Override @@ -287,17 +284,17 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -   * Optional metadata included with the artifact.
        +   * Optional. Metadata included with the artifact.
            * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ @java.lang.Override public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; } - public static final int EXTENSIONS_FIELD_NUMBER = 7; + public static final int EXTENSIONS_FIELD_NUMBER = 6; @SuppressWarnings("serial") private com.google.protobuf.LazyStringArrayList extensions_ = com.google.protobuf.LazyStringArrayList.emptyList(); @@ -306,7 +303,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @return A list containing the extensions. */ public com.google.protobuf.ProtocolStringList @@ -318,7 +315,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @return The count of extensions. */ public int getExtensionsCount() { @@ -329,7 +326,7 @@ public int getExtensionsCount() { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param index The index of the element to return. * @return The extensions at the given index. */ @@ -341,7 +338,7 @@ public java.lang.String getExtensions(int index) { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param index The index of the value to return. * @return The bytes of the extensions at the given index. */ @@ -368,19 +365,19 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) com.google.protobuf.GeneratedMessage.writeString(output, 1, artifactId_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, name_); + com.google.protobuf.GeneratedMessage.writeString(output, 2, name_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, description_); + com.google.protobuf.GeneratedMessage.writeString(output, 3, description_); } for (int i = 0; i < parts_.size(); i++) { - output.writeMessage(5, parts_.get(i)); + output.writeMessage(4, parts_.get(i)); } if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(6, getMetadata()); + output.writeMessage(5, getMetadata()); } for (int i = 0; i < extensions_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 7, extensions_.getRaw(i)); + com.google.protobuf.GeneratedMessage.writeString(output, 6, extensions_.getRaw(i)); } getUnknownFields().writeTo(output); } @@ -395,18 +392,18 @@ public int getSerializedSize() { size += com.google.protobuf.GeneratedMessage.computeStringSize(1, artifactId_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, name_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, name_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, description_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, description_); } for (int i = 0; i < parts_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, parts_.get(i)); + .computeMessageSize(4, parts_.get(i)); } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, getMetadata()); + .computeMessageSize(5, getMetadata()); } { int dataSize = 0; @@ -574,25 +571,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:Artifact]
            * Artifacts represent task outputs.
            * 
        * - * Protobuf type {@code a2a.v1.Artifact} + * Protobuf type {@code lf.a2a.v1.Artifact} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Artifact) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.Artifact) io.a2a.grpc.ArtifactOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.Artifact.class, io.a2a.grpc.Artifact.Builder.class); } @@ -641,7 +637,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor; } @java.lang.Override @@ -801,17 +797,17 @@ public Builder mergeFrom( bitField0_ |= 0x00000001; break; } // case 10 - case 26: { + case 18: { name_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; - } // case 26 - case 34: { + } // case 18 + case 26: { description_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000004; break; - } // case 34 - case 42: { + } // case 26 + case 34: { io.a2a.grpc.Part m = input.readMessage( io.a2a.grpc.Part.parser(), @@ -823,20 +819,20 @@ public Builder mergeFrom( partsBuilder_.addMessage(m); } break; - } // case 42 - case 50: { + } // case 34 + case 42: { input.readMessage( internalGetMetadataFieldBuilder().getBuilder(), extensionRegistry); bitField0_ |= 0x00000010; break; - } // case 50 - case 58: { + } // case 42 + case 50: { java.lang.String s = input.readStringRequireUtf8(); ensureExtensionsIsMutable(); extensions_.add(s); break; - } // case 58 + } // case 50 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -857,8 +853,7 @@ public Builder mergeFrom( private java.lang.Object artifactId_ = ""; /** *
        -     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -     * within a task.
        +     * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
              * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -878,8 +873,7 @@ public java.lang.String getArtifactId() { } /** *
        -     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -     * within a task.
        +     * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
              * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -900,8 +894,7 @@ public java.lang.String getArtifactId() { } /** *
        -     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -     * within a task.
        +     * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
              * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -918,8 +911,7 @@ public Builder setArtifactId( } /** *
        -     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -     * within a task.
        +     * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
              * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -933,8 +925,7 @@ public Builder clearArtifactId() { } /** *
        -     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -     * within a task.
        +     * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
              * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -957,7 +948,7 @@ public Builder setArtifactIdBytes( * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @return The name. */ public java.lang.String getName() { @@ -977,7 +968,7 @@ public java.lang.String getName() { * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @return The bytes for name. */ public com.google.protobuf.ByteString @@ -998,7 +989,7 @@ public java.lang.String getName() { * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @param value The name to set. * @return This builder for chaining. */ @@ -1015,7 +1006,7 @@ public Builder setName( * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @return This builder for chaining. */ public Builder clearName() { @@ -1029,7 +1020,7 @@ public Builder clearName() { * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @param value The bytes for name to set. * @return This builder for chaining. */ @@ -1046,10 +1037,10 @@ public Builder setNameBytes( private java.lang.Object description_ = ""; /** *
        -     * A human readable description of the artifact, optional.
        +     * Optional. A human readable description of the artifact.
              * 
        * - * string description = 4; + * string description = 3; * @return The description. */ public java.lang.String getDescription() { @@ -1066,10 +1057,10 @@ public java.lang.String getDescription() { } /** *
        -     * A human readable description of the artifact, optional.
        +     * Optional. A human readable description of the artifact.
              * 
        * - * string description = 4; + * string description = 3; * @return The bytes for description. */ public com.google.protobuf.ByteString @@ -1087,10 +1078,10 @@ public java.lang.String getDescription() { } /** *
        -     * A human readable description of the artifact, optional.
        +     * Optional. A human readable description of the artifact.
              * 
        * - * string description = 4; + * string description = 3; * @param value The description to set. * @return This builder for chaining. */ @@ -1104,10 +1095,10 @@ public Builder setDescription( } /** *
        -     * A human readable description of the artifact, optional.
        +     * Optional. A human readable description of the artifact.
              * 
        * - * string description = 4; + * string description = 3; * @return This builder for chaining. */ public Builder clearDescription() { @@ -1118,10 +1109,10 @@ public Builder clearDescription() { } /** *
        -     * A human readable description of the artifact, optional.
        +     * Optional. A human readable description of the artifact.
              * 
        * - * string description = 4; + * string description = 3; * @param value The bytes for description to set. * @return This builder for chaining. */ @@ -1152,7 +1143,7 @@ private void ensurePartsIsMutable() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getPartsList() { if (partsBuilder_ == null) { @@ -1166,7 +1157,7 @@ public java.util.List getPartsList() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public int getPartsCount() { if (partsBuilder_ == null) { @@ -1180,7 +1171,7 @@ public int getPartsCount() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Part getParts(int index) { if (partsBuilder_ == null) { @@ -1194,7 +1185,7 @@ public io.a2a.grpc.Part getParts(int index) { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setParts( int index, io.a2a.grpc.Part value) { @@ -1215,7 +1206,7 @@ public Builder setParts( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setParts( int index, io.a2a.grpc.Part.Builder builderForValue) { @@ -1233,7 +1224,7 @@ public Builder setParts( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addParts(io.a2a.grpc.Part value) { if (partsBuilder_ == null) { @@ -1253,7 +1244,7 @@ public Builder addParts(io.a2a.grpc.Part value) { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addParts( int index, io.a2a.grpc.Part value) { @@ -1274,7 +1265,7 @@ public Builder addParts( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addParts( io.a2a.grpc.Part.Builder builderForValue) { @@ -1292,7 +1283,7 @@ public Builder addParts( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addParts( int index, io.a2a.grpc.Part.Builder builderForValue) { @@ -1310,7 +1301,7 @@ public Builder addParts( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addAllParts( java.lang.Iterable values) { @@ -1329,7 +1320,7 @@ public Builder addAllParts( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearParts() { if (partsBuilder_ == null) { @@ -1346,7 +1337,7 @@ public Builder clearParts() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public Builder removeParts(int index) { if (partsBuilder_ == null) { @@ -1363,7 +1354,7 @@ public Builder removeParts(int index) { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Part.Builder getPartsBuilder( int index) { @@ -1374,7 +1365,7 @@ public io.a2a.grpc.Part.Builder getPartsBuilder( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( int index) { @@ -1388,7 +1379,7 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getPartsOrBuilderList() { @@ -1403,7 +1394,7 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Part.Builder addPartsBuilder() { return internalGetPartsFieldBuilder().addBuilder( @@ -1414,7 +1405,7 @@ public io.a2a.grpc.Part.Builder addPartsBuilder() { * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Part.Builder addPartsBuilder( int index) { @@ -1426,7 +1417,7 @@ public io.a2a.grpc.Part.Builder addPartsBuilder( * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getPartsBuilderList() { @@ -1452,10 +1443,10 @@ public io.a2a.grpc.Part.Builder addPartsBuilder( com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; * @return Whether the metadata field is set. */ public boolean hasMetadata() { @@ -1463,10 +1454,10 @@ public boolean hasMetadata() { } /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; * @return The metadata. */ public com.google.protobuf.Struct getMetadata() { @@ -1478,10 +1469,10 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ public Builder setMetadata(com.google.protobuf.Struct value) { if (metadataBuilder_ == null) { @@ -1498,10 +1489,10 @@ public Builder setMetadata(com.google.protobuf.Struct value) { } /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ public Builder setMetadata( com.google.protobuf.Struct.Builder builderForValue) { @@ -1516,10 +1507,10 @@ public Builder setMetadata( } /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ public Builder mergeMetadata(com.google.protobuf.Struct value) { if (metadataBuilder_ == null) { @@ -1541,10 +1532,10 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) { } /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ public Builder clearMetadata() { bitField0_ = (bitField0_ & ~0x00000010); @@ -1558,10 +1549,10 @@ public Builder clearMetadata() { } /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ public com.google.protobuf.Struct.Builder getMetadataBuilder() { bitField0_ |= 0x00000010; @@ -1570,10 +1561,10 @@ public com.google.protobuf.Struct.Builder getMetadataBuilder() { } /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { if (metadataBuilder_ != null) { @@ -1585,10 +1576,10 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { } /** *
        -     * Optional metadata included with the artifact.
        +     * Optional. Metadata included with the artifact.
              * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ private com.google.protobuf.SingleFieldBuilder< com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> @@ -1617,7 +1608,7 @@ private void ensureExtensionsIsMutable() { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @return A list containing the extensions. */ public com.google.protobuf.ProtocolStringList @@ -1630,7 +1621,7 @@ private void ensureExtensionsIsMutable() { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @return The count of extensions. */ public int getExtensionsCount() { @@ -1641,7 +1632,7 @@ public int getExtensionsCount() { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param index The index of the element to return. * @return The extensions at the given index. */ @@ -1653,7 +1644,7 @@ public java.lang.String getExtensions(int index) { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param index The index of the value to return. * @return The bytes of the extensions at the given index. */ @@ -1666,7 +1657,7 @@ public java.lang.String getExtensions(int index) { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param index The index to set the value at. * @param value The extensions to set. * @return This builder for chaining. @@ -1685,7 +1676,7 @@ public Builder setExtensions( * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param value The extensions to add. * @return This builder for chaining. */ @@ -1703,7 +1694,7 @@ public Builder addExtensions( * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param values The extensions to add. * @return This builder for chaining. */ @@ -1721,7 +1712,7 @@ public Builder addAllExtensions( * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @return This builder for chaining. */ public Builder clearExtensions() { @@ -1736,7 +1727,7 @@ public Builder clearExtensions() { * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param value The bytes of the extensions to add. * @return This builder for chaining. */ @@ -1751,10 +1742,10 @@ public Builder addExtensionsBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.Artifact) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.Artifact) } - // @@protoc_insertion_point(class_scope:a2a.v1.Artifact) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.Artifact) private static final io.a2a.grpc.Artifact DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.Artifact(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java index 3c1de141f..4ba0ed83d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java @@ -7,13 +7,12 @@ @com.google.protobuf.Generated public interface ArtifactOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Artifact) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.Artifact) com.google.protobuf.MessageOrBuilder { /** *
        -   * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -   * within a task.
        +   * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
            * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -22,8 +21,7 @@ public interface ArtifactOrBuilder extends java.lang.String getArtifactId(); /** *
        -   * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
        -   * within a task.
        +   * Unique identifier (e.g. UUID) for the artifact. It must be unique within a task.
            * 
        * * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -37,7 +35,7 @@ public interface ArtifactOrBuilder extends * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @return The name. */ java.lang.String getName(); @@ -46,7 +44,7 @@ public interface ArtifactOrBuilder extends * A human readable name for the artifact. * * - * string name = 3; + * string name = 2; * @return The bytes for name. */ com.google.protobuf.ByteString @@ -54,19 +52,19 @@ public interface ArtifactOrBuilder extends /** *
        -   * A human readable description of the artifact, optional.
        +   * Optional. A human readable description of the artifact.
            * 
        * - * string description = 4; + * string description = 3; * @return The description. */ java.lang.String getDescription(); /** *
        -   * A human readable description of the artifact, optional.
        +   * Optional. A human readable description of the artifact.
            * 
        * - * string description = 4; + * string description = 3; * @return The bytes for description. */ com.google.protobuf.ByteString @@ -77,7 +75,7 @@ public interface ArtifactOrBuilder extends * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getPartsList(); @@ -86,7 +84,7 @@ public interface ArtifactOrBuilder extends * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.Part getParts(int index); /** @@ -94,7 +92,7 @@ public interface ArtifactOrBuilder extends * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ int getPartsCount(); /** @@ -102,7 +100,7 @@ public interface ArtifactOrBuilder extends * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getPartsOrBuilderList(); @@ -111,35 +109,35 @@ public interface ArtifactOrBuilder extends * The content of the artifact. Must contain at least one part. * * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.PartOrBuilder getPartsOrBuilder( int index); /** *
        -   * Optional metadata included with the artifact.
        +   * Optional. Metadata included with the artifact.
            * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; * @return Whether the metadata field is set. */ boolean hasMetadata(); /** *
        -   * Optional metadata included with the artifact.
        +   * Optional. Metadata included with the artifact.
            * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; * @return The metadata. */ com.google.protobuf.Struct getMetadata(); /** *
        -   * Optional metadata included with the artifact.
        +   * Optional. Metadata included with the artifact.
            * 
        * - * .google.protobuf.Struct metadata = 6; + * .google.protobuf.Struct metadata = 5; */ com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); @@ -148,7 +146,7 @@ io.a2a.grpc.PartOrBuilder getPartsOrBuilder( * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @return A list containing the extensions. */ java.util.List @@ -158,7 +156,7 @@ io.a2a.grpc.PartOrBuilder getPartsOrBuilder( * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @return The count of extensions. */ int getExtensionsCount(); @@ -167,7 +165,7 @@ io.a2a.grpc.PartOrBuilder getPartsOrBuilder( * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param index The index of the element to return. * @return The extensions at the given index. */ @@ -177,7 +175,7 @@ io.a2a.grpc.PartOrBuilder getPartsOrBuilder( * The URIs of extensions that are present or contributed to this Artifact. * * - * repeated string extensions = 7; + * repeated string extensions = 6; * @param index The index of the value to return. * @return The bytes of the extensions at the given index. */ diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java index 703a6da52..fc4750715 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:PushNotificationAuthenticationInfo]
          * Defines authentication details, used for push notifications.
          * 
        * - * Protobuf type {@code a2a.v1.AuthenticationInfo} + * Protobuf type {@code lf.a2a.v1.AuthenticationInfo} */ @com.google.protobuf.Generated public final class AuthenticationInfo extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AuthenticationInfo) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AuthenticationInfo) AuthenticationInfoOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,13 +38,13 @@ private AuthenticationInfo() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AuthenticationInfo.class, io.a2a.grpc.AuthenticationInfo.Builder.class); } @@ -56,7 +55,8 @@ private AuthenticationInfo() { /** *
            * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +   * Examples: `Bearer`, `Basic`, `Digest`.
        +   * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
            * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -78,7 +78,8 @@ public java.lang.String getScheme() { /** *
            * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +   * Examples: `Bearer`, `Basic`, `Digest`.
        +   * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
            * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -314,25 +315,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:PushNotificationAuthenticationInfo]
            * Defines authentication details, used for push notifications.
            * 
        * - * Protobuf type {@code a2a.v1.AuthenticationInfo} + * Protobuf type {@code lf.a2a.v1.AuthenticationInfo} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AuthenticationInfo) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AuthenticationInfo) io.a2a.grpc.AuthenticationInfoOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AuthenticationInfo.class, io.a2a.grpc.AuthenticationInfo.Builder.class); } @@ -359,7 +359,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor; } @java.lang.Override @@ -473,7 +473,8 @@ public Builder mergeFrom( /** *
              * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +     * Examples: `Bearer`, `Basic`, `Digest`.
        +     * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
              * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -494,7 +495,8 @@ public java.lang.String getScheme() { /** *
              * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +     * Examples: `Bearer`, `Basic`, `Digest`.
        +     * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
              * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -516,7 +518,8 @@ public java.lang.String getScheme() { /** *
              * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +     * Examples: `Bearer`, `Basic`, `Digest`.
        +     * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
              * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -534,7 +537,8 @@ public Builder setScheme( /** *
              * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +     * Examples: `Bearer`, `Basic`, `Digest`.
        +     * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
              * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -549,7 +553,8 @@ public Builder clearScheme() { /** *
              * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +     * Examples: `Bearer`, `Basic`, `Digest`.
        +     * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
              * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -658,10 +663,10 @@ public Builder setCredentialsBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AuthenticationInfo) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AuthenticationInfo) } - // @@protoc_insertion_point(class_scope:a2a.v1.AuthenticationInfo) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AuthenticationInfo) private static final io.a2a.grpc.AuthenticationInfo DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AuthenticationInfo(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java index b142c3670..7d5860fe1 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java @@ -7,13 +7,14 @@ @com.google.protobuf.Generated public interface AuthenticationInfoOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AuthenticationInfo) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AuthenticationInfo) com.google.protobuf.MessageOrBuilder { /** *
            * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +   * Examples: `Bearer`, `Basic`, `Digest`.
        +   * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
            * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -23,7 +24,8 @@ public interface AuthenticationInfoOrBuilder extends /** *
            * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
        -   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
        +   * Examples: `Bearer`, `Basic`, `Digest`.
        +   * Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
            * 
        * * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java index 06b7b8f41..13b09915a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:AuthorizationCodeOAuthFlow]
          * Defines configuration details for the OAuth 2.0 Authorization Code flow.
          * 
        * - * Protobuf type {@code a2a.v1.AuthorizationCodeOAuthFlow} + * Protobuf type {@code lf.a2a.v1.AuthorizationCodeOAuthFlow} */ @com.google.protobuf.Generated public final class AuthorizationCodeOAuthFlow extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AuthorizationCodeOAuthFlow) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.AuthorizationCodeOAuthFlow) AuthorizationCodeOAuthFlowOrBuilder { private static final long serialVersionUID = 0L; static { @@ -40,7 +39,7 @@ private AuthorizationCodeOAuthFlow() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -58,7 +57,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AuthorizationCodeOAuthFlow.class, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder.class); } @@ -210,7 +209,7 @@ private static final class ScopesDefaultEntryHolder { java.lang.String, java.lang.String> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.STRING, @@ -527,19 +526,18 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:AuthorizationCodeOAuthFlow]
            * Defines configuration details for the OAuth 2.0 Authorization Code flow.
            * 
        * - * Protobuf type {@code a2a.v1.AuthorizationCodeOAuthFlow} + * Protobuf type {@code lf.a2a.v1.AuthorizationCodeOAuthFlow} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AuthorizationCodeOAuthFlow) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AuthorizationCodeOAuthFlow) io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -567,7 +565,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.AuthorizationCodeOAuthFlow.class, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder.class); } @@ -597,7 +595,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; } @java.lang.Override @@ -1225,10 +1223,10 @@ public Builder clearPkceRequired() { return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.AuthorizationCodeOAuthFlow) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.AuthorizationCodeOAuthFlow) } - // @@protoc_insertion_point(class_scope:a2a.v1.AuthorizationCodeOAuthFlow) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.AuthorizationCodeOAuthFlow) private static final io.a2a.grpc.AuthorizationCodeOAuthFlow DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.AuthorizationCodeOAuthFlow(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java index 5dd2d393d..55c17dc7b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface AuthorizationCodeOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AuthorizationCodeOAuthFlow) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.AuthorizationCodeOAuthFlow) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java index 3aa57435f..d1ca30eca 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:CancelTaskRequest]
          * Represents a request for the `CancelTask` method.
          * 
        * - * Protobuf type {@code a2a.v1.CancelTaskRequest} + * Protobuf type {@code lf.a2a.v1.CancelTaskRequest} */ @com.google.protobuf.Generated public final class CancelTaskRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.CancelTaskRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.CancelTaskRequest) CancelTaskRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,26 +38,27 @@ private CancelTaskRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.CancelTaskRequest.class, io.a2a.grpc.CancelTaskRequest.Builder.class); } - public static final int TENANT_FIELD_NUMBER = 2; + private int bitField0_; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -76,10 +76,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -97,15 +97,15 @@ public java.lang.String getTenant() { } } - public static final int ID_FIELD_NUMBER = 1; + public static final int ID_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object id_ = ""; /** *
        -   * The resource id of the task to cancel.
        +   * The resource ID of the task to cancel.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ @java.lang.Override @@ -123,10 +123,10 @@ public java.lang.String getId() { } /** *
        -   * The resource id of the task to cancel.
        +   * The resource ID of the task to cancel.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ @java.lang.Override @@ -144,6 +144,44 @@ public java.lang.String getId() { } } + public static final int METADATA_FIELD_NUMBER = 3; + private com.google.protobuf.Struct metadata_; + /** + *
        +   * A flexible key-value map for passing additional context or parameters.
        +   * 
        + * + * .google.protobuf.Struct metadata = 3; + * @return Whether the metadata field is set. + */ + @java.lang.Override + public boolean hasMetadata() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
        +   * A flexible key-value map for passing additional context or parameters.
        +   * 
        + * + * .google.protobuf.Struct metadata = 3; + * @return The metadata. + */ + @java.lang.Override + public com.google.protobuf.Struct getMetadata() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + /** + *
        +   * A flexible key-value map for passing additional context or parameters.
        +   * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -158,11 +196,14 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); + com.google.protobuf.GeneratedMessage.writeString(output, 2, id_); } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(3, getMetadata()); } getUnknownFields().writeTo(output); } @@ -173,11 +214,15 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, id_); } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getMetadata()); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -198,6 +243,11 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getTenant())) return false; if (!getId() .equals(other.getId())) return false; + if (hasMetadata() != other.hasMetadata()) return false; + if (hasMetadata()) { + if (!getMetadata() + .equals(other.getMetadata())) return false; + } if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -213,6 +263,10 @@ public int hashCode() { hash = (53 * hash) + getTenant().hashCode(); hash = (37 * hash) + ID_FIELD_NUMBER; hash = (53 * hash) + getId().hashCode(); + if (hasMetadata()) { + hash = (37 * hash) + METADATA_FIELD_NUMBER; + hash = (53 * hash) + getMetadata().hashCode(); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -312,38 +366,43 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:CancelTaskRequest]
            * Represents a request for the `CancelTask` method.
            * 
        * - * Protobuf type {@code a2a.v1.CancelTaskRequest} + * Protobuf type {@code lf.a2a.v1.CancelTaskRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.CancelTaskRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.CancelTaskRequest) io.a2a.grpc.CancelTaskRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.CancelTaskRequest.class, io.a2a.grpc.CancelTaskRequest.Builder.class); } // Construct using io.a2a.grpc.CancelTaskRequest.newBuilder() private Builder() { - + maybeForceBuilderInitialization(); } private Builder( com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); - + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetMetadataFieldBuilder(); + } } @java.lang.Override public Builder clear() { @@ -351,13 +410,18 @@ public Builder clear() { bitField0_ = 0; tenant_ = ""; id_ = ""; + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } return this; } @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor; } @java.lang.Override @@ -390,6 +454,14 @@ private void buildPartial0(io.a2a.grpc.CancelTaskRequest result) { if (((from_bitField0_ & 0x00000002) != 0)) { result.id_ = id_; } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000004) != 0)) { + result.metadata_ = metadataBuilder_ == null + ? metadata_ + : metadataBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + result.bitField0_ |= to_bitField0_; } @java.lang.Override @@ -414,6 +486,9 @@ public Builder mergeFrom(io.a2a.grpc.CancelTaskRequest other) { bitField0_ |= 0x00000002; onChanged(); } + if (other.hasMetadata()) { + mergeMetadata(other.getMetadata()); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -441,15 +516,22 @@ public Builder mergeFrom( done = true; break; case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; break; } // case 10 case 18: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; break; } // case 18 + case 26: { + input.readMessage( + internalGetMetadataFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -470,10 +552,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -490,10 +572,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -511,10 +593,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -528,10 +610,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -542,10 +624,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -562,10 +644,10 @@ public Builder setTenantBytes( private java.lang.Object id_ = ""; /** *
        -     * The resource id of the task to cancel.
        +     * The resource ID of the task to cancel.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ public java.lang.String getId() { @@ -582,10 +664,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the task to cancel.
        +     * The resource ID of the task to cancel.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ public com.google.protobuf.ByteString @@ -603,10 +685,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the task to cancel.
        +     * The resource ID of the task to cancel.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The id to set. * @return This builder for chaining. */ @@ -620,10 +702,10 @@ public Builder setId( } /** *
        -     * The resource id of the task to cancel.
        +     * The resource ID of the task to cancel.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearId() { @@ -634,10 +716,10 @@ public Builder clearId() { } /** *
        -     * The resource id of the task to cancel.
        +     * The resource ID of the task to cancel.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for id to set. * @return This builder for chaining. */ @@ -651,10 +733,167 @@ public Builder setIdBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.CancelTaskRequest) + private com.google.protobuf.Struct metadata_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + * @return Whether the metadata field is set. + */ + public boolean hasMetadata() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + * @return The metadata. + */ + public com.google.protobuf.Struct getMetadata() { + if (metadataBuilder_ == null) { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } else { + return metadataBuilder_.getMessage(); + } + } + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + public Builder setMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + metadata_ = value; + } else { + metadataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + public Builder setMetadata( + com.google.protobuf.Struct.Builder builderForValue) { + if (metadataBuilder_ == null) { + metadata_ = builderForValue.build(); + } else { + metadataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + public Builder mergeMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + metadata_ != null && + metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { + getMetadataBuilder().mergeFrom(value); + } else { + metadata_ = value; + } + } else { + metadataBuilder_.mergeFrom(value); + } + if (metadata_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + public Builder clearMetadata() { + bitField0_ = (bitField0_ & ~0x00000004); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + public com.google.protobuf.Struct.Builder getMetadataBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return internalGetMetadataFieldBuilder().getBuilder(); + } + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + if (metadataBuilder_ != null) { + return metadataBuilder_.getMessageOrBuilder(); + } else { + return metadata_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + } + /** + *
        +     * A flexible key-value map for passing additional context or parameters.
        +     * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetMetadataFieldBuilder() { + if (metadataBuilder_ == null) { + metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getMetadata(), + getParentForChildren(), + isClean()); + metadata_ = null; + } + return metadataBuilder_; + } + + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.CancelTaskRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.CancelTaskRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.CancelTaskRequest) private static final io.a2a.grpc.CancelTaskRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.CancelTaskRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java index 1e3251328..6dc8b9243 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface CancelTaskRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.CancelTaskRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.CancelTaskRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -32,21 +32,48 @@ public interface CancelTaskRequestOrBuilder extends /** *
        -   * The resource id of the task to cancel.
        +   * The resource ID of the task to cancel.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ java.lang.String getId(); /** *
        -   * The resource id of the task to cancel.
        +   * The resource ID of the task to cancel.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ com.google.protobuf.ByteString getIdBytes(); + + /** + *
        +   * A flexible key-value map for passing additional context or parameters.
        +   * 
        + * + * .google.protobuf.Struct metadata = 3; + * @return Whether the metadata field is set. + */ + boolean hasMetadata(); + /** + *
        +   * A flexible key-value map for passing additional context or parameters.
        +   * 
        + * + * .google.protobuf.Struct metadata = 3; + * @return The metadata. + */ + com.google.protobuf.Struct getMetadata(); + /** + *
        +   * A flexible key-value map for passing additional context or parameters.
        +   * 
        + * + * .google.protobuf.Struct metadata = 3; + */ + com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java index 1af7c907c..c91bda94f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:ClientCredentialsOAuthFlow]
          * Defines configuration details for the OAuth 2.0 Client Credentials flow.
          * 
        * - * Protobuf type {@code a2a.v1.ClientCredentialsOAuthFlow} + * Protobuf type {@code lf.a2a.v1.ClientCredentialsOAuthFlow} */ @com.google.protobuf.Generated public final class ClientCredentialsOAuthFlow extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ClientCredentialsOAuthFlow) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.ClientCredentialsOAuthFlow) ClientCredentialsOAuthFlowOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,7 +38,7 @@ private ClientCredentialsOAuthFlow() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -57,7 +56,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.ClientCredentialsOAuthFlow.class, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder.class); } @@ -162,7 +161,7 @@ private static final class ScopesDefaultEntryHolder { java.lang.String, java.lang.String> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.STRING, @@ -441,19 +440,18 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:ClientCredentialsOAuthFlow]
            * Defines configuration details for the OAuth 2.0 Client Credentials flow.
            * 
        * - * Protobuf type {@code a2a.v1.ClientCredentialsOAuthFlow} + * Protobuf type {@code lf.a2a.v1.ClientCredentialsOAuthFlow} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ClientCredentialsOAuthFlow) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ClientCredentialsOAuthFlow) io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -481,7 +479,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.ClientCredentialsOAuthFlow.class, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder.class); } @@ -509,7 +507,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor; } @java.lang.Override @@ -974,10 +972,10 @@ public Builder putAllScopes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.ClientCredentialsOAuthFlow) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.ClientCredentialsOAuthFlow) } - // @@protoc_insertion_point(class_scope:a2a.v1.ClientCredentialsOAuthFlow) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.ClientCredentialsOAuthFlow) private static final io.a2a.grpc.ClientCredentialsOAuthFlow DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.ClientCredentialsOAuthFlow(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java index 4178ed50d..0c60b6a5a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface ClientCredentialsOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ClientCredentialsOAuthFlow) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.ClientCredentialsOAuthFlow) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java index f445a86d2..d48f29694 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:CreateTaskPushNotificationConfigRequest]
          * Represents a request for the `CreateTaskPushNotificationConfig` method.
          * 
        * - * Protobuf type {@code a2a.v1.CreateTaskPushNotificationConfigRequest} + * Protobuf type {@code lf.a2a.v1.CreateTaskPushNotificationConfigRequest} */ @com.google.protobuf.Generated public final class CreateTaskPushNotificationConfigRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.CreateTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) CreateTaskPushNotificationConfigRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -35,32 +34,31 @@ private CreateTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMes private CreateTaskPushNotificationConfigRequest() { tenant_ = ""; taskId_ = ""; - configId_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); } private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 4; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -78,10 +76,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -99,15 +97,15 @@ public java.lang.String getTenant() { } } - public static final int TASK_ID_FIELD_NUMBER = 1; + public static final int TASK_ID_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object taskId_ = ""; /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ @java.lang.Override @@ -125,10 +123,10 @@ public java.lang.String getTaskId() { } /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ @java.lang.Override @@ -146,61 +144,14 @@ public java.lang.String getTaskId() { } } - public static final int CONFIG_ID_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object configId_ = ""; - /** - *
        -   * The ID for the new config.
        -   * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The configId. - */ - @java.lang.Override - public java.lang.String getConfigId() { - java.lang.Object ref = configId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - configId_ = s; - return s; - } - } - /** - *
        -   * The ID for the new config.
        -   * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for configId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getConfigIdBytes() { - java.lang.Object ref = configId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - configId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONFIG_FIELD_NUMBER = 5; + public static final int CONFIG_FIELD_NUMBER = 3; private io.a2a.grpc.PushNotificationConfig config_; /** *
            * The configuration to create.
            * 
        * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the config field is set. */ @java.lang.Override @@ -212,7 +163,7 @@ public boolean hasConfig() { * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The config. */ @java.lang.Override @@ -224,7 +175,7 @@ public io.a2a.grpc.PushNotificationConfig getConfig() { * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { @@ -245,17 +196,14 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(configId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, configId_); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, taskId_); } if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(5, getConfig()); + output.writeMessage(3, getConfig()); } getUnknownFields().writeTo(output); } @@ -266,18 +214,15 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(configId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, configId_); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, taskId_); } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, getConfig()); + .computeMessageSize(3, getConfig()); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -298,8 +243,6 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getTenant())) return false; if (!getTaskId() .equals(other.getTaskId())) return false; - if (!getConfigId() - .equals(other.getConfigId())) return false; if (hasConfig() != other.hasConfig()) return false; if (hasConfig()) { if (!getConfig() @@ -320,8 +263,6 @@ public int hashCode() { hash = (53 * hash) + getTenant().hashCode(); hash = (37 * hash) + TASK_ID_FIELD_NUMBER; hash = (53 * hash) + getTaskId().hashCode(); - hash = (37 * hash) + CONFIG_ID_FIELD_NUMBER; - hash = (53 * hash) + getConfigId().hashCode(); if (hasConfig()) { hash = (37 * hash) + CONFIG_FIELD_NUMBER; hash = (53 * hash) + getConfig().hashCode(); @@ -425,25 +366,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:CreateTaskPushNotificationConfigRequest]
            * Represents a request for the `CreateTaskPushNotificationConfig` method.
            * 
        * - * Protobuf type {@code a2a.v1.CreateTaskPushNotificationConfigRequest} + * Protobuf type {@code lf.a2a.v1.CreateTaskPushNotificationConfigRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.CreateTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) io.a2a.grpc.CreateTaskPushNotificationConfigRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); } @@ -470,7 +410,6 @@ public Builder clear() { bitField0_ = 0; tenant_ = ""; taskId_ = ""; - configId_ = ""; config_ = null; if (configBuilder_ != null) { configBuilder_.dispose(); @@ -482,7 +421,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override @@ -515,11 +454,8 @@ private void buildPartial0(io.a2a.grpc.CreateTaskPushNotificationConfigRequest r if (((from_bitField0_ & 0x00000002) != 0)) { result.taskId_ = taskId_; } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.configId_ = configId_; - } int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { + if (((from_bitField0_ & 0x00000004) != 0)) { result.config_ = configBuilder_ == null ? config_ : configBuilder_.build(); @@ -550,11 +486,6 @@ public Builder mergeFrom(io.a2a.grpc.CreateTaskPushNotificationConfigRequest oth bitField0_ |= 0x00000002; onChanged(); } - if (!other.getConfigId().isEmpty()) { - configId_ = other.configId_; - bitField0_ |= 0x00000004; - onChanged(); - } if (other.hasConfig()) { mergeConfig(other.getConfig()); } @@ -585,27 +516,22 @@ public Builder mergeFrom( done = true; break; case 10: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; break; } // case 10 case 18: { - configId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; break; } // case 18 - case 34: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 34 - case 42: { + case 26: { input.readMessage( internalGetConfigFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; break; - } // case 42 + } // case 26 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -626,10 +552,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -646,10 +572,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -667,10 +593,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -684,10 +610,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -698,10 +624,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -718,10 +644,10 @@ public Builder setTenantBytes( private java.lang.Object taskId_ = ""; /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ public java.lang.String getTaskId() { @@ -738,10 +664,10 @@ public java.lang.String getTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ public com.google.protobuf.ByteString @@ -759,10 +685,10 @@ public java.lang.String getTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The taskId to set. * @return This builder for chaining. */ @@ -776,10 +702,10 @@ public Builder setTaskId( } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearTaskId() { @@ -790,10 +716,10 @@ public Builder clearTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for taskId to set. * @return This builder for chaining. */ @@ -807,98 +733,6 @@ public Builder setTaskIdBytes( return this; } - private java.lang.Object configId_ = ""; - /** - *
        -     * The ID for the new config.
        -     * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The configId. - */ - public java.lang.String getConfigId() { - java.lang.Object ref = configId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - configId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
        -     * The ID for the new config.
        -     * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for configId. - */ - public com.google.protobuf.ByteString - getConfigIdBytes() { - java.lang.Object ref = configId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - configId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
        -     * The ID for the new config.
        -     * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The configId to set. - * @return This builder for chaining. - */ - public Builder setConfigId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - configId_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
        -     * The ID for the new config.
        -     * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearConfigId() { - configId_ = getDefaultInstance().getConfigId(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
        -     * The ID for the new config.
        -     * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for configId to set. - * @return This builder for chaining. - */ - public Builder setConfigIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - configId_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - private io.a2a.grpc.PushNotificationConfig config_; private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> configBuilder_; @@ -907,18 +741,18 @@ public Builder setConfigIdBytes( * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the config field is set. */ public boolean hasConfig() { - return ((bitField0_ & 0x00000008) != 0); + return ((bitField0_ & 0x00000004) != 0); } /** *
              * The configuration to create.
              * 
        * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The config. */ public io.a2a.grpc.PushNotificationConfig getConfig() { @@ -933,7 +767,7 @@ public io.a2a.grpc.PushNotificationConfig getConfig() { * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setConfig(io.a2a.grpc.PushNotificationConfig value) { if (configBuilder_ == null) { @@ -944,7 +778,7 @@ public Builder setConfig(io.a2a.grpc.PushNotificationConfig value) { } else { configBuilder_.setMessage(value); } - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; onChanged(); return this; } @@ -953,7 +787,7 @@ public Builder setConfig(io.a2a.grpc.PushNotificationConfig value) { * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setConfig( io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { @@ -962,7 +796,7 @@ public Builder setConfig( } else { configBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; onChanged(); return this; } @@ -971,11 +805,11 @@ public Builder setConfig( * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder mergeConfig(io.a2a.grpc.PushNotificationConfig value) { if (configBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && + if (((bitField0_ & 0x00000004) != 0) && config_ != null && config_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { getConfigBuilder().mergeFrom(value); @@ -986,7 +820,7 @@ public Builder mergeConfig(io.a2a.grpc.PushNotificationConfig value) { configBuilder_.mergeFrom(value); } if (config_ != null) { - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; onChanged(); } return this; @@ -996,10 +830,10 @@ public Builder mergeConfig(io.a2a.grpc.PushNotificationConfig value) { * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearConfig() { - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000004); config_ = null; if (configBuilder_ != null) { configBuilder_.dispose(); @@ -1013,10 +847,10 @@ public Builder clearConfig() { * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.PushNotificationConfig.Builder getConfigBuilder() { - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; onChanged(); return internalGetConfigFieldBuilder().getBuilder(); } @@ -1025,7 +859,7 @@ public io.a2a.grpc.PushNotificationConfig.Builder getConfigBuilder() { * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { if (configBuilder_ != null) { @@ -1040,7 +874,7 @@ public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> @@ -1056,10 +890,10 @@ public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { return configBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.CreateTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.CreateTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) private static final io.a2a.grpc.CreateTaskPushNotificationConfigRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.CreateTaskPushNotificationConfigRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java index 77a661f26..d8863657e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface CreateTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.CreateTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -32,50 +32,30 @@ public interface CreateTaskPushNotificationConfigRequestOrBuilder extends /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ java.lang.String getTaskId(); /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ com.google.protobuf.ByteString getTaskIdBytes(); - /** - *
        -   * The ID for the new config.
        -   * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The configId. - */ - java.lang.String getConfigId(); - /** - *
        -   * The ID for the new config.
        -   * 
        - * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for configId. - */ - com.google.protobuf.ByteString - getConfigIdBytes(); - /** *
            * The configuration to create.
            * 
        * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the config field is set. */ boolean hasConfig(); @@ -84,7 +64,7 @@ public interface CreateTaskPushNotificationConfigRequestOrBuilder extends * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The config. */ io.a2a.grpc.PushNotificationConfig getConfig(); @@ -93,7 +73,7 @@ public interface CreateTaskPushNotificationConfigRequestOrBuilder extends * The configuration to create. * * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java index bb1ac53b5..7375f7b5d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:DeleteTaskPushNotificationConfigRequest]
          * Represents a request for the `DeleteTaskPushNotificationConfig` method.
          * 
        * - * Protobuf type {@code a2a.v1.DeleteTaskPushNotificationConfigRequest} + * Protobuf type {@code lf.a2a.v1.DeleteTaskPushNotificationConfigRequest} */ @com.google.protobuf.Generated public final class DeleteTaskPushNotificationConfigRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.DeleteTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.DeleteTaskPushNotificationConfigRequest) DeleteTaskPushNotificationConfigRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -40,26 +39,26 @@ private DeleteTaskPushNotificationConfigRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.class, io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class); } - public static final int TENANT_FIELD_NUMBER = 2; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -77,10 +76,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -98,15 +97,15 @@ public java.lang.String getTenant() { } } - public static final int TASK_ID_FIELD_NUMBER = 3; + public static final int TASK_ID_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object taskId_ = ""; /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ @java.lang.Override @@ -124,10 +123,10 @@ public java.lang.String getTaskId() { } /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ @java.lang.Override @@ -145,15 +144,15 @@ public java.lang.String getTaskId() { } } - public static final int ID_FIELD_NUMBER = 1; + public static final int ID_FIELD_NUMBER = 3; @SuppressWarnings("serial") private volatile java.lang.Object id_ = ""; /** *
        -   * The resource id of the config to delete.
        +   * The resource ID of the configuration to delete.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ @java.lang.Override @@ -171,10 +170,10 @@ public java.lang.String getId() { } /** *
        -   * The resource id of the config to delete.
        +   * The resource ID of the configuration to delete.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ @java.lang.Override @@ -206,14 +205,14 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); + com.google.protobuf.GeneratedMessage.writeString(output, 2, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, id_); } getUnknownFields().writeTo(output); } @@ -224,14 +223,14 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, id_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -370,25 +369,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:DeleteTaskPushNotificationConfigRequest]
            * Represents a request for the `DeleteTaskPushNotificationConfig` method.
            * 
        * - * Protobuf type {@code a2a.v1.DeleteTaskPushNotificationConfigRequest} + * Protobuf type {@code lf.a2a.v1.DeleteTaskPushNotificationConfigRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.DeleteTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.DeleteTaskPushNotificationConfigRequest) io.a2a.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.class, io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class); } @@ -416,7 +414,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override @@ -508,18 +506,18 @@ public Builder mergeFrom( done = true; break; case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; break; } // case 10 case 18: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; break; } // case 18 case 26: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; break; } // case 26 default: { @@ -542,10 +540,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -562,10 +560,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -583,10 +581,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -600,10 +598,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -614,10 +612,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -634,10 +632,10 @@ public Builder setTenantBytes( private java.lang.Object taskId_ = ""; /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ public java.lang.String getTaskId() { @@ -654,10 +652,10 @@ public java.lang.String getTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ public com.google.protobuf.ByteString @@ -675,10 +673,10 @@ public java.lang.String getTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The taskId to set. * @return This builder for chaining. */ @@ -692,10 +690,10 @@ public Builder setTaskId( } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearTaskId() { @@ -706,10 +704,10 @@ public Builder clearTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for taskId to set. * @return This builder for chaining. */ @@ -726,10 +724,10 @@ public Builder setTaskIdBytes( private java.lang.Object id_ = ""; /** *
        -     * The resource id of the config to delete.
        +     * The resource ID of the configuration to delete.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ public java.lang.String getId() { @@ -746,10 +744,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the config to delete.
        +     * The resource ID of the configuration to delete.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ public com.google.protobuf.ByteString @@ -767,10 +765,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the config to delete.
        +     * The resource ID of the configuration to delete.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @param value The id to set. * @return This builder for chaining. */ @@ -784,10 +782,10 @@ public Builder setId( } /** *
        -     * The resource id of the config to delete.
        +     * The resource ID of the configuration to delete.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearId() { @@ -798,10 +796,10 @@ public Builder clearId() { } /** *
        -     * The resource id of the config to delete.
        +     * The resource ID of the configuration to delete.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for id to set. * @return This builder for chaining. */ @@ -815,10 +813,10 @@ public Builder setIdBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.DeleteTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.DeleteTaskPushNotificationConfigRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.DeleteTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.DeleteTaskPushNotificationConfigRequest) private static final io.a2a.grpc.DeleteTaskPushNotificationConfigRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.DeleteTaskPushNotificationConfigRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java index 4219aea04..f0f9c4b0d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface DeleteTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.DeleteTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.DeleteTaskPushNotificationConfigRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -32,19 +32,19 @@ public interface DeleteTaskPushNotificationConfigRequestOrBuilder extends /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ java.lang.String getTaskId(); /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ com.google.protobuf.ByteString @@ -52,19 +52,19 @@ public interface DeleteTaskPushNotificationConfigRequestOrBuilder extends /** *
        -   * The resource id of the config to delete.
        +   * The resource ID of the configuration to delete.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ java.lang.String getId(); /** *
        -   * The resource id of the config to delete.
        +   * The resource ID of the configuration to delete.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ com.google.protobuf.ByteString diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java index 701371c2b..15c0404ca 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java @@ -7,18 +7,17 @@ /** *
        - * --8<-- [start:DeviceCodeOAuthFlow]
          * Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628).
          * This flow is designed for input-constrained devices such as IoT devices,
          * and CLI tools where the user authenticates on a separate device.
          * 
        * - * Protobuf type {@code a2a.v1.DeviceCodeOAuthFlow} + * Protobuf type {@code lf.a2a.v1.DeviceCodeOAuthFlow} */ @com.google.protobuf.Generated public final class DeviceCodeOAuthFlow extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.DeviceCodeOAuthFlow) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.DeviceCodeOAuthFlow) DeviceCodeOAuthFlowOrBuilder { private static final long serialVersionUID = 0L; static { @@ -42,7 +41,7 @@ private DeviceCodeOAuthFlow() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -60,7 +59,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.DeviceCodeOAuthFlow.class, io.a2a.grpc.DeviceCodeOAuthFlow.Builder.class); } @@ -212,7 +211,7 @@ private static final class ScopesDefaultEntryHolder { java.lang.String, java.lang.String> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.STRING, @@ -501,21 +500,20 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:DeviceCodeOAuthFlow]
            * Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628).
            * This flow is designed for input-constrained devices such as IoT devices,
            * and CLI tools where the user authenticates on a separate device.
            * 
        * - * Protobuf type {@code a2a.v1.DeviceCodeOAuthFlow} + * Protobuf type {@code lf.a2a.v1.DeviceCodeOAuthFlow} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.DeviceCodeOAuthFlow) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.DeviceCodeOAuthFlow) io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -543,7 +541,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.DeviceCodeOAuthFlow.class, io.a2a.grpc.DeviceCodeOAuthFlow.Builder.class); } @@ -572,7 +570,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor; } @java.lang.Override @@ -1142,10 +1140,10 @@ public Builder putAllScopes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.DeviceCodeOAuthFlow) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.DeviceCodeOAuthFlow) } - // @@protoc_insertion_point(class_scope:a2a.v1.DeviceCodeOAuthFlow) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.DeviceCodeOAuthFlow) private static final io.a2a.grpc.DeviceCodeOAuthFlow DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.DeviceCodeOAuthFlow(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java index 761e2a6db..d7b8add51 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface DeviceCodeOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.DeviceCodeOAuthFlow) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.DeviceCodeOAuthFlow) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java index 5c1b07907..452f7481e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java @@ -7,15 +7,15 @@ /** *
        - * --8<-- [start:GetExtendedAgentCardRequest]
        + * Represents a request for the `GetExtendedAgentCard` method.
          * 
        * - * Protobuf type {@code a2a.v1.GetExtendedAgentCardRequest} + * Protobuf type {@code lf.a2a.v1.GetExtendedAgentCardRequest} */ @com.google.protobuf.Generated public final class GetExtendedAgentCardRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.GetExtendedAgentCardRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.GetExtendedAgentCardRequest) GetExtendedAgentCardRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -37,13 +37,13 @@ private GetExtendedAgentCardRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.GetExtendedAgentCardRequest.class, io.a2a.grpc.GetExtendedAgentCardRequest.Builder.class); } @@ -53,7 +53,7 @@ private GetExtendedAgentCardRequest() { private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * * string tenant = 1; @@ -74,7 +74,7 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * * string tenant = 1; @@ -253,24 +253,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:GetExtendedAgentCardRequest]
        +   * Represents a request for the `GetExtendedAgentCard` method.
            * 
        * - * Protobuf type {@code a2a.v1.GetExtendedAgentCardRequest} + * Protobuf type {@code lf.a2a.v1.GetExtendedAgentCardRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.GetExtendedAgentCardRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.GetExtendedAgentCardRequest) io.a2a.grpc.GetExtendedAgentCardRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.GetExtendedAgentCardRequest.class, io.a2a.grpc.GetExtendedAgentCardRequest.Builder.class); } @@ -296,7 +296,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor; } @java.lang.Override @@ -396,7 +396,7 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 1; @@ -416,7 +416,7 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 1; @@ -437,7 +437,7 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 1; @@ -454,7 +454,7 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 1; @@ -468,7 +468,7 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 1; @@ -485,10 +485,10 @@ public Builder setTenantBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.GetExtendedAgentCardRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.GetExtendedAgentCardRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.GetExtendedAgentCardRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.GetExtendedAgentCardRequest) private static final io.a2a.grpc.GetExtendedAgentCardRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.GetExtendedAgentCardRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java index f6efaa410..e7f6a6615 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java @@ -7,12 +7,12 @@ @com.google.protobuf.Generated public interface GetExtendedAgentCardRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.GetExtendedAgentCardRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.GetExtendedAgentCardRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * * string tenant = 1; @@ -21,7 +21,7 @@ public interface GetExtendedAgentCardRequestOrBuilder extends java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * * string tenant = 1; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java index e254a9022..5fc7aa7fc 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java @@ -7,15 +7,15 @@ /** *
        - * --8<-- [start:GetTaskPushNotificationConfigRequest]
        + * Represents a request for the `GetTaskPushNotificationConfig` method.
          * 
        * - * Protobuf type {@code a2a.v1.GetTaskPushNotificationConfigRequest} + * Protobuf type {@code lf.a2a.v1.GetTaskPushNotificationConfigRequest} */ @com.google.protobuf.Generated public final class GetTaskPushNotificationConfigRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.GetTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.GetTaskPushNotificationConfigRequest) GetTaskPushNotificationConfigRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,26 +39,26 @@ private GetTaskPushNotificationConfigRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.GetTaskPushNotificationConfigRequest.class, io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder.class); } - public static final int TENANT_FIELD_NUMBER = 2; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -76,10 +76,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -97,15 +97,15 @@ public java.lang.String getTenant() { } } - public static final int TASK_ID_FIELD_NUMBER = 3; + public static final int TASK_ID_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object taskId_ = ""; /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ @java.lang.Override @@ -123,10 +123,10 @@ public java.lang.String getTaskId() { } /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ @java.lang.Override @@ -144,15 +144,15 @@ public java.lang.String getTaskId() { } } - public static final int ID_FIELD_NUMBER = 1; + public static final int ID_FIELD_NUMBER = 3; @SuppressWarnings("serial") private volatile java.lang.Object id_ = ""; /** *
        -   * The resource id of the config to retrieve.
        +   * The resource ID of the configuration to retrieve.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ @java.lang.Override @@ -170,10 +170,10 @@ public java.lang.String getId() { } /** *
        -   * The resource id of the config to retrieve.
        +   * The resource ID of the configuration to retrieve.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ @java.lang.Override @@ -205,14 +205,14 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); + com.google.protobuf.GeneratedMessage.writeString(output, 2, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, id_); } getUnknownFields().writeTo(output); } @@ -223,14 +223,14 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, id_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -369,24 +369,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:GetTaskPushNotificationConfigRequest]
        +   * Represents a request for the `GetTaskPushNotificationConfig` method.
            * 
        * - * Protobuf type {@code a2a.v1.GetTaskPushNotificationConfigRequest} + * Protobuf type {@code lf.a2a.v1.GetTaskPushNotificationConfigRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.GetTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.GetTaskPushNotificationConfigRequest) io.a2a.grpc.GetTaskPushNotificationConfigRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.GetTaskPushNotificationConfigRequest.class, io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder.class); } @@ -414,7 +414,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; } @java.lang.Override @@ -506,18 +506,18 @@ public Builder mergeFrom( done = true; break; case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; break; } // case 10 case 18: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; break; } // case 18 case 26: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; break; } // case 26 default: { @@ -540,10 +540,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -560,10 +560,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -581,10 +581,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -598,10 +598,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -612,10 +612,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -632,10 +632,10 @@ public Builder setTenantBytes( private java.lang.Object taskId_ = ""; /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ public java.lang.String getTaskId() { @@ -652,10 +652,10 @@ public java.lang.String getTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ public com.google.protobuf.ByteString @@ -673,10 +673,10 @@ public java.lang.String getTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The taskId to set. * @return This builder for chaining. */ @@ -690,10 +690,10 @@ public Builder setTaskId( } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearTaskId() { @@ -704,10 +704,10 @@ public Builder clearTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for taskId to set. * @return This builder for chaining. */ @@ -724,10 +724,10 @@ public Builder setTaskIdBytes( private java.lang.Object id_ = ""; /** *
        -     * The resource id of the config to retrieve.
        +     * The resource ID of the configuration to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ public java.lang.String getId() { @@ -744,10 +744,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the config to retrieve.
        +     * The resource ID of the configuration to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ public com.google.protobuf.ByteString @@ -765,10 +765,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the config to retrieve.
        +     * The resource ID of the configuration to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @param value The id to set. * @return This builder for chaining. */ @@ -782,10 +782,10 @@ public Builder setId( } /** *
        -     * The resource id of the config to retrieve.
        +     * The resource ID of the configuration to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearId() { @@ -796,10 +796,10 @@ public Builder clearId() { } /** *
        -     * The resource id of the config to retrieve.
        +     * The resource ID of the configuration to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for id to set. * @return This builder for chaining. */ @@ -813,10 +813,10 @@ public Builder setIdBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.GetTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.GetTaskPushNotificationConfigRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.GetTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.GetTaskPushNotificationConfigRequest) private static final io.a2a.grpc.GetTaskPushNotificationConfigRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.GetTaskPushNotificationConfigRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java index 5e9047f46..9c6ab84e3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface GetTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.GetTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.GetTaskPushNotificationConfigRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -32,19 +32,19 @@ public interface GetTaskPushNotificationConfigRequestOrBuilder extends /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ java.lang.String getTaskId(); /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ com.google.protobuf.ByteString @@ -52,19 +52,19 @@ public interface GetTaskPushNotificationConfigRequestOrBuilder extends /** *
        -   * The resource id of the config to retrieve.
        +   * The resource ID of the configuration to retrieve.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ java.lang.String getId(); /** *
        -   * The resource id of the config to retrieve.
        +   * The resource ID of the configuration to retrieve.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ com.google.protobuf.ByteString diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java index 9fa872c52..2d6ff2246 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:GetTaskRequest]
          * Represents a request for the `GetTask` method.
          * 
        * - * Protobuf type {@code a2a.v1.GetTaskRequest} + * Protobuf type {@code lf.a2a.v1.GetTaskRequest} */ @com.google.protobuf.Generated public final class GetTaskRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.GetTaskRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.GetTaskRequest) GetTaskRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,27 +38,27 @@ private GetTaskRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.GetTaskRequest.class, io.a2a.grpc.GetTaskRequest.Builder.class); } private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 3; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 3; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -77,10 +76,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 3; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -98,15 +97,15 @@ public java.lang.String getTenant() { } } - public static final int ID_FIELD_NUMBER = 1; + public static final int ID_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object id_ = ""; /** *
        -   * The resource id of the task.
        +   * The resource ID of the task to retrieve.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ @java.lang.Override @@ -124,10 +123,10 @@ public java.lang.String getId() { } /** *
        -   * The resource id of the task.
        +   * The resource ID of the task to retrieve.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ @java.lang.Override @@ -145,7 +144,7 @@ public java.lang.String getId() { } } - public static final int HISTORY_LENGTH_FIELD_NUMBER = 2; + public static final int HISTORY_LENGTH_FIELD_NUMBER = 3; private int historyLength_ = 0; /** *
        @@ -155,7 +154,7 @@ public java.lang.String getId() {
            * messages than the provided value, but MAY apply a lower limit.
            * 
        * - * optional int32 history_length = 2; + * optional int32 history_length = 3; * @return Whether the historyLength field is set. */ @java.lang.Override @@ -170,7 +169,7 @@ public boolean hasHistoryLength() { * messages than the provided value, but MAY apply a lower limit. * * - * optional int32 history_length = 2; + * optional int32 history_length = 3; * @return The historyLength. */ @java.lang.Override @@ -192,14 +191,14 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); + com.google.protobuf.GeneratedMessage.writeString(output, 2, id_); } if (((bitField0_ & 0x00000001) != 0)) { - output.writeInt32(2, historyLength_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, tenant_); + output.writeInt32(3, historyLength_); } getUnknownFields().writeTo(output); } @@ -210,15 +209,15 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, id_); } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeInt32Size(2, historyLength_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, tenant_); + .computeInt32Size(3, historyLength_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -362,25 +361,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:GetTaskRequest]
            * Represents a request for the `GetTask` method.
            * 
        * - * Protobuf type {@code a2a.v1.GetTaskRequest} + * Protobuf type {@code lf.a2a.v1.GetTaskRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.GetTaskRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.GetTaskRequest) io.a2a.grpc.GetTaskRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.GetTaskRequest.class, io.a2a.grpc.GetTaskRequest.Builder.class); } @@ -408,7 +406,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor; } @java.lang.Override @@ -501,20 +499,20 @@ public Builder mergeFrom( done = true; break; case 10: { + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { id_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; - } // case 10 - case 16: { + } // case 18 + case 24: { historyLength_ = input.readInt32(); bitField0_ |= 0x00000004; break; - } // case 16 - case 26: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 26 + } // case 24 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -535,10 +533,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 3; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -555,10 +553,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 3; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -576,10 +574,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 3; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -593,10 +591,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 3; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -607,10 +605,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 3; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -627,10 +625,10 @@ public Builder setTenantBytes( private java.lang.Object id_ = ""; /** *
        -     * The resource id of the task.
        +     * The resource ID of the task to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ public java.lang.String getId() { @@ -647,10 +645,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the task.
        +     * The resource ID of the task to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ public com.google.protobuf.ByteString @@ -668,10 +666,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the task.
        +     * The resource ID of the task to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The id to set. * @return This builder for chaining. */ @@ -685,10 +683,10 @@ public Builder setId( } /** *
        -     * The resource id of the task.
        +     * The resource ID of the task to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearId() { @@ -699,10 +697,10 @@ public Builder clearId() { } /** *
        -     * The resource id of the task.
        +     * The resource ID of the task to retrieve.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for id to set. * @return This builder for chaining. */ @@ -725,7 +723,7 @@ public Builder setIdBytes( * messages than the provided value, but MAY apply a lower limit. * * - * optional int32 history_length = 2; + * optional int32 history_length = 3; * @return Whether the historyLength field is set. */ @java.lang.Override @@ -740,7 +738,7 @@ public boolean hasHistoryLength() { * messages than the provided value, but MAY apply a lower limit. * * - * optional int32 history_length = 2; + * optional int32 history_length = 3; * @return The historyLength. */ @java.lang.Override @@ -755,7 +753,7 @@ public int getHistoryLength() { * messages than the provided value, but MAY apply a lower limit. * * - * optional int32 history_length = 2; + * optional int32 history_length = 3; * @param value The historyLength to set. * @return This builder for chaining. */ @@ -774,7 +772,7 @@ public Builder setHistoryLength(int value) { * messages than the provided value, but MAY apply a lower limit. * * - * optional int32 history_length = 2; + * optional int32 history_length = 3; * @return This builder for chaining. */ public Builder clearHistoryLength() { @@ -784,10 +782,10 @@ public Builder clearHistoryLength() { return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.GetTaskRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.GetTaskRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.GetTaskRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.GetTaskRequest) private static final io.a2a.grpc.GetTaskRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.GetTaskRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java index 7a86eb56c..e844a918c 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface GetTaskRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.GetTaskRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.GetTaskRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 3; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 3; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -32,19 +32,19 @@ public interface GetTaskRequestOrBuilder extends /** *
        -   * The resource id of the task.
        +   * The resource ID of the task to retrieve.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ java.lang.String getId(); /** *
        -   * The resource id of the task.
        +   * The resource ID of the task to retrieve.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ com.google.protobuf.ByteString @@ -58,7 +58,7 @@ public interface GetTaskRequestOrBuilder extends * messages than the provided value, but MAY apply a lower limit. * * - * optional int32 history_length = 2; + * optional int32 history_length = 3; * @return Whether the historyLength field is set. */ boolean hasHistoryLength(); @@ -70,7 +70,7 @@ public interface GetTaskRequestOrBuilder extends * messages than the provided value, but MAY apply a lower limit. * * - * optional int32 history_length = 2; + * optional int32 history_length = 3; * @return The historyLength. */ int getHistoryLength(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java index cad53d0b9..9e1132a20 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:HTTPAuthSecurityScheme]
          * Defines a security scheme using HTTP authentication.
          * 
        * - * Protobuf type {@code a2a.v1.HTTPAuthSecurityScheme} + * Protobuf type {@code lf.a2a.v1.HTTPAuthSecurityScheme} */ @com.google.protobuf.Generated public final class HTTPAuthSecurityScheme extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.HTTPAuthSecurityScheme) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.HTTPAuthSecurityScheme) HTTPAuthSecuritySchemeOrBuilder { private static final long serialVersionUID = 0L; static { @@ -40,13 +39,13 @@ private HTTPAuthSecurityScheme() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.HTTPAuthSecurityScheme.class, io.a2a.grpc.HTTPAuthSecurityScheme.Builder.class); } @@ -155,7 +154,7 @@ public java.lang.String getScheme() { /** *
            * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -   * This is primarily for documentation purposes.
        +   * Primarily for documentation purposes.
            * 
        * * string bearer_format = 3; @@ -177,7 +176,7 @@ public java.lang.String getBearerFormat() { /** *
            * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -   * This is primarily for documentation purposes.
        +   * Primarily for documentation purposes.
            * 
        * * string bearer_format = 3; @@ -376,25 +375,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:HTTPAuthSecurityScheme]
            * Defines a security scheme using HTTP authentication.
            * 
        * - * Protobuf type {@code a2a.v1.HTTPAuthSecurityScheme} + * Protobuf type {@code lf.a2a.v1.HTTPAuthSecurityScheme} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.HTTPAuthSecurityScheme) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.HTTPAuthSecurityScheme) io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.HTTPAuthSecurityScheme.class, io.a2a.grpc.HTTPAuthSecurityScheme.Builder.class); } @@ -422,7 +420,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor; } @java.lang.Override @@ -743,7 +741,7 @@ public Builder setSchemeBytes( /** *
              * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -     * This is primarily for documentation purposes.
        +     * Primarily for documentation purposes.
              * 
        * * string bearer_format = 3; @@ -764,7 +762,7 @@ public java.lang.String getBearerFormat() { /** *
              * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -     * This is primarily for documentation purposes.
        +     * Primarily for documentation purposes.
              * 
        * * string bearer_format = 3; @@ -786,7 +784,7 @@ public java.lang.String getBearerFormat() { /** *
              * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -     * This is primarily for documentation purposes.
        +     * Primarily for documentation purposes.
              * 
        * * string bearer_format = 3; @@ -804,7 +802,7 @@ public Builder setBearerFormat( /** *
              * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -     * This is primarily for documentation purposes.
        +     * Primarily for documentation purposes.
              * 
        * * string bearer_format = 3; @@ -819,7 +817,7 @@ public Builder clearBearerFormat() { /** *
              * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -     * This is primarily for documentation purposes.
        +     * Primarily for documentation purposes.
              * 
        * * string bearer_format = 3; @@ -836,10 +834,10 @@ public Builder setBearerFormatBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.HTTPAuthSecurityScheme) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.HTTPAuthSecurityScheme) } - // @@protoc_insertion_point(class_scope:a2a.v1.HTTPAuthSecurityScheme) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.HTTPAuthSecurityScheme) private static final io.a2a.grpc.HTTPAuthSecurityScheme DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.HTTPAuthSecurityScheme(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java index 9a8e8847b..ee79f8014 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface HTTPAuthSecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.HTTPAuthSecurityScheme) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.HTTPAuthSecurityScheme) com.google.protobuf.MessageOrBuilder { /** @@ -57,7 +57,7 @@ public interface HTTPAuthSecuritySchemeOrBuilder extends /** *
            * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -   * This is primarily for documentation purposes.
        +   * Primarily for documentation purposes.
            * 
        * * string bearer_format = 3; @@ -67,7 +67,7 @@ public interface HTTPAuthSecuritySchemeOrBuilder extends /** *
            * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
        -   * This is primarily for documentation purposes.
        +   * Primarily for documentation purposes.
            * 
        * * string bearer_format = 3; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java index e1fd0601c..e11473d4f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java @@ -7,15 +7,15 @@ /** *
        - * DEPRECATED
        + * Deprecated: Use Authorization Code + PKCE instead.
          * 
        * - * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} + * Protobuf type {@code lf.a2a.v1.ImplicitOAuthFlow} */ @com.google.protobuf.Generated public final class ImplicitOAuthFlow extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ImplicitOAuthFlow) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.ImplicitOAuthFlow) ImplicitOAuthFlowOrBuilder { private static final long serialVersionUID = 0L; static { @@ -38,7 +38,7 @@ private ImplicitOAuthFlow() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -56,7 +56,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class); } @@ -165,7 +165,7 @@ private static final class ScopesDefaultEntryHolder { java.lang.String, java.lang.String> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.STRING, @@ -448,18 +448,18 @@ protected Builder newBuilderForType( } /** *
        -   * DEPRECATED
        +   * Deprecated: Use Authorization Code + PKCE instead.
            * 
        * - * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} + * Protobuf type {@code lf.a2a.v1.ImplicitOAuthFlow} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ImplicitOAuthFlow) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ImplicitOAuthFlow) io.a2a.grpc.ImplicitOAuthFlowOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -487,7 +487,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class); } @@ -515,7 +515,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor; } @java.lang.Override @@ -997,10 +997,10 @@ public Builder putAllScopes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.ImplicitOAuthFlow) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.ImplicitOAuthFlow) } - // @@protoc_insertion_point(class_scope:a2a.v1.ImplicitOAuthFlow) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.ImplicitOAuthFlow) private static final io.a2a.grpc.ImplicitOAuthFlow DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.ImplicitOAuthFlow(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java index 3b0180dbc..90d959a61 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface ImplicitOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ImplicitOAuthFlow) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.ImplicitOAuthFlow) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequest.java similarity index 81% rename from spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java rename to spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequest.java index b80396df7..a95d7ea53 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequest.java @@ -7,16 +7,16 @@ /** *
        - * --8<-- [start:ListTaskPushNotificationConfigRequest]
        + * Represents a request for the `ListTaskPushNotificationConfigs` method.
          * 
        * - * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigRequest} + * Protobuf type {@code lf.a2a.v1.ListTaskPushNotificationConfigsRequest} */ @com.google.protobuf.Generated -public final class ListTaskPushNotificationConfigRequest extends +public final class ListTaskPushNotificationConfigsRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ListTaskPushNotificationConfigRequest) - ListTaskPushNotificationConfigRequestOrBuilder { + // @@protoc_insertion_point(message_implements:lf.a2a.v1.ListTaskPushNotificationConfigsRequest) + ListTaskPushNotificationConfigsRequestOrBuilder { private static final long serialVersionUID = 0L; static { com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( @@ -25,13 +25,13 @@ public final class ListTaskPushNotificationConfigRequest extends /* minor= */ 33, /* patch= */ 1, /* suffix= */ "", - "ListTaskPushNotificationConfigRequest"); + "ListTaskPushNotificationConfigsRequest"); } - // Use ListTaskPushNotificationConfigRequest.newBuilder() to construct. - private ListTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + // Use ListTaskPushNotificationConfigsRequest.newBuilder() to construct. + private ListTaskPushNotificationConfigsRequest(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); } - private ListTaskPushNotificationConfigRequest() { + private ListTaskPushNotificationConfigsRequest() { tenant_ = ""; taskId_ = ""; pageToken_ = ""; @@ -39,15 +39,15 @@ private ListTaskPushNotificationConfigRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTaskPushNotificationConfigRequest.class, io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder.class); + io.a2a.grpc.ListTaskPushNotificationConfigsRequest.class, io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder.class); } public static final int TENANT_FIELD_NUMBER = 4; @@ -55,7 +55,7 @@ private ListTaskPushNotificationConfigRequest() { private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * * string tenant = 4; @@ -76,7 +76,7 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * * string tenant = 4; @@ -102,7 +102,7 @@ public java.lang.String getTenant() { private volatile java.lang.Object taskId_ = ""; /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -123,7 +123,7 @@ public java.lang.String getTaskId() { } /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -164,7 +164,7 @@ public int getPageSize() { private volatile java.lang.Object pageToken_ = ""; /** *
        -   * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +   * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
            * 
        * * string page_token = 3; @@ -185,7 +185,7 @@ public java.lang.String getPageToken() { } /** *
        -   * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +   * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
            * 
        * * string page_token = 3; @@ -264,10 +264,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.a2a.grpc.ListTaskPushNotificationConfigRequest)) { + if (!(obj instanceof io.a2a.grpc.ListTaskPushNotificationConfigsRequest)) { return super.equals(obj); } - io.a2a.grpc.ListTaskPushNotificationConfigRequest other = (io.a2a.grpc.ListTaskPushNotificationConfigRequest) obj; + io.a2a.grpc.ListTaskPushNotificationConfigsRequest other = (io.a2a.grpc.ListTaskPushNotificationConfigsRequest) obj; if (!getTenant() .equals(other.getTenant())) return false; @@ -301,44 +301,44 @@ public int hashCode() { return hash; } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom(byte[] data) + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -346,26 +346,26 @@ public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseDelimitedFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -378,7 +378,7 @@ public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.a2a.grpc.ListTaskPushNotificationConfigRequest prototype) { + public static Builder newBuilder(io.a2a.grpc.ListTaskPushNotificationConfigsRequest prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -395,29 +395,29 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:ListTaskPushNotificationConfigRequest]
        +   * Represents a request for the `ListTaskPushNotificationConfigs` method.
            * 
        * - * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigRequest} + * Protobuf type {@code lf.a2a.v1.ListTaskPushNotificationConfigsRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ListTaskPushNotificationConfigRequest) - io.a2a.grpc.ListTaskPushNotificationConfigRequestOrBuilder { + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ListTaskPushNotificationConfigsRequest) + io.a2a.grpc.ListTaskPushNotificationConfigsRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTaskPushNotificationConfigRequest.class, io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder.class); + io.a2a.grpc.ListTaskPushNotificationConfigsRequest.class, io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder.class); } - // Construct using io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder() + // Construct using io.a2a.grpc.ListTaskPushNotificationConfigsRequest.newBuilder() private Builder() { } @@ -441,17 +441,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor; } @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return io.a2a.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance(); + public io.a2a.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstanceForType() { + return io.a2a.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance(); } @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigRequest build() { - io.a2a.grpc.ListTaskPushNotificationConfigRequest result = buildPartial(); + public io.a2a.grpc.ListTaskPushNotificationConfigsRequest build() { + io.a2a.grpc.ListTaskPushNotificationConfigsRequest result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -459,14 +459,14 @@ public io.a2a.grpc.ListTaskPushNotificationConfigRequest build() { } @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigRequest buildPartial() { - io.a2a.grpc.ListTaskPushNotificationConfigRequest result = new io.a2a.grpc.ListTaskPushNotificationConfigRequest(this); + public io.a2a.grpc.ListTaskPushNotificationConfigsRequest buildPartial() { + io.a2a.grpc.ListTaskPushNotificationConfigsRequest result = new io.a2a.grpc.ListTaskPushNotificationConfigsRequest(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigRequest result) { + private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigsRequest result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { result.tenant_ = tenant_; @@ -484,16 +484,16 @@ private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigRequest res @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ListTaskPushNotificationConfigRequest) { - return mergeFrom((io.a2a.grpc.ListTaskPushNotificationConfigRequest)other); + if (other instanceof io.a2a.grpc.ListTaskPushNotificationConfigsRequest) { + return mergeFrom((io.a2a.grpc.ListTaskPushNotificationConfigsRequest)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigRequest other) { - if (other == io.a2a.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance()) return this; + public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigsRequest other) { + if (other == io.a2a.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance()) return this; if (!other.getTenant().isEmpty()) { tenant_ = other.tenant_; bitField0_ |= 0x00000001; @@ -578,7 +578,7 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 4; @@ -598,7 +598,7 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 4; @@ -619,7 +619,7 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 4; @@ -636,7 +636,7 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 4; @@ -650,7 +650,7 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * * string tenant = 4; @@ -670,7 +670,7 @@ public Builder setTenantBytes( private java.lang.Object taskId_ = ""; /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -690,7 +690,7 @@ public java.lang.String getTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -711,7 +711,7 @@ public java.lang.String getTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -728,7 +728,7 @@ public Builder setTaskId( } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -742,7 +742,7 @@ public Builder clearTaskId() { } /** *
        -     * The parent task resource id.
        +     * The parent task resource ID.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -806,7 +806,7 @@ public Builder clearPageSize() { private java.lang.Object pageToken_ = ""; /** *
        -     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +     * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
              * 
        * * string page_token = 3; @@ -826,7 +826,7 @@ public java.lang.String getPageToken() { } /** *
        -     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +     * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
              * 
        * * string page_token = 3; @@ -847,7 +847,7 @@ public java.lang.String getPageToken() { } /** *
        -     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +     * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
              * 
        * * string page_token = 3; @@ -864,7 +864,7 @@ public Builder setPageToken( } /** *
        -     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +     * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
              * 
        * * string page_token = 3; @@ -878,7 +878,7 @@ public Builder clearPageToken() { } /** *
        -     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +     * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
              * 
        * * string page_token = 3; @@ -895,23 +895,23 @@ public Builder setPageTokenBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.ListTaskPushNotificationConfigRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.ListTaskPushNotificationConfigsRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.ListTaskPushNotificationConfigRequest) - private static final io.a2a.grpc.ListTaskPushNotificationConfigRequest DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:lf.a2a.v1.ListTaskPushNotificationConfigsRequest) + private static final io.a2a.grpc.ListTaskPushNotificationConfigsRequest DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.a2a.grpc.ListTaskPushNotificationConfigRequest(); + DEFAULT_INSTANCE = new io.a2a.grpc.ListTaskPushNotificationConfigsRequest(); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest getDefaultInstance() { + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { @java.lang.Override - public ListTaskPushNotificationConfigRequest parsePartialFrom( + public ListTaskPushNotificationConfigsRequest parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { @@ -930,17 +930,17 @@ public ListTaskPushNotificationConfigRequest parsePartialFrom( } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } @java.lang.Override - public com.google.protobuf.Parser getParserForType() { + public com.google.protobuf.Parser getParserForType() { return PARSER; } @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigRequest getDefaultInstanceForType() { + public io.a2a.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstanceForType() { return DEFAULT_INSTANCE; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java similarity index 73% rename from spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java rename to spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java index ba43bb3d7..adaf35d45 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java @@ -6,13 +6,13 @@ package io.a2a.grpc; @com.google.protobuf.Generated -public interface ListTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ListTaskPushNotificationConfigRequest) +public interface ListTaskPushNotificationConfigsRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.ListTaskPushNotificationConfigsRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * * string tenant = 4; @@ -21,7 +21,7 @@ public interface ListTaskPushNotificationConfigRequestOrBuilder extends java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * * string tenant = 4; @@ -32,7 +32,7 @@ public interface ListTaskPushNotificationConfigRequestOrBuilder extends /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -41,7 +41,7 @@ public interface ListTaskPushNotificationConfigRequestOrBuilder extends java.lang.String getTaskId(); /** *
        -   * The parent task resource id.
        +   * The parent task resource ID.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -62,7 +62,7 @@ public interface ListTaskPushNotificationConfigRequestOrBuilder extends /** *
        -   * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +   * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
            * 
        * * string page_token = 3; @@ -71,7 +71,7 @@ public interface ListTaskPushNotificationConfigRequestOrBuilder extends java.lang.String getPageToken(); /** *
        -   * A page token received from a previous ListTaskPushNotificationConfigRequest call.
        +   * A page token received from a previous `ListTaskPushNotificationConfigsRequest` call.
            * 
        * * string page_token = 3; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponse.java similarity index 78% rename from spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java rename to spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponse.java index e057230c9..231e22f89 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponse.java @@ -7,18 +7,17 @@ /** *
        - * --8<-- [start:ListTaskPushNotificationConfigResponse]
        - * Represents a successful response for the `ListTaskPushNotificationConfig`
        + * Represents a successful response for the `ListTaskPushNotificationConfigs`
          * method.
          * 
        * - * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigResponse} + * Protobuf type {@code lf.a2a.v1.ListTaskPushNotificationConfigsResponse} */ @com.google.protobuf.Generated -public final class ListTaskPushNotificationConfigResponse extends +public final class ListTaskPushNotificationConfigsResponse extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ListTaskPushNotificationConfigResponse) - ListTaskPushNotificationConfigResponseOrBuilder { + // @@protoc_insertion_point(message_implements:lf.a2a.v1.ListTaskPushNotificationConfigsResponse) + ListTaskPushNotificationConfigsResponseOrBuilder { private static final long serialVersionUID = 0L; static { com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( @@ -27,28 +26,28 @@ public final class ListTaskPushNotificationConfigResponse extends /* minor= */ 33, /* patch= */ 1, /* suffix= */ "", - "ListTaskPushNotificationConfigResponse"); + "ListTaskPushNotificationConfigsResponse"); } - // Use ListTaskPushNotificationConfigResponse.newBuilder() to construct. - private ListTaskPushNotificationConfigResponse(com.google.protobuf.GeneratedMessage.Builder builder) { + // Use ListTaskPushNotificationConfigsResponse.newBuilder() to construct. + private ListTaskPushNotificationConfigsResponse(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); } - private ListTaskPushNotificationConfigResponse() { + private ListTaskPushNotificationConfigsResponse() { configs_ = java.util.Collections.emptyList(); nextPageToken_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTaskPushNotificationConfigResponse.class, io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder.class); + io.a2a.grpc.ListTaskPushNotificationConfigsResponse.class, io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder.class); } public static final int CONFIGS_FIELD_NUMBER = 1; @@ -59,7 +58,7 @@ private ListTaskPushNotificationConfigResponse() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ @java.lang.Override public java.util.List getConfigsList() { @@ -70,7 +69,7 @@ public java.util.List getConfigsList() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ @java.lang.Override public java.util.List @@ -82,7 +81,7 @@ public java.util.List getConfigsList() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ @java.lang.Override public int getConfigsCount() { @@ -93,7 +92,7 @@ public int getConfigsCount() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ @java.lang.Override public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) { @@ -104,7 +103,7 @@ public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ @java.lang.Override public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( @@ -117,8 +116,7 @@ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( private volatile java.lang.Object nextPageToken_ = ""; /** *
        -   * A token, which can be sent as `page_token` to retrieve the next page.
        -   * If this field is omitted, there are no subsequent pages.
        +   * A token to retrieve the next page of results, or empty if there are no more results in the list.
            * 
        * * string next_page_token = 2; @@ -139,8 +137,7 @@ public java.lang.String getNextPageToken() { } /** *
        -   * A token, which can be sent as `page_token` to retrieve the next page.
        -   * If this field is omitted, there are no subsequent pages.
        +   * A token to retrieve the next page of results, or empty if there are no more results in the list.
            * 
        * * string next_page_token = 2; @@ -207,10 +204,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof io.a2a.grpc.ListTaskPushNotificationConfigResponse)) { + if (!(obj instanceof io.a2a.grpc.ListTaskPushNotificationConfigsResponse)) { return super.equals(obj); } - io.a2a.grpc.ListTaskPushNotificationConfigResponse other = (io.a2a.grpc.ListTaskPushNotificationConfigResponse) obj; + io.a2a.grpc.ListTaskPushNotificationConfigsResponse other = (io.a2a.grpc.ListTaskPushNotificationConfigsResponse) obj; if (!getConfigsList() .equals(other.getConfigsList())) return false; @@ -238,44 +235,44 @@ public int hashCode() { return hash; } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom(byte[] data) + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom(java.io.InputStream input) + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -283,26 +280,26 @@ public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseDelimitedFrom(java.io.InputStream input) + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseDelimitedFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessage .parseWithIOException(PARSER, input); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -315,7 +312,7 @@ public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(io.a2a.grpc.ListTaskPushNotificationConfigResponse prototype) { + public static Builder newBuilder(io.a2a.grpc.ListTaskPushNotificationConfigsResponse prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -332,31 +329,30 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:ListTaskPushNotificationConfigResponse]
        -   * Represents a successful response for the `ListTaskPushNotificationConfig`
        +   * Represents a successful response for the `ListTaskPushNotificationConfigs`
            * method.
            * 
        * - * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigResponse} + * Protobuf type {@code lf.a2a.v1.ListTaskPushNotificationConfigsResponse} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ListTaskPushNotificationConfigResponse) - io.a2a.grpc.ListTaskPushNotificationConfigResponseOrBuilder { + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ListTaskPushNotificationConfigsResponse) + io.a2a.grpc.ListTaskPushNotificationConfigsResponseOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_fieldAccessorTable .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTaskPushNotificationConfigResponse.class, io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder.class); + io.a2a.grpc.ListTaskPushNotificationConfigsResponse.class, io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder.class); } - // Construct using io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder() + // Construct using io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder() private Builder() { } @@ -384,17 +380,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor; } @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigResponse getDefaultInstanceForType() { - return io.a2a.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance(); + public io.a2a.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstanceForType() { + return io.a2a.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance(); } @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigResponse build() { - io.a2a.grpc.ListTaskPushNotificationConfigResponse result = buildPartial(); + public io.a2a.grpc.ListTaskPushNotificationConfigsResponse build() { + io.a2a.grpc.ListTaskPushNotificationConfigsResponse result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -402,15 +398,15 @@ public io.a2a.grpc.ListTaskPushNotificationConfigResponse build() { } @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigResponse buildPartial() { - io.a2a.grpc.ListTaskPushNotificationConfigResponse result = new io.a2a.grpc.ListTaskPushNotificationConfigResponse(this); + public io.a2a.grpc.ListTaskPushNotificationConfigsResponse buildPartial() { + io.a2a.grpc.ListTaskPushNotificationConfigsResponse result = new io.a2a.grpc.ListTaskPushNotificationConfigsResponse(this); buildPartialRepeatedFields(result); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartialRepeatedFields(io.a2a.grpc.ListTaskPushNotificationConfigResponse result) { + private void buildPartialRepeatedFields(io.a2a.grpc.ListTaskPushNotificationConfigsResponse result) { if (configsBuilder_ == null) { if (((bitField0_ & 0x00000001) != 0)) { configs_ = java.util.Collections.unmodifiableList(configs_); @@ -422,7 +418,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.ListTaskPushNotificationConf } } - private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigResponse result) { + private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigsResponse result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000002) != 0)) { result.nextPageToken_ = nextPageToken_; @@ -431,16 +427,16 @@ private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigResponse re @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ListTaskPushNotificationConfigResponse) { - return mergeFrom((io.a2a.grpc.ListTaskPushNotificationConfigResponse)other); + if (other instanceof io.a2a.grpc.ListTaskPushNotificationConfigsResponse) { + return mergeFrom((io.a2a.grpc.ListTaskPushNotificationConfigsResponse)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigResponse other) { - if (other == io.a2a.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance()) return this; + public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigsResponse other) { + if (other == io.a2a.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance()) return this; if (configsBuilder_ == null) { if (!other.configs_.isEmpty()) { if (configs_.isEmpty()) { @@ -550,7 +546,7 @@ private void ensureConfigsIsMutable() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public java.util.List getConfigsList() { if (configsBuilder_ == null) { @@ -564,7 +560,7 @@ public java.util.List getConfigsList() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public int getConfigsCount() { if (configsBuilder_ == null) { @@ -578,7 +574,7 @@ public int getConfigsCount() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) { if (configsBuilder_ == null) { @@ -592,7 +588,7 @@ public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder setConfigs( int index, io.a2a.grpc.TaskPushNotificationConfig value) { @@ -613,7 +609,7 @@ public Builder setConfigs( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder setConfigs( int index, io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) { @@ -631,7 +627,7 @@ public Builder setConfigs( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder addConfigs(io.a2a.grpc.TaskPushNotificationConfig value) { if (configsBuilder_ == null) { @@ -651,7 +647,7 @@ public Builder addConfigs(io.a2a.grpc.TaskPushNotificationConfig value) { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder addConfigs( int index, io.a2a.grpc.TaskPushNotificationConfig value) { @@ -672,7 +668,7 @@ public Builder addConfigs( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder addConfigs( io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) { @@ -690,7 +686,7 @@ public Builder addConfigs( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder addConfigs( int index, io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) { @@ -708,7 +704,7 @@ public Builder addConfigs( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder addAllConfigs( java.lang.Iterable values) { @@ -727,7 +723,7 @@ public Builder addAllConfigs( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder clearConfigs() { if (configsBuilder_ == null) { @@ -744,7 +740,7 @@ public Builder clearConfigs() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public Builder removeConfigs(int index) { if (configsBuilder_ == null) { @@ -761,7 +757,7 @@ public Builder removeConfigs(int index) { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public io.a2a.grpc.TaskPushNotificationConfig.Builder getConfigsBuilder( int index) { @@ -772,7 +768,7 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder getConfigsBuilder( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( int index) { @@ -786,7 +782,7 @@ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public java.util.List getConfigsOrBuilderList() { @@ -801,7 +797,7 @@ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder() { return internalGetConfigsFieldBuilder().addBuilder( @@ -812,7 +808,7 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder() { * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder( int index) { @@ -824,7 +820,7 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder( * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ public java.util.List getConfigsBuilderList() { @@ -848,8 +844,7 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder( private java.lang.Object nextPageToken_ = ""; /** *
        -     * A token, which can be sent as `page_token` to retrieve the next page.
        -     * If this field is omitted, there are no subsequent pages.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2; @@ -869,8 +864,7 @@ public java.lang.String getNextPageToken() { } /** *
        -     * A token, which can be sent as `page_token` to retrieve the next page.
        -     * If this field is omitted, there are no subsequent pages.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2; @@ -891,8 +885,7 @@ public java.lang.String getNextPageToken() { } /** *
        -     * A token, which can be sent as `page_token` to retrieve the next page.
        -     * If this field is omitted, there are no subsequent pages.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2; @@ -909,8 +902,7 @@ public Builder setNextPageToken( } /** *
        -     * A token, which can be sent as `page_token` to retrieve the next page.
        -     * If this field is omitted, there are no subsequent pages.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2; @@ -924,8 +916,7 @@ public Builder clearNextPageToken() { } /** *
        -     * A token, which can be sent as `page_token` to retrieve the next page.
        -     * If this field is omitted, there are no subsequent pages.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2; @@ -942,23 +933,23 @@ public Builder setNextPageTokenBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.ListTaskPushNotificationConfigResponse) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.ListTaskPushNotificationConfigsResponse) } - // @@protoc_insertion_point(class_scope:a2a.v1.ListTaskPushNotificationConfigResponse) - private static final io.a2a.grpc.ListTaskPushNotificationConfigResponse DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:lf.a2a.v1.ListTaskPushNotificationConfigsResponse) + private static final io.a2a.grpc.ListTaskPushNotificationConfigsResponse DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new io.a2a.grpc.ListTaskPushNotificationConfigResponse(); + DEFAULT_INSTANCE = new io.a2a.grpc.ListTaskPushNotificationConfigsResponse(); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse getDefaultInstance() { + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { @java.lang.Override - public ListTaskPushNotificationConfigResponse parsePartialFrom( + public ListTaskPushNotificationConfigsResponse parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { @@ -977,17 +968,17 @@ public ListTaskPushNotificationConfigResponse parsePartialFrom( } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } @java.lang.Override - public com.google.protobuf.Parser getParserForType() { + public com.google.protobuf.Parser getParserForType() { return PARSER; } @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigResponse getDefaultInstanceForType() { + public io.a2a.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstanceForType() { return DEFAULT_INSTANCE; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java similarity index 63% rename from spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java rename to spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java index a68796c49..1aa552f31 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java @@ -6,8 +6,8 @@ package io.a2a.grpc; @com.google.protobuf.Generated -public interface ListTaskPushNotificationConfigResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ListTaskPushNotificationConfigResponse) +public interface ListTaskPushNotificationConfigsResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.ListTaskPushNotificationConfigsResponse) com.google.protobuf.MessageOrBuilder { /** @@ -15,7 +15,7 @@ public interface ListTaskPushNotificationConfigResponseOrBuilder extends * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ java.util.List getConfigsList(); @@ -24,7 +24,7 @@ public interface ListTaskPushNotificationConfigResponseOrBuilder extends * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index); /** @@ -32,7 +32,7 @@ public interface ListTaskPushNotificationConfigResponseOrBuilder extends * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ int getConfigsCount(); /** @@ -40,7 +40,7 @@ public interface ListTaskPushNotificationConfigResponseOrBuilder extends * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ java.util.List getConfigsOrBuilderList(); @@ -49,15 +49,14 @@ public interface ListTaskPushNotificationConfigResponseOrBuilder extends * The list of push notification configurations. * * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1; */ io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( int index); /** *
        -   * A token, which can be sent as `page_token` to retrieve the next page.
        -   * If this field is omitted, there are no subsequent pages.
        +   * A token to retrieve the next page of results, or empty if there are no more results in the list.
            * 
        * * string next_page_token = 2; @@ -66,8 +65,7 @@ io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( java.lang.String getNextPageToken(); /** *
        -   * A token, which can be sent as `page_token` to retrieve the next page.
        -   * If this field is omitted, there are no subsequent pages.
        +   * A token to retrieve the next page of results, or empty if there are no more results in the list.
            * 
        * * string next_page_token = 2; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java index c2645afcc..414660319 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:ListTasksRequest]
          * Parameters for listing tasks with optional filtering criteria.
          * 
        * - * Protobuf type {@code a2a.v1.ListTasksRequest} + * Protobuf type {@code lf.a2a.v1.ListTasksRequest} */ @com.google.protobuf.Generated public final class ListTasksRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ListTasksRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.ListTasksRequest) ListTasksRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -41,27 +40,27 @@ private ListTasksRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.ListTasksRequest.class, io.a2a.grpc.ListTasksRequest.Builder.class); } private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 9; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 9; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -79,10 +78,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 9; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -100,7 +99,7 @@ public java.lang.String getTenant() { } } - public static final int CONTEXT_ID_FIELD_NUMBER = 1; + public static final int CONTEXT_ID_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object contextId_ = ""; /** @@ -108,7 +107,7 @@ public java.lang.String getTenant() { * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @return The contextId. */ @java.lang.Override @@ -129,7 +128,7 @@ public java.lang.String getContextId() { * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @return The bytes for contextId. */ @java.lang.Override @@ -147,14 +146,14 @@ public java.lang.String getContextId() { } } - public static final int STATUS_FIELD_NUMBER = 2; + public static final int STATUS_FIELD_NUMBER = 3; private int status_ = 0; /** *
            * Filter tasks by their current status state.
            * 
        * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @return The enum numeric value on the wire for status. */ @java.lang.Override public int getStatusValue() { @@ -165,7 +164,7 @@ public java.lang.String getContextId() { * Filter tasks by their current status state. * * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @return The status. */ @java.lang.Override public io.a2a.grpc.TaskState getStatus() { @@ -173,15 +172,17 @@ public java.lang.String getContextId() { return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result; } - public static final int PAGE_SIZE_FIELD_NUMBER = 3; + public static final int PAGE_SIZE_FIELD_NUMBER = 4; private int pageSize_ = 0; /** *
        -   * Maximum number of tasks to return. Must be between 1 and 100.
        -   * Defaults to 50 if not specified.
        +   * The maximum number of tasks to return. The service may return fewer than this value.
        +   * If unspecified, at most 50 tasks will be returned.
        +   * The minimum value is 1.
        +   * The maximum value is 100.
            * 
        * - * optional int32 page_size = 3; + * optional int32 page_size = 4; * @return Whether the pageSize field is set. */ @java.lang.Override @@ -190,11 +191,13 @@ public boolean hasPageSize() { } /** *
        -   * Maximum number of tasks to return. Must be between 1 and 100.
        -   * Defaults to 50 if not specified.
        +   * The maximum number of tasks to return. The service may return fewer than this value.
        +   * If unspecified, at most 50 tasks will be returned.
        +   * The minimum value is 1.
        +   * The maximum value is 100.
            * 
        * - * optional int32 page_size = 3; + * optional int32 page_size = 4; * @return The pageSize. */ @java.lang.Override @@ -202,15 +205,17 @@ public int getPageSize() { return pageSize_; } - public static final int PAGE_TOKEN_FIELD_NUMBER = 4; + public static final int PAGE_TOKEN_FIELD_NUMBER = 5; @SuppressWarnings("serial") private volatile java.lang.Object pageToken_ = ""; /** *
        -   * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +   * A page token, received from a previous `ListTasks` call.
        +   * `ListTasksResponse.next_page_token`.
        +   * Provide this to retrieve the subsequent page.
            * 
        * - * string page_token = 4; + * string page_token = 5; * @return The pageToken. */ @java.lang.Override @@ -228,10 +233,12 @@ public java.lang.String getPageToken() { } /** *
        -   * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +   * A page token, received from a previous `ListTasks` call.
        +   * `ListTasksResponse.next_page_token`.
        +   * Provide this to retrieve the subsequent page.
            * 
        * - * string page_token = 4; + * string page_token = 5; * @return The bytes for pageToken. */ @java.lang.Override @@ -249,14 +256,14 @@ public java.lang.String getPageToken() { } } - public static final int HISTORY_LENGTH_FIELD_NUMBER = 5; + public static final int HISTORY_LENGTH_FIELD_NUMBER = 6; private int historyLength_ = 0; /** *
            * The maximum number of messages to include in each task's history.
            * 
        * - * optional int32 history_length = 5; + * optional int32 history_length = 6; * @return Whether the historyLength field is set. */ @java.lang.Override @@ -268,7 +275,7 @@ public boolean hasHistoryLength() { * The maximum number of messages to include in each task's history. * * - * optional int32 history_length = 5; + * optional int32 history_length = 6; * @return The historyLength. */ @java.lang.Override @@ -276,7 +283,7 @@ public int getHistoryLength() { return historyLength_; } - public static final int STATUS_TIMESTAMP_AFTER_FIELD_NUMBER = 6; + public static final int STATUS_TIMESTAMP_AFTER_FIELD_NUMBER = 7; private com.google.protobuf.Timestamp statusTimestampAfter_; /** *
        @@ -284,7 +291,7 @@ public int getHistoryLength() {
            * Only tasks with a status timestamp time greater than or equal to this value will be returned.
            * 
        * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; * @return Whether the statusTimestampAfter field is set. */ @java.lang.Override @@ -297,7 +304,7 @@ public boolean hasStatusTimestampAfter() { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; * @return The statusTimestampAfter. */ @java.lang.Override @@ -310,14 +317,14 @@ public com.google.protobuf.Timestamp getStatusTimestampAfter() { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ @java.lang.Override public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder() { return statusTimestampAfter_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; } - public static final int INCLUDE_ARTIFACTS_FIELD_NUMBER = 7; + public static final int INCLUDE_ARTIFACTS_FIELD_NUMBER = 8; private boolean includeArtifacts_ = false; /** *
        @@ -325,7 +332,7 @@ public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder()
            * Defaults to false to reduce payload size.
            * 
        * - * optional bool include_artifacts = 7; + * optional bool include_artifacts = 8; * @return Whether the includeArtifacts field is set. */ @java.lang.Override @@ -338,7 +345,7 @@ public boolean hasIncludeArtifacts() { * Defaults to false to reduce payload size. * * - * optional bool include_artifacts = 7; + * optional bool include_artifacts = 8; * @return The includeArtifacts. */ @java.lang.Override @@ -360,29 +367,29 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, contextId_); + com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); } if (status_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) { - output.writeEnum(2, status_); + output.writeEnum(3, status_); } if (((bitField0_ & 0x00000001) != 0)) { - output.writeInt32(3, pageSize_); + output.writeInt32(4, pageSize_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(pageToken_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, pageToken_); + com.google.protobuf.GeneratedMessage.writeString(output, 5, pageToken_); } if (((bitField0_ & 0x00000002) != 0)) { - output.writeInt32(5, historyLength_); + output.writeInt32(6, historyLength_); } if (((bitField0_ & 0x00000004) != 0)) { - output.writeMessage(6, getStatusTimestampAfter()); + output.writeMessage(7, getStatusTimestampAfter()); } if (((bitField0_ & 0x00000008) != 0)) { - output.writeBool(7, includeArtifacts_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 9, tenant_); + output.writeBool(8, includeArtifacts_); } getUnknownFields().writeTo(output); } @@ -393,34 +400,34 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, contextId_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); } if (status_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) { size += com.google.protobuf.CodedOutputStream - .computeEnumSize(2, status_); + .computeEnumSize(3, status_); } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, pageSize_); + .computeInt32Size(4, pageSize_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(pageToken_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, pageToken_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(5, pageToken_); } if (((bitField0_ & 0x00000002) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeInt32Size(5, historyLength_); + .computeInt32Size(6, historyLength_); } if (((bitField0_ & 0x00000004) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, getStatusTimestampAfter()); + .computeMessageSize(7, getStatusTimestampAfter()); } if (((bitField0_ & 0x00000008) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeBoolSize(7, includeArtifacts_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(9, tenant_); + .computeBoolSize(8, includeArtifacts_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -599,25 +606,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:ListTasksRequest]
            * Parameters for listing tasks with optional filtering criteria.
            * 
        * - * Protobuf type {@code a2a.v1.ListTasksRequest} + * Protobuf type {@code lf.a2a.v1.ListTasksRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ListTasksRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ListTasksRequest) io.a2a.grpc.ListTasksRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.ListTasksRequest.class, io.a2a.grpc.ListTasksRequest.Builder.class); } @@ -660,7 +666,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor; } @java.lang.Override @@ -790,47 +796,47 @@ public Builder mergeFrom( done = true; break; case 10: { + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { contextId_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; - } // case 10 - case 16: { + } // case 18 + case 24: { status_ = input.readEnum(); bitField0_ |= 0x00000004; break; - } // case 16 - case 24: { + } // case 24 + case 32: { pageSize_ = input.readInt32(); bitField0_ |= 0x00000008; break; - } // case 24 - case 34: { + } // case 32 + case 42: { pageToken_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000010; break; - } // case 34 - case 40: { + } // case 42 + case 48: { historyLength_ = input.readInt32(); bitField0_ |= 0x00000020; break; - } // case 40 - case 50: { + } // case 48 + case 58: { input.readMessage( internalGetStatusTimestampAfterFieldBuilder().getBuilder(), extensionRegistry); bitField0_ |= 0x00000040; break; - } // case 50 - case 56: { + } // case 58 + case 64: { includeArtifacts_ = input.readBool(); bitField0_ |= 0x00000080; break; - } // case 56 - case 74: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 74 + } // case 64 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -851,10 +857,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 9; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -871,10 +877,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 9; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -892,10 +898,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 9; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -909,10 +915,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 9; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -923,10 +929,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 9; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -946,7 +952,7 @@ public Builder setTenantBytes( * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @return The contextId. */ public java.lang.String getContextId() { @@ -966,7 +972,7 @@ public java.lang.String getContextId() { * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @return The bytes for contextId. */ public com.google.protobuf.ByteString @@ -987,7 +993,7 @@ public java.lang.String getContextId() { * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @param value The contextId to set. * @return This builder for chaining. */ @@ -1004,7 +1010,7 @@ public Builder setContextId( * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @return This builder for chaining. */ public Builder clearContextId() { @@ -1018,7 +1024,7 @@ public Builder clearContextId() { * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @param value The bytes for contextId to set. * @return This builder for chaining. */ @@ -1038,7 +1044,7 @@ public Builder setContextIdBytes( * Filter tasks by their current status state. * * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @return The enum numeric value on the wire for status. */ @java.lang.Override public int getStatusValue() { @@ -1049,7 +1055,7 @@ public Builder setContextIdBytes( * Filter tasks by their current status state. * * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @param value The enum numeric value on the wire for status to set. * @return This builder for chaining. */ @@ -1064,7 +1070,7 @@ public Builder setStatusValue(int value) { * Filter tasks by their current status state. * * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @return The status. */ @java.lang.Override @@ -1077,7 +1083,7 @@ public io.a2a.grpc.TaskState getStatus() { * Filter tasks by their current status state. * * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @param value The status to set. * @return This builder for chaining. */ @@ -1093,7 +1099,7 @@ public Builder setStatus(io.a2a.grpc.TaskState value) { * Filter tasks by their current status state. * * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @return This builder for chaining. */ public Builder clearStatus() { @@ -1106,11 +1112,13 @@ public Builder clearStatus() { private int pageSize_ ; /** *
        -     * Maximum number of tasks to return. Must be between 1 and 100.
        -     * Defaults to 50 if not specified.
        +     * The maximum number of tasks to return. The service may return fewer than this value.
        +     * If unspecified, at most 50 tasks will be returned.
        +     * The minimum value is 1.
        +     * The maximum value is 100.
              * 
        * - * optional int32 page_size = 3; + * optional int32 page_size = 4; * @return Whether the pageSize field is set. */ @java.lang.Override @@ -1119,11 +1127,13 @@ public boolean hasPageSize() { } /** *
        -     * Maximum number of tasks to return. Must be between 1 and 100.
        -     * Defaults to 50 if not specified.
        +     * The maximum number of tasks to return. The service may return fewer than this value.
        +     * If unspecified, at most 50 tasks will be returned.
        +     * The minimum value is 1.
        +     * The maximum value is 100.
              * 
        * - * optional int32 page_size = 3; + * optional int32 page_size = 4; * @return The pageSize. */ @java.lang.Override @@ -1132,11 +1142,13 @@ public int getPageSize() { } /** *
        -     * Maximum number of tasks to return. Must be between 1 and 100.
        -     * Defaults to 50 if not specified.
        +     * The maximum number of tasks to return. The service may return fewer than this value.
        +     * If unspecified, at most 50 tasks will be returned.
        +     * The minimum value is 1.
        +     * The maximum value is 100.
              * 
        * - * optional int32 page_size = 3; + * optional int32 page_size = 4; * @param value The pageSize to set. * @return This builder for chaining. */ @@ -1149,11 +1161,13 @@ public Builder setPageSize(int value) { } /** *
        -     * Maximum number of tasks to return. Must be between 1 and 100.
        -     * Defaults to 50 if not specified.
        +     * The maximum number of tasks to return. The service may return fewer than this value.
        +     * If unspecified, at most 50 tasks will be returned.
        +     * The minimum value is 1.
        +     * The maximum value is 100.
              * 
        * - * optional int32 page_size = 3; + * optional int32 page_size = 4; * @return This builder for chaining. */ public Builder clearPageSize() { @@ -1166,10 +1180,12 @@ public Builder clearPageSize() { private java.lang.Object pageToken_ = ""; /** *
        -     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +     * A page token, received from a previous `ListTasks` call.
        +     * `ListTasksResponse.next_page_token`.
        +     * Provide this to retrieve the subsequent page.
              * 
        * - * string page_token = 4; + * string page_token = 5; * @return The pageToken. */ public java.lang.String getPageToken() { @@ -1186,10 +1202,12 @@ public java.lang.String getPageToken() { } /** *
        -     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +     * A page token, received from a previous `ListTasks` call.
        +     * `ListTasksResponse.next_page_token`.
        +     * Provide this to retrieve the subsequent page.
              * 
        * - * string page_token = 4; + * string page_token = 5; * @return The bytes for pageToken. */ public com.google.protobuf.ByteString @@ -1207,10 +1225,12 @@ public java.lang.String getPageToken() { } /** *
        -     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +     * A page token, received from a previous `ListTasks` call.
        +     * `ListTasksResponse.next_page_token`.
        +     * Provide this to retrieve the subsequent page.
              * 
        * - * string page_token = 4; + * string page_token = 5; * @param value The pageToken to set. * @return This builder for chaining. */ @@ -1224,10 +1244,12 @@ public Builder setPageToken( } /** *
        -     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +     * A page token, received from a previous `ListTasks` call.
        +     * `ListTasksResponse.next_page_token`.
        +     * Provide this to retrieve the subsequent page.
              * 
        * - * string page_token = 4; + * string page_token = 5; * @return This builder for chaining. */ public Builder clearPageToken() { @@ -1238,10 +1260,12 @@ public Builder clearPageToken() { } /** *
        -     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +     * A page token, received from a previous `ListTasks` call.
        +     * `ListTasksResponse.next_page_token`.
        +     * Provide this to retrieve the subsequent page.
              * 
        * - * string page_token = 4; + * string page_token = 5; * @param value The bytes for pageToken to set. * @return This builder for chaining. */ @@ -1261,7 +1285,7 @@ public Builder setPageTokenBytes( * The maximum number of messages to include in each task's history. * * - * optional int32 history_length = 5; + * optional int32 history_length = 6; * @return Whether the historyLength field is set. */ @java.lang.Override @@ -1273,7 +1297,7 @@ public boolean hasHistoryLength() { * The maximum number of messages to include in each task's history. * * - * optional int32 history_length = 5; + * optional int32 history_length = 6; * @return The historyLength. */ @java.lang.Override @@ -1285,7 +1309,7 @@ public int getHistoryLength() { * The maximum number of messages to include in each task's history. * * - * optional int32 history_length = 5; + * optional int32 history_length = 6; * @param value The historyLength to set. * @return This builder for chaining. */ @@ -1301,7 +1325,7 @@ public Builder setHistoryLength(int value) { * The maximum number of messages to include in each task's history. * * - * optional int32 history_length = 5; + * optional int32 history_length = 6; * @return This builder for chaining. */ public Builder clearHistoryLength() { @@ -1320,7 +1344,7 @@ public Builder clearHistoryLength() { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; * @return Whether the statusTimestampAfter field is set. */ public boolean hasStatusTimestampAfter() { @@ -1332,7 +1356,7 @@ public boolean hasStatusTimestampAfter() { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; * @return The statusTimestampAfter. */ public com.google.protobuf.Timestamp getStatusTimestampAfter() { @@ -1348,7 +1372,7 @@ public com.google.protobuf.Timestamp getStatusTimestampAfter() { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ public Builder setStatusTimestampAfter(com.google.protobuf.Timestamp value) { if (statusTimestampAfterBuilder_ == null) { @@ -1369,7 +1393,7 @@ public Builder setStatusTimestampAfter(com.google.protobuf.Timestamp value) { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ public Builder setStatusTimestampAfter( com.google.protobuf.Timestamp.Builder builderForValue) { @@ -1388,7 +1412,7 @@ public Builder setStatusTimestampAfter( * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ public Builder mergeStatusTimestampAfter(com.google.protobuf.Timestamp value) { if (statusTimestampAfterBuilder_ == null) { @@ -1414,7 +1438,7 @@ public Builder mergeStatusTimestampAfter(com.google.protobuf.Timestamp value) { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ public Builder clearStatusTimestampAfter() { bitField0_ = (bitField0_ & ~0x00000040); @@ -1432,7 +1456,7 @@ public Builder clearStatusTimestampAfter() { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ public com.google.protobuf.Timestamp.Builder getStatusTimestampAfterBuilder() { bitField0_ |= 0x00000040; @@ -1445,7 +1469,7 @@ public com.google.protobuf.Timestamp.Builder getStatusTimestampAfterBuilder() { * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder() { if (statusTimestampAfterBuilder_ != null) { @@ -1461,7 +1485,7 @@ public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder() * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ private com.google.protobuf.SingleFieldBuilder< com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> @@ -1484,7 +1508,7 @@ public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder() * Defaults to false to reduce payload size. * * - * optional bool include_artifacts = 7; + * optional bool include_artifacts = 8; * @return Whether the includeArtifacts field is set. */ @java.lang.Override @@ -1497,7 +1521,7 @@ public boolean hasIncludeArtifacts() { * Defaults to false to reduce payload size. * * - * optional bool include_artifacts = 7; + * optional bool include_artifacts = 8; * @return The includeArtifacts. */ @java.lang.Override @@ -1510,7 +1534,7 @@ public boolean getIncludeArtifacts() { * Defaults to false to reduce payload size. * * - * optional bool include_artifacts = 7; + * optional bool include_artifacts = 8; * @param value The includeArtifacts to set. * @return This builder for chaining. */ @@ -1527,7 +1551,7 @@ public Builder setIncludeArtifacts(boolean value) { * Defaults to false to reduce payload size. * * - * optional bool include_artifacts = 7; + * optional bool include_artifacts = 8; * @return This builder for chaining. */ public Builder clearIncludeArtifacts() { @@ -1537,10 +1561,10 @@ public Builder clearIncludeArtifacts() { return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.ListTasksRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.ListTasksRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.ListTasksRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.ListTasksRequest) private static final io.a2a.grpc.ListTasksRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.ListTasksRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java index 410485d50..d577c8507 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface ListTasksRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ListTasksRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.ListTasksRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 9; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 9; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -35,7 +35,7 @@ public interface ListTasksRequestOrBuilder extends * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @return The contextId. */ java.lang.String getContextId(); @@ -44,7 +44,7 @@ public interface ListTasksRequestOrBuilder extends * Filter tasks by context ID to get tasks from a specific conversation or session. * * - * string context_id = 1; + * string context_id = 2; * @return The bytes for contextId. */ com.google.protobuf.ByteString @@ -55,7 +55,7 @@ public interface ListTasksRequestOrBuilder extends * Filter tasks by their current status state. * * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @return The enum numeric value on the wire for status. */ int getStatusValue(); @@ -64,47 +64,55 @@ public interface ListTasksRequestOrBuilder extends * Filter tasks by their current status state. * * - * .a2a.v1.TaskState status = 2; + * .lf.a2a.v1.TaskState status = 3; * @return The status. */ io.a2a.grpc.TaskState getStatus(); /** *
        -   * Maximum number of tasks to return. Must be between 1 and 100.
        -   * Defaults to 50 if not specified.
        +   * The maximum number of tasks to return. The service may return fewer than this value.
        +   * If unspecified, at most 50 tasks will be returned.
        +   * The minimum value is 1.
        +   * The maximum value is 100.
            * 
        * - * optional int32 page_size = 3; + * optional int32 page_size = 4; * @return Whether the pageSize field is set. */ boolean hasPageSize(); /** *
        -   * Maximum number of tasks to return. Must be between 1 and 100.
        -   * Defaults to 50 if not specified.
        +   * The maximum number of tasks to return. The service may return fewer than this value.
        +   * If unspecified, at most 50 tasks will be returned.
        +   * The minimum value is 1.
        +   * The maximum value is 100.
            * 
        * - * optional int32 page_size = 3; + * optional int32 page_size = 4; * @return The pageSize. */ int getPageSize(); /** *
        -   * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +   * A page token, received from a previous `ListTasks` call.
        +   * `ListTasksResponse.next_page_token`.
        +   * Provide this to retrieve the subsequent page.
            * 
        * - * string page_token = 4; + * string page_token = 5; * @return The pageToken. */ java.lang.String getPageToken(); /** *
        -   * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
        +   * A page token, received from a previous `ListTasks` call.
        +   * `ListTasksResponse.next_page_token`.
        +   * Provide this to retrieve the subsequent page.
            * 
        * - * string page_token = 4; + * string page_token = 5; * @return The bytes for pageToken. */ com.google.protobuf.ByteString @@ -115,7 +123,7 @@ public interface ListTasksRequestOrBuilder extends * The maximum number of messages to include in each task's history. * * - * optional int32 history_length = 5; + * optional int32 history_length = 6; * @return Whether the historyLength field is set. */ boolean hasHistoryLength(); @@ -124,7 +132,7 @@ public interface ListTasksRequestOrBuilder extends * The maximum number of messages to include in each task's history. * * - * optional int32 history_length = 5; + * optional int32 history_length = 6; * @return The historyLength. */ int getHistoryLength(); @@ -135,7 +143,7 @@ public interface ListTasksRequestOrBuilder extends * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; * @return Whether the statusTimestampAfter field is set. */ boolean hasStatusTimestampAfter(); @@ -145,7 +153,7 @@ public interface ListTasksRequestOrBuilder extends * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; * @return The statusTimestampAfter. */ com.google.protobuf.Timestamp getStatusTimestampAfter(); @@ -155,7 +163,7 @@ public interface ListTasksRequestOrBuilder extends * Only tasks with a status timestamp time greater than or equal to this value will be returned. * * - * .google.protobuf.Timestamp status_timestamp_after = 6; + * .google.protobuf.Timestamp status_timestamp_after = 7; */ com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder(); @@ -165,7 +173,7 @@ public interface ListTasksRequestOrBuilder extends * Defaults to false to reduce payload size. * * - * optional bool include_artifacts = 7; + * optional bool include_artifacts = 8; * @return Whether the includeArtifacts field is set. */ boolean hasIncludeArtifacts(); @@ -175,7 +183,7 @@ public interface ListTasksRequestOrBuilder extends * Defaults to false to reduce payload size. * * - * optional bool include_artifacts = 7; + * optional bool include_artifacts = 8; * @return The includeArtifacts. */ boolean getIncludeArtifacts(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java index 1c0078076..4eaf740db 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:ListTasksResponse]
        - * Result object for tasks/list method containing an array of tasks and pagination information.
        + * Result object for `ListTasks` method containing an array of tasks and pagination information.
          * 
        * - * Protobuf type {@code a2a.v1.ListTasksResponse} + * Protobuf type {@code lf.a2a.v1.ListTasksResponse} */ @com.google.protobuf.Generated public final class ListTasksResponse extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ListTasksResponse) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.ListTasksResponse) ListTasksResponseOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,13 +38,13 @@ private ListTasksResponse() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.ListTasksResponse.class, io.a2a.grpc.ListTasksResponse.Builder.class); } @@ -58,7 +57,7 @@ private ListTasksResponse() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List getTasksList() { @@ -69,7 +68,7 @@ public java.util.List getTasksList() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List @@ -81,7 +80,7 @@ public java.util.List getTasksList() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public int getTasksCount() { @@ -92,7 +91,7 @@ public int getTasksCount() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.Task getTasks(int index) { @@ -103,7 +102,7 @@ public io.a2a.grpc.Task getTasks(int index) { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( @@ -116,7 +115,7 @@ public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( private volatile java.lang.Object nextPageToken_ = ""; /** *
        -   * Token for retrieving the next page. Empty string if no more results.
        +   * A token to retrieve the next page of results, or empty if there are no more results in the list.
            * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -137,7 +136,7 @@ public java.lang.String getNextPageToken() { } /** *
        -   * Token for retrieving the next page. Empty string if no more results.
        +   * A token to retrieve the next page of results, or empty if there are no more results in the list.
            * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -162,7 +161,7 @@ public java.lang.String getNextPageToken() { private int pageSize_ = 0; /** *
        -   * The size of page requested.
        +   * The page size used for this response.
            * 
        * * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; @@ -381,25 +380,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:ListTasksResponse]
        -   * Result object for tasks/list method containing an array of tasks and pagination information.
        +   * Result object for `ListTasks` method containing an array of tasks and pagination information.
            * 
        * - * Protobuf type {@code a2a.v1.ListTasksResponse} + * Protobuf type {@code lf.a2a.v1.ListTasksResponse} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ListTasksResponse) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ListTasksResponse) io.a2a.grpc.ListTasksResponseOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.ListTasksResponse.class, io.a2a.grpc.ListTasksResponse.Builder.class); } @@ -434,7 +432,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor; } @java.lang.Override @@ -622,7 +620,7 @@ private void ensureTasksIsMutable() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getTasksList() { if (tasksBuilder_ == null) { @@ -636,7 +634,7 @@ public java.util.List getTasksList() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public int getTasksCount() { if (tasksBuilder_ == null) { @@ -650,7 +648,7 @@ public int getTasksCount() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Task getTasks(int index) { if (tasksBuilder_ == null) { @@ -664,7 +662,7 @@ public io.a2a.grpc.Task getTasks(int index) { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setTasks( int index, io.a2a.grpc.Task value) { @@ -685,7 +683,7 @@ public Builder setTasks( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setTasks( int index, io.a2a.grpc.Task.Builder builderForValue) { @@ -703,7 +701,7 @@ public Builder setTasks( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addTasks(io.a2a.grpc.Task value) { if (tasksBuilder_ == null) { @@ -723,7 +721,7 @@ public Builder addTasks(io.a2a.grpc.Task value) { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addTasks( int index, io.a2a.grpc.Task value) { @@ -744,7 +742,7 @@ public Builder addTasks( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addTasks( io.a2a.grpc.Task.Builder builderForValue) { @@ -762,7 +760,7 @@ public Builder addTasks( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addTasks( int index, io.a2a.grpc.Task.Builder builderForValue) { @@ -780,7 +778,7 @@ public Builder addTasks( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addAllTasks( java.lang.Iterable values) { @@ -799,7 +797,7 @@ public Builder addAllTasks( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearTasks() { if (tasksBuilder_ == null) { @@ -816,7 +814,7 @@ public Builder clearTasks() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public Builder removeTasks(int index) { if (tasksBuilder_ == null) { @@ -833,7 +831,7 @@ public Builder removeTasks(int index) { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Task.Builder getTasksBuilder( int index) { @@ -844,7 +842,7 @@ public io.a2a.grpc.Task.Builder getTasksBuilder( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( int index) { @@ -858,7 +856,7 @@ public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getTasksOrBuilderList() { @@ -873,7 +871,7 @@ public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Task.Builder addTasksBuilder() { return internalGetTasksFieldBuilder().addBuilder( @@ -884,7 +882,7 @@ public io.a2a.grpc.Task.Builder addTasksBuilder() { * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Task.Builder addTasksBuilder( int index) { @@ -896,7 +894,7 @@ public io.a2a.grpc.Task.Builder addTasksBuilder( * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getTasksBuilderList() { @@ -920,7 +918,7 @@ public io.a2a.grpc.Task.Builder addTasksBuilder( private java.lang.Object nextPageToken_ = ""; /** *
        -     * Token for retrieving the next page. Empty string if no more results.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -940,7 +938,7 @@ public java.lang.String getNextPageToken() { } /** *
        -     * Token for retrieving the next page. Empty string if no more results.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -961,7 +959,7 @@ public java.lang.String getNextPageToken() { } /** *
        -     * Token for retrieving the next page. Empty string if no more results.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -978,7 +976,7 @@ public Builder setNextPageToken( } /** *
        -     * Token for retrieving the next page. Empty string if no more results.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -992,7 +990,7 @@ public Builder clearNextPageToken() { } /** *
        -     * Token for retrieving the next page. Empty string if no more results.
        +     * A token to retrieve the next page of results, or empty if there are no more results in the list.
              * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -1012,7 +1010,7 @@ public Builder setNextPageTokenBytes( private int pageSize_ ; /** *
        -     * The size of page requested.
        +     * The page size used for this response.
              * 
        * * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; @@ -1024,7 +1022,7 @@ public int getPageSize() { } /** *
        -     * The size of page requested.
        +     * The page size used for this response.
              * 
        * * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; @@ -1040,7 +1038,7 @@ public Builder setPageSize(int value) { } /** *
        -     * The size of page requested.
        +     * The page size used for this response.
              * 
        * * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; @@ -1097,10 +1095,10 @@ public Builder clearTotalSize() { return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.ListTasksResponse) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.ListTasksResponse) } - // @@protoc_insertion_point(class_scope:a2a.v1.ListTasksResponse) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.ListTasksResponse) private static final io.a2a.grpc.ListTasksResponse DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.ListTasksResponse(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java index 430700f61..cbaddefbf 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface ListTasksResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ListTasksResponse) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.ListTasksResponse) com.google.protobuf.MessageOrBuilder { /** @@ -15,7 +15,7 @@ public interface ListTasksResponseOrBuilder extends * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getTasksList(); @@ -24,7 +24,7 @@ public interface ListTasksResponseOrBuilder extends * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.Task getTasks(int index); /** @@ -32,7 +32,7 @@ public interface ListTasksResponseOrBuilder extends * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ int getTasksCount(); /** @@ -40,7 +40,7 @@ public interface ListTasksResponseOrBuilder extends * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getTasksOrBuilderList(); @@ -49,14 +49,14 @@ public interface ListTasksResponseOrBuilder extends * Array of tasks matching the specified criteria. * * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( int index); /** *
        -   * Token for retrieving the next page. Empty string if no more results.
        +   * A token to retrieve the next page of results, or empty if there are no more results in the list.
            * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -65,7 +65,7 @@ io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( java.lang.String getNextPageToken(); /** *
        -   * Token for retrieving the next page. Empty string if no more results.
        +   * A token to retrieve the next page of results, or empty if there are no more results in the list.
            * 
        * * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -76,7 +76,7 @@ io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( /** *
        -   * The size of page requested.
        +   * The page size used for this response.
            * 
        * * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Message.java b/spec-grpc/src/main/java/io/a2a/grpc/Message.java index e8f296411..ac9dbdc6f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/Message.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/Message.java @@ -7,21 +7,20 @@ /** *
        - * --8<-- [start:Message]
        - * Message is one unit of communication between client and server. It can be
        - * associated with a context and/or a task. For server messages, context_id must
        - * be provided, and task_id only if a task was created. For client messages, both
        + * `Message` is one unit of communication between client and server. It can be
        + * associated with a context and/or a task. For server messages, `context_id` must
        + * be provided, and `task_id` only if a task was created. For client messages, both
          * fields are optional, with the caveat that if both are provided, they have to
        - * match (the context_id has to be the one that is set on the task). If only
        - * task_id is provided, the server will infer context_id from it.
        + * match (the `context_id` has to be the one that is set on the task). If only
        + * `task_id` is provided, the server will infer `context_id` from it.
          * 
        * - * Protobuf type {@code a2a.v1.Message} + * Protobuf type {@code lf.a2a.v1.Message} */ @com.google.protobuf.Generated public final class Message extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Message) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.Message) MessageOrBuilder { private static final long serialVersionUID = 0L; static { @@ -51,13 +50,13 @@ private Message() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.Message.class, io.a2a.grpc.Message.Builder.class); } @@ -68,8 +67,7 @@ private Message() { private volatile java.lang.Object messageId_ = ""; /** *
        -   * The unique identifier (e.g. UUID) of the message. This is required and
        -   * created by the message creator.
        +   * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
            * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -90,8 +88,7 @@ public java.lang.String getMessageId() { } /** *
        -   * The unique identifier (e.g. UUID) of the message. This is required and
        -   * created by the message creator.
        +   * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
            * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -117,8 +114,7 @@ public java.lang.String getMessageId() { private volatile java.lang.Object contextId_ = ""; /** *
        -   * The context id of the message. This is optional and if set, the message
        -   * will be associated with the given context.
        +   * Optional. The context id of the message. If set, the message will be associated with the given context.
            * 
        * * string context_id = 2; @@ -139,8 +135,7 @@ public java.lang.String getContextId() { } /** *
        -   * The context id of the message. This is optional and if set, the message
        -   * will be associated with the given context.
        +   * Optional. The context id of the message. If set, the message will be associated with the given context.
            * 
        * * string context_id = 2; @@ -166,8 +161,7 @@ public java.lang.String getContextId() { private volatile java.lang.Object taskId_ = ""; /** *
        -   * The task id of the message. This is optional and if set, the message
        -   * will be associated with the given task.
        +   * Optional. The task id of the message. If set, the message will be associated with the given task.
            * 
        * * string task_id = 3; @@ -188,8 +182,7 @@ public java.lang.String getTaskId() { } /** *
        -   * The task id of the message. This is optional and if set, the message
        -   * will be associated with the given task.
        +   * Optional. The task id of the message. If set, the message will be associated with the given task.
            * 
        * * string task_id = 3; @@ -217,7 +210,7 @@ public java.lang.String getTaskId() { * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @return The enum numeric value on the wire for role. */ @java.lang.Override public int getRoleValue() { @@ -228,7 +221,7 @@ public java.lang.String getTaskId() { * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @return The role. */ @java.lang.Override public io.a2a.grpc.Role getRole() { @@ -241,11 +234,10 @@ public java.lang.String getTaskId() { private java.util.List parts_; /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List getPartsList() { @@ -253,11 +245,10 @@ public java.util.List getPartsList() { } /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public java.util.List @@ -266,11 +257,10 @@ public java.util.List getPartsList() { } /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public int getPartsCount() { @@ -278,11 +268,10 @@ public int getPartsCount() { } /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.Part getParts(int index) { @@ -290,11 +279,10 @@ public io.a2a.grpc.Part getParts(int index) { } /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( @@ -306,8 +294,7 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( private com.google.protobuf.Struct metadata_; /** *
        -   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -   * Any optional metadata to provide along with the message.
        +   * Optional. Any metadata to provide along with the message.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -319,8 +306,7 @@ public boolean hasMetadata() { } /** *
        -   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -   * Any optional metadata to provide along with the message.
        +   * Optional. Any metadata to provide along with the message.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -332,8 +318,7 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -   * Any optional metadata to provide along with the message.
        +   * Optional. Any metadata to provide along with the message.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -700,30 +685,29 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:Message]
        -   * Message is one unit of communication between client and server. It can be
        -   * associated with a context and/or a task. For server messages, context_id must
        -   * be provided, and task_id only if a task was created. For client messages, both
        +   * `Message` is one unit of communication between client and server. It can be
        +   * associated with a context and/or a task. For server messages, `context_id` must
        +   * be provided, and `task_id` only if a task was created. For client messages, both
            * fields are optional, with the caveat that if both are provided, they have to
        -   * match (the context_id has to be the one that is set on the task). If only
        -   * task_id is provided, the server will infer context_id from it.
        +   * match (the `context_id` has to be the one that is set on the task). If only
        +   * `task_id` is provided, the server will infer `context_id` from it.
            * 
        * - * Protobuf type {@code a2a.v1.Message} + * Protobuf type {@code lf.a2a.v1.Message} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Message) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.Message) io.a2a.grpc.MessageOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.Message.class, io.a2a.grpc.Message.Builder.class); } @@ -775,7 +759,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor; } @java.lang.Override @@ -1022,8 +1006,7 @@ public Builder mergeFrom( private java.lang.Object messageId_ = ""; /** *
        -     * The unique identifier (e.g. UUID) of the message. This is required and
        -     * created by the message creator.
        +     * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
              * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -1043,8 +1026,7 @@ public java.lang.String getMessageId() { } /** *
        -     * The unique identifier (e.g. UUID) of the message. This is required and
        -     * created by the message creator.
        +     * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
              * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -1065,8 +1047,7 @@ public java.lang.String getMessageId() { } /** *
        -     * The unique identifier (e.g. UUID) of the message. This is required and
        -     * created by the message creator.
        +     * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
              * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -1083,8 +1064,7 @@ public Builder setMessageId( } /** *
        -     * The unique identifier (e.g. UUID) of the message. This is required and
        -     * created by the message creator.
        +     * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
              * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -1098,8 +1078,7 @@ public Builder clearMessageId() { } /** *
        -     * The unique identifier (e.g. UUID) of the message. This is required and
        -     * created by the message creator.
        +     * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
              * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -1119,8 +1098,7 @@ public Builder setMessageIdBytes( private java.lang.Object contextId_ = ""; /** *
        -     * The context id of the message. This is optional and if set, the message
        -     * will be associated with the given context.
        +     * Optional. The context id of the message. If set, the message will be associated with the given context.
              * 
        * * string context_id = 2; @@ -1140,8 +1118,7 @@ public java.lang.String getContextId() { } /** *
        -     * The context id of the message. This is optional and if set, the message
        -     * will be associated with the given context.
        +     * Optional. The context id of the message. If set, the message will be associated with the given context.
              * 
        * * string context_id = 2; @@ -1162,8 +1139,7 @@ public java.lang.String getContextId() { } /** *
        -     * The context id of the message. This is optional and if set, the message
        -     * will be associated with the given context.
        +     * Optional. The context id of the message. If set, the message will be associated with the given context.
              * 
        * * string context_id = 2; @@ -1180,8 +1156,7 @@ public Builder setContextId( } /** *
        -     * The context id of the message. This is optional and if set, the message
        -     * will be associated with the given context.
        +     * Optional. The context id of the message. If set, the message will be associated with the given context.
              * 
        * * string context_id = 2; @@ -1195,8 +1170,7 @@ public Builder clearContextId() { } /** *
        -     * The context id of the message. This is optional and if set, the message
        -     * will be associated with the given context.
        +     * Optional. The context id of the message. If set, the message will be associated with the given context.
              * 
        * * string context_id = 2; @@ -1216,8 +1190,7 @@ public Builder setContextIdBytes( private java.lang.Object taskId_ = ""; /** *
        -     * The task id of the message. This is optional and if set, the message
        -     * will be associated with the given task.
        +     * Optional. The task id of the message. If set, the message will be associated with the given task.
              * 
        * * string task_id = 3; @@ -1237,8 +1210,7 @@ public java.lang.String getTaskId() { } /** *
        -     * The task id of the message. This is optional and if set, the message
        -     * will be associated with the given task.
        +     * Optional. The task id of the message. If set, the message will be associated with the given task.
              * 
        * * string task_id = 3; @@ -1259,8 +1231,7 @@ public java.lang.String getTaskId() { } /** *
        -     * The task id of the message. This is optional and if set, the message
        -     * will be associated with the given task.
        +     * Optional. The task id of the message. If set, the message will be associated with the given task.
              * 
        * * string task_id = 3; @@ -1277,8 +1248,7 @@ public Builder setTaskId( } /** *
        -     * The task id of the message. This is optional and if set, the message
        -     * will be associated with the given task.
        +     * Optional. The task id of the message. If set, the message will be associated with the given task.
              * 
        * * string task_id = 3; @@ -1292,8 +1262,7 @@ public Builder clearTaskId() { } /** *
        -     * The task id of the message. This is optional and if set, the message
        -     * will be associated with the given task.
        +     * Optional. The task id of the message. If set, the message will be associated with the given task.
              * 
        * * string task_id = 3; @@ -1316,7 +1285,7 @@ public Builder setTaskIdBytes( * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @return The enum numeric value on the wire for role. */ @java.lang.Override public int getRoleValue() { @@ -1327,7 +1296,7 @@ public Builder setTaskIdBytes( * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @param value The enum numeric value on the wire for role to set. * @return This builder for chaining. */ @@ -1342,7 +1311,7 @@ public Builder setRoleValue(int value) { * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @return The role. */ @java.lang.Override @@ -1355,7 +1324,7 @@ public io.a2a.grpc.Role getRole() { * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @param value The role to set. * @return This builder for chaining. */ @@ -1371,7 +1340,7 @@ public Builder setRole(io.a2a.grpc.Role value) { * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearRole() { @@ -1395,11 +1364,10 @@ private void ensurePartsIsMutable() { /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getPartsList() { if (partsBuilder_ == null) { @@ -1410,11 +1378,10 @@ public java.util.List getPartsList() { } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public int getPartsCount() { if (partsBuilder_ == null) { @@ -1425,11 +1392,10 @@ public int getPartsCount() { } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Part getParts(int index) { if (partsBuilder_ == null) { @@ -1440,11 +1406,10 @@ public io.a2a.grpc.Part getParts(int index) { } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setParts( int index, io.a2a.grpc.Part value) { @@ -1462,11 +1427,10 @@ public Builder setParts( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setParts( int index, io.a2a.grpc.Part.Builder builderForValue) { @@ -1481,11 +1445,10 @@ public Builder setParts( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addParts(io.a2a.grpc.Part value) { if (partsBuilder_ == null) { @@ -1502,11 +1465,10 @@ public Builder addParts(io.a2a.grpc.Part value) { } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addParts( int index, io.a2a.grpc.Part value) { @@ -1524,11 +1486,10 @@ public Builder addParts( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addParts( io.a2a.grpc.Part.Builder builderForValue) { @@ -1543,11 +1504,10 @@ public Builder addParts( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addParts( int index, io.a2a.grpc.Part.Builder builderForValue) { @@ -1562,11 +1522,10 @@ public Builder addParts( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder addAllParts( java.lang.Iterable values) { @@ -1582,11 +1541,10 @@ public Builder addAllParts( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearParts() { if (partsBuilder_ == null) { @@ -1600,11 +1558,10 @@ public Builder clearParts() { } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public Builder removeParts(int index) { if (partsBuilder_ == null) { @@ -1618,11 +1575,10 @@ public Builder removeParts(int index) { } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Part.Builder getPartsBuilder( int index) { @@ -1630,11 +1586,10 @@ public io.a2a.grpc.Part.Builder getPartsBuilder( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( int index) { @@ -1645,11 +1600,10 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getPartsOrBuilderList() { @@ -1661,11 +1615,10 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Part.Builder addPartsBuilder() { return internalGetPartsFieldBuilder().addBuilder( @@ -1673,11 +1626,10 @@ public io.a2a.grpc.Part.Builder addPartsBuilder() { } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Part.Builder addPartsBuilder( int index) { @@ -1686,11 +1638,10 @@ public io.a2a.grpc.Part.Builder addPartsBuilder( } /** *
        -     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
              * Parts is the container of the message content.
              * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ public java.util.List getPartsBuilderList() { @@ -1716,8 +1667,7 @@ public io.a2a.grpc.Part.Builder addPartsBuilder( com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1728,8 +1678,7 @@ public boolean hasMetadata() { } /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1744,8 +1693,7 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1765,8 +1713,7 @@ public Builder setMetadata(com.google.protobuf.Struct value) { } /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1784,8 +1731,7 @@ public Builder setMetadata( } /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1810,8 +1756,7 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) { } /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1828,8 +1773,7 @@ public Builder clearMetadata() { } /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1841,8 +1785,7 @@ public com.google.protobuf.Struct.Builder getMetadataBuilder() { } /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1857,8 +1800,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { } /** *
        -     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -     * Any optional metadata to provide along with the message.
        +     * Optional. Any metadata to provide along with the message.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -2171,10 +2113,10 @@ public Builder addReferenceTaskIdsBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.Message) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.Message) } - // @@protoc_insertion_point(class_scope:a2a.v1.Message) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.Message) private static final io.a2a.grpc.Message DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.Message(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java index cfd7ea3ef..256f38fe4 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java @@ -7,13 +7,12 @@ @com.google.protobuf.Generated public interface MessageOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Message) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.Message) com.google.protobuf.MessageOrBuilder { /** *
        -   * The unique identifier (e.g. UUID) of the message. This is required and
        -   * created by the message creator.
        +   * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
            * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -22,8 +21,7 @@ public interface MessageOrBuilder extends java.lang.String getMessageId(); /** *
        -   * The unique identifier (e.g. UUID) of the message. This is required and
        -   * created by the message creator.
        +   * The unique identifier (e.g. UUID) of the message. This is created by the message creator.
            * 
        * * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -34,8 +32,7 @@ public interface MessageOrBuilder extends /** *
        -   * The context id of the message. This is optional and if set, the message
        -   * will be associated with the given context.
        +   * Optional. The context id of the message. If set, the message will be associated with the given context.
            * 
        * * string context_id = 2; @@ -44,8 +41,7 @@ public interface MessageOrBuilder extends java.lang.String getContextId(); /** *
        -   * The context id of the message. This is optional and if set, the message
        -   * will be associated with the given context.
        +   * Optional. The context id of the message. If set, the message will be associated with the given context.
            * 
        * * string context_id = 2; @@ -56,8 +52,7 @@ public interface MessageOrBuilder extends /** *
        -   * The task id of the message. This is optional and if set, the message
        -   * will be associated with the given task.
        +   * Optional. The task id of the message. If set, the message will be associated with the given task.
            * 
        * * string task_id = 3; @@ -66,8 +61,7 @@ public interface MessageOrBuilder extends java.lang.String getTaskId(); /** *
        -   * The task id of the message. This is optional and if set, the message
        -   * will be associated with the given task.
        +   * Optional. The task id of the message. If set, the message will be associated with the given task.
            * 
        * * string task_id = 3; @@ -81,7 +75,7 @@ public interface MessageOrBuilder extends * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @return The enum numeric value on the wire for role. */ int getRoleValue(); @@ -90,64 +84,58 @@ public interface MessageOrBuilder extends * Identifies the sender of the message. * * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; * @return The role. */ io.a2a.grpc.Role getRole(); /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getPartsList(); /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.Part getParts(int index); /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ int getPartsCount(); /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ java.util.List getPartsOrBuilderList(); /** *
        -   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            * Parts is the container of the message content.
            * 
        * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; + * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.PartOrBuilder getPartsOrBuilder( int index); /** *
        -   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -   * Any optional metadata to provide along with the message.
        +   * Optional. Any metadata to provide along with the message.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -156,8 +144,7 @@ io.a2a.grpc.PartOrBuilder getPartsOrBuilder( boolean hasMetadata(); /** *
        -   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -   * Any optional metadata to provide along with the message.
        +   * Optional. Any metadata to provide along with the message.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -166,8 +153,7 @@ io.a2a.grpc.PartOrBuilder getPartsOrBuilder( com.google.protobuf.Struct getMetadata(); /** *
        -   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
        -   * Any optional metadata to provide along with the message.
        +   * Optional. Any metadata to provide along with the message.
            * 
        * * .google.protobuf.Struct metadata = 6; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java index b85fce3e4..66490ee33 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:MutualTLSSecurityScheme]
          * Defines a security scheme using mTLS authentication.
          * 
        * - * Protobuf type {@code a2a.v1.MutualTlsSecurityScheme} + * Protobuf type {@code lf.a2a.v1.MutualTlsSecurityScheme} */ @com.google.protobuf.Generated public final class MutualTlsSecurityScheme extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.MutualTlsSecurityScheme) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.MutualTlsSecurityScheme) MutualTlsSecuritySchemeOrBuilder { private static final long serialVersionUID = 0L; static { @@ -38,13 +37,13 @@ private MutualTlsSecurityScheme() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.MutualTlsSecurityScheme.class, io.a2a.grpc.MutualTlsSecurityScheme.Builder.class); } @@ -254,25 +253,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:MutualTLSSecurityScheme]
            * Defines a security scheme using mTLS authentication.
            * 
        * - * Protobuf type {@code a2a.v1.MutualTlsSecurityScheme} + * Protobuf type {@code lf.a2a.v1.MutualTlsSecurityScheme} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.MutualTlsSecurityScheme) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.MutualTlsSecurityScheme) io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.MutualTlsSecurityScheme.class, io.a2a.grpc.MutualTlsSecurityScheme.Builder.class); } @@ -298,7 +296,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor; } @java.lang.Override @@ -487,10 +485,10 @@ public Builder setDescriptionBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.MutualTlsSecurityScheme) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.MutualTlsSecurityScheme) } - // @@protoc_insertion_point(class_scope:a2a.v1.MutualTlsSecurityScheme) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.MutualTlsSecurityScheme) private static final io.a2a.grpc.MutualTlsSecurityScheme DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.MutualTlsSecurityScheme(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java index c5c606198..b16aa1add 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface MutualTlsSecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.MutualTlsSecurityScheme) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.MutualTlsSecurityScheme) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java index 6b3d725e8..144a99864 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:OAuth2SecurityScheme]
          * Defines a security scheme using OAuth 2.0.
          * 
        * - * Protobuf type {@code a2a.v1.OAuth2SecurityScheme} + * Protobuf type {@code lf.a2a.v1.OAuth2SecurityScheme} */ @com.google.protobuf.Generated public final class OAuth2SecurityScheme extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.OAuth2SecurityScheme) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.OAuth2SecurityScheme) OAuth2SecuritySchemeOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,13 +38,13 @@ private OAuth2SecurityScheme() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.OAuth2SecurityScheme.class, io.a2a.grpc.OAuth2SecurityScheme.Builder.class); } @@ -105,7 +104,7 @@ public java.lang.String getDescription() { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the flows field is set. */ @java.lang.Override @@ -117,7 +116,7 @@ public boolean hasFlows() { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The flows. */ @java.lang.Override @@ -129,7 +128,7 @@ public io.a2a.grpc.OAuthFlows getFlows() { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { @@ -141,8 +140,8 @@ public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { private volatile java.lang.Object oauth2MetadataUrl_ = ""; /** *
        -   * URL to the oauth2 authorization server metadata
        -   * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +   * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +   * TLS is required.
            * 
        * * string oauth2_metadata_url = 3; @@ -163,8 +162,8 @@ public java.lang.String getOauth2MetadataUrl() { } /** *
        -   * URL to the oauth2 authorization server metadata
        -   * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +   * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +   * TLS is required.
            * 
        * * string oauth2_metadata_url = 3; @@ -369,25 +368,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:OAuth2SecurityScheme]
            * Defines a security scheme using OAuth 2.0.
            * 
        * - * Protobuf type {@code a2a.v1.OAuth2SecurityScheme} + * Protobuf type {@code lf.a2a.v1.OAuth2SecurityScheme} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.OAuth2SecurityScheme) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.OAuth2SecurityScheme) io.a2a.grpc.OAuth2SecuritySchemeOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.OAuth2SecurityScheme.class, io.a2a.grpc.OAuth2SecurityScheme.Builder.class); } @@ -425,7 +423,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor; } @java.lang.Override @@ -653,7 +651,7 @@ public Builder setDescriptionBytes( * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the flows field is set. */ public boolean hasFlows() { @@ -664,7 +662,7 @@ public boolean hasFlows() { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The flows. */ public io.a2a.grpc.OAuthFlows getFlows() { @@ -679,7 +677,7 @@ public io.a2a.grpc.OAuthFlows getFlows() { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setFlows(io.a2a.grpc.OAuthFlows value) { if (flowsBuilder_ == null) { @@ -699,7 +697,7 @@ public Builder setFlows(io.a2a.grpc.OAuthFlows value) { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setFlows( io.a2a.grpc.OAuthFlows.Builder builderForValue) { @@ -717,7 +715,7 @@ public Builder setFlows( * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ public Builder mergeFlows(io.a2a.grpc.OAuthFlows value) { if (flowsBuilder_ == null) { @@ -742,7 +740,7 @@ public Builder mergeFlows(io.a2a.grpc.OAuthFlows value) { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearFlows() { bitField0_ = (bitField0_ & ~0x00000002); @@ -759,7 +757,7 @@ public Builder clearFlows() { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.OAuthFlows.Builder getFlowsBuilder() { bitField0_ |= 0x00000002; @@ -771,7 +769,7 @@ public io.a2a.grpc.OAuthFlows.Builder getFlowsBuilder() { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { if (flowsBuilder_ != null) { @@ -786,7 +784,7 @@ public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.OAuthFlows, io.a2a.grpc.OAuthFlows.Builder, io.a2a.grpc.OAuthFlowsOrBuilder> @@ -805,8 +803,8 @@ public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { private java.lang.Object oauth2MetadataUrl_ = ""; /** *
        -     * URL to the oauth2 authorization server metadata
        -     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +     * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +     * TLS is required.
              * 
        * * string oauth2_metadata_url = 3; @@ -826,8 +824,8 @@ public java.lang.String getOauth2MetadataUrl() { } /** *
        -     * URL to the oauth2 authorization server metadata
        -     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +     * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +     * TLS is required.
              * 
        * * string oauth2_metadata_url = 3; @@ -848,8 +846,8 @@ public java.lang.String getOauth2MetadataUrl() { } /** *
        -     * URL to the oauth2 authorization server metadata
        -     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +     * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +     * TLS is required.
              * 
        * * string oauth2_metadata_url = 3; @@ -866,8 +864,8 @@ public Builder setOauth2MetadataUrl( } /** *
        -     * URL to the oauth2 authorization server metadata
        -     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +     * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +     * TLS is required.
              * 
        * * string oauth2_metadata_url = 3; @@ -881,8 +879,8 @@ public Builder clearOauth2MetadataUrl() { } /** *
        -     * URL to the oauth2 authorization server metadata
        -     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +     * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +     * TLS is required.
              * 
        * * string oauth2_metadata_url = 3; @@ -899,10 +897,10 @@ public Builder setOauth2MetadataUrlBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.OAuth2SecurityScheme) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.OAuth2SecurityScheme) } - // @@protoc_insertion_point(class_scope:a2a.v1.OAuth2SecurityScheme) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.OAuth2SecurityScheme) private static final io.a2a.grpc.OAuth2SecurityScheme DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.OAuth2SecurityScheme(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java index 52b49d1c3..1eb612bb1 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface OAuth2SecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.OAuth2SecurityScheme) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.OAuth2SecurityScheme) com.google.protobuf.MessageOrBuilder { /** @@ -35,7 +35,7 @@ public interface OAuth2SecuritySchemeOrBuilder extends * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the flows field is set. */ boolean hasFlows(); @@ -44,7 +44,7 @@ public interface OAuth2SecuritySchemeOrBuilder extends * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The flows. */ io.a2a.grpc.OAuthFlows getFlows(); @@ -53,14 +53,14 @@ public interface OAuth2SecuritySchemeOrBuilder extends * An object containing configuration information for the supported OAuth 2.0 flows. * * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder(); /** *
        -   * URL to the oauth2 authorization server metadata
        -   * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +   * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +   * TLS is required.
            * 
        * * string oauth2_metadata_url = 3; @@ -69,8 +69,8 @@ public interface OAuth2SecuritySchemeOrBuilder extends java.lang.String getOauth2MetadataUrl(); /** *
        -   * URL to the oauth2 authorization server metadata
        -   * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
        +   * URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
        +   * TLS is required.
            * 
        * * string oauth2_metadata_url = 3; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java index 8b1a661f7..ab013c822 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:OAuthFlows]
          * Defines the configuration for the supported OAuth 2.0 flows.
          * 
        * - * Protobuf type {@code a2a.v1.OAuthFlows} + * Protobuf type {@code lf.a2a.v1.OAuthFlows} */ @com.google.protobuf.Generated public final class OAuthFlows extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.OAuthFlows) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.OAuthFlows) OAuthFlowsOrBuilder { private static final long serialVersionUID = 0L; static { @@ -37,13 +36,13 @@ private OAuthFlows() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.OAuthFlows.class, io.a2a.grpc.OAuthFlows.Builder.class); } @@ -102,7 +101,7 @@ public int getNumber() { * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; * @return Whether the authorizationCode field is set. */ @java.lang.Override @@ -114,7 +113,7 @@ public boolean hasAuthorizationCode() { * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; * @return The authorizationCode. */ @java.lang.Override @@ -129,7 +128,7 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() { * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ @java.lang.Override public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() { @@ -145,7 +144,7 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBui * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; * @return Whether the clientCredentials field is set. */ @java.lang.Override @@ -157,7 +156,7 @@ public boolean hasClientCredentials() { * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; * @return The clientCredentials. */ @java.lang.Override @@ -172,7 +171,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials() { * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ @java.lang.Override public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() { @@ -184,9 +183,13 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui public static final int IMPLICIT_FIELD_NUMBER = 3; /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 + *
        +   * Deprecated: Use Authorization Code + PKCE instead.
        +   * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. + * See a2a.proto;l=570 * @return Whether the implicit field is set. */ @java.lang.Override @@ -194,9 +197,13 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return flowCase_ == 3; } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 + *
        +   * Deprecated: Use Authorization Code + PKCE instead.
        +   * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. + * See a2a.proto;l=570 * @return The implicit. */ @java.lang.Override @@ -207,7 +214,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +   * Deprecated: Use Authorization Code + PKCE instead.
        +   * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ @java.lang.Override @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() { @@ -219,9 +230,13 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui public static final int PASSWORD_FIELD_NUMBER = 4; /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 + *
        +   * Deprecated: Use Authorization Code + PKCE or Device Code.
        +   * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. + * See a2a.proto;l=572 * @return Whether the password field is set. */ @java.lang.Override @@ -229,9 +244,13 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return flowCase_ == 4; } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 + *
        +   * Deprecated: Use Authorization Code + PKCE or Device Code.
        +   * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. + * See a2a.proto;l=572 * @return The password. */ @java.lang.Override @@ -242,7 +261,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +   * Deprecated: Use Authorization Code + PKCE or Device Code.
        +   * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ @java.lang.Override @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() { @@ -258,7 +281,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; * @return Whether the deviceCode field is set. */ @java.lang.Override @@ -270,7 +293,7 @@ public boolean hasDeviceCode() { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; * @return The deviceCode. */ @java.lang.Override @@ -285,7 +308,7 @@ public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ @java.lang.Override public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() { @@ -527,25 +550,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:OAuthFlows]
            * Defines the configuration for the supported OAuth 2.0 flows.
            * 
        * - * Protobuf type {@code a2a.v1.OAuthFlows} + * Protobuf type {@code lf.a2a.v1.OAuthFlows} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.OAuthFlows) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.OAuthFlows) io.a2a.grpc.OAuthFlowsOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.OAuthFlows.class, io.a2a.grpc.OAuthFlows.Builder.class); } @@ -587,7 +609,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor; } @java.lang.Override @@ -779,7 +801,7 @@ public Builder clearFlow() { * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; * @return Whether the authorizationCode field is set. */ @java.lang.Override @@ -791,7 +813,7 @@ public boolean hasAuthorizationCode() { * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; * @return The authorizationCode. */ @java.lang.Override @@ -813,7 +835,7 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() { * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ public Builder setAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow value) { if (authorizationCodeBuilder_ == null) { @@ -833,7 +855,7 @@ public Builder setAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow value * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ public Builder setAuthorizationCode( io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder builderForValue) { @@ -851,7 +873,7 @@ public Builder setAuthorizationCode( * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ public Builder mergeAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow value) { if (authorizationCodeBuilder_ == null) { @@ -878,7 +900,7 @@ public Builder mergeAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow val * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ public Builder clearAuthorizationCode() { if (authorizationCodeBuilder_ == null) { @@ -901,7 +923,7 @@ public Builder clearAuthorizationCode() { * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ public io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder getAuthorizationCodeBuilder() { return internalGetAuthorizationCodeFieldBuilder().getBuilder(); @@ -911,7 +933,7 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder getAuthorizationCodeBuilde * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ @java.lang.Override public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() { @@ -929,7 +951,7 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBui * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.AuthorizationCodeOAuthFlow, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder, io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder> @@ -957,7 +979,7 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBui * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; * @return Whether the clientCredentials field is set. */ @java.lang.Override @@ -969,7 +991,7 @@ public boolean hasClientCredentials() { * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; * @return The clientCredentials. */ @java.lang.Override @@ -991,7 +1013,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials() { * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ public Builder setClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow value) { if (clientCredentialsBuilder_ == null) { @@ -1011,7 +1033,7 @@ public Builder setClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow value * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ public Builder setClientCredentials( io.a2a.grpc.ClientCredentialsOAuthFlow.Builder builderForValue) { @@ -1029,7 +1051,7 @@ public Builder setClientCredentials( * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ public Builder mergeClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow value) { if (clientCredentialsBuilder_ == null) { @@ -1056,7 +1078,7 @@ public Builder mergeClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow val * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ public Builder clearClientCredentials() { if (clientCredentialsBuilder_ == null) { @@ -1079,7 +1101,7 @@ public Builder clearClientCredentials() { * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ public io.a2a.grpc.ClientCredentialsOAuthFlow.Builder getClientCredentialsBuilder() { return internalGetClientCredentialsFieldBuilder().getBuilder(); @@ -1089,7 +1111,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlow.Builder getClientCredentialsBuilde * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ @java.lang.Override public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() { @@ -1107,7 +1129,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.ClientCredentialsOAuthFlow, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder, io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder> @@ -1131,9 +1153,13 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> implicitBuilder_; /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. + * See a2a.proto;l=570 * @return Whether the implicit field is set. */ @java.lang.Override @@ -1141,9 +1167,13 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return flowCase_ == 3; } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. + * See a2a.proto;l=570 * @return The implicit. */ @java.lang.Override @@ -1161,7 +1191,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui } } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ @java.lang.Deprecated public Builder setImplicit(io.a2a.grpc.ImplicitOAuthFlow value) { if (implicitBuilder_ == null) { @@ -1177,7 +1211,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return this; } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ @java.lang.Deprecated public Builder setImplicit( io.a2a.grpc.ImplicitOAuthFlow.Builder builderForValue) { @@ -1191,7 +1229,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return this; } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ @java.lang.Deprecated public Builder mergeImplicit(io.a2a.grpc.ImplicitOAuthFlow value) { if (implicitBuilder_ == null) { @@ -1214,7 +1256,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return this; } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ @java.lang.Deprecated public Builder clearImplicit() { if (implicitBuilder_ == null) { @@ -1233,13 +1279,21 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return this; } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow.Builder getImplicitBuilder() { return internalGetImplicitFieldBuilder().getBuilder(); } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ @java.lang.Override @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() { @@ -1253,7 +1307,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui } } /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE instead.
        +     * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> @@ -1277,9 +1335,13 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> passwordBuilder_; /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. + * See a2a.proto;l=572 * @return Whether the password field is set. */ @java.lang.Override @@ -1287,9 +1349,13 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return flowCase_ == 4; } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. + * See a2a.proto;l=572 * @return The password. */ @java.lang.Override @@ -1307,7 +1373,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui } } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ @java.lang.Deprecated public Builder setPassword(io.a2a.grpc.PasswordOAuthFlow value) { if (passwordBuilder_ == null) { @@ -1323,7 +1393,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return this; } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ @java.lang.Deprecated public Builder setPassword( io.a2a.grpc.PasswordOAuthFlow.Builder builderForValue) { @@ -1337,7 +1411,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return this; } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ @java.lang.Deprecated public Builder mergePassword(io.a2a.grpc.PasswordOAuthFlow value) { if (passwordBuilder_ == null) { @@ -1360,7 +1438,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return this; } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ @java.lang.Deprecated public Builder clearPassword() { if (passwordBuilder_ == null) { @@ -1379,13 +1461,21 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui return this; } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow.Builder getPasswordBuilder() { return internalGetPasswordFieldBuilder().getBuilder(); } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ @java.lang.Override @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() { @@ -1399,7 +1489,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui } } /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +     * Deprecated: Use Authorization Code + PKCE or Device Code.
        +     * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> @@ -1427,7 +1521,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; * @return Whether the deviceCode field is set. */ @java.lang.Override @@ -1439,7 +1533,7 @@ public boolean hasDeviceCode() { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; * @return The deviceCode. */ @java.lang.Override @@ -1461,7 +1555,7 @@ public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ public Builder setDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) { if (deviceCodeBuilder_ == null) { @@ -1481,7 +1575,7 @@ public Builder setDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ public Builder setDeviceCode( io.a2a.grpc.DeviceCodeOAuthFlow.Builder builderForValue) { @@ -1499,7 +1593,7 @@ public Builder setDeviceCode( * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ public Builder mergeDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) { if (deviceCodeBuilder_ == null) { @@ -1526,7 +1620,7 @@ public Builder mergeDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ public Builder clearDeviceCode() { if (deviceCodeBuilder_ == null) { @@ -1549,7 +1643,7 @@ public Builder clearDeviceCode() { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ public io.a2a.grpc.DeviceCodeOAuthFlow.Builder getDeviceCodeBuilder() { return internalGetDeviceCodeFieldBuilder().getBuilder(); @@ -1559,7 +1653,7 @@ public io.a2a.grpc.DeviceCodeOAuthFlow.Builder getDeviceCodeBuilder() { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ @java.lang.Override public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() { @@ -1577,7 +1671,7 @@ public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() { * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder> @@ -1598,10 +1692,10 @@ public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() { return deviceCodeBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.OAuthFlows) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.OAuthFlows) } - // @@protoc_insertion_point(class_scope:a2a.v1.OAuthFlows) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.OAuthFlows) private static final io.a2a.grpc.OAuthFlows DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.OAuthFlows(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java index 1debd6d12..b4c4a30fc 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface OAuthFlowsOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.OAuthFlows) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.OAuthFlows) com.google.protobuf.MessageOrBuilder { /** @@ -15,7 +15,7 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; * @return Whether the authorizationCode field is set. */ boolean hasAuthorizationCode(); @@ -24,7 +24,7 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; * @return The authorizationCode. */ io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode(); @@ -33,7 +33,7 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Authorization Code flow. * * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; */ io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder(); @@ -42,7 +42,7 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; * @return Whether the clientCredentials field is set. */ boolean hasClientCredentials(); @@ -51,7 +51,7 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; * @return The clientCredentials. */ io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials(); @@ -60,45 +60,69 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Client Credentials flow. * * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; */ io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder(); /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 + *
        +   * Deprecated: Use Authorization Code + PKCE instead.
        +   * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. + * See a2a.proto;l=570 * @return Whether the implicit field is set. */ @java.lang.Deprecated boolean hasImplicit(); /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 + *
        +   * Deprecated: Use Authorization Code + PKCE instead.
        +   * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. + * See a2a.proto;l=570 * @return The implicit. */ @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlow getImplicit(); /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; + *
        +   * Deprecated: Use Authorization Code + PKCE instead.
        +   * 
        + * + * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; */ @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder(); /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 + *
        +   * Deprecated: Use Authorization Code + PKCE or Device Code.
        +   * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. + * See a2a.proto;l=572 * @return Whether the password field is set. */ @java.lang.Deprecated boolean hasPassword(); /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 + *
        +   * Deprecated: Use Authorization Code + PKCE or Device Code.
        +   * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. + * See a2a.proto;l=572 * @return The password. */ @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlow getPassword(); /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; + *
        +   * Deprecated: Use Authorization Code + PKCE or Device Code.
        +   * 
        + * + * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; */ @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder(); @@ -107,7 +131,7 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; * @return Whether the deviceCode field is set. */ boolean hasDeviceCode(); @@ -116,7 +140,7 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; * @return The deviceCode. */ io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode(); @@ -125,7 +149,7 @@ public interface OAuthFlowsOrBuilder extends * Configuration for the OAuth Device Code flow. * * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; + * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5; */ io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java index 001ea51e8..d0b2eb580 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:OpenIdConnectSecurityScheme]
          * Defines a security scheme using OpenID Connect.
          * 
        * - * Protobuf type {@code a2a.v1.OpenIdConnectSecurityScheme} + * Protobuf type {@code lf.a2a.v1.OpenIdConnectSecurityScheme} */ @com.google.protobuf.Generated public final class OpenIdConnectSecurityScheme extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.OpenIdConnectSecurityScheme) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.OpenIdConnectSecurityScheme) OpenIdConnectSecuritySchemeOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,13 +38,13 @@ private OpenIdConnectSecurityScheme() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.OpenIdConnectSecurityScheme.class, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder.class); } @@ -102,8 +101,7 @@ public java.lang.String getDescription() { private volatile java.lang.Object openIdConnectUrl_ = ""; /** *
        -   * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -   * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +   * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
            * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -124,8 +122,7 @@ public java.lang.String getOpenIdConnectUrl() { } /** *
        -   * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -   * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +   * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
            * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -314,25 +311,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:OpenIdConnectSecurityScheme]
            * Defines a security scheme using OpenID Connect.
            * 
        * - * Protobuf type {@code a2a.v1.OpenIdConnectSecurityScheme} + * Protobuf type {@code lf.a2a.v1.OpenIdConnectSecurityScheme} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.OpenIdConnectSecurityScheme) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.OpenIdConnectSecurityScheme) io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.OpenIdConnectSecurityScheme.class, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder.class); } @@ -359,7 +355,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor; } @java.lang.Override @@ -564,8 +560,7 @@ public Builder setDescriptionBytes( private java.lang.Object openIdConnectUrl_ = ""; /** *
        -     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +     * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
              * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -585,8 +580,7 @@ public java.lang.String getOpenIdConnectUrl() { } /** *
        -     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +     * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
              * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -607,8 +601,7 @@ public java.lang.String getOpenIdConnectUrl() { } /** *
        -     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +     * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
              * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -625,8 +618,7 @@ public Builder setOpenIdConnectUrl( } /** *
        -     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +     * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
              * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -640,8 +632,7 @@ public Builder clearOpenIdConnectUrl() { } /** *
        -     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +     * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
              * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -658,10 +649,10 @@ public Builder setOpenIdConnectUrlBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.OpenIdConnectSecurityScheme) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.OpenIdConnectSecurityScheme) } - // @@protoc_insertion_point(class_scope:a2a.v1.OpenIdConnectSecurityScheme) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.OpenIdConnectSecurityScheme) private static final io.a2a.grpc.OpenIdConnectSecurityScheme DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.OpenIdConnectSecurityScheme(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java index d51225f03..3887a6d38 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface OpenIdConnectSecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.OpenIdConnectSecurityScheme) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.OpenIdConnectSecurityScheme) com.google.protobuf.MessageOrBuilder { /** @@ -32,8 +32,7 @@ public interface OpenIdConnectSecuritySchemeOrBuilder extends /** *
        -   * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -   * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +   * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
            * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -42,8 +41,7 @@ public interface OpenIdConnectSecuritySchemeOrBuilder extends java.lang.String getOpenIdConnectUrl(); /** *
        -   * The OpenID Connect Discovery URL for the OIDC provider's metadata.
        -   * See: https://openid.net/specs/openid-connect-discovery-1_0.html
        +   * The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata.
            * 
        * * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Part.java b/spec-grpc/src/main/java/io/a2a/grpc/Part.java index 879380c96..46f10d95c 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/Part.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/Part.java @@ -7,18 +7,17 @@ /** *
        - * --8<-- [start:Part]
        - * Part represents a container for a section of communication content.
        + * `Part` represents a container for a section of communication content.
          * Parts can be purely textual, some sort of file (image, video, etc) or
          * a structured data blob (i.e. JSON).
          * 
        * - * Protobuf type {@code a2a.v1.Part} + * Protobuf type {@code lf.a2a.v1.Part} */ @com.google.protobuf.Generated public final class Part extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Part) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.Part) PartOrBuilder { private static final long serialVersionUID = 0L; static { @@ -41,13 +40,13 @@ private Part() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.Part.class, io.a2a.grpc.Part.Builder.class); } @@ -102,7 +101,7 @@ public int getNumber() { public static final int TEXT_FIELD_NUMBER = 1; /** *
        -   * The string content of the text part.
        +   * The string content of the `text` part.
            * 
        * * string text = 1; @@ -113,7 +112,7 @@ public boolean hasText() { } /** *
        -   * The string content of the text part.
        +   * The string content of the `text` part.
            * 
        * * string text = 1; @@ -138,7 +137,7 @@ public java.lang.String getText() { } /** *
        -   * The string content of the text part.
        +   * The string content of the `text` part.
            * 
        * * string text = 1; @@ -166,7 +165,7 @@ public java.lang.String getText() { public static final int RAW_FIELD_NUMBER = 2; /** *
        -   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        +   * The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string.
            * 
        * * bytes raw = 2; @@ -178,7 +177,7 @@ public boolean hasRaw() { } /** *
        -   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        +   * The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string.
            * 
        * * bytes raw = 2; @@ -195,7 +194,7 @@ public com.google.protobuf.ByteString getRaw() { public static final int URL_FIELD_NUMBER = 3; /** *
        -   * A URL pointing to the file's content.
        +   * A `url` pointing to the file's content.
            * 
        * * string url = 3; @@ -206,7 +205,7 @@ public boolean hasUrl() { } /** *
        -   * A URL pointing to the file's content.
        +   * A `url` pointing to the file's content.
            * 
        * * string url = 3; @@ -231,7 +230,7 @@ public java.lang.String getUrl() { } /** *
        -   * A URL pointing to the file's content.
        +   * A `url` pointing to the file's content.
            * 
        * * string url = 3; @@ -259,7 +258,7 @@ public java.lang.String getUrl() { public static final int DATA_FIELD_NUMBER = 4; /** *
        -   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +   * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
            * 
        * * .google.protobuf.Value data = 4; @@ -271,7 +270,7 @@ public boolean hasData() { } /** *
        -   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +   * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
            * 
        * * .google.protobuf.Value data = 4; @@ -286,7 +285,7 @@ public com.google.protobuf.Value getData() { } /** *
        -   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +   * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
            * 
        * * .google.protobuf.Value data = 4; @@ -303,7 +302,7 @@ public com.google.protobuf.ValueOrBuilder getDataOrBuilder() { private com.google.protobuf.Struct metadata_; /** *
        -   * Optional metadata associated with this part.
        +   * Optional. metadata associated with this part.
            * 
        * * .google.protobuf.Struct metadata = 5; @@ -315,7 +314,7 @@ public boolean hasMetadata() { } /** *
        -   * Optional metadata associated with this part.
        +   * Optional. metadata associated with this part.
            * 
        * * .google.protobuf.Struct metadata = 5; @@ -327,7 +326,7 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -   * Optional metadata associated with this part.
        +   * Optional. metadata associated with this part.
            * 
        * * .google.protobuf.Struct metadata = 5; @@ -342,7 +341,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { private volatile java.lang.Object filename_ = ""; /** *
        -   * An optional name for the file (e.g., "document.pdf").
        +   * An optional `filename` for the file (e.g., "document.pdf").
            * 
        * * string filename = 6; @@ -363,7 +362,7 @@ public java.lang.String getFilename() { } /** *
        -   * An optional name for the file (e.g., "document.pdf").
        +   * An optional `filename` for the file (e.g., "document.pdf").
            * 
        * * string filename = 6; @@ -389,7 +388,7 @@ public java.lang.String getFilename() { private volatile java.lang.Object mediaType_ = ""; /** *
        -   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +   * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
            * This field is available for all part types.
            * 
        * @@ -411,7 +410,7 @@ public java.lang.String getMediaType() { } /** *
        -   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +   * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
            * This field is available for all part types.
            * 
        * @@ -686,27 +685,26 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:Part]
        -   * Part represents a container for a section of communication content.
        +   * `Part` represents a container for a section of communication content.
            * Parts can be purely textual, some sort of file (image, video, etc) or
            * a structured data blob (i.e. JSON).
            * 
        * - * Protobuf type {@code a2a.v1.Part} + * Protobuf type {@code lf.a2a.v1.Part} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Part) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.Part) io.a2a.grpc.PartOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.Part.class, io.a2a.grpc.Part.Builder.class); } @@ -749,7 +747,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor; } @java.lang.Override @@ -953,7 +951,7 @@ public Builder clearContent() { /** *
        -     * The string content of the text part.
        +     * The string content of the `text` part.
              * 
        * * string text = 1; @@ -965,7 +963,7 @@ public boolean hasText() { } /** *
        -     * The string content of the text part.
        +     * The string content of the `text` part.
              * 
        * * string text = 1; @@ -991,7 +989,7 @@ public java.lang.String getText() { } /** *
        -     * The string content of the text part.
        +     * The string content of the `text` part.
              * 
        * * string text = 1; @@ -1018,7 +1016,7 @@ public java.lang.String getText() { } /** *
        -     * The string content of the text part.
        +     * The string content of the `text` part.
              * 
        * * string text = 1; @@ -1035,7 +1033,7 @@ public Builder setText( } /** *
        -     * The string content of the text part.
        +     * The string content of the `text` part.
              * 
        * * string text = 1; @@ -1051,7 +1049,7 @@ public Builder clearText() { } /** *
        -     * The string content of the text part.
        +     * The string content of the `text` part.
              * 
        * * string text = 1; @@ -1070,7 +1068,7 @@ public Builder setTextBytes( /** *
        -     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        +     * The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string.
              * 
        * * bytes raw = 2; @@ -1081,7 +1079,7 @@ public boolean hasRaw() { } /** *
        -     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        +     * The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string.
              * 
        * * bytes raw = 2; @@ -1095,7 +1093,7 @@ public com.google.protobuf.ByteString getRaw() { } /** *
        -     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        +     * The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string.
              * 
        * * bytes raw = 2; @@ -1111,7 +1109,7 @@ public Builder setRaw(com.google.protobuf.ByteString value) { } /** *
        -     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        +     * The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string.
              * 
        * * bytes raw = 2; @@ -1128,7 +1126,7 @@ public Builder clearRaw() { /** *
        -     * A URL pointing to the file's content.
        +     * A `url` pointing to the file's content.
              * 
        * * string url = 3; @@ -1140,7 +1138,7 @@ public boolean hasUrl() { } /** *
        -     * A URL pointing to the file's content.
        +     * A `url` pointing to the file's content.
              * 
        * * string url = 3; @@ -1166,7 +1164,7 @@ public java.lang.String getUrl() { } /** *
        -     * A URL pointing to the file's content.
        +     * A `url` pointing to the file's content.
              * 
        * * string url = 3; @@ -1193,7 +1191,7 @@ public java.lang.String getUrl() { } /** *
        -     * A URL pointing to the file's content.
        +     * A `url` pointing to the file's content.
              * 
        * * string url = 3; @@ -1210,7 +1208,7 @@ public Builder setUrl( } /** *
        -     * A URL pointing to the file's content.
        +     * A `url` pointing to the file's content.
              * 
        * * string url = 3; @@ -1226,7 +1224,7 @@ public Builder clearUrl() { } /** *
        -     * A URL pointing to the file's content.
        +     * A `url` pointing to the file's content.
              * 
        * * string url = 3; @@ -1247,7 +1245,7 @@ public Builder setUrlBytes( com.google.protobuf.Value, com.google.protobuf.Value.Builder, com.google.protobuf.ValueOrBuilder> dataBuilder_; /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1259,7 +1257,7 @@ public boolean hasData() { } /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1281,7 +1279,7 @@ public com.google.protobuf.Value getData() { } /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1301,7 +1299,7 @@ public Builder setData(com.google.protobuf.Value value) { } /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1319,7 +1317,7 @@ public Builder setData( } /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1346,7 +1344,7 @@ public Builder mergeData(com.google.protobuf.Value value) { } /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1369,7 +1367,7 @@ public Builder clearData() { } /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1379,7 +1377,7 @@ public com.google.protobuf.Value.Builder getDataBuilder() { } /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1397,7 +1395,7 @@ public com.google.protobuf.ValueOrBuilder getDataOrBuilder() { } /** *
        -     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +     * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
              * 
        * * .google.protobuf.Value data = 4; @@ -1426,7 +1424,7 @@ public com.google.protobuf.ValueOrBuilder getDataOrBuilder() { com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1437,7 +1435,7 @@ public boolean hasMetadata() { } /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1452,7 +1450,7 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1472,7 +1470,7 @@ public Builder setMetadata(com.google.protobuf.Struct value) { } /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1490,7 +1488,7 @@ public Builder setMetadata( } /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1515,7 +1513,7 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) { } /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1532,7 +1530,7 @@ public Builder clearMetadata() { } /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1544,7 +1542,7 @@ public com.google.protobuf.Struct.Builder getMetadataBuilder() { } /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1559,7 +1557,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { } /** *
        -     * Optional metadata associated with this part.
        +     * Optional. metadata associated with this part.
              * 
        * * .google.protobuf.Struct metadata = 5; @@ -1581,7 +1579,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { private java.lang.Object filename_ = ""; /** *
        -     * An optional name for the file (e.g., "document.pdf").
        +     * An optional `filename` for the file (e.g., "document.pdf").
              * 
        * * string filename = 6; @@ -1601,7 +1599,7 @@ public java.lang.String getFilename() { } /** *
        -     * An optional name for the file (e.g., "document.pdf").
        +     * An optional `filename` for the file (e.g., "document.pdf").
              * 
        * * string filename = 6; @@ -1622,7 +1620,7 @@ public java.lang.String getFilename() { } /** *
        -     * An optional name for the file (e.g., "document.pdf").
        +     * An optional `filename` for the file (e.g., "document.pdf").
              * 
        * * string filename = 6; @@ -1639,7 +1637,7 @@ public Builder setFilename( } /** *
        -     * An optional name for the file (e.g., "document.pdf").
        +     * An optional `filename` for the file (e.g., "document.pdf").
              * 
        * * string filename = 6; @@ -1653,7 +1651,7 @@ public Builder clearFilename() { } /** *
        -     * An optional name for the file (e.g., "document.pdf").
        +     * An optional `filename` for the file (e.g., "document.pdf").
              * 
        * * string filename = 6; @@ -1673,7 +1671,7 @@ public Builder setFilenameBytes( private java.lang.Object mediaType_ = ""; /** *
        -     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +     * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
              * This field is available for all part types.
              * 
        * @@ -1694,7 +1692,7 @@ public java.lang.String getMediaType() { } /** *
        -     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +     * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
              * This field is available for all part types.
              * 
        * @@ -1716,7 +1714,7 @@ public java.lang.String getMediaType() { } /** *
        -     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +     * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
              * This field is available for all part types.
              * 
        * @@ -1734,7 +1732,7 @@ public Builder setMediaType( } /** *
        -     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +     * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
              * This field is available for all part types.
              * 
        * @@ -1749,7 +1747,7 @@ public Builder clearMediaType() { } /** *
        -     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +     * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
              * This field is available for all part types.
              * 
        * @@ -1767,10 +1765,10 @@ public Builder setMediaTypeBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.Part) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.Part) } - // @@protoc_insertion_point(class_scope:a2a.v1.Part) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.Part) private static final io.a2a.grpc.Part DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.Part(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java index 0216594f2..1ac1a1c9b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java @@ -7,12 +7,12 @@ @com.google.protobuf.Generated public interface PartOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Part) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.Part) com.google.protobuf.MessageOrBuilder { /** *
        -   * The string content of the text part.
        +   * The string content of the `text` part.
            * 
        * * string text = 1; @@ -21,7 +21,7 @@ public interface PartOrBuilder extends boolean hasText(); /** *
        -   * The string content of the text part.
        +   * The string content of the `text` part.
            * 
        * * string text = 1; @@ -30,7 +30,7 @@ public interface PartOrBuilder extends java.lang.String getText(); /** *
        -   * The string content of the text part.
        +   * The string content of the `text` part.
            * 
        * * string text = 1; @@ -41,7 +41,7 @@ public interface PartOrBuilder extends /** *
        -   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        +   * The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string.
            * 
        * * bytes raw = 2; @@ -50,7 +50,7 @@ public interface PartOrBuilder extends boolean hasRaw(); /** *
        -   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
        +   * The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string.
            * 
        * * bytes raw = 2; @@ -60,7 +60,7 @@ public interface PartOrBuilder extends /** *
        -   * A URL pointing to the file's content.
        +   * A `url` pointing to the file's content.
            * 
        * * string url = 3; @@ -69,7 +69,7 @@ public interface PartOrBuilder extends boolean hasUrl(); /** *
        -   * A URL pointing to the file's content.
        +   * A `url` pointing to the file's content.
            * 
        * * string url = 3; @@ -78,7 +78,7 @@ public interface PartOrBuilder extends java.lang.String getUrl(); /** *
        -   * A URL pointing to the file's content.
        +   * A `url` pointing to the file's content.
            * 
        * * string url = 3; @@ -89,7 +89,7 @@ public interface PartOrBuilder extends /** *
        -   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +   * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
            * 
        * * .google.protobuf.Value data = 4; @@ -98,7 +98,7 @@ public interface PartOrBuilder extends boolean hasData(); /** *
        -   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +   * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
            * 
        * * .google.protobuf.Value data = 4; @@ -107,7 +107,7 @@ public interface PartOrBuilder extends com.google.protobuf.Value getData(); /** *
        -   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
        +   * Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null).
            * 
        * * .google.protobuf.Value data = 4; @@ -116,7 +116,7 @@ public interface PartOrBuilder extends /** *
        -   * Optional metadata associated with this part.
        +   * Optional. metadata associated with this part.
            * 
        * * .google.protobuf.Struct metadata = 5; @@ -125,7 +125,7 @@ public interface PartOrBuilder extends boolean hasMetadata(); /** *
        -   * Optional metadata associated with this part.
        +   * Optional. metadata associated with this part.
            * 
        * * .google.protobuf.Struct metadata = 5; @@ -134,7 +134,7 @@ public interface PartOrBuilder extends com.google.protobuf.Struct getMetadata(); /** *
        -   * Optional metadata associated with this part.
        +   * Optional. metadata associated with this part.
            * 
        * * .google.protobuf.Struct metadata = 5; @@ -143,7 +143,7 @@ public interface PartOrBuilder extends /** *
        -   * An optional name for the file (e.g., "document.pdf").
        +   * An optional `filename` for the file (e.g., "document.pdf").
            * 
        * * string filename = 6; @@ -152,7 +152,7 @@ public interface PartOrBuilder extends java.lang.String getFilename(); /** *
        -   * An optional name for the file (e.g., "document.pdf").
        +   * An optional `filename` for the file (e.g., "document.pdf").
            * 
        * * string filename = 6; @@ -163,7 +163,7 @@ public interface PartOrBuilder extends /** *
        -   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +   * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
            * This field is available for all part types.
            * 
        * @@ -173,7 +173,7 @@ public interface PartOrBuilder extends java.lang.String getMediaType(); /** *
        -   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
        +   * The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
            * This field is available for all part types.
            * 
        * diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java index 50f6032bb..df4abb7a3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java @@ -7,15 +7,15 @@ /** *
        - * DEPRECATED
        + * Deprecated: Use Authorization Code + PKCE or Device Code.
          * 
        * - * Protobuf type {@code a2a.v1.PasswordOAuthFlow} + * Protobuf type {@code lf.a2a.v1.PasswordOAuthFlow} */ @com.google.protobuf.Generated public final class PasswordOAuthFlow extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.PasswordOAuthFlow) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.PasswordOAuthFlow) PasswordOAuthFlowOrBuilder { private static final long serialVersionUID = 0L; static { @@ -38,7 +38,7 @@ private PasswordOAuthFlow() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -56,7 +56,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class); } @@ -165,7 +165,7 @@ private static final class ScopesDefaultEntryHolder { java.lang.String, java.lang.String> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.STRING, @@ -448,18 +448,18 @@ protected Builder newBuilderForType( } /** *
        -   * DEPRECATED
        +   * Deprecated: Use Authorization Code + PKCE or Device Code.
            * 
        * - * Protobuf type {@code a2a.v1.PasswordOAuthFlow} + * Protobuf type {@code lf.a2a.v1.PasswordOAuthFlow} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.PasswordOAuthFlow) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.PasswordOAuthFlow) io.a2a.grpc.PasswordOAuthFlowOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -487,7 +487,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class); } @@ -515,7 +515,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor; } @java.lang.Override @@ -997,10 +997,10 @@ public Builder putAllScopes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.PasswordOAuthFlow) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.PasswordOAuthFlow) } - // @@protoc_insertion_point(class_scope:a2a.v1.PasswordOAuthFlow) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.PasswordOAuthFlow) private static final io.a2a.grpc.PasswordOAuthFlow DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.PasswordOAuthFlow(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java index d319dd1e7..0eab9e995 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface PasswordOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.PasswordOAuthFlow) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.PasswordOAuthFlow) com.google.protobuf.MessageOrBuilder { /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java index 5c23d23ba..e5a4960a4 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:PushNotificationConfig]
          * Configuration for setting up push notifications for task updates.
          * 
        * - * Protobuf type {@code a2a.v1.PushNotificationConfig} + * Protobuf type {@code lf.a2a.v1.PushNotificationConfig} */ @com.google.protobuf.Generated public final class PushNotificationConfig extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.PushNotificationConfig) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.PushNotificationConfig) PushNotificationConfigOrBuilder { private static final long serialVersionUID = 0L; static { @@ -40,13 +39,13 @@ private PushNotificationConfig() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.PushNotificationConfig.class, io.a2a.grpc.PushNotificationConfig.Builder.class); } @@ -57,7 +56,7 @@ private PushNotificationConfig() { private volatile java.lang.Object id_ = ""; /** *
        -   * A unique identifier (e.g. UUID) for this push notification.
        +   * A unique identifier (e.g. UUID) for this push notification configuration.
            * 
        * * string id = 1; @@ -78,7 +77,7 @@ public java.lang.String getId() { } /** *
        -   * A unique identifier (e.g. UUID) for this push notification.
        +   * A unique identifier (e.g. UUID) for this push notification configuration.
            * 
        * * string id = 1; @@ -104,7 +103,7 @@ public java.lang.String getId() { private volatile java.lang.Object url_ = ""; /** *
        -   * Url to send the notification too
        +   * The URL where the notification should be sent.
            * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -125,7 +124,7 @@ public java.lang.String getUrl() { } /** *
        -   * Url to send the notification too
        +   * The URL where the notification should be sent.
            * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -151,7 +150,7 @@ public java.lang.String getUrl() { private volatile java.lang.Object token_ = ""; /** *
        -   * Token unique for this task/session
        +   * A token unique for this task or session.
            * 
        * * string token = 3; @@ -172,7 +171,7 @@ public java.lang.String getToken() { } /** *
        -   * Token unique for this task/session
        +   * A token unique for this task or session.
            * 
        * * string token = 3; @@ -197,10 +196,10 @@ public java.lang.String getToken() { private io.a2a.grpc.AuthenticationInfo authentication_; /** *
        -   * Authentication information required to send the notification
        +   * Authentication information required to send the notification.
            * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; * @return Whether the authentication field is set. */ @java.lang.Override @@ -209,10 +208,10 @@ public boolean hasAuthentication() { } /** *
        -   * Authentication information required to send the notification
        +   * Authentication information required to send the notification.
            * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; * @return The authentication. */ @java.lang.Override @@ -221,10 +220,10 @@ public io.a2a.grpc.AuthenticationInfo getAuthentication() { } /** *
        -   * Authentication information required to send the notification
        +   * Authentication information required to send the notification.
            * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ @java.lang.Override public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { @@ -425,25 +424,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:PushNotificationConfig]
            * Configuration for setting up push notifications for task updates.
            * 
        * - * Protobuf type {@code a2a.v1.PushNotificationConfig} + * Protobuf type {@code lf.a2a.v1.PushNotificationConfig} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.PushNotificationConfig) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.PushNotificationConfig) io.a2a.grpc.PushNotificationConfigOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.PushNotificationConfig.class, io.a2a.grpc.PushNotificationConfig.Builder.class); } @@ -482,7 +480,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_descriptor; } @java.lang.Override @@ -626,7 +624,7 @@ public Builder mergeFrom( private java.lang.Object id_ = ""; /** *
        -     * A unique identifier (e.g. UUID) for this push notification.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
              * 
        * * string id = 1; @@ -646,7 +644,7 @@ public java.lang.String getId() { } /** *
        -     * A unique identifier (e.g. UUID) for this push notification.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
              * 
        * * string id = 1; @@ -667,7 +665,7 @@ public java.lang.String getId() { } /** *
        -     * A unique identifier (e.g. UUID) for this push notification.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
              * 
        * * string id = 1; @@ -684,7 +682,7 @@ public Builder setId( } /** *
        -     * A unique identifier (e.g. UUID) for this push notification.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
              * 
        * * string id = 1; @@ -698,7 +696,7 @@ public Builder clearId() { } /** *
        -     * A unique identifier (e.g. UUID) for this push notification.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
              * 
        * * string id = 1; @@ -718,7 +716,7 @@ public Builder setIdBytes( private java.lang.Object url_ = ""; /** *
        -     * Url to send the notification too
        +     * The URL where the notification should be sent.
              * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -738,7 +736,7 @@ public java.lang.String getUrl() { } /** *
        -     * Url to send the notification too
        +     * The URL where the notification should be sent.
              * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -759,7 +757,7 @@ public java.lang.String getUrl() { } /** *
        -     * Url to send the notification too
        +     * The URL where the notification should be sent.
              * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -776,7 +774,7 @@ public Builder setUrl( } /** *
        -     * Url to send the notification too
        +     * The URL where the notification should be sent.
              * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -790,7 +788,7 @@ public Builder clearUrl() { } /** *
        -     * Url to send the notification too
        +     * The URL where the notification should be sent.
              * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -810,7 +808,7 @@ public Builder setUrlBytes( private java.lang.Object token_ = ""; /** *
        -     * Token unique for this task/session
        +     * A token unique for this task or session.
              * 
        * * string token = 3; @@ -830,7 +828,7 @@ public java.lang.String getToken() { } /** *
        -     * Token unique for this task/session
        +     * A token unique for this task or session.
              * 
        * * string token = 3; @@ -851,7 +849,7 @@ public java.lang.String getToken() { } /** *
        -     * Token unique for this task/session
        +     * A token unique for this task or session.
              * 
        * * string token = 3; @@ -868,7 +866,7 @@ public Builder setToken( } /** *
        -     * Token unique for this task/session
        +     * A token unique for this task or session.
              * 
        * * string token = 3; @@ -882,7 +880,7 @@ public Builder clearToken() { } /** *
        -     * Token unique for this task/session
        +     * A token unique for this task or session.
              * 
        * * string token = 3; @@ -904,10 +902,10 @@ public Builder setTokenBytes( io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> authenticationBuilder_; /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; * @return Whether the authentication field is set. */ public boolean hasAuthentication() { @@ -915,10 +913,10 @@ public boolean hasAuthentication() { } /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; * @return The authentication. */ public io.a2a.grpc.AuthenticationInfo getAuthentication() { @@ -930,10 +928,10 @@ public io.a2a.grpc.AuthenticationInfo getAuthentication() { } /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ public Builder setAuthentication(io.a2a.grpc.AuthenticationInfo value) { if (authenticationBuilder_ == null) { @@ -950,10 +948,10 @@ public Builder setAuthentication(io.a2a.grpc.AuthenticationInfo value) { } /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ public Builder setAuthentication( io.a2a.grpc.AuthenticationInfo.Builder builderForValue) { @@ -968,10 +966,10 @@ public Builder setAuthentication( } /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ public Builder mergeAuthentication(io.a2a.grpc.AuthenticationInfo value) { if (authenticationBuilder_ == null) { @@ -993,10 +991,10 @@ public Builder mergeAuthentication(io.a2a.grpc.AuthenticationInfo value) { } /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ public Builder clearAuthentication() { bitField0_ = (bitField0_ & ~0x00000008); @@ -1010,10 +1008,10 @@ public Builder clearAuthentication() { } /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ public io.a2a.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() { bitField0_ |= 0x00000008; @@ -1022,10 +1020,10 @@ public io.a2a.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() { } /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { if (authenticationBuilder_ != null) { @@ -1037,10 +1035,10 @@ public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { } /** *
        -     * Authentication information required to send the notification
        +     * Authentication information required to send the notification.
              * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> @@ -1056,10 +1054,10 @@ public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { return authenticationBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.PushNotificationConfig) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.PushNotificationConfig) } - // @@protoc_insertion_point(class_scope:a2a.v1.PushNotificationConfig) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.PushNotificationConfig) private static final io.a2a.grpc.PushNotificationConfig DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.PushNotificationConfig(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java index b65c0d5a0..74c6127b1 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java @@ -7,12 +7,12 @@ @com.google.protobuf.Generated public interface PushNotificationConfigOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.PushNotificationConfig) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.PushNotificationConfig) com.google.protobuf.MessageOrBuilder { /** *
        -   * A unique identifier (e.g. UUID) for this push notification.
        +   * A unique identifier (e.g. UUID) for this push notification configuration.
            * 
        * * string id = 1; @@ -21,7 +21,7 @@ public interface PushNotificationConfigOrBuilder extends java.lang.String getId(); /** *
        -   * A unique identifier (e.g. UUID) for this push notification.
        +   * A unique identifier (e.g. UUID) for this push notification configuration.
            * 
        * * string id = 1; @@ -32,7 +32,7 @@ public interface PushNotificationConfigOrBuilder extends /** *
        -   * Url to send the notification too
        +   * The URL where the notification should be sent.
            * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -41,7 +41,7 @@ public interface PushNotificationConfigOrBuilder extends java.lang.String getUrl(); /** *
        -   * Url to send the notification too
        +   * The URL where the notification should be sent.
            * 
        * * string url = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -52,7 +52,7 @@ public interface PushNotificationConfigOrBuilder extends /** *
        -   * Token unique for this task/session
        +   * A token unique for this task or session.
            * 
        * * string token = 3; @@ -61,7 +61,7 @@ public interface PushNotificationConfigOrBuilder extends java.lang.String getToken(); /** *
        -   * Token unique for this task/session
        +   * A token unique for this task or session.
            * 
        * * string token = 3; @@ -72,28 +72,28 @@ public interface PushNotificationConfigOrBuilder extends /** *
        -   * Authentication information required to send the notification
        +   * Authentication information required to send the notification.
            * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; * @return Whether the authentication field is set. */ boolean hasAuthentication(); /** *
        -   * Authentication information required to send the notification
        +   * Authentication information required to send the notification.
            * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; * @return The authentication. */ io.a2a.grpc.AuthenticationInfo getAuthentication(); /** *
        -   * Authentication information required to send the notification
        +   * Authentication information required to send the notification.
            * 
        * - * .a2a.v1.AuthenticationInfo authentication = 4; + * .lf.a2a.v1.AuthenticationInfo authentication = 4; */ io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Role.java b/spec-grpc/src/main/java/io/a2a/grpc/Role.java index 1d8b02c6e..b33496ba1 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/Role.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/Role.java @@ -7,22 +7,25 @@ /** *
        - * --8<-- [start:Role]
          * Defines the sender of a message in A2A protocol communication.
          * 
        * - * Protobuf enum {@code a2a.v1.Role} + * Protobuf enum {@code lf.a2a.v1.Role} */ @com.google.protobuf.Generated public enum Role implements com.google.protobuf.ProtocolMessageEnum { /** + *
        +   * The role is unspecified.
        +   * 
        + * * ROLE_UNSPECIFIED = 0; */ ROLE_UNSPECIFIED(0), /** *
        -   * USER role refers to communication from the client to the server.
        +   * The message is from the client to the server.
            * 
        * * ROLE_USER = 1; @@ -30,7 +33,7 @@ public enum Role ROLE_USER(1), /** *
        -   * AGENT role refers to communication from the server to the client.
        +   * The message is from the server to the client.
            * 
        * * ROLE_AGENT = 2; @@ -49,12 +52,16 @@ public enum Role "Role"); } /** + *
        +   * The role is unspecified.
        +   * 
        + * * ROLE_UNSPECIFIED = 0; */ public static final int ROLE_UNSPECIFIED_VALUE = 0; /** *
        -   * USER role refers to communication from the client to the server.
        +   * The message is from the client to the server.
            * 
        * * ROLE_USER = 1; @@ -62,7 +69,7 @@ public enum Role public static final int ROLE_USER_VALUE = 1; /** *
        -   * AGENT role refers to communication from the server to the client.
        +   * The message is from the server to the client.
            * 
        * * ROLE_AGENT = 2; @@ -150,6 +157,6 @@ private Role(int value) { this.value = value; } - // @@protoc_insertion_point(enum_scope:a2a.v1.Role) + // @@protoc_insertion_point(enum_scope:lf.a2a.v1.Role) } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java index 945b2608d..3208d39a0 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java @@ -6,12 +6,16 @@ package io.a2a.grpc; /** - * Protobuf type {@code a2a.v1.SecurityRequirement} + *
        + * Defines the security requirements for an agent.
        + * 
        + * + * Protobuf type {@code lf.a2a.v1.SecurityRequirement} */ @com.google.protobuf.Generated public final class SecurityRequirement extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SecurityRequirement) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.SecurityRequirement) SecurityRequirementOrBuilder { private static final long serialVersionUID = 0L; static { @@ -32,7 +36,7 @@ private SecurityRequirement() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -50,7 +54,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SecurityRequirement.class, io.a2a.grpc.SecurityRequirement.Builder.class); } @@ -61,7 +65,7 @@ private static final class SchemesDefaultEntryHolder { java.lang.String, io.a2a.grpc.StringList> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, + io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.MESSAGE, @@ -82,7 +86,11 @@ public int getSchemesCount() { return internalGetSchemes().getMap().size(); } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ @java.lang.Override public boolean containsSchemes( @@ -99,14 +107,22 @@ public java.util.Map getSchemes() { return getSchemesMap(); } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ @java.lang.Override public java.util.Map getSchemesMap() { return internalGetSchemes().getMap(); } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ @java.lang.Override public /* nullable */ @@ -120,7 +136,11 @@ io.a2a.grpc.StringList getSchemesOrDefault( return map.containsKey(key) ? map.get(key) : defaultValue; } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ @java.lang.Override public io.a2a.grpc.StringList getSchemesOrThrow( @@ -303,15 +323,19 @@ protected Builder newBuilderForType( return builder; } /** - * Protobuf type {@code a2a.v1.SecurityRequirement} + *
        +   * Defines the security requirements for an agent.
        +   * 
        + * + * Protobuf type {@code lf.a2a.v1.SecurityRequirement} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SecurityRequirement) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SecurityRequirement) io.a2a.grpc.SecurityRequirementOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -339,7 +363,7 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SecurityRequirement.class, io.a2a.grpc.SecurityRequirement.Builder.class); } @@ -365,7 +389,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor; } @java.lang.Override @@ -500,7 +524,11 @@ public int getSchemesCount() { return internalGetSchemes().ensureBuilderMap().size(); } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +     * A map of security schemes to the required scopes.
        +     * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ @java.lang.Override public boolean containsSchemes( @@ -517,14 +545,22 @@ public java.util.Map getSchemes() { return getSchemesMap(); } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +     * A map of security schemes to the required scopes.
        +     * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ @java.lang.Override public java.util.Map getSchemesMap() { return internalGetSchemes().getImmutableMap(); } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +     * A map of security schemes to the required scopes.
        +     * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ @java.lang.Override public /* nullable */ @@ -537,7 +573,11 @@ io.a2a.grpc.StringList getSchemesOrDefault( return map.containsKey(key) ? schemesConverter.build(map.get(key)) : defaultValue; } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +     * A map of security schemes to the required scopes.
        +     * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ @java.lang.Override public io.a2a.grpc.StringList getSchemesOrThrow( @@ -555,7 +595,11 @@ public Builder clearSchemes() { return this; } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +     * A map of security schemes to the required scopes.
        +     * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ public Builder removeSchemes( java.lang.String key) { @@ -574,7 +618,11 @@ public Builder removeSchemes( return internalGetMutableSchemes().ensureMessageMap(); } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +     * A map of security schemes to the required scopes.
        +     * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ public Builder putSchemes( java.lang.String key, @@ -587,7 +635,11 @@ public Builder putSchemes( return this; } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +     * A map of security schemes to the required scopes.
        +     * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ public Builder putAllSchemes( java.util.Map values) { @@ -602,7 +654,11 @@ public Builder putAllSchemes( return this; } /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +     * A map of security schemes to the required scopes.
        +     * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ public io.a2a.grpc.StringList.Builder putSchemesBuilderIfAbsent( java.lang.String key) { @@ -619,10 +675,10 @@ public io.a2a.grpc.StringList.Builder putSchemesBuilderIfAbsent( return (io.a2a.grpc.StringList.Builder) entry; } - // @@protoc_insertion_point(builder_scope:a2a.v1.SecurityRequirement) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.SecurityRequirement) } - // @@protoc_insertion_point(class_scope:a2a.v1.SecurityRequirement) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.SecurityRequirement) private static final io.a2a.grpc.SecurityRequirement DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.SecurityRequirement(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java index 14b23d252..6fe317ba1 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java @@ -7,15 +7,23 @@ @com.google.protobuf.Generated public interface SecurityRequirementOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SecurityRequirement) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.SecurityRequirement) com.google.protobuf.MessageOrBuilder { /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ int getSchemesCount(); /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ boolean containsSchemes( java.lang.String key); @@ -26,12 +34,20 @@ boolean containsSchemes( java.util.Map getSchemes(); /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ java.util.Map getSchemesMap(); /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ /* nullable */ io.a2a.grpc.StringList getSchemesOrDefault( @@ -39,7 +55,11 @@ io.a2a.grpc.StringList getSchemesOrDefault( /* nullable */ io.a2a.grpc.StringList defaultValue); /** - * map<string, .a2a.v1.StringList> schemes = 1; + *
        +   * A map of security schemes to the required scopes.
        +   * 
        + * + * map<string, .lf.a2a.v1.StringList> schemes = 1; */ io.a2a.grpc.StringList getSchemesOrThrow( java.lang.String key); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java index c1202fccf..db9617df3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java @@ -7,18 +7,17 @@ /** *
        - * --8<-- [start:SecurityScheme]
          * Defines a security scheme that can be used to secure an agent's endpoints.
          * This is a discriminated union type based on the OpenAPI 3.2 Security Scheme Object.
          * See: https://spec.openapis.org/oas/v3.2.0.html#security-scheme-object
          * 
        * - * Protobuf type {@code a2a.v1.SecurityScheme} + * Protobuf type {@code lf.a2a.v1.SecurityScheme} */ @com.google.protobuf.Generated public final class SecurityScheme extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SecurityScheme) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.SecurityScheme) SecuritySchemeOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,13 +38,13 @@ private SecurityScheme() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SecurityScheme.class, io.a2a.grpc.SecurityScheme.Builder.class); } @@ -104,7 +103,7 @@ public int getNumber() { * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; * @return Whether the apiKeySecurityScheme field is set. */ @java.lang.Override @@ -116,7 +115,7 @@ public boolean hasApiKeySecurityScheme() { * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; * @return The apiKeySecurityScheme. */ @java.lang.Override @@ -131,7 +130,7 @@ public io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme() { * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ @java.lang.Override public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() { @@ -147,7 +146,7 @@ public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilde * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; * @return Whether the httpAuthSecurityScheme field is set. */ @java.lang.Override @@ -159,7 +158,7 @@ public boolean hasHttpAuthSecurityScheme() { * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; * @return The httpAuthSecurityScheme. */ @java.lang.Override @@ -174,7 +173,7 @@ public io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() { * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ @java.lang.Override public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() { @@ -190,7 +189,7 @@ public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBu * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; * @return Whether the oauth2SecurityScheme field is set. */ @java.lang.Override @@ -202,7 +201,7 @@ public boolean hasOauth2SecurityScheme() { * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; * @return The oauth2SecurityScheme. */ @java.lang.Override @@ -217,7 +216,7 @@ public io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() { * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ @java.lang.Override public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() { @@ -233,7 +232,7 @@ public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilde * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; * @return Whether the openIdConnectSecurityScheme field is set. */ @java.lang.Override @@ -245,7 +244,7 @@ public boolean hasOpenIdConnectSecurityScheme() { * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; * @return The openIdConnectSecurityScheme. */ @java.lang.Override @@ -260,7 +259,7 @@ public io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ @java.lang.Override public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() { @@ -276,7 +275,7 @@ public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecurity * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; * @return Whether the mtlsSecurityScheme field is set. */ @java.lang.Override @@ -288,7 +287,7 @@ public boolean hasMtlsSecurityScheme() { * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; * @return The mtlsSecurityScheme. */ @java.lang.Override @@ -303,7 +302,7 @@ public io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() { * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ @java.lang.Override public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() { @@ -545,27 +544,26 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:SecurityScheme]
            * Defines a security scheme that can be used to secure an agent's endpoints.
            * This is a discriminated union type based on the OpenAPI 3.2 Security Scheme Object.
            * See: https://spec.openapis.org/oas/v3.2.0.html#security-scheme-object
            * 
        * - * Protobuf type {@code a2a.v1.SecurityScheme} + * Protobuf type {@code lf.a2a.v1.SecurityScheme} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SecurityScheme) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SecurityScheme) io.a2a.grpc.SecuritySchemeOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SecurityScheme.class, io.a2a.grpc.SecurityScheme.Builder.class); } @@ -607,7 +605,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor; } @java.lang.Override @@ -799,7 +797,7 @@ public Builder clearScheme() { * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; * @return Whether the apiKeySecurityScheme field is set. */ @java.lang.Override @@ -811,7 +809,7 @@ public boolean hasApiKeySecurityScheme() { * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; * @return The apiKeySecurityScheme. */ @java.lang.Override @@ -833,7 +831,7 @@ public io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme() { * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ public Builder setApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) { if (apiKeySecuritySchemeBuilder_ == null) { @@ -853,7 +851,7 @@ public Builder setApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) { * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ public Builder setApiKeySecurityScheme( io.a2a.grpc.APIKeySecurityScheme.Builder builderForValue) { @@ -871,7 +869,7 @@ public Builder setApiKeySecurityScheme( * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ public Builder mergeApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) { if (apiKeySecuritySchemeBuilder_ == null) { @@ -898,7 +896,7 @@ public Builder mergeApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ public Builder clearApiKeySecurityScheme() { if (apiKeySecuritySchemeBuilder_ == null) { @@ -921,7 +919,7 @@ public Builder clearApiKeySecurityScheme() { * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ public io.a2a.grpc.APIKeySecurityScheme.Builder getApiKeySecuritySchemeBuilder() { return internalGetApiKeySecuritySchemeFieldBuilder().getBuilder(); @@ -931,7 +929,7 @@ public io.a2a.grpc.APIKeySecurityScheme.Builder getApiKeySecuritySchemeBuilder() * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ @java.lang.Override public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() { @@ -949,7 +947,7 @@ public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilde * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.APIKeySecurityScheme, io.a2a.grpc.APIKeySecurityScheme.Builder, io.a2a.grpc.APIKeySecuritySchemeOrBuilder> @@ -977,7 +975,7 @@ public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilde * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; * @return Whether the httpAuthSecurityScheme field is set. */ @java.lang.Override @@ -989,7 +987,7 @@ public boolean hasHttpAuthSecurityScheme() { * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; * @return The httpAuthSecurityScheme. */ @java.lang.Override @@ -1011,7 +1009,7 @@ public io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() { * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ public Builder setHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme value) { if (httpAuthSecuritySchemeBuilder_ == null) { @@ -1031,7 +1029,7 @@ public Builder setHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme valu * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ public Builder setHttpAuthSecurityScheme( io.a2a.grpc.HTTPAuthSecurityScheme.Builder builderForValue) { @@ -1049,7 +1047,7 @@ public Builder setHttpAuthSecurityScheme( * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ public Builder mergeHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme value) { if (httpAuthSecuritySchemeBuilder_ == null) { @@ -1076,7 +1074,7 @@ public Builder mergeHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme va * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ public Builder clearHttpAuthSecurityScheme() { if (httpAuthSecuritySchemeBuilder_ == null) { @@ -1099,7 +1097,7 @@ public Builder clearHttpAuthSecurityScheme() { * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ public io.a2a.grpc.HTTPAuthSecurityScheme.Builder getHttpAuthSecuritySchemeBuilder() { return internalGetHttpAuthSecuritySchemeFieldBuilder().getBuilder(); @@ -1109,7 +1107,7 @@ public io.a2a.grpc.HTTPAuthSecurityScheme.Builder getHttpAuthSecuritySchemeBuild * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ @java.lang.Override public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() { @@ -1127,7 +1125,7 @@ public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBu * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.HTTPAuthSecurityScheme, io.a2a.grpc.HTTPAuthSecurityScheme.Builder, io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder> @@ -1155,7 +1153,7 @@ public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBu * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; * @return Whether the oauth2SecurityScheme field is set. */ @java.lang.Override @@ -1167,7 +1165,7 @@ public boolean hasOauth2SecurityScheme() { * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; * @return The oauth2SecurityScheme. */ @java.lang.Override @@ -1189,7 +1187,7 @@ public io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() { * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ public Builder setOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) { if (oauth2SecuritySchemeBuilder_ == null) { @@ -1209,7 +1207,7 @@ public Builder setOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) { * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ public Builder setOauth2SecurityScheme( io.a2a.grpc.OAuth2SecurityScheme.Builder builderForValue) { @@ -1227,7 +1225,7 @@ public Builder setOauth2SecurityScheme( * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ public Builder mergeOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) { if (oauth2SecuritySchemeBuilder_ == null) { @@ -1254,7 +1252,7 @@ public Builder mergeOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ public Builder clearOauth2SecurityScheme() { if (oauth2SecuritySchemeBuilder_ == null) { @@ -1277,7 +1275,7 @@ public Builder clearOauth2SecurityScheme() { * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ public io.a2a.grpc.OAuth2SecurityScheme.Builder getOauth2SecuritySchemeBuilder() { return internalGetOauth2SecuritySchemeFieldBuilder().getBuilder(); @@ -1287,7 +1285,7 @@ public io.a2a.grpc.OAuth2SecurityScheme.Builder getOauth2SecuritySchemeBuilder() * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ @java.lang.Override public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() { @@ -1305,7 +1303,7 @@ public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilde * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.OAuth2SecurityScheme, io.a2a.grpc.OAuth2SecurityScheme.Builder, io.a2a.grpc.OAuth2SecuritySchemeOrBuilder> @@ -1333,7 +1331,7 @@ public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilde * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; * @return Whether the openIdConnectSecurityScheme field is set. */ @java.lang.Override @@ -1345,7 +1343,7 @@ public boolean hasOpenIdConnectSecurityScheme() { * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; * @return The openIdConnectSecurityScheme. */ @java.lang.Override @@ -1367,7 +1365,7 @@ public io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ public Builder setOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurityScheme value) { if (openIdConnectSecuritySchemeBuilder_ == null) { @@ -1387,7 +1385,7 @@ public Builder setOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurityS * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ public Builder setOpenIdConnectSecurityScheme( io.a2a.grpc.OpenIdConnectSecurityScheme.Builder builderForValue) { @@ -1405,7 +1403,7 @@ public Builder setOpenIdConnectSecurityScheme( * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ public Builder mergeOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurityScheme value) { if (openIdConnectSecuritySchemeBuilder_ == null) { @@ -1432,7 +1430,7 @@ public Builder mergeOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurit * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ public Builder clearOpenIdConnectSecurityScheme() { if (openIdConnectSecuritySchemeBuilder_ == null) { @@ -1455,7 +1453,7 @@ public Builder clearOpenIdConnectSecurityScheme() { * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ public io.a2a.grpc.OpenIdConnectSecurityScheme.Builder getOpenIdConnectSecuritySchemeBuilder() { return internalGetOpenIdConnectSecuritySchemeFieldBuilder().getBuilder(); @@ -1465,7 +1463,7 @@ public io.a2a.grpc.OpenIdConnectSecurityScheme.Builder getOpenIdConnectSecurityS * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ @java.lang.Override public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() { @@ -1483,7 +1481,7 @@ public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecurity * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.OpenIdConnectSecurityScheme, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder, io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder> @@ -1511,7 +1509,7 @@ public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecurity * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; * @return Whether the mtlsSecurityScheme field is set. */ @java.lang.Override @@ -1523,7 +1521,7 @@ public boolean hasMtlsSecurityScheme() { * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; * @return The mtlsSecurityScheme. */ @java.lang.Override @@ -1545,7 +1543,7 @@ public io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() { * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ public Builder setMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value) { if (mtlsSecuritySchemeBuilder_ == null) { @@ -1565,7 +1563,7 @@ public Builder setMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value) * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ public Builder setMtlsSecurityScheme( io.a2a.grpc.MutualTlsSecurityScheme.Builder builderForValue) { @@ -1583,7 +1581,7 @@ public Builder setMtlsSecurityScheme( * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ public Builder mergeMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value) { if (mtlsSecuritySchemeBuilder_ == null) { @@ -1610,7 +1608,7 @@ public Builder mergeMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ public Builder clearMtlsSecurityScheme() { if (mtlsSecuritySchemeBuilder_ == null) { @@ -1633,7 +1631,7 @@ public Builder clearMtlsSecurityScheme() { * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ public io.a2a.grpc.MutualTlsSecurityScheme.Builder getMtlsSecuritySchemeBuilder() { return internalGetMtlsSecuritySchemeFieldBuilder().getBuilder(); @@ -1643,7 +1641,7 @@ public io.a2a.grpc.MutualTlsSecurityScheme.Builder getMtlsSecuritySchemeBuilder( * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ @java.lang.Override public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() { @@ -1661,7 +1659,7 @@ public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuild * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.MutualTlsSecurityScheme, io.a2a.grpc.MutualTlsSecurityScheme.Builder, io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder> @@ -1682,10 +1680,10 @@ public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuild return mtlsSecuritySchemeBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.SecurityScheme) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.SecurityScheme) } - // @@protoc_insertion_point(class_scope:a2a.v1.SecurityScheme) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.SecurityScheme) private static final io.a2a.grpc.SecurityScheme DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.SecurityScheme(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java index 6a5d92b7c..c76a1b560 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface SecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SecurityScheme) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.SecurityScheme) com.google.protobuf.MessageOrBuilder { /** @@ -15,7 +15,7 @@ public interface SecuritySchemeOrBuilder extends * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; * @return Whether the apiKeySecurityScheme field is set. */ boolean hasApiKeySecurityScheme(); @@ -24,7 +24,7 @@ public interface SecuritySchemeOrBuilder extends * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; * @return The apiKeySecurityScheme. */ io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme(); @@ -33,7 +33,7 @@ public interface SecuritySchemeOrBuilder extends * API key-based authentication. * * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; */ io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder(); @@ -42,7 +42,7 @@ public interface SecuritySchemeOrBuilder extends * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; * @return Whether the httpAuthSecurityScheme field is set. */ boolean hasHttpAuthSecurityScheme(); @@ -51,7 +51,7 @@ public interface SecuritySchemeOrBuilder extends * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; * @return The httpAuthSecurityScheme. */ io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme(); @@ -60,7 +60,7 @@ public interface SecuritySchemeOrBuilder extends * HTTP authentication (Basic, Bearer, etc.). * * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; */ io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder(); @@ -69,7 +69,7 @@ public interface SecuritySchemeOrBuilder extends * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; * @return Whether the oauth2SecurityScheme field is set. */ boolean hasOauth2SecurityScheme(); @@ -78,7 +78,7 @@ public interface SecuritySchemeOrBuilder extends * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; * @return The oauth2SecurityScheme. */ io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme(); @@ -87,7 +87,7 @@ public interface SecuritySchemeOrBuilder extends * OAuth 2.0 authentication. * * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; */ io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder(); @@ -96,7 +96,7 @@ public interface SecuritySchemeOrBuilder extends * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; * @return Whether the openIdConnectSecurityScheme field is set. */ boolean hasOpenIdConnectSecurityScheme(); @@ -105,7 +105,7 @@ public interface SecuritySchemeOrBuilder extends * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; * @return The openIdConnectSecurityScheme. */ io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme(); @@ -114,7 +114,7 @@ public interface SecuritySchemeOrBuilder extends * OpenID Connect authentication. * * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; */ io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder(); @@ -123,7 +123,7 @@ public interface SecuritySchemeOrBuilder extends * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; * @return Whether the mtlsSecurityScheme field is set. */ boolean hasMtlsSecurityScheme(); @@ -132,7 +132,7 @@ public interface SecuritySchemeOrBuilder extends * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; * @return The mtlsSecurityScheme. */ io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme(); @@ -141,7 +141,7 @@ public interface SecuritySchemeOrBuilder extends * Mutual TLS authentication. * * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; */ io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java index 57374039f..f89c54f1a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:SendMessageConfiguration]
          * Configuration of a send message request.
          * 
        * - * Protobuf type {@code a2a.v1.SendMessageConfiguration} + * Protobuf type {@code lf.a2a.v1.SendMessageConfiguration} */ @com.google.protobuf.Generated public final class SendMessageConfiguration extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageConfiguration) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.SendMessageConfiguration) SendMessageConfigurationOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,13 +38,13 @@ private SendMessageConfiguration() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SendMessageConfiguration.class, io.a2a.grpc.SendMessageConfiguration.Builder.class); } @@ -57,7 +56,8 @@ private SendMessageConfiguration() { com.google.protobuf.LazyStringArrayList.emptyList(); /** *
        -   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +   * A list of media types the client is prepared to accept for response parts.
        +   * Agents SHOULD use this to tailor their output.
            * 
        * * repeated string accepted_output_modes = 1; @@ -69,7 +69,8 @@ private SendMessageConfiguration() { } /** *
        -   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +   * A list of media types the client is prepared to accept for response parts.
        +   * Agents SHOULD use this to tailor their output.
            * 
        * * repeated string accepted_output_modes = 1; @@ -80,7 +81,8 @@ public int getAcceptedOutputModesCount() { } /** *
        -   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +   * A list of media types the client is prepared to accept for response parts.
        +   * Agents SHOULD use this to tailor their output.
            * 
        * * repeated string accepted_output_modes = 1; @@ -92,7 +94,8 @@ public java.lang.String getAcceptedOutputModes(int index) { } /** *
        -   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +   * A list of media types the client is prepared to accept for response parts.
        +   * Agents SHOULD use this to tailor their output.
            * 
        * * repeated string accepted_output_modes = 1; @@ -111,7 +114,7 @@ public java.lang.String getAcceptedOutputModes(int index) { * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; * @return Whether the pushNotificationConfig field is set. */ @java.lang.Override @@ -123,7 +126,7 @@ public boolean hasPushNotificationConfig() { * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; * @return The pushNotificationConfig. */ @java.lang.Override @@ -135,7 +138,7 @@ public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ @java.lang.Override public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { @@ -179,7 +182,9 @@ public int getHistoryLength() { private boolean blocking_ = false; /** *
        -   * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
        +   * If `true`, the operation MUST wait until the task reaches a terminal state
        +   * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        +   * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
            * 
        * * bool blocking = 4; @@ -399,25 +404,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:SendMessageConfiguration]
            * Configuration of a send message request.
            * 
        * - * Protobuf type {@code a2a.v1.SendMessageConfiguration} + * Protobuf type {@code lf.a2a.v1.SendMessageConfiguration} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageConfiguration) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SendMessageConfiguration) io.a2a.grpc.SendMessageConfigurationOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SendMessageConfiguration.class, io.a2a.grpc.SendMessageConfiguration.Builder.class); } @@ -457,7 +461,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor; } @java.lang.Override @@ -612,7 +616,8 @@ private void ensureAcceptedOutputModesIsMutable() { } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -625,7 +630,8 @@ private void ensureAcceptedOutputModesIsMutable() { } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -636,7 +642,8 @@ public int getAcceptedOutputModesCount() { } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -648,7 +655,8 @@ public java.lang.String getAcceptedOutputModes(int index) { } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -661,7 +669,8 @@ public java.lang.String getAcceptedOutputModes(int index) { } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -680,7 +689,8 @@ public Builder setAcceptedOutputModes( } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -698,7 +708,8 @@ public Builder addAcceptedOutputModes( } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -716,7 +727,8 @@ public Builder addAllAcceptedOutputModes( } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -731,7 +743,8 @@ public Builder clearAcceptedOutputModes() { } /** *
        -     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +     * A list of media types the client is prepared to accept for response parts.
        +     * Agents SHOULD use this to tailor their output.
              * 
        * * repeated string accepted_output_modes = 1; @@ -757,7 +770,7 @@ public Builder addAcceptedOutputModesBytes( * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; * @return Whether the pushNotificationConfig field is set. */ public boolean hasPushNotificationConfig() { @@ -768,7 +781,7 @@ public boolean hasPushNotificationConfig() { * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; * @return The pushNotificationConfig. */ public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { @@ -783,7 +796,7 @@ public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { if (pushNotificationConfigBuilder_ == null) { @@ -803,7 +816,7 @@ public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig valu * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ public Builder setPushNotificationConfig( io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { @@ -821,7 +834,7 @@ public Builder setPushNotificationConfig( * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { if (pushNotificationConfigBuilder_ == null) { @@ -846,7 +859,7 @@ public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig va * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ public Builder clearPushNotificationConfig() { bitField0_ = (bitField0_ & ~0x00000002); @@ -863,7 +876,7 @@ public Builder clearPushNotificationConfig() { * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuilder() { bitField0_ |= 0x00000002; @@ -875,7 +888,7 @@ public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuild * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { if (pushNotificationConfigBuilder_ != null) { @@ -890,7 +903,7 @@ public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBu * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> @@ -977,7 +990,9 @@ public Builder clearHistoryLength() { private boolean blocking_ ; /** *
        -     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
        +     * If `true`, the operation MUST wait until the task reaches a terminal state
        +     * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        +     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
              * 
        * * bool blocking = 4; @@ -989,7 +1004,9 @@ public boolean getBlocking() { } /** *
        -     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
        +     * If `true`, the operation MUST wait until the task reaches a terminal state
        +     * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        +     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
              * 
        * * bool blocking = 4; @@ -1005,7 +1022,9 @@ public Builder setBlocking(boolean value) { } /** *
        -     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
        +     * If `true`, the operation MUST wait until the task reaches a terminal state
        +     * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        +     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
              * 
        * * bool blocking = 4; @@ -1018,10 +1037,10 @@ public Builder clearBlocking() { return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageConfiguration) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.SendMessageConfiguration) } - // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageConfiguration) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.SendMessageConfiguration) private static final io.a2a.grpc.SendMessageConfiguration DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageConfiguration(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java index a9e9fc401..555708a45 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java @@ -7,12 +7,13 @@ @com.google.protobuf.Generated public interface SendMessageConfigurationOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageConfiguration) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.SendMessageConfiguration) com.google.protobuf.MessageOrBuilder { /** *
        -   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +   * A list of media types the client is prepared to accept for response parts.
        +   * Agents SHOULD use this to tailor their output.
            * 
        * * repeated string accepted_output_modes = 1; @@ -22,7 +23,8 @@ public interface SendMessageConfigurationOrBuilder extends getAcceptedOutputModesList(); /** *
        -   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +   * A list of media types the client is prepared to accept for response parts.
        +   * Agents SHOULD use this to tailor their output.
            * 
        * * repeated string accepted_output_modes = 1; @@ -31,7 +33,8 @@ public interface SendMessageConfigurationOrBuilder extends int getAcceptedOutputModesCount(); /** *
        -   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +   * A list of media types the client is prepared to accept for response parts.
        +   * Agents SHOULD use this to tailor their output.
            * 
        * * repeated string accepted_output_modes = 1; @@ -41,7 +44,8 @@ public interface SendMessageConfigurationOrBuilder extends java.lang.String getAcceptedOutputModes(int index); /** *
        -   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
        +   * A list of media types the client is prepared to accept for response parts.
        +   * Agents SHOULD use this to tailor their output.
            * 
        * * repeated string accepted_output_modes = 1; @@ -56,7 +60,7 @@ public interface SendMessageConfigurationOrBuilder extends * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; * @return Whether the pushNotificationConfig field is set. */ boolean hasPushNotificationConfig(); @@ -65,7 +69,7 @@ public interface SendMessageConfigurationOrBuilder extends * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; * @return The pushNotificationConfig. */ io.a2a.grpc.PushNotificationConfig getPushNotificationConfig(); @@ -74,7 +78,7 @@ public interface SendMessageConfigurationOrBuilder extends * Configuration for the agent to send push notifications for task updates. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; */ io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder(); @@ -105,7 +109,9 @@ public interface SendMessageConfigurationOrBuilder extends /** *
        -   * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
        +   * If `true`, the operation MUST wait until the task reaches a terminal state
        +   * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        +   * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
            * 
        * * bool blocking = 4; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java index 943fc6067..c629f23d5 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java @@ -7,17 +7,15 @@ /** *
        - * /////////// Request Messages ///////////
        - * --8<-- [start:SendMessageRequest]
          * Represents a request for the `SendMessage` method.
          * 
        * - * Protobuf type {@code a2a.v1.SendMessageRequest} + * Protobuf type {@code lf.a2a.v1.SendMessageRequest} */ @com.google.protobuf.Generated public final class SendMessageRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.SendMessageRequest) SendMessageRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -39,27 +37,27 @@ private SendMessageRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SendMessageRequest.class, io.a2a.grpc.SendMessageRequest.Builder.class); } private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 4; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -77,10 +75,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -98,14 +96,14 @@ public java.lang.String getTenant() { } } - public static final int MESSAGE_FIELD_NUMBER = 1; + public static final int MESSAGE_FIELD_NUMBER = 2; private io.a2a.grpc.Message message_; /** *
            * The message to send to the agent.
            * 
        * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the message field is set. */ @java.lang.Override @@ -117,7 +115,7 @@ public boolean hasMessage() { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The message. */ @java.lang.Override @@ -129,21 +127,21 @@ public io.a2a.grpc.Message getMessage() { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; } - public static final int CONFIGURATION_FIELD_NUMBER = 2; + public static final int CONFIGURATION_FIELD_NUMBER = 3; private io.a2a.grpc.SendMessageConfiguration configuration_; /** *
            * Configuration for the send request.
            * 
        * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; * @return Whether the configuration field is set. */ @java.lang.Override @@ -155,7 +153,7 @@ public boolean hasConfiguration() { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; * @return The configuration. */ @java.lang.Override @@ -167,21 +165,21 @@ public io.a2a.grpc.SendMessageConfiguration getConfiguration() { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ @java.lang.Override public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() { return configuration_ == null ? io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; } - public static final int METADATA_FIELD_NUMBER = 3; + public static final int METADATA_FIELD_NUMBER = 4; private com.google.protobuf.Struct metadata_; /** *
            * A flexible key-value map for passing additional context or parameters.
            * 
        * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; * @return Whether the metadata field is set. */ @java.lang.Override @@ -193,7 +191,7 @@ public boolean hasMetadata() { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; * @return The metadata. */ @java.lang.Override @@ -205,7 +203,7 @@ public com.google.protobuf.Struct getMetadata() { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ @java.lang.Override public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { @@ -226,17 +224,17 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); + } if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(1, getMessage()); + output.writeMessage(2, getMessage()); } if (((bitField0_ & 0x00000002) != 0)) { - output.writeMessage(2, getConfiguration()); + output.writeMessage(3, getConfiguration()); } if (((bitField0_ & 0x00000004) != 0)) { - output.writeMessage(3, getMetadata()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); + output.writeMessage(4, getMetadata()); } getUnknownFields().writeTo(output); } @@ -247,20 +245,20 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); + } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, getMessage()); + .computeMessageSize(2, getMessage()); } if (((bitField0_ & 0x00000002) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getConfiguration()); + .computeMessageSize(3, getConfiguration()); } if (((bitField0_ & 0x00000004) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getMetadata()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); + .computeMessageSize(4, getMetadata()); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -418,26 +416,24 @@ protected Builder newBuilderForType( } /** *
        -   * /////////// Request Messages ///////////
        -   * --8<-- [start:SendMessageRequest]
            * Represents a request for the `SendMessage` method.
            * 
        * - * Protobuf type {@code a2a.v1.SendMessageRequest} + * Protobuf type {@code lf.a2a.v1.SendMessageRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SendMessageRequest) io.a2a.grpc.SendMessageRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SendMessageRequest.class, io.a2a.grpc.SendMessageRequest.Builder.class); } @@ -486,7 +482,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor; } @java.lang.Override @@ -591,30 +587,30 @@ public Builder mergeFrom( done = true; break; case 10: { + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { input.readMessage( internalGetMessageFieldBuilder().getBuilder(), extensionRegistry); bitField0_ |= 0x00000002; break; - } // case 10 - case 18: { + } // case 18 + case 26: { input.readMessage( internalGetConfigurationFieldBuilder().getBuilder(), extensionRegistry); bitField0_ |= 0x00000004; break; - } // case 18 - case 26: { + } // case 26 + case 34: { input.readMessage( internalGetMetadataFieldBuilder().getBuilder(), extensionRegistry); bitField0_ |= 0x00000008; break; - } // case 26 - case 34: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { @@ -636,10 +632,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -656,10 +652,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -677,10 +673,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -694,10 +690,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -708,10 +704,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -733,7 +729,7 @@ public Builder setTenantBytes( * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the message field is set. */ public boolean hasMessage() { @@ -744,7 +740,7 @@ public boolean hasMessage() { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The message. */ public io.a2a.grpc.Message getMessage() { @@ -759,7 +755,7 @@ public io.a2a.grpc.Message getMessage() { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setMessage(io.a2a.grpc.Message value) { if (messageBuilder_ == null) { @@ -779,7 +775,7 @@ public Builder setMessage(io.a2a.grpc.Message value) { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setMessage( io.a2a.grpc.Message.Builder builderForValue) { @@ -797,7 +793,7 @@ public Builder setMessage( * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ public Builder mergeMessage(io.a2a.grpc.Message value) { if (messageBuilder_ == null) { @@ -822,7 +818,7 @@ public Builder mergeMessage(io.a2a.grpc.Message value) { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearMessage() { bitField0_ = (bitField0_ & ~0x00000002); @@ -839,7 +835,7 @@ public Builder clearMessage() { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Message.Builder getMessageBuilder() { bitField0_ |= 0x00000002; @@ -851,7 +847,7 @@ public io.a2a.grpc.Message.Builder getMessageBuilder() { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { if (messageBuilder_ != null) { @@ -866,7 +862,7 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> @@ -890,7 +886,7 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; * @return Whether the configuration field is set. */ public boolean hasConfiguration() { @@ -901,7 +897,7 @@ public boolean hasConfiguration() { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; * @return The configuration. */ public io.a2a.grpc.SendMessageConfiguration getConfiguration() { @@ -916,7 +912,7 @@ public io.a2a.grpc.SendMessageConfiguration getConfiguration() { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ public Builder setConfiguration(io.a2a.grpc.SendMessageConfiguration value) { if (configurationBuilder_ == null) { @@ -936,7 +932,7 @@ public Builder setConfiguration(io.a2a.grpc.SendMessageConfiguration value) { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ public Builder setConfiguration( io.a2a.grpc.SendMessageConfiguration.Builder builderForValue) { @@ -954,7 +950,7 @@ public Builder setConfiguration( * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ public Builder mergeConfiguration(io.a2a.grpc.SendMessageConfiguration value) { if (configurationBuilder_ == null) { @@ -979,7 +975,7 @@ public Builder mergeConfiguration(io.a2a.grpc.SendMessageConfiguration value) { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ public Builder clearConfiguration() { bitField0_ = (bitField0_ & ~0x00000004); @@ -996,7 +992,7 @@ public Builder clearConfiguration() { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ public io.a2a.grpc.SendMessageConfiguration.Builder getConfigurationBuilder() { bitField0_ |= 0x00000004; @@ -1008,7 +1004,7 @@ public io.a2a.grpc.SendMessageConfiguration.Builder getConfigurationBuilder() { * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() { if (configurationBuilder_ != null) { @@ -1023,7 +1019,7 @@ public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.SendMessageConfiguration, io.a2a.grpc.SendMessageConfiguration.Builder, io.a2a.grpc.SendMessageConfigurationOrBuilder> @@ -1047,7 +1043,7 @@ public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; * @return Whether the metadata field is set. */ public boolean hasMetadata() { @@ -1058,7 +1054,7 @@ public boolean hasMetadata() { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; * @return The metadata. */ public com.google.protobuf.Struct getMetadata() { @@ -1073,7 +1069,7 @@ public com.google.protobuf.Struct getMetadata() { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ public Builder setMetadata(com.google.protobuf.Struct value) { if (metadataBuilder_ == null) { @@ -1093,7 +1089,7 @@ public Builder setMetadata(com.google.protobuf.Struct value) { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ public Builder setMetadata( com.google.protobuf.Struct.Builder builderForValue) { @@ -1111,7 +1107,7 @@ public Builder setMetadata( * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ public Builder mergeMetadata(com.google.protobuf.Struct value) { if (metadataBuilder_ == null) { @@ -1136,7 +1132,7 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ public Builder clearMetadata() { bitField0_ = (bitField0_ & ~0x00000008); @@ -1153,7 +1149,7 @@ public Builder clearMetadata() { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ public com.google.protobuf.Struct.Builder getMetadataBuilder() { bitField0_ |= 0x00000008; @@ -1165,7 +1161,7 @@ public com.google.protobuf.Struct.Builder getMetadataBuilder() { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { if (metadataBuilder_ != null) { @@ -1180,7 +1176,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ private com.google.protobuf.SingleFieldBuilder< com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> @@ -1196,10 +1192,10 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { return metadataBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.SendMessageRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.SendMessageRequest) private static final io.a2a.grpc.SendMessageRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java index de2e6cc12..5adba7a8a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface SendMessageRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.SendMessageRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -35,7 +35,7 @@ public interface SendMessageRequestOrBuilder extends * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the message field is set. */ boolean hasMessage(); @@ -44,7 +44,7 @@ public interface SendMessageRequestOrBuilder extends * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The message. */ io.a2a.grpc.Message getMessage(); @@ -53,7 +53,7 @@ public interface SendMessageRequestOrBuilder extends * The message to send to the agent. * * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); @@ -62,7 +62,7 @@ public interface SendMessageRequestOrBuilder extends * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; * @return Whether the configuration field is set. */ boolean hasConfiguration(); @@ -71,7 +71,7 @@ public interface SendMessageRequestOrBuilder extends * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; * @return The configuration. */ io.a2a.grpc.SendMessageConfiguration getConfiguration(); @@ -80,7 +80,7 @@ public interface SendMessageRequestOrBuilder extends * Configuration for the send request. * * - * .a2a.v1.SendMessageConfiguration configuration = 2; + * .lf.a2a.v1.SendMessageConfiguration configuration = 3; */ io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder(); @@ -89,7 +89,7 @@ public interface SendMessageRequestOrBuilder extends * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; * @return Whether the metadata field is set. */ boolean hasMetadata(); @@ -98,7 +98,7 @@ public interface SendMessageRequestOrBuilder extends * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; * @return The metadata. */ com.google.protobuf.Struct getMetadata(); @@ -107,7 +107,7 @@ public interface SendMessageRequestOrBuilder extends * A flexible key-value map for passing additional context or parameters. * * - * .google.protobuf.Struct metadata = 3; + * .google.protobuf.Struct metadata = 4; */ com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java index 466f2206a..b848b65e1 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java @@ -7,16 +7,15 @@ /** *
        - * ////// Response Messages ///////////
        - * --8<-- [start:SendMessageResponse]
        + * Represents the response for the `SendMessage` method.
          * 
        * - * Protobuf type {@code a2a.v1.SendMessageResponse} + * Protobuf type {@code lf.a2a.v1.SendMessageResponse} */ @com.google.protobuf.Generated public final class SendMessageResponse extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageResponse) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.SendMessageResponse) SendMessageResponseOrBuilder { private static final long serialVersionUID = 0L; static { @@ -37,13 +36,13 @@ private SendMessageResponse() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SendMessageResponse.class, io.a2a.grpc.SendMessageResponse.Builder.class); } @@ -92,7 +91,11 @@ public int getNumber() { public static final int TASK_FIELD_NUMBER = 1; /** - * .a2a.v1.Task task = 1; + *
        +   * The task created or updated by the message.
        +   * 
        + * + * .lf.a2a.v1.Task task = 1; * @return Whether the task field is set. */ @java.lang.Override @@ -100,7 +103,11 @@ public boolean hasTask() { return payloadCase_ == 1; } /** - * .a2a.v1.Task task = 1; + *
        +   * The task created or updated by the message.
        +   * 
        + * + * .lf.a2a.v1.Task task = 1; * @return The task. */ @java.lang.Override @@ -111,7 +118,11 @@ public io.a2a.grpc.Task getTask() { return io.a2a.grpc.Task.getDefaultInstance(); } /** - * .a2a.v1.Task task = 1; + *
        +   * The task created or updated by the message.
        +   * 
        + * + * .lf.a2a.v1.Task task = 1; */ @java.lang.Override public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { @@ -123,7 +134,11 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { public static final int MESSAGE_FIELD_NUMBER = 2; /** - * .a2a.v1.Message message = 2; + *
        +   * A message from the agent.
        +   * 
        + * + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ @java.lang.Override @@ -131,7 +146,11 @@ public boolean hasMessage() { return payloadCase_ == 2; } /** - * .a2a.v1.Message message = 2; + *
        +   * A message from the agent.
        +   * 
        + * + * .lf.a2a.v1.Message message = 2; * @return The message. */ @java.lang.Override @@ -142,7 +161,11 @@ public io.a2a.grpc.Message getMessage() { return io.a2a.grpc.Message.getDefaultInstance(); } /** - * .a2a.v1.Message message = 2; + *
        +   * A message from the agent.
        +   * 
        + * + * .lf.a2a.v1.Message message = 2; */ @java.lang.Override public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { @@ -339,25 +362,24 @@ protected Builder newBuilderForType( } /** *
        -   * ////// Response Messages ///////////
        -   * --8<-- [start:SendMessageResponse]
        +   * Represents the response for the `SendMessage` method.
            * 
        * - * Protobuf type {@code a2a.v1.SendMessageResponse} + * Protobuf type {@code lf.a2a.v1.SendMessageResponse} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageResponse) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SendMessageResponse) io.a2a.grpc.SendMessageResponseOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SendMessageResponse.class, io.a2a.grpc.SendMessageResponse.Builder.class); } @@ -390,7 +412,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor; } @java.lang.Override @@ -533,7 +555,11 @@ public Builder clearPayload() { private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> taskBuilder_; /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; * @return Whether the task field is set. */ @java.lang.Override @@ -541,7 +567,11 @@ public boolean hasTask() { return payloadCase_ == 1; } /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; * @return The task. */ @java.lang.Override @@ -559,7 +589,11 @@ public io.a2a.grpc.Task getTask() { } } /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; */ public Builder setTask(io.a2a.grpc.Task value) { if (taskBuilder_ == null) { @@ -575,7 +609,11 @@ public Builder setTask(io.a2a.grpc.Task value) { return this; } /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; */ public Builder setTask( io.a2a.grpc.Task.Builder builderForValue) { @@ -589,7 +627,11 @@ public Builder setTask( return this; } /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; */ public Builder mergeTask(io.a2a.grpc.Task value) { if (taskBuilder_ == null) { @@ -612,7 +654,11 @@ public Builder mergeTask(io.a2a.grpc.Task value) { return this; } /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; */ public Builder clearTask() { if (taskBuilder_ == null) { @@ -631,13 +677,21 @@ public Builder clearTask() { return this; } /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; */ public io.a2a.grpc.Task.Builder getTaskBuilder() { return internalGetTaskFieldBuilder().getBuilder(); } /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; */ @java.lang.Override public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { @@ -651,7 +705,11 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { } } /** - * .a2a.v1.Task task = 1; + *
        +     * The task created or updated by the message.
        +     * 
        + * + * .lf.a2a.v1.Task task = 1; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> @@ -675,7 +733,11 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_; /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ @java.lang.Override @@ -683,7 +745,11 @@ public boolean hasMessage() { return payloadCase_ == 2; } /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; * @return The message. */ @java.lang.Override @@ -701,7 +767,11 @@ public io.a2a.grpc.Message getMessage() { } } /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; */ public Builder setMessage(io.a2a.grpc.Message value) { if (messageBuilder_ == null) { @@ -717,7 +787,11 @@ public Builder setMessage(io.a2a.grpc.Message value) { return this; } /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; */ public Builder setMessage( io.a2a.grpc.Message.Builder builderForValue) { @@ -731,7 +805,11 @@ public Builder setMessage( return this; } /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; */ public Builder mergeMessage(io.a2a.grpc.Message value) { if (messageBuilder_ == null) { @@ -754,7 +832,11 @@ public Builder mergeMessage(io.a2a.grpc.Message value) { return this; } /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; */ public Builder clearMessage() { if (messageBuilder_ == null) { @@ -773,13 +855,21 @@ public Builder clearMessage() { return this; } /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; */ public io.a2a.grpc.Message.Builder getMessageBuilder() { return internalGetMessageFieldBuilder().getBuilder(); } /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; */ @java.lang.Override public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { @@ -793,7 +883,11 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { } } /** - * .a2a.v1.Message message = 2; + *
        +     * A message from the agent.
        +     * 
        + * + * .lf.a2a.v1.Message message = 2; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> @@ -814,10 +908,10 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { return messageBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageResponse) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.SendMessageResponse) } - // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageResponse) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.SendMessageResponse) private static final io.a2a.grpc.SendMessageResponse DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageResponse(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java index 355131b71..9e56a7c36 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java @@ -7,36 +7,60 @@ @com.google.protobuf.Generated public interface SendMessageResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageResponse) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.SendMessageResponse) com.google.protobuf.MessageOrBuilder { /** - * .a2a.v1.Task task = 1; + *
        +   * The task created or updated by the message.
        +   * 
        + * + * .lf.a2a.v1.Task task = 1; * @return Whether the task field is set. */ boolean hasTask(); /** - * .a2a.v1.Task task = 1; + *
        +   * The task created or updated by the message.
        +   * 
        + * + * .lf.a2a.v1.Task task = 1; * @return The task. */ io.a2a.grpc.Task getTask(); /** - * .a2a.v1.Task task = 1; + *
        +   * The task created or updated by the message.
        +   * 
        + * + * .lf.a2a.v1.Task task = 1; */ io.a2a.grpc.TaskOrBuilder getTaskOrBuilder(); /** - * .a2a.v1.Message message = 2; + *
        +   * A message from the agent.
        +   * 
        + * + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ boolean hasMessage(); /** - * .a2a.v1.Message message = 2; + *
        +   * A message from the agent.
        +   * 
        + * + * .lf.a2a.v1.Message message = 2; * @return The message. */ io.a2a.grpc.Message getMessage(); /** - * .a2a.v1.Message message = 2; + *
        +   * A message from the agent.
        +   * 
        + * + * .lf.a2a.v1.Message message = 2; */ io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java index 3d27db5ef..7ed30be81 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:StreamResponse]
          * A wrapper object used in streaming operations to encapsulate different types of response data.
          * 
        * - * Protobuf type {@code a2a.v1.StreamResponse} + * Protobuf type {@code lf.a2a.v1.StreamResponse} */ @com.google.protobuf.Generated public final class StreamResponse extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.StreamResponse) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.StreamResponse) StreamResponseOrBuilder { private static final long serialVersionUID = 0L; static { @@ -37,13 +36,13 @@ private StreamResponse() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.StreamResponse.class, io.a2a.grpc.StreamResponse.Builder.class); } @@ -100,7 +99,7 @@ public int getNumber() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; * @return Whether the task field is set. */ @java.lang.Override @@ -112,7 +111,7 @@ public boolean hasTask() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; * @return The task. */ @java.lang.Override @@ -127,7 +126,7 @@ public io.a2a.grpc.Task getTask() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ @java.lang.Override public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { @@ -143,7 +142,7 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ @java.lang.Override @@ -155,7 +154,7 @@ public boolean hasMessage() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return The message. */ @java.lang.Override @@ -170,7 +169,7 @@ public io.a2a.grpc.Message getMessage() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ @java.lang.Override public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { @@ -186,7 +185,7 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; * @return Whether the statusUpdate field is set. */ @java.lang.Override @@ -198,7 +197,7 @@ public boolean hasStatusUpdate() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; * @return The statusUpdate. */ @java.lang.Override @@ -213,7 +212,7 @@ public io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ @java.lang.Override public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { @@ -229,7 +228,7 @@ public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; * @return Whether the artifactUpdate field is set. */ @java.lang.Override @@ -241,7 +240,7 @@ public boolean hasArtifactUpdate() { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; * @return The artifactUpdate. */ @java.lang.Override @@ -256,7 +255,7 @@ public io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate() { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ @java.lang.Override public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() { @@ -483,25 +482,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:StreamResponse]
            * A wrapper object used in streaming operations to encapsulate different types of response data.
            * 
        * - * Protobuf type {@code a2a.v1.StreamResponse} + * Protobuf type {@code lf.a2a.v1.StreamResponse} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.StreamResponse) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.StreamResponse) io.a2a.grpc.StreamResponseOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.StreamResponse.class, io.a2a.grpc.StreamResponse.Builder.class); } @@ -540,7 +538,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor; } @java.lang.Override @@ -717,7 +715,7 @@ public Builder clearPayload() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; * @return Whether the task field is set. */ @java.lang.Override @@ -729,7 +727,7 @@ public boolean hasTask() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; * @return The task. */ @java.lang.Override @@ -751,7 +749,7 @@ public io.a2a.grpc.Task getTask() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ public Builder setTask(io.a2a.grpc.Task value) { if (taskBuilder_ == null) { @@ -771,7 +769,7 @@ public Builder setTask(io.a2a.grpc.Task value) { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ public Builder setTask( io.a2a.grpc.Task.Builder builderForValue) { @@ -789,7 +787,7 @@ public Builder setTask( * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ public Builder mergeTask(io.a2a.grpc.Task value) { if (taskBuilder_ == null) { @@ -816,7 +814,7 @@ public Builder mergeTask(io.a2a.grpc.Task value) { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ public Builder clearTask() { if (taskBuilder_ == null) { @@ -839,7 +837,7 @@ public Builder clearTask() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ public io.a2a.grpc.Task.Builder getTaskBuilder() { return internalGetTaskFieldBuilder().getBuilder(); @@ -849,7 +847,7 @@ public io.a2a.grpc.Task.Builder getTaskBuilder() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ @java.lang.Override public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { @@ -867,7 +865,7 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> @@ -895,7 +893,7 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ @java.lang.Override @@ -907,7 +905,7 @@ public boolean hasMessage() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return The message. */ @java.lang.Override @@ -929,7 +927,7 @@ public io.a2a.grpc.Message getMessage() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public Builder setMessage(io.a2a.grpc.Message value) { if (messageBuilder_ == null) { @@ -949,7 +947,7 @@ public Builder setMessage(io.a2a.grpc.Message value) { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public Builder setMessage( io.a2a.grpc.Message.Builder builderForValue) { @@ -967,7 +965,7 @@ public Builder setMessage( * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public Builder mergeMessage(io.a2a.grpc.Message value) { if (messageBuilder_ == null) { @@ -994,7 +992,7 @@ public Builder mergeMessage(io.a2a.grpc.Message value) { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public Builder clearMessage() { if (messageBuilder_ == null) { @@ -1017,7 +1015,7 @@ public Builder clearMessage() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public io.a2a.grpc.Message.Builder getMessageBuilder() { return internalGetMessageFieldBuilder().getBuilder(); @@ -1027,7 +1025,7 @@ public io.a2a.grpc.Message.Builder getMessageBuilder() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ @java.lang.Override public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { @@ -1045,7 +1043,7 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> @@ -1073,7 +1071,7 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; * @return Whether the statusUpdate field is set. */ @java.lang.Override @@ -1085,7 +1083,7 @@ public boolean hasStatusUpdate() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; * @return The statusUpdate. */ @java.lang.Override @@ -1107,7 +1105,7 @@ public io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ public Builder setStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) { if (statusUpdateBuilder_ == null) { @@ -1127,7 +1125,7 @@ public Builder setStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ public Builder setStatusUpdate( io.a2a.grpc.TaskStatusUpdateEvent.Builder builderForValue) { @@ -1145,7 +1143,7 @@ public Builder setStatusUpdate( * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ public Builder mergeStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) { if (statusUpdateBuilder_ == null) { @@ -1172,7 +1170,7 @@ public Builder mergeStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ public Builder clearStatusUpdate() { if (statusUpdateBuilder_ == null) { @@ -1195,7 +1193,7 @@ public Builder clearStatusUpdate() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ public io.a2a.grpc.TaskStatusUpdateEvent.Builder getStatusUpdateBuilder() { return internalGetStatusUpdateFieldBuilder().getBuilder(); @@ -1205,7 +1203,7 @@ public io.a2a.grpc.TaskStatusUpdateEvent.Builder getStatusUpdateBuilder() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ @java.lang.Override public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { @@ -1223,7 +1221,7 @@ public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.TaskStatusUpdateEvent, io.a2a.grpc.TaskStatusUpdateEvent.Builder, io.a2a.grpc.TaskStatusUpdateEventOrBuilder> @@ -1251,7 +1249,7 @@ public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; * @return Whether the artifactUpdate field is set. */ @java.lang.Override @@ -1263,7 +1261,7 @@ public boolean hasArtifactUpdate() { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; * @return The artifactUpdate. */ @java.lang.Override @@ -1285,7 +1283,7 @@ public io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate() { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ public Builder setArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) { if (artifactUpdateBuilder_ == null) { @@ -1305,7 +1303,7 @@ public Builder setArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ public Builder setArtifactUpdate( io.a2a.grpc.TaskArtifactUpdateEvent.Builder builderForValue) { @@ -1323,7 +1321,7 @@ public Builder setArtifactUpdate( * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ public Builder mergeArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) { if (artifactUpdateBuilder_ == null) { @@ -1350,7 +1348,7 @@ public Builder mergeArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ public Builder clearArtifactUpdate() { if (artifactUpdateBuilder_ == null) { @@ -1373,7 +1371,7 @@ public Builder clearArtifactUpdate() { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ public io.a2a.grpc.TaskArtifactUpdateEvent.Builder getArtifactUpdateBuilder() { return internalGetArtifactUpdateFieldBuilder().getBuilder(); @@ -1383,7 +1381,7 @@ public io.a2a.grpc.TaskArtifactUpdateEvent.Builder getArtifactUpdateBuilder() { * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ @java.lang.Override public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() { @@ -1401,7 +1399,7 @@ public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.TaskArtifactUpdateEvent, io.a2a.grpc.TaskArtifactUpdateEvent.Builder, io.a2a.grpc.TaskArtifactUpdateEventOrBuilder> @@ -1422,10 +1420,10 @@ public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() return artifactUpdateBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.StreamResponse) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.StreamResponse) } - // @@protoc_insertion_point(class_scope:a2a.v1.StreamResponse) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.StreamResponse) private static final io.a2a.grpc.StreamResponse DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.StreamResponse(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java index 5688ed06b..228e5fa0f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface StreamResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.StreamResponse) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.StreamResponse) com.google.protobuf.MessageOrBuilder { /** @@ -15,7 +15,7 @@ public interface StreamResponseOrBuilder extends * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; * @return Whether the task field is set. */ boolean hasTask(); @@ -24,7 +24,7 @@ public interface StreamResponseOrBuilder extends * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; * @return The task. */ io.a2a.grpc.Task getTask(); @@ -33,7 +33,7 @@ public interface StreamResponseOrBuilder extends * A Task object containing the current state of the task. * * - * .a2a.v1.Task task = 1; + * .lf.a2a.v1.Task task = 1; */ io.a2a.grpc.TaskOrBuilder getTaskOrBuilder(); @@ -42,7 +42,7 @@ public interface StreamResponseOrBuilder extends * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ boolean hasMessage(); @@ -51,7 +51,7 @@ public interface StreamResponseOrBuilder extends * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return The message. */ io.a2a.grpc.Message getMessage(); @@ -60,7 +60,7 @@ public interface StreamResponseOrBuilder extends * A Message object containing a message from the agent. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); @@ -69,7 +69,7 @@ public interface StreamResponseOrBuilder extends * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; * @return Whether the statusUpdate field is set. */ boolean hasStatusUpdate(); @@ -78,7 +78,7 @@ public interface StreamResponseOrBuilder extends * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; * @return The statusUpdate. */ io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate(); @@ -87,7 +87,7 @@ public interface StreamResponseOrBuilder extends * An event indicating a task status update. * * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3; */ io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder(); @@ -96,7 +96,7 @@ public interface StreamResponseOrBuilder extends * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; * @return Whether the artifactUpdate field is set. */ boolean hasArtifactUpdate(); @@ -105,7 +105,7 @@ public interface StreamResponseOrBuilder extends * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; * @return The artifactUpdate. */ io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate(); @@ -114,7 +114,7 @@ public interface StreamResponseOrBuilder extends * An event indicating a task artifact update. * * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; */ io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StringList.java b/spec-grpc/src/main/java/io/a2a/grpc/StringList.java index 6fed6e257..258bd0cba 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/StringList.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/StringList.java @@ -8,14 +8,15 @@ /** *
          * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        + * A list of strings.
          * 
        * - * Protobuf type {@code a2a.v1.StringList} + * Protobuf type {@code lf.a2a.v1.StringList} */ @com.google.protobuf.Generated public final class StringList extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.StringList) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.StringList) StringListOrBuilder { private static final long serialVersionUID = 0L; static { @@ -38,13 +39,13 @@ private StringList() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.StringList.class, io.a2a.grpc.StringList.Builder.class); } @@ -54,6 +55,10 @@ private StringList() { private com.google.protobuf.LazyStringArrayList list_ = com.google.protobuf.LazyStringArrayList.emptyList(); /** + *
        +   * The individual string values.
        +   * 
        + * * repeated string list = 1; * @return A list containing the list. */ @@ -62,6 +67,10 @@ private StringList() { return list_; } /** + *
        +   * The individual string values.
        +   * 
        + * * repeated string list = 1; * @return The count of list. */ @@ -69,6 +78,10 @@ public int getListCount() { return list_.size(); } /** + *
        +   * The individual string values.
        +   * 
        + * * repeated string list = 1; * @param index The index of the element to return. * @return The list at the given index. @@ -77,6 +90,10 @@ public java.lang.String getList(int index) { return list_.get(index); } /** + *
        +   * The individual string values.
        +   * 
        + * * repeated string list = 1; * @param index The index of the value to return. * @return The bytes of the list at the given index. @@ -252,23 +269,24 @@ protected Builder newBuilderForType( /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        +   * A list of strings.
            * 
        * - * Protobuf type {@code a2a.v1.StringList} + * Protobuf type {@code lf.a2a.v1.StringList} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.StringList) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.StringList) io.a2a.grpc.StringListOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.StringList.class, io.a2a.grpc.StringList.Builder.class); } @@ -295,7 +313,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor; } @java.lang.Override @@ -408,6 +426,10 @@ private void ensureListIsMutable() { bitField0_ |= 0x00000001; } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @return A list containing the list. */ @@ -417,6 +439,10 @@ private void ensureListIsMutable() { return list_; } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @return The count of list. */ @@ -424,6 +450,10 @@ public int getListCount() { return list_.size(); } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @param index The index of the element to return. * @return The list at the given index. @@ -432,6 +462,10 @@ public java.lang.String getList(int index) { return list_.get(index); } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @param index The index of the value to return. * @return The bytes of the list at the given index. @@ -441,6 +475,10 @@ public java.lang.String getList(int index) { return list_.getByteString(index); } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @param index The index to set the value at. * @param value The list to set. @@ -456,6 +494,10 @@ public Builder setList( return this; } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @param value The list to add. * @return This builder for chaining. @@ -470,6 +512,10 @@ public Builder addList( return this; } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @param values The list to add. * @return This builder for chaining. @@ -484,6 +530,10 @@ public Builder addAllList( return this; } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @return This builder for chaining. */ @@ -495,6 +545,10 @@ public Builder clearList() { return this; } /** + *
        +     * The individual string values.
        +     * 
        + * * repeated string list = 1; * @param value The bytes of the list to add. * @return This builder for chaining. @@ -510,10 +564,10 @@ public Builder addListBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.StringList) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.StringList) } - // @@protoc_insertion_point(class_scope:a2a.v1.StringList) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.StringList) private static final io.a2a.grpc.StringList DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.StringList(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java index 48cdceac1..a6b31a667 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java @@ -7,27 +7,43 @@ @com.google.protobuf.Generated public interface StringListOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.StringList) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.StringList) com.google.protobuf.MessageOrBuilder { /** + *
        +   * The individual string values.
        +   * 
        + * * repeated string list = 1; * @return A list containing the list. */ java.util.List getListList(); /** + *
        +   * The individual string values.
        +   * 
        + * * repeated string list = 1; * @return The count of list. */ int getListCount(); /** + *
        +   * The individual string values.
        +   * 
        + * * repeated string list = 1; * @param index The index of the element to return. * @return The list at the given index. */ java.lang.String getList(int index); /** + *
        +   * The individual string values.
        +   * 
        + * * repeated string list = 1; * @param index The index of the value to return. * @return The bytes of the list at the given index. diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java index 82a95620a..a3f0eceb7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java @@ -7,15 +7,15 @@ /** *
        - * --8<-- [start:SubscribeToTaskRequest]
        + * Represents a request for the `SubscribeToTask` method.
          * 
        * - * Protobuf type {@code a2a.v1.SubscribeToTaskRequest} + * Protobuf type {@code lf.a2a.v1.SubscribeToTaskRequest} */ @com.google.protobuf.Generated public final class SubscribeToTaskRequest extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SubscribeToTaskRequest) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.SubscribeToTaskRequest) SubscribeToTaskRequestOrBuilder { private static final long serialVersionUID = 0L; static { @@ -38,26 +38,26 @@ private SubscribeToTaskRequest() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SubscribeToTaskRequest.class, io.a2a.grpc.SubscribeToTaskRequest.Builder.class); } - public static final int TENANT_FIELD_NUMBER = 2; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -75,10 +75,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -96,15 +96,15 @@ public java.lang.String getTenant() { } } - public static final int ID_FIELD_NUMBER = 1; + public static final int ID_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object id_ = ""; /** *
        -   * The resource id of the task to subscribe to.
        +   * The resource ID of the task to subscribe to.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ @java.lang.Override @@ -122,10 +122,10 @@ public java.lang.String getId() { } /** *
        -   * The resource id of the task to subscribe to.
        +   * The resource ID of the task to subscribe to.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ @java.lang.Override @@ -157,11 +157,11 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, id_); } getUnknownFields().writeTo(output); } @@ -172,11 +172,11 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, id_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -311,24 +311,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:SubscribeToTaskRequest]
        +   * Represents a request for the `SubscribeToTask` method.
            * 
        * - * Protobuf type {@code a2a.v1.SubscribeToTaskRequest} + * Protobuf type {@code lf.a2a.v1.SubscribeToTaskRequest} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SubscribeToTaskRequest) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SubscribeToTaskRequest) io.a2a.grpc.SubscribeToTaskRequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.SubscribeToTaskRequest.class, io.a2a.grpc.SubscribeToTaskRequest.Builder.class); } @@ -355,7 +355,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor; } @java.lang.Override @@ -439,13 +439,13 @@ public Builder mergeFrom( done = true; break; case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; break; } // case 10 case 18: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; break; } // case 18 default: { @@ -468,10 +468,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -488,10 +488,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -509,10 +509,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -526,10 +526,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -540,10 +540,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant, provided as a path parameter.
        +     * Optional. Tenant ID, provided as a path parameter.
              * 
        * - * string tenant = 2; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -560,10 +560,10 @@ public Builder setTenantBytes( private java.lang.Object id_ = ""; /** *
        -     * The resource id of the task to subscribe to.
        +     * The resource ID of the task to subscribe to.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ public java.lang.String getId() { @@ -580,10 +580,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the task to subscribe to.
        +     * The resource ID of the task to subscribe to.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ public com.google.protobuf.ByteString @@ -601,10 +601,10 @@ public java.lang.String getId() { } /** *
        -     * The resource id of the task to subscribe to.
        +     * The resource ID of the task to subscribe to.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The id to set. * @return This builder for chaining. */ @@ -618,10 +618,10 @@ public Builder setId( } /** *
        -     * The resource id of the task to subscribe to.
        +     * The resource ID of the task to subscribe to.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearId() { @@ -632,10 +632,10 @@ public Builder clearId() { } /** *
        -     * The resource id of the task to subscribe to.
        +     * The resource ID of the task to subscribe to.
              * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for id to set. * @return This builder for chaining. */ @@ -649,10 +649,10 @@ public Builder setIdBytes( return this; } - // @@protoc_insertion_point(builder_scope:a2a.v1.SubscribeToTaskRequest) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.SubscribeToTaskRequest) } - // @@protoc_insertion_point(class_scope:a2a.v1.SubscribeToTaskRequest) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.SubscribeToTaskRequest) private static final io.a2a.grpc.SubscribeToTaskRequest DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.SubscribeToTaskRequest(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java index 39f287b30..fccd932ad 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface SubscribeToTaskRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SubscribeToTaskRequest) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.SubscribeToTaskRequest) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant, provided as a path parameter.
        +   * Optional. Tenant ID, provided as a path parameter.
            * 
        * - * string tenant = 2; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -32,19 +32,19 @@ public interface SubscribeToTaskRequestOrBuilder extends /** *
        -   * The resource id of the task to subscribe to.
        +   * The resource ID of the task to subscribe to.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The id. */ java.lang.String getId(); /** *
        -   * The resource id of the task to subscribe to.
        +   * The resource ID of the task to subscribe to.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; + * string id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for id. */ com.google.protobuf.ByteString diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Task.java b/spec-grpc/src/main/java/io/a2a/grpc/Task.java index cc1e66690..87c24f027 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/Task.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/Task.java @@ -7,19 +7,18 @@ /** *
        - * --8<-- [start:Task]
        - * Task is the core unit of action for A2A. It has a current status
        + * `Task` is the core unit of action for A2A. It has a current status
          * and when results are created for the task they are stored in the
          * artifact. If there are multiple turns for a task, these are stored in
          * history.
          * 
        * - * Protobuf type {@code a2a.v1.Task} + * Protobuf type {@code lf.a2a.v1.Task} */ @com.google.protobuf.Generated public final class Task extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Task) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.Task) TaskOrBuilder { private static final long serialVersionUID = 0L; static { @@ -44,13 +43,13 @@ private Task() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.Task.class, io.a2a.grpc.Task.Builder.class); } @@ -158,10 +157,10 @@ public java.lang.String getContextId() { private io.a2a.grpc.TaskStatus status_; /** *
        -   * The current status of a Task, including state and a message.
        +   * The current status of a `Task`, including `state` and a `message`.
            * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the status field is set. */ @java.lang.Override @@ -170,10 +169,10 @@ public boolean hasStatus() { } /** *
        -   * The current status of a Task, including state and a message.
        +   * The current status of a `Task`, including `state` and a `message`.
            * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The status. */ @java.lang.Override @@ -182,10 +181,10 @@ public io.a2a.grpc.TaskStatus getStatus() { } /** *
        -   * The current status of a Task, including state and a message.
        +   * The current status of a `Task`, including `state` and a `message`.
            * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { @@ -197,10 +196,10 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { private java.util.List artifacts_; /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ @java.lang.Override public java.util.List getArtifactsList() { @@ -208,10 +207,10 @@ public java.util.List getArtifactsList() { } /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ @java.lang.Override public java.util.List @@ -220,10 +219,10 @@ public java.util.List getArtifactsList() { } /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ @java.lang.Override public int getArtifactsCount() { @@ -231,10 +230,10 @@ public int getArtifactsCount() { } /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ @java.lang.Override public io.a2a.grpc.Artifact getArtifacts(int index) { @@ -242,10 +241,10 @@ public io.a2a.grpc.Artifact getArtifacts(int index) { } /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ @java.lang.Override public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( @@ -259,10 +258,10 @@ public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ @java.lang.Override public java.util.List getHistoryList() { @@ -271,10 +270,10 @@ public java.util.List getHistoryList() { /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ @java.lang.Override public java.util.List @@ -284,10 +283,10 @@ public java.util.List getHistoryList() { /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ @java.lang.Override public int getHistoryCount() { @@ -296,10 +295,10 @@ public int getHistoryCount() { /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ @java.lang.Override public io.a2a.grpc.Message getHistory(int index) { @@ -308,10 +307,10 @@ public io.a2a.grpc.Message getHistory(int index) { /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ @java.lang.Override public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder( @@ -586,28 +585,27 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:Task]
        -   * Task is the core unit of action for A2A. It has a current status
        +   * `Task` is the core unit of action for A2A. It has a current status
            * and when results are created for the task they are stored in the
            * artifact. If there are multiple turns for a task, these are stored in
            * history.
            * 
        * - * Protobuf type {@code a2a.v1.Task} + * Protobuf type {@code lf.a2a.v1.Task} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Task) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.Task) io.a2a.grpc.TaskOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.Task.class, io.a2a.grpc.Task.Builder.class); } @@ -667,7 +665,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor; } @java.lang.Override @@ -1110,10 +1108,10 @@ public Builder setContextIdBytes( io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> statusBuilder_; /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the status field is set. */ public boolean hasStatus() { @@ -1121,10 +1119,10 @@ public boolean hasStatus() { } /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The status. */ public io.a2a.grpc.TaskStatus getStatus() { @@ -1136,10 +1134,10 @@ public io.a2a.grpc.TaskStatus getStatus() { } /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setStatus(io.a2a.grpc.TaskStatus value) { if (statusBuilder_ == null) { @@ -1156,10 +1154,10 @@ public Builder setStatus(io.a2a.grpc.TaskStatus value) { } /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setStatus( io.a2a.grpc.TaskStatus.Builder builderForValue) { @@ -1174,10 +1172,10 @@ public Builder setStatus( } /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder mergeStatus(io.a2a.grpc.TaskStatus value) { if (statusBuilder_ == null) { @@ -1199,10 +1197,10 @@ public Builder mergeStatus(io.a2a.grpc.TaskStatus value) { } /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearStatus() { bitField0_ = (bitField0_ & ~0x00000004); @@ -1216,10 +1214,10 @@ public Builder clearStatus() { } /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() { bitField0_ |= 0x00000004; @@ -1228,10 +1226,10 @@ public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() { } /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { if (statusBuilder_ != null) { @@ -1243,10 +1241,10 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { } /** *
        -     * The current status of a Task, including state and a message.
        +     * The current status of a `Task`, including `state` and a `message`.
              * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> @@ -1276,10 +1274,10 @@ private void ensureArtifactsIsMutable() { /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public java.util.List getArtifactsList() { if (artifactsBuilder_ == null) { @@ -1290,10 +1288,10 @@ public java.util.List getArtifactsList() { } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public int getArtifactsCount() { if (artifactsBuilder_ == null) { @@ -1304,10 +1302,10 @@ public int getArtifactsCount() { } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public io.a2a.grpc.Artifact getArtifacts(int index) { if (artifactsBuilder_ == null) { @@ -1318,10 +1316,10 @@ public io.a2a.grpc.Artifact getArtifacts(int index) { } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder setArtifacts( int index, io.a2a.grpc.Artifact value) { @@ -1339,10 +1337,10 @@ public Builder setArtifacts( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder setArtifacts( int index, io.a2a.grpc.Artifact.Builder builderForValue) { @@ -1357,10 +1355,10 @@ public Builder setArtifacts( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder addArtifacts(io.a2a.grpc.Artifact value) { if (artifactsBuilder_ == null) { @@ -1377,10 +1375,10 @@ public Builder addArtifacts(io.a2a.grpc.Artifact value) { } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder addArtifacts( int index, io.a2a.grpc.Artifact value) { @@ -1398,10 +1396,10 @@ public Builder addArtifacts( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder addArtifacts( io.a2a.grpc.Artifact.Builder builderForValue) { @@ -1416,10 +1414,10 @@ public Builder addArtifacts( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder addArtifacts( int index, io.a2a.grpc.Artifact.Builder builderForValue) { @@ -1434,10 +1432,10 @@ public Builder addArtifacts( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder addAllArtifacts( java.lang.Iterable values) { @@ -1453,10 +1451,10 @@ public Builder addAllArtifacts( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder clearArtifacts() { if (artifactsBuilder_ == null) { @@ -1470,10 +1468,10 @@ public Builder clearArtifacts() { } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public Builder removeArtifacts(int index) { if (artifactsBuilder_ == null) { @@ -1487,10 +1485,10 @@ public Builder removeArtifacts(int index) { } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public io.a2a.grpc.Artifact.Builder getArtifactsBuilder( int index) { @@ -1498,10 +1496,10 @@ public io.a2a.grpc.Artifact.Builder getArtifactsBuilder( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( int index) { @@ -1512,10 +1510,10 @@ public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public java.util.List getArtifactsOrBuilderList() { @@ -1527,10 +1525,10 @@ public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public io.a2a.grpc.Artifact.Builder addArtifactsBuilder() { return internalGetArtifactsFieldBuilder().addBuilder( @@ -1538,10 +1536,10 @@ public io.a2a.grpc.Artifact.Builder addArtifactsBuilder() { } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public io.a2a.grpc.Artifact.Builder addArtifactsBuilder( int index) { @@ -1550,10 +1548,10 @@ public io.a2a.grpc.Artifact.Builder addArtifactsBuilder( } /** *
        -     * A set of output artifacts for a Task.
        +     * A set of output artifacts for a `Task`.
              * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ public java.util.List getArtifactsBuilderList() { @@ -1589,10 +1587,10 @@ private void ensureHistoryIsMutable() { /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public java.util.List getHistoryList() { if (historyBuilder_ == null) { @@ -1604,10 +1602,10 @@ public java.util.List getHistoryList() { /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public int getHistoryCount() { if (historyBuilder_ == null) { @@ -1619,10 +1617,10 @@ public int getHistoryCount() { /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public io.a2a.grpc.Message getHistory(int index) { if (historyBuilder_ == null) { @@ -1634,10 +1632,10 @@ public io.a2a.grpc.Message getHistory(int index) { /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder setHistory( int index, io.a2a.grpc.Message value) { @@ -1656,10 +1654,10 @@ public Builder setHistory( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder setHistory( int index, io.a2a.grpc.Message.Builder builderForValue) { @@ -1675,10 +1673,10 @@ public Builder setHistory( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder addHistory(io.a2a.grpc.Message value) { if (historyBuilder_ == null) { @@ -1696,10 +1694,10 @@ public Builder addHistory(io.a2a.grpc.Message value) { /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder addHistory( int index, io.a2a.grpc.Message value) { @@ -1718,10 +1716,10 @@ public Builder addHistory( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder addHistory( io.a2a.grpc.Message.Builder builderForValue) { @@ -1737,10 +1735,10 @@ public Builder addHistory( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder addHistory( int index, io.a2a.grpc.Message.Builder builderForValue) { @@ -1756,10 +1754,10 @@ public Builder addHistory( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder addAllHistory( java.lang.Iterable values) { @@ -1776,10 +1774,10 @@ public Builder addAllHistory( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder clearHistory() { if (historyBuilder_ == null) { @@ -1794,10 +1792,10 @@ public Builder clearHistory() { /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public Builder removeHistory(int index) { if (historyBuilder_ == null) { @@ -1812,10 +1810,10 @@ public Builder removeHistory(int index) { /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public io.a2a.grpc.Message.Builder getHistoryBuilder( int index) { @@ -1824,10 +1822,10 @@ public io.a2a.grpc.Message.Builder getHistoryBuilder( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder( int index) { @@ -1839,10 +1837,10 @@ public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public java.util.List getHistoryOrBuilderList() { @@ -1855,10 +1853,10 @@ public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public io.a2a.grpc.Message.Builder addHistoryBuilder() { return internalGetHistoryFieldBuilder().addBuilder( @@ -1867,10 +1865,10 @@ public io.a2a.grpc.Message.Builder addHistoryBuilder() { /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public io.a2a.grpc.Message.Builder addHistoryBuilder( int index) { @@ -1880,10 +1878,10 @@ public io.a2a.grpc.Message.Builder addHistoryBuilder( /** *
              * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -     * The history of interactions from a task.
        +     * The history of interactions from a `Task`.
              * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ public java.util.List getHistoryBuilderList() { @@ -2070,10 +2068,10 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { return metadataBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.Task) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.Task) } - // @@protoc_insertion_point(class_scope:a2a.v1.Task) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.Task) private static final io.a2a.grpc.Task DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.Task(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java index 08be9ee0c..b89e56e3f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java @@ -7,17 +7,15 @@ /** *
        - * --8<-- [start:TaskArtifactUpdateEvent]
        - * TaskArtifactUpdateEvent represents a task delta where an artifact has
        - * been generated.
        + * A task delta where an artifact has been generated.
          * 
        * - * Protobuf type {@code a2a.v1.TaskArtifactUpdateEvent} + * Protobuf type {@code lf.a2a.v1.TaskArtifactUpdateEvent} */ @com.google.protobuf.Generated public final class TaskArtifactUpdateEvent extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.TaskArtifactUpdateEvent) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.TaskArtifactUpdateEvent) TaskArtifactUpdateEventOrBuilder { private static final long serialVersionUID = 0L; static { @@ -40,13 +38,13 @@ private TaskArtifactUpdateEvent() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.TaskArtifactUpdateEvent.class, io.a2a.grpc.TaskArtifactUpdateEvent.Builder.class); } @@ -57,7 +55,7 @@ private TaskArtifactUpdateEvent() { private volatile java.lang.Object taskId_ = ""; /** *
        -   * The id of the task for this artifact.
        +   * The ID of the task for this artifact.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -78,7 +76,7 @@ public java.lang.String getTaskId() { } /** *
        -   * The id of the task for this artifact.
        +   * The ID of the task for this artifact.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -104,7 +102,7 @@ public java.lang.String getTaskId() { private volatile java.lang.Object contextId_ = ""; /** *
        -   * The id of the context that this task belongs to.
        +   * The ID of the context that this task belongs to.
            * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -125,7 +123,7 @@ public java.lang.String getContextId() { } /** *
        -   * The id of the context that this task belongs to.
        +   * The ID of the context that this task belongs to.
            * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -153,7 +151,7 @@ public java.lang.String getContextId() { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the artifact field is set. */ @java.lang.Override @@ -165,7 +163,7 @@ public boolean hasArtifact() { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The artifact. */ @java.lang.Override @@ -177,7 +175,7 @@ public io.a2a.grpc.Artifact getArtifact() { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder() { @@ -219,7 +217,7 @@ public boolean getLastChunk() { private com.google.protobuf.Struct metadata_; /** *
        -   * Optional metadata associated with the artifact update.
        +   * Optional. Metadata associated with the artifact update.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -231,7 +229,7 @@ public boolean hasMetadata() { } /** *
        -   * Optional metadata associated with the artifact update.
        +   * Optional. Metadata associated with the artifact update.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -243,7 +241,7 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -   * Optional metadata associated with the artifact update.
        +   * Optional. Metadata associated with the artifact update.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -477,26 +475,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:TaskArtifactUpdateEvent]
        -   * TaskArtifactUpdateEvent represents a task delta where an artifact has
        -   * been generated.
        +   * A task delta where an artifact has been generated.
            * 
        * - * Protobuf type {@code a2a.v1.TaskArtifactUpdateEvent} + * Protobuf type {@code lf.a2a.v1.TaskArtifactUpdateEvent} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.TaskArtifactUpdateEvent) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.TaskArtifactUpdateEvent) io.a2a.grpc.TaskArtifactUpdateEventOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.TaskArtifactUpdateEvent.class, io.a2a.grpc.TaskArtifactUpdateEvent.Builder.class); } @@ -542,7 +538,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor; } @java.lang.Override @@ -711,7 +707,7 @@ public Builder mergeFrom( private java.lang.Object taskId_ = ""; /** *
        -     * The id of the task for this artifact.
        +     * The ID of the task for this artifact.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -731,7 +727,7 @@ public java.lang.String getTaskId() { } /** *
        -     * The id of the task for this artifact.
        +     * The ID of the task for this artifact.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -752,7 +748,7 @@ public java.lang.String getTaskId() { } /** *
        -     * The id of the task for this artifact.
        +     * The ID of the task for this artifact.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -769,7 +765,7 @@ public Builder setTaskId( } /** *
        -     * The id of the task for this artifact.
        +     * The ID of the task for this artifact.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -783,7 +779,7 @@ public Builder clearTaskId() { } /** *
        -     * The id of the task for this artifact.
        +     * The ID of the task for this artifact.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -803,7 +799,7 @@ public Builder setTaskIdBytes( private java.lang.Object contextId_ = ""; /** *
        -     * The id of the context that this task belongs to.
        +     * The ID of the context that this task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -823,7 +819,7 @@ public java.lang.String getContextId() { } /** *
        -     * The id of the context that this task belongs to.
        +     * The ID of the context that this task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -844,7 +840,7 @@ public java.lang.String getContextId() { } /** *
        -     * The id of the context that this task belongs to.
        +     * The ID of the context that this task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -861,7 +857,7 @@ public Builder setContextId( } /** *
        -     * The id of the context that this task belongs to.
        +     * The ID of the context that this task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -875,7 +871,7 @@ public Builder clearContextId() { } /** *
        -     * The id of the context that this task belongs to.
        +     * The ID of the context that this task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -900,7 +896,7 @@ public Builder setContextIdBytes( * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the artifact field is set. */ public boolean hasArtifact() { @@ -911,7 +907,7 @@ public boolean hasArtifact() { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The artifact. */ public io.a2a.grpc.Artifact getArtifact() { @@ -926,7 +922,7 @@ public io.a2a.grpc.Artifact getArtifact() { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setArtifact(io.a2a.grpc.Artifact value) { if (artifactBuilder_ == null) { @@ -946,7 +942,7 @@ public Builder setArtifact(io.a2a.grpc.Artifact value) { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setArtifact( io.a2a.grpc.Artifact.Builder builderForValue) { @@ -964,7 +960,7 @@ public Builder setArtifact( * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder mergeArtifact(io.a2a.grpc.Artifact value) { if (artifactBuilder_ == null) { @@ -989,7 +985,7 @@ public Builder mergeArtifact(io.a2a.grpc.Artifact value) { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearArtifact() { bitField0_ = (bitField0_ & ~0x00000004); @@ -1006,7 +1002,7 @@ public Builder clearArtifact() { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.Artifact.Builder getArtifactBuilder() { bitField0_ |= 0x00000004; @@ -1018,7 +1014,7 @@ public io.a2a.grpc.Artifact.Builder getArtifactBuilder() { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder() { if (artifactBuilder_ != null) { @@ -1033,7 +1029,7 @@ public io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder() { * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> @@ -1145,7 +1141,7 @@ public Builder clearLastChunk() { com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1156,7 +1152,7 @@ public boolean hasMetadata() { } /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1171,7 +1167,7 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1191,7 +1187,7 @@ public Builder setMetadata(com.google.protobuf.Struct value) { } /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1209,7 +1205,7 @@ public Builder setMetadata( } /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1234,7 +1230,7 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) { } /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1251,7 +1247,7 @@ public Builder clearMetadata() { } /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1263,7 +1259,7 @@ public com.google.protobuf.Struct.Builder getMetadataBuilder() { } /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1278,7 +1274,7 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { } /** *
        -     * Optional metadata associated with the artifact update.
        +     * Optional. Metadata associated with the artifact update.
              * 
        * * .google.protobuf.Struct metadata = 6; @@ -1297,10 +1293,10 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { return metadataBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.TaskArtifactUpdateEvent) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.TaskArtifactUpdateEvent) } - // @@protoc_insertion_point(class_scope:a2a.v1.TaskArtifactUpdateEvent) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.TaskArtifactUpdateEvent) private static final io.a2a.grpc.TaskArtifactUpdateEvent DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.TaskArtifactUpdateEvent(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java index 97b99f5d1..b543856f4 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java @@ -7,12 +7,12 @@ @com.google.protobuf.Generated public interface TaskArtifactUpdateEventOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.TaskArtifactUpdateEvent) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.TaskArtifactUpdateEvent) com.google.protobuf.MessageOrBuilder { /** *
        -   * The id of the task for this artifact.
        +   * The ID of the task for this artifact.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -21,7 +21,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends java.lang.String getTaskId(); /** *
        -   * The id of the task for this artifact.
        +   * The ID of the task for this artifact.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -32,7 +32,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends /** *
        -   * The id of the context that this task belongs to.
        +   * The ID of the context that this task belongs to.
            * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -41,7 +41,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends java.lang.String getContextId(); /** *
        -   * The id of the context that this task belongs to.
        +   * The ID of the context that this task belongs to.
            * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -55,7 +55,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the artifact field is set. */ boolean hasArtifact(); @@ -64,7 +64,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The artifact. */ io.a2a.grpc.Artifact getArtifact(); @@ -73,7 +73,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends * The artifact that was generated or updated. * * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder(); @@ -100,7 +100,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends /** *
        -   * Optional metadata associated with the artifact update.
        +   * Optional. Metadata associated with the artifact update.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -109,7 +109,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends boolean hasMetadata(); /** *
        -   * Optional metadata associated with the artifact update.
        +   * Optional. Metadata associated with the artifact update.
            * 
        * * .google.protobuf.Struct metadata = 6; @@ -118,7 +118,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends com.google.protobuf.Struct getMetadata(); /** *
        -   * Optional metadata associated with the artifact update.
        +   * Optional. Metadata associated with the artifact update.
            * 
        * * .google.protobuf.Struct metadata = 6; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java index 2c8648576..cdca99dcf 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface TaskOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Task) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.Task) com.google.protobuf.MessageOrBuilder { /** @@ -56,71 +56,71 @@ public interface TaskOrBuilder extends /** *
        -   * The current status of a Task, including state and a message.
        +   * The current status of a `Task`, including `state` and a `message`.
            * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the status field is set. */ boolean hasStatus(); /** *
        -   * The current status of a Task, including state and a message.
        +   * The current status of a `Task`, including `state` and a `message`.
            * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The status. */ io.a2a.grpc.TaskStatus getStatus(); /** *
        -   * The current status of a Task, including state and a message.
        +   * The current status of a `Task`, including `state` and a `message`.
            * 
        * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder(); /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ java.util.List getArtifactsList(); /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ io.a2a.grpc.Artifact getArtifacts(int index); /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ int getArtifactsCount(); /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ java.util.List getArtifactsOrBuilderList(); /** *
        -   * A set of output artifacts for a Task.
        +   * A set of output artifacts for a `Task`.
            * 
        * - * repeated .a2a.v1.Artifact artifacts = 4; + * repeated .lf.a2a.v1.Artifact artifacts = 4; */ io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( int index); @@ -128,48 +128,48 @@ io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ java.util.List getHistoryList(); /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ io.a2a.grpc.Message getHistory(int index); /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ int getHistoryCount(); /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ java.util.List getHistoryOrBuilderList(); /** *
            * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
        -   * The history of interactions from a task.
        +   * The history of interactions from a `Task`.
            * 
        * - * repeated .a2a.v1.Message history = 5; + * repeated .lf.a2a.v1.Message history = 5; */ io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder( int index); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java index 745594565..fdf27bc57 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java @@ -7,17 +7,15 @@ /** *
        - * --8<-- [start:TaskPushNotificationConfig]
        - * A container associating a push notification configuration with a specific
        - * task.
        + * A container associating a push notification configuration with a specific task.
          * 
        * - * Protobuf type {@code a2a.v1.TaskPushNotificationConfig} + * Protobuf type {@code lf.a2a.v1.TaskPushNotificationConfig} */ @com.google.protobuf.Generated public final class TaskPushNotificationConfig extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.TaskPushNotificationConfig) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.TaskPushNotificationConfig) TaskPushNotificationConfigOrBuilder { private static final long serialVersionUID = 0L; static { @@ -35,33 +33,32 @@ private TaskPushNotificationConfig(com.google.protobuf.GeneratedMessage.Builder< } private TaskPushNotificationConfig() { tenant_ = ""; - id_ = ""; taskId_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.TaskPushNotificationConfig.class, io.a2a.grpc.TaskPushNotificationConfig.Builder.class); } private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 4; + public static final int TENANT_FIELD_NUMBER = 1; @SuppressWarnings("serial") private volatile java.lang.Object tenant_ = ""; /** *
        -   * Optional tenant
        +   * Optional. Tenant ID.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ @java.lang.Override @@ -79,10 +76,10 @@ public java.lang.String getTenant() { } /** *
        -   * Optional tenant
        +   * Optional. Tenant ID.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ @java.lang.Override @@ -100,62 +97,15 @@ public java.lang.String getTenant() { } } - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
        -   * The id of the config.
        -   * 
        - * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
        -   * The id of the config.
        -   * 
        - * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TASK_ID_FIELD_NUMBER = 3; + public static final int TASK_ID_FIELD_NUMBER = 2; @SuppressWarnings("serial") private volatile java.lang.Object taskId_ = ""; /** *
        -   * The id of the task this config is associated with.
        +   * The ID of the task this configuration is associated with.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ @java.lang.Override @@ -173,10 +123,10 @@ public java.lang.String getTaskId() { } /** *
        -   * The id of the task this config is associated with.
        +   * The ID of the task this configuration is associated with.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ @java.lang.Override @@ -194,14 +144,14 @@ public java.lang.String getTaskId() { } } - public static final int PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 2; + public static final int PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 3; private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; /** *
            * The push notification configuration details.
            * 
        * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the pushNotificationConfig field is set. */ @java.lang.Override @@ -213,7 +163,7 @@ public boolean hasPushNotificationConfig() { * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The pushNotificationConfig. */ @java.lang.Override @@ -225,7 +175,7 @@ public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { @@ -246,17 +196,14 @@ public final boolean isInitialized() { @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(2, getPushNotificationConfig()); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); + com.google.protobuf.GeneratedMessage.writeString(output, 2, taskId_); } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(3, getPushNotificationConfig()); } getUnknownFields().writeTo(output); } @@ -267,18 +214,15 @@ public int getSerializedSize() { if (size != -1) return size; size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getPushNotificationConfig()); + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, taskId_); } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getPushNotificationConfig()); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -297,8 +241,6 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; - if (!getId() - .equals(other.getId())) return false; if (!getTaskId() .equals(other.getTaskId())) return false; if (hasPushNotificationConfig() != other.hasPushNotificationConfig()) return false; @@ -319,8 +261,6 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); hash = (37 * hash) + TASK_ID_FIELD_NUMBER; hash = (53 * hash) + getTaskId().hashCode(); if (hasPushNotificationConfig()) { @@ -426,26 +366,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:TaskPushNotificationConfig]
        -   * A container associating a push notification configuration with a specific
        -   * task.
        +   * A container associating a push notification configuration with a specific task.
            * 
        * - * Protobuf type {@code a2a.v1.TaskPushNotificationConfig} + * Protobuf type {@code lf.a2a.v1.TaskPushNotificationConfig} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.TaskPushNotificationConfig) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.TaskPushNotificationConfig) io.a2a.grpc.TaskPushNotificationConfigOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.TaskPushNotificationConfig.class, io.a2a.grpc.TaskPushNotificationConfig.Builder.class); } @@ -471,7 +409,6 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; - id_ = ""; taskId_ = ""; pushNotificationConfig_ = null; if (pushNotificationConfigBuilder_ != null) { @@ -484,7 +421,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor; } @java.lang.Override @@ -515,13 +452,10 @@ private void buildPartial0(io.a2a.grpc.TaskPushNotificationConfig result) { result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { - result.id_ = id_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { result.taskId_ = taskId_; } int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { + if (((from_bitField0_ & 0x00000004) != 0)) { result.pushNotificationConfig_ = pushNotificationConfigBuilder_ == null ? pushNotificationConfig_ : pushNotificationConfigBuilder_.build(); @@ -547,14 +481,9 @@ public Builder mergeFrom(io.a2a.grpc.TaskPushNotificationConfig other) { bitField0_ |= 0x00000001; onChanged(); } - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000002; - onChanged(); - } if (!other.getTaskId().isEmpty()) { taskId_ = other.taskId_; - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; onChanged(); } if (other.hasPushNotificationConfig()) { @@ -587,27 +516,22 @@ public Builder mergeFrom( done = true; break; case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; + tenant_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; break; } // case 10 case 18: { - input.readMessage( - internalGetPushNotificationConfigFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; break; } // case 18 case 26: { - taskId_ = input.readStringRequireUtf8(); + input.readMessage( + internalGetPushNotificationConfigFieldBuilder().getBuilder(), + extensionRegistry); bitField0_ |= 0x00000004; break; } // case 26 - case 34: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -628,10 +552,10 @@ public Builder mergeFrom( private java.lang.Object tenant_ = ""; /** *
        -     * Optional tenant
        +     * Optional. Tenant ID.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ public java.lang.String getTenant() { @@ -648,10 +572,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant
        +     * Optional. Tenant ID.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ public com.google.protobuf.ByteString @@ -669,10 +593,10 @@ public java.lang.String getTenant() { } /** *
        -     * Optional tenant
        +     * Optional. Tenant ID.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @param value The tenant to set. * @return This builder for chaining. */ @@ -686,10 +610,10 @@ public Builder setTenant( } /** *
        -     * Optional tenant
        +     * Optional. Tenant ID.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @return This builder for chaining. */ public Builder clearTenant() { @@ -700,10 +624,10 @@ public Builder clearTenant() { } /** *
        -     * Optional tenant
        +     * Optional. Tenant ID.
              * 
        * - * string tenant = 4; + * string tenant = 1; * @param value The bytes for tenant to set. * @return This builder for chaining. */ @@ -717,105 +641,13 @@ public Builder setTenantBytes( return this; } - private java.lang.Object id_ = ""; - /** - *
        -     * The id of the config.
        -     * 
        - * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
        -     * The id of the config.
        -     * 
        - * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
        -     * The id of the config.
        -     * 
        - * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
        -     * The id of the config.
        -     * 
        - * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
        -     * The id of the config.
        -     * 
        - * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - private java.lang.Object taskId_ = ""; /** *
        -     * The id of the task this config is associated with.
        +     * The ID of the task this configuration is associated with.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ public java.lang.String getTaskId() { @@ -832,10 +664,10 @@ public java.lang.String getTaskId() { } /** *
        -     * The id of the task this config is associated with.
        +     * The ID of the task this configuration is associated with.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ public com.google.protobuf.ByteString @@ -853,10 +685,10 @@ public java.lang.String getTaskId() { } /** *
        -     * The id of the task this config is associated with.
        +     * The ID of the task this configuration is associated with.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The taskId to set. * @return This builder for chaining. */ @@ -864,30 +696,30 @@ public Builder setTaskId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } taskId_ = value; - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; onChanged(); return this; } /** *
        -     * The id of the task this config is associated with.
        +     * The ID of the task this configuration is associated with.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearTaskId() { taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000002); onChanged(); return this; } /** *
        -     * The id of the task this config is associated with.
        +     * The ID of the task this configuration is associated with.
              * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @param value The bytes for taskId to set. * @return This builder for chaining. */ @@ -896,7 +728,7 @@ public Builder setTaskIdBytes( if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); taskId_ = value; - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; onChanged(); return this; } @@ -909,18 +741,18 @@ public Builder setTaskIdBytes( * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the pushNotificationConfig field is set. */ public boolean hasPushNotificationConfig() { - return ((bitField0_ & 0x00000008) != 0); + return ((bitField0_ & 0x00000004) != 0); } /** *
              * The push notification configuration details.
              * 
        * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The pushNotificationConfig. */ public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { @@ -935,7 +767,7 @@ public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { if (pushNotificationConfigBuilder_ == null) { @@ -946,7 +778,7 @@ public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig valu } else { pushNotificationConfigBuilder_.setMessage(value); } - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; onChanged(); return this; } @@ -955,7 +787,7 @@ public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig valu * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setPushNotificationConfig( io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { @@ -964,7 +796,7 @@ public Builder setPushNotificationConfig( } else { pushNotificationConfigBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; onChanged(); return this; } @@ -973,11 +805,11 @@ public Builder setPushNotificationConfig( * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { if (pushNotificationConfigBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && + if (((bitField0_ & 0x00000004) != 0) && pushNotificationConfig_ != null && pushNotificationConfig_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { getPushNotificationConfigBuilder().mergeFrom(value); @@ -988,7 +820,7 @@ public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig va pushNotificationConfigBuilder_.mergeFrom(value); } if (pushNotificationConfig_ != null) { - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; onChanged(); } return this; @@ -998,10 +830,10 @@ public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig va * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearPushNotificationConfig() { - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000004); pushNotificationConfig_ = null; if (pushNotificationConfigBuilder_ != null) { pushNotificationConfigBuilder_.dispose(); @@ -1015,10 +847,10 @@ public Builder clearPushNotificationConfig() { * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuilder() { - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000004; onChanged(); return internalGetPushNotificationConfigFieldBuilder().getBuilder(); } @@ -1027,7 +859,7 @@ public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuild * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { if (pushNotificationConfigBuilder_ != null) { @@ -1042,7 +874,7 @@ public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBu * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> @@ -1058,10 +890,10 @@ public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBu return pushNotificationConfigBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.TaskPushNotificationConfig) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.TaskPushNotificationConfig) } - // @@protoc_insertion_point(class_scope:a2a.v1.TaskPushNotificationConfig) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.TaskPushNotificationConfig) private static final io.a2a.grpc.TaskPushNotificationConfig DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.TaskPushNotificationConfig(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java index 2da32ae41..7bffa7a54 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java @@ -7,24 +7,24 @@ @com.google.protobuf.Generated public interface TaskPushNotificationConfigOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.TaskPushNotificationConfig) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.TaskPushNotificationConfig) com.google.protobuf.MessageOrBuilder { /** *
        -   * Optional tenant
        +   * Optional. Tenant ID.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The tenant. */ java.lang.String getTenant(); /** *
        -   * Optional tenant
        +   * Optional. Tenant ID.
            * 
        * - * string tenant = 4; + * string tenant = 1; * @return The bytes for tenant. */ com.google.protobuf.ByteString @@ -32,39 +32,19 @@ public interface TaskPushNotificationConfigOrBuilder extends /** *
        -   * The id of the config.
        +   * The ID of the task this configuration is associated with.
            * 
        * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
        -   * The id of the config.
        -   * 
        - * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - *
        -   * The id of the task this config is associated with.
        -   * 
        - * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The taskId. */ java.lang.String getTaskId(); /** *
        -   * The id of the task this config is associated with.
        +   * The ID of the task this configuration is associated with.
            * 
        * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; * @return The bytes for taskId. */ com.google.protobuf.ByteString @@ -75,7 +55,7 @@ public interface TaskPushNotificationConfigOrBuilder extends * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the pushNotificationConfig field is set. */ boolean hasPushNotificationConfig(); @@ -84,7 +64,7 @@ public interface TaskPushNotificationConfigOrBuilder extends * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The pushNotificationConfig. */ io.a2a.grpc.PushNotificationConfig getPushNotificationConfig(); @@ -93,7 +73,7 @@ public interface TaskPushNotificationConfigOrBuilder extends * The push notification configuration details. * * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java index 9fc6b6441..b5632db75 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java @@ -7,11 +7,10 @@ /** *
        - * --8<-- [start:TaskState]
        - * Defines the possible lifecycle states of a Task.
        + * Defines the possible lifecycle states of a `Task`.
          * 
        * - * Protobuf enum {@code a2a.v1.TaskState} + * Protobuf enum {@code lf.a2a.v1.TaskState} */ @com.google.protobuf.Generated public enum TaskState @@ -26,7 +25,7 @@ public enum TaskState TASK_STATE_UNSPECIFIED(0), /** *
        -   * Represents the status that acknowledges a task is created.
        +   * Indicates that a task has been successfully submitted and acknowledged.
            * 
        * * TASK_STATE_SUBMITTED = 1; @@ -34,7 +33,7 @@ public enum TaskState TASK_STATE_SUBMITTED(1), /** *
        -   * Represents the status that a task is actively being processed.
        +   * Indicates that a task is actively being processed by the agent.
            * 
        * * TASK_STATE_WORKING = 2; @@ -42,7 +41,7 @@ public enum TaskState TASK_STATE_WORKING(2), /** *
        -   * Represents the status a task is finished. This is a terminal state.
        +   * Indicates that a task has finished successfully. This is a terminal state.
            * 
        * * TASK_STATE_COMPLETED = 3; @@ -50,7 +49,7 @@ public enum TaskState TASK_STATE_COMPLETED(3), /** *
        -   * Represents the status a task is done but failed. This is a terminal state.
        +   * Indicates that a task has finished with an error. This is a terminal state.
            * 
        * * TASK_STATE_FAILED = 4; @@ -58,8 +57,7 @@ public enum TaskState TASK_STATE_FAILED(4), /** *
        -   * Represents the status a task was canceled before it finished.
        -   * This is a terminal state.
        +   * Indicates that a task was canceled before completion. This is a terminal state.
            * 
        * * TASK_STATE_CANCELED = 5; @@ -67,8 +65,7 @@ public enum TaskState TASK_STATE_CANCELED(5), /** *
        -   * Represents the status that the task requires information to complete.
        -   * This is an interrupted state.
        +   * Indicates that the agent requires additional user input to proceed. This is an interrupted state.
            * 
        * * TASK_STATE_INPUT_REQUIRED = 6; @@ -76,7 +73,7 @@ public enum TaskState TASK_STATE_INPUT_REQUIRED(6), /** *
        -   * Represents the status that the agent has decided to not perform the task.
        +   * Indicates that the agent has decided to not perform the task.
            * This may be done during initial task creation or later once an agent
            * has determined it can't or won't proceed. This is a terminal state.
            * 
        @@ -86,8 +83,7 @@ public enum TaskState TASK_STATE_REJECTED(7), /** *
        -   * Represents the state that some authentication is needed from the upstream
        -   * client. This is an interrupted state. Authentication is expected to come out-of-band.
        +   * Indicates that authentication is required to proceed. This is an interrupted state.
            * 
        * * TASK_STATE_AUTH_REQUIRED = 8; @@ -115,7 +111,7 @@ public enum TaskState public static final int TASK_STATE_UNSPECIFIED_VALUE = 0; /** *
        -   * Represents the status that acknowledges a task is created.
        +   * Indicates that a task has been successfully submitted and acknowledged.
            * 
        * * TASK_STATE_SUBMITTED = 1; @@ -123,7 +119,7 @@ public enum TaskState public static final int TASK_STATE_SUBMITTED_VALUE = 1; /** *
        -   * Represents the status that a task is actively being processed.
        +   * Indicates that a task is actively being processed by the agent.
            * 
        * * TASK_STATE_WORKING = 2; @@ -131,7 +127,7 @@ public enum TaskState public static final int TASK_STATE_WORKING_VALUE = 2; /** *
        -   * Represents the status a task is finished. This is a terminal state.
        +   * Indicates that a task has finished successfully. This is a terminal state.
            * 
        * * TASK_STATE_COMPLETED = 3; @@ -139,7 +135,7 @@ public enum TaskState public static final int TASK_STATE_COMPLETED_VALUE = 3; /** *
        -   * Represents the status a task is done but failed. This is a terminal state.
        +   * Indicates that a task has finished with an error. This is a terminal state.
            * 
        * * TASK_STATE_FAILED = 4; @@ -147,8 +143,7 @@ public enum TaskState public static final int TASK_STATE_FAILED_VALUE = 4; /** *
        -   * Represents the status a task was canceled before it finished.
        -   * This is a terminal state.
        +   * Indicates that a task was canceled before completion. This is a terminal state.
            * 
        * * TASK_STATE_CANCELED = 5; @@ -156,8 +151,7 @@ public enum TaskState public static final int TASK_STATE_CANCELED_VALUE = 5; /** *
        -   * Represents the status that the task requires information to complete.
        -   * This is an interrupted state.
        +   * Indicates that the agent requires additional user input to proceed. This is an interrupted state.
            * 
        * * TASK_STATE_INPUT_REQUIRED = 6; @@ -165,7 +159,7 @@ public enum TaskState public static final int TASK_STATE_INPUT_REQUIRED_VALUE = 6; /** *
        -   * Represents the status that the agent has decided to not perform the task.
        +   * Indicates that the agent has decided to not perform the task.
            * This may be done during initial task creation or later once an agent
            * has determined it can't or won't proceed. This is a terminal state.
            * 
        @@ -175,8 +169,7 @@ public enum TaskState public static final int TASK_STATE_REJECTED_VALUE = 7; /** *
        -   * Represents the state that some authentication is needed from the upstream
        -   * client. This is an interrupted state. Authentication is expected to come out-of-band.
        +   * Indicates that authentication is required to proceed. This is an interrupted state.
            * 
        * * TASK_STATE_AUTH_REQUIRED = 8; @@ -270,6 +263,6 @@ private TaskState(int value) { this.value = value; } - // @@protoc_insertion_point(enum_scope:a2a.v1.TaskState) + // @@protoc_insertion_point(enum_scope:lf.a2a.v1.TaskState) } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java index d435fbb50..f31bffb15 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java @@ -7,16 +7,15 @@ /** *
        - * --8<-- [start:TaskStatus]
          * A container for the status of a task
          * 
        * - * Protobuf type {@code a2a.v1.TaskStatus} + * Protobuf type {@code lf.a2a.v1.TaskStatus} */ @com.google.protobuf.Generated public final class TaskStatus extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.TaskStatus) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.TaskStatus) TaskStatusOrBuilder { private static final long serialVersionUID = 0L; static { @@ -38,13 +37,13 @@ private TaskStatus() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.TaskStatus.class, io.a2a.grpc.TaskStatus.Builder.class); } @@ -57,7 +56,7 @@ private TaskStatus() { * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @return The enum numeric value on the wire for state. */ @java.lang.Override public int getStateValue() { @@ -68,7 +67,7 @@ private TaskStatus() { * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @return The state. */ @java.lang.Override public io.a2a.grpc.TaskState getState() { @@ -83,7 +82,7 @@ private TaskStatus() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ @java.lang.Override @@ -95,7 +94,7 @@ public boolean hasMessage() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return The message. */ @java.lang.Override @@ -107,7 +106,7 @@ public io.a2a.grpc.Message getMessage() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ @java.lang.Override public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { @@ -345,25 +344,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:TaskStatus]
            * A container for the status of a task
            * 
        * - * Protobuf type {@code a2a.v1.TaskStatus} + * Protobuf type {@code lf.a2a.v1.TaskStatus} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.TaskStatus) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.TaskStatus) io.a2a.grpc.TaskStatusOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.TaskStatus.class, io.a2a.grpc.TaskStatus.Builder.class); } @@ -406,7 +404,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor; } @java.lang.Override @@ -541,7 +539,7 @@ public Builder mergeFrom( * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @return The enum numeric value on the wire for state. */ @java.lang.Override public int getStateValue() { @@ -552,7 +550,7 @@ public Builder mergeFrom( * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @param value The enum numeric value on the wire for state to set. * @return This builder for chaining. */ @@ -567,7 +565,7 @@ public Builder setStateValue(int value) { * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @return The state. */ @java.lang.Override @@ -580,7 +578,7 @@ public io.a2a.grpc.TaskState getState() { * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @param value The state to set. * @return This builder for chaining. */ @@ -596,7 +594,7 @@ public Builder setState(io.a2a.grpc.TaskState value) { * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @return This builder for chaining. */ public Builder clearState() { @@ -614,7 +612,7 @@ public Builder clearState() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ public boolean hasMessage() { @@ -625,7 +623,7 @@ public boolean hasMessage() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return The message. */ public io.a2a.grpc.Message getMessage() { @@ -640,7 +638,7 @@ public io.a2a.grpc.Message getMessage() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public Builder setMessage(io.a2a.grpc.Message value) { if (messageBuilder_ == null) { @@ -660,7 +658,7 @@ public Builder setMessage(io.a2a.grpc.Message value) { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public Builder setMessage( io.a2a.grpc.Message.Builder builderForValue) { @@ -678,7 +676,7 @@ public Builder setMessage( * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public Builder mergeMessage(io.a2a.grpc.Message value) { if (messageBuilder_ == null) { @@ -703,7 +701,7 @@ public Builder mergeMessage(io.a2a.grpc.Message value) { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public Builder clearMessage() { bitField0_ = (bitField0_ & ~0x00000002); @@ -720,7 +718,7 @@ public Builder clearMessage() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public io.a2a.grpc.Message.Builder getMessageBuilder() { bitField0_ |= 0x00000002; @@ -732,7 +730,7 @@ public io.a2a.grpc.Message.Builder getMessageBuilder() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { if (messageBuilder_ != null) { @@ -747,7 +745,7 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> @@ -929,10 +927,10 @@ public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() { return timestampBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.TaskStatus) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.TaskStatus) } - // @@protoc_insertion_point(class_scope:a2a.v1.TaskStatus) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.TaskStatus) private static final io.a2a.grpc.TaskStatus DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.TaskStatus(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java index fc9d5434b..f2e5c1270 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java @@ -7,7 +7,7 @@ @com.google.protobuf.Generated public interface TaskStatusOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.TaskStatus) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.TaskStatus) com.google.protobuf.MessageOrBuilder { /** @@ -15,7 +15,7 @@ public interface TaskStatusOrBuilder extends * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @return The enum numeric value on the wire for state. */ int getStateValue(); @@ -24,7 +24,7 @@ public interface TaskStatusOrBuilder extends * The current state of this task. * * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; * @return The state. */ io.a2a.grpc.TaskState getState(); @@ -34,7 +34,7 @@ public interface TaskStatusOrBuilder extends * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return Whether the message field is set. */ boolean hasMessage(); @@ -43,7 +43,7 @@ public interface TaskStatusOrBuilder extends * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; * @return The message. */ io.a2a.grpc.Message getMessage(); @@ -52,7 +52,7 @@ public interface TaskStatusOrBuilder extends * A message associated with the status. * * - * .a2a.v1.Message message = 2; + * .lf.a2a.v1.Message message = 2; */ io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java index 06cb104e0..43eac7f2d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java @@ -7,17 +7,15 @@ /** *
        - * --8<-- [start:TaskStatusUpdateEvent]
        - * An event sent by the agent to notify the client of a change in a task's
        - * status.
        + * An event sent by the agent to notify the client of a change in a task's status.
          * 
        * - * Protobuf type {@code a2a.v1.TaskStatusUpdateEvent} + * Protobuf type {@code lf.a2a.v1.TaskStatusUpdateEvent} */ @com.google.protobuf.Generated public final class TaskStatusUpdateEvent extends com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.TaskStatusUpdateEvent) + // @@protoc_insertion_point(message_implements:lf.a2a.v1.TaskStatusUpdateEvent) TaskStatusUpdateEventOrBuilder { private static final long serialVersionUID = 0L; static { @@ -40,13 +38,13 @@ private TaskStatusUpdateEvent() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.TaskStatusUpdateEvent.class, io.a2a.grpc.TaskStatusUpdateEvent.Builder.class); } @@ -57,7 +55,7 @@ private TaskStatusUpdateEvent() { private volatile java.lang.Object taskId_ = ""; /** *
        -   * The id of the task that is changed
        +   * The ID of the task that has changed.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -78,7 +76,7 @@ public java.lang.String getTaskId() { } /** *
        -   * The id of the task that is changed
        +   * The ID of the task that has changed.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -104,7 +102,7 @@ public java.lang.String getTaskId() { private volatile java.lang.Object contextId_ = ""; /** *
        -   * The id of the context that the task belongs to
        +   * The ID of the context that the task belongs to.
            * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -125,7 +123,7 @@ public java.lang.String getContextId() { } /** *
        -   * The id of the context that the task belongs to
        +   * The ID of the context that the task belongs to.
            * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -153,7 +151,7 @@ public java.lang.String getContextId() { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the status field is set. */ @java.lang.Override @@ -165,7 +163,7 @@ public boolean hasStatus() { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The status. */ @java.lang.Override @@ -177,21 +175,21 @@ public io.a2a.grpc.TaskStatus getStatus() { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ @java.lang.Override public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; } - public static final int METADATA_FIELD_NUMBER = 5; + public static final int METADATA_FIELD_NUMBER = 4; private com.google.protobuf.Struct metadata_; /** *
        -   * Optional metadata to associate with the task update.
        +   * Optional. Metadata associated with the task update.
            * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; * @return Whether the metadata field is set. */ @java.lang.Override @@ -200,10 +198,10 @@ public boolean hasMetadata() { } /** *
        -   * Optional metadata to associate with the task update.
        +   * Optional. Metadata associated with the task update.
            * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; * @return The metadata. */ @java.lang.Override @@ -212,10 +210,10 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -   * Optional metadata to associate with the task update.
        +   * Optional. Metadata associated with the task update.
            * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ @java.lang.Override public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { @@ -246,7 +244,7 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) output.writeMessage(3, getStatus()); } if (((bitField0_ & 0x00000002) != 0)) { - output.writeMessage(5, getMetadata()); + output.writeMessage(4, getMetadata()); } getUnknownFields().writeTo(output); } @@ -269,7 +267,7 @@ public int getSerializedSize() { } if (((bitField0_ & 0x00000002) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, getMetadata()); + .computeMessageSize(4, getMetadata()); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -422,26 +420,24 @@ protected Builder newBuilderForType( } /** *
        -   * --8<-- [start:TaskStatusUpdateEvent]
        -   * An event sent by the agent to notify the client of a change in a task's
        -   * status.
        +   * An event sent by the agent to notify the client of a change in a task's status.
            * 
        * - * Protobuf type {@code a2a.v1.TaskStatusUpdateEvent} + * Protobuf type {@code lf.a2a.v1.TaskStatusUpdateEvent} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.TaskStatusUpdateEvent) + // @@protoc_insertion_point(builder_implements:lf.a2a.v1.TaskStatusUpdateEvent) io.a2a.grpc.TaskStatusUpdateEventOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable .ensureFieldAccessorsInitialized( io.a2a.grpc.TaskStatusUpdateEvent.class, io.a2a.grpc.TaskStatusUpdateEvent.Builder.class); } @@ -485,7 +481,7 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; + return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor; } @java.lang.Override @@ -605,13 +601,13 @@ public Builder mergeFrom( bitField0_ |= 0x00000004; break; } // case 26 - case 42: { + case 34: { input.readMessage( internalGetMetadataFieldBuilder().getBuilder(), extensionRegistry); bitField0_ |= 0x00000008; break; - } // case 42 + } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -632,7 +628,7 @@ public Builder mergeFrom( private java.lang.Object taskId_ = ""; /** *
        -     * The id of the task that is changed
        +     * The ID of the task that has changed.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -652,7 +648,7 @@ public java.lang.String getTaskId() { } /** *
        -     * The id of the task that is changed
        +     * The ID of the task that has changed.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -673,7 +669,7 @@ public java.lang.String getTaskId() { } /** *
        -     * The id of the task that is changed
        +     * The ID of the task that has changed.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -690,7 +686,7 @@ public Builder setTaskId( } /** *
        -     * The id of the task that is changed
        +     * The ID of the task that has changed.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -704,7 +700,7 @@ public Builder clearTaskId() { } /** *
        -     * The id of the task that is changed
        +     * The ID of the task that has changed.
              * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -724,7 +720,7 @@ public Builder setTaskIdBytes( private java.lang.Object contextId_ = ""; /** *
        -     * The id of the context that the task belongs to
        +     * The ID of the context that the task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -744,7 +740,7 @@ public java.lang.String getContextId() { } /** *
        -     * The id of the context that the task belongs to
        +     * The ID of the context that the task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -765,7 +761,7 @@ public java.lang.String getContextId() { } /** *
        -     * The id of the context that the task belongs to
        +     * The ID of the context that the task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -782,7 +778,7 @@ public Builder setContextId( } /** *
        -     * The id of the context that the task belongs to
        +     * The ID of the context that the task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -796,7 +792,7 @@ public Builder clearContextId() { } /** *
        -     * The id of the context that the task belongs to
        +     * The ID of the context that the task belongs to.
              * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -821,7 +817,7 @@ public Builder setContextIdBytes( * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the status field is set. */ public boolean hasStatus() { @@ -832,7 +828,7 @@ public boolean hasStatus() { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The status. */ public io.a2a.grpc.TaskStatus getStatus() { @@ -847,7 +843,7 @@ public io.a2a.grpc.TaskStatus getStatus() { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setStatus(io.a2a.grpc.TaskStatus value) { if (statusBuilder_ == null) { @@ -867,7 +863,7 @@ public Builder setStatus(io.a2a.grpc.TaskStatus value) { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder setStatus( io.a2a.grpc.TaskStatus.Builder builderForValue) { @@ -885,7 +881,7 @@ public Builder setStatus( * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder mergeStatus(io.a2a.grpc.TaskStatus value) { if (statusBuilder_ == null) { @@ -910,7 +906,7 @@ public Builder mergeStatus(io.a2a.grpc.TaskStatus value) { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public Builder clearStatus() { bitField0_ = (bitField0_ & ~0x00000004); @@ -927,7 +923,7 @@ public Builder clearStatus() { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() { bitField0_ |= 0x00000004; @@ -939,7 +935,7 @@ public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { if (statusBuilder_ != null) { @@ -954,7 +950,7 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ private com.google.protobuf.SingleFieldBuilder< io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> @@ -975,10 +971,10 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; * @return Whether the metadata field is set. */ public boolean hasMetadata() { @@ -986,10 +982,10 @@ public boolean hasMetadata() { } /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; * @return The metadata. */ public com.google.protobuf.Struct getMetadata() { @@ -1001,10 +997,10 @@ public com.google.protobuf.Struct getMetadata() { } /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ public Builder setMetadata(com.google.protobuf.Struct value) { if (metadataBuilder_ == null) { @@ -1021,10 +1017,10 @@ public Builder setMetadata(com.google.protobuf.Struct value) { } /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ public Builder setMetadata( com.google.protobuf.Struct.Builder builderForValue) { @@ -1039,10 +1035,10 @@ public Builder setMetadata( } /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ public Builder mergeMetadata(com.google.protobuf.Struct value) { if (metadataBuilder_ == null) { @@ -1064,10 +1060,10 @@ public Builder mergeMetadata(com.google.protobuf.Struct value) { } /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ public Builder clearMetadata() { bitField0_ = (bitField0_ & ~0x00000008); @@ -1081,10 +1077,10 @@ public Builder clearMetadata() { } /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ public com.google.protobuf.Struct.Builder getMetadataBuilder() { bitField0_ |= 0x00000008; @@ -1093,10 +1089,10 @@ public com.google.protobuf.Struct.Builder getMetadataBuilder() { } /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { if (metadataBuilder_ != null) { @@ -1108,10 +1104,10 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { } /** *
        -     * Optional metadata to associate with the task update.
        +     * Optional. Metadata associated with the task update.
              * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ private com.google.protobuf.SingleFieldBuilder< com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> @@ -1127,10 +1123,10 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { return metadataBuilder_; } - // @@protoc_insertion_point(builder_scope:a2a.v1.TaskStatusUpdateEvent) + // @@protoc_insertion_point(builder_scope:lf.a2a.v1.TaskStatusUpdateEvent) } - // @@protoc_insertion_point(class_scope:a2a.v1.TaskStatusUpdateEvent) + // @@protoc_insertion_point(class_scope:lf.a2a.v1.TaskStatusUpdateEvent) private static final io.a2a.grpc.TaskStatusUpdateEvent DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new io.a2a.grpc.TaskStatusUpdateEvent(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java index 225000e2a..155fee71a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java @@ -7,12 +7,12 @@ @com.google.protobuf.Generated public interface TaskStatusUpdateEventOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.TaskStatusUpdateEvent) + // @@protoc_insertion_point(interface_extends:lf.a2a.v1.TaskStatusUpdateEvent) com.google.protobuf.MessageOrBuilder { /** *
        -   * The id of the task that is changed
        +   * The ID of the task that has changed.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -21,7 +21,7 @@ public interface TaskStatusUpdateEventOrBuilder extends java.lang.String getTaskId(); /** *
        -   * The id of the task that is changed
        +   * The ID of the task that has changed.
            * 
        * * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; @@ -32,7 +32,7 @@ public interface TaskStatusUpdateEventOrBuilder extends /** *
        -   * The id of the context that the task belongs to
        +   * The ID of the context that the task belongs to.
            * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -41,7 +41,7 @@ public interface TaskStatusUpdateEventOrBuilder extends java.lang.String getContextId(); /** *
        -   * The id of the context that the task belongs to
        +   * The ID of the context that the task belongs to.
            * 
        * * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; @@ -55,7 +55,7 @@ public interface TaskStatusUpdateEventOrBuilder extends * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return Whether the status field is set. */ boolean hasStatus(); @@ -64,7 +64,7 @@ public interface TaskStatusUpdateEventOrBuilder extends * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; * @return The status. */ io.a2a.grpc.TaskStatus getStatus(); @@ -73,34 +73,34 @@ public interface TaskStatusUpdateEventOrBuilder extends * The new status of the task. * * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; */ io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder(); /** *
        -   * Optional metadata to associate with the task update.
        +   * Optional. Metadata associated with the task update.
            * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; * @return Whether the metadata field is set. */ boolean hasMetadata(); /** *
        -   * Optional metadata to associate with the task update.
        +   * Optional. Metadata associated with the task update.
            * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; * @return The metadata. */ com.google.protobuf.Struct getMetadata(); /** *
        -   * Optional metadata to associate with the task update.
        +   * Optional. Metadata associated with the task update.
            * 
        * - * .google.protobuf.Struct metadata = 5; + * .google.protobuf.Struct metadata = 4; */ com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java index d33c04711..ce74a8741 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java @@ -29,7 +29,6 @@ public interface CreateTaskPushNotificationConfigMapper { * @param config the domain TaskPushNotificationConfig * @return proto CreateTaskPushNotificationConfigRequest */ - @Mapping(target = "configId", expression = "java(extractConfigId(config))") CreateTaskPushNotificationConfigRequest toProto(TaskPushNotificationConfig config); /** @@ -57,7 +56,7 @@ default PushNotificationConfig mapPushNotificationConfigWithId(CreateTaskPushNot PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto(request.getConfig()); // Override ID with config_id from request - String configId = request.getConfigId(); + String configId = request.getConfig().getId(); if (configId != null && !configId.isEmpty() && !configId.equals(result.id())) { return new PushNotificationConfig( result.url(), diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java index f54ba28d2..4b3361f77 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java @@ -7,7 +7,7 @@ import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.grpc.ListTaskPushNotificationConfigRequest} and {@link io.a2a.spec.ListTaskPushNotificationConfigParams}. + * Mapper between {@link io.a2a.grpc.ListTaskPushNotificationConfigsRequest} and {@link io.a2a.spec.ListTaskPushNotificationConfigParams}. */ @Mapper(config = A2AProtoMapperConfig.class) public interface ListTaskPushNotificationConfigParamsMapper { @@ -15,17 +15,17 @@ public interface ListTaskPushNotificationConfigParamsMapper { ListTaskPushNotificationConfigParamsMapper INSTANCE = A2AMappers.getMapper(ListTaskPushNotificationConfigParamsMapper.class); /** - * Converts proto ListTaskPushNotificationConfigRequest to domain ListTaskPushNotificationConfigParams. + * Converts proto ListTaskPushNotificationConfigsRequest to domain ListTaskPushNotificationConfigParams. */ @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "taskId") @Mapping(target = "tenant", source = "tenant") - ListTaskPushNotificationConfigParams fromProto(io.a2a.grpc.ListTaskPushNotificationConfigRequest proto); + ListTaskPushNotificationConfigParams fromProto(io.a2a.grpc.ListTaskPushNotificationConfigsRequest proto); /** - * Converts domain ListTaskPushNotificationConfigParams to proto ListTaskPushNotificationConfigRequest. + * Converts domain ListTaskPushNotificationConfigParams to proto ListTaskPushNotificationConfigsRequest. */ @Mapping(target = "taskId", source = "id") @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.ListTaskPushNotificationConfigRequest toProto(ListTaskPushNotificationConfigParams domain); + io.a2a.grpc.ListTaskPushNotificationConfigsRequest toProto(ListTaskPushNotificationConfigParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java index 70595b50e..15522ce72 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java @@ -1,5 +1,6 @@ package io.a2a.grpc.mapper; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.TaskIdParams; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; @@ -11,7 +12,7 @@ *

        * Extracts task ID from resource name format "tasks/{id}" using {@link ResourceNameParser}. */ -@Mapper(config = A2AProtoMapperConfig.class) +@Mapper(config = A2AProtoMapperConfig.class, uses = A2ACommonFieldMapper.class) public interface TaskIdParamsMapper { TaskIdParamsMapper INSTANCE = A2AMappers.getMapper(TaskIdParamsMapper.class); @@ -22,7 +23,8 @@ public interface TaskIdParamsMapper { */ @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "id") - TaskIdParams fromProtoCancelTaskRequest(io.a2a.grpc.CancelTaskRequest proto); + @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") + CancelTaskParams fromProtoCancelTaskRequest(io.a2a.grpc.CancelTaskRequest proto); /** * Converts proto CancelTaskRequest to domain TaskIdParams. @@ -30,7 +32,8 @@ public interface TaskIdParamsMapper { */ @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "id") - io.a2a.grpc.CancelTaskRequest toProtoCancelTaskRequest(TaskIdParams domain); + @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") + io.a2a.grpc.CancelTaskRequest toProtoCancelTaskRequest(CancelTaskParams domain); /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java index 5e3a6e669..beeb9bfef 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java @@ -22,7 +22,6 @@ public interface TaskPushNotificationConfigMapper { * @param domain the domain TaskPushNotificationConfig * @return protobuf TaskPushNotificationConfig */ - @Mapping(target = "id", expression = "java(extractId(domain))") @Mapping(target = "taskId", source = "taskId") @Mapping(target = "pushNotificationConfig", source = "config") @Mapping(target = "tenant", source = "tenant", conditionExpression = "java(domain.tenant() != null)") @@ -65,7 +64,7 @@ default PushNotificationConfig mapPushNotificationConfigWithId(io.a2a.grpc.TaskP PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto(proto.getPushNotificationConfig()); // Override ID with the id from TaskPushNotificationConfig if they differ - String configId = proto.getId(); + String configId = proto.getPushNotificationConfig().getId(); if (configId != null && !configId.isEmpty() && !configId.equals(result.id())) { return new PushNotificationConfig(result.url(), result.token(), result.authentication(), configId); } 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 1480ac42a..0f6d3ed19 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 @@ -54,8 +54,8 @@ 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.ListTaskPushNotificationConfigsRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; @@ -218,7 +218,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); } - return new CancelTaskRequest(version, id, ProtoUtils.FromProto.taskIdParams(builder)); + return new CancelTaskRequest(version, id, ProtoUtils.FromProto.cancelTaskParams(builder)); } case LIST_TASK_METHOD -> { io.a2a.grpc.ListTasksRequest.Builder builder = io.a2a.grpc.ListTasksRequest.newBuilder(); @@ -253,12 +253,12 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new SendMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); } case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder(); + io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigsRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); } - return new ListTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.listTaskPushNotificationConfigParams(builder)); + return new ListTaskPushNotificationConfigsRequest(version, id, ProtoUtils.FromProto.listTaskPushNotificationConfigParams(builder)); } case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); @@ -350,9 +350,9 @@ public static A2AResponse parseResponseBody(String body, String method) throw return new SendMessageResponse(id, ProtoUtils.FromProto.task(builder.getTask())); } case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder(); + io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); - return new ListTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.listTaskPushNotificationConfigResult(builder)); + return new ListTaskPushNotificationConfigsResponse(id, ProtoUtils.FromProto.listTaskPushNotificationConfigResult(builder)); } case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { return new DeleteTaskPushNotificationConfigResponse(id); @@ -389,7 +389,7 @@ public static A2AResponse parseError(JsonObject error, Object id, String meth return new SendMessageResponse(id, rpcError); } case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - return new ListTaskPushNotificationConfigResponse(id, rpcError); + return new ListTaskPushNotificationConfigsResponse(id, rpcError); } case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { return new DeleteTaskPushNotificationConfigResponse(id, rpcError); 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 ebd859909..6c48902a2 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 @@ -25,6 +25,7 @@ import io.a2a.grpc.mapper.TaskStatusUpdateEventMapper; import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.AgentCard; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetExtendedAgentCardParams; @@ -68,7 +69,7 @@ public static io.a2a.grpc.GetTaskRequest getTaskRequest(TaskQueryParams params) return TaskQueryParamsMapper.INSTANCE.toProto(params); } - public static io.a2a.grpc.CancelTaskRequest cancelTaskRequest(TaskIdParams params) { + public static io.a2a.grpc.CancelTaskRequest cancelTaskRequest(CancelTaskParams params) { return TaskIdParamsMapper.INSTANCE.toProtoCancelTaskRequest(params); } @@ -88,7 +89,7 @@ public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest deleteTaskPush return DeleteTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest listTaskPushNotificationConfigRequest(ListTaskPushNotificationConfigParams params) { + public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest listTaskPushNotificationConfigRequest(ListTaskPushNotificationConfigParams params) { return ListTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); } @@ -132,12 +133,12 @@ public static io.a2a.grpc.SendMessageRequest sendMessageRequest(MessageSendParam return MessageSendParamsMapper.INSTANCE.toProto(request); } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfigResponse(ListTaskPushNotificationConfigResult result) { + public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigResponse(ListTaskPushNotificationConfigResult result) { List confs = new ArrayList<>(result.configs().size()); for (TaskPushNotificationConfig config : result.configs()) { confs.add(taskPushNotificationConfig(config)); } - io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder().addAllConfigs(confs); + io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder().addAllConfigs(confs); if (result.nextPageToken() != null) { builder.setNextPageToken(result.nextPageToken()); } @@ -222,7 +223,7 @@ public static ListTasksParams listTasksParams(io.a2a.grpc.ListTasksRequestOrBuil return convert(() -> ListTasksParamsMapper.INSTANCE.fromProto(reqProto)); } - public static TaskIdParams taskIdParams(io.a2a.grpc.CancelTaskRequestOrBuilder request) { + public static CancelTaskParams cancelTaskParams(io.a2a.grpc.CancelTaskRequestOrBuilder request) { io.a2a.grpc.CancelTaskRequest reqProto = request instanceof io.a2a.grpc.CancelTaskRequest ? (io.a2a.grpc.CancelTaskRequest) request : ((io.a2a.grpc.CancelTaskRequest.Builder) request).build(); @@ -264,7 +265,7 @@ public static TaskIdParams taskIdParams(io.a2a.grpc.SubscribeToTaskRequestOrBuil return convert(() -> TaskIdParamsMapper.INSTANCE.fromProtoSubscribeToTaskRequest(reqProto)); } - public static ListTaskPushNotificationConfigResult listTaskPushNotificationConfigResult(io.a2a.grpc.ListTaskPushNotificationConfigResponseOrBuilder response) { + public static ListTaskPushNotificationConfigResult listTaskPushNotificationConfigResult(io.a2a.grpc.ListTaskPushNotificationConfigsResponseOrBuilder response) { List configs = response.getConfigsList(); List result = new ArrayList<>(configs.size()); for (io.a2a.grpc.TaskPushNotificationConfig config : configs) { @@ -277,10 +278,10 @@ public static ListTaskPushNotificationConfigResult listTaskPushNotificationConfi return new ListTaskPushNotificationConfigResult(result, nextPageToken); } - public static ListTaskPushNotificationConfigParams listTaskPushNotificationConfigParams(io.a2a.grpc.ListTaskPushNotificationConfigRequestOrBuilder request) { - io.a2a.grpc.ListTaskPushNotificationConfigRequest reqProto = request instanceof io.a2a.grpc.ListTaskPushNotificationConfigRequest - ? (io.a2a.grpc.ListTaskPushNotificationConfigRequest) request - : ((io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder) request).build(); + public static ListTaskPushNotificationConfigParams listTaskPushNotificationConfigParams(io.a2a.grpc.ListTaskPushNotificationConfigsRequestOrBuilder request) { + io.a2a.grpc.ListTaskPushNotificationConfigsRequest reqProto = request instanceof io.a2a.grpc.ListTaskPushNotificationConfigsRequest + ? (io.a2a.grpc.ListTaskPushNotificationConfigsRequest) request + : ((io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder) request).build(); return convert(() -> ListTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto)); } diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto index 97157cce8..7753faeb1 100644 --- a/spec-grpc/src/main/proto/a2a.proto +++ b/spec-grpc/src/main/proto/a2a.proto @@ -1,6 +1,6 @@ // Older protoc compilers don't understand edition yet. syntax = "proto3"; -package a2a.v1; +package lf.a2a.v1; import "google/api/annotations.proto"; import "google/api/client.proto"; @@ -9,17 +9,17 @@ import "google/protobuf/empty.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; -//From commit b86d8bb2edd20a972951666823cf6c9f51317550 +// From commit 1997c9d63058ca0b89361a7d6e508f4641a6f68b -option csharp_namespace = "A2a.V1"; -option go_package = "google.golang.org/a2a/v1"; +option csharp_namespace = "Lf.A2a.V1"; +option go_package = "google.golang.org/lf/a2a/v1"; option java_multiple_files = true; option java_outer_classname = "A2A"; option java_package = "io.a2a.grpc"; -// A2AService defines the operations of the A2A protocol. +// Provides operations for interacting with agents using the A2A protocol. service A2AService { - // Send a message to the agent. + // Sends a message to an agent. rpc SendMessage(SendMessageRequest) returns (SendMessageResponse) { option (google.api.http) = { post: "/message:send" @@ -30,7 +30,8 @@ service A2AService { } }; } - // SendStreamingMessage is a streaming version of SendMessage. + // Sends a streaming message to an agent, allowing for real-time interaction and status updates. + // Streaming version of `SendMessage` rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse) { option (google.api.http) = { post: "/message:stream" @@ -42,7 +43,7 @@ service A2AService { }; } - // Get the current state of a task from the agent. + // Gets the latest state of a task. rpc GetTask(GetTaskRequest) returns (Task) { option (google.api.http) = { get: "/tasks/{id=*}" @@ -52,7 +53,7 @@ service A2AService { }; option (google.api.method_signature) = "id"; } - // List tasks with optional filtering and pagination. + // Lists tasks that match the specified filter. rpc ListTasks(ListTasksRequest) returns (ListTasksResponse) { option (google.api.http) = { get: "/tasks" @@ -61,7 +62,7 @@ service A2AService { } }; } - // Cancel a task. + // Cancels a task in progress. rpc CancelTask(CancelTaskRequest) returns (Task) { option (google.api.http) = { post: "/tasks/{id=*}:cancel" @@ -72,8 +73,8 @@ service A2AService { } }; } - // SubscribeToTask allows subscribing to task updates for tasks not in terminal state. - // Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected). + // Subscribes to task updates for tasks not in a terminal state. + // Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected). rpc SubscribeToTask(SubscribeToTaskRequest) returns (stream StreamResponse) { option (google.api.http) = { get: "/tasks/{id=*}:subscribe" @@ -83,7 +84,10 @@ service A2AService { }; } - // Create a push notification config for a task. + // (-- api-linter: client-libraries::4232::required-fields=disabled + // api-linter: core::0133::method-signature=disabled + // aip.dev/not-precedent: method_signature preserved for backwards compatibility --) + // Creates a push notification config for a task. rpc CreateTaskPushNotificationConfig(CreateTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { option (google.api.http) = { post: "/tasks/{task_id=*}/pushNotificationConfigs" @@ -95,7 +99,7 @@ service A2AService { }; option (google.api.method_signature) = "task_id,config"; } - // Get a push notification config for a task. + // Gets a push notification config for a task. rpc GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { option (google.api.http) = { get: "/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" @@ -106,7 +110,7 @@ service A2AService { option (google.api.method_signature) = "task_id,id"; } // Get a list of push notifications configured for a task. - rpc ListTaskPushNotificationConfig(ListTaskPushNotificationConfigRequest) returns (ListTaskPushNotificationConfigResponse) { + rpc ListTaskPushNotificationConfigs(ListTaskPushNotificationConfigsRequest) returns (ListTaskPushNotificationConfigsResponse) { option (google.api.http) = { get: "/tasks/{task_id=*}/pushNotificationConfigs" additional_bindings: { @@ -115,7 +119,7 @@ service A2AService { }; option (google.api.method_signature) = "task_id"; } - // GetExtendedAgentCard returns the extended agent card for authenticated agents. + // Gets the extended agent card for the authenticated agent. rpc GetExtendedAgentCard(GetExtendedAgentCardRequest) returns (AgentCard) { option (google.api.http) = { get: "/extendedAgentCard" @@ -124,7 +128,7 @@ service A2AService { } }; } - // Delete a push notification config for a task. + // Deletes a push notification config for a task. rpc DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" @@ -136,12 +140,10 @@ service A2AService { } } -///////// Data Model //////////// - -// --8<-- [start:SendMessageConfiguration] // Configuration of a send message request. message SendMessageConfiguration { - // A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output. + // A list of media types the client is prepared to accept for response parts. + // Agents SHOULD use this to tailor their output. repeated string accepted_output_modes = 1; // Configuration for the agent to send push notifications for task updates. PushNotificationConfig push_notification_config = 2; @@ -150,13 +152,13 @@ message SendMessageConfiguration { // value of zero is a request to not include any messages. The server MUST NOT // return more messages than the provided value, but MAY apply a lower limit. optional int32 history_length = 3; - // If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false. + // If `true`, the operation MUST wait until the task reaches a terminal state + // (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state + // (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`. bool blocking = 4; } -// --8<-- [end:SendMessageConfiguration] -// --8<-- [start:Task] -// Task is the core unit of action for A2A. It has a current status +// `Task` is the core unit of action for A2A. It has a current status // and when results are created for the task they are stored in the // artifact. If there are multiple turns for a task, these are stored in // history. @@ -167,49 +169,42 @@ message Task { // Unique identifier (e.g. UUID) for the contextual collection of interactions // (tasks and messages). Created by the A2A server. string context_id = 2 [(google.api.field_behavior) = REQUIRED]; - // The current status of a Task, including state and a message. + // The current status of a `Task`, including `state` and a `message`. TaskStatus status = 3 [(google.api.field_behavior) = REQUIRED]; - // A set of output artifacts for a Task. + // A set of output artifacts for a `Task`. repeated Artifact artifacts = 4; // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED - // The history of interactions from a task. + // The history of interactions from a `Task`. repeated Message history = 5; // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED // A key/value object to store custom metadata about a task. google.protobuf.Struct metadata = 6; } -// --8<-- [end:Task] -// --8<-- [start:TaskState] -// Defines the possible lifecycle states of a Task. +// Defines the possible lifecycle states of a `Task`. enum TaskState { // The task is in an unknown or indeterminate state. TASK_STATE_UNSPECIFIED = 0; - // Represents the status that acknowledges a task is created. + // Indicates that a task has been successfully submitted and acknowledged. TASK_STATE_SUBMITTED = 1; - // Represents the status that a task is actively being processed. + // Indicates that a task is actively being processed by the agent. TASK_STATE_WORKING = 2; - // Represents the status a task is finished. This is a terminal state. + // Indicates that a task has finished successfully. This is a terminal state. TASK_STATE_COMPLETED = 3; - // Represents the status a task is done but failed. This is a terminal state. + // Indicates that a task has finished with an error. This is a terminal state. TASK_STATE_FAILED = 4; - // Represents the status a task was canceled before it finished. - // This is a terminal state. + // Indicates that a task was canceled before completion. This is a terminal state. TASK_STATE_CANCELED = 5; - // Represents the status that the task requires information to complete. - // This is an interrupted state. + // Indicates that the agent requires additional user input to proceed. This is an interrupted state. TASK_STATE_INPUT_REQUIRED = 6; - // Represents the status that the agent has decided to not perform the task. + // Indicates that the agent has decided to not perform the task. // This may be done during initial task creation or later once an agent // has determined it can't or won't proceed. This is a terminal state. TASK_STATE_REJECTED = 7; - // Represents the state that some authentication is needed from the upstream - // client. This is an interrupted state. Authentication is expected to come out-of-band. + // Indicates that authentication is required to proceed. This is an interrupted state. TASK_STATE_AUTH_REQUIRED = 8; } -// --8<-- [end:TaskState] -// --8<-- [start:TaskStatus] // A container for the status of a task message TaskStatus { // The current state of this task. @@ -220,118 +215,98 @@ message TaskStatus { // Example: "2023-10-27T10:00:00Z" google.protobuf.Timestamp timestamp = 3; } -// --8<-- [end:TaskStatus] -// --8<-- [start:Part] -// Part represents a container for a section of communication content. +// `Part` represents a container for a section of communication content. // Parts can be purely textual, some sort of file (image, video, etc) or // a structured data blob (i.e. JSON). message Part { oneof content { - // The string content of the text part. + // The string content of the `text` part. string text = 1; - // The raw byte content of a file. In JSON serialization, this is encoded as a base64 string. + // The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string. bytes raw = 2; - // A URL pointing to the file's content. + // A `url` pointing to the file's content. string url = 3; - // Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null). + // Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null). google.protobuf.Value data = 4; } - // Optional metadata associated with this part. + // Optional. metadata associated with this part. google.protobuf.Struct metadata = 5; - // An optional name for the file (e.g., "document.pdf"). + // An optional `filename` for the file (e.g., "document.pdf"). string filename = 6; - // The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png"). + // The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png"). // This field is available for all part types. string media_type = 7; } -// --8<-- [end:Part] -// --8<-- [start:Role] // Defines the sender of a message in A2A protocol communication. enum Role { + // The role is unspecified. ROLE_UNSPECIFIED = 0; - // USER role refers to communication from the client to the server. + // The message is from the client to the server. ROLE_USER = 1; - // AGENT role refers to communication from the server to the client. + // The message is from the server to the client. ROLE_AGENT = 2; } -// --8<-- [end:Role] -// --8<-- [start:Message] -// Message is one unit of communication between client and server. It can be -// associated with a context and/or a task. For server messages, context_id must -// be provided, and task_id only if a task was created. For client messages, both +// `Message` is one unit of communication between client and server. It can be +// associated with a context and/or a task. For server messages, `context_id` must +// be provided, and `task_id` only if a task was created. For client messages, both // fields are optional, with the caveat that if both are provided, they have to -// match (the context_id has to be the one that is set on the task). If only -// task_id is provided, the server will infer context_id from it. +// match (the `context_id` has to be the one that is set on the task). If only +// `task_id` is provided, the server will infer `context_id` from it. message Message { - // The unique identifier (e.g. UUID) of the message. This is required and - // created by the message creator. + // The unique identifier (e.g. UUID) of the message. This is created by the message creator. string message_id = 1 [(google.api.field_behavior) = REQUIRED]; - // The context id of the message. This is optional and if set, the message - // will be associated with the given context. + // Optional. The context id of the message. If set, the message will be associated with the given context. string context_id = 2; - // The task id of the message. This is optional and if set, the message - // will be associated with the given task. + // Optional. The task id of the message. If set, the message will be associated with the given task. string task_id = 3; // Identifies the sender of the message. Role role = 4 [(google.api.field_behavior) = REQUIRED]; - // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED // Parts is the container of the message content. repeated Part parts = 5 [(google.api.field_behavior) = REQUIRED]; - // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED - // Any optional metadata to provide along with the message. + // Optional. Any metadata to provide along with the message. google.protobuf.Struct metadata = 6; // The URIs of extensions that are present or contributed to this Message. repeated string extensions = 7; // A list of task IDs that this message references for additional context. repeated string reference_task_ids = 8; } -// --8<-- [end:Message] -// --8<-- [start:Artifact] // Artifacts represent task outputs. message Artifact { - // Unique identifier (e.g. UUID) for the artifact. It must be at least unique - // within a task. + // Unique identifier (e.g. UUID) for the artifact. It must be unique within a task. string artifact_id = 1 [(google.api.field_behavior) = REQUIRED]; // A human readable name for the artifact. - string name = 3; - // A human readable description of the artifact, optional. - string description = 4; + string name = 2; + // Optional. A human readable description of the artifact. + string description = 3; // The content of the artifact. Must contain at least one part. - repeated Part parts = 5 [(google.api.field_behavior) = REQUIRED]; - // Optional metadata included with the artifact. - google.protobuf.Struct metadata = 6; + repeated Part parts = 4 [(google.api.field_behavior) = REQUIRED]; + // Optional. Metadata included with the artifact. + google.protobuf.Struct metadata = 5; // The URIs of extensions that are present or contributed to this Artifact. - repeated string extensions = 7; + repeated string extensions = 6; } -// --8<-- [end:Artifact] -// --8<-- [start:TaskStatusUpdateEvent] -// An event sent by the agent to notify the client of a change in a task's -// status. +// An event sent by the agent to notify the client of a change in a task's status. message TaskStatusUpdateEvent { - // The id of the task that is changed + // The ID of the task that has changed. string task_id = 1 [(google.api.field_behavior) = REQUIRED]; - // The id of the context that the task belongs to + // The ID of the context that the task belongs to. string context_id = 2 [(google.api.field_behavior) = REQUIRED]; // The new status of the task. TaskStatus status = 3 [(google.api.field_behavior) = REQUIRED]; - reserved 4; - // Optional metadata to associate with the task update. - google.protobuf.Struct metadata = 5; + // Optional. Metadata associated with the task update. + google.protobuf.Struct metadata = 4; } -// --8<-- [end:TaskStatusUpdateEvent] -// --8<-- [start:TaskArtifactUpdateEvent] -// TaskArtifactUpdateEvent represents a task delta where an artifact has -// been generated. +// A task delta where an artifact has been generated. message TaskArtifactUpdateEvent { - // The id of the task for this artifact. + // The ID of the task for this artifact. string task_id = 1 [(google.api.field_behavior) = REQUIRED]; - // The id of the context that this task belongs to. + // The ID of the context that this task belongs to. string context_id = 2 [(google.api.field_behavior) = REQUIRED]; // The artifact that was generated or updated. Artifact artifact = 3 [(google.api.field_behavior) = REQUIRED]; @@ -340,37 +315,32 @@ message TaskArtifactUpdateEvent { bool append = 4; // If true, this is the final chunk of the artifact. bool last_chunk = 5; - // Optional metadata associated with the artifact update. + // Optional. Metadata associated with the artifact update. google.protobuf.Struct metadata = 6; } -// --8<-- [end:TaskArtifactUpdateEvent] -// --8<-- [start:PushNotificationConfig] // Configuration for setting up push notifications for task updates. message PushNotificationConfig { - // A unique identifier (e.g. UUID) for this push notification. + // A unique identifier (e.g. UUID) for this push notification configuration. string id = 1; - // Url to send the notification too + // The URL where the notification should be sent. string url = 2 [(google.api.field_behavior) = REQUIRED]; - // Token unique for this task/session + // A token unique for this task or session. string token = 3; - // Authentication information required to send the notification + // Authentication information required to send the notification. AuthenticationInfo authentication = 4; } -// --8<-- [end:PushNotificationConfig] -// --8<-- [start:PushNotificationAuthenticationInfo] // Defines authentication details, used for push notifications. message AuthenticationInfo { // HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/). - // Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1). + // Examples: `Bearer`, `Basic`, `Digest`. + // Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1). string scheme = 1 [(google.api.field_behavior) = REQUIRED]; // Push Notification credentials. Format depends on the scheme (e.g., token for Bearer). string credentials = 2; } -// --8<-- [end:PushNotificationAuthenticationInfo] -// --8<-- [start:AgentInterface] // Declares a combination of a target URL, transport and protocol version for interacting with the agent. // This allows agents to expose the same functionality over multiple protocol binding mechanisms. message AgentInterface { @@ -381,24 +351,19 @@ message AgentInterface { // easily extended for other protocol bindings. The core ones officially // supported are `JSONRPC`, `GRPC` and `HTTP+JSON`. string protocol_binding = 2 [(google.api.field_behavior) = REQUIRED]; - // Tenant to be set in the request when calling the agent. + // Tenant ID to be used in the request when calling the agent. string tenant = 3; // The version of the A2A protocol this interface exposes. // Use the latest supported minor version per major version. // Examples: "0.3", "1.0" string protocol_version = 4 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:AgentInterface] -// --8<-- [start:AgentCard] -// AgentCard is a self-describing manifest for an agent. It provides essential +// A self-describing manifest for an agent. It provides essential // metadata including the agent's identity, capabilities, skills, supported // communication methods, and security requirements. // Next ID: 20 message AgentCard { - // Reserve these field numbers as they were previously used by removed - // fields. - reserved 3, 9, 14, 15, 16; // A human readable name for the agent. // Example: "Recipe Agent" string name = 1 [(google.api.field_behavior) = REQUIRED]; @@ -406,39 +371,37 @@ message AgentCard { // in understanding its purpose. // Example: "Agent that helps users with recipes and cooking." string description = 2 [(google.api.field_behavior) = REQUIRED]; - // Ordered list of supported interfaces. First entry is preferred. - repeated AgentInterface supported_interfaces = 19 [(google.api.field_behavior) = REQUIRED]; + // Ordered list of supported interfaces. The first entry is preferred. + repeated AgentInterface supported_interfaces = 3 [(google.api.field_behavior) = REQUIRED]; // The service provider of the agent. AgentProvider provider = 4; // The version of the agent. // Example: "1.0.0" string version = 5 [(google.api.field_behavior) = REQUIRED]; - // A url to provide additional documentation about the agent. + // A URL providing additional documentation about the agent. optional string documentation_url = 6; // A2A Capability set supported by the agent. AgentCapabilities capabilities = 7 [(google.api.field_behavior) = REQUIRED]; // The security scheme details used for authenticating with this agent. map security_schemes = 8; // Security requirements for contacting the agent. - repeated SecurityRequirement security_requirements = 13; + repeated SecurityRequirement security_requirements = 9; // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED // The set of interaction modes that the agent supports across all skills. // This can be overridden per skill. Defined as media types. repeated string default_input_modes = 10 [(google.api.field_behavior) = REQUIRED]; // The media types supported as outputs from this agent. repeated string default_output_modes = 11 [(google.api.field_behavior) = REQUIRED]; - // Skills represent an ability of an agent. It is largely - // a descriptive concept but represents a more focused set of behaviors that the + // Skills represent the abilities of an agent. + // It is largely a descriptive concept but represents a more focused set of behaviors that the // agent is likely to succeed at. repeated AgentSkill skills = 12 [(google.api.field_behavior) = REQUIRED]; - // JSON Web Signatures computed for this AgentCard. - repeated AgentCardSignature signatures = 17; - // An optional URL to an icon for the agent. - optional string icon_url = 18; + // JSON Web Signatures computed for this `AgentCard`. + repeated AgentCardSignature signatures = 13; + // Optional. A URL to an icon for the agent. + optional string icon_url = 14; } -// --8<-- [end:AgentCard] -// --8<-- [start:AgentProvider] // Represents the service provider of an agent. message AgentProvider { // A URL for the agent provider's website or relevant documentation. @@ -448,9 +411,7 @@ message AgentProvider { // Example: "Google" string organization = 2 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:AgentProvider] -// --8<-- [start:AgentCapabilities] // Defines optional capabilities supported by an agent. message AgentCapabilities { // Indicates if the agent supports streaming responses. @@ -459,14 +420,10 @@ message AgentCapabilities { optional bool push_notifications = 2; // A list of protocol extensions supported by the agent. repeated AgentExtension extensions = 3; - // Field 4 was previously used by state_transition_history capability. - reserved 4; // Indicates if the agent supports providing an extended agent card when authenticated. - optional bool extended_agent_card = 5; + optional bool extended_agent_card = 4; } -// --8<-- [end:AgentCapabilities] -// --8<-- [start:AgentExtension] // A declaration of a protocol extension supported by an Agent. message AgentExtension { // The unique URI identifying the extension. @@ -475,12 +432,10 @@ message AgentExtension { string description = 2; // If true, the client must understand and comply with the extension's requirements. bool required = 3; - // Optional, extension-specific configuration parameters. + // Optional. Extension-specific configuration parameters. google.protobuf.Struct params = 4; } -// --8<-- [end:AgentExtension] -// --8<-- [start:AgentSkill] // Represents a distinct capability or function that an agent can perform. message AgentSkill { // A unique identifier for the agent's skill. @@ -500,51 +455,45 @@ message AgentSkill { // Security schemes necessary for this skill. repeated SecurityRequirement security_requirements = 8; } -// --8<-- [end:AgentSkill] -// --8<-- [start:AgentCardSignature] // AgentCardSignature represents a JWS signature of an AgentCard. // This follows the JSON format of an RFC 7515 JSON Web Signature (JWS). message AgentCardSignature { - // The protected JWS header for the signature. This is always a - // base64url-encoded JSON object. Required. + // (-- api-linter: core::0140::reserved-words=disabled + // aip.dev/not-precedent: Backwards compatibility --) + // Required. The protected JWS header for the signature. This is always a + // base64url-encoded JSON object. string protected = 1 [(google.api.field_behavior) = REQUIRED]; - // The computed signature, base64url-encoded. Required. + // Required. The computed signature, base64url-encoded. string signature = 2 [(google.api.field_behavior) = REQUIRED]; // The unprotected JWS header values. google.protobuf.Struct header = 3; } -// --8<-- [end:AgentCardSignature] -// --8<-- [start:TaskPushNotificationConfig] -// A container associating a push notification configuration with a specific -// task. +// A container associating a push notification configuration with a specific task. message TaskPushNotificationConfig { - // Optional tenant - string tenant = 4; - - // The id of the config. - string id = 1 [(google.api.field_behavior) = REQUIRED]; - - // The id of the task this config is associated with. - string task_id = 3 [(google.api.field_behavior) = REQUIRED]; - + // Optional. Tenant ID. + string tenant = 1; + // The ID of the task this configuration is associated with. + string task_id = 2 [(google.api.field_behavior) = REQUIRED]; // The push notification configuration details. - PushNotificationConfig push_notification_config = 2 [(google.api.field_behavior) = REQUIRED]; + PushNotificationConfig push_notification_config = 3 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:TaskPushNotificationConfig] // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED +// A list of strings. message StringList { + // The individual string values. repeated string list = 1; } // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED +// Defines the security requirements for an agent. message SecurityRequirement { + // A map of security schemes to the required scopes. map schemes = 1; } -// --8<-- [start:SecurityScheme] // Defines a security scheme that can be used to secure an agent's endpoints. // This is a discriminated union type based on the OpenAPI 3.2 Security Scheme Object. // See: https://spec.openapis.org/oas/v3.2.0.html#security-scheme-object @@ -562,9 +511,7 @@ message SecurityScheme { MutualTlsSecurityScheme mtls_security_scheme = 5; } } -// --8<-- [end:SecurityScheme] -// --8<-- [start:APIKeySecurityScheme] // Defines a security scheme using an API key. message APIKeySecurityScheme { // An optional description for the security scheme. @@ -574,9 +521,7 @@ message APIKeySecurityScheme { // The name of the header, query, or cookie parameter to be used. string name = 3 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:APIKeySecurityScheme] -// --8<-- [start:HTTPAuthSecurityScheme] // Defines a security scheme using HTTP authentication. message HTTPAuthSecurityScheme { // An optional description for the security scheme. @@ -586,44 +531,35 @@ message HTTPAuthSecurityScheme { // This value should be registered in the IANA Authentication Scheme registry. string scheme = 2 [(google.api.field_behavior) = REQUIRED]; // A hint to the client to identify how the bearer token is formatted (e.g., "JWT"). - // This is primarily for documentation purposes. + // Primarily for documentation purposes. string bearer_format = 3; } -// --8<-- [end:HTTPAuthSecurityScheme] -// --8<-- [start:OAuth2SecurityScheme] // Defines a security scheme using OAuth 2.0. message OAuth2SecurityScheme { // An optional description for the security scheme. string description = 1; // An object containing configuration information for the supported OAuth 2.0 flows. OAuthFlows flows = 2 [(google.api.field_behavior) = REQUIRED]; - // URL to the oauth2 authorization server metadata - // RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required. + // URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414). + // TLS is required. string oauth2_metadata_url = 3; } -// --8<-- [end:OAuth2SecurityScheme] -// --8<-- [start:OpenIdConnectSecurityScheme] // Defines a security scheme using OpenID Connect. message OpenIdConnectSecurityScheme { // An optional description for the security scheme. string description = 1; - // The OpenID Connect Discovery URL for the OIDC provider's metadata. - // See: https://openid.net/specs/openid-connect-discovery-1_0.html + // The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata. string open_id_connect_url = 2 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:OpenIdConnectSecurityScheme] -// --8<-- [start:MutualTLSSecurityScheme] // Defines a security scheme using mTLS authentication. message MutualTlsSecurityScheme { // An optional description for the security scheme. string description = 1; } -// --8<-- [end:MutualTLSSecurityScheme] -// --8<-- [start:OAuthFlows] // Defines the configuration for the supported OAuth 2.0 flows. message OAuthFlows { oneof flow { @@ -631,15 +567,15 @@ message OAuthFlows { AuthorizationCodeOAuthFlow authorization_code = 1; // Configuration for the OAuth Client Credentials flow. ClientCredentialsOAuthFlow client_credentials = 2; + // Deprecated: Use Authorization Code + PKCE instead. ImplicitOAuthFlow implicit = 3 [deprecated = true]; + // Deprecated: Use Authorization Code + PKCE or Device Code. PasswordOAuthFlow password = 4 [deprecated = true]; // Configuration for the OAuth Device Code flow. DeviceCodeOAuthFlow device_code = 5; } } -// --8<-- [end:OAuthFlows] -// --8<-- [start:AuthorizationCodeOAuthFlow] // Defines configuration details for the OAuth 2.0 Authorization Code flow. message AuthorizationCodeOAuthFlow { // The authorization URL to be used for this flow. @@ -654,9 +590,7 @@ message AuthorizationCodeOAuthFlow { // PKCE should always be used for public clients and is recommended for all clients. bool pkce_required = 5; } -// --8<-- [end:AuthorizationCodeOAuthFlow] -// --8<-- [start:ClientCredentialsOAuthFlow] // Defines configuration details for the OAuth 2.0 Client Credentials flow. message ClientCredentialsOAuthFlow { // The token URL to be used for this flow. @@ -666,9 +600,8 @@ message ClientCredentialsOAuthFlow { // The available scopes for the OAuth2 security scheme. map scopes = 3 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:ClientCredentialsOAuthFlow] -// DEPRECATED +// Deprecated: Use Authorization Code + PKCE instead. message ImplicitOAuthFlow { // The authorization URL to be used for this flow. This MUST be in the // form of a URL. The OAuth2 standard requires the use of TLS @@ -681,7 +614,7 @@ message ImplicitOAuthFlow { map scopes = 3; } -// DEPRECATED +// Deprecated: Use Authorization Code + PKCE or Device Code. message PasswordOAuthFlow { // The token URL to be used for this flow. This MUST be in the form of a URL. // The OAuth2 standard requires the use of TLS. @@ -694,7 +627,6 @@ message PasswordOAuthFlow { map scopes = 3; } -// --8<-- [start:DeviceCodeOAuthFlow] // Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628). // This flow is designed for input-constrained devices such as IoT devices, // and CLI tools where the user authenticates on a separate device. @@ -708,169 +640,153 @@ message DeviceCodeOAuthFlow { // The available scopes for the OAuth2 security scheme. map scopes = 4 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:DeviceCodeOAuthFlow] -///////////// Request Messages /////////// -// --8<-- [start:SendMessageRequest] // Represents a request for the `SendMessage` method. message SendMessageRequest { - // Optional tenant, provided as a path parameter. - string tenant = 4; + // Optional. Tenant ID, provided as a path parameter. + string tenant = 1; // The message to send to the agent. - Message message = 1 [(google.api.field_behavior) = REQUIRED]; + Message message = 2 [(google.api.field_behavior) = REQUIRED]; // Configuration for the send request. - SendMessageConfiguration configuration = 2; + SendMessageConfiguration configuration = 3; // A flexible key-value map for passing additional context or parameters. - google.protobuf.Struct metadata = 3; + google.protobuf.Struct metadata = 4; } -// --8<-- [end:SendMessageRequest] -// --8<-- [start:GetTaskRequest] // Represents a request for the `GetTask` method. message GetTaskRequest { - // Optional tenant, provided as a path parameter. - string tenant = 3; - // The resource id of the task. - string id = 1 [(google.api.field_behavior) = REQUIRED]; + // Optional. Tenant ID, provided as a path parameter. + string tenant = 1; + // The resource ID of the task to retrieve. + string id = 2 [(google.api.field_behavior) = REQUIRED]; // The maximum number of most recent messages from the task's history to retrieve. An // unset value means the client does not impose any limit. A value of zero is // a request to not include any messages. The server MUST NOT return more // messages than the provided value, but MAY apply a lower limit. - optional int32 history_length = 2; + optional int32 history_length = 3; } -// --8<-- [end:GetTaskRequest] -// --8<-- [start:ListTasksRequest] // Parameters for listing tasks with optional filtering criteria. message ListTasksRequest { - // Optional tenant, provided as a path parameter. - string tenant = 9; + // Tenant ID, provided as a path parameter. + string tenant = 1; // Filter tasks by context ID to get tasks from a specific conversation or session. - string context_id = 1; + string context_id = 2; // Filter tasks by their current status state. - TaskState status = 2; - // Maximum number of tasks to return. Must be between 1 and 100. - // Defaults to 50 if not specified. - optional int32 page_size = 3; - // Token for pagination. Use the next_page_token from a previous ListTasksResponse. - string page_token = 4; + TaskState status = 3; + // The maximum number of tasks to return. The service may return fewer than this value. + // If unspecified, at most 50 tasks will be returned. + // The minimum value is 1. + // The maximum value is 100. + optional int32 page_size = 4; + // A page token, received from a previous `ListTasks` call. + // `ListTasksResponse.next_page_token`. + // Provide this to retrieve the subsequent page. + string page_token = 5; // The maximum number of messages to include in each task's history. - optional int32 history_length = 5; + optional int32 history_length = 6; // Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z"). // Only tasks with a status timestamp time greater than or equal to this value will be returned. - google.protobuf.Timestamp status_timestamp_after = 6; + google.protobuf.Timestamp status_timestamp_after = 7; // Whether to include artifacts in the returned tasks. // Defaults to false to reduce payload size. - optional bool include_artifacts = 7; + optional bool include_artifacts = 8; } -// --8<-- [end:ListTasksRequest] -// --8<-- [start:ListTasksResponse] -// Result object for tasks/list method containing an array of tasks and pagination information. +// Result object for `ListTasks` method containing an array of tasks and pagination information. message ListTasksResponse { // Array of tasks matching the specified criteria. repeated Task tasks = 1 [(google.api.field_behavior) = REQUIRED]; - // Token for retrieving the next page. Empty string if no more results. + // A token to retrieve the next page of results, or empty if there are no more results in the list. string next_page_token = 2 [(google.api.field_behavior) = REQUIRED]; - // The size of page requested. + // The page size used for this response. int32 page_size = 3 [(google.api.field_behavior) = REQUIRED]; // Total number of tasks available (before pagination). int32 total_size = 4 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:ListTasksResponse] -// --8<-- [start:CancelTaskRequest] // Represents a request for the `CancelTask` method. message CancelTaskRequest { - // Optional tenant, provided as a path parameter. - string tenant = 2; - // The resource id of the task to cancel. - string id = 1 [(google.api.field_behavior) = REQUIRED]; + // Optional. Tenant ID, provided as a path parameter. + string tenant = 1; + // The resource ID of the task to cancel. + string id = 2 [(google.api.field_behavior) = REQUIRED]; + // A flexible key-value map for passing additional context or parameters. + google.protobuf.Struct metadata = 3; } -// --8<-- [end:CancelTaskRequest] -// --8<-- [start:GetTaskPushNotificationConfigRequest] +// Represents a request for the `GetTaskPushNotificationConfig` method. message GetTaskPushNotificationConfigRequest { - // Optional tenant, provided as a path parameter. - string tenant = 2; - // The parent task resource id. - string task_id = 3 [(google.api.field_behavior) = REQUIRED]; - // The resource id of the config to retrieve. - string id = 1 [(google.api.field_behavior) = REQUIRED]; + // Optional. Tenant ID, provided as a path parameter. + string tenant = 1; + // The parent task resource ID. + string task_id = 2 [(google.api.field_behavior) = REQUIRED]; + // The resource ID of the configuration to retrieve. + string id = 3 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:GetTaskPushNotificationConfigRequest] -// --8<-- [start:DeleteTaskPushNotificationConfigRequest] // Represents a request for the `DeleteTaskPushNotificationConfig` method. message DeleteTaskPushNotificationConfigRequest { - // Optional tenant, provided as a path parameter. - string tenant = 2; - // The parent task resource id. - string task_id = 3 [(google.api.field_behavior) = REQUIRED]; - // The resource id of the config to delete. - string id = 1 [(google.api.field_behavior) = REQUIRED]; + // Optional. Tenant ID, provided as a path parameter. + string tenant = 1; + // The parent task resource ID. + string task_id = 2 [(google.api.field_behavior) = REQUIRED]; + // The resource ID of the configuration to delete. + string id = 3 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:DeleteTaskPushNotificationConfigRequest] -// --8<-- [start:CreateTaskPushNotificationConfigRequest] // Represents a request for the `CreateTaskPushNotificationConfig` method. message CreateTaskPushNotificationConfigRequest { - reserved 3; - // Optional tenant, provided as a path parameter. - string tenant = 4; - // The parent task resource id. - string task_id = 1 [(google.api.field_behavior) = REQUIRED]; - // The ID for the new config. - string config_id = 2 [(google.api.field_behavior) = REQUIRED]; + // Optional. Tenant ID, provided as a path parameter. + string tenant = 1; + // The parent task resource ID. + string task_id = 2 [(google.api.field_behavior) = REQUIRED]; // The configuration to create. - PushNotificationConfig config = 5 [(google.api.field_behavior) = REQUIRED]; + PushNotificationConfig config = 3 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:CreateTaskPushNotificationConfigRequest] -// --8<-- [start:SubscribeToTaskRequest] +// Represents a request for the `SubscribeToTask` method. message SubscribeToTaskRequest { - // Optional tenant, provided as a path parameter. - string tenant = 2; - // The resource id of the task to subscribe to. - string id = 1 [(google.api.field_behavior) = REQUIRED]; + // Optional. Tenant ID, provided as a path parameter. + string tenant = 1; + // The resource ID of the task to subscribe to. + string id = 2 [(google.api.field_behavior) = REQUIRED]; } -// --8<-- [end:SubscribeToTaskRequest] -// --8<-- [start:ListTaskPushNotificationConfigRequest] -message ListTaskPushNotificationConfigRequest { - // Optional tenant, provided as a path parameter. +// Represents a request for the `ListTaskPushNotificationConfigs` method. +message ListTaskPushNotificationConfigsRequest { + // Optional. Tenant ID, provided as a path parameter. string tenant = 4; - // The parent task resource id. + // The parent task resource ID. string task_id = 1 [(google.api.field_behavior) = REQUIRED]; // The maximum number of configurations to return. int32 page_size = 2; - // A page token received from a previous ListTaskPushNotificationConfigRequest call. + // A page token received from a previous `ListTaskPushNotificationConfigsRequest` call. string page_token = 3; } -// --8<-- [end:ListTaskPushNotificationConfigRequest] -// --8<-- [start:GetExtendedAgentCardRequest] +// Represents a request for the `GetExtendedAgentCard` method. message GetExtendedAgentCardRequest { - // Optional tenant, provided as a path parameter. + // Optional. Tenant ID, provided as a path parameter. string tenant = 1; } -// --8<-- [end:GetExtendedAgentCardRequest] -//////// Response Messages /////////// -// --8<-- [start:SendMessageResponse] +// Represents the response for the `SendMessage` method. message SendMessageResponse { + // The payload of the response. oneof payload { + // The task created or updated by the message. Task task = 1; + // A message from the agent. Message message = 2; } } -// --8<-- [end:SendMessageResponse] -// --8<-- [start:StreamResponse] // A wrapper object used in streaming operations to encapsulate different types of response data. message StreamResponse { + // The payload of the stream response. oneof payload { // A Task object containing the current state of the task. Task task = 1; @@ -882,16 +798,12 @@ message StreamResponse { TaskArtifactUpdateEvent artifact_update = 4; } } -// --8<-- [end:StreamResponse] -// --8<-- [start:ListTaskPushNotificationConfigResponse] -// Represents a successful response for the `ListTaskPushNotificationConfig` +// Represents a successful response for the `ListTaskPushNotificationConfigs` // method. -message ListTaskPushNotificationConfigResponse { +message ListTaskPushNotificationConfigsResponse { // The list of push notification configurations. repeated TaskPushNotificationConfig configs = 1; - // A token, which can be sent as `page_token` to retrieve the next page. - // If this field is omitted, there are no subsequent pages. + // A token to retrieve the next page of results, or empty if there are no more results in the list. string next_page_token = 2; } -// --8<-- [end:ListTaskPushNotificationConfigResponse] 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 569d77981..b5bb95f4e 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 @@ -11,7 +11,6 @@ import com.google.gson.JsonSyntaxException; -import io.a2a.grpc.Role; import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; import io.a2a.jsonrpc.common.json.JsonMappingException; import io.a2a.jsonrpc.common.json.JsonProcessingException; @@ -20,10 +19,8 @@ import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.Message; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; import org.junit.jupiter.api.Test; @@ -39,9 +36,9 @@ public void testParseCreateTaskPushNotificationConfigRequest_ValidProtoFormat() "id": "1", "params": { "taskId": "task-123", - "configId": "config-456", "tenant": "", "config": { + "id": "config-456", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" @@ -145,7 +142,7 @@ public void testParseInvalidProtoStructure_ThrowsInvalidParamsJsonMappingExcepti () -> JSONRPCUtils.parseRequestBody(invalidStructure, null) ); assertEquals(4, exception.getId()); - assertEquals(ERROR_MESSAGE.formatted("invalid_field in message a2a.v1.CreateTaskPushNotificationConfigRequest"), exception.getMessage()); + assertEquals(ERROR_MESSAGE.formatted("invalid_field in message lf.a2a.v1.CreateTaskPushNotificationConfigRequest"), exception.getMessage()); } @Test @@ -241,7 +238,7 @@ public void testParseUnknownField_ThrowsJsonMappingException() throws JsonMappin JsonMappingException.class, () -> JSONRPCUtils.parseRequestBody(unkownFieldMessage, null) ); - assertEquals(ERROR_MESSAGE.formatted("unknown in message a2a.v1.Message"), exception.getMessage()); + assertEquals(ERROR_MESSAGE.formatted("unknown in message lf.a2a.v1.Message"), exception.getMessage()); } @Test @@ -315,10 +312,10 @@ public void testGenerateCreateTaskPushNotificationConfigResponse_Success() throw String responseJson = """ { "jsonrpc": "2.0", - "id": "1", + "id": 1, "result": { + "tenant": "tenant", "taskId": "task-123", - "id": "config-456", "pushNotificationConfig": { "url": "https://example.com/callback", "id": "config-456" @@ -342,10 +339,10 @@ public void testGenerateGetTaskPushNotificationConfigResponse_Success() throws E String responseJson = """ { "jsonrpc": "2.0", - "id": "2", + "id": 2, "result": { + "tenant": "tenant", "taskId": "task-123", - "id": "config-456", "pushNotificationConfig": { "url": "https://example.com/callback", "id": "config-456" diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index b857cb6b1..ea0f320a0 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -216,8 +216,8 @@ public void convertTaskPushNotificationConfig() { .build(), null); io.a2a.grpc.TaskPushNotificationConfig result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); assertEquals("push-task-123", result.getTaskId()); - assertEquals("xyz", result.getId()); assertNotNull(result.getPushNotificationConfig()); + assertEquals("xyz", result.getPushNotificationConfig().getId()); assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); assertEquals("xyz", result.getPushNotificationConfig().getId()); assertEquals(false, result.getPushNotificationConfig().hasAuthentication()); @@ -231,8 +231,8 @@ public void convertTaskPushNotificationConfig() { .build(), null); result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); assertEquals("push-task-123", result.getTaskId()); - assertEquals("xyz", result.getId()); assertNotNull(result.getPushNotificationConfig()); + assertEquals("xyz", result.getPushNotificationConfig().getId()); assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); assertEquals("xyz", result.getPushNotificationConfig().getId()); assertEquals("AAAAAA", result.getPushNotificationConfig().getToken()); @@ -328,10 +328,10 @@ public void convertDeleteTaskPushNotificationConfigRequest() { } @Test - public void convertListTaskPushNotificationConfigRequest() { + public void convertListTaskPushNotificationConfigsRequest() { ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-789"); - io.a2a.grpc.ListTaskPushNotificationConfigRequest result = + io.a2a.grpc.ListTaskPushNotificationConfigsRequest result = ProtoUtils.ToProto.listTaskPushNotificationConfigRequest(params); assertEquals("task-789", result.getTaskId()); diff --git a/spec/src/main/java/io/a2a/spec/A2AMethods.java b/spec/src/main/java/io/a2a/spec/A2AMethods.java index 1731077fe..782fa0d2e 100644 --- a/spec/src/main/java/io/a2a/spec/A2AMethods.java +++ b/spec/src/main/java/io/a2a/spec/A2AMethods.java @@ -18,7 +18,7 @@ public interface A2AMethods { /** Method name for listing tasks. */ String LIST_TASK_METHOD = "ListTasks"; /** Method name for listing task push notification configurations. */ - String LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "ListTaskPushNotificationConfig"; + String LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "ListTaskPushNotificationConfigs"; /** Method name for sending a message. */ String SEND_MESSAGE_METHOD = "SendMessage"; /** Method name for sending a streaming message. */ diff --git a/spec/src/main/java/io/a2a/spec/CancelTaskParams.java b/spec/src/main/java/io/a2a/spec/CancelTaskParams.java new file mode 100644 index 000000000..2eee837e4 --- /dev/null +++ b/spec/src/main/java/io/a2a/spec/CancelTaskParams.java @@ -0,0 +1,113 @@ +package io.a2a.spec; + +import io.a2a.util.Assert; +import io.a2a.util.Utils; +import java.util.Collections; +import java.util.Map; +import org.jspecify.annotations.Nullable; + +/** + * Parameters for cancelling a task. + *

        + * Carries the task identifier and optional tenant and metadata for cancel-specific context, + * such as a cancellation reason or source system. + * + * @param id the unique task identifier (required) + * @param tenant optional tenant, provided as a path parameter + * @param metadata optional arbitrary key-value metadata (e.g. cancellation reason) + * @see A2A Protocol Specification + */ +public record CancelTaskParams(String id, String tenant, Map metadata) { + + /** + * Compact constructor for validation. + * Validates that required parameters are not null. + * + * @param id the task identifier + * @param tenant the tenant identifier + */ + public CancelTaskParams { + Assert.checkNotNullParam("id", id); + Assert.checkNotNullParam("tenant", tenant); + } + + /** + * Convenience constructor with default tenant. + * + * @param id the task identifier (required) + */ + public CancelTaskParams(String id) { + this(id, "", Collections.emptyMap()); + } + + /** + * Create a new Builder + * + * @return the builder + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for constructing instances. + */ + public static class Builder { + private @Nullable String id; + private @Nullable String tenant; + private Map metadata = Collections.emptyMap(); + + /** + * Creates a new Builder with all fields unset. + */ + private Builder() { + } + + /** + * Sets the id. + * + * @param id the task identifier (required) + * @return this builder for method chaining + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * Sets the tenant. + * + * @param tenant the tenant identifier + * @return this builder for method chaining + */ + public Builder tenant(String tenant) { + this.tenant = tenant; + return this; + } + + /** + * Sets optional metadata for the request. + * + * @param metadata arbitrary key-value metadata + * @return this builder + */ + public Builder metadata(Map metadata) { + this.metadata = Map.copyOf(metadata); + return this; + } + + /** + * Builds the TaskIdParams. + * + * @return a new TaskIdParams instance + * @throws IllegalArgumentException if id is null + */ + public CancelTaskParams build() { + return new CancelTaskParams( + Assert.checkNotNullParam("id", id), + Utils.defaultIfNull(tenant,""), + metadata + ); + } + } +} diff --git a/spec/src/main/java/io/a2a/spec/TaskIdParams.java b/spec/src/main/java/io/a2a/spec/TaskIdParams.java index 972bb4a22..f61c74684 100644 --- a/spec/src/main/java/io/a2a/spec/TaskIdParams.java +++ b/spec/src/main/java/io/a2a/spec/TaskIdParams.java @@ -81,6 +81,7 @@ public Builder tenant(String tenant) { return this; } + /** * Builds the TaskIdParams. * 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 75ba229ea..8b4021b65 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 @@ -55,6 +55,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.Artifact; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.Event; import io.a2a.spec.GetTaskPushNotificationConfigParams; @@ -211,7 +212,7 @@ public void testGetTaskNotFound() throws Exception { public void testCancelTaskSuccess() throws Exception { saveTaskInTaskStore(CANCEL_TASK); try { - Task task = getClient().cancelTask(new TaskIdParams(CANCEL_TASK.id())); + Task task = getClient().cancelTask(new CancelTaskParams(CANCEL_TASK.id())); assertEquals(CANCEL_TASK.id(), task.id()); assertEquals(CANCEL_TASK.contextId(), task.contextId()); assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); @@ -226,7 +227,7 @@ public void testCancelTaskSuccess() throws Exception { public void testCancelTaskNotSupported() throws Exception { saveTaskInTaskStore(CANCEL_TASK_NOT_SUPPORTED); try { - getClient().cancelTask(new TaskIdParams(CANCEL_TASK_NOT_SUPPORTED.id())); + getClient().cancelTask(new CancelTaskParams(CANCEL_TASK_NOT_SUPPORTED.id())); fail("Expected A2AClientException for unsupported cancel operation"); } catch (A2AClientException e) { // Expected - the client should throw an exception for unsupported operations @@ -239,7 +240,7 @@ public void testCancelTaskNotSupported() throws Exception { @Test public void testCancelTaskNotFound() { try { - getClient().cancelTask(new TaskIdParams("non-existent-task")); + getClient().cancelTask(new CancelTaskParams("non-existent-task")); fail("Expected A2AClientException for non-existent task"); } catch (A2AClientException e) { // Expected - the client should throw an exception for non-existent tasks 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 277a763cd..0298b8ac6 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 @@ -31,6 +31,7 @@ import io.a2a.server.version.A2AVersionValidator; import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; @@ -145,7 +146,7 @@ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, StreamObserver responseObserver) { try { ServerCallContext context = createCallContext(responseObserver); - TaskIdParams params = FromProto.taskIdParams(request); + CancelTaskParams params = FromProto.cancelTaskParams(request); Task task = getRequestHandler().onCancelTask(params, context); if (task != null) { responseObserver.onNext(ToProto.task(task)); @@ -209,8 +210,8 @@ public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationCon } @Override - public void listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request, - StreamObserver responseObserver) { + public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request, + StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().pushNotifications()) { handleError(responseObserver, new PushNotificationNotSupportedError()); return; @@ -220,7 +221,7 @@ public void listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationC ServerCallContext context = createCallContext(responseObserver); ListTaskPushNotificationConfigParams params = FromProto.listTaskPushNotificationConfigParams(request); ListTaskPushNotificationConfigResult result = getRequestHandler().onListTaskPushNotificationConfig(params, context); - io.a2a.grpc.ListTaskPushNotificationConfigResponse response = ToProto.listTaskPushNotificationConfigResponse(result); + io.a2a.grpc.ListTaskPushNotificationConfigsResponse response = ToProto.listTaskPushNotificationConfigResponse(result); responseObserver.onNext(response); responseObserver.onCompleted(); } catch (A2AError e) { 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 fac5ce02c..1e52a925d 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 @@ -215,7 +215,6 @@ public void testSetPushNotificationConfigSuccess() throws Exception { assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), response.getTaskId()); PushNotificationConfig responseConfig = response.getPushNotificationConfig(); assertEquals("config456", responseConfig.getId()); - assertEquals("config456", response.getId()); assertEquals("http://example.com", responseConfig.getUrl()); assertEquals(AuthenticationInfo.getDefaultInstance(), responseConfig.getAuthentication()); Assertions.assertTrue(responseConfig.getToken().isEmpty()); @@ -241,7 +240,6 @@ public void testGetPushNotificationConfigSuccess() throws Exception { Assertions.assertEquals(1, result.size()); TaskPushNotificationConfig response = result.get(0); assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), response.getTaskId()); - assertEquals("config456", response.getId()); PushNotificationConfig responseConfig = response.getPushNotificationConfig(); assertEquals("config456", responseConfig.getId()); assertEquals("http://example.com", responseConfig.getUrl()); @@ -633,13 +631,13 @@ public void testListPushNotificationConfig() throws Exception { AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); Assertions.assertNull(pushRecorder.getError()); - ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() + ListTaskPushNotificationConfigsRequest request = ListTaskPushNotificationConfigsRequest.newBuilder() .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.listTaskPushNotificationConfig(request, streamRecorder); + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.listTaskPushNotificationConfigs(request, streamRecorder); Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); + List result = streamRecorder.getValues(); Assertions.assertEquals(1, result.size()); List configList = result.get(0).getConfigsList(); Assertions.assertEquals(1, configList.size()); @@ -655,11 +653,11 @@ public void testListPushNotificationConfigNotSupported() throws Exception { agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() + ListTaskPushNotificationConfigsRequest request = ListTaskPushNotificationConfigsRequest.newBuilder() .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.listTaskPushNotificationConfig(request, streamRecorder); + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.listTaskPushNotificationConfigs(request, streamRecorder); assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); } @@ -672,11 +670,11 @@ public void testListPushNotificationConfigNoPushConfigStore() { agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() + ListTaskPushNotificationConfigsRequest request = ListTaskPushNotificationConfigsRequest.newBuilder() .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.listTaskPushNotificationConfig(request, streamRecorder); + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.listTaskPushNotificationConfigs(request, streamRecorder); assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); } @@ -687,11 +685,11 @@ public void testListPushNotificationConfigTaskNotFound() { agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() + ListTaskPushNotificationConfigsRequest request = ListTaskPushNotificationConfigsRequest.newBuilder() .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.listTaskPushNotificationConfig(request, streamRecorder); + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.listTaskPushNotificationConfigs(request, streamRecorder); assertGrpcError(streamRecorder, Status.Code.NOT_FOUND); } @@ -1152,7 +1150,6 @@ private StreamRecorder createTaskPushNotificationCon .build(); CreateTaskPushNotificationConfigRequest setRequest = CreateTaskPushNotificationConfigRequest.newBuilder() .setConfig(config) - .setConfigId("config456") .setTaskId(MINIMAL_TASK.id()) .build(); 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 aa5ad4493..d4de45c82 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 @@ -20,8 +20,8 @@ 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.ListTaskPushNotificationConfigsRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksResult; @@ -226,20 +226,20 @@ public ListTasksResponse onListTasks(ListTasksRequest request, ServerCallContext } } - public ListTaskPushNotificationConfigResponse listPushNotificationConfig( - ListTaskPushNotificationConfigRequest request, ServerCallContext context) { + public ListTaskPushNotificationConfigsResponse listPushNotificationConfig( + ListTaskPushNotificationConfigsRequest request, ServerCallContext context) { if ( !agentCard.capabilities().pushNotifications()) { - return new ListTaskPushNotificationConfigResponse(request.getId(), + return new ListTaskPushNotificationConfigsResponse(request.getId(), new PushNotificationNotSupportedError()); } try { ListTaskPushNotificationConfigResult result = requestHandler.onListTaskPushNotificationConfig(request.getParams(), context); - return new ListTaskPushNotificationConfigResponse(request.getId(), result); + return new ListTaskPushNotificationConfigsResponse(request.getId(), result); } catch (A2AError e) { - return new ListTaskPushNotificationConfigResponse(request.getId(), e); + return new ListTaskPushNotificationConfigsResponse(request.getId(), e); } catch (Throwable t) { - return new ListTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); + return new ListTaskPushNotificationConfigsResponse(request.getId(), new InternalError(t.getMessage())); } } 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 9087a1864..926b9b363 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 @@ -32,8 +32,8 @@ 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.ListTaskPushNotificationConfigsRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; import io.a2a.jsonrpc.common.wrappers.ListTasksResult; @@ -53,6 +53,7 @@ import io.a2a.spec.AgentExtension; import io.a2a.spec.AgentInterface; import io.a2a.spec.Artifact; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.Event; import io.a2a.spec.ExtendedAgentCardNotConfiguredError; @@ -134,7 +135,7 @@ public void testOnCancelTaskSuccess() throws Exception { agentEmitter.cancel(); }; - CancelTaskRequest request = new CancelTaskRequest("111", new TaskIdParams(MINIMAL_TASK.id())); + CancelTaskRequest request = new CancelTaskRequest("111", new CancelTaskParams(MINIMAL_TASK.id())); CancelTaskResponse response = handler.onCancelTask(request, callContext); assertNull(response.getError()); @@ -154,7 +155,7 @@ public void testOnCancelTaskNotSupported() { throw new UnsupportedOperationError(); }; - CancelTaskRequest request = new CancelTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); + CancelTaskRequest request = new CancelTaskRequest("1", new CancelTaskParams(MINIMAL_TASK.id())); CancelTaskResponse response = handler.onCancelTask(request, callContext); assertEquals(request.getId(), response.getId()); assertNull(response.getResult()); @@ -164,7 +165,7 @@ public void testOnCancelTaskNotSupported() { @Test public void testOnCancelTaskNotFound() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - CancelTaskRequest request = new CancelTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); + CancelTaskRequest request = new CancelTaskRequest("1", new CancelTaskParams(MINIMAL_TASK.id())); CancelTaskResponse response = handler.onCancelTask(request, callContext); assertEquals(request.getId(), response.getId()); assertNull(response.getResult()); @@ -1359,9 +1360,9 @@ public void testListPushNotificationConfig() { .url("http://example.com") .id(MINIMAL_TASK.id()) .build(), ""); - ListTaskPushNotificationConfigRequest listRequest - = new ListTaskPushNotificationConfigRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigResponse listResponse = handler.listPushNotificationConfig(listRequest, callContext); + ListTaskPushNotificationConfigsRequest listRequest + = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + ListTaskPushNotificationConfigsResponse listResponse = handler.listPushNotificationConfig(listRequest, callContext); assertEquals("111", listResponse.getId()); assertEquals(1, listResponse.getResult().size()); @@ -1386,9 +1387,9 @@ public void testListPushNotificationConfigNotSupported() { CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); - ListTaskPushNotificationConfigRequest listRequest - = new ListTaskPushNotificationConfigRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigResponse listResponse + ListTaskPushNotificationConfigsRequest listRequest + = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + ListTaskPushNotificationConfigsResponse listResponse = handler.listPushNotificationConfig(listRequest, callContext); assertEquals("111", listResponse.getId()); @@ -1405,9 +1406,9 @@ public void testListPushNotificationConfigNoPushConfigStore() { agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - ListTaskPushNotificationConfigRequest listRequest - = new ListTaskPushNotificationConfigRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigResponse listResponse + ListTaskPushNotificationConfigsRequest listRequest + = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + ListTaskPushNotificationConfigsResponse listResponse = handler.listPushNotificationConfig(listRequest, callContext); assertEquals("111", listResponse.getId()); @@ -1422,9 +1423,9 @@ public void testListPushNotificationConfigTaskNotFound() { agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - ListTaskPushNotificationConfigRequest listRequest - = new ListTaskPushNotificationConfigRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigResponse listResponse + ListTaskPushNotificationConfigsRequest listRequest + = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + ListTaskPushNotificationConfigsResponse listResponse = handler.listPushNotificationConfig(listRequest, callContext); assertEquals("111", listResponse.getId()); 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 7312824c2..68819d8d8 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 @@ -36,6 +36,7 @@ import io.a2a.server.util.async.Internal; import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; @@ -144,12 +145,14 @@ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String t } } - public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, String taskId) { + @SuppressWarnings("unchecked") + public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, String body, String taskId) { try { if (taskId == null || taskId.isEmpty()) { throw new InvalidParamsError(); } - TaskIdParams params = new TaskIdParams(taskId, tenant); + Map metadata =JsonUtil.readMetadata(body); + CancelTaskParams params = CancelTaskParams.builder().id(taskId).tenant(tenant).metadata(metadata).build(); Task task = requestHandler.onCancelTask(params, context); if (task != null) { return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); @@ -184,7 +187,7 @@ public HTTPRestResponse subscribeToTask(ServerCallContext context, String tenant if (!agentCard.capabilities().streaming()) { return createErrorResponse(new InvalidRequestError("Streaming is not supported by the agent")); } - TaskIdParams params = new TaskIdParams(taskId, tenant); + TaskIdParams params = TaskIdParams.builder().id(taskId).tenant(tenant).build(); Flow.Publisher publisher = requestHandler.onSubscribeToTask(params, context); return createStreamingResponse(publisher); } catch (A2AError e) { @@ -293,7 +296,7 @@ public HTTPRestResponse listTaskPushNotificationConfigurations(ServerCallContext } 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))); + return createSuccessResponse(200, io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(ProtoUtils.ToProto.listTaskPushNotificationConfigResponse(result))); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { 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 cc0e8c303..31dcb29f9 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 @@ -174,7 +174,8 @@ public void testCancelTaskSuccess() { agentEmitter.cancel(); }; - RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", MINIMAL_TASK.id()); + String requestBody = String.format("{\"id\":\"%s\"}", MINIMAL_TASK.id()); + RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, MINIMAL_TASK.id()); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); @@ -185,13 +186,107 @@ public void testCancelTaskSuccess() { public void testCancelTaskNotFound() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", "nonexistent"); + String requestBody = "{\"id\":\"nonexistent\"}"; + RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, "nonexistent"); Assertions.assertEquals(404, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("TaskNotFoundError")); } + @Test + public void testCancelTaskWithMetadata() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); + + agentExecutorCancel = (context, agentEmitter) -> { + // Verify metadata is accessible in the context + Task task = context.getTask(); + + // Cancel the task so EventConsumer finds a final event + agentEmitter.cancel(); + }; + + // Request body with metadata + String requestBody = """ + { + "metadata": { + "reason": "user_requested", + "source": "web_ui", + "priority": "high" + } + } + """; + + RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, MINIMAL_TASK.id()); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); + } + + @Test + public void testCancelTaskWithEmptyMetadata() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); + + agentExecutorCancel = (context, agentEmitter) -> { + Task task = context.getTask(); + agentEmitter.cancel(); + }; + + // Request body with empty metadata object + String requestBody = """ + { + "metadata": {} + } + """; + + RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, MINIMAL_TASK.id()); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); + } + + @Test + public void testCancelTaskWithNoMetadata() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); + + agentExecutorCancel = (context, agentEmitter) -> { + Task task = context.getTask(); + agentEmitter.cancel(); + }; + + // Request body without metadata field + String requestBody = "{}"; + + RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, MINIMAL_TASK.id()); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); + } + + @Test + public void testCancelTaskWithNullBody() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); + + agentExecutorCancel = (context, agentEmitter) -> { + Task task = context.getTask(); + agentEmitter.cancel(); + }; + + // Null body should still work - metadata defaults to empty map + RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", null, MINIMAL_TASK.id()); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); + } + @Test public void testSendStreamingMessageSuccess() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); @@ -252,8 +347,8 @@ public void testPushNotificationConfigSuccess() { String requestBody = """ { "taskId": "%s", - "configId": "default-config-id", "config": { + "id": "default-config-id", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" @@ -297,8 +392,8 @@ public void testGetPushNotificationConfig() { String createRequestBody = """ { "taskId": "%s", - "configId": "default-config-id", "config": { + "id": "default-config-id", "url": "https://example.com/callback", "authentication": { "scheme": "jwt" From 432ae59a2022183ae6a6271a8f0aef66d86694a8 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 4 Mar 2026 18:39:58 +0100 Subject: [PATCH 056/192] fix: Add javadoc for grpc transport server-side modules (#680) Fixes #479 --- .../quarkus/A2AExtensionsInterceptor.java | 73 ++++- .../grpc/quarkus/QuarkusGrpcHandler.java | 76 ++++- .../quarkus/QuarkusGrpcTransportMetadata.java | 37 +++ .../a2a/server/grpc/quarkus/package-info.java | 168 ++++++++++ .../grpc/context/GrpcContextKeys.java | 55 +++- .../grpc/handler/CallContextFactory.java | 66 ++++ .../transport/grpc/handler/GrpcHandler.java | 307 ++++++++++++++++++ .../transport/grpc/handler/package-info.java | 45 +++ 8 files changed, 813 insertions(+), 14 deletions(-) create mode 100644 reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java 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 3b0421b44..c024a92f0 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 @@ -13,17 +13,78 @@ /** * gRPC server interceptor that captures request metadata and context information, - * providing equivalent functionality to Python's grpc.aio.ServicerContext. + * providing equivalent functionality to Python's {@code grpc.aio.ServicerContext}. * - * This interceptor: - * - Extracts A2A extension headers from incoming requests - * - Captures ServerCall and Metadata for rich context access - * - Stores context information in gRPC Context for service method access - * - Provides proper equivalence to Python's ServicerContext + *

        This interceptor executes before service methods are invoked, extracting A2A protocol + * headers and request metadata from the gRPC call and storing them in the gRPC {@link Context} + * for access by {@link io.a2a.transport.grpc.handler.GrpcHandler} and agent implementations. + * + *

        Captured Information

        + *
          + *
        • A2A Protocol Version: {@code X-A2A-Version} header
        • + *
        • A2A Extensions: {@code X-A2A-Extensions} header
        • + *
        • Complete Metadata: All request headers via {@link io.grpc.Metadata}
        • + *
        • Method Name: gRPC method being invoked
        • + *
        • Peer Information: Client connection details
        • + *
        + * + *

        Context Storage

        + *

        All captured information is stored in the gRPC {@link Context} using keys from + * {@link io.a2a.transport.grpc.context.GrpcContextKeys}: + *

          + *
        • {@link io.a2a.transport.grpc.context.GrpcContextKeys#VERSION_HEADER_KEY VERSION_HEADER_KEY}
        • + *
        • {@link io.a2a.transport.grpc.context.GrpcContextKeys#EXTENSIONS_HEADER_KEY EXTENSIONS_HEADER_KEY}
        • + *
        • {@link io.a2a.transport.grpc.context.GrpcContextKeys#METADATA_KEY METADATA_KEY}
        • + *
        • {@link io.a2a.transport.grpc.context.GrpcContextKeys#GRPC_METHOD_NAME_KEY GRPC_METHOD_NAME_KEY}
        • + *
        • {@link io.a2a.transport.grpc.context.GrpcContextKeys#METHOD_NAME_KEY METHOD_NAME_KEY}
        • + *
        • {@link io.a2a.transport.grpc.context.GrpcContextKeys#PEER_INFO_KEY PEER_INFO_KEY}
        • + *
        + * + *

        CDI Integration

        + *

        This interceptor is registered as an {@code @ApplicationScoped} CDI bean and automatically + * applied to gRPC services through Quarkus gRPC's {@code @RegisterInterceptor} annotation. + * + *

        Python Equivalence

        + *

        This interceptor provides functionality equivalent to Python's {@code grpc.aio.ServicerContext}, + * enabling Java handlers to access the same rich context information available in Python implementations: + *

          + *
        • {@code context.invocation_metadata()} → {@link io.grpc.Metadata}
        • + *
        • {@code context.method()} → Method name via {@code GRPC_METHOD_NAME_KEY}
        • + *
        • {@code context.peer()} → Peer info via {@code PEER_INFO_KEY}
        • + *
        + * + * @see io.a2a.transport.grpc.context.GrpcContextKeys + * @see io.a2a.transport.grpc.handler.GrpcHandler + * @see io.grpc.ServerInterceptor */ @ApplicationScoped public class A2AExtensionsInterceptor implements ServerInterceptor { + /** + * Intercepts incoming gRPC calls to capture metadata and context information. + * + *

        This method extracts A2A protocol headers and request metadata, stores them + * in the gRPC {@link Context}, and proceeds with the call in the enhanced context. + * + *

        Extraction Process: + *

          + *
        1. Extract {@code X-A2A-Version} header from metadata
        2. + *
        3. Extract {@code X-A2A-Extensions} header from metadata
        4. + *
        5. Capture complete {@link Metadata} object
        6. + *
        7. Capture gRPC method name from {@link ServerCall}
        8. + *
        9. Map gRPC method to A2A protocol method name
        10. + *
        11. Extract peer information from server call attributes
        12. + *
        13. Create enhanced {@link Context} with all captured information
        14. + *
        15. Proceed with call in enhanced context
        16. + *
        + * + * @param the request message type + * @param the response message type + * @param serverCall the gRPC server call + * @param metadata the request metadata (headers) + * @param serverCallHandler the next handler in the interceptor chain + * @return a listener for the server call + */ @Override public ServerCall.Listener interceptCall( ServerCall serverCall, 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 e5f7a27c2..02d441a17 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 @@ -17,6 +17,55 @@ import io.quarkus.security.Authenticated; import org.jspecify.annotations.Nullable; +/** + * Quarkus gRPC service implementation for the A2A protocol. + * + *

        This class provides a production-ready gRPC service built on Quarkus gRPC, + * implementing the A2A protocol with CDI integration, authentication, and + * interceptor support for metadata extraction. + * + *

        CDI Integration

        + *

        This class is a Quarkus gRPC service ({@code @GrpcService}) that automatically: + *

          + *
        • Injects the public {@link AgentCard} (required)
        • + *
        • Injects the extended {@link AgentCard} (optional)
        • + *
        • Injects the {@link RequestHandler} for protocol operations
        • + *
        • Injects the {@link CallContextFactory} for custom context creation (optional)
        • + *
        • Injects the {@link Executor} for async operations
        • + *
        + * + *

        Security

        + *

        The service is protected with {@code @Authenticated} annotation, requiring + * authentication for all gRPC method calls. Configure authentication in + * {@code application.properties}: + *

        + * quarkus.security.users.embedded.enabled=true
        + * quarkus.security.users.embedded.plain-text=true
        + * quarkus.security.users.embedded.users.alice=password
        + * 
        + * + *

        Interceptor Registration

        + *

        The {@code @RegisterInterceptor} annotation automatically registers + * {@link A2AExtensionsInterceptor} to capture A2A protocol headers and + * metadata before service methods are invoked. + * + *

        Extension Points

        + *

        To customize context creation, provide a CDI bean implementing + * {@link CallContextFactory}: + *

        {@code
        + * @ApplicationScoped
        + * public class CustomCallContextFactory implements CallContextFactory {
        + *     @Override
        + *     public  ServerCallContext create(StreamObserver responseObserver) {
        + *         // Custom context creation logic
        + *     }
        + * }
        + * }
        + * + * @see io.a2a.transport.grpc.handler.GrpcHandler + * @see A2AExtensionsInterceptor + * @see CallContextFactory + */ @GrpcService @RegisterInterceptor(A2AExtensionsInterceptor.class) @Authenticated @@ -29,11 +78,30 @@ public class QuarkusGrpcHandler extends GrpcHandler { private final Executor executor; /** - * No-args constructor for CDI proxy creation. - * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. - * All fields are initialized by the @Inject constructor during actual bean creation. + * Constructs a new QuarkusGrpcHandler with CDI-injected dependencies. + * + *

        This constructor is invoked by CDI to create the gRPC service bean, + * injecting all required and optional dependencies. + * + *

        Required Dependencies: + *

          + *
        • {@code agentCard} - Public agent card defining capabilities
        • + *
        • {@code requestHandler} - Request handler for protocol operations
        • + *
        • {@code executor} - Executor for async operations
        • + *
        + * + *

        Optional Dependencies: + *

          + *
        • {@code extendedAgentCard} - Extended agent card (can be unresolvable)
        • + *
        • {@code callContextFactoryInstance} - Custom context factory (can be unsatisfied)
        • + *
        + * + * @param agentCard the public agent card (qualified with {@code @PublicAgentCard}) + * @param extendedAgentCard the extended agent card instance (qualified with {@code @ExtendedAgentCard}) + * @param requestHandler the request handler for protocol operations + * @param callContextFactoryInstance the call context factory instance (optional) + * @param executor the executor for async operations (qualified with {@code @Internal}) */ - @Inject public QuarkusGrpcHandler(@PublicAgentCard AgentCard agentCard, @ExtendedAgentCard Instance extendedAgentCard, diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java index 1a5a7a078..b12635523 100644 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java +++ b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java @@ -3,7 +3,44 @@ import io.a2a.server.TransportMetadata; import io.a2a.spec.TransportProtocol; +/** + * Transport metadata provider for the Quarkus gRPC reference implementation. + * + *

        This class identifies the transport protocol used by the gRPC server implementation. + * It is automatically discovered by the A2A server framework through CDI to provide + * protocol-specific metadata to components that need to distinguish between different + * transport implementations. + * + *

        CDI Integration

        + *

        This bean is automatically registered and can be injected where transport + * protocol information is needed: + *

        {@code
        + * @Inject
        + * TransportMetadata transportMetadata;
        + *
        + * public void logProtocol() {
        + *     String protocol = transportMetadata.getTransportProtocol();
        + *     // Returns "grpc" for this implementation
        + * }
        + * }
        + * + *

        Use Cases

        + *
          + *
        • Identifying the active transport protocol in multi-transport deployments
        • + *
        • Conditional logic based on transport capabilities
        • + *
        • Logging and metrics collection with transport-specific tags
        • + *
        • Protocol-specific error handling or feature detection
        • + *
        + * + * @see io.a2a.server.TransportMetadata + * @see io.a2a.spec.TransportProtocol + */ public class QuarkusGrpcTransportMetadata implements TransportMetadata { + /** + * Returns the transport protocol identifier for gRPC. + * + * @return the string "grpc" identifying this transport implementation + */ @Override public String getTransportProtocol() { return TransportProtocol.GRPC.asString(); diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java new file mode 100644 index 000000000..b61c213f5 --- /dev/null +++ b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java @@ -0,0 +1,168 @@ +/** + * Quarkus gRPC reference implementation for the A2A protocol. + * + *

        This package provides a production-ready gRPC server implementation built on + * Quarkus gRPC and Protocol Buffers, demonstrating best practices for A2A protocol + * integration with CDI, authentication, and interceptor support. + * + *

        Architecture

        + *
        + * gRPC Request (Protocol Buffers)
        + *     ↓
        + * A2AExtensionsInterceptor (metadata extraction)
        + *     ↓
        + * QuarkusGrpcHandler (@GrpcService)
        + *     ├─ Protobuf → Domain conversion
        + *     ├─ Create ServerCallContext
        + *     ├─ Route to GrpcHandler (transport layer)
        + *     └─ Domain → Protobuf conversion
        + *         ↓
        + * GrpcHandler (transport/grpc)
        + *     ↓
        + * RequestHandler (server-common)
        + *     ↓
        + * AgentExecutor (your implementation)
        + * 
        + * + *

        Core Components

        + *
          + *
        • {@link io.a2a.server.grpc.quarkus.QuarkusGrpcHandler QuarkusGrpcHandler} - Main gRPC service implementation
        • + *
        • {@link io.a2a.server.grpc.quarkus.A2AExtensionsInterceptor A2AExtensionsInterceptor} - Metadata extraction interceptor
        • + *
        • {@link io.a2a.server.grpc.quarkus.QuarkusGrpcTransportMetadata QuarkusGrpcTransportMetadata} - Transport protocol identification
        • + *
        + * + *

        gRPC Methods

        + * + *

        Unary RPC (blocking): + *

          + *
        • {@code SendMessage} - Send message and wait for completion
        • + *
        • {@code GetTask} - Get task by ID
        • + *
        • {@code ListTasks} - List tasks with filtering
        • + *
        • {@code CancelTask} - Cancel task execution
        • + *
        • {@code CreateTaskPushNotificationConfig} - Configure push notifications
        • + *
        • {@code GetTaskPushNotificationConfig} - Get push notification config
        • + *
        • {@code ListTaskPushNotificationConfig} - List push notification configs
        • + *
        • {@code DeleteTaskPushNotificationConfig} - Delete push notification config
        • + *
        • {@code GetExtendedAgentCard} - Get extended agent card
        • + *
        + * + *

        Server Streaming RPC: + *

          + *
        • {@code SendStreamingMessage} - Send message with streaming response
        • + *
        • {@code SubscribeToTask} - Subscribe to task events
        • + *
        + * + *

        CDI Integration

        + * + *

        Required CDI Beans: + *

          + *
        • {@link io.a2a.spec.AgentCard AgentCard} with {@code @PublicAgentCard} qualifier
        • + *
        • {@link io.a2a.server.agentexecution.AgentExecutor AgentExecutor} implementation
        • + *
        + * + *

        Optional CDI Beans: + *

          + *
        • {@link io.a2a.spec.AgentCard AgentCard} with {@code @ExtendedAgentCard} qualifier
        • + *
        • {@link io.a2a.transport.grpc.handler.CallContextFactory CallContextFactory} for custom context creation
        • + *
        + * + *

        Usage

        + * + *

        Add Dependency: + *

        {@code
        + * 
        + *   io.github.a2asdk
        + *   a2a-java-sdk-reference-grpc
        + *   ${a2a.version}
        + * 
        + * }
        + * + *

        Provide Agent Card: + *

        {@code
        + * @ApplicationScoped
        + * public class MyAgentCardProducer {
        + *     @Produces @PublicAgentCard
        + *     public AgentCard agentCard() {
        + *         return new AgentCard.Builder()
        + *             .name("My gRPC Agent")
        + *             .description("Agent description")
        + *             .url("http://localhost:9090")
        + *             .capabilities(new AgentCapabilities.Builder()
        + *                 .streaming(true)
        + *                 .build())
        + *             .build();
        + *     }
        + * }
        + * }
        + * + *

        Provide Agent Executor: + *

        {@code
        + * @ApplicationScoped
        + * public class MyAgentExecutorProducer {
        + *     @Produces
        + *     public AgentExecutor agentExecutor() {
        + *         return new MyAgentExecutor();
        + *     }
        + * }
        + * }
        + * + *

        Configuration

        + * + *

        gRPC Server: + *

        + * quarkus.grpc.server.port=9090
        + * quarkus.grpc.server.host=0.0.0.0
        + * 
        + * + *

        Authentication: + *

        + * quarkus.security.users.embedded.enabled=true
        + * quarkus.security.users.embedded.plain-text=true
        + * quarkus.security.users.embedded.users.alice=password
        + * 
        + * + *

        Customization

        + * + *

        Custom Context Creation: + *

        Provide a CDI bean implementing {@link io.a2a.transport.grpc.handler.CallContextFactory CallContextFactory}: + *

        {@code
        + * @ApplicationScoped
        + * public class CustomCallContextFactory implements CallContextFactory {
        + *     @Override
        + *     public  ServerCallContext create(StreamObserver responseObserver) {
        + *         // Extract custom data from gRPC context
        + *         Context grpcContext = Context.current();
        + *         Metadata metadata = GrpcContextKeys.METADATA_KEY.get(grpcContext);
        + *         String orgId = metadata.get(
        + *             Metadata.Key.of("x-organization-id", Metadata.ASCII_STRING_MARSHALLER)
        + *         );
        + *
        + *         Map state = new HashMap<>();
        + *         state.put("organization", orgId);
        + *         state.put("grpc_response_observer", responseObserver);
        + *
        + *         return new ServerCallContext(
        + *             extractUser(),
        + *             state,
        + *             extractExtensions(grpcContext),
        + *             extractVersion(grpcContext)
        + *         );
        + *     }
        + * }
        + * }
        + * + *

        Python Equivalence

        + *

        This implementation provides equivalent functionality to Python's {@code grpc.aio} server: + *

          + *
        • {@code grpc.aio.ServicerContext} → {@link io.grpc.Context} with {@link A2AExtensionsInterceptor}
        • + *
        • {@code context.invocation_metadata()} → {@link io.a2a.transport.grpc.context.GrpcContextKeys#METADATA_KEY}
        • + *
        • {@code context.method()} → {@link io.a2a.transport.grpc.context.GrpcContextKeys#GRPC_METHOD_NAME_KEY}
        • + *
        • {@code context.peer()} → {@link io.a2a.transport.grpc.context.GrpcContextKeys#PEER_INFO_KEY}
        • + *
        + * + * @see io.a2a.server.grpc.quarkus.QuarkusGrpcHandler + * @see io.a2a.server.grpc.quarkus.A2AExtensionsInterceptor + * @see io.a2a.transport.grpc.handler.GrpcHandler + * @see io.a2a.transport.grpc.context.GrpcContextKeys + */ +package io.a2a.server.grpc.quarkus; diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java index a1392f20a..58878c7a3 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java @@ -9,9 +9,33 @@ /** * Shared gRPC context keys for A2A protocol data. * - * These keys provide access to gRPC context information similar to - * Python's grpc.aio.ServicerContext, enabling rich context access - * in service method implementations. + *

        These keys provide access to gRPC context information stored in + * {@link io.grpc.Context}, enabling rich context access in service method + * implementations similar to Python's {@code grpc.aio.ServicerContext}. + * + *

        Usage Example

        + *
        {@code
        + * public void processRequest(ServerCallContext context) {
        + *     // Access gRPC context information
        + *     Context grpcContext = Context.current();
        + *     String method = GrpcContextKeys.GRPC_METHOD_NAME_KEY.get(grpcContext);
        + *     Metadata metadata = GrpcContextKeys.METADATA_KEY.get(grpcContext);
        + *     String peerInfo = GrpcContextKeys.PEER_INFO_KEY.get(grpcContext);
        + *
        + *     // Access A2A protocol headers
        + *     String version = GrpcContextKeys.VERSION_HEADER_KEY.get(grpcContext);
        + *     String extensions = GrpcContextKeys.EXTENSIONS_HEADER_KEY.get(grpcContext);
        + * }
        + * }
        + * + *

        Context Population

        + *

        These context keys are populated by server interceptors (typically + * {@code A2AExtensionsInterceptor}) that capture request metadata and store + * it in the gRPC context before service methods are called. + * + * @see io.grpc.Context + * @see io.grpc.Metadata + * @see io.a2a.server.ServerCallContext */ public final class GrpcContextKeys { @@ -54,9 +78,32 @@ public final class GrpcContextKeys { * Context key for storing the peer information. * Provides access to client connection details. */ - public static final Context.Key PEER_INFO_KEY = + public static final Context.Key PEER_INFO_KEY = Context.key("grpc-peer-info"); + /** + * Mapping from gRPC method names to A2A protocol method names. + * + *

        This mapping translates gRPC protobuf method names to their corresponding + * A2A protocol method name constants for consistent method identification across + * all transports. + * + *

        Method Mappings: + *

          + *
        • SendMessage → SendMessage
        • + *
        • SendStreamingMessage → SendStreamingMessage
        • + *
        • GetTask → GetTask
        • + *
        • ListTask → ListTasks
        • + *
        • CancelTask → CancelTask
        • + *
        • SubscribeToTask → SubscribeToTask
        • + *
        • CreateTaskPushNotification → CreateTaskPushNotificationConfig
        • + *
        • GetTaskPushNotification → GetTaskPushNotificationConfig
        • + *
        • ListTaskPushNotification → ListTaskPushNotificationConfig
        • + *
        • DeleteTaskPushNotification → DeleteTaskPushNotificationConfig
        • + *
        + * + * @see io.a2a.spec.A2AMethods + */ public static final Map METHOD_MAPPING = Map.of( "SendMessage", A2AMethods.SEND_MESSAGE_METHOD, "SendStreamingMessage", A2AMethods.SEND_STREAMING_MESSAGE_METHOD, diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java index f214a51e5..1a52f41bb 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java @@ -3,6 +3,72 @@ import io.a2a.server.ServerCallContext; import io.grpc.stub.StreamObserver; +/** + * Factory interface for creating {@link ServerCallContext} from gRPC request context. + * + *

        This interface provides an extension point for customizing how {@link ServerCallContext} + * instances are created in gRPC applications. The default implementation in {@link GrpcHandler} + * extracts standard information (user, metadata, headers, peer info, protocol version), but + * applications can provide their own implementation to add custom context data. + * + *

        Default Behavior

        + *

        When no CDI bean implementing this interface is provided, {@link GrpcHandler} + * creates contexts with: + *

          + *
        • User authentication from security context
        • + *
        • gRPC metadata (headers)
        • + *
        • Method name and peer information
        • + *
        • A2A protocol version from {@code X-A2A-Version} header
        • + *
        • Required extensions from {@code X-A2A-Extensions} header
        • + *
        • Response observer for gRPC streaming
        • + *
        + * + *

        Custom Implementation Example

        + *
        {@code
        + * @ApplicationScoped
        + * public class CustomCallContextFactory implements CallContextFactory {
        + *     @Override
        + *     public  ServerCallContext create(StreamObserver responseObserver) {
        + *         // Extract custom data from gRPC context
        + *         Context grpcContext = Context.current();
        + *         Metadata metadata = GrpcContextKeys.METADATA_KEY.get(grpcContext);
        + *         String orgId = metadata.get(
        + *             Metadata.Key.of("x-organization-id", Metadata.ASCII_STRING_MARSHALLER)
        + *         );
        + *
        + *         Map state = new HashMap<>();
        + *         state.put("organization", orgId);
        + *         state.put("grpc_response_observer", responseObserver);
        + *
        + *         return new ServerCallContext(
        + *             extractUser(),
        + *             state,
        + *             extractExtensions(grpcContext),
        + *             extractVersion(grpcContext)
        + *         );
        + *     }
        + * }
        + * }
        + * + * @see ServerCallContext + * @see GrpcHandler#createCallContext + * @see io.a2a.transport.grpc.context.GrpcContextKeys + */ public interface CallContextFactory { + /** + * Creates a {@link ServerCallContext} from gRPC request context. + * + *

        This method is called for each incoming gRPC request to create the context + * that will be passed to the {@link io.a2a.server.requesthandlers.RequestHandler} + * and eventually to the {@link io.a2a.server.agentexecution.AgentExecutor}. + * + *

        Implementations should extract information from the current {@link io.grpc.Context} + * using {@link io.a2a.transport.grpc.context.GrpcContextKeys} to access metadata, + * method name, peer info, and A2A protocol headers. + * + * @param the response type for the gRPC method + * @param responseObserver the gRPC response stream observer + * @return a new ServerCallContext with extracted authentication, metadata, and headers + */ ServerCallContext create(StreamObserver responseObserver); } \ No newline at end of file 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 0298b8ac6..9fee45786 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 @@ -65,6 +65,88 @@ import io.grpc.stub.StreamObserver; import org.jspecify.annotations.Nullable; +/** + * gRPC transport handler for processing A2A protocol requests. + * + *

        This abstract class implements the gRPC service interface for the A2A protocol, + * handling both unary (blocking) and server streaming RPC calls. It translates gRPC + * requests to A2A protocol operations, coordinates with the request handler and agent + * executor, and manages error handling with appropriate gRPC status codes. + * + *

        Request Flow

        + *
        + * gRPC Request → GrpcHandler (this class)
        + *     ↓
        + * Protobuf → Domain conversion
        + *     ↓
        + * RequestHandler → AgentExecutor
        + *     ↓
        + * Domain → Protobuf conversion
        + *     ↓
        + * gRPC Response (unary or streaming)
        + * 
        + * + *

        Supported Operations

        + * + *

        Unary RPC (blocking): + *

          + *
        • {@link #sendMessage} - Send message and wait for completion
        • + *
        • {@link #getTask} - Retrieve task by ID
        • + *
        • {@link #cancelTask} - Cancel task execution
        • + *
        • {@link #listTasks} - List tasks with filtering
        • + *
        • {@link #createTaskPushNotificationConfig} - Configure push notifications
        • + *
        • {@link #getTaskPushNotificationConfig} - Get push notification config
        • + *
        • {@link #listTaskPushNotificationConfig} - List push notification configs
        • + *
        • {@link #deleteTaskPushNotificationConfig} - Delete push notification config
        • + *
        • {@link #getExtendedAgentCard} - Get extended agent capabilities
        • + *
        + * + *

        Server Streaming RPC: + *

          + *
        • {@link #sendStreamingMessage} - Send message with streaming response
        • + *
        • {@link #subscribeToTask} - Subscribe to task events
        • + *
        + * + *

        Error Handling

        + *

        A2A errors are mapped to gRPC status codes: + *

          + *
        • {@link io.a2a.spec.InvalidRequestError} → {@link Status#INVALID_ARGUMENT}
        • + *
        • {@link io.a2a.spec.MethodNotFoundError} → {@link Status#NOT_FOUND}
        • + *
        • {@link io.a2a.spec.TaskNotFoundError} → {@link Status#NOT_FOUND}
        • + *
        • {@link io.a2a.spec.InternalError} → {@link Status#INTERNAL}
        • + *
        • {@link io.a2a.spec.UnsupportedOperationError} → {@link Status#UNIMPLEMENTED}
        • + *
        • {@link SecurityException} → {@link Status#UNAUTHENTICATED} or {@link Status#PERMISSION_DENIED}
        • + *
        + * + *

        Context Access

        + *

        The handler provides rich context information equivalent to Python's + * {@code grpc.aio.ServicerContext}: + *

          + *
        • {@link #getCurrentMetadata()} - Request metadata (headers)
        • + *
        • {@link #getCurrentMethodName()} - gRPC method name
        • + *
        • {@link #getCurrentPeerInfo()} - Client connection details
        • + *
        + * + *

        Extension Points

        + *

        Subclasses must implement: + *

          + *
        • {@link #getRequestHandler()} - Request handler instance
        • + *
        • {@link #getAgentCard()} - Public agent card
        • + *
        • {@link #getExtendedAgentCard()} - Extended agent card (nullable)
        • + *
        • {@link #getCallContextFactory()} - Custom context factory (nullable)
        • + *
        • {@link #getExecutor()} - Executor for async operations
        • + *
        + * + *

        CDI Integration

        + *

        This class is marked with {@code @Vetoed} to prevent direct CDI management. + * Subclasses should be CDI beans (e.g., {@code @GrpcService} in Quarkus) that + * inject dependencies and provide them through the abstract methods. + * + * @see io.a2a.grpc.A2AServiceGrpc.A2AServiceImplBase + * @see io.a2a.server.requesthandlers.RequestHandler + * @see CallContextFactory + * @see io.a2a.transport.grpc.context.GrpcContextKeys + */ @Vetoed public abstract class GrpcHandler extends A2AServiceGrpc.A2AServiceImplBase { @@ -76,10 +158,38 @@ public abstract class GrpcHandler extends A2AServiceGrpc.A2AServiceImplBase { private static final Logger LOGGER = Logger.getLogger(GrpcHandler.class.getName()); + /** + * Constructs a new GrpcHandler. + */ public GrpcHandler() { } + /** + * Handles a unary (blocking) message send request. + * + *

        This method processes a message send request, waits for the agent to complete + * processing, and returns either a Task or Message in the response. + * + *

        Protocol Flow: + *

          + *
        1. Validate A2A protocol version and extensions
        2. + *
        3. Convert protobuf request to domain {@link MessageSendParams}
        4. + *
        5. Invoke {@link io.a2a.server.requesthandlers.RequestHandler#onMessageSend}
        6. + *
        7. Convert domain response to protobuf {@link io.a2a.grpc.SendMessageResponse}
        8. + *
        9. Send response and complete the RPC
        10. + *
        + * + *

        Error Handling: + *

          + *
        • {@link A2AError} → mapped to appropriate gRPC status code
        • + *
        • {@link SecurityException} → {@code UNAUTHENTICATED} or {@code PERMISSION_DENIED}
        • + *
        • {@link Throwable} → {@code INTERNAL} error
        • + *
        + * + * @param request the gRPC message send request + * @param responseObserver the gRPC response stream observer + */ @Override public void sendMessage(io.a2a.grpc.SendMessageRequest request, StreamObserver responseObserver) { @@ -233,6 +343,43 @@ public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotification } } + /** + * Handles a server streaming message send request. + * + *

        This method processes a message send request with streaming response, where + * the agent can emit multiple events (artifacts, status updates, messages) as the + * task progresses. + * + *

        Protocol Flow: + *

          + *
        1. Verify streaming capability is enabled in agent card
        2. + *
        3. Validate A2A protocol version and extensions
        4. + *
        5. Convert protobuf request to domain {@link MessageSendParams}
        6. + *
        7. Invoke {@link io.a2a.server.requesthandlers.RequestHandler#onMessageSendStream}
        8. + *
        9. Subscribe to event publisher and stream responses
        10. + *
        11. Convert each domain event to protobuf {@link io.a2a.grpc.StreamResponse}
        12. + *
        13. Complete RPC when final event received or error occurs
        14. + *
        + * + *

        Streaming Characteristics: + *

          + *
        • Server streaming RPC - server sends multiple responses
        • + *
        • Backpressure handled through reactive streams subscription
        • + *
        • Client disconnect detection via gRPC context cancellation
        • + *
        • Automatic cleanup when stream completes or errors
        • + *
        + * + *

        Error Handling: + *

          + *
        • Streaming not enabled → {@link io.a2a.spec.InvalidRequestError}
        • + *
        • Other {@link A2AError} → mapped to appropriate gRPC status code
        • + *
        • {@link SecurityException} → {@code UNAUTHENTICATED} or {@code PERMISSION_DENIED}
        • + *
        • {@link Throwable} → {@code INTERNAL} error
        • + *
        + * + * @param request the gRPC message send request + * @param responseObserver the gRPC response stream observer + */ @Override public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, StreamObserver responseObserver) { @@ -279,6 +426,43 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, } } + /** + * Converts a reactive stream of domain events to gRPC streaming responses. + * + *

        This method subscribes to the event publisher and converts each domain event + * to a protobuf {@link StreamResponse}, handling backpressure through the reactive + * streams subscription and detecting client disconnections. + * + *

        Backpressure Handling: + *

          + *
        1. Request 1 event from upstream
        2. + *
        3. Send event to gRPC response observer
        4. + *
        5. Wait for send completion
        6. + *
        7. Request next event (backpressure)
        8. + *
        + * + *

        Disconnect Detection: + *

        When the gRPC client disconnects: + *

          + *
        1. gRPC Context cancellation listener fires
        2. + *
        3. Invokes {@link ServerCallContext#invokeEventConsumerCancelCallback()}
        4. + *
        5. Cancels upstream subscription
        6. + *
        7. Stops event polling
        8. + *
        + * + *

        Final Event Detection: + *

        The stream completes automatically when a final task status is received: + *

          + *
        • {@code TASK_STATE_COMPLETED}
        • + *
        • {@code TASK_STATE_CANCELED}
        • + *
        • {@code TASK_STATE_FAILED}
        • + *
        • {@code TASK_STATE_REJECTED}
        • + *
        + * + * @param publisher the reactive publisher of streaming events + * @param responseObserver the gRPC response stream observer + * @param context the server call context for disconnect detection + */ private void convertToStreamResponse(Flow.Publisher publisher, StreamObserver responseObserver, ServerCallContext context) { @@ -399,6 +583,42 @@ public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificat } } + /** + * Creates a {@link ServerCallContext} from the current gRPC request context. + * + *

        This method extracts authentication, metadata, and A2A protocol information + * from the gRPC context and packages them into a context object for use by the + * request handler and agent executor. + * + *

        Default Context Creation: + *

        If no {@link CallContextFactory} is provided, creates a context with: + *

          + *
        • User authentication (defaults to {@link UnauthenticatedUser})
        • + *
        • Transport protocol ({@link TransportProtocol#GRPC})
        • + *
        • gRPC response observer for streaming
        • + *
        • gRPC context and metadata (equivalent to Python's ServicerContext)
        • + *
        • HTTP headers extracted from metadata
        • + *
        • gRPC method name
        • + *
        • Peer information (client connection details)
        • + *
        • A2A protocol version from {@code X-A2A-Version} header (via context)
        • + *
        • Required extensions from {@code X-A2A-Extensions} header (via context)
        • + *
        + * + *

        Custom Context Creation: + *

        If a {@link CallContextFactory} bean is present, delegates to + * {@link CallContextFactory#create(StreamObserver)} for custom context creation. + * + *

        Context Information: + *

        The gRPC context information is populated by server interceptors (typically + * {@code A2AExtensionsInterceptor}) that capture request metadata before service + * methods are invoked. + * + * @param the response type for the gRPC method + * @param responseObserver the gRPC response stream observer + * @return the server call context + * @see CallContextFactory + * @see io.a2a.transport.grpc.context.GrpcContextKeys + */ private ServerCallContext createCallContext(StreamObserver responseObserver) { CallContextFactory factory = getCallContextFactory(); if (factory == null) { @@ -464,6 +684,36 @@ private ServerCallContext createCallContext(StreamObserver responseObserv } } + /** + * Handles A2A protocol errors by mapping them to appropriate gRPC status codes. + * + *

        This method converts domain-specific A2A errors to gRPC status codes with + * descriptive error messages, allowing clients to understand and handle errors + * appropriately. + * + *

        Error Mappings: + *

          + *
        • {@link InvalidRequestError} → {@code INVALID_ARGUMENT}
        • + *
        • {@link MethodNotFoundError} → {@code NOT_FOUND}
        • + *
        • {@link InvalidParamsError} → {@code INVALID_ARGUMENT}
        • + *
        • {@link InternalError} → {@code INTERNAL}
        • + *
        • {@link TaskNotFoundError} → {@code NOT_FOUND}
        • + *
        • {@link TaskNotCancelableError} → {@code FAILED_PRECONDITION}
        • + *
        • {@link PushNotificationNotSupportedError} → {@code UNIMPLEMENTED}
        • + *
        • {@link UnsupportedOperationError} → {@code UNIMPLEMENTED}
        • + *
        • {@link JSONParseError} → {@code INTERNAL}
        • + *
        • {@link ContentTypeNotSupportedError} → {@code INVALID_ARGUMENT}
        • + *
        • {@link InvalidAgentResponseError} → {@code INTERNAL}
        • + *
        • {@link ExtendedAgentCardNotConfiguredError} → {@code FAILED_PRECONDITION}
        • + *
        • {@link ExtensionSupportRequiredError} → {@code FAILED_PRECONDITION}
        • + *
        • {@link VersionNotSupportedError} → {@code UNIMPLEMENTED}
        • + *
        • Unknown errors → {@code UNKNOWN}
        • + *
        + * + * @param the response type for the gRPC method + * @param responseObserver the gRPC response stream observer + * @param error the A2A protocol error + */ private void handleError(StreamObserver responseObserver, A2AError error) { Status status; String description; @@ -516,6 +766,23 @@ private void handleError(StreamObserver responseObserver, A2AError error) responseObserver.onError(status.withDescription(description).asRuntimeException()); } + /** + * Handles security-related exceptions by mapping them to gRPC authentication/authorization errors. + * + *

        This method attempts to detect the type of security exception based on the exception + * class name and maps it to the appropriate gRPC status code. + * + *

        Error Detection: + *

          + *
        • Unauthorized/Unauthenticated/Authentication exceptions → {@code UNAUTHENTICATED}
        • + *
        • Forbidden/AccessDenied/Authorization exceptions → {@code PERMISSION_DENIED}
        • + *
        • Other SecurityException → {@code PERMISSION_DENIED} (default)
        • + *
        + * + * @param the response type for the gRPC method + * @param responseObserver the gRPC response stream observer + * @param e the security exception + */ private void handleSecurityException(StreamObserver responseObserver, SecurityException e) { Status status; String description; @@ -575,22 +842,62 @@ private void validateTransportConfigurationWithCorrectClassLoader(AgentCard agen } } + /** + * Returns the deployment classloader for this handler. + * + *

        Used for transport configuration validation with proper classloader context. + * + * @return the deployment classloader + */ protected ClassLoader getDeploymentClassLoader() { return this.getClass().getClassLoader(); } + /** + * Sets a callback to be invoked when streaming subscription starts. + * + *

        This is a testing hook used to synchronize test execution with streaming setup. + * In production, this remains null. + * + * @param runnable the callback to invoke on subscription + */ public static void setStreamingSubscribedRunnable(Runnable runnable) { streamingSubscribedRunnable = runnable; } + /** + * Returns the request handler instance for processing A2A protocol requests. + * + * @return the request handler + */ protected abstract RequestHandler getRequestHandler(); + /** + * Returns the public agent card defining the agent's capabilities and metadata. + * + * @return the agent card + */ protected abstract AgentCard getAgentCard(); + /** + * Returns the extended agent card with additional capabilities, or null if not configured. + * + * @return the extended agent card, or null if not available + */ protected abstract AgentCard getExtendedAgentCard(); + /** + * Returns the custom call context factory, or null to use default context creation. + * + * @return the call context factory, or null for default behavior + */ protected abstract CallContextFactory getCallContextFactory(); + /** + * Returns the executor for running async operations (streaming subscriptions, etc.). + * + * @return the executor + */ protected abstract Executor getExecutor(); /** diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java index 0cc667b2d..b05417c46 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java @@ -2,6 +2,51 @@ * Copyright The WildFly Authors * SPDX-License-Identifier: Apache-2.0 */ + +/** + * gRPC transport handler implementations for the A2A protocol. + * + *

        This package contains the core gRPC handler that processes gRPC requests + * and translates them to A2A protocol operations. It supports both unary (blocking) + * and streaming responses with proper gRPC error handling and status codes. + * + *

        gRPC Protocol

        + *

        This implementation uses Protocol Buffers for message serialization and provides: + *

          + *
        • Unary RPC calls for blocking operations
        • + *
        • Server streaming RPC for streaming responses
        • + *
        • Rich error handling with gRPC status codes
        • + *
        • Context-aware metadata extraction
        • + *
        + * + *

        Supported Methods

        + *
          + *
        • {@code SendMessage} - Send message (unary/blocking)
        • + *
        • {@code SendStreamingMessage} - Send message (server streaming)
        • + *
        • {@code SubscribeToTask} - Subscribe to task updates (server streaming)
        • + *
        • {@code GetTask} - Get task by ID
        • + *
        • {@code ListTasks} - List tasks with filtering
        • + *
        • {@code CancelTask} - Cancel task execution
        • + *
        • {@code GetTaskPushNotificationConfig} - Get push notification config
        • + *
        • {@code CreateTaskPushNotificationConfig} - Create push notification config
        • + *
        • {@code ListTaskPushNotificationConfig} - List push notification configs
        • + *
        • {@code DeleteTaskPushNotificationConfig} - Delete push notification config
        • + *
        • {@code GetExtendedAgentCard} - Get extended agent card
        • + *
        + * + *

        Context Access

        + *

        The gRPC handler provides rich context information equivalent to Python's + * {@code grpc.aio.ServicerContext}, including: + *

          + *
        • Request metadata (headers)
        • + *
        • Method name
        • + *
        • Peer information
        • + *
        • A2A protocol version and extensions
        • + *
        + * + * @see io.a2a.transport.grpc.handler.GrpcHandler + * @see io.a2a.transport.grpc.context.GrpcContextKeys + */ @NullMarked package io.a2a.transport.grpc.handler; From 03fb5394573fe7dc95b4a16a1b7ecf9627aa7117 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 4 Mar 2026 18:40:11 +0100 Subject: [PATCH 057/192] fix: Add javadoc for http-client module (#681) Fixes: #481 --- .../io/a2a/client/http/A2ACardResolver.java | 51 +++++- .../io/a2a/client/http/A2AHttpClient.java | 151 ++++++++++++++++++ .../io/a2a/client/http/A2AHttpResponse.java | 38 +++++ .../io/a2a/client/http/JdkA2AHttpClient.java | 31 ++++ .../java/io/a2a/client/http/package-info.java | 55 +++++++ 5 files changed, 325 insertions(+), 1 deletion(-) 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 b4847cd40..6cbcd949e 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 @@ -19,6 +19,55 @@ import io.a2a.spec.AgentInterface; +/** + * Utility for fetching agent cards from A2A agents. + * + *

        Retrieves agent cards from the standard {@code /.well-known/agent-card.json} endpoint + * with support for tenant-specific paths and authentication headers. + * + *

        Features

        + *
          + *
        • Standard agent card endpoint discovery ({@code /.well-known/agent-card.json})
        • + *
        • Tenant-specific path support ({@code /tenant/.well-known/agent-card.json})
        • + *
        • Custom authentication header injection
        • + *
        • Pluggable HTTP client via {@link A2AHttpClientFactory}
        • + *
        • Support for both public and extended agent cards
        • + *
        + * + *

        Usage Examples

        + *
        {@code
        + * // Basic usage - fetch agent card
        + * A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999");
        + * AgentCard card = resolver.getAgentCard();
        + *
        + * // With tenant path
        + * A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999", "my-tenant");
        + * AgentCard card = resolver.getAgentCard();
        + *
        + * // With custom HTTP client
        + * A2AHttpClient httpClient = A2AHttpClientFactory.create();
        + * A2ACardResolver resolver = new A2ACardResolver(httpClient, "http://localhost:9999", "my-tenant");
        + * AgentCard card = resolver.getAgentCard();
        + *
        + * // With authentication headers
        + * A2AHttpClient httpClient = A2AHttpClientFactory.create();
        + * Map authHeaders = Map.of("Authorization", "Bearer token");
        + * A2ACardResolver resolver = new A2ACardResolver(
        + *     httpClient,
        + *     "http://localhost:9999",
        + *     "my-tenant",
        + *     null,  // use default agent card path
        + *     authHeaders
        + * );
        + * AgentCard card = resolver.getAgentCard();
        + *
        + * // Fetch extended agent card (if available)
        + * AgentCard extendedCard = resolver.getExtendedAgentCard();
        + * }
        + * + * @see AgentCard + * @see A2AHttpClient + */ public class A2ACardResolver { private final A2AHttpClient httpClient; private final String url; @@ -27,7 +76,7 @@ public class A2ACardResolver { private static final String DEFAULT_AGENT_CARD_PATH = "/.well-known/agent-card.json"; /** - * Get the agent card for an A2A agent. An HTTP client will be auto-selected via {@link A2AHttpClientFactory}. + * Creates an agent card resolver. An HTTP client will be auto-selected via {@link A2AHttpClientFactory}. * * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null * @throws A2AClientError if the URL for the agent is invalid diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java b/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java index 9e4f5f705..1529f3e14 100644 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java +++ b/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java @@ -5,43 +5,194 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; +/** + * HTTP client interface for making HTTP requests to A2A agents. + * + *

        Provides a fluent builder API for constructing and executing HTTP requests + * with support for GET, POST, and DELETE methods. Includes support for both + * synchronous requests and asynchronous Server-Sent Events (SSE) streaming. + * + *

        Usage Example

        + *
        {@code
        + * A2AHttpClient client = A2AHttpClientFactory.create();
        + *
        + * // Synchronous GET request
        + * A2AHttpResponse response = client.createGet()
        + *     .url("http://localhost:9999/api/endpoint")
        + *     .addHeader("Authorization", "Bearer token")
        + *     .get();
        + *
        + * // Synchronous POST request
        + * A2AHttpResponse response = client.createPost()
        + *     .url("http://localhost:9999/message:send")
        + *     .body("{\"message\": \"Hello\"}")
        + *     .post();
        + *
        + * // Asynchronous SSE streaming
        + * CompletableFuture future = client.createPost()
        + *     .url("http://localhost:9999/message:stream")
        + *     .body(jsonBody)
        + *     .postAsyncSSE(
        + *         message -> System.out.println("Event: " + message),
        + *         error -> System.err.println("Error: " + error),
        + *         () -> System.out.println("Stream complete")
        + *     );
        + * }
        + * + * @see A2AHttpClientFactory + * @see A2AHttpResponse + */ public interface A2AHttpClient { + /** HTTP Content-Type header name. */ String CONTENT_TYPE= "Content-Type"; + /** JSON content type value. */ String APPLICATION_JSON= "application/json"; + /** HTTP Accept header name. */ String ACCEPT = "Accept"; + /** SSE event stream content type. */ String EVENT_STREAM = "text/event-stream"; + /** + * Creates a builder for GET requests. + * + * @return a new GetBuilder instance + */ GetBuilder createGet(); + /** + * Creates a builder for POST requests. + * + * @return a new PostBuilder instance + */ PostBuilder createPost(); + /** + * Creates a builder for DELETE requests. + * + * @return a new DeleteBuilder instance + */ DeleteBuilder createDelete(); + /** + * Base builder interface for HTTP requests. + * + * @param the concrete builder type for method chaining + */ interface Builder> { + /** + * Sets the target URL for the request. + * + * @param s the URL string + * @return this builder for chaining + */ T url(String s); + + /** + * Adds multiple HTTP headers to the request. + * + * @param headers map of header names to values + * @return this builder for chaining + */ T addHeaders(Map headers); + + /** + * Adds a single HTTP header to the request. + * + * @param name the header name + * @param value the header value + * @return this builder for chaining + */ T addHeader(String name, String value); } + /** + * Builder for HTTP GET requests. + * + *

        Supports both synchronous requests and asynchronous Server-Sent Events (SSE) streaming. + */ interface GetBuilder extends Builder { + /** + * Executes a synchronous GET request. + * + * @return the HTTP response + * @throws IOException if an I/O error occurs + * @throws InterruptedException if the operation is interrupted + */ A2AHttpResponse get() throws IOException, InterruptedException; + + /** + * Executes an asynchronous GET request expecting Server-Sent Events (SSE). + * + *

        The request will stream SSE messages asynchronously, invoking the provided + * consumers for each event, error, or completion. + * + * @param messageConsumer callback for each SSE message received + * @param errorConsumer callback for errors during streaming + * @param completeRunnable callback when the stream completes normally + * @return a CompletableFuture that completes when streaming ends + * @throws IOException if an I/O error occurs + * @throws InterruptedException if the operation is interrupted + */ CompletableFuture getAsyncSSE( Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException; } + /** + * Builder for HTTP POST requests. + * + *

        Supports both synchronous requests and asynchronous Server-Sent Events (SSE) streaming. + */ interface PostBuilder extends Builder { + /** + * Sets the request body content. + * + * @param body the request body string (typically JSON) + * @return this builder for chaining + */ PostBuilder body(String body); + + /** + * Executes a synchronous POST request. + * + * @return the HTTP response + * @throws IOException if an I/O error occurs + * @throws InterruptedException if the operation is interrupted + */ A2AHttpResponse post() throws IOException, InterruptedException; + + /** + * Executes an asynchronous POST request expecting Server-Sent Events (SSE). + * + *

        The request will stream SSE messages asynchronously, invoking the provided + * consumers for each event, error, or completion. + * + * @param messageConsumer callback for each SSE message received + * @param errorConsumer callback for errors during streaming + * @param completeRunnable callback when the stream completes normally + * @return a CompletableFuture that completes when streaming ends + * @throws IOException if an I/O error occurs + * @throws InterruptedException if the operation is interrupted + */ CompletableFuture postAsyncSSE( Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException; } + /** + * Builder for HTTP DELETE requests. + */ interface DeleteBuilder extends Builder { + /** + * Executes a synchronous DELETE request. + * + * @return the HTTP response + * @throws IOException if an I/O error occurs + * @throws InterruptedException if the operation is interrupted + */ A2AHttpResponse delete() throws IOException, InterruptedException; } } diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java b/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java index 171fceebd..837636bcc 100644 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java +++ b/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java @@ -1,9 +1,47 @@ package io.a2a.client.http; +/** + * HTTP response wrapper containing status code and response body. + * + *

        Provides access to the HTTP status code, a success indicator, and the + * response body content. + * + *

        Usage Example

        + *
        {@code
        + * A2AHttpResponse response = client.createGet()
        + *     .url("http://localhost:9999/api/endpoint")
        + *     .get();
        + *
        + * if (response.success()) {
        + *     String body = response.body();
        + *     // Process successful response
        + * } else {
        + *     int status = response.status();
        + *     // Handle error based on status code
        + * }
        + * }
        + */ public interface A2AHttpResponse { + /** + * Returns the HTTP status code. + * + * @return the HTTP status code (e.g., 200, 404, 500) + */ int status(); + /** + * Indicates whether the request was successful. + * + *

        Typically returns {@code true} for 2xx status codes. + * + * @return {@code true} if the request was successful, {@code false} otherwise + */ boolean success(); + /** + * Returns the response body content as a string. + * + * @return the response body, may be empty but not null + */ String body(); } diff --git a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java b/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java index d5bc68651..c04596360 100644 --- a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java +++ b/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java @@ -25,10 +25,41 @@ import io.a2a.common.A2AErrorMessages; +/** + * Default HTTP client implementation using JDK 11+ {@link HttpClient}. + * + *

        This is the fallback implementation used when no higher-priority + * {@link A2AHttpClientProvider} is available. It provides full support for: + *

          + *
        • HTTP/2 with automatic fallback to HTTP/1.1
        • + *
        • Synchronous GET, POST, and DELETE requests
        • + *
        • Asynchronous Server-Sent Events (SSE) streaming
        • + *
        • Automatic redirect following
        • + *
        + * + *

        Provider Priority: 0 (lowest - used as fallback) + * + *

        This implementation is registered via {@link JdkA2AHttpClientProvider} + * in the ServiceLoader system and is automatically used by {@link A2AHttpClientFactory} + * when no other provider is available. + * + * @see A2AHttpClient + * @see A2AHttpClientFactory + * @see JdkA2AHttpClientProvider + */ public class JdkA2AHttpClient implements A2AHttpClient { private final HttpClient httpClient; + /** + * Creates a new JDK-based HTTP client. + * + *

        Configures the client with: + *

          + *
        • HTTP/2 preferred (with HTTP/1.1 fallback)
        • + *
        • Normal redirect following
        • + *
        + */ public JdkA2AHttpClient() { httpClient = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) diff --git a/http-client/src/main/java/io/a2a/client/http/package-info.java b/http-client/src/main/java/io/a2a/client/http/package-info.java index 525333cf1..667c28f5a 100644 --- a/http-client/src/main/java/io/a2a/client/http/package-info.java +++ b/http-client/src/main/java/io/a2a/client/http/package-info.java @@ -1,3 +1,58 @@ +/** + * HTTP client utilities for A2A protocol communication. + * + *

        This package provides a pluggable HTTP client abstraction for making HTTP requests + * to A2A agents, including support for fetching agent cards, synchronous requests, and + * Server-Sent Events (SSE) streaming. + * + *

        Core Components

        + *
          + *
        • {@link io.a2a.client.http.A2AHttpClient} - Main HTTP client interface with builder pattern
        • + *
        • {@link io.a2a.client.http.A2AHttpClientFactory} - Factory for creating client instances via ServiceLoader
        • + *
        • {@link io.a2a.client.http.A2ACardResolver} - Utility for fetching agent cards from standard endpoints
        • + *
        • {@link io.a2a.client.http.A2AHttpResponse} - Response wrapper with status and body
        • + *
        + * + *

        Provider System

        + *

        The module uses a ServiceLoader-based provider system allowing different HTTP client + * implementations to be plugged in: + *

          + *
        • {@link io.a2a.client.http.JdkA2AHttpClient} - Default implementation using JDK 11+ HttpClient (priority 0)
        • + *
        • VertxA2AHttpClient - Vertx-based implementation when available (priority 100)
        • + *
        + * + *

        Usage Example

        + *
        {@code
        + * // Fetch an agent card
        + * A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999");
        + * AgentCard card = resolver.getAgentCard();
        + *
        + * // Make HTTP requests
        + * A2AHttpClient client = A2AHttpClientFactory.create();
        + * A2AHttpResponse response = client.createGet()
        + *     .url("http://localhost:9999/api/endpoint")
        + *     .addHeader("Authorization", "Bearer token")
        + *     .get();
        + *
        + * // Server-Sent Events (SSE) streaming
        + * client.createPost()
        + *     .url("http://localhost:9999/message:stream")
        + *     .body(jsonBody)
        + *     .postAsyncSSE(
        + *         message -> System.out.println("Received: " + message),
        + *         error -> System.err.println("Error: " + error),
        + *         () -> System.out.println("Stream complete")
        + *     );
        + * }
        + * + *

        Agent Card Resolution

        + *

        Agent cards are fetched from the standard {@code /.well-known/agent-card.json} endpoint + * by default, with support for tenant-specific paths and custom authentication headers. + * + * @see io.a2a.client.http.A2AHttpClient + * @see io.a2a.client.http.A2ACardResolver + * @see io.a2a.spec.AgentCard + */ @NullMarked package io.a2a.client.http; From a6bb10aae9e51588f5121ebdacfd02681f526c81 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 4 Mar 2026 18:50:46 +0100 Subject: [PATCH 058/192] feat: Add tests for AUTH_REQUIRED (#684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #504 🦕 --- .../DefaultRequestHandler.java | 12 +- .../DefaultRequestHandlerTest.java | 512 ++++++++++++++++++ .../server/tasks/ResultAggregatorTest.java | 183 +++++++ .../apps/common/AbstractA2AServerTest.java | 126 +++++ .../apps/common/AgentExecutorProducer.java | 25 + 5 files changed, 857 insertions(+), 1 deletion(-) 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 65d622f5d..34969f89c 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 @@ -496,7 +496,17 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte pushConfigStore.setInfo(createdTask.id(), params.configuration().pushNotificationConfig()); } - if (blocking && interruptedOrNonBlocking) { + // Check if task requires immediate return (AUTH_REQUIRED) + // AUTH_REQUIRED expects the client to receive it immediately and handle it out-of-band, + // while the agent continues executing in the background + boolean requiresImmediateReturn = kind instanceof Task task && + task.status().state() == io.a2a.spec.TaskState.TASK_STATE_AUTH_REQUIRED; + if (requiresImmediateReturn) { + LOGGER.debug("DefaultRequestHandler: Task {} in AUTH_REQUIRED state, skipping fire-and-forget handling", + taskId.get()); + } + + if (blocking && interruptedOrNonBlocking && !requiresImmediateReturn) { // For blocking calls: ensure all consumed events are persisted to TaskStore before returning // Order of operations is critical to avoid circular dependency and race conditions: // 1. Wait for agent to finish enqueueing events (or timeout) 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 e69de29bb..00db599f2 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 @@ -0,0 +1,512 @@ +package io.a2a.server.requesthandlers; + +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 java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import io.a2a.server.ServerCallContext; +import io.a2a.server.agentexecution.AgentExecutor; +import io.a2a.server.agentexecution.RequestContext; +import io.a2a.server.events.EventQueue; +import io.a2a.server.events.EventQueueItem; +import io.a2a.server.events.EventQueueUtil; +import io.a2a.server.events.InMemoryQueueManager; +import io.a2a.server.events.MainEventBus; +import io.a2a.server.events.MainEventBusProcessor; +import io.a2a.server.tasks.AgentEmitter; +import io.a2a.server.tasks.InMemoryPushNotificationConfigStore; +import io.a2a.server.tasks.InMemoryTaskStore; +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.Event; +import io.a2a.spec.EventKind; +import io.a2a.spec.Message; +import io.a2a.spec.MessageSendConfiguration; +import io.a2a.spec.MessageSendParams; +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.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Integration tests for DefaultRequestHandler focusing on AUTH_REQUIRED workflow. + * Tests verify the special interrupt behavior where AUTH_REQUIRED tasks: + * 1. Return immediately to the client + * 2. Continue agent execution in background + * 3. Keep queues open for late events + * 4. Perform async cleanup + */ +public class DefaultRequestHandlerTest { + + private static final MessageSendConfiguration DEFAULT_CONFIG = MessageSendConfiguration.builder() + .blocking(false) + .acceptedOutputModes(List.of()) + .build(); + + private static final ServerCallContext NULL_CONTEXT = null; + + private static final Message MESSAGE = Message.builder() + .messageId("111") + .role(Message.Role.ROLE_AGENT) + .parts(new TextPart("test message")) + .build(); + + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + + // Test infrastructure components + protected AgentExecutor executor; + protected TaskStore taskStore; + protected RequestHandler requestHandler; + protected InMemoryQueueManager queueManager; + protected MainEventBus mainEventBus; + protected MainEventBusProcessor mainEventBusProcessor; + protected AgentExecutorMethod agentExecutorExecute; + protected AgentExecutorMethod agentExecutorCancel; + + protected final Executor internalExecutor = Executors.newCachedThreadPool(); + + @BeforeEach + public void init() { + // Create test AgentExecutor with mocked execute/cancel methods + executor = new AgentExecutor() { + @Override + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + if (agentExecutorExecute != null) { + agentExecutorExecute.invoke(context, agentEmitter); + } + } + + @Override + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + if (agentExecutorCancel != null) { + agentExecutorCancel.invoke(context, agentEmitter); + } + } + }; + + // Set up infrastructure + InMemoryTaskStore inMemoryTaskStore = new InMemoryTaskStore(); + taskStore = inMemoryTaskStore; + + PushNotificationConfigStore pushConfigStore = new InMemoryPushNotificationConfigStore(); + + // Create MainEventBus and MainEventBusProcessor + mainEventBus = new MainEventBus(); + queueManager = new InMemoryQueueManager(inMemoryTaskStore, mainEventBus); + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); + EventQueueUtil.start(mainEventBusProcessor); + + // Create DefaultRequestHandler + requestHandler = DefaultRequestHandler.create( + executor, taskStore, queueManager, pushConfigStore, mainEventBusProcessor, internalExecutor, internalExecutor); + } + + @AfterEach + public void cleanup() { + agentExecutorExecute = null; + agentExecutorCancel = null; + + // Stop MainEventBusProcessor background thread + if (mainEventBusProcessor != null) { + EventQueueUtil.stop(mainEventBusProcessor); + } + } + + /** + * Functional interface for test agent executor methods. + */ + protected interface AgentExecutorMethod { + void invoke(RequestContext context, AgentEmitter agentEmitter) throws A2AError; + } + + /** + * Test 1: Non-streaming AUTH_REQUIRED returns immediately while agent continues. + * Verifies: + * - Task returned immediately with AUTH_REQUIRED state + * - Agent still running in background (not blocked) + * - TaskStore persisted AUTH_REQUIRED state + * - Agent completes after release + * - Final state persisted to TaskStore + */ + @Test + void testAuthRequired_NonStreaming_ReturnsImmediately() throws Exception { + // Arrange: Set up agent that emits AUTH_REQUIRED then waits + CountDownLatch authRequiredEmitted = new CountDownLatch(1); + CountDownLatch continueAgent = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + // Emit AUTH_REQUIRED - client should receive immediately + emitter.requiresAuth(Message.builder() + .role(Message.Role.ROLE_AGENT) + .parts(new TextPart("Please authenticate with OAuth provider")) + .build()); + authRequiredEmitted.countDown(); + + // Agent continues processing (simulating waiting for out-of-band auth) + try { + continueAgent.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + + // Complete after "auth received" + emitter.complete(); + }; + + // Create MessageSendParams + MessageSendParams params = MessageSendParams.builder() + .message(MESSAGE) + .configuration(DEFAULT_CONFIG) + .build(); + + // Act: Send message (non-streaming) + EventKind eventKind = requestHandler.onMessageSend(params, NULL_CONTEXT); + + // Assert: Task returned immediately with AUTH_REQUIRED state + assertNotNull(eventKind, "Result should not be null"); + assertInstanceOf(Task.class, eventKind, "Result should be a Task"); + Task result = (Task) eventKind; + + assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, result.status().state(), + "Task should be in AUTH_REQUIRED state"); + assertTrue(authRequiredEmitted.await(2, TimeUnit.SECONDS), + "AUTH_REQUIRED should be emitted quickly"); + + // Verify agent still running (continueAgent latch not counted down yet) + assertFalse(continueAgent.await(100, TimeUnit.MILLISECONDS), + "Agent should still be waiting (not completed yet)"); + + // Verify TaskStore has AUTH_REQUIRED state + Task storedTask = taskStore.get(result.id()); + assertNotNull(storedTask, "Task should be persisted in TaskStore"); + assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, storedTask.status().state(), + "TaskStore should have AUTH_REQUIRED state"); + + // Release agent to complete + continueAgent.countDown(); + + // Wait for completion and verify final state + Thread.sleep(1000); // Allow time for completion to process through MainEventBus + Task finalTask = taskStore.get(result.id()); + assertEquals(TaskState.TASK_STATE_COMPLETED, finalTask.status().state(), + "TaskStore should have COMPLETED state after agent finishes"); + } + + /** + * Test 2: Queue remains open after AUTH_REQUIRED for late events. + * Verifies: + * - Queue stays open after AUTH_REQUIRED response + * - Can tap into queue after AUTH_REQUIRED + * - Late artifacts arrive on tapped queue + * - Completion event arrives on tapped queue + */ + @Test + void testAuthRequired_QueueRemainsOpen() throws Exception { + // Arrange: Agent emits AUTH_REQUIRED then continues with late events + CountDownLatch authEmitted = new CountDownLatch(1); + CountDownLatch continueAgent = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + // Emit AUTH_REQUIRED + emitter.requiresAuth(Message.builder() + .role(Message.Role.ROLE_AGENT) + .parts(new TextPart("Authenticate required")) + .build()); + authEmitted.countDown(); + + // Wait for test to tap queue + try { + continueAgent.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + + // Emit late artifact after AUTH_REQUIRED + emitter.addArtifact(List.of(new TextPart("Late artifact after auth"))); + emitter.complete(); + }; + + // Create MessageSendParams + MessageSendParams params = MessageSendParams.builder() + .message(MESSAGE) + .configuration(DEFAULT_CONFIG) + .build(); + + // Act: Send message, get AUTH_REQUIRED response + EventKind eventKind = requestHandler.onMessageSend(params, NULL_CONTEXT); + assertInstanceOf(Task.class, eventKind); + Task task = (Task) eventKind; + + assertTrue(authEmitted.await(2, TimeUnit.SECONDS), + "AUTH_REQUIRED should be emitted"); + + // Tap into the queue (simulates client resubscription after AUTH_REQUIRED) + EventQueue tappedQueue = queueManager.tap(task.id()); + assertNotNull(tappedQueue, "Queue should remain open after AUTH_REQUIRED"); + + // Release agent to continue and emit late events + continueAgent.countDown(); + + // Assert: Late events arrive on tapped queue + + // First event should be the late artifact + EventQueueItem item = tappedQueue.dequeueEventItem(5000); + assertNotNull(item, "Should receive late artifact event"); + Event event = item.getEvent(); + assertInstanceOf(TaskArtifactUpdateEvent.class, event, + "First event should be TaskArtifactUpdateEvent"); + + // Second event should be completion + item = tappedQueue.dequeueEventItem(5000); + assertNotNull(item, "Should receive completion event"); + event = item.getEvent(); + assertInstanceOf(TaskStatusUpdateEvent.class, event, + "Second event should be TaskStatusUpdateEvent"); + assertEquals(TaskState.TASK_STATE_COMPLETED, + ((TaskStatusUpdateEvent) event).status().state(), + "Task should be completed"); + } + + /** + * Test 3: TaskStore persistence through AUTH_REQUIRED lifecycle. + * Verifies: + * - AUTH_REQUIRED state persisted correctly + * - State transitions persisted (AUTH_REQUIRED → WORKING → COMPLETED) + * - TaskStore always reflects current state + */ + @Test + void testAuthRequired_TaskStorePersistence() throws Exception { + // Arrange: Agent emits AUTH_REQUIRED, then WORKING, then COMPLETED + CountDownLatch authEmitted = new CountDownLatch(1); + CountDownLatch continueAgent = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + // Emit AUTH_REQUIRED + emitter.requiresAuth(); + authEmitted.countDown(); + + // Wait for test to verify AUTH_REQUIRED persisted + try { + continueAgent.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + + // Continue working (simulating auth received out-of-band) + emitter.startWork(); + + // Complete the task + emitter.complete(); + }; + + // Create MessageSendParams + MessageSendParams params = MessageSendParams.builder() + .message(MESSAGE) + .configuration(DEFAULT_CONFIG) + .build(); + + // Act: Send message + EventKind eventKind = requestHandler.onMessageSend(params, NULL_CONTEXT); + assertInstanceOf(Task.class, eventKind); + Task task = (Task) eventKind; + + assertTrue(authEmitted.await(2, TimeUnit.SECONDS), + "AUTH_REQUIRED should be emitted"); + + // Assert: Verify AUTH_REQUIRED state persisted + Task storedTask1 = taskStore.get(task.id()); + assertNotNull(storedTask1, "Task should be in TaskStore"); + assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, storedTask1.status().state(), + "TaskStore should have AUTH_REQUIRED state"); + + // Release agent to continue + continueAgent.countDown(); + + // Wait for state transitions to process + Thread.sleep(1000); + + // Verify WORKING state persisted + Task storedTask2 = taskStore.get(task.id()); + // Note: WORKING might be skipped if processing is fast, so we accept either WORKING or COMPLETED + TaskState state2 = storedTask2.status().state(); + assertTrue(state2 == TaskState.TASK_STATE_WORKING || state2 == TaskState.TASK_STATE_COMPLETED, + "TaskStore should have WORKING or COMPLETED state"); + + // Wait a bit more and verify final COMPLETED state + Thread.sleep(500); + Task storedTask3 = taskStore.get(task.id()); + assertEquals(TaskState.TASK_STATE_COMPLETED, storedTask3.status().state(), + "TaskStore should have COMPLETED state after agent finishes"); + } + + /** + * Test 4: Streaming with AUTH_REQUIRED continues in background. + * Verifies: + * - Client receives AUTH_REQUIRED in stream + * - Agent continues emitting artifacts after AUTH_REQUIRED + * - Artifacts stream to client + * - Completion event arrives in stream + */ + @Test + void testAuthRequired_Streaming_ContinuesInBackground() throws Exception { + // Arrange: Agent emits AUTH_REQUIRED, then streams artifacts + CountDownLatch authEmitted = new CountDownLatch(1); + CountDownLatch continueAgent = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + // Emit AUTH_REQUIRED + emitter.requiresAuth(); + authEmitted.countDown(); + + // Wait briefly (simulating auth happening out-of-band) + try { + continueAgent.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + + // Continue streaming artifacts + emitter.addArtifact(List.of(new TextPart("Artifact 1"))); + emitter.addArtifact(List.of(new TextPart("Artifact 2"))); + emitter.complete(); + }; + + // Create MessageSendParams + MessageSendParams params = MessageSendParams.builder() + .message(MESSAGE) + .configuration(DEFAULT_CONFIG) + .build(); + + // Act: Send message with streaming enabled + EventKind eventKind = requestHandler.onMessageSend(params, NULL_CONTEXT); + assertInstanceOf(Task.class, eventKind); + Task result = (Task) eventKind; + + assertTrue(authEmitted.await(2, TimeUnit.SECONDS), + "AUTH_REQUIRED should be emitted"); + + // Verify AUTH_REQUIRED received + assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, result.status().state(), + "Should receive AUTH_REQUIRED state"); + + // Tap queue to receive subsequent events + EventQueue tappedQueue = queueManager.tap(result.id()); + + // Release agent to continue streaming + continueAgent.countDown(); + + // Assert: Verify artifacts stream through + EventQueueItem item1 = tappedQueue.dequeueEventItem(5000); + assertNotNull(item1, "Should receive first artifact"); + assertInstanceOf(TaskArtifactUpdateEvent.class, item1.getEvent()); + + EventQueueItem item2 = tappedQueue.dequeueEventItem(5000); + assertNotNull(item2, "Should receive second artifact"); + assertInstanceOf(TaskArtifactUpdateEvent.class, item2.getEvent()); + + // Verify completion arrives + EventQueueItem completionItem = tappedQueue.dequeueEventItem(5000); + assertNotNull(completionItem, "Should receive completion"); + Event completionEvent = completionItem.getEvent(); + assertInstanceOf(TaskStatusUpdateEvent.class, completionEvent); + assertEquals(TaskState.TASK_STATE_COMPLETED, + ((TaskStatusUpdateEvent) completionEvent).status().state()); + } + + /** + * Test 5: Resubscription after AUTH_REQUIRED works correctly. + * Verifies: + * - Queue stays open after AUTH_REQUIRED and client disconnect + * - Can resubscribe (tap) after AUTH_REQUIRED + * - Late events received on resubscribed queue + * - Completion event arrives on resubscribed queue + */ + @Test + void testAuthRequired_Resubscription() throws Exception { + // Arrange: Agent emits AUTH_REQUIRED, simulates client disconnect, then continues + CountDownLatch authEmitted = new CountDownLatch(1); + CountDownLatch continueAgent = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + // Emit AUTH_REQUIRED + emitter.requiresAuth(); + authEmitted.countDown(); + + // Wait for test to simulate disconnect and resubscribe + try { + continueAgent.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + + // Emit late events after "client reconnect" + emitter.addArtifact(List.of(new TextPart("Event after reconnect"))); + emitter.complete(); + }; + + // Create MessageSendParams + MessageSendParams params = MessageSendParams.builder() + .message(MESSAGE) + .configuration(DEFAULT_CONFIG) + .build(); + + // Act: Send message, get AUTH_REQUIRED + EventKind eventKind = requestHandler.onMessageSend(params, NULL_CONTEXT); + assertInstanceOf(Task.class, eventKind); + Task task = (Task) eventKind; + + assertTrue(authEmitted.await(2, TimeUnit.SECONDS), + "AUTH_REQUIRED should be emitted"); + + assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, task.status().state(), + "Should receive AUTH_REQUIRED state"); + + // Simulate client disconnect by just waiting + Thread.sleep(100); + + // Client reconnects: tap into queue (resubscription) + EventQueue resubscribedQueue = queueManager.tap(task.id()); + assertNotNull(resubscribedQueue, + "Should be able to resubscribe after AUTH_REQUIRED"); + + // Release agent to continue + continueAgent.countDown(); + + // Assert: Late events arrive on resubscribed queue + EventQueueItem item = resubscribedQueue.dequeueEventItem(5000); + assertNotNull(item, "Should receive late artifact on resubscribed queue"); + assertInstanceOf(TaskArtifactUpdateEvent.class, item.getEvent(), + "Should receive artifact update event"); + + // Verify completion arrives + EventQueueItem completionItem = resubscribedQueue.dequeueEventItem(5000); + assertNotNull(completionItem, "Should receive completion event"); + Event completionEvent = completionItem.getEvent(); + assertInstanceOf(TaskStatusUpdateEvent.class, completionEvent, + "Should receive status update event"); + assertEquals(TaskState.TASK_STATE_COMPLETED, + ((TaskStatusUpdateEvent) completionEvent).status().state(), + "Task should be completed"); + } +} diff --git a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java index fa4eb8ef5..a347d9cd0 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java @@ -1,6 +1,7 @@ package io.a2a.server.tasks; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.atMost; @@ -27,6 +28,7 @@ import io.a2a.spec.Task; 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.BeforeEach; @@ -278,4 +280,185 @@ void testConsumeAndBreakNonBlocking() throws Exception { // Cleanup: stop the processor EventQueueUtil.stop(processor); } + + // AUTH_REQUIRED Tests + + @Test + void testConsumeAndBreakOnAuthRequired_Blocking() throws Exception { + // Test that AUTH_REQUIRED with blocking=true sets interrupted=true and continues consumption in background + String taskId = "auth-required-blocking-task"; + Task authRequiredTask = createSampleTask(taskId, TaskState.TASK_STATE_AUTH_REQUIRED, "ctx1"); + + when(mockTaskManager.getTask()).thenReturn(authRequiredTask); + + // Create event queue infrastructure + MainEventBus mainEventBus = new MainEventBus(); + InMemoryTaskStore taskStore = new InMemoryTaskStore(); + InMemoryQueueManager queueManager = + new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + EventQueueUtil.start(processor); + + EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); + + try { + // Enqueue AUTH_REQUIRED task using callback pattern + waitForEventProcessing(processor, () -> queue.enqueueEvent(authRequiredTask)); + + // Create EventConsumer + EventConsumer eventConsumer = new EventConsumer(queue); + + // Call consumeAndBreakOnInterrupt with blocking=true + ResultAggregator.EventTypeAndInterrupt result = + aggregator.consumeAndBreakOnInterrupt(eventConsumer, true); + + // Assert: interrupted=true for AUTH_REQUIRED + assertTrue(result.interrupted(), "AUTH_REQUIRED should trigger interrupt in blocking mode"); + assertEquals(authRequiredTask, result.eventType(), "Event type should be the AUTH_REQUIRED task"); + + // Verify consumption continues in background (consumptionFuture should be running) + // For blocking mode, the consumption future should complete after processing + assertNotNull(result, "Result should not be null"); + } finally { + queue.close(); + EventQueueUtil.stop(processor); + } + } + + @Test + void testConsumeAndBreakOnAuthRequired_NonBlocking() throws Exception { + // Test that AUTH_REQUIRED with blocking=false sets interrupted=true and completes immediately + String taskId = "auth-required-nonblocking-task"; + Task authRequiredTask = createSampleTask(taskId, TaskState.TASK_STATE_AUTH_REQUIRED, "ctx1"); + + when(mockTaskManager.getTask()).thenReturn(authRequiredTask); + + // Create event queue infrastructure + MainEventBus mainEventBus = new MainEventBus(); + InMemoryTaskStore taskStore = new InMemoryTaskStore(); + InMemoryQueueManager queueManager = + new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + EventQueueUtil.start(processor); + + EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); + + try { + // Enqueue AUTH_REQUIRED task + waitForEventProcessing(processor, () -> queue.enqueueEvent(authRequiredTask)); + + // Create EventConsumer + EventConsumer eventConsumer = new EventConsumer(queue); + + // Call consumeAndBreakOnInterrupt with blocking=false + ResultAggregator.EventTypeAndInterrupt result = + aggregator.consumeAndBreakOnInterrupt(eventConsumer, false); + + // Assert: interrupted=true for AUTH_REQUIRED + assertTrue(result.interrupted(), "AUTH_REQUIRED should trigger interrupt in non-blocking mode"); + assertEquals(authRequiredTask, result.eventType(), "Event type should be the AUTH_REQUIRED task"); + + // For non-blocking mode, consumption should complete immediately + assertNotNull(result, "Result should not be null"); + } finally { + queue.close(); + EventQueueUtil.stop(processor); + } + } + + @Test + void testAuthRequiredWithTaskStatusUpdateEvent() throws Exception { + // Test that TaskStatusUpdateEvent with AUTH_REQUIRED state triggers same interrupt behavior + String taskId = "auth-required-status-update-task"; + TaskStatusUpdateEvent authRequiredEvent = new TaskStatusUpdateEvent( + taskId, + new TaskStatus(TaskState.TASK_STATE_AUTH_REQUIRED), + "ctx1", + false, // isFinal=false for AUTH_REQUIRED + null + ); + + Task authRequiredTask = createSampleTask(taskId, TaskState.TASK_STATE_AUTH_REQUIRED, "ctx1"); + when(mockTaskManager.getTask()).thenReturn(authRequiredTask); + + // Create event queue infrastructure + MainEventBus mainEventBus = new MainEventBus(); + InMemoryTaskStore taskStore = new InMemoryTaskStore(); + InMemoryQueueManager queueManager = + new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + EventQueueUtil.start(processor); + + EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); + + try { + // Enqueue TaskStatusUpdateEvent + waitForEventProcessing(processor, () -> queue.enqueueEvent(authRequiredEvent)); + + // Create EventConsumer + EventConsumer eventConsumer = new EventConsumer(queue); + + // Call consumeAndBreakOnInterrupt + ResultAggregator.EventTypeAndInterrupt result = + aggregator.consumeAndBreakOnInterrupt(eventConsumer, true); + + // Assert: interrupted=true for AUTH_REQUIRED (TaskStatusUpdateEvent) + assertTrue(result.interrupted(), "AUTH_REQUIRED via TaskStatusUpdateEvent should trigger interrupt"); + + // Note: ResultAggregator returns a Task (from getCurrentResult or capturedTask), + // not the TaskStatusUpdateEvent itself. The event triggers interrupt behavior, + // but the returned eventType is a Task. + assertNotNull(result.eventType(), "Result should have an event type"); + assertTrue(result.eventType() instanceof Task, "Event type should be a Task"); + Task resultTask = (Task) result.eventType(); + assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, resultTask.status().state(), + "Task should have AUTH_REQUIRED state"); + } finally { + queue.close(); + EventQueueUtil.stop(processor); + } + } + + @Test + void testAuthRequiredWithTaskEvent() throws Exception { + // Test that Task event with AUTH_REQUIRED state triggers interrupt correctly + String taskId = "auth-required-task-event"; + Task authRequiredTask = createSampleTask(taskId, TaskState.TASK_STATE_AUTH_REQUIRED, "ctx1"); + + when(mockTaskManager.getTask()).thenReturn(authRequiredTask); + + // Create event queue infrastructure + MainEventBus mainEventBus = new MainEventBus(); + InMemoryTaskStore taskStore = new InMemoryTaskStore(); + InMemoryQueueManager queueManager = + new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + EventQueueUtil.start(processor); + + EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); + + try { + // Enqueue Task event with AUTH_REQUIRED + waitForEventProcessing(processor, () -> queue.enqueueEvent(authRequiredTask)); + + // Create EventConsumer + EventConsumer eventConsumer = new EventConsumer(queue); + + // Call consumeAndBreakOnInterrupt + ResultAggregator.EventTypeAndInterrupt result = + aggregator.consumeAndBreakOnInterrupt(eventConsumer, true); + + // Assert: interrupted=true for AUTH_REQUIRED + assertTrue(result.interrupted(), "AUTH_REQUIRED Task event should trigger interrupt"); + assertEquals(authRequiredTask, result.eventType(), "Event type should be the AUTH_REQUIRED task"); + + // Verify both Task and TaskStatusUpdateEvent can trigger AUTH_REQUIRED interrupt + // (this test validates Task event, testAuthRequiredWithTaskStatusUpdateEvent validates TaskStatusUpdateEvent) + TaskState state = ((Task) result.eventType()).status().state(); + assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, state, "Task state should be AUTH_REQUIRED"); + } finally { + queue.close(); + EventQueueUtil.stop(processor); + } + } } 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 8b4021b65..ea1661ee9 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 @@ -1617,6 +1617,132 @@ public void testInputRequiredWorkflow() throws Exception { } } + /** + * Test AUTH_REQUIRED workflow: agent emits AUTH_REQUIRED, continues in background, completes after out-of-band auth. + *

        + * Flow: + * 1. Send initial message → Agent emits AUTH_REQUIRED and returns immediately + * 2. Verify client receives AUTH_REQUIRED state (non-streaming blocking call) + * 3. Subscribe to task to catch background completion + * 4. Verify agent completes in background (simulating out-of-band auth) + * 5. Verify COMPLETED state received via subscription + *

        + * Key behaviors: + * - AUTH_REQUIRED causes immediate return from blocking call (like INPUT_REQUIRED) + * - Agent continues executing in background after returning AUTH_REQUIRED + * - No second message sent (auth happens out-of-band) + * - Subscription receives completion event when agent finishes + */ + @Test + @Timeout(value = 1, unit = TimeUnit.MINUTES) + public void testAuthRequiredWorkflow() throws Exception { + String authRequiredTaskId = "auth-required-test-" + java.util.UUID.randomUUID(); + boolean taskCreated = false; + try { + // 1. Send initial message - AgentExecutor will transition task to AUTH_REQUIRED then continue in background + Message initialMessage = Message.builder(MESSAGE) + .taskId(authRequiredTaskId) + .contextId("test-context") + .parts(new TextPart("Initial request requiring auth")) + .build(); + + CountDownLatch initialLatch = new CountDownLatch(1); + AtomicReference initialState = new AtomicReference<>(); + AtomicBoolean initialUnexpectedEvent = new AtomicBoolean(false); + + BiConsumer initialConsumer = (event, agentCard) -> { + // Idempotency guard: prevent late events from modifying state after latch countdown + if (initialLatch.getCount() == 0) { + return; + } + if (event instanceof TaskEvent te) { + TaskState state = te.getTask().status().state(); + initialState.set(state); + // Only count down when we receive AUTH_REQUIRED, not intermediate states like WORKING + if (state == TaskState.TASK_STATE_AUTH_REQUIRED) { + initialLatch.countDown(); + } + } else { + initialUnexpectedEvent.set(true); + } + }; + + // Send initial message - task will go to AUTH_REQUIRED state and return immediately + getNonStreamingClient().sendMessage(initialMessage, List.of(initialConsumer), null); + assertTrue(initialLatch.await(10, TimeUnit.SECONDS), "Should receive AUTH_REQUIRED state"); + assertFalse(initialUnexpectedEvent.get(), "Should only receive TaskEvent"); + assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, initialState.get(), "Task should be in AUTH_REQUIRED state"); + taskCreated = true; + + // 2. Subscribe to task to catch background completion + // Agent continues executing after returning AUTH_REQUIRED (simulating out-of-band auth flow) + CountDownLatch completionLatch = new CountDownLatch(1); + AtomicReference completedState = new AtomicReference<>(); + AtomicBoolean completionUnexpectedEvent = new AtomicBoolean(false); + AtomicReference errorRef = new AtomicReference<>(); + + BiConsumer subscriptionConsumer = (event, agentCard) -> { + // Idempotency guard: prevent late events from modifying state after latch countdown + if (completionLatch.getCount() == 0) { + return; + } + // subscribeToTask returns initial state as TaskEvent, then subsequent events as TaskUpdateEvent + TaskState state = null; + if (event instanceof TaskEvent te) { + state = te.getTask().status().state(); + } else if (event instanceof TaskUpdateEvent tue) { + io.a2a.spec.UpdateEvent updateEvent = tue.getUpdateEvent(); + if (updateEvent instanceof TaskStatusUpdateEvent statusUpdate) { + state = statusUpdate.status().state(); + } else { + // Ignore other update events like TaskArtifactUpdateEvent as they don't change the task state + return; + } + } else { + completionUnexpectedEvent.set(true); + return; + } + + completedState.set(state); + // A2A spec: first event from subscribeToTask is TaskEvent with current state (AUTH_REQUIRED) + // Then we receive TaskUpdateEvent with COMPLETED when agent finishes + if (state == TaskState.TASK_STATE_COMPLETED) { + completionLatch.countDown(); + } + }; + + Consumer errorHandler = errorRef::set; + + // Wait for subscription to be established + CountDownLatch subscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); + + getClient().subscribeToTask(new TaskIdParams(authRequiredTaskId), + List.of(subscriptionConsumer), + errorHandler); + + assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS), "Subscription should be established"); + + // Note: We don't use awaitChildQueueCountStable() here because the agent is already running + // in the background (sleeping for 3s). By the time we check, it might have already completed. + // The subscriptionLatch already ensures the subscription is established, and completionLatch + // below will catch the COMPLETED event from the background agent. + + // 3. Verify subscription receives COMPLETED state from background agent execution + // Agent should complete after simulating out-of-band auth delay (500ms) + assertTrue(completionLatch.await(10, TimeUnit.SECONDS), "Should receive COMPLETED state from background agent"); + assertFalse(completionUnexpectedEvent.get(), "Should only receive TaskEvent"); + assertNull(errorRef.get(), "Should not receive errors"); + assertEquals(TaskState.TASK_STATE_COMPLETED, completedState.get(), "Task should be COMPLETED after background auth"); + + } finally { + if (taskCreated) { + deleteTaskInTaskStore(authRequiredTaskId); + } + } + } + @Test public void testMalformedJSONRPCRequest() { // skip this test for non-JSONRPC transports 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 1db5f2d78..74fe78eab 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 @@ -97,6 +97,31 @@ public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2 } } + // Special handling for auth-required test + if (taskId != null && taskId.startsWith("auth-required-test")) { + // AUTH_REQUIRED workflow: agent emits AUTH_REQUIRED, simulates out-of-band auth delay, then completes + // Go directly to AUTH_REQUIRED without intermediate WORKING state + // This avoids race condition where blocking call interrupts on WORKING + // before AUTH_REQUIRED is persisted to TaskStore + agentEmitter.requiresAuth(agentEmitter.newAgentMessage( + List.of(new TextPart("Please authenticate with OAuth provider")), + context.getMessage().metadata())); + + try { + // Simulate out-of-band authentication delay (user authenticates externally) + // Sleep long enough for test to establish subscription and wait for completion + Thread.sleep(2000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new InternalError("Auth simulation interrupted: " + e.getMessage()); + } + + // Complete task (auth "received" out-of-band) + // Agent continues after AUTH_REQUIRED without new request + agentEmitter.complete(); + return; + } + if (context.getTaskId().equals("task-not-supported-123")) { throw new UnsupportedOperationError(); } From c9df26056bb92d0aade40b3bc578d3dafeadc983 Mon Sep 17 00:00:00 2001 From: Lee Chae Min Date: Thu, 5 Mar 2026 17:44:26 +0900 Subject: [PATCH 059/192] refactor: use TransportProtocol enum in examples AgentCardProducer (#696) # Description Replace the raw string switch statement with an exhaustive switch expression based on the TransportProtocol enum. --- .../helloworld/AgentCardProducer.java | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java index 0f4821290..7ffb4dd09 100644 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java +++ b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java @@ -1,24 +1,23 @@ package io.a2a.examples.helloworld; - -import java.util.Collections; -import java.util.List; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - import io.a2a.server.PublicAgentCard; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.AgentSkill; +import io.a2a.spec.TransportProtocol; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; import org.eclipse.microprofile.config.inject.ConfigProperty; +import java.util.Collections; +import java.util.List; + @ApplicationScoped public class AgentCardProducer { - @ConfigProperty(name = "quarkus.agentcard.protocol", defaultValue="JSONRPC") - String protocol; + @ConfigProperty(name = "quarkus.agentcard.protocol", defaultValue = "JSONRPC") + TransportProtocol protocol; @Produces @PublicAgentCard @@ -39,24 +38,20 @@ public AgentCard agentCard() { .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) .skills(Collections.singletonList(AgentSkill.builder() - .id("hello_world") - .name("Returns hello world") - .description("just returns hello world") - .tags(Collections.singletonList("hello world")) - .examples(List.of("hi", "hello world")) - .build())) + .id("hello_world") + .name("Returns hello world") + .description("just returns hello world") + .tags(Collections.singletonList("hello world")) + .examples(List.of("hi", "hello world")) + .build())) .build(); } private AgentInterface getAgentInterface() { - switch(protocol) { - case "GRPC": - return new AgentInterface("GRPC", "localhost:9000"); - case "HTTP+JSON": - return new AgentInterface("HTTP+JSON", "http://localhost:9999"); - case "JSONRPC": - default: - return new AgentInterface("JSONRPC", "http://localhost:9999"); - } + String url = switch (protocol) { + case GRPC -> "localhost:9000"; + case JSONRPC, HTTP_JSON -> "http://localhost:9999"; + }; + return new AgentInterface(protocol.asString(), url); } } From ddf65aaeeeb74331fad0143372ead7aa871115e5 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 5 Mar 2026 09:45:20 +0100 Subject: [PATCH 060/192] =?UTF-8?q?feat:=20improve=20TaskStore=20error=20r?= =?UTF-8?q?eporting=20with=20domain-specific=20exceptio=E2=80=A6=20(#682)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ns (#516) Replace generic RuntimeException with TaskSerializationException and TaskPersistenceException throughout the TaskStore persistence layer. Wire execptions into MainEventQueueBusProcessor. Fixes #516 🦕 --------- Co-authored-by: Claude Sonnet 4.5 --- .gitignore | 1 + .../database/jpa/JpaDatabaseTaskStore.java | 260 +++++++++-------- .../server/events/MainEventBusProcessor.java | 29 ++ .../a2a/server/tasks/InMemoryTaskStore.java | 56 ++++ .../server/tasks/PushNotificationSender.java | 1 - .../tasks/TaskPersistenceException.java | 91 ++++++ .../tasks/TaskSerializationException.java | 87 ++++++ .../java/io/a2a/server/tasks/TaskStore.java | 71 +++++ .../a2a/server/tasks/TaskStoreException.java | 113 ++++++++ .../MainEventBusProcessorExceptionTest.java | 270 +++++++++++++++++ .../tasks/AbstractTaskStoreExceptionTest.java | 168 +++++++++++ .../tasks/TaskPersistenceExceptionTest.java | 258 +++++++++++++++++ .../tasks/TaskSerializationExceptionTest.java | 272 ++++++++++++++++++ .../server/tasks/TaskStoreExceptionTest.java | 191 ++++++++++++ 14 files changed, 1753 insertions(+), 115 deletions(-) create mode 100644 server-common/src/main/java/io/a2a/server/tasks/TaskPersistenceException.java create mode 100644 server-common/src/main/java/io/a2a/server/tasks/TaskSerializationException.java create mode 100644 server-common/src/main/java/io/a2a/server/tasks/TaskStoreException.java create mode 100644 server-common/src/test/java/io/a2a/server/events/MainEventBusProcessorExceptionTest.java create mode 100644 server-common/src/test/java/io/a2a/server/tasks/AbstractTaskStoreExceptionTest.java create mode 100644 server-common/src/test/java/io/a2a/server/tasks/TaskPersistenceExceptionTest.java create mode 100644 server-common/src/test/java/io/a2a/server/tasks/TaskSerializationExceptionTest.java create mode 100644 server-common/src/test/java/io/a2a/server/tasks/TaskStoreExceptionTest.java diff --git a/.gitignore b/.gitignore index 3679c8f0c..441ef20e1 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,4 @@ nbproject/ .serena/ .bob/ claudedocs +backlog/ 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 086e640e3..3a704ee2a 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 @@ -13,6 +13,7 @@ import jakarta.inject.Inject; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import jakarta.persistence.PersistenceException; import jakarta.persistence.TypedQuery; import jakarta.transaction.Transactional; @@ -22,6 +23,8 @@ import io.a2a.server.config.A2AConfigProvider; import io.a2a.server.tasks.TaskStateProvider; import io.a2a.server.tasks.TaskStore; +import io.a2a.server.tasks.TaskSerializationException; +import io.a2a.server.tasks.TaskPersistenceException; import io.a2a.spec.Artifact; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; @@ -63,6 +66,7 @@ void initConfig() { gracePeriodSeconds = Long.parseLong(configProvider.getValue(A2A_REPLICATION_GRACE_PERIOD_SECONDS)); } + @Transactional @Override public void save(Task task, boolean isReplicated) { @@ -85,7 +89,12 @@ public void save(Task task, boolean isReplicated) { } } catch (JsonProcessingException e) { LOGGER.error("Failed to serialize task with ID: {}", task.id(), e); - throw new RuntimeException("Failed to serialize task with ID: " + task.id(), e); + throw new TaskSerializationException(task.id(), + "Failed to serialize task for persistence", e); + } catch (PersistenceException e) { + LOGGER.error("Database save failed for task with ID: {}", task.id(), e); + throw new TaskPersistenceException(task.id(), + "Database save failed for task", e); } } @@ -93,19 +102,27 @@ public void save(Task task, boolean isReplicated) { @Override public Task get(String taskId) { LOGGER.debug("Retrieving task with ID: {}", taskId); - JpaTask jpaTask = em.find(JpaTask.class, taskId); - if (jpaTask == null) { - LOGGER.debug("Task not found with ID: {}", taskId); - return null; - } - try { - Task task = jpaTask.getTask(); - LOGGER.debug("Successfully retrieved task with ID: {}", taskId); - return task; - } catch (JsonProcessingException e) { - LOGGER.error("Failed to deserialize task with ID: {}", taskId, e); - throw new RuntimeException("Failed to deserialize task with ID: " + taskId, e); + JpaTask jpaTask = em.find(JpaTask.class, taskId); + if (jpaTask == null) { + LOGGER.debug("Task not found with ID: {}", taskId); + return null; + } + + try { + Task task = jpaTask.getTask(); + LOGGER.debug("Successfully retrieved task with ID: {}", taskId); + return task; + } catch (JsonProcessingException e) { + LOGGER.error("Failed to deserialize task with ID: {}", taskId, e); + throw new TaskSerializationException(taskId, + "Failed to deserialize task from database", e); + } + + } catch (PersistenceException e) { + LOGGER.error("Database retrieval failed for task with ID: {}", taskId, e); + throw new TaskPersistenceException(taskId, + "Database retrieval failed for task", e); } } @@ -113,12 +130,18 @@ public Task get(String taskId) { @Override public void delete(String taskId) { LOGGER.debug("Deleting task with ID: {}", taskId); - JpaTask jpaTask = em.find(JpaTask.class, taskId); - if (jpaTask != null) { - em.remove(jpaTask); - LOGGER.debug("Successfully deleted task with ID: {}", taskId); - } else { - LOGGER.debug("Task not found for deletion with ID: {}", taskId); + try { + JpaTask jpaTask = em.find(JpaTask.class, taskId); + if (jpaTask != null) { + em.remove(jpaTask); + LOGGER.debug("Successfully deleted task with ID: {}", taskId); + } else { + LOGGER.debug("Task not found for deletion with ID: {}", taskId); + } + } catch (PersistenceException e) { + LOGGER.error("Database deletion failed for task with ID: {}", taskId, e); + throw new TaskPersistenceException(taskId, + "Database deletion failed for task", e); } } @@ -231,117 +254,126 @@ public ListTasksResult list(ListTasksParams params) { LOGGER.debug("Listing tasks with params: contextId={}, status={}, pageSize={}, pageToken={}", params.contextId(), params.status(), params.pageSize(), params.pageToken()); - // Parse pageToken once at the beginning - PageToken pageToken = PageToken.fromString(params.pageToken()); - Instant tokenTimestamp = pageToken != null ? pageToken.timestamp() : null; - String tokenId = pageToken != null ? pageToken.id() : null; - - // Build dynamic JPQL query with WHERE clauses for filtering - StringBuilder queryBuilder = new StringBuilder("SELECT t FROM JpaTask t WHERE 1=1"); - StringBuilder countQueryBuilder = new StringBuilder("SELECT COUNT(t) FROM JpaTask t WHERE 1=1"); - - // Apply contextId filter using denormalized column - if (params.contextId() != null) { - queryBuilder.append(" AND t.contextId = :contextId"); - countQueryBuilder.append(" AND t.contextId = :contextId"); - } + try { + // Parse pageToken once at the beginning + PageToken pageToken = PageToken.fromString(params.pageToken()); + Instant tokenTimestamp = pageToken != null ? pageToken.timestamp() : null; + String tokenId = pageToken != null ? pageToken.id() : null; + + // Build dynamic JPQL query with WHERE clauses for filtering + StringBuilder queryBuilder = new StringBuilder("SELECT t FROM JpaTask t WHERE 1=1"); + StringBuilder countQueryBuilder = new StringBuilder("SELECT COUNT(t) FROM JpaTask t WHERE 1=1"); + + // Apply contextId filter using denormalized column + if (params.contextId() != null) { + queryBuilder.append(" AND t.contextId = :contextId"); + countQueryBuilder.append(" AND t.contextId = :contextId"); + } - // Apply status filter using denormalized column - if (params.status() != null) { - queryBuilder.append(" AND t.state = :state"); - countQueryBuilder.append(" AND t.state = :state"); - } + // Apply status filter using denormalized column + if (params.status() != null) { + queryBuilder.append(" AND t.state = :state"); + countQueryBuilder.append(" AND t.state = :state"); + } - // Apply statusTimestampAfter filter using denormalized timestamp column - if (params.statusTimestampAfter() != null) { - queryBuilder.append(" AND t.statusTimestamp > :statusTimestampAfter"); - countQueryBuilder.append(" AND t.statusTimestamp > :statusTimestampAfter"); - } + // Apply statusTimestampAfter filter using denormalized timestamp column + if (params.statusTimestampAfter() != null) { + queryBuilder.append(" AND t.statusTimestamp > :statusTimestampAfter"); + countQueryBuilder.append(" AND t.statusTimestamp > :statusTimestampAfter"); + } - // Apply pagination cursor using keyset pagination for composite sort (timestamp DESC, id ASC) - if (tokenTimestamp != null) { - // Keyset pagination: get tasks where timestamp < tokenTimestamp OR (timestamp = tokenTimestamp AND id > tokenId) - queryBuilder.append(" AND (t.statusTimestamp < :tokenTimestamp OR (t.statusTimestamp = :tokenTimestamp AND t.id > :tokenId))"); - } + // Apply pagination cursor using keyset pagination for composite sort (timestamp DESC, id ASC) + if (tokenTimestamp != null) { + // Keyset pagination: get tasks where timestamp < tokenTimestamp OR (timestamp = tokenTimestamp AND id > tokenId) + queryBuilder.append(" AND (t.statusTimestamp < :tokenTimestamp OR (t.statusTimestamp = :tokenTimestamp AND t.id > :tokenId))"); + } - // Sort by status timestamp descending (most recent first), then by ID for stable ordering - queryBuilder.append(" ORDER BY t.statusTimestamp DESC, t.id ASC"); + // Sort by status timestamp descending (most recent first), then by ID for stable ordering + queryBuilder.append(" ORDER BY t.statusTimestamp DESC, t.id ASC"); - // Create and configure the main query - TypedQuery query = em.createQuery(queryBuilder.toString(), JpaTask.class); + // Create and configure the main query + TypedQuery query = em.createQuery(queryBuilder.toString(), JpaTask.class); - // Set filter parameters - if (params.contextId() != null) { - query.setParameter("contextId", params.contextId()); - } - if (params.status() != null) { - query.setParameter("state", params.status().name()); - } - if (params.statusTimestampAfter() != null) { - query.setParameter("statusTimestampAfter", params.statusTimestampAfter()); - } - if (tokenTimestamp != null) { - query.setParameter("tokenTimestamp", tokenTimestamp); - query.setParameter("tokenId", tokenId); - } + // Set filter parameters + if (params.contextId() != null) { + query.setParameter("contextId", params.contextId()); + } + if (params.status() != null) { + query.setParameter("state", params.status().name()); + } + if (params.statusTimestampAfter() != null) { + query.setParameter("statusTimestampAfter", params.statusTimestampAfter()); + } + if (tokenTimestamp != null) { + query.setParameter("tokenTimestamp", tokenTimestamp); + query.setParameter("tokenId", tokenId); + } - // Apply page size limit (+1 to check for next page) - int pageSize = params.getEffectivePageSize(); - query.setMaxResults(pageSize + 1); + // Apply page size limit (+1 to check for next page) + int pageSize = params.getEffectivePageSize(); + query.setMaxResults(pageSize + 1); - // Execute query and deserialize tasks - List jpaTasksPage = query.getResultList(); + // Execute query and deserialize tasks + List jpaTasksPage = query.getResultList(); - // Determine if there are more results - boolean hasMore = jpaTasksPage.size() > pageSize; - if (hasMore) { - jpaTasksPage = jpaTasksPage.subList(0, pageSize); - } + // Determine if there are more results + boolean hasMore = jpaTasksPage.size() > pageSize; + if (hasMore) { + jpaTasksPage = jpaTasksPage.subList(0, pageSize); + } - // Get total count of matching tasks - TypedQuery countQuery = em.createQuery(countQueryBuilder.toString(), Long.class); - if (params.contextId() != null) { - countQuery.setParameter("contextId", params.contextId()); - } - if (params.status() != null) { - countQuery.setParameter("state", params.status().name()); - } - if (params.statusTimestampAfter() != null) { - countQuery.setParameter("statusTimestampAfter", params.statusTimestampAfter()); - } - int totalSize = countQuery.getSingleResult().intValue(); + // Get total count of matching tasks + TypedQuery countQuery = em.createQuery(countQueryBuilder.toString(), Long.class); + if (params.contextId() != null) { + countQuery.setParameter("contextId", params.contextId()); + } + if (params.status() != null) { + countQuery.setParameter("state", params.status().name()); + } + if (params.statusTimestampAfter() != null) { + countQuery.setParameter("statusTimestampAfter", params.statusTimestampAfter()); + } + int totalSize = countQuery.getSingleResult().intValue(); + + // Deserialize tasks from JSON + List tasks = new ArrayList<>(); + for (JpaTask jpaTask : jpaTasksPage) { + try { + tasks.add(jpaTask.getTask()); + } catch (JsonProcessingException e) { + LOGGER.error("Failed to deserialize task with ID: {}", jpaTask.getId(), e); + throw new TaskSerializationException(jpaTask.getId(), + "Failed to deserialize task during list operation", e); + } + } - // Deserialize tasks from JSON - List tasks = new ArrayList<>(); - for (JpaTask jpaTask : jpaTasksPage) { - try { - tasks.add(jpaTask.getTask()); - } catch (JsonProcessingException e) { - LOGGER.error("Failed to deserialize task with ID: {}", jpaTask.getId(), e); - throw new RuntimeException("Failed to deserialize task with ID: " + jpaTask.getId(), e); + // Determine next page token (timestamp:ID of last task if there are more results) + // Format: "timestamp_millis:taskId" for keyset pagination + String nextPageToken = null; + if (hasMore && !tasks.isEmpty()) { + Task lastTask = tasks.get(tasks.size() - 1); + // All tasks have timestamps (TaskStatus canonical constructor ensures this) + Instant timestamp = lastTask.status().timestamp().toInstant(); + nextPageToken = new PageToken(timestamp, lastTask.id()).toString(); } - } - // Determine next page token (timestamp:ID of last task if there are more results) - // Format: "timestamp_millis:taskId" for keyset pagination - String nextPageToken = null; - if (hasMore && !tasks.isEmpty()) { - Task lastTask = tasks.get(tasks.size() - 1); - // All tasks have timestamps (TaskStatus canonical constructor ensures this) - Instant timestamp = lastTask.status().timestamp().toInstant(); - nextPageToken = new PageToken(timestamp, lastTask.id()).toString(); - } + // Apply post-processing transformations (history limiting, artifact removal) + int historyLength = params.getEffectiveHistoryLength(); + boolean includeArtifacts = params.shouldIncludeArtifacts(); - // Apply post-processing transformations (history limiting, artifact removal) - int historyLength = params.getEffectiveHistoryLength(); - boolean includeArtifacts = params.shouldIncludeArtifacts(); + List transformedTasks = tasks.stream() + .map(task -> transformTask(task, historyLength, includeArtifacts)) + .toList(); - List transformedTasks = tasks.stream() - .map(task -> transformTask(task, historyLength, includeArtifacts)) - .toList(); + LOGGER.debug("Returning {} tasks out of {} total", transformedTasks.size(), totalSize); + return new ListTasksResult(transformedTasks, totalSize, transformedTasks.size(), nextPageToken); - LOGGER.debug("Returning {} tasks out of {} total", transformedTasks.size(), totalSize); - return new ListTasksResult(transformedTasks, totalSize, transformedTasks.size(), nextPageToken); + } catch (PersistenceException e) { + // Database errors from query creation, execution, or count + LOGGER.error("Database query failed during list operation", e); + throw new TaskPersistenceException(null, // No single taskId for list operation + "Database query failed during list operation", e); + } } private Task transformTask(Task task, int historyLength, boolean includeArtifacts) { diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java index 575078679..d7eece30b 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java +++ b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java @@ -10,6 +10,8 @@ import io.a2a.server.tasks.PushNotificationSender; import io.a2a.server.tasks.TaskManager; +import io.a2a.server.tasks.TaskPersistenceException; +import io.a2a.server.tasks.TaskSerializationException; import io.a2a.server.tasks.TaskStore; import io.a2a.spec.A2AError; import io.a2a.spec.A2AServerException; @@ -41,6 +43,18 @@ * Note: This bean is eagerly initialized by {@link MainEventBusProcessorInitializer} * to ensure the background thread starts automatically when the application starts. *

        + * + *

        Exception Handling

        + * TaskStore persistence failures are caught and handled gracefully: + *
          + *
        • {@link TaskSerializationException} - Data corruption or schema mismatch. + * Logged at ERROR level, distributed as {@link InternalError} to clients.
        • + *
        • {@link TaskPersistenceException} - Database/storage system failure. + * Logged at ERROR level, distributed as {@link InternalError} to clients.
        • + *
        + * + *

        Processing continues after errors - the failed event is distributed as InternalError + * to all ChildQueues, and the MainEventBusProcessor continues consuming subsequent events.

        */ @ApplicationScoped public class MainEventBusProcessor implements Runnable { @@ -293,11 +307,26 @@ private boolean updateTaskStore(String taskId, Event event, boolean isReplicated LOGGER.debug("TaskStore updated via TaskManager.process() for task {}: {} (final: {}, replicated: {})", taskId, event.getClass().getSimpleName(), isFinal, isReplicated); return isFinal; + + } catch (TaskSerializationException e) { + // Data corruption or schema mismatch - ALWAYS permanent + LOGGER.error("Task {} event serialization failed - data corruption detected: {}", + taskId, e.getMessage(), e); + throw new InternalError("Failed to serialize task " + taskId + ": " + e.getMessage()); + + } catch (TaskPersistenceException e) { + // Database/storage failure + LOGGER.error("Task {} event persistence failed: {}", taskId, e.getMessage(), e); + throw new InternalError("Storage failure for task " + taskId + ": " + e.getMessage()); + } catch (InternalError e) { + // Already an InternalError from TaskManager validation - pass through LOGGER.error("Error updating TaskStore via TaskManager for task {}", taskId, e); // Rethrow to prevent distributing unpersisted event to clients throw e; + } catch (Exception e) { + // Unexpected exception type - treat as permanent failure LOGGER.error("Unexpected error updating TaskStore for task {}", taskId, e); // Rethrow to prevent distributing unpersisted event to clients throw new InternalError("TaskStore persistence failed: " + e.getMessage()); 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 15f94d7e8..7c443b1cc 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 @@ -25,6 +25,62 @@ *

        * This is the default TaskStore used when no other implementation is provided. *

        + * + *

        Exception Behavior

        + * InMemoryTaskStore has minimal exception scenarios compared to database-backed implementations: + *
          + *
        • No TaskSerializationException: Task objects are stored directly in memory without + * serialization. No JSON parsing or schema compatibility issues can occur.
        • + *
        • No TaskPersistenceException: ConcurrentHashMap operations do not involve I/O, + * network, or transactional concerns. Standard put/get/remove operations are guaranteed + * to succeed under normal JVM operation.
        • + *
        • OutOfMemoryError (potential): The only failure scenario is JVM heap exhaustion if + * too many tasks are stored. This is an {@link Error} (not Exception) and indicates a fatal + * system condition requiring JVM restart and capacity planning.
        • + *
        + * + *

        Design Rationale

        + * This implementation intentionally does NOT throw {@link TaskStoreException} or its subclasses + * because: + *
          + *
        • No serialization step exists - tasks stored as Java objects
        • + *
        • No I/O or network operations that can fail
        • + *
        • ConcurrentHashMap guarantees thread-safe operations without checked exceptions
        • + *
        • Memory exhaustion (OutOfMemoryError) is an unrecoverable system failure
        • + *
        + * + *

        Comparison to Database Implementations

        + * Database-backed implementations (e.g., JpaDatabaseTaskStore) throw exceptions for: + *
          + *
        • Serialization errors (JSON parsing, schema mismatches)
        • + *
        • Connection failures (network, timeouts)
        • + *
        • Transaction failures (deadlocks, constraint violations)
        • + *
        • Capacity issues (disk full, quota exceeded)
        • + *
        + * InMemoryTaskStore avoids all of these by operating entirely in-process. + * + *

        Memory Management Considerations

        + * Callers should monitor memory usage and implement task cleanup policies: + *
        {@code
        + * // Example: Delete finalized tasks older than 48 hours
        + * ListTasksParams params = new ListTasksParams.Builder()
        + *     .statusTimestampBefore(Instant.now().minus(Duration.ofHours(48)))
        + *     .build();
        + *
        + * List oldTasks = taskStore.list(params).tasks();
        + * oldTasks.stream()
        + *     .filter(task -> task.status().state().isFinal())
        + *     .forEach(task -> taskStore.delete(task.id()));
        + * }
        + * + *

        Thread Safety

        + * All operations are thread-safe via {@link ConcurrentHashMap}. Multiple threads can + * concurrently save, get, list, and delete tasks without synchronization. Last-write-wins + * semantics apply for concurrent {@code save()} calls to the same task ID. + * + * @see TaskStore for interface contract and exception documentation + * @see TaskStoreException for exception hierarchy (not thrown by this implementation) + * @see TaskStateProvider for queue lifecycle integration */ @ApplicationScoped public class InMemoryTaskStore implements TaskStore, TaskStateProvider { diff --git a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java index f8b7b018d..093241182 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java +++ b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java @@ -63,7 +63,6 @@ * Implementations should handle errors gracefully: *
          *
        • Log failures but don't throw exceptions (notifications are best-effort)
        • - *
        • Consider retry logic for transient failures
        • *
        • Don't block on network I/O - execute asynchronously if needed
        • *
        • Circuit breaker patterns for repeatedly failing endpoints
        • *
        diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskPersistenceException.java b/server-common/src/main/java/io/a2a/server/tasks/TaskPersistenceException.java new file mode 100644 index 000000000..97007cab9 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/tasks/TaskPersistenceException.java @@ -0,0 +1,91 @@ +package io.a2a.server.tasks; + +import org.jspecify.annotations.Nullable; + +/** + * Exception for database/storage system failures during task persistence operations. + *

        + * Indicates failures in the underlying storage system (database, filesystem, etc.) rather + * than data format issues. + * + *

        Common Scenarios

        + *
          + *
        • Database connection timeout or network partition
        • + *
        • Transaction deadlock or lock wait timeout
        • + *
        • Connection pool exhausted
        • + *
        • Disk full / storage quota exceeded
        • + *
        • Database constraint violations (unique key, foreign key)
        • + *
        • Insufficient permissions or authentication failures
        • + *
        • Database schema incompatibilities
        • + *
        + * + *

        Usage Example

        + *
        {@code
        + * try {
        + *     em.merge(jpaTask);
        + * } catch (PersistenceException e) {
        + *     throw new TaskPersistenceException(taskId, "Database save failed", e);
        + * }
        + * }
        + * + * @see TaskStoreException + * @see TaskSerializationException for data format errors + */ +public class TaskPersistenceException extends TaskStoreException { + + /** + * Creates a new TaskPersistenceException with no message or cause. + */ + public TaskPersistenceException() { + super(); + } + + /** + * Creates a new TaskPersistenceException with the specified message. + * + * @param msg the exception message + */ + public TaskPersistenceException(final String msg) { + super(msg); + } + + /** + * Creates a new TaskPersistenceException with the specified cause. + * + * @param cause the underlying cause + */ + public TaskPersistenceException(final Throwable cause) { + super(cause); + } + + /** + * Creates a new TaskPersistenceException with the specified message and cause. + * + * @param msg the exception message + * @param cause the underlying cause + */ + public TaskPersistenceException(final String msg, final Throwable cause) { + super(msg, cause); + } + + /** + * Creates a new TaskPersistenceException with the specified task ID and message. + * + * @param taskId the task identifier (may be null for operations not tied to a specific task) + * @param msg the exception message + */ + public TaskPersistenceException(@Nullable final String taskId, final String msg) { + super(taskId, msg); + } + + /** + * Creates a new TaskPersistenceException with the specified task ID, message, and cause. + * + * @param taskId the task identifier (may be null for operations not tied to a specific task) + * @param msg the exception message + * @param cause the underlying cause + */ + public TaskPersistenceException(@Nullable final String taskId, final String msg, final Throwable cause) { + super(taskId, msg, cause); + } +} diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskSerializationException.java b/server-common/src/main/java/io/a2a/server/tasks/TaskSerializationException.java new file mode 100644 index 000000000..5916ce530 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/tasks/TaskSerializationException.java @@ -0,0 +1,87 @@ +package io.a2a.server.tasks; + +import org.jspecify.annotations.Nullable; + +/** + * Exception for task serialization/deserialization failures. + *

        + * Indicates failures converting between Task domain objects and persistent storage format (JSON). + * + *

        Common Scenarios

        + *
          + *
        • JSON parsing errors during {@code get()} operations
        • + *
        • JSON serialization errors during {@code save()} operations
        • + *
        • Invalid enum values or missing required fields
        • + *
        • Data format version mismatches after upgrades
        • + *
        + * + *

        Usage Example

        + *
        {@code
        + * try {
        + *     Task task = jsonMapper.readValue(json, Task.class);
        + * } catch (JsonProcessingException e) {
        + *     throw new TaskSerializationException(taskId, "Failed to deserialize task", e);
        + * }
        + * }
        + * + * @see TaskStoreException + * @see TaskPersistenceException for database failures + */ +public class TaskSerializationException extends TaskStoreException { + + /** + * Creates a new TaskSerializationException with no message or cause. + */ + public TaskSerializationException() { + super(); + } + + /** + * Creates a new TaskSerializationException with the specified message. + * + * @param msg the exception message + */ + public TaskSerializationException(final String msg) { + super(msg); + } + + /** + * Creates a new TaskSerializationException with the specified cause. + * + * @param cause the underlying cause + */ + public TaskSerializationException(final Throwable cause) { + super(cause); + } + + /** + * Creates a new TaskSerializationException with the specified message and cause. + * + * @param msg the exception message + * @param cause the underlying cause + */ + public TaskSerializationException(final String msg, final Throwable cause) { + super(msg, cause); + } + + /** + * Creates a new TaskSerializationException with the specified task ID and message. + * + * @param taskId the task identifier (may be null for operations not tied to a specific task) + * @param msg the exception message + */ + public TaskSerializationException(@Nullable final String taskId, final String msg) { + super(taskId, msg); + } + + /** + * Creates a new TaskSerializationException with the specified task ID, message, and cause. + * + * @param taskId the task identifier (may be null for operations not tied to a specific task) + * @param msg the exception message + * @param cause the underlying cause + */ + public TaskSerializationException(@Nullable final String taskId, final String msg, final Throwable cause) { + super(taskId, msg, cause); + } +} 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 3df903f77..7ae7a46bf 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 @@ -90,10 +90,64 @@ *
      • Consider caching for frequently-accessed task lists
      • * * + *

        Exception Contract

        + * All TaskStore methods may throw {@link TaskStoreException} or its subclasses to indicate + * persistence failures: + *
          + *
        • {@link TaskSerializationException} - JSON/data format errors
        • + *
        • {@link TaskPersistenceException} - Database/storage system failures
        • + *
        + * + *

        When to Throw TaskSerializationException

        + * Use when task data cannot be serialized or deserialized: + *
          + *
        • JSON parsing errors during {@code get()} operations
        • + *
        • JSON serialization errors during {@code save()} operations
        • + *
        • Invalid enum values or missing required fields
        • + *
        • Schema version mismatches after upgrades
        • + *
        + * + *

        When to Throw TaskPersistenceException

        + * Use when the storage system fails: + *
          + *
        • Database connection timeouts
        • + *
        • Transaction deadlocks
        • + *
        • Connection pool exhausted
        • + *
        • Disk full / quota exceeded
        • + *
        • Database constraint violations
        • + *
        • Insufficient permissions
        • + *
        + * + *

        Implementer Example

        + *
        {@code
        + * @Override
        + * public void save(Task task, boolean isReplicated) {
        + *     try {
        + *         String json = objectMapper.writeValueAsString(task);
        + *     } catch (JsonProcessingException e) {
        + *         throw new TaskSerializationException(task.id(), "Failed to serialize task", e);
        + *     }
        + *
        + *     try {
        + *         entityManager.merge(toEntity(json));
        + *     } catch (PersistenceException e) {
        + *         throw new TaskPersistenceException(task.id(), "Database save failed", e);
        + *     }
        + * }
        + * }
        + * + *

        Exception Handling

        + * {@link io.a2a.server.events.MainEventBusProcessor} catches TaskStore exceptions and + * wraps them in {@link io.a2a.spec.InternalError} events for client distribution. + * * @see TaskManager * @see TaskStateProvider + * @see TaskStoreException + * @see TaskSerializationException + * @see TaskPersistenceException * @see InMemoryTaskStore * @see io.a2a.server.requesthandlers.DefaultRequestHandler + * @see io.a2a.server.events.MainEventBusProcessor */ public interface TaskStore { /** @@ -103,6 +157,10 @@ public interface TaskStore { * @param isReplicated true if this task update came from a replicated event, * false if it originated locally. Used to prevent feedback loops * in replicated scenarios (e.g., don't fire TaskFinalizedEvent for replicated updates) + * @throws TaskSerializationException if the task cannot be serialized to storage format (JSON parsing error, + * invalid field values, schema mismatch) + * @throws TaskPersistenceException if the storage system fails (database timeout, connection error, disk full) + * @throws TaskStoreException for other persistence failures not covered by specific subclasses */ void save(Task task, boolean isReplicated); @@ -111,6 +169,11 @@ public interface TaskStore { * * @param taskId the task identifier * @return the task if found, null otherwise + * @throws TaskSerializationException if the persisted task data cannot be deserialized (corrupted JSON, + * schema incompatibility) + * @throws TaskPersistenceException if the storage system fails during retrieval (database connection error, + * query timeout) + * @throws TaskStoreException for other retrieval failures not covered by specific subclasses */ @Nullable Task get(String taskId); @@ -118,6 +181,9 @@ public interface TaskStore { * Deletes a task by its ID. * * @param taskId the task identifier + * @throws TaskPersistenceException if the storage system fails during deletion (database connection error, + * transaction timeout, constraint violation) + * @throws TaskStoreException for other deletion failures not covered by specific subclasses */ void delete(String taskId); @@ -126,6 +192,11 @@ public interface TaskStore { * * @param params the filtering and pagination parameters * @return the list of tasks matching the criteria with pagination info + * @throws TaskSerializationException if any persisted task data cannot be deserialized during listing + * (corrupted JSON in database) + * @throws TaskPersistenceException if the storage system fails during the list operation (database query timeout, + * connection error) + * @throws TaskStoreException for other listing failures not covered by specific subclasses */ ListTasksResult list(ListTasksParams params); } diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskStoreException.java b/server-common/src/main/java/io/a2a/server/tasks/TaskStoreException.java new file mode 100644 index 000000000..5865c5a80 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/tasks/TaskStoreException.java @@ -0,0 +1,113 @@ +package io.a2a.server.tasks; + +import io.a2a.spec.A2AServerException; +import org.jspecify.annotations.Nullable; + +/** + * Base exception for TaskStore persistence layer failures. + *

        + * Root exception for all task storage and retrieval errors. Specialized subclasses + * provide specific failure contexts: + *

          + *
        • {@link TaskSerializationException} - JSON/data format errors
        • + *
        • {@link TaskPersistenceException} - Database/storage system failures
        • + *
        + * + *

        Usage Context

        + * Thrown by {@link TaskStore} implementations during: + *
          + *
        • {@code save(Task, boolean)} - Task persistence failures
        • + *
        • {@code get(String)} - Task retrieval failures
        • + *
        • {@code delete(String)} - Task deletion failures
        • + *
        • {@code list(ListTasksParams)} - Task listing failures
        • + *
        + * + *

        Error Handling Pattern

        + * Caught by {@link io.a2a.server.events.MainEventBusProcessor} which: + *
          + *
        1. Logs the failure with full context (taskId, operation)
        2. + *
        3. Distributes {@link io.a2a.spec.InternalError} event to clients
        4. + *
        5. Preserves exception cause chain for diagnostics
        6. + *
        + * + * @see TaskSerializationException for data format errors + * @see TaskPersistenceException for storage system failures + * @see TaskStore + */ +public class TaskStoreException extends A2AServerException { + + @Nullable + private final String taskId; + + /** + * Creates a new TaskStoreException with no message or cause. + */ + public TaskStoreException() { + super(); + this.taskId = null; + } + + /** + * Creates a new TaskStoreException with the specified message. + * + * @param msg the exception message + */ + public TaskStoreException(final String msg) { + super(msg); + this.taskId = null; + } + + /** + * Creates a new TaskStoreException with the specified cause. + * + * @param cause the underlying cause + */ + public TaskStoreException(final Throwable cause) { + super(cause); + this.taskId = null; + } + + /** + * Creates a new TaskStoreException with the specified message and cause. + * + * @param msg the exception message + * @param cause the underlying cause + */ + public TaskStoreException(final String msg, final Throwable cause) { + super(msg, cause); + this.taskId = null; + } + + /** + * Creates a new TaskStoreException with the specified task ID and message. + * + * @param taskId the task identifier (may be null for operations not tied to a specific task) + * @param msg the exception message + */ + public TaskStoreException(@Nullable final String taskId, final String msg) { + super(msg); + this.taskId = taskId; + } + + /** + * Creates a new TaskStoreException with the specified task ID, message, and cause. + * + * @param taskId the task identifier (may be null for operations not tied to a specific task) + * @param msg the exception message + * @param cause the underlying cause + */ + public TaskStoreException(@Nullable final String taskId, final String msg, final Throwable cause) { + super(msg, cause); + this.taskId = taskId; + } + + /** + * Returns the task ID associated with this exception. + * + * @return the task ID, or null if not associated with a specific task + */ + @Nullable + public String getTaskId() { + return taskId; + } +} diff --git a/server-common/src/test/java/io/a2a/server/events/MainEventBusProcessorExceptionTest.java b/server-common/src/test/java/io/a2a/server/events/MainEventBusProcessorExceptionTest.java new file mode 100644 index 000000000..8bb212601 --- /dev/null +++ b/server-common/src/test/java/io/a2a/server/events/MainEventBusProcessorExceptionTest.java @@ -0,0 +1,270 @@ +package io.a2a.server.events; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import io.a2a.server.tasks.PushNotificationSender; +import io.a2a.server.tasks.TaskManager; +import io.a2a.server.tasks.TaskPersistenceException; +import io.a2a.server.tasks.TaskSerializationException; +import io.a2a.server.tasks.TaskStore; +import io.a2a.spec.Event; +import io.a2a.spec.InternalError; +import io.a2a.spec.Task; +import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatus; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.LoggerFactory; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; + +/** + * Integration tests for MainEventBusProcessor exception handling. + *

        + * Tests verify that TaskStore persistence failures are converted to InternalError events + * and distributed to clients with appropriate logging based on failure type: + *

          + *
        • TaskSerializationException → ERROR log + InternalError
        • + *
        • TaskPersistenceException → ERROR log + InternalError
        • + *
        + */ +public class MainEventBusProcessorExceptionTest { + + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final String TASK_ID = "test-task-123"; + + private MainEventBus mainEventBus; + private MainEventBusProcessor mainEventBusProcessor; + private TaskStore mockTaskStore; + private InMemoryQueueManager queueManager; + private EventQueue eventQueue; + private ListAppender logAppender; + + @BeforeEach + public void setUp() { + // Set up mock TaskStore + mockTaskStore = mock(TaskStore.class); + + // Set up MainEventBus and processor with mock TaskStore + mainEventBus = new MainEventBus(); + queueManager = new InMemoryQueueManager(null, mainEventBus); // null TaskStateProvider for tests + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, mockTaskStore, + NOOP_PUSHNOTIFICATION_SENDER, queueManager); + + // Set up log capture for verifying error messages + Logger logger = (Logger) LoggerFactory.getLogger(MainEventBusProcessor.class); + logAppender = new ListAppender<>(); + logAppender.start(); + logger.addAppender(logAppender); + + // Start processor + EventQueueUtil.start(mainEventBusProcessor); + + // Create event queue for testing + eventQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .taskId(TASK_ID) + .mainEventBus(mainEventBus) + .build().tap(); + } + + @AfterEach + public void tearDown() { + if (mainEventBusProcessor != null) { + mainEventBusProcessor.setCallback(null); + EventQueueUtil.stop(mainEventBusProcessor); + } + + // Clean up log appender + Logger logger = (Logger) LoggerFactory.getLogger(MainEventBusProcessor.class); + logger.detachAppender(logAppender); + } + + /** + * Test that TaskSerializationException is converted to InternalError with ERROR log. + * AC#1: Mock TaskStore throws TaskSerializationException → MainEventBusProcessor distributes InternalError + */ + @Test + public void testTaskSerializationException_ConvertsToInternalError() throws InterruptedException { + // Arrange: Mock TaskStore to throw TaskSerializationException + String exceptionMessage = "Failed to deserialize corrupted JSON"; + TaskSerializationException exception = new TaskSerializationException(TASK_ID, exceptionMessage); + when(mockTaskStore.get(any())).thenThrow(exception); + doThrow(exception).when(mockTaskStore).save(any(Task.class), anyBoolean()); + + Task testTask = createTestTask(); + + // Act: Enqueue event and wait for processing + List distributedEvents = captureDistributedEvent(testTask); + + // Assert: Verify InternalError was distributed + assertEquals(1, distributedEvents.size(), "Should distribute exactly one event"); + Event distributedEvent = distributedEvents.get(0); + assertInstanceOf(InternalError.class, distributedEvent, + "TaskSerializationException should convert to InternalError"); + + InternalError error = (InternalError) distributedEvent; + assertTrue(error.getMessage().contains(TASK_ID), + "Error message should contain task ID: " + error.getMessage()); + assertTrue(error.getMessage().contains("serialize"), + "Error message should mention serialization: " + error.getMessage()); + + // Assert: Verify ERROR level logging + boolean foundErrorLog = logAppender.list.stream() + .anyMatch(event -> event.getLevel() == Level.ERROR + && event.getFormattedMessage().contains(TASK_ID) + && event.getFormattedMessage().contains("serialization")); + assertTrue(foundErrorLog, "Should log TaskSerializationException at ERROR level"); + } + + /** + * Test that TaskPersistenceException is converted to InternalError with ERROR log. + * AC#2: Mock TaskStore throws TaskPersistenceException → ERROR log + InternalError + */ + @Test + public void testTaskPersistenceException_ConvertsToInternalError() throws InterruptedException { + // Arrange: Mock TaskStore to throw TaskPersistenceException + String exceptionMessage = "Database operation failed"; + TaskPersistenceException exception = new TaskPersistenceException( + TASK_ID, exceptionMessage + ); + when(mockTaskStore.get(any())).thenThrow(exception); + doThrow(exception).when(mockTaskStore).save(any(Task.class), anyBoolean()); + + Task testTask = createTestTask(); + + // Act: Enqueue event and wait for processing + List distributedEvents = captureDistributedEvent(testTask); + + // Assert: Verify InternalError was distributed + assertEquals(1, distributedEvents.size(), "Should distribute exactly one event"); + Event distributedEvent = distributedEvents.get(0); + assertInstanceOf(InternalError.class, distributedEvent, + "TaskPersistenceException should convert to InternalError"); + + InternalError error = (InternalError) distributedEvent; + assertTrue(error.getMessage().contains(TASK_ID), + "Error message should contain task ID: " + error.getMessage()); + + // Assert: Verify ERROR level logging + boolean foundErrorLog = logAppender.list.stream() + .anyMatch(event -> event.getLevel() == Level.ERROR + && event.getFormattedMessage().contains(TASK_ID) + && event.getFormattedMessage().contains("persistence failed")); + assertTrue(foundErrorLog, "Should log TaskPersistenceException at ERROR level"); + } + + /** + * Test that taskId is preserved through exception chain and appears in error messages. + * AC#5: All tests validate error messages contain taskId and failure type + */ + @Test + public void testTaskIdPreservedInExceptionChain() throws InterruptedException { + // Arrange: Create exception with specific taskId + String specificTaskId = "task-with-unique-id-12345"; + TaskSerializationException exception = new TaskSerializationException( + specificTaskId, "Test exception with specific task ID" + ); + when(mockTaskStore.get(any())).thenThrow(exception); + doThrow(exception).when(mockTaskStore).save(any(Task.class), anyBoolean()); + + // Create event queue with specific taskId + EventQueue specificQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) + .taskId(specificTaskId) + .mainEventBus(mainEventBus) + .build().tap(); + + Task testTask = Task.builder() + .id(specificTaskId) + .contextId("test-context") + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) + .build(); + + // Act: Enqueue event and wait for processing + List distributedEvents = new ArrayList<>(); + CountDownLatch latch = new CountDownLatch(1); + mainEventBusProcessor.setCallback(new MainEventBusProcessorCallback() { + @Override + public void onEventProcessed(String taskId, Event event) { + distributedEvents.add(event); + latch.countDown(); + } + + @Override + public void onTaskFinalized(String taskId) { + // No-op for this test + } + }); + + specificQueue.enqueueEvent(testTask); + assertTrue(latch.await(5, TimeUnit.SECONDS), "Event processing should complete within timeout"); + + // Assert: Verify specific taskId appears in distributed error + assertEquals(1, distributedEvents.size()); + InternalError error = (InternalError) distributedEvents.get(0); + assertTrue(error.getMessage().contains(specificTaskId), + "Error should contain specific task ID: " + error.getMessage()); + + // Assert: Verify specific taskId appears in logs + boolean foundTaskIdInLog = logAppender.list.stream() + .anyMatch(event -> event.getFormattedMessage().contains(specificTaskId)); + assertTrue(foundTaskIdInLog, "Logs should contain specific task ID"); + } + + /** + * Helper method to create a test Task. + */ + private Task createTestTask() { + return Task.builder() + .id(TASK_ID) + .contextId("test-context") + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) + .build(); + } + + /** + * Helper method to enqueue an event and capture what gets distributed to clients. + * Uses MainEventBusProcessorCallback to wait for async processing. + * + * @param event the event to enqueue + * @return list of events distributed to ChildQueues (should be 1 event) + */ + private List captureDistributedEvent(Event event) throws InterruptedException { + List distributedEvents = new ArrayList<>(); + CountDownLatch latch = new CountDownLatch(1); + + mainEventBusProcessor.setCallback(new MainEventBusProcessorCallback() { + @Override + public void onEventProcessed(String taskId, Event processedEvent) { + distributedEvents.add(processedEvent); + latch.countDown(); + } + + @Override + public void onTaskFinalized(String taskId) { + // No-op for exception tests + } + }); + + eventQueue.enqueueEvent(event); + + assertTrue(latch.await(5, TimeUnit.SECONDS), + "Event processing should complete within timeout"); + + return distributedEvents; + } +} diff --git a/server-common/src/test/java/io/a2a/server/tasks/AbstractTaskStoreExceptionTest.java b/server-common/src/test/java/io/a2a/server/tasks/AbstractTaskStoreExceptionTest.java new file mode 100644 index 000000000..9646c24bf --- /dev/null +++ b/server-common/src/test/java/io/a2a/server/tasks/AbstractTaskStoreExceptionTest.java @@ -0,0 +1,168 @@ +package io.a2a.server.tasks; + +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 static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; + +/** + * Base test class for TaskStore exception validation. + *

        + * Provides reusable test patterns for exception construction, field verification, + * and message formatting. Subclasses must implement {@link #createException} methods + * to test specific exception types. + *

        + * This class is designed to be extended by implementation tests (e.g., InMemoryTaskStore tests) + * to ensure consistent exception behavior across all TaskStore implementations. + * + * @param the exception type being tested (must extend TaskStoreException) + */ +public abstract class AbstractTaskStoreExceptionTest { + + /** + * Creates an exception with a message and taskId. + * Used for testing basic exception construction with task context. + * + * @param taskId the task identifier + * @param message the exception message + * @return the constructed exception + */ + protected abstract T createException(String taskId, String message); + + /** + * Creates an exception with a taskId, message, and cause. + * Used for testing exception chaining with task context. + * + * @param taskId the task identifier + * @param message the exception message + * @param cause the underlying cause + * @return the constructed exception + */ + protected abstract T createException(String taskId, String message, Throwable cause); + + // ========== Task ID Field Tests ========== + + @Test + void testTaskIdField_withTaskId() { + T exception = createException("task-123", "Test message"); + assertEquals("task-123", exception.getTaskId()); + } + + @Test + void testTaskIdField_nullTaskId() { + T exception = createException(null, "Test message"); + assertNull(exception.getTaskId()); + } + + @Test + void testTaskIdField_emptyTaskId() { + T exception = createException("", "Test message"); + assertEquals("", exception.getTaskId()); + } + + // ========== Message Field Tests ========== + + @Test + void testMessageField_nonNull() { + T exception = createException("task-123", "Failed to save task"); + assertNotNull(exception.getMessage()); + assertEquals("Failed to save task", exception.getMessage()); + } + + @Test + void testMessageField_withContext() { + T exception = createException("task-123", "Database connection timeout"); + assertNotNull(exception.getMessage()); + assertEquals("Database connection timeout", exception.getMessage()); + } + + // ========== Cause Chain Tests ========== + + @Test + void testCauseChain_withCause() { + RuntimeException cause = new RuntimeException("Root cause"); + T exception = createException("task-123", "Wrapper message", cause); + + assertNotNull(exception.getCause()); + assertSame(cause, exception.getCause()); + assertEquals("Root cause", exception.getCause().getMessage()); + } + + @Test + void testCauseChain_multipleLevels() { + RuntimeException rootCause = new RuntimeException("Database error"); + IllegalStateException intermediateCause = new IllegalStateException("Transaction failed", rootCause); + T exception = createException("task-123", "Save failed", intermediateCause); + + assertNotNull(exception.getCause()); + assertSame(intermediateCause, exception.getCause()); + assertNotNull(exception.getCause().getCause()); + assertSame(rootCause, exception.getCause().getCause()); + } + + // ========== Exception Inheritance Tests ========== + + @Test + void testInheritance_isTaskStoreException() { + T exception = createException("task-123", "Test message"); + assertNotNull(exception); + // Verified by generic type constraint: T extends TaskStoreException + } + + @Test + void testInheritance_isThrowable() { + T exception = createException("task-123", "Test message"); + Throwable throwable = exception; + assertNotNull(throwable); + } + + // ========== Message Clarity Tests ========== + + /** + * Verifies that exception messages are clear and actionable. + * Subclasses should override this to test domain-specific message patterns. + */ + @Test + void testMessageClarity_basicPattern() { + T exception = createException("task-123", "Operation failed"); + String message = exception.getMessage(); + + assertNotNull(message); + // Message should not be empty + assert !message.trim().isEmpty() : "Exception message should not be empty"; + // Message should not be too short (less than 5 characters is typically not helpful) + assert message.length() >= 5 : "Exception message should be descriptive"; + } + + // ========== Helper Assertions for Subclasses ========== + + /** + * Asserts that an exception message contains expected context information. + * Useful for implementation tests to verify TaskStore-specific message patterns. + * + * @param exception the exception to check + * @param expectedSubstring the expected substring in the message + */ + protected void assertMessageContains(T exception, String expectedSubstring) { + assertNotNull(exception.getMessage()); + assert exception.getMessage().contains(expectedSubstring) + : String.format("Expected message to contain '%s' but was: %s", + expectedSubstring, exception.getMessage()); + } + + /** + * Asserts that an exception has both taskId and cause properly set. + * Useful for implementation tests to verify complete exception context. + * + * @param exception the exception to check + * @param expectedTaskId the expected task ID + * @param expectedCause the expected cause + */ + protected void assertFullContext(T exception, String expectedTaskId, Throwable expectedCause) { + assertEquals(expectedTaskId, exception.getTaskId()); + assertSame(expectedCause, exception.getCause()); + assertNotNull(exception.getMessage()); + } +} diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskPersistenceExceptionTest.java b/server-common/src/test/java/io/a2a/server/tasks/TaskPersistenceExceptionTest.java new file mode 100644 index 000000000..51ad86dc3 --- /dev/null +++ b/server-common/src/test/java/io/a2a/server/tasks/TaskPersistenceExceptionTest.java @@ -0,0 +1,258 @@ +package io.a2a.server.tasks; + +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 static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link TaskPersistenceException}. + *

        + * Tests the exception class for database/storage system failures. + */ +class TaskPersistenceExceptionTest extends AbstractTaskStoreExceptionTest { + + @Override + protected TaskPersistenceException createException(String taskId, String message) { + return new TaskPersistenceException(taskId, message); + } + + @Override + protected TaskPersistenceException createException(String taskId, String message, Throwable cause) { + return new TaskPersistenceException(taskId, message, cause); + } + + // ========== Constructor Tests ========== + + @Test + void testConstructor_noArgs() { + TaskPersistenceException exception = new TaskPersistenceException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_messageOnly() { + TaskPersistenceException exception = new TaskPersistenceException("Database error"); + assertEquals("Database error", exception.getMessage()); + assertNull(exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_causeOnly() { + RuntimeException cause = new RuntimeException("Connection failed"); + TaskPersistenceException exception = new TaskPersistenceException(cause); + + assertNotNull(exception.getMessage()); + assertSame(cause, exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_messageAndCause() { + RuntimeException cause = new RuntimeException("Timeout"); + TaskPersistenceException exception = new TaskPersistenceException("Operation failed", cause); + + assertEquals("Operation failed", exception.getMessage()); + assertSame(cause, exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_taskIdAndMessage() { + TaskPersistenceException exception = new TaskPersistenceException("task-123", "Save failed"); + + assertEquals("Save failed", exception.getMessage()); + assertEquals("task-123", exception.getTaskId()); + assertNull(exception.getCause()); + } + + @Test + void testConstructor_taskIdMessageAndCause() { + RuntimeException cause = new RuntimeException("Disk error"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-456", "Persistence failed", cause); + + assertEquals("Persistence failed", exception.getMessage()); + assertEquals("task-456", exception.getTaskId()); + assertSame(cause, exception.getCause()); + } + + // ========== Inheritance Verification ========== + + @Test + void testInheritance_extendsTaskStoreException() { + TaskPersistenceException exception = new TaskPersistenceException("test", "Test message"); + TaskStoreException baseException = exception; + assertNotNull(baseException); + } + + @Test + void testInheritance_taskIdFieldAccessible() { + TaskPersistenceException exception = new TaskPersistenceException("task-xyz", "Test message"); + // Should be accessible via TaskStoreException parent class + assertEquals("task-xyz", exception.getTaskId()); + } + + // ========== Real-World Scenario Tests ========== + + @Test + void testScenario_connectionTimeout() { + RuntimeException timeout = new RuntimeException("Connection timeout after 30s"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-123", "Database connection timeout", timeout); + + assertFullContext(exception, "task-123", timeout); + assertMessageContains(exception, "timeout"); + } + + @Test + void testScenario_deadlock() { + RuntimeException deadlock = new RuntimeException("Deadlock detected"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-456", "Transaction deadlock", deadlock); + + assertMessageContains(exception, "deadlock"); + } + + @Test + void testScenario_lockTimeout() { + RuntimeException lockTimeout = new RuntimeException("Lock wait timeout exceeded"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-789", "Failed to acquire row lock", lockTimeout); + + assertMessageContains(exception, "lock"); + } + + @Test + void testScenario_networkPartition() { + RuntimeException networkError = new RuntimeException("Network unreachable"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-abc", "Database host unreachable due to network partition", networkError); + + assertMessageContains(exception, "network"); + } + + @Test + void testScenario_poolExhausted() { + RuntimeException poolError = new RuntimeException("Connection pool exhausted"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-def", "No database connections available", poolError); + + assertMessageContains(exception, "connections available"); + } + + @Test + void testScenario_diskFull() { + RuntimeException diskError = new RuntimeException("No space left on device"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-123", "Cannot write task: disk full", diskError); + + assertMessageContains(exception, "disk full"); + } + + @Test + void testScenario_uniqueConstraint() { + RuntimeException constraintError = new RuntimeException("Duplicate entry for key 'PRIMARY'"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-456", "Task ID already exists", constraintError); + + assertMessageContains(exception, "already exists"); + } + + @Test + void testScenario_foreignKeyViolation() { + RuntimeException fkError = new RuntimeException("Cannot add or update child row"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-789", "Foreign key constraint violation", fkError); + + assertMessageContains(exception, "constraint"); + } + + @Test + void testScenario_permissionDenied() { + RuntimeException permError = new RuntimeException("Access denied for user 'app'"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-abc", "Insufficient database permissions", permError); + + assertMessageContains(exception, "permission"); + } + + @Test + void testScenario_schemaIncompatibility() { + RuntimeException schemaError = new RuntimeException("Column 'new_field' does not exist"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-def", "Database schema incompatible with application version", schemaError); + + assertMessageContains(exception, "schema"); + } + + @Test + void testScenario_quotaExceeded() { + RuntimeException quotaError = new RuntimeException("Storage quota exceeded"); + TaskPersistenceException exception = new TaskPersistenceException( + "task-ghi", "Database storage limit reached", quotaError); + + assertMessageContains(exception, "storage limit"); + } + + // ========== Message Quality Tests ========== + + @Test + void testMessage_connectionError() { + TaskPersistenceException exception = new TaskPersistenceException( + "task-123", + "Failed to connect to database at jdbc:postgresql://localhost:5432/a2a"); + + assertMessageContains(exception, "connect to database"); + assertMessageContains(exception, "jdbc:postgresql"); + } + + @Test + void testMessage_transactionRollback() { + TaskPersistenceException exception = new TaskPersistenceException( + "task-123", + "Transaction rolled back due to deadlock"); + + assertMessageContains(exception, "Transaction rolled back"); + } + + @Test + void testMessage_constraintViolation() { + TaskPersistenceException exception = new TaskPersistenceException( + "task-123", + "Unique constraint violation: task_id 'task-123' already exists in table 'tasks'"); + + assertMessageContains(exception, "Unique constraint"); + assertMessageContains(exception, "already exists"); + } + + // ========== Cause Chain Tests ========== + + @Test + void testCauseChain_withContext() { + RuntimeException sqlError = new RuntimeException("SQL state: 08006 - Connection failure"); + RuntimeException jdbcError = new RuntimeException("JDBC connection error", sqlError); + TaskPersistenceException exception = new TaskPersistenceException( + "task-xyz", "Database operation failed", jdbcError); + + assertEquals("task-xyz", exception.getTaskId()); + assertSame(jdbcError, exception.getCause()); + assertSame(sqlError, exception.getCause().getCause()); + } + + // ========== Null Safety ========== + + @Test + void testNullSafety_nullTaskId() { + TaskPersistenceException exception = new TaskPersistenceException( + null, "Generic database error"); + + assertNull(exception.getTaskId()); + assertEquals("Generic database error", exception.getMessage()); + } +} diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskSerializationExceptionTest.java b/server-common/src/test/java/io/a2a/server/tasks/TaskSerializationExceptionTest.java new file mode 100644 index 000000000..df356ef14 --- /dev/null +++ b/server-common/src/test/java/io/a2a/server/tasks/TaskSerializationExceptionTest.java @@ -0,0 +1,272 @@ +package io.a2a.server.tasks; + +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 static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link TaskSerializationException}. + *

        + * Tests the exception class for task serialization/deserialization failures, + * verifying all constructor variants. + */ +class TaskSerializationExceptionTest extends AbstractTaskStoreExceptionTest { + + @Override + protected TaskSerializationException createException(String taskId, String message) { + return new TaskSerializationException(taskId, message); + } + + @Override + protected TaskSerializationException createException(String taskId, String message, Throwable cause) { + return new TaskSerializationException(taskId, message, cause); + } + + // ========== Constructor Tests ========== + + @Test + void testConstructor_noArgs() { + TaskSerializationException exception = new TaskSerializationException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_messageOnly() { + TaskSerializationException exception = new TaskSerializationException("JSON parsing failed"); + assertEquals("JSON parsing failed", exception.getMessage()); + assertNull(exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_causeOnly() { + RuntimeException cause = new RuntimeException("Invalid JSON format"); + TaskSerializationException exception = new TaskSerializationException(cause); + + assertNotNull(exception.getMessage()); + // Exception message should contain cause class name + assert exception.getMessage().contains("RuntimeException"); + assertSame(cause, exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_messageAndCause() { + RuntimeException cause = new RuntimeException("Unexpected field type"); + TaskSerializationException exception = new TaskSerializationException("Deserialization failed", cause); + + assertEquals("Deserialization failed", exception.getMessage()); + assertSame(cause, exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_taskIdAndMessage() { + TaskSerializationException exception = new TaskSerializationException( + "task-123", "Failed to serialize task"); + + assertEquals("Failed to serialize task", exception.getMessage()); + assertEquals("task-123", exception.getTaskId()); + assertNull(exception.getCause()); + } + + @Test + void testConstructor_taskIdMessageAndCause() { + RuntimeException cause = new RuntimeException("Missing required field"); + TaskSerializationException exception = new TaskSerializationException( + "task-456", "Task deserialization failed", cause); + + assertEquals("Task deserialization failed", exception.getMessage()); + assertEquals("task-456", exception.getTaskId()); + assertSame(cause, exception.getCause()); + } + + // ========== Inheritance Verification ========== + + @Test + void testInheritance_extendsTaskStoreException() { + TaskSerializationException exception = new TaskSerializationException("test", "Test message"); + TaskStoreException baseException = exception; + assertNotNull(baseException); + } + + @Test + void testInheritance_taskIdFieldAccessible() { + TaskSerializationException exception = new TaskSerializationException("task-789", "Test message"); + // Should be accessible via TaskStoreException parent class + assertEquals("task-789", exception.getTaskId()); + } + + // ========== Message Quality Tests - Serialization Context ========== + + @Test + void testMessage_jsonParsingError() { + TaskSerializationException exception = new TaskSerializationException( + "task-123", + "Failed to deserialize task: unexpected token at line 42, column 15"); + + assertNotNull(exception.getMessage()); + assertMessageContains(exception, "deserialize"); + assertMessageContains(exception, "line 42"); + } + + @Test + void testMessage_invalidFieldType() { + TaskSerializationException exception = new TaskSerializationException( + "task-123", + "Field 'status' expected enum TaskState, got string 'INVALID'"); + + assertNotNull(exception.getMessage()); + assertMessageContains(exception, "Field 'status'"); + assertMessageContains(exception, "expected enum"); + } + + @Test + void testMessage_missingRequiredField() { + TaskSerializationException exception = new TaskSerializationException( + "task-123", + "Missing required field 'id' during task deserialization"); + + assertNotNull(exception.getMessage()); + assertMessageContains(exception, "Missing required field"); + assertMessageContains(exception, "'id'"); + } + + @Test + void testMessage_schemaVersionMismatch() { + TaskSerializationException exception = new TaskSerializationException( + "task-123", + "Task schema version 2.0 not compatible with current version 1.0"); + + assertNotNull(exception.getMessage()); + assertMessageContains(exception, "schema version"); + assertMessageContains(exception, "not compatible"); + } + + // ========== Real-World Scenario Tests ========== + + @Test + void testScenario_jsonProcessingException() { + // Simulate Jackson JsonProcessingException wrapping + RuntimeException jsonError = new RuntimeException( + "Unrecognized field \"unknownField\" (class Task), not marked as ignorable"); + TaskSerializationException exception = new TaskSerializationException( + "task-abc", "Failed to deserialize task from JSON", jsonError); + + assertFullContext(exception, "task-abc", jsonError); + assertMessageContains(exception, "Failed to deserialize"); + } + + @Test + void testScenario_enumConversionError() { + RuntimeException enumError = new RuntimeException( + "Cannot deserialize value of type `TaskState` from String \"INVALID_STATE\""); + TaskSerializationException exception = new TaskSerializationException( + "task-def", "Invalid enum value in task JSON", enumError); + + assertFullContext(exception, "task-def", enumError); + assertMessageContains(exception, "Invalid enum value"); + } + + @Test + void testScenario_nullValueError() { + TaskSerializationException exception = new TaskSerializationException( + "task-ghi", + "Required field 'taskId' cannot be null during deserialization"); + + assertEquals("task-ghi", exception.getTaskId()); + assertMessageContains(exception, "cannot be null"); + } + + // ========== Cause Chain for Debugging ========== + + @Test + void testCauseChain_multiLevelSerializationError() { + // Simulate nested serialization error with multiple layers + RuntimeException rootCause = new RuntimeException("Invalid UTF-8 sequence at byte 1024"); + IllegalArgumentException parseError = new IllegalArgumentException("Cannot parse JSON", rootCause); + TaskSerializationException exception = new TaskSerializationException( + "task-xyz", "Task deserialization failed", parseError); + + // Verify full chain for debugging + assertEquals("task-xyz", exception.getTaskId()); + assertSame(parseError, exception.getCause()); + assertSame(rootCause, exception.getCause().getCause()); + assertMessageContains(exception, "deserialization failed"); + } + + // ========== Edge Cases ========== + + @Test + void testEdgeCase_emptyJsonError() { + TaskSerializationException exception = new TaskSerializationException( + "task-empty", "Cannot deserialize empty JSON string"); + + assertEquals("task-empty", exception.getTaskId()); + assertMessageContains(exception, "empty JSON"); + } + + @Test + void testEdgeCase_circularReferenceError() { + TaskSerializationException exception = new TaskSerializationException( + "task-circular", + "Infinite recursion detected during serialization (StackOverflowError)"); + + assertEquals("task-circular", exception.getTaskId()); + assertMessageContains(exception, "Infinite recursion"); + } + + @Test + void testEdgeCase_characterEncodingError() { + RuntimeException encodingError = new RuntimeException("Invalid character encoding"); + TaskSerializationException exception = new TaskSerializationException( + "task-encoding", "Failed to encode task JSON", encodingError); + + assertFullContext(exception, "task-encoding", encodingError); + } + + // ========== Message Actionability Tests ========== + + @Test + void testMessageActionable_providesContext() { + TaskSerializationException exception = new TaskSerializationException( + "task-123", + "Failed to deserialize task: field 'createdAt' expects ISO-8601 timestamp, got '2024-13-45'"); + + // Message should help developer understand the problem + assertMessageContains(exception, "field 'createdAt'"); + assertMessageContains(exception, "expects ISO-8601"); + assertMessageContains(exception, "got '2024-13-45'"); + } + + @Test + void testMessageActionable_suggestsResolution() { + TaskSerializationException exception = new TaskSerializationException( + "task-123", + "Schema version mismatch. Run database migration to update task format to v2.0"); + + assertMessageContains(exception, "Schema version"); + assertMessageContains(exception, "Run database migration"); + } + + // ========== Null Safety ========== + + @Test + void testNullSafety_nullTaskIdWithMessage() { + TaskSerializationException exception = new TaskSerializationException(null, "Generic serialization error"); + assertNull(exception.getTaskId()); + assertEquals("Generic serialization error", exception.getMessage()); + } + + @Test + void testNullSafety_nullMessageWithTaskId() { + TaskSerializationException exception = new TaskSerializationException("task-123", (String) null); + assertEquals("task-123", exception.getTaskId()); + assertNull(exception.getMessage()); + } +} diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskStoreExceptionTest.java b/server-common/src/test/java/io/a2a/server/tasks/TaskStoreExceptionTest.java new file mode 100644 index 000000000..351e4332f --- /dev/null +++ b/server-common/src/test/java/io/a2a/server/tasks/TaskStoreExceptionTest.java @@ -0,0 +1,191 @@ +package io.a2a.server.tasks; + +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 static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link TaskStoreException}. + *

        + * Tests the base exception class for TaskStore persistence layer failures, + * verifying all constructor variants and field behavior. + */ +class TaskStoreExceptionTest extends AbstractTaskStoreExceptionTest { + + @Override + protected TaskStoreException createException(String taskId, String message) { + return new TaskStoreException(taskId, message); + } + + @Override + protected TaskStoreException createException(String taskId, String message, Throwable cause) { + return new TaskStoreException(taskId, message, cause); + } + + // ========== Constructor Tests ========== + + @Test + void testConstructor_noArgs() { + TaskStoreException exception = new TaskStoreException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_messageOnly() { + TaskStoreException exception = new TaskStoreException("Failed to persist task"); + assertEquals("Failed to persist task", exception.getMessage()); + assertNull(exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_causeOnly() { + RuntimeException cause = new RuntimeException("Database error"); + TaskStoreException exception = new TaskStoreException(cause); + + assertNotNull(exception.getMessage()); + // Exception message should contain cause class name + assert exception.getMessage().contains("RuntimeException"); + assertSame(cause, exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_messageAndCause() { + RuntimeException cause = new RuntimeException("Database error"); + TaskStoreException exception = new TaskStoreException("Persistence failed", cause); + + assertEquals("Persistence failed", exception.getMessage()); + assertSame(cause, exception.getCause()); + assertNull(exception.getTaskId()); + } + + @Test + void testConstructor_taskIdAndMessage() { + TaskStoreException exception = new TaskStoreException("task-123", "Failed to save"); + + assertEquals("Failed to save", exception.getMessage()); + assertEquals("task-123", exception.getTaskId()); + assertNull(exception.getCause()); + } + + @Test + void testConstructor_taskIdMessageAndCause() { + RuntimeException cause = new RuntimeException("Connection timeout"); + TaskStoreException exception = new TaskStoreException("task-456", "Save operation failed", cause); + + assertEquals("Save operation failed", exception.getMessage()); + assertEquals("task-456", exception.getTaskId()); + assertSame(cause, exception.getCause()); + } + + // ========== Task ID Edge Cases ========== + + @Test + void testTaskId_uuid() { + String uuid = "550e8400-e29b-41d4-a716-446655440000"; + TaskStoreException exception = new TaskStoreException(uuid, "Test message"); + assertEquals(uuid, exception.getTaskId()); + } + + @Test + void testTaskId_numericString() { + TaskStoreException exception = new TaskStoreException("12345", "Test message"); + assertEquals("12345", exception.getTaskId()); + } + + @Test + void testTaskId_specialCharacters() { + String taskId = "task-123_v2.0"; + TaskStoreException exception = new TaskStoreException(taskId, "Test message"); + assertEquals(taskId, exception.getTaskId()); + } + + // ========== Inheritance Verification ========== + + @Test + void testInheritance_extendsA2AServerException() { + TaskStoreException exception = new TaskStoreException("test", "Test message"); + assertNotNull(exception); + // TaskStoreException extends A2AServerException (verified by compilation) + } + + @Test + void testInheritance_isException() { + TaskStoreException exception = new TaskStoreException("test", "Test message"); + Exception e = exception; + assertNotNull(e); + } + + // ========== Message Quality Tests ========== + + @Test + void testMessage_descriptive() { + TaskStoreException exception = new TaskStoreException( + "task-123", + "Failed to persist task to database: connection timeout after 30s"); + + assertNotNull(exception.getMessage()); + assertMessageContains(exception, "Failed to persist"); + assertMessageContains(exception, "database"); + assertMessageContains(exception, "connection timeout"); + } + + @Test + void testMessage_actionable() { + TaskStoreException exception = new TaskStoreException( + "task-123", + "Task not found in store. Verify taskId and retry operation."); + + assertNotNull(exception.getMessage()); + assertMessageContains(exception, "Task not found"); + assertMessageContains(exception, "Verify taskId"); + } + + // ========== Cause Chain Preservation ========== + + @Test + void testCausePreservation_multipleWrapping() { + RuntimeException rootCause = new RuntimeException("Disk full"); + IllegalStateException level1 = new IllegalStateException("Write failed", rootCause); + IllegalArgumentException level2 = new IllegalArgumentException("Validation failed", level1); + TaskStoreException exception = new TaskStoreException("task-789", "Complete failure", level2); + + // Verify full chain + assertEquals("Complete failure", exception.getMessage()); + assertEquals("task-789", exception.getTaskId()); + assertSame(level2, exception.getCause()); + assertSame(level1, exception.getCause().getCause()); + assertSame(rootCause, exception.getCause().getCause().getCause()); + } + + // ========== Null Safety Tests ========== + + @Test + void testNullSafety_nullMessage() { + TaskStoreException exception = new TaskStoreException("task-123", (String) null); + assertEquals("task-123", exception.getTaskId()); + assertNull(exception.getMessage()); + } + + @Test + void testNullSafety_nullCause() { + TaskStoreException exception = new TaskStoreException("task-123", "Message", (Throwable) null); + assertEquals("task-123", exception.getTaskId()); + assertEquals("Message", exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + void testNullSafety_allNulls() { + TaskStoreException exception = new TaskStoreException(null, (String) null, (Throwable) null); + assertNull(exception.getTaskId()); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } +} From 8c6b50f9d20001bf152a39dda4044c9ae69ee232 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Thu, 5 Mar 2026 10:12:37 +0100 Subject: [PATCH 061/192] chore: fix Javadoc (#701) Signed-off-by: Jeff Mesnil --- .../main/java/io/a2a/transport/grpc/handler/GrpcHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9fee45786..4e34a1af2 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 @@ -96,7 +96,7 @@ *

      • {@link #listTasks} - List tasks with filtering
      • *
      • {@link #createTaskPushNotificationConfig} - Configure push notifications
      • *
      • {@link #getTaskPushNotificationConfig} - Get push notification config
      • - *
      • {@link #listTaskPushNotificationConfig} - List push notification configs
      • + *
      • {@link #listTaskPushNotificationConfigs} - List push notification configs
      • *
      • {@link #deleteTaskPushNotificationConfig} - Delete push notification config
      • *
      • {@link #getExtendedAgentCard} - Get extended agent capabilities
      • * From ebd09217a01c1bcf23ff92fe609127be0f705d9b Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 5 Mar 2026 11:20:52 +0100 Subject: [PATCH 062/192] fix!: rewrite PartTypeAdapter to use flat JSON format for Part serialization (#700) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the nested "file" wrapper with flat fields (raw, url, filename, mediaType) aligned with the proto Part message schema and A2A spec. Fixes #689 🦕 Signed-off-by: Emmanuel Hugonnet --- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 90 ++++-- .../common/json/TaskSerializationTest.java | 20 +- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 4 +- .../a2a/grpc/utils/PartTypeAdapterTest.java | 286 ++++++++++++++++++ 4 files changed, 359 insertions(+), 41 deletions(-) create mode 100644 spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index b301dc98c..734f3043a 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -13,7 +13,6 @@ 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.DataPart.DATA; -import static io.a2a.spec.FilePart.FILE; import static io.a2a.spec.TextPart.TEXT; import static java.lang.String.format; import static java.util.Collections.emptyMap; @@ -521,33 +520,58 @@ public static Map readMetadata(@Nullable String json) throws Jso */ static class PartTypeAdapter extends TypeAdapter> { - private static final Set VALID_KEYS = Set.of(TEXT, FILE, DATA); + private static final String RAW = "raw"; + private static final String URL = "url"; + private static final String FILENAME = "filename"; + private static final String MEDIA_TYPE = "mediaType"; + // The oneOf content-type discriminator keys in the flat JSON format. + // Exactly one must be present (and non-null) in each Part object. + private static final Set VALID_KEYS = Set.of(TEXT, RAW, URL, DATA); private static final Type MAP_TYPE = new TypeToken>(){}.getType(); // Create separate Gson instance without the Part adapter to avoid recursion private final Gson delegateGson = createBaseGsonBuilder().create(); + private void writeMetadata(JsonWriter out, @Nullable Map metadata) throws java.io.IOException { + if (metadata != null && !metadata.isEmpty()) { + out.name("metadata"); + delegateGson.toJson(metadata, MAP_TYPE, out); + } + } + + /** Writes a string field only when the value is non-null and non-empty. */ + private void writeNonEmpty(JsonWriter out, String name, String value) throws java.io.IOException { + if (!value.isEmpty()) { + out.name(name).value(value); + } + } + @Override public void write(JsonWriter out, Part value) throws java.io.IOException { if (value == null) { out.nullValue(); return; } - // Write wrapper object with member name as discriminator out.beginObject(); if (value instanceof TextPart textPart) { - // TextPart: { "text": "value" } - direct string value - out.name(TEXT); - out.value(textPart.text()); - JsonUtil.writeMetadata(out, textPart.metadata()); + out.name(TEXT).value(textPart.text()); + writeMetadata(out, textPart.metadata()); } else if (value instanceof FilePart filePart) { - // FilePart: { "file": {...} } - out.name(FILE); - delegateGson.toJson(filePart.file(), FileContent.class, out); - JsonUtil.writeMetadata(out, filePart.metadata()); + if (filePart.file() instanceof FileWithBytes withBytes) { + out.name(RAW).value(withBytes.bytes()); + writeNonEmpty(out, FILENAME, withBytes.name()); + writeNonEmpty(out, MEDIA_TYPE, withBytes.mimeType()); + } else if (filePart.file() instanceof FileWithUri withUri) { + out.name(URL).value(withUri.uri()); + writeNonEmpty(out, FILENAME, withUri.name()); + writeNonEmpty(out, MEDIA_TYPE, withUri.mimeType()); + } else { + throw new JsonSyntaxException("Unknown FileContent subclass: " + filePart.file().getClass().getName()); + } + writeMetadata(out, filePart.metadata()); + } else if (value instanceof DataPart dataPart) { - // DataPart: { "data": } out.name(DATA); delegateGson.toJson(dataPart.data(), Object.class, out); JsonUtil.writeMetadata(out, dataPart.metadata()); @@ -566,7 +590,6 @@ Part read(JsonReader in) throws java.io.IOException { return null; } - // Read the JSON as a tree to inspect the member name discriminator com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); if (!jsonElement.isJsonObject()) { throw new JsonSyntaxException("Part must be a JSON object"); @@ -576,34 +599,47 @@ Part read(JsonReader in) throws java.io.IOException { // Extract metadata if present Map metadata = JsonUtil.readMetadata(jsonObject); - - // Check for member name discriminators (v1.0 protocol) Set keys = jsonObject.keySet(); - if (keys.size() < 1 || keys.size() > 2) { - throw new JsonSyntaxException(format("Part object must have one content key from %s and optionally 'metadata' (found: %s)", VALID_KEYS, keys)); - } - // Find the discriminator (should be one of TEXT, FILE, DATA) + // Find the oneOf discriminator, skipping null/empty values to tolerate formats + // where multiple content keys may be present with only one populated + // (e.g., proto serialization with alwaysPrintFieldsWithNoPresence). + // Unknown extra fields are ignored. String discriminator = keys.stream() .filter(VALID_KEYS::contains) + .filter(key -> { + com.google.gson.JsonElement el = jsonObject.get(key); + return el != null && !el.isJsonNull(); + }) .findFirst() .orElseThrow(() -> new JsonSyntaxException(format("Part must have one of: %s (found: %s)", VALID_KEYS, keys))); return switch (discriminator) { case TEXT -> new TextPart(jsonObject.get(TEXT).getAsString(), metadata); - case FILE -> new FilePart(delegateGson.fromJson(jsonObject.get(FILE), FileContent.class), metadata); + case RAW -> new FilePart(new FileWithBytes( + stringOrEmpty(jsonObject, MEDIA_TYPE), + stringOrEmpty(jsonObject, FILENAME), + jsonObject.get(RAW).getAsString()), metadata); + case URL -> new FilePart(new FileWithUri( + stringOrEmpty(jsonObject, MEDIA_TYPE), + stringOrEmpty(jsonObject, FILENAME), + jsonObject.get(URL).getAsString()), metadata); case DATA -> { - // DataPart supports any JSON value: object, array, primitive, or null - Object data = delegateGson.fromJson( - jsonObject.get(DATA), - Object.class - ); + Object data = delegateGson.fromJson(jsonObject.get(DATA), Object.class); yield new DataPart(data, metadata); } - default -> - throw new JsonSyntaxException(format("Part must have one of: %s (found: %s)", VALID_KEYS, discriminator)); + default -> throw new JsonSyntaxException(format("Part must have one of: %s (found: %s)", VALID_KEYS, discriminator)); }; } + + /** Returns the string value of the field, or an empty string if absent or null. */ + private String stringOrEmpty(com.google.gson.JsonObject obj, String key) { + com.google.gson.JsonElement el = obj.get(key); + if (el == null || el.isJsonNull()) { + return ""; + } + return el.getAsString(); + } } /** diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java index 9c0fd2610..ff47e746b 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java @@ -255,8 +255,8 @@ void testTaskWithFilePartBytes() throws JsonProcessingException { // Serialize String json = JsonUtil.toJson(task); - // Verify JSON contains file part data (v1.0 format uses member name "file", not "kind") - assertTrue(json.contains("\"file\"")); + // Verify JSON contains file part data in flat format (raw/filename/mediaType, not "file" wrapper) + assertTrue(json.contains("\"raw\"")); assertFalse(json.contains("\"kind\"")); assertTrue(json.contains("document.pdf")); assertTrue(json.contains("application/pdf")); @@ -492,11 +492,9 @@ void testDeserializeTaskWithFilePartBytesFromJson() throws JsonProcessingExcepti "artifactId": "file-artifact", "parts": [ { - "file": { - "mimeType": "application/pdf", - "name": "document.pdf", - "bytes": "base64encodeddata" - } + "raw": "base64encodeddata", + "filename": "document.pdf", + "mediaType": "application/pdf" } ] } @@ -532,11 +530,9 @@ void testDeserializeTaskWithFilePartUriFromJson() throws JsonProcessingException "artifactId": "uri-artifact", "parts": [ { - "file": { - "mimeType": "image/png", - "name": "photo.png", - "uri": "https://example.com/photo.png" - } + "url": "https://example.com/photo.png", + "filename": "photo.png", + "mediaType": "image/png" } ] } 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 0f6d3ed19..6a0f4525a 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 @@ -576,7 +576,7 @@ public static String toJsonRPCRequest(@Nullable String requestId, String method, output.name("method").value(method); } if (payload != null) { - String resultValue = JsonFormat.printer().includingDefaultValueFields().omittingInsignificantWhitespace().print(payload); + String resultValue = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(payload); output.name("params").jsonValue(resultValue); } output.endObject(); @@ -599,7 +599,7 @@ public static String toJsonRPCResultResponse(Object requestId, com.google.protob output.name("id").value(number.longValue()); } } - String resultValue = JsonFormat.printer().includingDefaultValueFields().omittingInsignificantWhitespace().print(builder); + String resultValue = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); output.name("result").jsonValue(resultValue); output.endObject(); return result.toString(); diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java new file mode 100644 index 000000000..8b7eb741b --- /dev/null +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java @@ -0,0 +1,286 @@ +package io.a2a.grpc.utils; + +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; + +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 com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Value; +import com.google.protobuf.util.JsonFormat; +import com.google.protobuf.util.Structs; +import io.a2a.grpc.mapper.A2ACommonFieldMapper; +import java.util.List; +import java.util.Map; + +import io.a2a.spec.DataPart; +import io.a2a.spec.FilePart; +import io.a2a.spec.FileWithBytes; +import io.a2a.spec.FileWithUri; +import io.a2a.spec.Part; +import io.a2a.spec.TextPart; +import java.util.Base64; +import org.junit.jupiter.api.Test; + + +public class PartTypeAdapterTest { + + // ------------------------------------------------------------------------- + // TextPart + // ------------------------------------------------------------------------- + + @Test + public void shouldSerializeTextPart() throws JsonProcessingException { + TextPart part = new TextPart("Hello, world!"); + String json = JsonUtil.toJson(part); + assertEquals("{\"text\":\"Hello, world!\"}", json); + } + + @Test + public void shouldSerializeTextPartWithMetadata() throws JsonProcessingException { + TextPart part = new TextPart("Bonjour!", Map.of("language", "fr")); + String json = JsonUtil.toJson(part); + // Verify the round-trip to avoid ordering issues + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(TextPart.class, deserialized); + TextPart result = (TextPart) deserialized; + assertEquals("Bonjour!", result.text()); + assertEquals("fr", result.metadata().get("language")); + } + + @Test + public void shouldDeserializeTextPart() throws JsonProcessingException, InvalidProtocolBufferException { + io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + builder.setText("Hello, world!"); + String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); + Partpart = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(TextPart.class, part); + TextPart textPart = (TextPart) part; + assertEquals("Hello, world!", textPart.text()); + assertNotNull(textPart.metadata()); + assertEquals(0, textPart.metadata().size()); + } + + @Test + public void shouldDeserializeTextPartWithMetadata() throws JsonProcessingException, InvalidProtocolBufferException { + io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + builder.setText("Hi"); + builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(Map.of("key", "value"))); + String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); + Part part = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(TextPart.class, part); + TextPart textPart = (TextPart) part; + assertEquals("Hi", textPart.text()); + assertEquals("value", textPart.metadata().get("key")); + } + + @Test + public void shouldRoundTripTextPart() throws JsonProcessingException { + TextPart original = new TextPart("round-trip"); + String json = JsonUtil.toJson(original); + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(TextPart.class, deserialized); + assertEquals(original.text(), ((TextPart) deserialized).text()); + } + + // ------------------------------------------------------------------------- + // FilePart – FileWithBytes + // ------------------------------------------------------------------------- + + @Test + public void shouldSerializeFilePartWithBytes() throws JsonProcessingException { + FilePart part = new FilePart(new FileWithBytes("image/png", "diagram.png", "abc12w==")); + String json = JsonUtil.toJson(part); + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(FilePart.class, deserialized); + FileWithBytes result = (FileWithBytes) ((FilePart) deserialized).file(); + assertEquals("image/png", result.mimeType()); + assertEquals("diagram.png", result.name()); + assertEquals("abc12w==", result.bytes()); + } + + @Test + public void shouldDeserializeFilePartWithBytes() throws JsonProcessingException, InvalidProtocolBufferException { + io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + builder.setFilename("diagram.png").setMediaType("image/png").setRaw(ByteString.copyFrom(Base64.getDecoder().decode("abc12w=="))); + builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(Map.of("key", "value"))); + String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); + Part part = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(FilePart.class, part); + FilePart filePart = (FilePart) part; + assertInstanceOf(FileWithBytes.class, filePart.file()); + FileWithBytes fileWithBytes = (FileWithBytes) filePart.file(); + assertEquals("image/png", fileWithBytes.mimeType()); + assertEquals("diagram.png", fileWithBytes.name()); + assertEquals("abc12w==", fileWithBytes.bytes()); + assertEquals("value", filePart.metadata().get("key")); + + } + + @Test + public void shouldRoundTripFilePartWithBytes() throws JsonProcessingException { + FilePart original = new FilePart(new FileWithBytes("application/pdf", "report.pdf", "AAEC")); + String json = JsonUtil.toJson(original); + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(FilePart.class, deserialized); + FilePart result = (FilePart) deserialized; + assertInstanceOf(FileWithBytes.class, result.file()); + FileWithBytes bytes = (FileWithBytes) result.file(); + assertEquals("application/pdf", bytes.mimeType()); + assertEquals("report.pdf", bytes.name()); + assertEquals("AAEC", bytes.bytes()); + } + + // ------------------------------------------------------------------------- + // FilePart – FileWithUri + // ------------------------------------------------------------------------- + + @Test + public void shouldSerializeFilePartWithUri() throws JsonProcessingException { + FilePart part = new FilePart(new FileWithUri("image/png", "photo.png", "https://example.com/photo.png")); + String json = JsonUtil.toJson(part); + // Verify the serialized JSON can be deserialized correctly (round-trip) + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(FilePart.class, deserialized); + FileWithUri result = (FileWithUri) ((FilePart) deserialized).file(); + assertEquals("image/png", result.mimeType()); + assertEquals("photo.png", result.name()); + assertEquals("https://example.com/photo.png", result.uri()); + } + + @Test + public void shouldDeserializeFilePartWithUri() throws JsonProcessingException, InvalidProtocolBufferException { + io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + builder.setFilename("photo.png").setMediaType("image/png").setUrl("https://example.com/photo.png"); + builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(Map.of("key", "value"))); + String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); + Part part = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(FilePart.class, part); + FilePart filePart = (FilePart) part; + assertInstanceOf(FileWithUri.class, filePart.file()); + FileWithUri fileWithUri = (FileWithUri) filePart.file(); + assertEquals("image/png", fileWithUri.mimeType()); + assertEquals("photo.png", fileWithUri.name()); + assertEquals("https://example.com/photo.png", fileWithUri.uri()); + assertEquals("value", filePart.metadata().get("key")); + } + + @Test + public void shouldRoundTripFilePartWithUri() throws JsonProcessingException { + FilePart original = new FilePart(new FileWithUri("text/plain", "notes.txt", "https://example.com/notes.txt")); + String json = JsonUtil.toJson(original); + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(FilePart.class, deserialized); + FilePart result = (FilePart) deserialized; + assertInstanceOf(FileWithUri.class, result.file()); + FileWithUri uri = (FileWithUri) result.file(); + assertEquals("text/plain", uri.mimeType()); + assertEquals("notes.txt", uri.name()); + assertEquals("https://example.com/notes.txt", uri.uri()); + } + + @Test + public void shouldRoundTripFilePartWithMetadata() throws JsonProcessingException { + FilePart original = new FilePart( + new FileWithUri("image/jpeg", "pic.jpg", "https://example.com/pic.jpg"), + Map.of("source", "camera")); + String json = JsonUtil.toJson(original); + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(FilePart.class, deserialized); + FilePart result = (FilePart) deserialized; + assertEquals("camera", result.metadata().get("source")); + } + + // ------------------------------------------------------------------------- + // DataPart + // ------------------------------------------------------------------------- + + @Test + public void shouldSerializeDataPartWithObject() throws JsonProcessingException { + DataPart part = new DataPart(Map.of("status", "ok")); + String json = JsonUtil.toJson(part); + // Verify round-trip to avoid ordering issues with map serialization + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(DataPart.class, deserialized); + @SuppressWarnings("unchecked") + Map data = (Map) ((DataPart) deserialized).data(); + assertEquals("ok", data.get("status")); + } + + @Test + public void shouldDeserializeDataPartWithObject() throws JsonProcessingException, InvalidProtocolBufferException { + io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + builder.setData(Value.newBuilder().setStructValue(Structs.of("count", Value.newBuilder().setNumberValue(42).build(), "label", Value.newBuilder().setStringValue("items").build()))); + builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(Map.of("key", "value"))); + String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); + Part part = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(DataPart.class, part); + @SuppressWarnings("unchecked") + Map data = (Map) ((DataPart) part).data(); + assertEquals(42.0, data.get("count")); + assertEquals("items", data.get("label")); + } + + @Test + public void shouldSerializeDataPartWithArray() throws JsonProcessingException { + DataPart part = new DataPart(List.of("a", "b", "c")); + String json = JsonUtil.toJson(part); + assertEquals("{\"data\":[\"a\",\"b\",\"c\"]}", json); + } + + @Test + public void shouldDeserializeDataPartWithArray() throws JsonProcessingException { + String json = "{\"data\":[\"a\",\"b\",\"c\"]}"; + Part part = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(DataPart.class, part); + @SuppressWarnings("unchecked") + List data = (List) ((DataPart) part).data(); + assertEquals(List.of("a", "b", "c"), data); + } + + @Test + public void shouldSerializeDataPartWithString() throws JsonProcessingException { + DataPart part = new DataPart("hello"); + String json = JsonUtil.toJson(part); + assertEquals("{\"data\":\"hello\"}", json); + } + + @Test + public void shouldDeserializeDataPartWithString() throws JsonProcessingException { + String json = "{\"data\":\"hello\"}"; + Part part = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(DataPart.class, part); + assertEquals("hello", ((DataPart) part).data()); + } + + @Test + public void shouldSerializeDataPartWithNumber() throws JsonProcessingException { + DataPart part = new DataPart(42L); + String json = JsonUtil.toJson(part); + assertEquals("{\"data\":42}", json); + } + + @Test + public void shouldDeserializeDataPartWithNumber() throws JsonProcessingException { + String json = "{\"data\":42}"; + Part part = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(DataPart.class, part); + assertEquals(42L, ((DataPart) part).data()); + } + + @Test + public void shouldRoundTripDataPartWithMetadata() throws JsonProcessingException { + DataPart original = new DataPart(Map.of("key", "val"), Map.of("version", "1")); + String json = JsonUtil.toJson(original); + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(DataPart.class, deserialized); + DataPart result = (DataPart) deserialized; + assertEquals("1", result.metadata().get("version")); + @SuppressWarnings("unchecked") + Map data = (Map) result.data(); + assertEquals("val", data.get("key")); + } +} From 566978cc794c2bf3cd0557c076a1d3acc35e7e0b Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Fri, 6 Mar 2026 09:55:15 +0100 Subject: [PATCH 063/192] feat!: update a2a.proto to upstream commit dec790a (#705) To do the update to a2a.proto, I added an AGENTS.md (that fixes #595) and an `update-a2a-proto` skill that did the job. @gemini-code-assist pay special attention to this PR to verify that the changes introduced by the a2a.proto matches the code convention of the project. --------- Signed-off-by: Jeff Mesnil Co-authored-by: Claude Opus 4.6 --- AGENTS.md | 78 ++ .../java/io/a2a/client/AbstractClient.java | 5 +- .../src/main/java/io/a2a/client/Client.java | 50 +- .../io/a2a/client/config/ClientConfig.java | 39 +- .../client/transport/grpc/GrpcTransport.java | 7 +- .../jsonrpc/JSONRPCTransportTest.java | 28 +- .../transport/jsonrpc/JsonMessages.java | 26 +- .../client/transport/rest/RestTransport.java | 6 +- .../transport/rest/JsonRestMessages.java | 46 +- .../transport/rest/RestTransportTest.java | 50 +- .../client/OpenTelemetryClientTransport.java | 4 +- .../OpenTelemetryRequestHandlerDecorator.java | 4 +- ...nTelemetryRequestHandlerDecoratorTest.java | 15 +- ...paDatabasePushNotificationConfigStore.java | 27 +- .../jpa/JpaPushNotificationConfig.java | 12 +- ...otificationConfigStoreIntegrationTest.java | 37 +- .../JpaPushNotificationConfigStoreTest.java | 108 +- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 2 +- ...eateTaskPushNotificationConfigRequest.java | 2 - .../common/wrappers/SendMessageRequest.java | 2 +- .../server/grpc/quarkus/A2ATestResource.java | 4 +- .../apps/quarkus/A2AServerRoutesTest.java | 52 +- .../server/apps/quarkus/A2ATestRoutes.java | 4 +- .../server/rest/quarkus/A2ATestRoutes.java | 4 +- .../DefaultRequestHandler.java | 30 +- .../tasks/BasePushNotificationSender.java | 7 +- .../InMemoryPushNotificationConfigStore.java | 44 +- .../tasks/PushNotificationConfigStore.java | 13 +- .../server/tasks/PushNotificationSender.java | 2 +- ...MemoryPushNotificationConfigStoreTest.java | 162 +-- .../tasks/PushNotificationSenderTest.java | 51 +- skills/update-a2a-proto/SKILL.md | 86 ++ spec-grpc/src/main/java/io/a2a/grpc/A2A.java | 589 +++++---- .../main/java/io/a2a/grpc/A2AServiceGrpc.java | 31 +- ...eateTaskPushNotificationConfigRequest.java | 943 -------------- ...ushNotificationConfigRequestOrBuilder.java | 79 -- .../src/main/java/io/a2a/grpc/OAuthFlows.java | 16 +- .../java/io/a2a/grpc/OAuthFlowsOrBuilder.java | 8 +- .../io/a2a/grpc/PushNotificationConfig.java | 1107 ----------------- .../grpc/PushNotificationConfigOrBuilder.java | 99 -- .../io/a2a/grpc/SendMessageConfiguration.java | 186 +-- .../SendMessageConfigurationOrBuilder.java | 19 +- spec-grpc/src/main/java/io/a2a/grpc/Task.java | 28 +- .../main/java/io/a2a/grpc/TaskOrBuilder.java | 8 +- .../a2a/grpc/TaskPushNotificationConfig.java | 747 +++++++++-- .../TaskPushNotificationConfigOrBuilder.java | 88 +- ...reateTaskPushNotificationConfigMapper.java | 71 -- .../MessageSendConfigurationMapper.java | 6 +- .../mapper/PushNotificationConfigMapper.java | 31 - .../TaskPushNotificationConfigMapper.java | 56 +- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 6 +- .../java/io/a2a/grpc/utils/ProtoUtils.java | 15 +- spec-grpc/src/main/proto/a2a.proto | 51 +- .../io/a2a/grpc/utils/JSONRPCUtilsTest.java | 41 +- .../java/io/a2a/grpc/utils/ToProtoTest.java | 48 +- .../java/io/a2a/spec/AuthenticationInfo.java | 2 +- .../io/a2a/spec/MessageSendConfiguration.java | 20 +- .../io/a2a/spec/PushNotificationConfig.java | 145 --- .../java/io/a2a/spec/TaskNotFoundError.java | 9 +- .../a2a/spec/TaskPushNotificationConfig.java | 173 ++- .../apps/common/AbstractA2AServerTest.java | 79 +- .../a2a/server/apps/common/TestUtilsBean.java | 6 +- .../transport/grpc/handler/GrpcHandler.java | 4 +- .../grpc/handler/GrpcHandlerTest.java | 23 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 126 +- .../transport/rest/handler/RestHandler.java | 4 +- .../rest/handler/RestHandlerTest.java | 25 +- 67 files changed, 2097 insertions(+), 3799 deletions(-) create mode 100644 AGENTS.md create mode 100644 skills/update-a2a-proto/SKILL.md delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/PushNotificationConfigMapper.java delete mode 100644 spec/src/main/java/io/a2a/spec/PushNotificationConfig.java diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..c5d2d7eed --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,78 @@ +# AGENTS.md + +## Project Overview + +Java SDK for the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/). Multi-module Maven project (`io.github.a2asdk` group) providing client and server libraries for A2A agent communication over JSON-RPC, gRPC, and REST transports. + +## Build + +Requires Java 17+. +Tests output is redirected to files by default. + +```bash +mvn clean install +``` + + +## Project Structure + +- `spec/` — A2A specification types (Java POJOs for the protocol) +- `spec-grpc/` — gRPC protobuf definitions and generated classes +- `common/` — Shared utilities used across modules +- `client/` — Client SDK + - `base/` — Core client API + - `transport/spi/` — Transport SPI + - `transport/jsonrpc/`, `transport/grpc/`, `transport/rest/` — Transport implementations +- `server-common/` — Server-side core (AgentExecutor, TaskStore, QueueManager) +- `transport/` — Server transport layer (jsonrpc, grpc, rest) +- `http-client/` — HTTP client abstraction +- `jsonrpc-common/` — Shared JSON-RPC utilities +- `reference/` — Reference server implementations built on Quarkus + - `common/`, `jsonrpc/`, `grpc/`, `rest/` +- `tck/` — Technology Compatibility Kit (protocol conformance tests) +- `tests/` — Integration tests +- `extras/` — Optional add-ons (OpenTelemetry, JPA task/notification stores, replicated queue manager, Vert.x HTTP client) +- `integrations/` — Runtime integrations (e.g., MicroProfile Config) +- `boms/` — Bill of Materials POMs (sdk, extras, reference, test-utils) +- `examples/` — Sample applications (helloworld, cloud-deployment) + +## Key Conventions + +- Package root: `io.a2a` +- Serialization: Gson (see `gson.version` in parent POM) +- Null safety: NullAway + JSpecify annotations enforced via Error Prone +- Reference server runtime: Quarkus +- Testing: JUnit 5, Mockito, REST Assured, Testcontainers + +### Code Style + +- Import statements are sorted +- Remove any unused import statements +- Do not use "star" imports (eg `import java.util.*`) +- Use Java `record` for immutable data types +- Use `@Nullable` (from org.jspecify.annotations) for optional fields +- Use `io.a2a.util.Assert.checkNotNullParam()` in the compact constructor to validate required fields +- Use `List.copyOf()` and `Map.copyOf()` for defensive copying of collections +- Apply the Builder pattern for records with many fields (see `AgentCard.java` as reference) + +### Code generation + +- Be concise +- Try to use existing code instead of generating new similar code +- Use the same code convention than existing code. If the existing convention seems incorrect, make suggestion before doing any changes + +### PR instructions +- Follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) for the commit title and message +- Always ask if the commit is related to a GitHub issue. If that's the case, add a `This fixes #{issue_number}` at the end of the commit message + +### Skills + +- [update-a2a-proto](skills/update-a2a-proto/SKILL.md) — Update the gRPC proto file `a2a.proto` from upstream and regenerate Java sources + +### Commands + +- `mvn clean install` — Clean build of the project + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md). Fork the repo, create a branch per issue, submit PRs against `main`. 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 4f7964832..3ef1747d5 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java @@ -19,7 +19,6 @@ import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; import io.a2a.spec.TaskPushNotificationConfig; @@ -137,7 +136,7 @@ public abstract void sendMessage(@NonNull Message request, * @throws A2AClientException if sending the message fails for any reason */ public void sendMessage(@NonNull Message request, - @Nullable PushNotificationConfig pushNotificationConfiguration, + @Nullable TaskPushNotificationConfig pushNotificationConfiguration, @Nullable Map metadata) throws A2AClientException { sendMessage(request, pushNotificationConfiguration, metadata, null); } @@ -158,7 +157,7 @@ public void sendMessage(@NonNull Message request, * @throws A2AClientException if sending the message fails for any reason */ public abstract void sendMessage(@NonNull Message request, - @Nullable PushNotificationConfig pushNotificationConfiguration, + @Nullable TaskPushNotificationConfig pushNotificationConfiguration, @Nullable Map metadata, @Nullable ClientCallContext context) throws A2AClientException; 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 515190c95..2ca01307b 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -26,7 +26,6 @@ import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; @@ -132,10 +131,11 @@ * Push notifications: Configure webhooks to receive task updates: *
        {@code
          * // Configure push notifications for a task
        - * PushNotificationConfig pushConfig = new PushNotificationConfig(
        - *     "https://my-app.com/webhooks/task-updates",
        - *     Map.of("Authorization", "Bearer my-token")
        - * );
        + * TaskPushNotificationConfig pushConfig = TaskPushNotificationConfig.builder()
        + *     .id("config-1")
        + *     .url("https://my-app.com/webhooks/task-updates")
        + *     .authentication(new AuthenticationInfo("Bearer", "my-token"))
        + *     .build();
          *
          * // Send message with push notifications
          * client.sendMessage(
        @@ -236,7 +236,7 @@ public void sendMessage(@NonNull Message request,
                                     @NonNull List> consumers,
                                     @Nullable Consumer streamingErrorHandler,
                                     @Nullable ClientCallContext context) throws A2AClientException {
        -        MessageSendConfiguration messageSendConfiguration = createMessageSendConfiguration(clientConfig.getPushNotificationConfig());
        +        MessageSendConfiguration messageSendConfiguration = createMessageSendConfiguration(clientConfig.getTaskPushNotificationConfig());
         
                 MessageSendParams messageSendParams = MessageSendParams.builder()
                         .message(request)
        @@ -267,10 +267,11 @@ public void sendMessage(@NonNull Message request,
              * 

        * With push notifications: *

        {@code
        -     * PushNotificationConfig pushConfig = new PushNotificationConfig(
        -     *     "https://my-app.com/webhook",
        -     *     Map.of("Authorization", "Bearer token")
        -     * );
        +     * TaskPushNotificationConfig pushConfig = TaskPushNotificationConfig.builder()
        +     *     .id("config-1")
        +     *     .url("https://my-app.com/webhook")
        +     *     .authentication(new AuthenticationInfo("Bearer", "token"))
        +     *     .build();
              * client.sendMessage(userMessage, pushConfig, null, null);
              * }
        *

        @@ -289,11 +290,11 @@ public void sendMessage(@NonNull Message request, * @param context custom call context for request interceptors (optional) * @throws A2AClientException if the message cannot be sent or if the agent returns an error * @see #sendMessage(Message, List, Consumer, ClientCallContext) - * @see PushNotificationConfig + * @see TaskPushNotificationConfig */ @Override public void sendMessage(@NonNull Message request, - @Nullable PushNotificationConfig pushNotificationConfiguration, + @Nullable TaskPushNotificationConfig pushNotificationConfiguration, @Nullable Map metadata, @Nullable ClientCallContext context) throws A2AClientException { MessageSendConfiguration messageSendConfiguration = createMessageSendConfiguration(pushNotificationConfiguration); @@ -459,16 +460,12 @@ public Task cancelTask(CancelTaskParams request, @Nullable ClientCallContext con *

        * Example: *

        {@code
        -     * TaskPushNotificationConfig config = new TaskPushNotificationConfig(
        -     *     "task-123",
        -     *     new PushNotificationConfig(
        -     *         "https://my-app.com/webhooks/task-updates",
        -     *         Map.of(
        -     *             "Authorization", "Bearer my-webhook-secret",
        -     *             "X-App-ID", "my-app"
        -     *         )
        -     *     )
        -     * );
        +     * TaskPushNotificationConfig config = TaskPushNotificationConfig.builder()
        +     *     .id("config-1")
        +     *     .taskId("task-123")
        +     *     .url("https://my-app.com/webhooks/task-updates")
        +     *     .authentication(new AuthenticationInfo("Bearer", "my-webhook-secret"))
        +     *     .build();
              * client.createTaskPushNotificationConfiguration(config);
              * }
        * @@ -477,7 +474,6 @@ public Task cancelTask(CancelTaskParams request, @Nullable ClientCallContext con * @return the stored configuration (may include server-assigned IDs) * @throws A2AClientException if the configuration cannot be set * @see TaskPushNotificationConfig - * @see PushNotificationConfig */ @Override public TaskPushNotificationConfig createTaskPushNotificationConfiguration( @@ -495,7 +491,7 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration( * TaskPushNotificationConfig config = * client.getTaskPushNotificationConfiguration(params); * System.out.println("Webhook URL: " + - * config.pushNotificationConfig().url()); + * config.url()); * }
        * * @param request the parameters specifying which task's configuration to retrieve @@ -522,7 +518,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration( * client.listTaskPushNotificationConfigurations(params); * for (TaskPushNotificationConfig config : result.configurations()) { * System.out.println("Task " + config.taskId() + " -> " + - * config.pushNotificationConfig().url()); + * config.url()); * } * } * @@ -697,12 +693,12 @@ private ClientEvent getClientEvent(StreamingEventKind event, ClientTaskManager t } } - private MessageSendConfiguration createMessageSendConfiguration(@Nullable PushNotificationConfig pushNotificationConfig) { + private MessageSendConfiguration createMessageSendConfiguration(@Nullable TaskPushNotificationConfig taskPushNotificationConfig) { return MessageSendConfiguration.builder() .acceptedOutputModes(clientConfig.getAcceptedOutputModes()) .blocking(!clientConfig.isPolling()) .historyLength(clientConfig.getHistoryLength()) - .pushNotificationConfig(pushNotificationConfig) + .taskPushNotificationConfig(taskPushNotificationConfig) .build(); } 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 d9ffd7e6e..276a17194 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 @@ -5,7 +5,7 @@ import java.util.List; import java.util.Map; -import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.TaskPushNotificationConfig; import org.jspecify.annotations.Nullable; /** @@ -79,12 +79,13 @@ *

        * Push notifications: Configure default webhook for all task updates: *

        {@code
        - * PushNotificationConfig pushConfig = new PushNotificationConfig(
        - *     "https://my-app.com/webhooks/tasks",
        - *     Map.of("Authorization", "Bearer my-token")
        - * );
        + * TaskPushNotificationConfig pushConfig = TaskPushNotificationConfig.builder()
        + *     .id("config-1")
        + *     .url("https://my-app.com/webhooks/tasks")
        + *     .authentication(new AuthenticationInfo("bearer", "my-token"))
        + *     .build();
          * ClientConfig config = new ClientConfig.Builder()
        - *     .setPushNotificationConfig(pushConfig)
        + *     .setTaskPushNotificationConfig(pushConfig)
          *     .build();
          * // All sendMessage() calls will use this webhook config
          * }
        @@ -125,7 +126,7 @@ *
      • useClientPreference: {@code false} (server preference)
      • *
      • acceptedOutputModes: empty list (accept all)
      • *
      • historyLength: {@code null} (no history)
      • - *
      • pushNotificationConfig: {@code null} (no push notifications)
      • + *
      • taskPushNotificationConfig: {@code null} (no push notifications)
      • *
      • metadata: empty map
      • * *

        @@ -134,7 +135,7 @@ * * @see io.a2a.client.Client * @see io.a2a.client.ClientBuilder - * @see PushNotificationConfig + * @see TaskPushNotificationConfig */ public class ClientConfig { @@ -142,7 +143,7 @@ public class ClientConfig { private final Boolean polling; private final Boolean useClientPreference; private final List acceptedOutputModes; - private final @Nullable PushNotificationConfig pushNotificationConfig; + private final @Nullable TaskPushNotificationConfig taskPushNotificationConfig; private final @Nullable Integer historyLength; private final Map metadata; @@ -151,7 +152,7 @@ private ClientConfig(Builder builder) { this.polling = builder.polling == null ? false : builder.polling; this.useClientPreference = builder.useClientPreference == null ? false : builder.useClientPreference; this.acceptedOutputModes = builder.acceptedOutputModes; - this.pushNotificationConfig = builder.pushNotificationConfig; + this.taskPushNotificationConfig = builder.taskPushNotificationConfig; this.historyLength = builder.historyLength; this.metadata = builder.metadata; } @@ -219,10 +220,10 @@ public List getAcceptedOutputModes() { * calls unless overridden with a different configuration. * * @return the push notification config, or {@code null} if not configured - * @see io.a2a.client.Client#sendMessage(io.a2a.spec.Message, io.a2a.spec.PushNotificationConfig, java.util.Map, io.a2a.client.transport.spi.interceptors.ClientCallContext) + * @see io.a2a.client.Client#sendMessage(io.a2a.spec.Message, io.a2a.spec.TaskPushNotificationConfig, java.util.Map, io.a2a.client.transport.spi.interceptors.ClientCallContext) */ - public @Nullable PushNotificationConfig getPushNotificationConfig() { - return pushNotificationConfig; + public @Nullable TaskPushNotificationConfig getTaskPushNotificationConfig() { + return taskPushNotificationConfig; } /** @@ -278,7 +279,7 @@ public static class Builder { private @Nullable Boolean polling; private @Nullable Boolean useClientPreference; private List acceptedOutputModes = new ArrayList<>(); - private @Nullable PushNotificationConfig pushNotificationConfig; + private @Nullable TaskPushNotificationConfig taskPushNotificationConfig; private @Nullable Integer historyLength; private Map metadata = new HashMap<>(); @@ -347,12 +348,12 @@ public Builder setAcceptedOutputModes(List acceptedOutputModes) { * This webhook configuration will be used for all sendMessage calls * unless overridden. The agent will POST task update events to the specified URL. * - * @param pushNotificationConfig the push notification configuration + * @param taskPushNotificationConfig the push notification configuration * @return this builder for method chaining - * @see io.a2a.client.Client#sendMessage(io.a2a.spec.Message, io.a2a.spec.PushNotificationConfig, java.util.Map, io.a2a.client.transport.spi.interceptors.ClientCallContext) + * @see io.a2a.client.Client#sendMessage(io.a2a.spec.Message, io.a2a.spec.TaskPushNotificationConfig, java.util.Map, io.a2a.client.transport.spi.interceptors.ClientCallContext) */ - public Builder setPushNotificationConfig(PushNotificationConfig pushNotificationConfig) { - this.pushNotificationConfig = pushNotificationConfig; + public Builder setTaskPushNotificationConfig(TaskPushNotificationConfig taskPushNotificationConfig) { + this.taskPushNotificationConfig = taskPushNotificationConfig; return this; } @@ -396,7 +397,7 @@ public Builder setMetadata(Map metadata) { *

      • polling: {@code false}
      • *
      • useClientPreference: {@code false}
      • *
      • acceptedOutputModes: empty list
      • - *
      • pushNotificationConfig: {@code null}
      • + *
      • taskPushNotificationConfig: {@code null}
      • *
      • historyLength: {@code null}
      • *
      • metadata: empty map
      • * 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 cb0fef677..474b7b784 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 @@ -235,12 +235,7 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPu @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - String configId = request.config().id(); - io.a2a.grpc.CreateTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(request.taskId()) - .setConfig(ToProto.taskPushNotificationConfig(request).getPushNotificationConfig()) - .setTenant(resolveTenant(request.tenant())) - .build(); + io.a2a.grpc.TaskPushNotificationConfig grpcRequest = ToProto.taskPushNotificationConfig(request); PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); try { diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index bf341a118..23174820e 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -58,7 +58,6 @@ import io.a2a.spec.MessageSendParams; import io.a2a.spec.OpenIdConnectSecurityScheme; import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.SecurityRequirement; import io.a2a.spec.SecurityScheme; import io.a2a.spec.Task; @@ -311,10 +310,9 @@ public void testA2AClientGetTaskPushNotificationConfig() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); TaskPushNotificationConfig taskPushNotificationConfig = client.getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64", "c295ea44-7543-4f78-b524-7a38915ad6e4"), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); + assertNotNull(taskPushNotificationConfig); + assertEquals("https://example.com/callback", taskPushNotificationConfig.url()); + AuthenticationInfo authenticationInfo = taskPushNotificationConfig.authentication(); assertEquals("jwt", authenticationInfo.scheme()); } @@ -335,16 +333,16 @@ public void testA2AClientCreateTaskPushNotificationConfig() throws Exception { JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); TaskPushNotificationConfig taskPushNotificationConfig = client.createTaskPushNotificationConfiguration( - new TaskPushNotificationConfig("de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("c295ea44-7543-4f78-b524-7a38915ad6e4") - .url("https://example.com/callback") - .authentication(new AuthenticationInfo("jwt", null)) - .build(), ""), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); + TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId("de38c76d-d54c-436c-8b9f-4c2703648d64") + .url("https://example.com/callback") + .authentication(new AuthenticationInfo("jwt", null)) + .tenant("") + .build(), null); + assertNotNull(taskPushNotificationConfig); + assertEquals("https://example.com/callback", taskPushNotificationConfig.url()); + AuthenticationInfo authenticationInfo = taskPushNotificationConfig.authentication(); assertEquals("jwt", authenticationInfo.scheme()); } 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 f2a5977d4..71fac010e 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 @@ -321,13 +321,11 @@ public class JsonMessages { "jsonrpc": "2.0", "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "result": { + "id": "c295ea44-7543-4f78-b524-7a38915ad6e4", "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "pushNotificationConfig": { - "id": "c295ea44-7543-4f78-b524-7a38915ad6e4", - "url": "https://example.com/callback", - "authentication": { + "url": "https://example.com/callback", + "authentication": { "scheme": "jwt" - } } } } @@ -338,13 +336,11 @@ public class JsonMessages { "jsonrpc":"2.0", "method":"CreateTaskPushNotificationConfig", "params":{ + "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "config":{ - "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "url":"https://example.com/callback", - "authentication":{ - "scheme":"jwt" - } + "url":"https://example.com/callback", + "authentication":{ + "scheme":"jwt" } } }"""; @@ -354,13 +350,11 @@ public class JsonMessages { "jsonrpc": "2.0", "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", "result": { + "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "pushNotificationConfig": { - "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "url": "https://example.com/callback", - "authentication": { + "url": "https://example.com/callback", + "authentication": { "scheme": "jwt" - } } } } 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 695c2e5ab..1eb15291e 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 @@ -271,10 +271,8 @@ private String buildListTasksQueryString(ListTasksParams request) { @Override public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder - = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); - builder.setConfig(ProtoUtils.ToProto.taskPushNotificationConfig(request).getPushNotificationConfig()) - .setTaskId(request.taskId()); + io.a2a.grpc.TaskPushNotificationConfig.Builder builder + = ProtoUtils.ToProto.taskPushNotificationConfig(request).toBuilder(); 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); diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java index aa54d4b86..471ac5d90 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java @@ -307,34 +307,28 @@ public class JsonRestMessages { static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ { + "id": "10", "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "pushNotificationConfig": { - "id": "10", - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } }"""; static final String LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ { "configs":[ { + "id": "10", "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "pushNotificationConfig": { - "id": "10", - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } }, { + "id": "5", "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "pushNotificationConfig": { - "id": "5", - "url": "https://test.com/callback" - } + "url": "https://test.com/callback" } ] }"""; @@ -342,25 +336,21 @@ public class JsonRestMessages { static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ { + "id": "default-config-id", "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "config": { - "id": "default-config-id", - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } }"""; static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ { + "id": "10", "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "pushNotificationConfig": { - "id": "10", - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } }"""; diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index 70f6e24d4..bf8e482fe 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -52,7 +52,6 @@ import io.a2a.spec.MessageSendConfiguration; import io.a2a.spec.MessageSendParams; import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; @@ -302,19 +301,17 @@ public void testCreateTaskPushNotificationConfiguration() throws Exception { .withBody(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) ); RestTransport client = new RestTransport(CARD); - TaskPushNotificationConfig pushedConfig = new TaskPushNotificationConfig( - "de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("default-config-id") - .url("https://example.com/callback") - .authentication( - new AuthenticationInfo("jwt", null)) - .build(), "tenant"); + TaskPushNotificationConfig pushedConfig = TaskPushNotificationConfig.builder() + .id("default-config-id") + .taskId("de38c76d-d54c-436c-8b9f-4c2703648d64") + .url("https://example.com/callback") + .authentication(new AuthenticationInfo("jwt", null)) + .tenant("tenant") + .build(); TaskPushNotificationConfig taskPushNotificationConfig = client.createTaskPushNotificationConfiguration(pushedConfig, null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); + assertNotNull(taskPushNotificationConfig); + assertEquals("https://example.com/callback", taskPushNotificationConfig.url()); + AuthenticationInfo authenticationInfo = taskPushNotificationConfig.authentication(); assertEquals("jwt", authenticationInfo.scheme()); } @@ -337,10 +334,9 @@ public void testGetTaskPushNotificationConfiguration() throws Exception { RestTransport client = new RestTransport(CARD); TaskPushNotificationConfig taskPushNotificationConfig = client.getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64", "10"), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); + assertNotNull(taskPushNotificationConfig); + assertEquals("https://example.com/callback", taskPushNotificationConfig.url()); + AuthenticationInfo authenticationInfo = taskPushNotificationConfig.authentication(); assertEquals("jwt", authenticationInfo.scheme()); } @@ -364,18 +360,18 @@ public void testListTaskPushNotificationConfigurations() throws Exception { ListTaskPushNotificationConfigResult result = client.listTaskPushNotificationConfigurations( new ListTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null); assertEquals(2, result.configs().size()); - PushNotificationConfig pushNotificationConfig = result.configs().get(0).config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - assertEquals("10", pushNotificationConfig.id()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); + TaskPushNotificationConfig config0 = result.configs().get(0); + assertNotNull(config0); + assertEquals("https://example.com/callback", config0.url()); + assertEquals("10", config0.id()); + AuthenticationInfo authenticationInfo = config0.authentication(); assertEquals("jwt", authenticationInfo.scheme()); assertEquals("", authenticationInfo.credentials()); - pushNotificationConfig = result.configs().get(1).config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://test.com/callback", pushNotificationConfig.url()); - assertEquals("5", pushNotificationConfig.id()); - authenticationInfo = pushNotificationConfig.authentication(); + TaskPushNotificationConfig config1 = result.configs().get(1); + assertNotNull(config1); + assertEquals("https://test.com/callback", config1.url()); + assertEquals("5", config1.id()); + authenticationInfo = config1.authentication(); assertNull(authenticationInfo); } diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java index f162dadb9..9051e0c2d 100644 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java +++ b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java @@ -248,8 +248,8 @@ public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPu if (request.taskId() != null) { spanBuilder.setAttribute(GENAI_TASK_ID, request.taskId()); } - if (request.config() != null && request.config().id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, request.config().id()); + if (request.id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, request.id()); } if (extractRequest()) { spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java index 7cc6c2297..ffa7a1322 100644 --- a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java +++ b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java @@ -299,8 +299,8 @@ public TaskPushNotificationConfig onCreateTaskPushNotificationConfig(TaskPushNot if (params.taskId() != null) { spanBuilder.setAttribute(GENAI_TASK_ID, params.taskId()); } - if (params.config() != null && params.config().id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, params.config().id()); + if (params.id() != null) { + spanBuilder.setAttribute(GENAI_CONFIG_ID, params.id()); } if (extractRequest()) { spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java index b529c86cc..748bb3927 100644 --- a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java +++ b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java @@ -297,9 +297,10 @@ void onMessageSendStream_withError_setsErrorStatus() throws A2AError { class SetTaskPushNotificationConfigTests { @Test void onSetTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { - PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); - TaskPushNotificationConfig params = new TaskPushNotificationConfig("task-123", config, null); - TaskPushNotificationConfig result = new TaskPushNotificationConfig("task-123", config, null); + TaskPushNotificationConfig params = TaskPushNotificationConfig.builder() + .id("config-1").taskId("task-123").url("http://example.com").build(); + TaskPushNotificationConfig result = TaskPushNotificationConfig.builder() + .id("config-1").taskId("task-123").url("http://example.com").build(); when(delegate.onCreateTaskPushNotificationConfig(params, context)).thenReturn(result); TaskPushNotificationConfig actualResult = decorator.onCreateTaskPushNotificationConfig(params, context); @@ -314,8 +315,8 @@ void onSetTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A @Test void onSetTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { - PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); - TaskPushNotificationConfig params = new TaskPushNotificationConfig("task-123", config, null); + TaskPushNotificationConfig params = TaskPushNotificationConfig.builder() + .id("config-1").taskId("task-123").url("http://example.com").build(); A2AError error = new InvalidRequestError("Invalid config"); when(delegate.onCreateTaskPushNotificationConfig(params, context)).thenThrow(error); @@ -332,8 +333,8 @@ class GetTaskPushNotificationConfigTests { @Test void onGetTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { GetTaskPushNotificationConfigParams params = new GetTaskPushNotificationConfigParams("task-123", "config-1"); - PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); - TaskPushNotificationConfig result = new TaskPushNotificationConfig("task-123", config, null); + TaskPushNotificationConfig result = TaskPushNotificationConfig.builder() + .id("config-1").taskId("task-123").url("http://example.com").build(); when(delegate.onGetTaskPushNotificationConfig(params, context)).thenReturn(result); TaskPushNotificationConfig actualResult = decorator.onGetTaskPushNotificationConfig(params, context); 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 5049bc9a4..a34d0b55f 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 @@ -15,10 +15,9 @@ import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.util.Assert; import io.a2a.util.PageToken; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,15 +35,14 @@ public class JpaDatabasePushNotificationConfigStore implements PushNotificationC @Transactional @Override - public PushNotificationConfig setInfo(String taskId, PushNotificationConfig notificationConfig) { + public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificationConfig) { + String taskId = Assert.checkNotNullParam("taskId", notificationConfig.taskId()); // Ensure config has an ID - default to taskId if not provided (mirroring InMemoryPushNotificationConfigStore behavior) - PushNotificationConfig.Builder builder = PushNotificationConfig.builder(notificationConfig); - if (notificationConfig.id() == null || notificationConfig.id().isEmpty()) { + if (notificationConfig.id().isEmpty()) { // This means the taskId and configId are same. This will not allow having multiple configs for a single Task. // The configId is a required field in the spec and should not be empty - builder.id(taskId); + notificationConfig = TaskPushNotificationConfig.builder(notificationConfig).id(taskId).build(); } - notificationConfig = builder.build(); LOGGER.debug("Saving PushNotificationConfig for Task '{}' with ID: {}", taskId, notificationConfig.id()); try { @@ -118,10 +116,15 @@ public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConf nextPageToken = new PageToken(timestamp, lastConfig.getId().getConfigId()).toString(); } - List configs = jpaConfigsPage.stream() + List taskPushNotificationConfigs = jpaConfigsPage.stream() .map(jpaConfig -> { try { - return jpaConfig.getConfig(); + TaskPushNotificationConfig config = jpaConfig.getConfig(); + // Set taskId and tenant from the params + return TaskPushNotificationConfig.builder(config) + .taskId(params.id()) + .tenant(params.tenant()) + .build(); } catch (JsonProcessingException e) { LOGGER.error("Failed to deserialize PushNotificationConfig for Task '{}' with ID: {}", taskId, jpaConfig.getId().getConfigId(), e); @@ -131,11 +134,7 @@ public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConf }) .toList(); - LOGGER.debug("Successfully retrieved {} PushNotificationConfigs for Task '{}'", configs.size(), taskId); - - List taskPushNotificationConfigs = configs.stream() - .map(config -> new TaskPushNotificationConfig(params.id(), config, params.tenant())) - .collect(Collectors.toList()); + LOGGER.debug("Successfully retrieved {} PushNotificationConfigs for Task '{}'", taskPushNotificationConfigs.size(), taskId); return new ListTaskPushNotificationConfigResult(taskPushNotificationConfigs, nextPageToken); } catch (Exception e) { 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 d38b136ca..6bc74a2f5 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 @@ -9,7 +9,7 @@ import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.TaskPushNotificationConfig; import java.time.Instant; @Entity @@ -25,7 +25,7 @@ public class JpaPushNotificationConfig { private Instant createdAt; @Transient - private PushNotificationConfig config; + private TaskPushNotificationConfig config; // Default constructor required by JPA public JpaPushNotificationConfig() { @@ -55,14 +55,14 @@ public void setConfigJson(String configJson) { this.configJson = configJson; } - public PushNotificationConfig getConfig() throws JsonProcessingException { + public TaskPushNotificationConfig getConfig() throws JsonProcessingException { if (config == null) { - this.config = JsonUtil.fromJson(configJson, PushNotificationConfig.class); + this.config = JsonUtil.fromJson(configJson, TaskPushNotificationConfig.class); } return config; } - public void setConfig(PushNotificationConfig config) throws JsonProcessingException { + public void setConfig(TaskPushNotificationConfig config) throws JsonProcessingException { if (config.id() == null || !config.id().equals(id.getConfigId())) { throw new IllegalArgumentException("Mismatched config id. " + "Expected '" + id.getConfigId() + "'. Got: '" + config.id() + "'"); @@ -79,7 +79,7 @@ public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - static JpaPushNotificationConfig createFromConfig(String taskId, PushNotificationConfig config) throws JsonProcessingException { + static JpaPushNotificationConfig createFromConfig(String taskId, TaskPushNotificationConfig config) throws JsonProcessingException { String json = JsonUtil.toJson(config); JpaPushNotificationConfig jpaPushNotificationConfig = new JpaPushNotificationConfig(new TaskConfigId(taskId, config.id()), json); 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 75a0df5de..3551f700a 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 @@ -28,7 +28,6 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.Message; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TextPart; @@ -117,13 +116,13 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep assertTrue(createLatch.await(10, TimeUnit.SECONDS), "Timeout waiting for task creation"); // Step 2: Set the push notification configuration - PushNotificationConfig pushConfig = PushNotificationConfig.builder() + TaskPushNotificationConfig taskPushConfig = TaskPushNotificationConfig.builder() + .id("test-config-1") + .taskId(taskId) .url("http://localhost:9999/mock-endpoint") .token("test-token-123") - .id("test-config-1") + .tenant("") .build(); - - TaskPushNotificationConfig taskPushConfig = new TaskPushNotificationConfig(taskId, pushConfig, ""); TaskPushNotificationConfig setResult = client.createTaskPushNotificationConfiguration(taskPushConfig); assertNotNull(setResult); @@ -133,9 +132,9 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep assertNotNull(storedConfig); assertEquals(taskId, storedConfig.taskId()); - assertEquals("test-config-1", storedConfig.config().id()); - assertEquals("http://localhost:9999/mock-endpoint", storedConfig.config().url()); - assertEquals("test-token-123", storedConfig.config().token()); + assertEquals("test-config-1", storedConfig.id()); + assertEquals("http://localhost:9999/mock-endpoint", storedConfig.url()); + assertEquals("test-token-123", storedConfig.token()); // Step 4: Update the task to trigger the notification Message updateMessage = Message.builder() @@ -193,8 +192,8 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep }, "Getting a deleted config should throw an A2AClientException"); } - private PushNotificationConfig createSamplePushConfig(String url, String configId, String token) { - return PushNotificationConfig.builder() + private TaskPushNotificationConfig createSamplePushConfig(String url, String configId, String token) { + return TaskPushNotificationConfig.builder() .url(url) .id(configId) .token(token) @@ -239,10 +238,10 @@ public void testPaginationWithPageToken() { // Verify NO overlap between pages - collect all IDs from both pages List firstPageIds = firstPage.configs().stream() - .map(c -> c.config().id()) + .map(c -> c.id()) .toList(); List secondPageIds = secondPage.configs().stream() - .map(c -> c.config().id()) + .map(c -> c.id()) .toList(); // Check that no ID from first page appears in second page @@ -471,10 +470,10 @@ public void testMultipleTasksDoNotInterfere() { assertEquals(2, result2.configs().size(), "Task2 should have 2 configs"); List task1Ids = result1.configs().stream() - .map(c -> taskId1 + c.config().id()) + .map(c -> taskId1 + c.id()) .toList(); List task2Ids = result2.configs().stream() - .map(c -> taskId2 + c.config().id()) + .map(c -> taskId2 + c.id()) .toList(); for (String id : task1Ids) { @@ -505,9 +504,9 @@ public void testGetInfoReturnsTenantFromParams() { String taskId = "task_tenant_" + System.currentTimeMillis(); String tenant = "test-tenant-123"; - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig( "http://url.com/callback", "cfg1", "token"); - pushNotificationConfigStore.setInfo(taskId, config); + pushNotificationConfigStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build()); ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 0, "", tenant); @@ -535,7 +534,7 @@ public void testPaginationOrderingConsistency() { ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); result.configs().forEach(c -> - allConfigIds.add(c.config().id())); + allConfigIds.add(c.id())); pageToken = result.nextPageToken(); pageCount++; @@ -555,9 +554,9 @@ public void testPaginationOrderingConsistency() { private void createSamples(String taskId, int size) { // Create configs with slight delays to ensure unique timestamps for deterministic ordering for (int i = 0; i < size; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig( "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - pushNotificationConfigStore.setInfo(taskId, config); + pushNotificationConfigStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build()); // Sleep briefly to ensure each config gets a unique timestamp // This prevents non-deterministic ordering in pagination tests 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 6023a74b9..9e10e1910 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 @@ -22,7 +22,6 @@ import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskState; @@ -71,8 +70,8 @@ private Task createSampleTask(String taskId, TaskState state) { .build(); } - private PushNotificationConfig createSamplePushConfig(String url, String configId, String token) { - return PushNotificationConfig.builder() + private TaskPushNotificationConfig createSamplePushConfig(String url, String configId, String token) { + return TaskPushNotificationConfig.builder() .url(url) .id(configId) .token(token) @@ -83,9 +82,9 @@ private PushNotificationConfig createSamplePushConfig(String url, String configI @Transactional public void testSetInfoAddsNewConfig() { String taskId = "task_new"; - PushNotificationConfig config = createSamplePushConfig("http://new.url/callback", "cfg1", null); + TaskPushNotificationConfig config = createSamplePushConfig("http://new.url/callback", "cfg1", null); - PushNotificationConfig result = configStore.setInfo(taskId, config); + TaskPushNotificationConfig result = configStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build()); assertNotNull(result); assertEquals(config.url(), result.url()); @@ -94,35 +93,33 @@ public void testSetInfoAddsNewConfig() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - assertEquals(config.id(), configResult.configs().get(0).config().id()); + assertEquals(config.url(), configResult.configs().get(0).url()); + assertEquals(config.id(), configResult.configs().get(0).id()); } @Test @Transactional public void testSetInfoAppendsToExistingConfig() { String taskId = "task_update"; - PushNotificationConfig initialConfig = createSamplePushConfig( + TaskPushNotificationConfig initialConfig = createSamplePushConfig( "http://initial.url/callback", "cfg_initial", null); - configStore.setInfo(taskId, initialConfig); + configStore.setInfo(TaskPushNotificationConfig.builder(initialConfig).taskId(taskId).build()); - PushNotificationConfig updatedConfig = createSamplePushConfig( + TaskPushNotificationConfig updatedConfig = createSamplePushConfig( "http://updated.url/callback", "cfg_updated", null); - configStore.setInfo(taskId, updatedConfig); + configStore.setInfo(TaskPushNotificationConfig.builder(updatedConfig).taskId(taskId).build()); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(2, configResult.configs().size()); // Find the configs by ID since order might vary - List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::config) - .toList(); - PushNotificationConfig foundInitial = configs.stream() + List configs = configResult.configs(); + TaskPushNotificationConfig foundInitial = configs.stream() .filter(c -> "cfg_initial".equals(c.id())) .findFirst() .orElse(null); - PushNotificationConfig foundUpdated = configs.stream() + TaskPushNotificationConfig foundUpdated = configs.stream() .filter(c -> "cfg_updated".equals(c.id())) .findFirst() .orElse(null); @@ -137,41 +134,45 @@ public void testSetInfoAppendsToExistingConfig() { @Transactional public void testSetInfoWithoutConfigId() { String taskId = "task1"; - PushNotificationConfig initialConfig = PushNotificationConfig.builder() + TaskPushNotificationConfig initialConfig = TaskPushNotificationConfig.builder() + .id("") .url("http://initial.url/callback") - .build(); // No ID set + .taskId(taskId) + .build(); - PushNotificationConfig result = configStore.setInfo(taskId, initialConfig); + TaskPushNotificationConfig result = configStore.setInfo(initialConfig); assertEquals(taskId, result.id(), "Config ID should default to taskId when not provided"); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size()); - assertEquals(taskId, configResult.configs().get(0).config().id()); + assertEquals(taskId, configResult.configs().get(0).id()); - PushNotificationConfig updatedConfig = PushNotificationConfig.builder() + TaskPushNotificationConfig updatedConfig = TaskPushNotificationConfig.builder() + .id("") .url("http://initial.url/callback_new") - .build(); // No ID set + .taskId(taskId) + .build(); - PushNotificationConfig updatedResult = configStore.setInfo(taskId, updatedConfig); + TaskPushNotificationConfig updatedResult = configStore.setInfo(updatedConfig); assertEquals(taskId, updatedResult.id()); configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size(), "Should replace existing config with same ID rather than adding new one"); - assertEquals(updatedConfig.url(), configResult.configs().get(0).config().url()); + assertEquals(updatedConfig.url(), configResult.configs().get(0).url()); } @Test @Transactional public void testGetInfoExistingConfig() { String taskId = "task_get_exist"; - PushNotificationConfig config = createSamplePushConfig("http://get.this/callback", "cfg1", null); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig("http://get.this/callback", "cfg1", null); + configStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build()); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - assertEquals(config.id(), configResult.configs().get(0).config().id()); + assertEquals(config.url(), configResult.configs().get(0).url()); + assertEquals(config.id(), configResult.configs().get(0).id()); } @Test @@ -187,8 +188,8 @@ public void testGetInfoNonExistentConfig() { @Transactional public void testDeleteInfoExistingConfig() { String taskId = "task_delete_exist"; - PushNotificationConfig config = createSamplePushConfig("http://delete.this/callback", "cfg1", null); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig("http://delete.this/callback", "cfg1", null); + configStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build()); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); @@ -217,10 +218,12 @@ public void testDeleteInfoNonExistentConfig() { @Transactional public void testDeleteInfoWithNullConfigId() { String taskId = "task_delete_null_config"; - PushNotificationConfig config = PushNotificationConfig.builder() + TaskPushNotificationConfig config = TaskPushNotificationConfig.builder() + .id("") .url("http://delete.this/callback") - .build(); // No ID set, will use taskId - configStore.setInfo(taskId, config); + .taskId(taskId) + .build(); + configStore.setInfo(config); // Delete with null configId should use taskId configStore.deleteInfo(taskId, null); @@ -235,8 +238,8 @@ public void testDeleteInfoWithNullConfigId() { public void testSendNotificationSuccess() throws Exception { String taskId = "task_send_success"; Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); + configStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build()); // Mock successful HTTP response when(mockHttpClient.createPost()).thenReturn(mockPostBuilder); @@ -268,8 +271,8 @@ public void testSendNotificationSuccess() throws Exception { public void testSendNotificationWithToken() throws Exception { String taskId = "task_send_with_token"; Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); + configStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build()); // Mock successful HTTP response when(mockHttpClient.createPost()).thenReturn(mockPostBuilder); @@ -314,33 +317,30 @@ public void testSendNotificationNoConfig() throws Exception { @Transactional public void testMultipleConfigsForSameTask() { String taskId = "task_multiple"; - PushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); + TaskPushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); + TaskPushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); + configStore.setInfo(TaskPushNotificationConfig.builder(config1).taskId(taskId).build()); + configStore.setInfo(TaskPushNotificationConfig.builder(config2).taskId(taskId).build()); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(2, configResult.configs().size()); // Verify both configs are present - List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::config) - .toList(); - assertTrue(configs.stream().anyMatch(c -> "cfg1".equals(c.id()))); - assertTrue(configs.stream().anyMatch(c -> "cfg2".equals(c.id()))); + assertTrue(configResult.configs().stream().anyMatch(c -> "cfg1".equals(c.id()))); + assertTrue(configResult.configs().stream().anyMatch(c -> "cfg2".equals(c.id()))); } @Test @Transactional public void testDeleteSpecificConfigFromMultiple() { String taskId = "task_delete_specific"; - PushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); + TaskPushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); + TaskPushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); + configStore.setInfo(TaskPushNotificationConfig.builder(config1).taskId(taskId).build()); + configStore.setInfo(TaskPushNotificationConfig.builder(config2).taskId(taskId).build()); // Delete only config1 configStore.deleteInfo(taskId, "cfg1"); @@ -348,23 +348,23 @@ public void testDeleteSpecificConfigFromMultiple() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals("cfg2", configResult.configs().get(0).config().id()); + assertEquals("cfg2", configResult.configs().get(0).id()); } @Test @Transactional public void testConfigStoreIntegration() { String taskId = "integration_test"; - PushNotificationConfig config = createSamplePushConfig("http://example.com", "test_id", "test_token"); + TaskPushNotificationConfig config = createSamplePushConfig("http://example.com", "test_id", "test_token"); // Test that we can store and retrieve configurations - PushNotificationConfig storedConfig = configStore.setInfo(taskId, config); + TaskPushNotificationConfig storedConfig = configStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build()); assertEquals(config.url(), storedConfig.url()); assertEquals(config.token(), storedConfig.token()); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); + assertEquals(config.url(), configResult.configs().get(0).url()); // Test deletion configStore.deleteInfo(taskId, storedConfig.id()); diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index 734f3043a..76a23273a 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -428,7 +428,7 @@ private A2AError createErrorInstance(@Nullable Integer code, @Nullable String me case INTERNAL_ERROR_CODE -> new io.a2a.spec.InternalError(code, message, data); case TASK_NOT_FOUND_ERROR_CODE -> - new TaskNotFoundError(code, message, data); + new TaskNotFoundError(message, data); case TASK_NOT_CANCELABLE_ERROR_CODE -> new TaskNotCancelableError(code, message, data); case PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE -> diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java index b9b8716be..13d7a8b25 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java @@ -4,7 +4,6 @@ import java.util.UUID; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; /** @@ -18,7 +17,6 @@ * * @see CreateTaskPushNotificationConfigResponse for the response * @see TaskPushNotificationConfig for the parameter structure - * @see PushNotificationConfig for notification endpoint details * @see A2A Protocol Specification */ public final class CreateTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java index 999361635..a3abf3c4c 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java @@ -77,7 +77,7 @@ public static Builder builder() { * Example usage: *
        {@code
              * SendMessageRequest request = SendMessageRequest.builder()
        -     *     .params(new MessageSendParams(message, taskId, pushNotificationConfig))
        +     *     .params(new MessageSendParams(message, taskId, taskPushNotificationConfig))
              *     .build();
              * }
        */ 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 fc57c705d..8b67aa446 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 @@ -20,7 +20,7 @@ import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.apps.common.TestUtilsBean; -import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatusUpdateEvent; @@ -130,7 +130,7 @@ public Response deleteTaskPushNotificationConfig(@PathParam("taskId") String tas @Path("/task/{taskId}") @Consumes(MediaType.APPLICATION_JSON) public Response savePushNotificationConfigInStore(@PathParam("taskId") String taskId, String body) throws Exception { - PushNotificationConfig notificationConfig = JsonUtil.fromJson(body, PushNotificationConfig.class); + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); if (notificationConfig == null) { return Response.status(404).build(); } 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 1aa8335e0..2e6d3562a 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 @@ -45,7 +45,6 @@ import io.a2a.spec.AgentInterface; import io.a2a.spec.AuthenticationInfo; import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskState; @@ -331,26 +330,23 @@ public void testCreateTaskPushNotificationConfig_MethodNameSetInContext() { "method": "CreateTaskPushNotificationConfig", "params": { "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "config": { - "id": "config-123", - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } + "id": "config-123", + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } } }"""; when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); // Create a real response with a TaskPushNotificationConfig - TaskPushNotificationConfig responseConfig = new TaskPushNotificationConfig( - "de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("config-123") - .url("https://example.com/callback") - .authentication(new AuthenticationInfo("jwt", null)) - .build(), - "tenant"); + TaskPushNotificationConfig responseConfig = TaskPushNotificationConfig.builder() + .id("config-123") + .taskId("de38c76d-d54c-436c-8b9f-4c2703648d64") + .url("https://example.com/callback") + .authentication(new AuthenticationInfo("jwt", null)) + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigResponse realResponse = new CreateTaskPushNotificationConfigResponse("1", responseConfig); when(mockJsonRpcHandler.setPushNotificationConfig(any(CreateTaskPushNotificationConfigRequest.class), @@ -385,14 +381,11 @@ public void testGetTaskPushNotificationConfig_MethodNameSetInContext() { when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); // Create a real response with a TaskPushNotificationConfig - TaskPushNotificationConfig responseConfig = new TaskPushNotificationConfig( - "de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("config-456") - .url("https://example.com/callback") - .build(), - null - ); + TaskPushNotificationConfig responseConfig = TaskPushNotificationConfig.builder() + .id("config-456") + .taskId("de38c76d-d54c-436c-8b9f-4c2703648d64") + .url("https://example.com/callback") + .build(); GetTaskPushNotificationConfigResponse realResponse = new GetTaskPushNotificationConfigResponse("1", responseConfig); when(mockJsonRpcHandler.getPushNotificationConfig(any(GetTaskPushNotificationConfigRequest.class), any(ServerCallContext.class))).thenReturn(realResponse); @@ -427,14 +420,11 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() { when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); // Create a real response with a list of TaskPushNotificationConfig - TaskPushNotificationConfig config = new TaskPushNotificationConfig( - "de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("config-123") - .url("https://example.com/callback") - .build(), - null - ); + TaskPushNotificationConfig config = TaskPushNotificationConfig.builder() + .id("config-123") + .taskId("de38c76d-d54c-436c-8b9f-4c2703648d64") + .url("https://example.com/callback") + .build(); ListTaskPushNotificationConfigsResponse realResponse = new ListTaskPushNotificationConfigsResponse("1", new ListTaskPushNotificationConfigResult(singletonList(config))); when(mockJsonRpcHandler.listPushNotificationConfig(any(ListTaskPushNotificationConfigsRequest.class), any(ServerCallContext.class))).thenReturn(realResponse); 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 937c8a2b1..b421c48d5 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 @@ -12,7 +12,7 @@ import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.apps.common.TestUtilsBean; -import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatusUpdateEvent; @@ -169,7 +169,7 @@ public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { try { - PushNotificationConfig notificationConfig = JsonUtil.fromJson(body, PushNotificationConfig.class); + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); if (notificationConfig == null) { rc.response() .setStatusCode(404) 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 0ce5750b3..4099b7f73 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 @@ -12,7 +12,7 @@ import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.apps.common.TestUtilsBean; -import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatusUpdateEvent; @@ -169,7 +169,7 @@ public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { try { - PushNotificationConfig notificationConfig = JsonUtil.fromJson(body, PushNotificationConfig.class); + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); if (notificationConfig == null) { rc.response() .setStatusCode(404) 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 34969f89c..1145a3092 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 @@ -57,7 +57,6 @@ import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; @@ -493,7 +492,8 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte if (mss.task() == null && kind instanceof Task createdTask && shouldAddPushInfo(params)) { LOGGER.debug("Storing push notification config for new task {} (original taskId from params: {})", createdTask.id(), params.message().taskId()); - pushConfigStore.setInfo(createdTask.id(), params.configuration().pushNotificationConfig()); + pushConfigStore.setInfo(TaskPushNotificationConfig.builder(params.configuration().taskPushNotificationConfig()) + .taskId(createdTask.id()).build()); } // Check if task requires immediate return (AUTH_REQUIRED) @@ -645,7 +645,8 @@ public Flow.Publisher onMessageSendStream( Objects.requireNonNull(taskId.get(), "taskId was null"); LOGGER.debug("Storing push notification config for new streaming task {} EARLY (original taskId from params: {})", taskId.get(), params.message().taskId()); - pushConfigStore.setInfo(taskId.get(), params.configuration().pushNotificationConfig()); + pushConfigStore.setInfo(TaskPushNotificationConfig.builder(params.configuration().taskPushNotificationConfig()) + .taskId(taskId.get()).build()); } ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); @@ -770,13 +771,15 @@ public TaskPushNotificationConfig onCreateTaskPushNotificationConfig( if (pushConfigStore == null) { throw new UnsupportedOperationError(); } + if (params.taskId() == null) { + throw new InvalidParamsError("taskId is required"); + } Task task = taskStore.get(params.taskId()); if (task == null) { throw new TaskNotFoundError(); } - PushNotificationConfig pushNotificationConfig = pushConfigStore.setInfo(params.taskId(), params.config()); - return new TaskPushNotificationConfig(params.taskId(), pushNotificationConfig, params.tenant()); + return pushConfigStore.setInfo(params); } @Override @@ -796,17 +799,17 @@ public TaskPushNotificationConfig onGetTaskPushNotificationConfig( } String configId = params.id(); - return new TaskPushNotificationConfig(params.taskId(), getPushNotificationConfig(listTaskPushNotificationConfigResult, configId), params.tenant()); + return getTaskPushNotificationConfig(listTaskPushNotificationConfigResult, configId); } - private PushNotificationConfig getPushNotificationConfig(ListTaskPushNotificationConfigResult notificationConfigList, + private TaskPushNotificationConfig getTaskPushNotificationConfig(ListTaskPushNotificationConfigResult notificationConfigList, String configId) { for (TaskPushNotificationConfig notificationConfig : notificationConfigList.configs()) { - if (configId.equals(notificationConfig.config().id())) { - return notificationConfig.config(); + if (configId.equals(notificationConfig.id())) { + return notificationConfig; } } - return notificationConfigList.configs().get(0).config(); + throw new TaskNotFoundError("Push notification config with id '" + configId + "' not found.", null); } @Override @@ -875,7 +878,7 @@ public void onDeleteTaskPushNotificationConfig( } private boolean shouldAddPushInfo(MessageSendParams params) { - return pushConfigStore != null && params.configuration() != null && params.configuration().pushNotificationConfig() != null; + return pushConfigStore != null && params.configuration() != null && params.configuration().taskPushNotificationConfig() != null; } /** @@ -1025,9 +1028,10 @@ private MessageSendSetup initMessageSend(MessageSendParams params, ServerCallCon LOGGER.debug("Found task updating with message {}", params.message()); task = taskManager.updateWithMessage(params.message(), task); - if (pushConfigStore != null && params.configuration() != null && params.configuration().pushNotificationConfig() != null) { + if (pushConfigStore != null && params.configuration() != null && params.configuration().taskPushNotificationConfig() != null) { LOGGER.debug("Adding push info"); - pushConfigStore.setInfo(task.id(), params.configuration().pushNotificationConfig()); + pushConfigStore.setInfo(TaskPushNotificationConfig.builder(params.configuration().taskPushNotificationConfig()) + .taskId(task.id()).build()); } } 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 0d6bdcf3b..ac64659ec 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 @@ -22,7 +22,6 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.Message; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; @@ -87,7 +86,7 @@ public void sendNotification(StreamingEventKind event) { List> dispatchResults = configs .stream() - .map(pushConfig -> dispatch(event, pushConfig.config())) + .map(pushConfig -> dispatch(event, pushConfig)) .toList(); CompletableFuture allFutures = CompletableFuture.allOf(dispatchResults.toArray(new CompletableFuture[0])); CompletableFuture dispatchResult = allFutures.thenApply(v -> dispatchResults.stream() @@ -124,11 +123,11 @@ public void sendNotification(StreamingEventKind event) { throw new IllegalStateException("Unknown StreamingEventKind: " + event); } - private CompletableFuture dispatch(StreamingEventKind event, PushNotificationConfig pushInfo) { + private CompletableFuture dispatch(StreamingEventKind event, TaskPushNotificationConfig pushInfo) { return CompletableFuture.supplyAsync(() -> dispatchNotification(event, pushInfo)); } - private boolean dispatchNotification(StreamingEventKind event, PushNotificationConfig pushInfo) { + private boolean dispatchNotification(StreamingEventKind event, TaskPushNotificationConfig pushInfo) { String url = pushInfo.url(); String token = pushInfo.token(); 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 e67ae01eb..8bdc82715 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 @@ -10,9 +10,9 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import io.a2a.util.Assert; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; /** @@ -23,24 +23,25 @@ @ApplicationScoped public class InMemoryPushNotificationConfigStore implements PushNotificationConfigStore { - private final Map> pushNotificationInfos = Collections.synchronizedMap(new HashMap<>()); + private final Map> pushNotificationInfos = Collections.synchronizedMap(new HashMap<>()); @Inject public InMemoryPushNotificationConfigStore() { } @Override - public PushNotificationConfig setInfo(String taskId, PushNotificationConfig notificationConfig) { - List notificationConfigList = pushNotificationInfos.getOrDefault(taskId, new ArrayList<>()); - PushNotificationConfig.Builder builder = PushNotificationConfig.builder(notificationConfig); - if (notificationConfig.id() == null || notificationConfig.id().isEmpty()) { + public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificationConfig) { + String taskId = Assert.checkNotNullParam("taskId", notificationConfig.taskId()); + List notificationConfigList = pushNotificationInfos.getOrDefault(taskId, new ArrayList<>()); + TaskPushNotificationConfig.Builder builder = TaskPushNotificationConfig.builder(notificationConfig); + if (notificationConfig.id().isEmpty()) { builder.id(taskId); } notificationConfig = builder.build(); - Iterator notificationConfigIterator = notificationConfigList.iterator(); + Iterator notificationConfigIterator = notificationConfigList.iterator(); while (notificationConfigIterator.hasNext()) { - PushNotificationConfig config = notificationConfigIterator.next(); + TaskPushNotificationConfig config = notificationConfigIterator.next(); if (config.id() != null && config.id().equals(notificationConfig.id())) { notificationConfigIterator.remove(); break; @@ -53,12 +54,12 @@ public PushNotificationConfig setInfo(String taskId, PushNotificationConfig noti @Override public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConfigParams params) { - List configs = pushNotificationInfos.get(params.id()); + List configs = pushNotificationInfos.get(params.id()); if (configs == null) { return new ListTaskPushNotificationConfigResult(Collections.emptyList()); } if (params.pageSize() <= 0) { - return new ListTaskPushNotificationConfigResult(convertPushNotificationConfig(configs, params), null); + return new ListTaskPushNotificationConfigResult(new ArrayList<>(configs), null); } if (params.pageToken() != null && !params.pageToken().isBlank()) { //find first index @@ -68,15 +69,15 @@ public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConf } } if (configs.size() <= params.pageSize()) { - return new ListTaskPushNotificationConfigResult(convertPushNotificationConfig(configs, params), null); + return new ListTaskPushNotificationConfigResult(new ArrayList<>(configs), null); } String newToken = configs.get(params.pageSize()).id(); - return new ListTaskPushNotificationConfigResult(convertPushNotificationConfig(configs.subList(0, params.pageSize()), params), newToken); + return new ListTaskPushNotificationConfigResult(new ArrayList<>(configs.subList(0, params.pageSize())), newToken); } - private int findFirstIndex(List configs, String id) { + private int findFirstIndex(List configs, String id) { //find first index - Iterator iter = configs.iterator(); + Iterator iter = configs.iterator(); int index = 0; while (iter.hasNext()) { if (id.equals(iter.next().id())) { @@ -87,28 +88,19 @@ private int findFirstIndex(List configs, String id) { return index; } - private List convertPushNotificationConfig(List pushNotificationConfigList, ListTaskPushNotificationConfigParams params) { - List taskPushNotificationConfigList = new ArrayList<>(pushNotificationConfigList.size()); - for (PushNotificationConfig pushNotificationConfig : pushNotificationConfigList) { - TaskPushNotificationConfig taskPushNotificationConfig = new TaskPushNotificationConfig(params.id(), pushNotificationConfig, params.tenant()); - taskPushNotificationConfigList.add(taskPushNotificationConfig); - } - return taskPushNotificationConfigList; - } - @Override public void deleteInfo(String taskId, String configId) { if (configId == null) { configId = taskId; } - List notificationConfigList = pushNotificationInfos.get(taskId); + List notificationConfigList = pushNotificationInfos.get(taskId); if (notificationConfigList == null || notificationConfigList.isEmpty()) { return; } - Iterator notificationConfigIterator = notificationConfigList.iterator(); + Iterator notificationConfigIterator = notificationConfigList.iterator(); while (notificationConfigIterator.hasNext()) { - PushNotificationConfig config = notificationConfigIterator.next(); + TaskPushNotificationConfig config = notificationConfigIterator.next(); if (configId.equals(config.id())) { notificationConfigIterator.remove(); break; 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 828b066a6..50c3b2e28 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,7 +2,7 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.TaskPushNotificationConfig; /** * Interface for storing and retrieving push notification configurations for tasks. @@ -15,7 +15,7 @@ *

        Configuration ID Semantics

        * Each push notification config has an ID: *
          - *
        • If not provided in {@link PushNotificationConfig}, defaults to the task ID
        • + *
        • If not provided in {@link TaskPushNotificationConfig}, defaults to the task ID
        • *
        • Multiple configs per task require unique IDs (e.g., "webhook-1", "webhook-2")
        • *
        • Used for retrieval and deletion of specific configurations
        • *
        @@ -53,7 +53,7 @@ * EntityManager em; * * @Transactional - * public PushNotificationConfig setInfo(String taskId, PushNotificationConfig config) { + * public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig config) { * // JPA persistence logic * } * } @@ -65,7 +65,7 @@ * * @see PushNotificationSender * @see InMemoryPushNotificationConfigStore - * @see io.a2a.spec.PushNotificationConfig + * @see io.a2a.spec.TaskPushNotificationConfig */ public interface PushNotificationConfigStore { @@ -76,11 +76,10 @@ public interface PushNotificationConfigStore { * If a config with the same ID already exists for this task, it's replaced. *

        * - * @param taskId the task ID - * @param notificationConfig the push notification configuration + * @param notificationConfig the task push notification configuration * @return the potentially updated configuration (with ID set if it was null) */ - PushNotificationConfig setInfo(String taskId, PushNotificationConfig notificationConfig); + TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificationConfig); /** * Retrieves push notification configurations for a task with pagination support. diff --git a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java index 093241182..d2e8bd6cf 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java +++ b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java @@ -75,7 +75,7 @@ * * @see PushNotificationConfigStore * @see BasePushNotificationSender - * @see io.a2a.spec.PushNotificationConfig + * @see io.a2a.spec.TaskPushNotificationConfig */ public interface PushNotificationSender { diff --git a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java b/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java index bc96b36ac..22caad022 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java @@ -18,7 +18,6 @@ import io.a2a.common.A2AHeaders; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskState; @@ -59,7 +58,7 @@ private void setupBasicMockHttpResponse() throws Exception { when(mockHttpResponse.success()).thenReturn(true); } - private void verifyHttpCallWithoutToken(PushNotificationConfig config, Task task, String expectedToken) throws Exception { + private void verifyHttpCallWithoutToken(TaskPushNotificationConfig config, Task task, String expectedToken) throws Exception { ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); verify(mockHttpClient).createPost(); verify(mockPostBuilder).url(config.url()); @@ -82,20 +81,23 @@ private Task createSampleTask(String taskId, TaskState state) { .build(); } - private PushNotificationConfig createSamplePushConfig(String url, String configId, String token) { - return PushNotificationConfig.builder() + private TaskPushNotificationConfig createSamplePushConfig(String taskId, String url, String configId, String token) { + TaskPushNotificationConfig.Builder builder = TaskPushNotificationConfig.builder() .url(url) .id(configId) - .token(token) - .build(); + .taskId(taskId); + if (token != null) { + builder.token(token); + } + return builder.build(); } @Test public void testSetInfoAddsNewConfig() { String taskId = "task_new"; - PushNotificationConfig config = createSamplePushConfig("http://new.url/callback", "cfg1", null); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://new.url/callback", "cfg1", null); - PushNotificationConfig result = configStore.setInfo(taskId, config); + TaskPushNotificationConfig result = configStore.setInfo(config); assertNotNull(result); assertEquals(config.url(), result.url()); @@ -104,34 +106,32 @@ public void testSetInfoAddsNewConfig() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - assertEquals(config.id(), configResult.configs().get(0).config().id()); + assertEquals(config.url(), configResult.configs().get(0).url()); + assertEquals(config.id(), configResult.configs().get(0).id()); } @Test public void testSetInfoAppendsToExistingConfig() { String taskId = "task_update"; - PushNotificationConfig initialConfig = createSamplePushConfig( + TaskPushNotificationConfig initialConfig = createSamplePushConfig(taskId, "http://initial.url/callback", "cfg_initial", null); - configStore.setInfo(taskId, initialConfig); + configStore.setInfo(initialConfig); - PushNotificationConfig updatedConfig = createSamplePushConfig( + TaskPushNotificationConfig updatedConfig = createSamplePushConfig(taskId, "http://updated.url/callback", "cfg_updated", null); - configStore.setInfo(taskId, updatedConfig); + configStore.setInfo(updatedConfig); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(2, configResult.configs().size()); // Find the configs by ID since order might vary - List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::config) - .toList(); - PushNotificationConfig foundInitial = configs.stream() + List configs = configResult.configs(); + TaskPushNotificationConfig foundInitial = configs.stream() .filter(c -> "cfg_initial".equals(c.id())) .findFirst() .orElse(null); - PushNotificationConfig foundUpdated = configs.stream() + TaskPushNotificationConfig foundUpdated = configs.stream() .filter(c -> "cfg_updated".equals(c.id())) .findFirst() .orElse(null); @@ -145,40 +145,44 @@ public void testSetInfoAppendsToExistingConfig() { @Test public void testSetInfoWithoutConfigId() { String taskId = "task1"; - PushNotificationConfig initialConfig = PushNotificationConfig.builder() + TaskPushNotificationConfig initialConfig = TaskPushNotificationConfig.builder() + .id("") // No ID set .url("http://initial.url/callback") - .build(); // No ID set + .taskId(taskId) + .build(); - PushNotificationConfig result = configStore.setInfo(taskId, initialConfig); + TaskPushNotificationConfig result = configStore.setInfo(initialConfig); assertEquals(taskId, result.id(), "Config ID should default to taskId when not provided"); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size()); - assertEquals(taskId, configResult.configs().get(0).config().id()); + assertEquals(taskId, configResult.configs().get(0).id()); - PushNotificationConfig updatedConfig = PushNotificationConfig.builder() + TaskPushNotificationConfig updatedConfig = TaskPushNotificationConfig.builder() + .id("") // No ID set .url("http://initial.url/callback_new") - .build(); // No ID set + .taskId(taskId) + .build(); - PushNotificationConfig updatedResult = configStore.setInfo(taskId, updatedConfig); + TaskPushNotificationConfig updatedResult = configStore.setInfo(updatedConfig); assertEquals(taskId, updatedResult.id()); configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size(), "Should replace existing config with same ID rather than adding new one"); - assertEquals(updatedConfig.url(), configResult.configs().get(0).config().url()); + assertEquals(updatedConfig.url(), configResult.configs().get(0).url()); } @Test public void testGetInfoExistingConfig() { String taskId = "task_get_exist"; - PushNotificationConfig config = createSamplePushConfig("http://get.this/callback", "cfg1", null); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://get.this/callback", "cfg1", null); + configStore.setInfo(config); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - assertEquals(config.id(), configResult.configs().get(0).config().id()); + assertEquals(config.url(), configResult.configs().get(0).url()); + assertEquals(config.id(), configResult.configs().get(0).id()); } @Test @@ -192,8 +196,8 @@ public void testGetInfoNonExistentConfig() { @Test public void testDeleteInfoExistingConfig() { String taskId = "task_delete_exist"; - PushNotificationConfig config = createSamplePushConfig("http://delete.this/callback", "cfg1", null); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://delete.this/callback", "cfg1", null); + configStore.setInfo(config); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); @@ -220,10 +224,12 @@ public void testDeleteInfoNonExistentConfig() { @Test public void testDeleteInfoWithNullConfigId() { String taskId = "task_delete_null_config"; - PushNotificationConfig config = PushNotificationConfig.builder() + TaskPushNotificationConfig config = TaskPushNotificationConfig.builder() + .id("") // No ID set, will use taskId .url("http://delete.this/callback") - .build(); // No ID set, will use taskId - configStore.setInfo(taskId, config); + .taskId(taskId) + .build(); + configStore.setInfo(config); // Delete with null configId should use taskId configStore.deleteInfo(taskId, null); @@ -237,8 +243,8 @@ public void testDeleteInfoWithNullConfigId() { public void testSendNotificationSuccess() throws Exception { String taskId = "task_send_success"; Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", null); + configStore.setInfo(config); // Mock successful HTTP response setupBasicMockHttpResponse(); @@ -262,8 +268,8 @@ public void testSendNotificationSuccess() throws Exception { public void testSendNotificationWithToken() throws Exception { String taskId = "task_send_with_token"; Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", "unique_token"); + configStore.setInfo(config); // Mock successful HTTP response when(mockHttpClient.createPost()).thenReturn(mockPostBuilder); @@ -305,8 +311,8 @@ public void testSendNotificationNoConfig() throws Exception { public void testSendNotificationWithEmptyToken() throws Exception { String taskId = "task_send_empty_token"; Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", ""); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", ""); + configStore.setInfo(config); setupBasicMockHttpResponse(); notificationSender.sendNotification(task); @@ -317,8 +323,8 @@ public void testSendNotificationWithEmptyToken() throws Exception { public void testSendNotificationWithBlankToken() throws Exception { String taskId = "task_send_blank_token"; Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", " "); - configStore.setInfo(taskId, config); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", " "); + configStore.setInfo(config); setupBasicMockHttpResponse(); notificationSender.sendNotification(task); @@ -328,20 +334,18 @@ public void testSendNotificationWithBlankToken() throws Exception { @Test public void testMultipleConfigsForSameTask() { String taskId = "task_multiple"; - PushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); + TaskPushNotificationConfig config1 = createSamplePushConfig(taskId, "http://url1.com/callback", "cfg1", null); + TaskPushNotificationConfig config2 = createSamplePushConfig(taskId, "http://url2.com/callback", "cfg2", null); - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); + configStore.setInfo(config1); + configStore.setInfo(config2); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(2, configResult.configs().size()); // Verify both configs are present - List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::config) - .toList(); + List configs = configResult.configs(); assertTrue(configs.stream().anyMatch(c -> "cfg1".equals(c.id()))); assertTrue(configs.stream().anyMatch(c -> "cfg2".equals(c.id()))); } @@ -349,11 +353,11 @@ public void testMultipleConfigsForSameTask() { @Test public void testDeleteSpecificConfigFromMultiple() { String taskId = "task_delete_specific"; - PushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); + TaskPushNotificationConfig config1 = createSamplePushConfig(taskId, "http://url1.com/callback", "cfg1", null); + TaskPushNotificationConfig config2 = createSamplePushConfig(taskId, "http://url2.com/callback", "cfg2", null); - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); + configStore.setInfo(config1); + configStore.setInfo(config2); // Delete only config1 configStore.deleteInfo(taskId, "cfg1"); @@ -361,22 +365,22 @@ public void testDeleteSpecificConfigFromMultiple() { ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertNotNull(configResult); assertEquals(1, configResult.configs().size()); - assertEquals("cfg2", configResult.configs().get(0).config().id()); + assertEquals("cfg2", configResult.configs().get(0).id()); } @Test public void testConfigStoreIntegration() { String taskId = "integration_test"; - PushNotificationConfig config = createSamplePushConfig("http://example.com", "test_id", "test_token"); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://example.com", "test_id", "test_token"); // Test that we can store and retrieve configurations - PushNotificationConfig storedConfig = configStore.setInfo(taskId, config); + TaskPushNotificationConfig storedConfig = configStore.setInfo(config); assertEquals(config.url(), storedConfig.url()); assertEquals(config.token(), storedConfig.token()); ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); + assertEquals(config.url(), configResult.configs().get(0).url()); // Test deletion configStore.deleteInfo(taskId, storedConfig.id()); @@ -390,9 +394,9 @@ public void testPaginationWithPageSize() { String taskId = "task_pagination"; // Create 5 configs for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Request first page with pageSize=2 @@ -409,9 +413,9 @@ public void testPaginationWithPageToken() { String taskId = "task_pagination_token"; // Create 5 configs for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Get first page @@ -430,10 +434,10 @@ public void testPaginationWithPageToken() { // Verify NO overlap between pages - collect all IDs from both pages List firstPageIds = firstPage.configs().stream() - .map(c -> c.config().id()) + .map(c -> c.id()) .toList(); List secondPageIds = secondPage.configs().stream() - .map(c -> c.config().id()) + .map(c -> c.id()) .toList(); // Check that no ID from first page appears in second page @@ -455,9 +459,9 @@ public void testPaginationLastPage() { String taskId = "task_pagination_last"; // Create 5 configs for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Get first page (2 items) @@ -484,9 +488,9 @@ public void testPaginationWithZeroPageSize() { String taskId = "task_pagination_zero"; // Create 5 configs for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Request with pageSize=0 should return all configs @@ -503,9 +507,9 @@ public void testPaginationWithNegativePageSize() { String taskId = "task_pagination_negative"; // Create 3 configs for (int i = 0; i < 3; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Request with negative pageSize should return all configs @@ -522,9 +526,9 @@ public void testPaginationPageSizeLargerThanConfigs() { String taskId = "task_pagination_large"; // Create 3 configs for (int i = 0; i < 3; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Request with pageSize larger than available configs @@ -541,9 +545,9 @@ public void testPaginationExactlyPageSize() { String taskId = "task_pagination_exact"; // Create exactly 3 configs for (int i = 0; i < 3; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Request with pageSize equal to number of configs @@ -560,9 +564,9 @@ public void testPaginationWithInvalidToken() { String taskId = "task_pagination_invalid_token"; // Create 5 configs for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Request with invalid pageToken - implementation behavior is to start from beginning @@ -594,9 +598,9 @@ public void testPaginationFullIteration() { String taskId = "task_pagination_full"; // Create 7 configs for (int i = 0; i < 7; i++) { - PushNotificationConfig config = createSamplePushConfig( + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); + configStore.setInfo(config); } // Iterate through all pages with pageSize=3 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 4a68d849a..487377255 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 @@ -23,8 +23,8 @@ import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.Artifact; import io.a2a.spec.Message; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskState; @@ -155,10 +155,10 @@ public void setUp() { private void testSendNotificationWithInvalidToken(String token, String testName) throws InterruptedException { String taskId = testName; Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", token); - + TaskPushNotificationConfig config = createSamplePushConfig(taskId, "http://notify.me/here", "cfg1", token); + // Set up the configuration in the store - configStore.setInfo(taskId, config); + configStore.setInfo(config); // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); @@ -194,22 +194,25 @@ private Task createSampleTask(String taskId, TaskState state) { .build(); } - private PushNotificationConfig createSamplePushConfig(String url, String configId, String token) { - return PushNotificationConfig.builder() + private TaskPushNotificationConfig createSamplePushConfig(String taskId, String url, String configId, String token) { + TaskPushNotificationConfig.Builder builder = TaskPushNotificationConfig.builder() .url(url) .id(configId) - .token(token) - .build(); + .taskId(taskId); + if (token != null) { + builder.token(token); + } + return builder.build(); } @Test public void testSendNotificationSuccess() throws InterruptedException { String taskId = "task_send_success"; Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", null); // Set up the configuration in the store - configStore.setInfo(taskId, config); + configStore.setInfo(config); // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); @@ -237,10 +240,10 @@ public void testSendNotificationSuccess() throws InterruptedException { public void testSendNotificationWithTokenSuccess() throws InterruptedException { String taskId = "task_send_with_token"; Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", "unique_token"); // Set up the configuration in the store - configStore.setInfo(taskId, config); + configStore.setInfo(config); // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); @@ -295,12 +298,12 @@ public void testSendNotificationWithBlankToken() throws InterruptedException { public void testSendNotificationMultipleConfigs() throws InterruptedException { String taskId = "task_multiple_configs"; Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config1 = createSamplePushConfig("http://notify.me/cfg1", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://notify.me/cfg2", "cfg2", null); + TaskPushNotificationConfig config1 = createSamplePushConfig(taskId,"http://notify.me/cfg1", "cfg1", null); + TaskPushNotificationConfig config2 = createSamplePushConfig(taskId,"http://notify.me/cfg2", "cfg2", null); // Set up multiple configurations in the store - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); + configStore.setInfo(config1); + configStore.setInfo(config2); // Set up latch to wait for async completion (2 calls expected) testHttpClient.latch = new CountDownLatch(2); @@ -329,10 +332,10 @@ public void testSendNotificationMultipleConfigs() throws InterruptedException { public void testSendNotificationHttpError() { String taskId = "task_send_http_err"; Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/http_error", "cfg1", null); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/http_error", "cfg1", null); // Set up the configuration in the store - configStore.setInfo(taskId, config); + configStore.setInfo(config); // Configure the test client to throw an exception testHttpClient.shouldThrowException = true; @@ -352,10 +355,10 @@ public void testSendNotificationMessage() throws InterruptedException { .role(Message.Role.ROLE_AGENT) .parts(new TextPart("Hello from agent")) .build(); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", null); // Set up the configuration in the store - configStore.setInfo(taskId, config); + configStore.setInfo(config); // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); @@ -385,10 +388,10 @@ public void testSendNotificationTaskStatusUpdate() throws InterruptedException { .contextId("ctx456") .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) .build(); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", null); // Set up the configuration in the store - configStore.setInfo(taskId, config); + configStore.setInfo(config); // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); @@ -424,10 +427,10 @@ public void testSendNotificationTaskArtifactUpdate() throws InterruptedException .contextId("ctx456") .artifact(artifact) .build(); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); + TaskPushNotificationConfig config = createSamplePushConfig(taskId,"http://notify.me/here", "cfg1", null); // Set up the configuration in the store - configStore.setInfo(taskId, config); + configStore.setInfo(config); // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); diff --git a/skills/update-a2a-proto/SKILL.md b/skills/update-a2a-proto/SKILL.md new file mode 100644 index 000000000..b3cef1c7b --- /dev/null +++ b/skills/update-a2a-proto/SKILL.md @@ -0,0 +1,86 @@ +--- +name: update-a2a-proto +description: Update the A2A Protobuf file (a2a.proto) when the A2A protocol specification changes. Use when the user mentions updating the spec, syncing with upstream A2A, or when a new version of the A2A protocol is released. +compatibility: Requires curl +allowed-tools: Bash(mvn:*) Bash(curl:*) Read Edit Write Glob Grep +--- + +# Update a2a.proto + +Update the A2A gRPC proto file from the upstream specification repository and regenerate Java sources. + +## Step 1: Capture the current state + +Before updating, record what we have now so we can diff later. + +1. Read `spec-grpc/src/main/proto/a2a.proto` to note the current commit hash (located at the top of the file in a comment) +2. Save a copy of the file for diffing: + +## Step 2: Download the updated specification + +1. Ask the user if they want to update from the `main` branch or pass a `tag` or a `commit cheksum` +2. Download the latest `a2a.proto` from the upstream A2A repository at https://github.com/a2aproject/A2A/blob/main/specification/a2a.proto and save it to `spec-grpc/src/main/proto/a2a.proto`. +3. Update the `java_package` option in the downloaded proto file to: + ``` + option java_package = "io.a2a.grpc"; + ``` +4. Update the comment tracking the upstream commit hash (line starting with `// From commit`) to the commit hash / tag of the downloaded proto file. + +## Step 3: Analyze specification changes + +Compare the old and new versions of the specification to identify changes: + +1. Diff `specification/a2a.proto` with the backup to find: + - New or changed message types + - New or changed RPC methods + - New or changed fields + +## Step 4: Regenerate gRPC classes + +1. Delete all the generated gRPC Java classes (in case of resources removed from the Protobuf definitions): + ```bash + find spec-grpc/src/main/java/io/a2a/grpc -maxdepth 1 -name "*.java" -delete``` + ``` + +2. Regenerate gRPC Java classes by running: + ```bash + mvn generate-sources -pl spec-grpc -Dskip.protobuf.generate=false + ``` + +## Step 5: Update the code + +Based on the spec diff, update the relevant files + +Summarize the changes for the user before proceeding. + +## Step 6: Validate + +Run the tests on all modules to verify the update + +```bash +mvn clean install +``` + +Fix any issues before proceeding. + +## Step 7: Audit changes + +Before committing, audit all code changes. + +Highlight any new, modified, or removed changes in the API in the `client`, `common`, `server-common`, and `spec` modules + +Verify the build succeeds for the full project: + +```bash +mvn clean install +``` + +## Step 8: Summarize + +Present the user with a summary of: +- The old and new spec commit hashes +- What changed in the specification +- What was updated in the code +- Any areas that need manual review or additional test coverage +- Impact on user API (from the `client`, `common`, `server-common`, and `spec` modules) + - Write a "migration summary" for breaking changes in the API \ No newline at end of file diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java index ab16709b0..5317db6ba 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java @@ -66,11 +66,6 @@ public static void registerAllExtensions( static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_lf_a2a_v1_PushNotificationConfig_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_lf_a2a_v1_PushNotificationConfig_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_lf_a2a_v1_AuthenticationInfo_descriptor; static final @@ -256,11 +251,6 @@ public static void registerAllExtensions( static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor; static final @@ -305,255 +295,248 @@ public static void registerAllExtensions( "oogle/api/field_behavior.proto\032\033google/p" + "rotobuf/empty.proto\032\034google/protobuf/str" + "uct.proto\032\037google/protobuf/timestamp.pro" + - "to\"\300\001\n\030SendMessageConfiguration\022\035\n\025accep" + - "ted_output_modes\030\001 \003(\t\022C\n\030push_notificat" + - "ion_config\030\002 \001(\0132!.lf.a2a.v1.PushNotific" + - "ationConfig\022\033\n\016history_length\030\003 \001(\005H\000\210\001\001" + - "\022\020\n\010blocking\030\004 \001(\010B\021\n\017_history_length\"\324\001" + - "\n\004Task\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 " + - "\001(\tB\003\340A\002\022*\n\006status\030\003 \001(\0132\025.lf.a2a.v1.Tas" + - "kStatusB\003\340A\002\022&\n\tartifacts\030\004 \003(\0132\023.lf.a2a" + - ".v1.Artifact\022#\n\007history\030\005 \003(\0132\022.lf.a2a.v" + - "1.Message\022)\n\010metadata\030\006 \001(\0132\027.google.pro" + - "tobuf.Struct\"\212\001\n\nTaskStatus\022(\n\005state\030\001 \001" + - "(\0162\024.lf.a2a.v1.TaskStateB\003\340A\002\022#\n\007message" + - "\030\002 \001(\0132\022.lf.a2a.v1.Message\022-\n\ttimestamp\030" + - "\003 \001(\0132\032.google.protobuf.Timestamp\"\270\001\n\004Pa" + - "rt\022\016\n\004text\030\001 \001(\tH\000\022\r\n\003raw\030\002 \001(\014H\000\022\r\n\003url" + - "\030\003 \001(\tH\000\022&\n\004data\030\004 \001(\0132\026.google.protobuf" + - ".ValueH\000\022)\n\010metadata\030\005 \001(\0132\027.google.prot" + - "obuf.Struct\022\020\n\010filename\030\006 \001(\t\022\022\n\nmedia_t" + - "ype\030\007 \001(\tB\t\n\007content\"\353\001\n\007Message\022\027\n\nmess" + - "age_id\030\001 \001(\tB\003\340A\002\022\022\n\ncontext_id\030\002 \001(\t\022\017\n" + - "\007task_id\030\003 \001(\t\022\"\n\004role\030\004 \001(\0162\017.lf.a2a.v1" + - ".RoleB\003\340A\002\022#\n\005parts\030\005 \003(\0132\017.lf.a2a.v1.Pa" + - "rtB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027.google.proto" + - "buf.Struct\022\022\n\nextensions\030\007 \003(\t\022\032\n\022refere" + - "nce_task_ids\030\010 \003(\t\"\253\001\n\010Artifact\022\030\n\013artif" + - "act_id\030\001 \001(\tB\003\340A\002\022\014\n\004name\030\002 \001(\t\022\023\n\013descr" + - "iption\030\003 \001(\t\022#\n\005parts\030\004 \003(\0132\017.lf.a2a.v1." + - "PartB\003\340A\002\022)\n\010metadata\030\005 \001(\0132\027.google.pro" + - "tobuf.Struct\022\022\n\nextensions\030\006 \003(\t\"\235\001\n\025Tas" + - "kStatusUpdateEvent\022\024\n\007task_id\030\001 \001(\tB\003\340A\002" + - "\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022*\n\006status\030\003 \001(" + - "\0132\025.lf.a2a.v1.TaskStatusB\003\340A\002\022)\n\010metadat" + - "a\030\004 \001(\0132\027.google.protobuf.Struct\"\303\001\n\027Tas" + - "kArtifactUpdateEvent\022\024\n\007task_id\030\001 \001(\tB\003\340" + - "A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022*\n\010artifact\030" + - "\003 \001(\0132\023.lf.a2a.v1.ArtifactB\003\340A\002\022\016\n\006appen" + - "d\030\004 \001(\010\022\022\n\nlast_chunk\030\005 \001(\010\022)\n\010metadata\030" + - "\006 \001(\0132\027.google.protobuf.Struct\"|\n\026PushNo" + - "tificationConfig\022\n\n\002id\030\001 \001(\t\022\020\n\003url\030\002 \001(" + - "\tB\003\340A\002\022\r\n\005token\030\003 \001(\t\0225\n\016authentication\030" + - "\004 \001(\0132\035.lf.a2a.v1.AuthenticationInfo\">\n\022" + - "AuthenticationInfo\022\023\n\006scheme\030\001 \001(\tB\003\340A\002\022" + - "\023\n\013credentials\030\002 \001(\t\"p\n\016AgentInterface\022\020" + - "\n\003url\030\001 \001(\tB\003\340A\002\022\035\n\020protocol_binding\030\002 \001" + - "(\tB\003\340A\002\022\016\n\006tenant\030\003 \001(\t\022\035\n\020protocol_vers" + - "ion\030\004 \001(\tB\003\340A\002\"\306\005\n\tAgentCard\022\021\n\004name\030\001 \001" + - "(\tB\003\340A\002\022\030\n\013description\030\002 \001(\tB\003\340A\002\022<\n\024sup" + - "ported_interfaces\030\003 \003(\0132\031.lf.a2a.v1.Agen" + - "tInterfaceB\003\340A\002\022*\n\010provider\030\004 \001(\0132\030.lf.a" + - "2a.v1.AgentProvider\022\024\n\007version\030\005 \001(\tB\003\340A" + - "\002\022\036\n\021documentation_url\030\006 \001(\tH\000\210\001\001\0227\n\014cap" + - "abilities\030\007 \001(\0132\034.lf.a2a.v1.AgentCapabil" + - "itiesB\003\340A\002\022C\n\020security_schemes\030\010 \003(\0132).l" + - "f.a2a.v1.AgentCard.SecuritySchemesEntry\022" + - "=\n\025security_requirements\030\t \003(\0132\036.lf.a2a." + - "v1.SecurityRequirement\022 \n\023default_input_" + - "modes\030\n \003(\tB\003\340A\002\022!\n\024default_output_modes" + - "\030\013 \003(\tB\003\340A\002\022*\n\006skills\030\014 \003(\0132\025.lf.a2a.v1." + - "AgentSkillB\003\340A\002\0221\n\nsignatures\030\r \003(\0132\035.lf" + - ".a2a.v1.AgentCardSignature\022\025\n\010icon_url\030\016" + - " \001(\tH\001\210\001\001\032Q\n\024SecuritySchemesEntry\022\013\n\003key" + - "\030\001 \001(\t\022(\n\005value\030\002 \001(\0132\031.lf.a2a.v1.Securi" + - "tyScheme:\0028\001B\024\n\022_documentation_urlB\013\n\t_i" + - "con_url\"<\n\rAgentProvider\022\020\n\003url\030\001 \001(\tB\003\340" + - "A\002\022\031\n\014organization\030\002 \001(\tB\003\340A\002\"\332\001\n\021AgentC" + - "apabilities\022\026\n\tstreaming\030\001 \001(\010H\000\210\001\001\022\037\n\022p" + - "ush_notifications\030\002 \001(\010H\001\210\001\001\022-\n\nextensio" + - "ns\030\003 \003(\0132\031.lf.a2a.v1.AgentExtension\022 \n\023e" + - "xtended_agent_card\030\004 \001(\010H\002\210\001\001B\014\n\n_stream" + - "ingB\025\n\023_push_notificationsB\026\n\024_extended_" + - "agent_card\"m\n\016AgentExtension\022\013\n\003uri\030\001 \001(" + - "\t\022\023\n\013description\030\002 \001(\t\022\020\n\010required\030\003 \001(\010" + - "\022\'\n\006params\030\004 \001(\0132\027.google.protobuf.Struc" + - "t\"\331\001\n\nAgentSkill\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\021\n\004nam" + - "e\030\002 \001(\tB\003\340A\002\022\030\n\013description\030\003 \001(\tB\003\340A\002\022\021" + - "\n\004tags\030\004 \003(\tB\003\340A\002\022\020\n\010examples\030\005 \003(\t\022\023\n\013i" + - "nput_modes\030\006 \003(\t\022\024\n\014output_modes\030\007 \003(\t\022=" + - "\n\025security_requirements\030\010 \003(\0132\036.lf.a2a.v" + - "1.SecurityRequirement\"m\n\022AgentCardSignat" + - "ure\022\026\n\tprotected\030\001 \001(\tB\003\340A\002\022\026\n\tsignature" + - "\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\0132\027.google.pro" + - "tobuf.Struct\"\214\001\n\032TaskPushNotificationCon" + - "fig\022\016\n\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A" + - "\002\022H\n\030push_notification_config\030\003 \001(\0132!.lf" + - ".a2a.v1.PushNotificationConfigB\003\340A\002\"\032\n\nS" + - "tringList\022\014\n\004list\030\001 \003(\t\"\232\001\n\023SecurityRequ" + - "irement\022<\n\007schemes\030\001 \003(\0132+.lf.a2a.v1.Sec" + - "urityRequirement.SchemesEntry\032E\n\014Schemes" + - "Entry\022\013\n\003key\030\001 \001(\t\022$\n\005value\030\002 \001(\0132\025.lf.a" + - "2a.v1.StringList:\0028\001\"\200\003\n\016SecurityScheme\022" + - "B\n\027api_key_security_scheme\030\001 \001(\0132\037.lf.a2" + - "a.v1.APIKeySecuritySchemeH\000\022F\n\031http_auth" + - "_security_scheme\030\002 \001(\0132!.lf.a2a.v1.HTTPA" + - "uthSecuritySchemeH\000\022A\n\026oauth2_security_s" + - "cheme\030\003 \001(\0132\037.lf.a2a.v1.OAuth2SecuritySc" + - "hemeH\000\022Q\n\037open_id_connect_security_schem" + - "e\030\004 \001(\0132&.lf.a2a.v1.OpenIdConnectSecurit" + - "ySchemeH\000\022B\n\024mtls_security_scheme\030\005 \001(\0132" + - "\".lf.a2a.v1.MutualTlsSecuritySchemeH\000B\010\n" + - "\006scheme\"U\n\024APIKeySecurityScheme\022\023\n\013descr" + - "iption\030\001 \001(\t\022\025\n\010location\030\002 \001(\tB\003\340A\002\022\021\n\004n" + - "ame\030\003 \001(\tB\003\340A\002\"Y\n\026HTTPAuthSecurityScheme" + - "\022\023\n\013description\030\001 \001(\t\022\023\n\006scheme\030\002 \001(\tB\003\340" + - "A\002\022\025\n\rbearer_format\030\003 \001(\t\"s\n\024OAuth2Secur" + - "ityScheme\022\023\n\013description\030\001 \001(\t\022)\n\005flows\030" + - "\002 \001(\0132\025.lf.a2a.v1.OAuthFlowsB\003\340A\002\022\033\n\023oau" + - "th2_metadata_url\030\003 \001(\t\"T\n\033OpenIdConnectS" + - "ecurityScheme\022\023\n\013description\030\001 \001(\t\022 \n\023op" + - "en_id_connect_url\030\002 \001(\tB\003\340A\002\".\n\027MutualTl" + - "sSecurityScheme\022\023\n\013description\030\001 \001(\t\"\301\002\n" + - "\nOAuthFlows\022C\n\022authorization_code\030\001 \001(\0132" + - "%.lf.a2a.v1.AuthorizationCodeOAuthFlowH\000" + - "\022C\n\022client_credentials\030\002 \001(\0132%.lf.a2a.v1" + - ".ClientCredentialsOAuthFlowH\000\0224\n\010implici" + - "t\030\003 \001(\0132\034.lf.a2a.v1.ImplicitOAuthFlowB\002\030" + - "\001H\000\0224\n\010password\030\004 \001(\0132\034.lf.a2a.v1.Passwo" + - "rdOAuthFlowB\002\030\001H\000\0225\n\013device_code\030\005 \001(\0132\036" + - ".lf.a2a.v1.DeviceCodeOAuthFlowH\000B\006\n\004flow" + - "\"\367\001\n\032AuthorizationCodeOAuthFlow\022\036\n\021autho" + - "rization_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001" + - "(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001(\t\022F\n\006scopes\030\004" + - " \003(\01321.lf.a2a.v1.AuthorizationCodeOAuthF" + - "low.ScopesEntryB\003\340A\002\022\025\n\rpkce_required\030\005 " + - "\001(\010\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value" + - "\030\002 \001(\t:\0028\001\"\300\001\n\032ClientCredentialsOAuthFlo" + - "w\022\026\n\ttoken_url\030\001 \001(\tB\003\340A\002\022\023\n\013refresh_url" + - "\030\002 \001(\t\022F\n\006scopes\030\003 \003(\01321.lf.a2a.v1.Clien" + - "tCredentialsOAuthFlow.ScopesEntryB\003\340A\002\032-" + - "\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(" + - "\t:\0028\001\"\254\001\n\021ImplicitOAuthFlow\022\031\n\021authoriza" + - "tion_url\030\001 \001(\t\022\023\n\013refresh_url\030\002 \001(\t\0228\n\006s" + - "copes\030\003 \003(\0132(.lf.a2a.v1.ImplicitOAuthFlo" + - "w.ScopesEntry\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(" + - "\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\244\001\n\021PasswordOAuthFl" + - "ow\022\021\n\ttoken_url\030\001 \001(\t\022\023\n\013refresh_url\030\002 \001" + - "(\t\0228\n\006scopes\030\003 \003(\0132(.lf.a2a.v1.PasswordO" + - "AuthFlow.ScopesEntry\032-\n\013ScopesEntry\022\013\n\003k" + - "ey\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\331\001\n\023DeviceCo" + - "deOAuthFlow\022%\n\030device_authorization_url\030" + - "\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013re" + - "fresh_url\030\003 \001(\t\022?\n\006scopes\030\004 \003(\0132*.lf.a2a" + - ".v1.DeviceCodeOAuthFlow.ScopesEntryB\003\340A\002" + - "\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 " + - "\001(\t:\0028\001\"\265\001\n\022SendMessageRequest\022\016\n\006tenant" + - "\030\001 \001(\t\022(\n\007message\030\002 \001(\0132\022.lf.a2a.v1.Mess" + - "ageB\003\340A\002\022:\n\rconfiguration\030\003 \001(\0132#.lf.a2a" + - ".v1.SendMessageConfiguration\022)\n\010metadata" + - "\030\004 \001(\0132\027.google.protobuf.Struct\"a\n\016GetTa" + - "skRequest\022\016\n\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340" + - "A\002\022\033\n\016history_length\030\003 \001(\005H\000\210\001\001B\021\n\017_hist" + - "ory_length\"\270\002\n\020ListTasksRequest\022\016\n\006tenan" + - "t\030\001 \001(\t\022\022\n\ncontext_id\030\002 \001(\t\022$\n\006status\030\003 " + - "\001(\0162\024.lf.a2a.v1.TaskState\022\026\n\tpage_size\030\004" + - " \001(\005H\000\210\001\001\022\022\n\npage_token\030\005 \001(\t\022\033\n\016history" + - "_length\030\006 \001(\005H\001\210\001\001\022:\n\026status_timestamp_a" + - "fter\030\007 \001(\0132\032.google.protobuf.Timestamp\022\036" + - "\n\021include_artifacts\030\010 \001(\010H\002\210\001\001B\014\n\n_page_" + - "sizeB\021\n\017_history_lengthB\024\n\022_include_arti" + - "facts\"\207\001\n\021ListTasksResponse\022#\n\005tasks\030\001 \003" + - "(\0132\017.lf.a2a.v1.TaskB\003\340A\002\022\034\n\017next_page_to" + - "ken\030\002 \001(\tB\003\340A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022\027" + - "\n\ntotal_size\030\004 \001(\005B\003\340A\002\"_\n\021CancelTaskReq" + - "uest\022\016\n\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\022)\n" + - "\010metadata\030\003 \001(\0132\027.google.protobuf.Struct" + - "\"]\n$GetTaskPushNotificationConfigRequest" + - "\022\016\n\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A\002\022\017" + - "\n\002id\030\003 \001(\tB\003\340A\002\"`\n\'DeleteTaskPushNotific" + - "ationConfigRequest\022\016\n\006tenant\030\001 \001(\t\022\024\n\007ta" + - "sk_id\030\002 \001(\tB\003\340A\002\022\017\n\002id\030\003 \001(\tB\003\340A\002\"\207\001\n\'Cr" + - "eateTaskPushNotificationConfigRequest\022\016\n" + - "\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A\002\0226\n\006c" + - "onfig\030\003 \001(\0132!.lf.a2a.v1.PushNotification" + - "ConfigB\003\340A\002\"9\n\026SubscribeToTaskRequest\022\016\n" + - "\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\"u\n&ListTa" + - "skPushNotificationConfigsRequest\022\016\n\006tena" + - "nt\030\004 \001(\t\022\024\n\007task_id\030\001 \001(\tB\003\340A\002\022\021\n\tpage_s" + - "ize\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t\"-\n\033GetExte" + - "ndedAgentCardRequest\022\016\n\006tenant\030\001 \001(\t\"h\n\023" + - "SendMessageResponse\022\037\n\004task\030\001 \001(\0132\017.lf.a" + - "2a.v1.TaskH\000\022%\n\007message\030\002 \001(\0132\022.lf.a2a.v" + - "1.MessageH\000B\t\n\007payload\"\335\001\n\016StreamRespons" + - "e\022\037\n\004task\030\001 \001(\0132\017.lf.a2a.v1.TaskH\000\022%\n\007me" + - "ssage\030\002 \001(\0132\022.lf.a2a.v1.MessageH\000\0229\n\rsta" + - "tus_update\030\003 \001(\0132 .lf.a2a.v1.TaskStatusU" + - "pdateEventH\000\022=\n\017artifact_update\030\004 \001(\0132\"." + - "lf.a2a.v1.TaskArtifactUpdateEventH\000B\t\n\007p" + - "ayload\"z\n\'ListTaskPushNotificationConfig" + - "sResponse\0226\n\007configs\030\001 \003(\0132%.lf.a2a.v1.T" + - "askPushNotificationConfig\022\027\n\017next_page_t" + - "oken\030\002 \001(\t*\371\001\n\tTaskState\022\032\n\026TASK_STATE_U" + - "NSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMITTED\020\001\022\026" + - "\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_STATE_COM" + - "PLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022\027\n\023TASK_" + - "STATE_CANCELED\020\005\022\035\n\031TASK_STATE_INPUT_REQ" + - "UIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020\007\022\034\n\030TASK" + - "_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE_U" + - "NSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AGEN" + - "T\020\0022\256\017\n\nA2AService\022\203\001\n\013SendMessage\022\035.lf." + - "a2a.v1.SendMessageRequest\032\036.lf.a2a.v1.Se" + - "ndMessageResponse\"5\202\323\344\223\002/\"\r/message:send" + - ":\001*Z\033\"\026/{tenant}/message:send:\001*\022\215\001\n\024Sen" + - "dStreamingMessage\022\035.lf.a2a.v1.SendMessag" + - "eRequest\032\031.lf.a2a.v1.StreamResponse\"9\202\323\344" + - "\223\0023\"\017/message:stream:\001*Z\035\"\030/{tenant}/mes" + - "sage:stream:\001*0\001\022k\n\007GetTask\022\031.lf.a2a.v1." + - "GetTaskRequest\032\017.lf.a2a.v1.Task\"4\332A\002id\202\323" + - "\344\223\002)\022\r/tasks/{id=*}Z\030\022\026/{tenant}/tasks/{" + - "id=*}\022i\n\tListTasks\022\033.lf.a2a.v1.ListTasks" + - "Request\032\034.lf.a2a.v1.ListTasksResponse\"!\202" + - "\323\344\223\002\033\022\006/tasksZ\021\022\017/{tenant}/tasks\022\200\001\n\nCan" + - "celTask\022\034.lf.a2a.v1.CancelTaskRequest\032\017." + - "lf.a2a.v1.Task\"C\202\323\344\223\002=\"\024/tasks/{id=*}:ca" + - "ncel:\001*Z\"\"\035/{tenant}/tasks/{id=*}:cancel" + - ":\001*\022\226\001\n\017SubscribeToTask\022!.lf.a2a.v1.Subs" + - "cribeToTaskRequest\032\031.lf.a2a.v1.StreamRes" + - "ponse\"C\202\323\344\223\002=\022\027/tasks/{id=*}:subscribeZ\"" + - "\022 /{tenant}/tasks/{id=*}:subscribe0\001\022\212\002\n" + - " CreateTaskPushNotificationConfig\0222.lf.a" + - "2a.v1.CreateTaskPushNotificationConfigRe" + - "quest\032%.lf.a2a.v1.TaskPushNotificationCo" + - "nfig\"\212\001\332A\016task_id,config\202\323\344\223\002s\"*/tasks/{" + - "task_id=*}/pushNotificationConfigs:\006conf" + - "igZ=\"3/{tenant}/tasks/{task_id=*}/pushNo" + - "tificationConfigs:\006config\022\376\001\n\035GetTaskPus" + - "hNotificationConfig\022/.lf.a2a.v1.GetTaskP" + - "ushNotificationConfigRequest\032%.lf.a2a.v1" + - ".TaskPushNotificationConfig\"\204\001\332A\ntask_id" + - ",id\202\323\344\223\002q\0221/tasks/{task_id=*}/pushNotifi" + - "cationConfigs/{id=*}Z<\022:/{tenant}/tasks/" + - "{task_id=*}/pushNotificationConfigs/{id=" + - "*}\022\375\001\n\037ListTaskPushNotificationConfigs\0221" + - ".lf.a2a.v1.ListTaskPushNotificationConfi" + - "gsRequest\0322.lf.a2a.v1.ListTaskPushNotifi" + - "cationConfigsResponse\"s\332A\007task_id\202\323\344\223\002c\022" + - "*/tasks/{task_id=*}/pushNotificationConf" + - "igsZ5\0223/{tenant}/tasks/{task_id=*}/pushN" + - "otificationConfigs\022\217\001\n\024GetExtendedAgentC" + - "ard\022&.lf.a2a.v1.GetExtendedAgentCardRequ" + - "est\032\024.lf.a2a.v1.AgentCard\"9\202\323\344\223\0023\022\022/exte" + - "ndedAgentCardZ\035\022\033/{tenant}/extendedAgent" + - "Card\022\365\001\n DeleteTaskPushNotificationConfi" + - "g\0222.lf.a2a.v1.DeleteTaskPushNotification" + - "ConfigRequest\032\026.google.protobuf.Empty\"\204\001" + - "\332A\ntask_id,id\202\323\344\223\002q*1/tasks/{task_id=*}/" + - "pushNotificationConfigs/{id=*}Z<*:/{tena" + - "nt}/tasks/{task_id=*}/pushNotificationCo" + - "nfigs/{id=*}B=\n\013io.a2a.grpcB\003A2AP\001Z\033goog" + - "le.golang.org/lf/a2a/v1\252\002\tLf.A2a.V1b\006pro" + - "to3" + "to\"\311\001\n\030SendMessageConfiguration\022\035\n\025accep" + + "ted_output_modes\030\001 \003(\t\022L\n\035task_push_noti" + + "fication_config\030\002 \001(\0132%.lf.a2a.v1.TaskPu" + + "shNotificationConfig\022\033\n\016history_length\030\003" + + " \001(\005H\000\210\001\001\022\020\n\010blocking\030\004 \001(\010B\021\n\017_history_" + + "length\"\317\001\n\004Task\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\022\n\ncont" + + "ext_id\030\002 \001(\t\022*\n\006status\030\003 \001(\0132\025.lf.a2a.v1" + + ".TaskStatusB\003\340A\002\022&\n\tartifacts\030\004 \003(\0132\023.lf" + + ".a2a.v1.Artifact\022#\n\007history\030\005 \003(\0132\022.lf.a" + + "2a.v1.Message\022)\n\010metadata\030\006 \001(\0132\027.google" + + ".protobuf.Struct\"\212\001\n\nTaskStatus\022(\n\005state" + + "\030\001 \001(\0162\024.lf.a2a.v1.TaskStateB\003\340A\002\022#\n\007mes" + + "sage\030\002 \001(\0132\022.lf.a2a.v1.Message\022-\n\ttimest" + + "amp\030\003 \001(\0132\032.google.protobuf.Timestamp\"\270\001" + + "\n\004Part\022\016\n\004text\030\001 \001(\tH\000\022\r\n\003raw\030\002 \001(\014H\000\022\r\n" + + "\003url\030\003 \001(\tH\000\022&\n\004data\030\004 \001(\0132\026.google.prot" + + "obuf.ValueH\000\022)\n\010metadata\030\005 \001(\0132\027.google." + + "protobuf.Struct\022\020\n\010filename\030\006 \001(\t\022\022\n\nmed" + + "ia_type\030\007 \001(\tB\t\n\007content\"\353\001\n\007Message\022\027\n\n" + + "message_id\030\001 \001(\tB\003\340A\002\022\022\n\ncontext_id\030\002 \001(" + + "\t\022\017\n\007task_id\030\003 \001(\t\022\"\n\004role\030\004 \001(\0162\017.lf.a2" + + "a.v1.RoleB\003\340A\002\022#\n\005parts\030\005 \003(\0132\017.lf.a2a.v" + + "1.PartB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027.google.p" + + "rotobuf.Struct\022\022\n\nextensions\030\007 \003(\t\022\032\n\022re" + + "ference_task_ids\030\010 \003(\t\"\253\001\n\010Artifact\022\030\n\013a" + + "rtifact_id\030\001 \001(\tB\003\340A\002\022\014\n\004name\030\002 \001(\t\022\023\n\013d" + + "escription\030\003 \001(\t\022#\n\005parts\030\004 \003(\0132\017.lf.a2a" + + ".v1.PartB\003\340A\002\022)\n\010metadata\030\005 \001(\0132\027.google" + + ".protobuf.Struct\022\022\n\nextensions\030\006 \003(\t\"\235\001\n" + + "\025TaskStatusUpdateEvent\022\024\n\007task_id\030\001 \001(\tB" + + "\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022*\n\006status\030" + + "\003 \001(\0132\025.lf.a2a.v1.TaskStatusB\003\340A\002\022)\n\010met" + + "adata\030\004 \001(\0132\027.google.protobuf.Struct\"\303\001\n" + + "\027TaskArtifactUpdateEvent\022\024\n\007task_id\030\001 \001(" + + "\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022*\n\010artif" + + "act\030\003 \001(\0132\023.lf.a2a.v1.ArtifactB\003\340A\002\022\016\n\006a" + + "ppend\030\004 \001(\010\022\022\n\nlast_chunk\030\005 \001(\010\022)\n\010metad" + + "ata\030\006 \001(\0132\027.google.protobuf.Struct\">\n\022Au" + + "thenticationInfo\022\023\n\006scheme\030\001 \001(\tB\003\340A\002\022\023\n" + + "\013credentials\030\002 \001(\t\"p\n\016AgentInterface\022\020\n\003" + + "url\030\001 \001(\tB\003\340A\002\022\035\n\020protocol_binding\030\002 \001(\t" + + "B\003\340A\002\022\016\n\006tenant\030\003 \001(\t\022\035\n\020protocol_versio" + + "n\030\004 \001(\tB\003\340A\002\"\306\005\n\tAgentCard\022\021\n\004name\030\001 \001(\t" + + "B\003\340A\002\022\030\n\013description\030\002 \001(\tB\003\340A\002\022<\n\024suppo" + + "rted_interfaces\030\003 \003(\0132\031.lf.a2a.v1.AgentI" + + "nterfaceB\003\340A\002\022*\n\010provider\030\004 \001(\0132\030.lf.a2a" + + ".v1.AgentProvider\022\024\n\007version\030\005 \001(\tB\003\340A\002\022" + + "\036\n\021documentation_url\030\006 \001(\tH\000\210\001\001\0227\n\014capab" + + "ilities\030\007 \001(\0132\034.lf.a2a.v1.AgentCapabilit" + + "iesB\003\340A\002\022C\n\020security_schemes\030\010 \003(\0132).lf." + + "a2a.v1.AgentCard.SecuritySchemesEntry\022=\n" + + "\025security_requirements\030\t \003(\0132\036.lf.a2a.v1" + + ".SecurityRequirement\022 \n\023default_input_mo" + + "des\030\n \003(\tB\003\340A\002\022!\n\024default_output_modes\030\013" + + " \003(\tB\003\340A\002\022*\n\006skills\030\014 \003(\0132\025.lf.a2a.v1.Ag" + + "entSkillB\003\340A\002\0221\n\nsignatures\030\r \003(\0132\035.lf.a" + + "2a.v1.AgentCardSignature\022\025\n\010icon_url\030\016 \001" + + "(\tH\001\210\001\001\032Q\n\024SecuritySchemesEntry\022\013\n\003key\030\001" + + " \001(\t\022(\n\005value\030\002 \001(\0132\031.lf.a2a.v1.Security" + + "Scheme:\0028\001B\024\n\022_documentation_urlB\013\n\t_ico" + + "n_url\"<\n\rAgentProvider\022\020\n\003url\030\001 \001(\tB\003\340A\002" + + "\022\031\n\014organization\030\002 \001(\tB\003\340A\002\"\332\001\n\021AgentCap" + + "abilities\022\026\n\tstreaming\030\001 \001(\010H\000\210\001\001\022\037\n\022pus" + + "h_notifications\030\002 \001(\010H\001\210\001\001\022-\n\nextensions" + + "\030\003 \003(\0132\031.lf.a2a.v1.AgentExtension\022 \n\023ext" + + "ended_agent_card\030\004 \001(\010H\002\210\001\001B\014\n\n_streamin" + + "gB\025\n\023_push_notificationsB\026\n\024_extended_ag" + + "ent_card\"m\n\016AgentExtension\022\013\n\003uri\030\001 \001(\t\022" + + "\023\n\013description\030\002 \001(\t\022\020\n\010required\030\003 \001(\010\022\'" + + "\n\006params\030\004 \001(\0132\027.google.protobuf.Struct\"" + + "\331\001\n\nAgentSkill\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\021\n\004name\030" + + "\002 \001(\tB\003\340A\002\022\030\n\013description\030\003 \001(\tB\003\340A\002\022\021\n\004" + + "tags\030\004 \003(\tB\003\340A\002\022\020\n\010examples\030\005 \003(\t\022\023\n\013inp" + + "ut_modes\030\006 \003(\t\022\024\n\014output_modes\030\007 \003(\t\022=\n\025" + + "security_requirements\030\010 \003(\0132\036.lf.a2a.v1." + + "SecurityRequirement\"m\n\022AgentCardSignatur" + + "e\022\026\n\tprotected\030\001 \001(\tB\003\340A\002\022\026\n\tsignature\030\002" + + " \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\0132\027.google.proto" + + "buf.Struct\"\241\001\n\032TaskPushNotificationConfi" + + "g\022\016\n\006tenant\030\001 \001(\t\022\n\n\002id\030\002 \001(\t\022\017\n\007task_id" + + "\030\003 \001(\t\022\020\n\003url\030\004 \001(\tB\003\340A\002\022\r\n\005token\030\005 \001(\t\022" + + "5\n\016authentication\030\006 \001(\0132\035.lf.a2a.v1.Auth" + + "enticationInfo\"\032\n\nStringList\022\014\n\004list\030\001 \003" + + "(\t\"\232\001\n\023SecurityRequirement\022<\n\007schemes\030\001 " + + "\003(\0132+.lf.a2a.v1.SecurityRequirement.Sche" + + "mesEntry\032E\n\014SchemesEntry\022\013\n\003key\030\001 \001(\t\022$\n" + + "\005value\030\002 \001(\0132\025.lf.a2a.v1.StringList:\0028\001\"" + + "\200\003\n\016SecurityScheme\022B\n\027api_key_security_s" + + "cheme\030\001 \001(\0132\037.lf.a2a.v1.APIKeySecuritySc" + + "hemeH\000\022F\n\031http_auth_security_scheme\030\002 \001(" + + "\0132!.lf.a2a.v1.HTTPAuthSecuritySchemeH\000\022A" + + "\n\026oauth2_security_scheme\030\003 \001(\0132\037.lf.a2a." + + "v1.OAuth2SecuritySchemeH\000\022Q\n\037open_id_con" + + "nect_security_scheme\030\004 \001(\0132&.lf.a2a.v1.O" + + "penIdConnectSecuritySchemeH\000\022B\n\024mtls_sec" + + "urity_scheme\030\005 \001(\0132\".lf.a2a.v1.MutualTls" + + "SecuritySchemeH\000B\010\n\006scheme\"U\n\024APIKeySecu" + + "rityScheme\022\023\n\013description\030\001 \001(\t\022\025\n\010locat" + + "ion\030\002 \001(\tB\003\340A\002\022\021\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026HTT" + + "PAuthSecurityScheme\022\023\n\013description\030\001 \001(\t" + + "\022\023\n\006scheme\030\002 \001(\tB\003\340A\002\022\025\n\rbearer_format\030\003" + + " \001(\t\"s\n\024OAuth2SecurityScheme\022\023\n\013descript" + + "ion\030\001 \001(\t\022)\n\005flows\030\002 \001(\0132\025.lf.a2a.v1.OAu" + + "thFlowsB\003\340A\002\022\033\n\023oauth2_metadata_url\030\003 \001(" + + "\t\"T\n\033OpenIdConnectSecurityScheme\022\023\n\013desc" + + "ription\030\001 \001(\t\022 \n\023open_id_connect_url\030\002 \001" + + "(\tB\003\340A\002\".\n\027MutualTlsSecurityScheme\022\023\n\013de" + + "scription\030\001 \001(\t\"\301\002\n\nOAuthFlows\022C\n\022author" + + "ization_code\030\001 \001(\0132%.lf.a2a.v1.Authoriza" + + "tionCodeOAuthFlowH\000\022C\n\022client_credential" + + "s\030\002 \001(\0132%.lf.a2a.v1.ClientCredentialsOAu" + + "thFlowH\000\0224\n\010implicit\030\003 \001(\0132\034.lf.a2a.v1.I" + + "mplicitOAuthFlowB\002\030\001H\000\0224\n\010password\030\004 \001(\013" + + "2\034.lf.a2a.v1.PasswordOAuthFlowB\002\030\001H\000\0225\n\013" + + "device_code\030\005 \001(\0132\036.lf.a2a.v1.DeviceCode" + + "OAuthFlowH\000B\006\n\004flow\"\367\001\n\032AuthorizationCod" + + "eOAuthFlow\022\036\n\021authorization_url\030\001 \001(\tB\003\340" + + "A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_ur" + + "l\030\003 \001(\t\022F\n\006scopes\030\004 \003(\01321.lf.a2a.v1.Auth" + + "orizationCodeOAuthFlow.ScopesEntryB\003\340A\002\022" + + "\025\n\rpkce_required\030\005 \001(\010\032-\n\013ScopesEntry\022\013\n" + + "\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\300\001\n\032Client" + + "CredentialsOAuthFlow\022\026\n\ttoken_url\030\001 \001(\tB" + + "\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022F\n\006scopes\030\003 \003(" + + "\01321.lf.a2a.v1.ClientCredentialsOAuthFlow" + + ".ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003key\030" + + "\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\254\001\n\021ImplicitOAu" + + "thFlow\022\031\n\021authorization_url\030\001 \001(\t\022\023\n\013ref" + + "resh_url\030\002 \001(\t\0228\n\006scopes\030\003 \003(\0132(.lf.a2a." + + "v1.ImplicitOAuthFlow.ScopesEntry\032-\n\013Scop" + + "esEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"" + + "\244\001\n\021PasswordOAuthFlow\022\021\n\ttoken_url\030\001 \001(\t" + + "\022\023\n\013refresh_url\030\002 \001(\t\0228\n\006scopes\030\003 \003(\0132(." + + "lf.a2a.v1.PasswordOAuthFlow.ScopesEntry\032" + + "-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001" + + "(\t:\0028\001\"\331\001\n\023DeviceCodeOAuthFlow\022%\n\030device" + + "_authorization_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_u" + + "rl\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001(\t\022?\n\006sc" + + "opes\030\004 \003(\0132*.lf.a2a.v1.DeviceCodeOAuthFl" + + "ow.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003ke" + + "y\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\265\001\n\022SendMessa" + + "geRequest\022\016\n\006tenant\030\001 \001(\t\022(\n\007message\030\002 \001" + + "(\0132\022.lf.a2a.v1.MessageB\003\340A\002\022:\n\rconfigura" + + "tion\030\003 \001(\0132#.lf.a2a.v1.SendMessageConfig" + + "uration\022)\n\010metadata\030\004 \001(\0132\027.google.proto" + + "buf.Struct\"a\n\016GetTaskRequest\022\016\n\006tenant\030\001" + + " \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\022\033\n\016history_length\030" + + "\003 \001(\005H\000\210\001\001B\021\n\017_history_length\"\270\002\n\020ListTa" + + "sksRequest\022\016\n\006tenant\030\001 \001(\t\022\022\n\ncontext_id" + + "\030\002 \001(\t\022$\n\006status\030\003 \001(\0162\024.lf.a2a.v1.TaskS" + + "tate\022\026\n\tpage_size\030\004 \001(\005H\000\210\001\001\022\022\n\npage_tok" + + "en\030\005 \001(\t\022\033\n\016history_length\030\006 \001(\005H\001\210\001\001\022:\n" + + "\026status_timestamp_after\030\007 \001(\0132\032.google.p" + + "rotobuf.Timestamp\022\036\n\021include_artifacts\030\010" + + " \001(\010H\002\210\001\001B\014\n\n_page_sizeB\021\n\017_history_leng" + + "thB\024\n\022_include_artifacts\"\207\001\n\021ListTasksRe" + + "sponse\022#\n\005tasks\030\001 \003(\0132\017.lf.a2a.v1.TaskB\003" + + "\340A\002\022\034\n\017next_page_token\030\002 \001(\tB\003\340A\002\022\026\n\tpag" + + "e_size\030\003 \001(\005B\003\340A\002\022\027\n\ntotal_size\030\004 \001(\005B\003\340" + + "A\002\"_\n\021CancelTaskRequest\022\016\n\006tenant\030\001 \001(\t\022" + + "\017\n\002id\030\002 \001(\tB\003\340A\002\022)\n\010metadata\030\003 \001(\0132\027.goo" + + "gle.protobuf.Struct\"]\n$GetTaskPushNotifi" + + "cationConfigRequest\022\016\n\006tenant\030\001 \001(\t\022\024\n\007t" + + "ask_id\030\002 \001(\tB\003\340A\002\022\017\n\002id\030\003 \001(\tB\003\340A\002\"`\n\'De" + + "leteTaskPushNotificationConfigRequest\022\016\n" + + "\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A\002\022\017\n\002i" + + "d\030\003 \001(\tB\003\340A\002\"9\n\026SubscribeToTaskRequest\022\016" + + "\n\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\"u\n&ListT" + + "askPushNotificationConfigsRequest\022\016\n\006ten" + + "ant\030\004 \001(\t\022\024\n\007task_id\030\001 \001(\tB\003\340A\002\022\021\n\tpage_" + + "size\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t\"-\n\033GetExt" + + "endedAgentCardRequest\022\016\n\006tenant\030\001 \001(\t\"h\n" + + "\023SendMessageResponse\022\037\n\004task\030\001 \001(\0132\017.lf." + + "a2a.v1.TaskH\000\022%\n\007message\030\002 \001(\0132\022.lf.a2a." + + "v1.MessageH\000B\t\n\007payload\"\335\001\n\016StreamRespon" + + "se\022\037\n\004task\030\001 \001(\0132\017.lf.a2a.v1.TaskH\000\022%\n\007m" + + "essage\030\002 \001(\0132\022.lf.a2a.v1.MessageH\000\0229\n\rst" + + "atus_update\030\003 \001(\0132 .lf.a2a.v1.TaskStatus" + + "UpdateEventH\000\022=\n\017artifact_update\030\004 \001(\0132\"" + + ".lf.a2a.v1.TaskArtifactUpdateEventH\000B\t\n\007" + + "payload\"z\n\'ListTaskPushNotificationConfi" + + "gsResponse\0226\n\007configs\030\001 \003(\0132%.lf.a2a.v1." + + "TaskPushNotificationConfig\022\027\n\017next_page_" + + "token\030\002 \001(\t*\371\001\n\tTaskState\022\032\n\026TASK_STATE_" + + "UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMITTED\020\001\022" + + "\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_STATE_CO" + + "MPLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022\027\n\023TASK" + + "_STATE_CANCELED\020\005\022\035\n\031TASK_STATE_INPUT_RE" + + "QUIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020\007\022\034\n\030TAS" + + "K_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE_" + + "UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AGE" + + "NT\020\0022\227\017\n\nA2AService\022\203\001\n\013SendMessage\022\035.lf" + + ".a2a.v1.SendMessageRequest\032\036.lf.a2a.v1.S" + + "endMessageResponse\"5\202\323\344\223\002/\"\r/message:sen" + + "d:\001*Z\033\"\026/{tenant}/message:send:\001*\022\215\001\n\024Se" + + "ndStreamingMessage\022\035.lf.a2a.v1.SendMessa" + + "geRequest\032\031.lf.a2a.v1.StreamResponse\"9\202\323" + + "\344\223\0023\"\017/message:stream:\001*Z\035\"\030/{tenant}/me" + + "ssage:stream:\001*0\001\022k\n\007GetTask\022\031.lf.a2a.v1" + + ".GetTaskRequest\032\017.lf.a2a.v1.Task\"4\332A\002id\202" + + "\323\344\223\002)\022\r/tasks/{id=*}Z\030\022\026/{tenant}/tasks/" + + "{id=*}\022i\n\tListTasks\022\033.lf.a2a.v1.ListTask" + + "sRequest\032\034.lf.a2a.v1.ListTasksResponse\"!" + + "\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tenant}/tasks\022\200\001\n\nCa" + + "ncelTask\022\034.lf.a2a.v1.CancelTaskRequest\032\017" + + ".lf.a2a.v1.Task\"C\202\323\344\223\002=\"\024/tasks/{id=*}:c" + + "ancel:\001*Z\"\"\035/{tenant}/tasks/{id=*}:cance" + + "l:\001*\022\226\001\n\017SubscribeToTask\022!.lf.a2a.v1.Sub" + + "scribeToTaskRequest\032\031.lf.a2a.v1.StreamRe" + + "sponse\"C\202\323\344\223\002=\022\027/tasks/{id=*}:subscribeZ" + + "\"\022 /{tenant}/tasks/{id=*}:subscribe0\001\022\363\001" + + "\n CreateTaskPushNotificationConfig\022%.lf." + + "a2a.v1.TaskPushNotificationConfig\032%.lf.a" + + "2a.v1.TaskPushNotificationConfig\"\200\001\332A\016ta" + + "sk_id,config\202\323\344\223\002i\"*/tasks/{task_id=*}/p" + + "ushNotificationConfigs:\001*Z8\"3/{tenant}/t" + + "asks/{task_id=*}/pushNotificationConfigs" + + ":\001*\022\376\001\n\035GetTaskPushNotificationConfig\022/." + + "lf.a2a.v1.GetTaskPushNotificationConfigR" + + "equest\032%.lf.a2a.v1.TaskPushNotificationC" + + "onfig\"\204\001\332A\ntask_id,id\202\323\344\223\002q\0221/tasks/{tas" + + "k_id=*}/pushNotificationConfigs/{id=*}Z<" + + "\022:/{tenant}/tasks/{task_id=*}/pushNotifi" + + "cationConfigs/{id=*}\022\375\001\n\037ListTaskPushNot" + + "ificationConfigs\0221.lf.a2a.v1.ListTaskPus" + + "hNotificationConfigsRequest\0322.lf.a2a.v1." + + "ListTaskPushNotificationConfigsResponse\"" + + "s\332A\007task_id\202\323\344\223\002c\022*/tasks/{task_id=*}/pu" + + "shNotificationConfigsZ5\0223/{tenant}/tasks" + + "/{task_id=*}/pushNotificationConfigs\022\217\001\n" + + "\024GetExtendedAgentCard\022&.lf.a2a.v1.GetExt" + + "endedAgentCardRequest\032\024.lf.a2a.v1.AgentC" + + "ard\"9\202\323\344\223\0023\022\022/extendedAgentCardZ\035\022\033/{ten" + + "ant}/extendedAgentCard\022\365\001\n DeleteTaskPus" + + "hNotificationConfig\0222.lf.a2a.v1.DeleteTa" + + "skPushNotificationConfigRequest\032\026.google" + + ".protobuf.Empty\"\204\001\332A\ntask_id,id\202\323\344\223\002q*1/" + + "tasks/{task_id=*}/pushNotificationConfig" + + "s/{id=*}Z<*:/{tenant}/tasks/{task_id=*}/" + + "pushNotificationConfigs/{id=*}B=\n\013io.a2a" + + ".grpcB\003A2AP\001Z\033google.golang.org/lf/a2a/v" + + "1\252\002\tLf.A2a.V1b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -570,7 +553,7 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor, - new java.lang.String[] { "AcceptedOutputModes", "PushNotificationConfig", "HistoryLength", "Blocking", }); + new java.lang.String[] { "AcceptedOutputModes", "TaskPushNotificationConfig", "HistoryLength", "Blocking", }); internal_static_lf_a2a_v1_Task_descriptor = getDescriptor().getMessageType(1); internal_static_lf_a2a_v1_Task_fieldAccessorTable = new @@ -613,26 +596,20 @@ public static void registerAllExtensions( com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor, new java.lang.String[] { "TaskId", "ContextId", "Artifact", "Append", "LastChunk", "Metadata", }); - internal_static_lf_a2a_v1_PushNotificationConfig_descriptor = - getDescriptor().getMessageType(8); - internal_static_lf_a2a_v1_PushNotificationConfig_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_lf_a2a_v1_PushNotificationConfig_descriptor, - new java.lang.String[] { "Id", "Url", "Token", "Authentication", }); internal_static_lf_a2a_v1_AuthenticationInfo_descriptor = - getDescriptor().getMessageType(9); + getDescriptor().getMessageType(8); internal_static_lf_a2a_v1_AuthenticationInfo_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AuthenticationInfo_descriptor, new java.lang.String[] { "Scheme", "Credentials", }); internal_static_lf_a2a_v1_AgentInterface_descriptor = - getDescriptor().getMessageType(10); + getDescriptor().getMessageType(9); internal_static_lf_a2a_v1_AgentInterface_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AgentInterface_descriptor, new java.lang.String[] { "Url", "ProtocolBinding", "Tenant", "ProtocolVersion", }); internal_static_lf_a2a_v1_AgentCard_descriptor = - getDescriptor().getMessageType(11); + getDescriptor().getMessageType(10); internal_static_lf_a2a_v1_AgentCard_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AgentCard_descriptor, @@ -644,49 +621,49 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_lf_a2a_v1_AgentProvider_descriptor = - getDescriptor().getMessageType(12); + getDescriptor().getMessageType(11); internal_static_lf_a2a_v1_AgentProvider_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AgentProvider_descriptor, new java.lang.String[] { "Url", "Organization", }); internal_static_lf_a2a_v1_AgentCapabilities_descriptor = - getDescriptor().getMessageType(13); + getDescriptor().getMessageType(12); internal_static_lf_a2a_v1_AgentCapabilities_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AgentCapabilities_descriptor, new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", "ExtendedAgentCard", }); internal_static_lf_a2a_v1_AgentExtension_descriptor = - getDescriptor().getMessageType(14); + getDescriptor().getMessageType(13); internal_static_lf_a2a_v1_AgentExtension_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AgentExtension_descriptor, new java.lang.String[] { "Uri", "Description", "Required", "Params", }); internal_static_lf_a2a_v1_AgentSkill_descriptor = - getDescriptor().getMessageType(15); + getDescriptor().getMessageType(14); internal_static_lf_a2a_v1_AgentSkill_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AgentSkill_descriptor, new java.lang.String[] { "Id", "Name", "Description", "Tags", "Examples", "InputModes", "OutputModes", "SecurityRequirements", }); internal_static_lf_a2a_v1_AgentCardSignature_descriptor = - getDescriptor().getMessageType(16); + getDescriptor().getMessageType(15); internal_static_lf_a2a_v1_AgentCardSignature_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AgentCardSignature_descriptor, new java.lang.String[] { "Protected", "Signature", "Header", }); internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor = - getDescriptor().getMessageType(17); + getDescriptor().getMessageType(16); internal_static_lf_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor, - new java.lang.String[] { "Tenant", "TaskId", "PushNotificationConfig", }); + new java.lang.String[] { "Tenant", "Id", "TaskId", "Url", "Token", "Authentication", }); internal_static_lf_a2a_v1_StringList_descriptor = - getDescriptor().getMessageType(18); + getDescriptor().getMessageType(17); internal_static_lf_a2a_v1_StringList_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_StringList_descriptor, new java.lang.String[] { "List", }); internal_static_lf_a2a_v1_SecurityRequirement_descriptor = - getDescriptor().getMessageType(19); + getDescriptor().getMessageType(18); internal_static_lf_a2a_v1_SecurityRequirement_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_SecurityRequirement_descriptor, @@ -698,49 +675,49 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_lf_a2a_v1_SecurityScheme_descriptor = - getDescriptor().getMessageType(20); + getDescriptor().getMessageType(19); internal_static_lf_a2a_v1_SecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_SecurityScheme_descriptor, new java.lang.String[] { "ApiKeySecurityScheme", "HttpAuthSecurityScheme", "Oauth2SecurityScheme", "OpenIdConnectSecurityScheme", "MtlsSecurityScheme", "Scheme", }); internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor = - getDescriptor().getMessageType(21); + getDescriptor().getMessageType(20); internal_static_lf_a2a_v1_APIKeySecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor, new java.lang.String[] { "Description", "Location", "Name", }); internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor = - getDescriptor().getMessageType(22); + getDescriptor().getMessageType(21); internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor, new java.lang.String[] { "Description", "Scheme", "BearerFormat", }); internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor = - getDescriptor().getMessageType(23); + getDescriptor().getMessageType(22); internal_static_lf_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor, new java.lang.String[] { "Description", "Flows", "Oauth2MetadataUrl", }); internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor = - getDescriptor().getMessageType(24); + getDescriptor().getMessageType(23); internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor, new java.lang.String[] { "Description", "OpenIdConnectUrl", }); internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor = - getDescriptor().getMessageType(25); + getDescriptor().getMessageType(24); internal_static_lf_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor, new java.lang.String[] { "Description", }); internal_static_lf_a2a_v1_OAuthFlows_descriptor = - getDescriptor().getMessageType(26); + getDescriptor().getMessageType(25); internal_static_lf_a2a_v1_OAuthFlows_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_OAuthFlows_descriptor, new java.lang.String[] { "AuthorizationCode", "ClientCredentials", "Implicit", "Password", "DeviceCode", "Flow", }); internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor = - getDescriptor().getMessageType(27); + getDescriptor().getMessageType(26); internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor, @@ -752,7 +729,7 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor = - getDescriptor().getMessageType(28); + getDescriptor().getMessageType(27); internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor, @@ -764,7 +741,7 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor = - getDescriptor().getMessageType(29); + getDescriptor().getMessageType(28); internal_static_lf_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor, @@ -776,7 +753,7 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor = - getDescriptor().getMessageType(30); + getDescriptor().getMessageType(29); internal_static_lf_a2a_v1_PasswordOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor, @@ -788,7 +765,7 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor = - getDescriptor().getMessageType(31); + getDescriptor().getMessageType(30); internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor, @@ -800,85 +777,79 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, new java.lang.String[] { "Key", "Value", }); internal_static_lf_a2a_v1_SendMessageRequest_descriptor = - getDescriptor().getMessageType(32); + getDescriptor().getMessageType(31); internal_static_lf_a2a_v1_SendMessageRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_SendMessageRequest_descriptor, new java.lang.String[] { "Tenant", "Message", "Configuration", "Metadata", }); internal_static_lf_a2a_v1_GetTaskRequest_descriptor = - getDescriptor().getMessageType(33); + getDescriptor().getMessageType(32); internal_static_lf_a2a_v1_GetTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_GetTaskRequest_descriptor, new java.lang.String[] { "Tenant", "Id", "HistoryLength", }); internal_static_lf_a2a_v1_ListTasksRequest_descriptor = - getDescriptor().getMessageType(34); + getDescriptor().getMessageType(33); internal_static_lf_a2a_v1_ListTasksRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_ListTasksRequest_descriptor, new java.lang.String[] { "Tenant", "ContextId", "Status", "PageSize", "PageToken", "HistoryLength", "StatusTimestampAfter", "IncludeArtifacts", }); internal_static_lf_a2a_v1_ListTasksResponse_descriptor = - getDescriptor().getMessageType(35); + getDescriptor().getMessageType(34); internal_static_lf_a2a_v1_ListTasksResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_ListTasksResponse_descriptor, new java.lang.String[] { "Tasks", "NextPageToken", "PageSize", "TotalSize", }); internal_static_lf_a2a_v1_CancelTaskRequest_descriptor = - getDescriptor().getMessageType(36); + getDescriptor().getMessageType(35); internal_static_lf_a2a_v1_CancelTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_CancelTaskRequest_descriptor, new java.lang.String[] { "Tenant", "Id", "Metadata", }); internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(37); + getDescriptor().getMessageType(36); internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "TaskId", "Id", }); internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(38); + getDescriptor().getMessageType(37); internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor, new java.lang.String[] { "Tenant", "TaskId", "Id", }); - internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(39); - internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "TaskId", "Config", }); internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor = - getDescriptor().getMessageType(40); + getDescriptor().getMessageType(38); internal_static_lf_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor, new java.lang.String[] { "Tenant", "Id", }); internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor = - getDescriptor().getMessageType(41); + getDescriptor().getMessageType(39); internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor, new java.lang.String[] { "Tenant", "TaskId", "PageSize", "PageToken", }); internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor = - getDescriptor().getMessageType(42); + getDescriptor().getMessageType(40); internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor, new java.lang.String[] { "Tenant", }); internal_static_lf_a2a_v1_SendMessageResponse_descriptor = - getDescriptor().getMessageType(43); + getDescriptor().getMessageType(41); internal_static_lf_a2a_v1_SendMessageResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_SendMessageResponse_descriptor, new java.lang.String[] { "Task", "Message", "Payload", }); internal_static_lf_a2a_v1_StreamResponse_descriptor = - getDescriptor().getMessageType(44); + getDescriptor().getMessageType(42); internal_static_lf_a2a_v1_StreamResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_StreamResponse_descriptor, new java.lang.String[] { "Task", "Message", "StatusUpdate", "ArtifactUpdate", "Payload", }); internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor = - getDescriptor().getMessageType(45); + getDescriptor().getMessageType(43); internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor, diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java index b1e719d33..c4527614a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java @@ -201,27 +201,27 @@ io.a2a.grpc.StreamResponse> getSubscribeToTaskMethod() { return getSubscribeToTaskMethod; } - private static volatile io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "CreateTaskPushNotificationConfig", - requestType = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, + requestType = io.a2a.grpc.TaskPushNotificationConfig.class, responseType = io.a2a.grpc.TaskPushNotificationConfig.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; + io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod = getCreateTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "CreateTaskPushNotificationConfig")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance())) + io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("CreateTaskPushNotificationConfig")) @@ -488,11 +488,12 @@ default void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, *
              * (-- api-linter: client-libraries::4232::required-fields=disabled
              *     api-linter: core::0133::method-signature=disabled
        +     *     api-linter: core::0133::request-message-name=disabled
              *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
              * Creates a push notification config for a task.
              * 
        */ - default void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, + default void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCreateTaskPushNotificationConfigMethod(), responseObserver); } @@ -643,11 +644,12 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, *
              * (-- api-linter: client-libraries::4232::required-fields=disabled
              *     api-linter: core::0133::method-signature=disabled
        +     *     api-linter: core::0133::request-message-name=disabled
              *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
              * Creates a push notification config for a task.
              * 
        */ - public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, + public void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); @@ -787,11 +789,12 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws *
              * (-- api-linter: client-libraries::4232::required-fields=disabled
              *     api-linter: core::0133::method-signature=disabled
        +     *     api-linter: core::0133::request-message-name=disabled
              *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
              * Creates a push notification config for a task.
              * 
        */ - public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); } @@ -924,11 +927,12 @@ public java.util.Iterator subscribeToTask( *
              * (-- api-linter: client-libraries::4232::required-fields=disabled
              *     api-linter: core::0133::method-signature=disabled
        +     *     api-linter: core::0133::request-message-name=disabled
              *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
              * Creates a push notification config for a task.
              * 
        */ - public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) { + public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); } @@ -1041,12 +1045,13 @@ public com.google.common.util.concurrent.ListenableFuture canc *
              * (-- api-linter: client-libraries::4232::required-fields=disabled
              *     api-linter: core::0133::method-signature=disabled
        +     *     api-linter: core::0133::request-message-name=disabled
              *     aip.dev/not-precedent: method_signature preserved for backwards compatibility --)
              * Creates a push notification config for a task.
              * 
        */ public com.google.common.util.concurrent.ListenableFuture createTaskPushNotificationConfig( - io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) { + io.a2a.grpc.TaskPushNotificationConfig request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request); } @@ -1150,7 +1155,7 @@ public void invoke(Req request, io.grpc.stub.StreamObserver responseObserv (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.createTaskPushNotificationConfig((io.a2a.grpc.CreateTaskPushNotificationConfigRequest) request, + serviceImpl.createTaskPushNotificationConfig((io.a2a.grpc.TaskPushNotificationConfig) request, (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG: @@ -1233,7 +1238,7 @@ public static final io.grpc.ServerServiceDefinition bindService(AsyncService ser getCreateTaskPushNotificationConfigMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.CreateTaskPushNotificationConfigRequest, + io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig>( service, METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG))) .addMethod( diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java deleted file mode 100644 index d48f29694..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,943 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
        - * Represents a request for the `CreateTaskPushNotificationConfig` method.
        - * 
        - * - * Protobuf type {@code lf.a2a.v1.CreateTaskPushNotificationConfigRequest} - */ -@com.google.protobuf.Generated -public final class CreateTaskPushNotificationConfigRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) - CreateTaskPushNotificationConfigRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "CreateTaskPushNotificationConfigRequest"); - } - // Use CreateTaskPushNotificationConfigRequest.newBuilder() to construct. - private CreateTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private CreateTaskPushNotificationConfigRequest() { - tenant_ = ""; - taskId_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); - } - - private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
        -   * Optional. Tenant ID, provided as a path parameter.
        -   * 
        - * - * string tenant = 1; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
        -   * Optional. Tenant ID, provided as a path parameter.
        -   * 
        - * - * string tenant = 1; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TASK_ID_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
        -   * The parent task resource ID.
        -   * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
        -   * The parent task resource ID.
        -   * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONFIG_FIELD_NUMBER = 3; - private io.a2a.grpc.PushNotificationConfig config_; - /** - *
        -   * The configuration to create.
        -   * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the config field is set. - */ - @java.lang.Override - public boolean hasConfig() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
        -   * The configuration to create.
        -   * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The config. - */ - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getConfig() { - return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; - } - /** - *
        -   * The configuration to create.
        -   * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { - return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, taskId_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(3, getConfig()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, taskId_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getConfig()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest)) { - return super.equals(obj); - } - io.a2a.grpc.CreateTaskPushNotificationConfigRequest other = (io.a2a.grpc.CreateTaskPushNotificationConfigRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (hasConfig() != other.hasConfig()) return false; - if (hasConfig()) { - if (!getConfig() - .equals(other.getConfig())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - if (hasConfig()) { - hash = (37 * hash) + CONFIG_FIELD_NUMBER; - hash = (53 * hash) + getConfig().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.CreateTaskPushNotificationConfigRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
        -   * Represents a request for the `CreateTaskPushNotificationConfig` method.
        -   * 
        - * - * Protobuf type {@code lf.a2a.v1.CreateTaskPushNotificationConfigRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) - io.a2a.grpc.CreateTaskPushNotificationConfigRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); - } - - // Construct using io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetConfigFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - taskId_ = ""; - config_ = null; - if (configBuilder_ != null) { - configBuilder_.dispose(); - configBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.CreateTaskPushNotificationConfigRequest build() { - io.a2a.grpc.CreateTaskPushNotificationConfigRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.CreateTaskPushNotificationConfigRequest buildPartial() { - io.a2a.grpc.CreateTaskPushNotificationConfigRequest result = new io.a2a.grpc.CreateTaskPushNotificationConfigRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.CreateTaskPushNotificationConfigRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.taskId_ = taskId_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000004) != 0)) { - result.config_ = configBuilder_ == null - ? config_ - : configBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest) { - return mergeFrom((io.a2a.grpc.CreateTaskPushNotificationConfigRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.CreateTaskPushNotificationConfigRequest other) { - if (other == io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.hasConfig()) { - mergeConfig(other.getConfig()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetConfigFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
        -     * Optional. Tenant ID, provided as a path parameter.
        -     * 
        - * - * string tenant = 1; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
        -     * Optional. Tenant ID, provided as a path parameter.
        -     * 
        - * - * string tenant = 1; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
        -     * Optional. Tenant ID, provided as a path parameter.
        -     * 
        - * - * string tenant = 1; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
        -     * Optional. Tenant ID, provided as a path parameter.
        -     * 
        - * - * string tenant = 1; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
        -     * Optional. Tenant ID, provided as a path parameter.
        -     * 
        - * - * string tenant = 1; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object taskId_ = ""; - /** - *
        -     * The parent task resource ID.
        -     * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
        -     * The parent task resource ID.
        -     * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
        -     * The parent task resource ID.
        -     * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
        -     * The parent task resource ID.
        -     * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
        -     * The parent task resource ID.
        -     * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private io.a2a.grpc.PushNotificationConfig config_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> configBuilder_; - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the config field is set. - */ - public boolean hasConfig() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The config. - */ - public io.a2a.grpc.PushNotificationConfig getConfig() { - if (configBuilder_ == null) { - return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; - } else { - return configBuilder_.getMessage(); - } - } - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setConfig(io.a2a.grpc.PushNotificationConfig value) { - if (configBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - config_ = value; - } else { - configBuilder_.setMessage(value); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setConfig( - io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { - if (configBuilder_ == null) { - config_ = builderForValue.build(); - } else { - configBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeConfig(io.a2a.grpc.PushNotificationConfig value) { - if (configBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0) && - config_ != null && - config_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { - getConfigBuilder().mergeFrom(value); - } else { - config_ = value; - } - } else { - configBuilder_.mergeFrom(value); - } - if (config_ != null) { - bitField0_ |= 0x00000004; - onChanged(); - } - return this; - } - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearConfig() { - bitField0_ = (bitField0_ & ~0x00000004); - config_ = null; - if (configBuilder_ != null) { - configBuilder_.dispose(); - configBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.PushNotificationConfig.Builder getConfigBuilder() { - bitField0_ |= 0x00000004; - onChanged(); - return internalGetConfigFieldBuilder().getBuilder(); - } - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { - if (configBuilder_ != null) { - return configBuilder_.getMessageOrBuilder(); - } else { - return config_ == null ? - io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; - } - } - /** - *
        -     * The configuration to create.
        -     * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> - internalGetConfigFieldBuilder() { - if (configBuilder_ == null) { - configBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder>( - getConfig(), - getParentForChildren(), - isClean()); - config_ = null; - } - return configBuilder_; - } - - // @@protoc_insertion_point(builder_scope:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) - } - - // @@protoc_insertion_point(class_scope:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) - private static final io.a2a.grpc.CreateTaskPushNotificationConfigRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.CreateTaskPushNotificationConfigRequest(); - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public CreateTaskPushNotificationConfigRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java deleted file mode 100644 index d8863657e..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java +++ /dev/null @@ -1,79 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface CreateTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:lf.a2a.v1.CreateTaskPushNotificationConfigRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
        -   * Optional. Tenant ID, provided as a path parameter.
        -   * 
        - * - * string tenant = 1; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
        -   * Optional. Tenant ID, provided as a path parameter.
        -   * 
        - * - * string tenant = 1; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
        -   * The parent task resource ID.
        -   * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
        -   * The parent task resource ID.
        -   * 
        - * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
        -   * The configuration to create.
        -   * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the config field is set. - */ - boolean hasConfig(); - /** - *
        -   * The configuration to create.
        -   * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The config. - */ - io.a2a.grpc.PushNotificationConfig getConfig(); - /** - *
        -   * The configuration to create.
        -   * 
        - * - * .lf.a2a.v1.PushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java index ab013c822..e512a7f46 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java @@ -189,7 +189,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=570 + * See a2a.proto;l=567 * @return Whether the implicit field is set. */ @java.lang.Override @@ -203,7 +203,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=570 + * See a2a.proto;l=567 * @return The implicit. */ @java.lang.Override @@ -236,7 +236,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=572 + * See a2a.proto;l=569 * @return Whether the password field is set. */ @java.lang.Override @@ -250,7 +250,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=572 + * See a2a.proto;l=569 * @return The password. */ @java.lang.Override @@ -1159,7 +1159,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=570 + * See a2a.proto;l=567 * @return Whether the implicit field is set. */ @java.lang.Override @@ -1173,7 +1173,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=570 + * See a2a.proto;l=567 * @return The implicit. */ @java.lang.Override @@ -1341,7 +1341,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=572 + * See a2a.proto;l=569 * @return Whether the password field is set. */ @java.lang.Override @@ -1355,7 +1355,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=572 + * See a2a.proto;l=569 * @return The password. */ @java.lang.Override diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java index b4c4a30fc..d4ee7267c 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java @@ -71,7 +71,7 @@ public interface OAuthFlowsOrBuilder extends * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=570 + * See a2a.proto;l=567 * @return Whether the implicit field is set. */ @java.lang.Deprecated boolean hasImplicit(); @@ -82,7 +82,7 @@ public interface OAuthFlowsOrBuilder extends * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=570 + * See a2a.proto;l=567 * @return The implicit. */ @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlow getImplicit(); @@ -102,7 +102,7 @@ public interface OAuthFlowsOrBuilder extends * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=572 + * See a2a.proto;l=569 * @return Whether the password field is set. */ @java.lang.Deprecated boolean hasPassword(); @@ -113,7 +113,7 @@ public interface OAuthFlowsOrBuilder extends * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=572 + * See a2a.proto;l=569 * @return The password. */ @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlow getPassword(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java deleted file mode 100644 index e5a4960a4..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java +++ /dev/null @@ -1,1107 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
        - * Configuration for setting up push notifications for task updates.
        - * 
        - * - * Protobuf type {@code lf.a2a.v1.PushNotificationConfig} - */ -@com.google.protobuf.Generated -public final class PushNotificationConfig extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:lf.a2a.v1.PushNotificationConfig) - PushNotificationConfigOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "PushNotificationConfig"); - } - // Use PushNotificationConfig.newBuilder() to construct. - private PushNotificationConfig(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private PushNotificationConfig() { - id_ = ""; - url_ = ""; - token_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.PushNotificationConfig.class, io.a2a.grpc.PushNotificationConfig.Builder.class); - } - - private int bitField0_; - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
        -   * A unique identifier (e.g. UUID) for this push notification configuration.
        -   * 
        - * - * string id = 1; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
        -   * A unique identifier (e.g. UUID) for this push notification configuration.
        -   * 
        - * - * string id = 1; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object url_ = ""; - /** - *
        -   * The URL where the notification should be sent.
        -   * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - @java.lang.Override - public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } - } - /** - *
        -   * The URL where the notification should be sent.
        -   * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TOKEN_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object token_ = ""; - /** - *
        -   * A token unique for this task or session.
        -   * 
        - * - * string token = 3; - * @return The token. - */ - @java.lang.Override - public java.lang.String getToken() { - java.lang.Object ref = token_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - token_ = s; - return s; - } - } - /** - *
        -   * A token unique for this task or session.
        -   * 
        - * - * string token = 3; - * @return The bytes for token. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTokenBytes() { - java.lang.Object ref = token_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - token_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int AUTHENTICATION_FIELD_NUMBER = 4; - private io.a2a.grpc.AuthenticationInfo authentication_; - /** - *
        -   * Authentication information required to send the notification.
        -   * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - * @return Whether the authentication field is set. - */ - @java.lang.Override - public boolean hasAuthentication() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
        -   * Authentication information required to send the notification.
        -   * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - * @return The authentication. - */ - @java.lang.Override - public io.a2a.grpc.AuthenticationInfo getAuthentication() { - return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; - } - /** - *
        -   * Authentication information required to send the notification.
        -   * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - @java.lang.Override - public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { - return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, url_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(token_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, token_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(4, getAuthentication()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, url_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(token_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, token_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, getAuthentication()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.PushNotificationConfig)) { - return super.equals(obj); - } - io.a2a.grpc.PushNotificationConfig other = (io.a2a.grpc.PushNotificationConfig) obj; - - if (!getId() - .equals(other.getId())) return false; - if (!getUrl() - .equals(other.getUrl())) return false; - if (!getToken() - .equals(other.getToken())) return false; - if (hasAuthentication() != other.hasAuthentication()) return false; - if (hasAuthentication()) { - if (!getAuthentication() - .equals(other.getAuthentication())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (37 * hash) + URL_FIELD_NUMBER; - hash = (53 * hash) + getUrl().hashCode(); - hash = (37 * hash) + TOKEN_FIELD_NUMBER; - hash = (53 * hash) + getToken().hashCode(); - if (hasAuthentication()) { - hash = (37 * hash) + AUTHENTICATION_FIELD_NUMBER; - hash = (53 * hash) + getAuthentication().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.PushNotificationConfig parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.PushNotificationConfig parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.PushNotificationConfig parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.PushNotificationConfig prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
        -   * Configuration for setting up push notifications for task updates.
        -   * 
        - * - * Protobuf type {@code lf.a2a.v1.PushNotificationConfig} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:lf.a2a.v1.PushNotificationConfig) - io.a2a.grpc.PushNotificationConfigOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.PushNotificationConfig.class, io.a2a.grpc.PushNotificationConfig.Builder.class); - } - - // Construct using io.a2a.grpc.PushNotificationConfig.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetAuthenticationFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - id_ = ""; - url_ = ""; - token_ = ""; - authentication_ = null; - if (authenticationBuilder_ != null) { - authenticationBuilder_.dispose(); - authenticationBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PushNotificationConfig_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getDefaultInstanceForType() { - return io.a2a.grpc.PushNotificationConfig.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig build() { - io.a2a.grpc.PushNotificationConfig result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig buildPartial() { - io.a2a.grpc.PushNotificationConfig result = new io.a2a.grpc.PushNotificationConfig(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.PushNotificationConfig result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.id_ = id_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.url_ = url_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.token_ = token_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { - result.authentication_ = authenticationBuilder_ == null - ? authentication_ - : authenticationBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.PushNotificationConfig) { - return mergeFrom((io.a2a.grpc.PushNotificationConfig)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.PushNotificationConfig other) { - if (other == io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) return this; - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getUrl().isEmpty()) { - url_ = other.url_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getToken().isEmpty()) { - token_ = other.token_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (other.hasAuthentication()) { - mergeAuthentication(other.getAuthentication()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - url_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - token_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - input.readMessage( - internalGetAuthenticationFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object id_ = ""; - /** - *
        -     * A unique identifier (e.g. UUID) for this push notification configuration.
        -     * 
        - * - * string id = 1; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
        -     * A unique identifier (e.g. UUID) for this push notification configuration.
        -     * 
        - * - * string id = 1; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
        -     * A unique identifier (e.g. UUID) for this push notification configuration.
        -     * 
        - * - * string id = 1; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
        -     * A unique identifier (e.g. UUID) for this push notification configuration.
        -     * 
        - * - * string id = 1; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
        -     * A unique identifier (e.g. UUID) for this push notification configuration.
        -     * 
        - * - * string id = 1; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object url_ = ""; - /** - *
        -     * The URL where the notification should be sent.
        -     * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
        -     * The URL where the notification should be sent.
        -     * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
        -     * The URL where the notification should be sent.
        -     * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The url to set. - * @return This builder for chaining. - */ - public Builder setUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - url_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
        -     * The URL where the notification should be sent.
        -     * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearUrl() { - url_ = getDefaultInstance().getUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
        -     * The URL where the notification should be sent.
        -     * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for url to set. - * @return This builder for chaining. - */ - public Builder setUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - url_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object token_ = ""; - /** - *
        -     * A token unique for this task or session.
        -     * 
        - * - * string token = 3; - * @return The token. - */ - public java.lang.String getToken() { - java.lang.Object ref = token_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - token_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
        -     * A token unique for this task or session.
        -     * 
        - * - * string token = 3; - * @return The bytes for token. - */ - public com.google.protobuf.ByteString - getTokenBytes() { - java.lang.Object ref = token_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - token_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
        -     * A token unique for this task or session.
        -     * 
        - * - * string token = 3; - * @param value The token to set. - * @return This builder for chaining. - */ - public Builder setToken( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - token_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
        -     * A token unique for this task or session.
        -     * 
        - * - * string token = 3; - * @return This builder for chaining. - */ - public Builder clearToken() { - token_ = getDefaultInstance().getToken(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
        -     * A token unique for this task or session.
        -     * 
        - * - * string token = 3; - * @param value The bytes for token to set. - * @return This builder for chaining. - */ - public Builder setTokenBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - token_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private io.a2a.grpc.AuthenticationInfo authentication_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> authenticationBuilder_; - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - * @return Whether the authentication field is set. - */ - public boolean hasAuthentication() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - * @return The authentication. - */ - public io.a2a.grpc.AuthenticationInfo getAuthentication() { - if (authenticationBuilder_ == null) { - return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; - } else { - return authenticationBuilder_.getMessage(); - } - } - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - public Builder setAuthentication(io.a2a.grpc.AuthenticationInfo value) { - if (authenticationBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - authentication_ = value; - } else { - authenticationBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - public Builder setAuthentication( - io.a2a.grpc.AuthenticationInfo.Builder builderForValue) { - if (authenticationBuilder_ == null) { - authentication_ = builderForValue.build(); - } else { - authenticationBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - public Builder mergeAuthentication(io.a2a.grpc.AuthenticationInfo value) { - if (authenticationBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && - authentication_ != null && - authentication_ != io.a2a.grpc.AuthenticationInfo.getDefaultInstance()) { - getAuthenticationBuilder().mergeFrom(value); - } else { - authentication_ = value; - } - } else { - authenticationBuilder_.mergeFrom(value); - } - if (authentication_ != null) { - bitField0_ |= 0x00000008; - onChanged(); - } - return this; - } - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - public Builder clearAuthentication() { - bitField0_ = (bitField0_ & ~0x00000008); - authentication_ = null; - if (authenticationBuilder_ != null) { - authenticationBuilder_.dispose(); - authenticationBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - public io.a2a.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return internalGetAuthenticationFieldBuilder().getBuilder(); - } - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { - if (authenticationBuilder_ != null) { - return authenticationBuilder_.getMessageOrBuilder(); - } else { - return authentication_ == null ? - io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; - } - } - /** - *
        -     * Authentication information required to send the notification.
        -     * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> - internalGetAuthenticationFieldBuilder() { - if (authenticationBuilder_ == null) { - authenticationBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder>( - getAuthentication(), - getParentForChildren(), - isClean()); - authentication_ = null; - } - return authenticationBuilder_; - } - - // @@protoc_insertion_point(builder_scope:lf.a2a.v1.PushNotificationConfig) - } - - // @@protoc_insertion_point(class_scope:lf.a2a.v1.PushNotificationConfig) - private static final io.a2a.grpc.PushNotificationConfig DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.PushNotificationConfig(); - } - - public static io.a2a.grpc.PushNotificationConfig getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public PushNotificationConfig parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java deleted file mode 100644 index 74c6127b1..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java +++ /dev/null @@ -1,99 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface PushNotificationConfigOrBuilder extends - // @@protoc_insertion_point(interface_extends:lf.a2a.v1.PushNotificationConfig) - com.google.protobuf.MessageOrBuilder { - - /** - *
        -   * A unique identifier (e.g. UUID) for this push notification configuration.
        -   * 
        - * - * string id = 1; - * @return The id. - */ - java.lang.String getId(); - /** - *
        -   * A unique identifier (e.g. UUID) for this push notification configuration.
        -   * 
        - * - * string id = 1; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - *
        -   * The URL where the notification should be sent.
        -   * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - java.lang.String getUrl(); - /** - *
        -   * The URL where the notification should be sent.
        -   * 
        - * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - com.google.protobuf.ByteString - getUrlBytes(); - - /** - *
        -   * A token unique for this task or session.
        -   * 
        - * - * string token = 3; - * @return The token. - */ - java.lang.String getToken(); - /** - *
        -   * A token unique for this task or session.
        -   * 
        - * - * string token = 3; - * @return The bytes for token. - */ - com.google.protobuf.ByteString - getTokenBytes(); - - /** - *
        -   * Authentication information required to send the notification.
        -   * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - * @return Whether the authentication field is set. - */ - boolean hasAuthentication(); - /** - *
        -   * Authentication information required to send the notification.
        -   * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - * @return The authentication. - */ - io.a2a.grpc.AuthenticationInfo getAuthentication(); - /** - *
        -   * Authentication information required to send the notification.
        -   * 
        - * - * .lf.a2a.v1.AuthenticationInfo authentication = 4; - */ - io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java index f89c54f1a..c622316de 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java @@ -107,42 +107,45 @@ public java.lang.String getAcceptedOutputModes(int index) { return acceptedOutputModes_.getByteString(index); } - public static final int PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 2; - private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; + public static final int TASK_PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 2; + private io.a2a.grpc.TaskPushNotificationConfig taskPushNotificationConfig_; /** *
            * Configuration for the agent to send push notifications for task updates.
        +   * Task id should be empty when sending this configuration in a `SendMessage` request.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return Whether the pushNotificationConfig field is set. + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; + * @return Whether the taskPushNotificationConfig field is set. */ @java.lang.Override - public boolean hasPushNotificationConfig() { + public boolean hasTaskPushNotificationConfig() { return ((bitField0_ & 0x00000001) != 0); } /** *
            * Configuration for the agent to send push notifications for task updates.
        +   * Task id should be empty when sending this configuration in a `SendMessage` request.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return The pushNotificationConfig. + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; + * @return The taskPushNotificationConfig. */ @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig() { + return taskPushNotificationConfig_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_; } /** *
            * Configuration for the agent to send push notifications for task updates.
        +   * Task id should be empty when sending this configuration in a `SendMessage` request.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ @java.lang.Override - public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder() { + return taskPushNotificationConfig_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_; } public static final int HISTORY_LENGTH_FIELD_NUMBER = 3; @@ -213,7 +216,7 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) com.google.protobuf.GeneratedMessage.writeString(output, 1, acceptedOutputModes_.getRaw(i)); } if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(2, getPushNotificationConfig()); + output.writeMessage(2, getTaskPushNotificationConfig()); } if (((bitField0_ & 0x00000002) != 0)) { output.writeInt32(3, historyLength_); @@ -240,7 +243,7 @@ public int getSerializedSize() { } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getPushNotificationConfig()); + .computeMessageSize(2, getTaskPushNotificationConfig()); } if (((bitField0_ & 0x00000002) != 0)) { size += com.google.protobuf.CodedOutputStream @@ -267,10 +270,10 @@ public boolean equals(final java.lang.Object obj) { if (!getAcceptedOutputModesList() .equals(other.getAcceptedOutputModesList())) return false; - if (hasPushNotificationConfig() != other.hasPushNotificationConfig()) return false; - if (hasPushNotificationConfig()) { - if (!getPushNotificationConfig() - .equals(other.getPushNotificationConfig())) return false; + if (hasTaskPushNotificationConfig() != other.hasTaskPushNotificationConfig()) return false; + if (hasTaskPushNotificationConfig()) { + if (!getTaskPushNotificationConfig() + .equals(other.getTaskPushNotificationConfig())) return false; } if (hasHistoryLength() != other.hasHistoryLength()) return false; if (hasHistoryLength()) { @@ -294,9 +297,9 @@ public int hashCode() { hash = (37 * hash) + ACCEPTED_OUTPUT_MODES_FIELD_NUMBER; hash = (53 * hash) + getAcceptedOutputModesList().hashCode(); } - if (hasPushNotificationConfig()) { - hash = (37 * hash) + PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER; - hash = (53 * hash) + getPushNotificationConfig().hashCode(); + if (hasTaskPushNotificationConfig()) { + hash = (37 * hash) + TASK_PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER; + hash = (53 * hash) + getTaskPushNotificationConfig().hashCode(); } if (hasHistoryLength()) { hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER; @@ -439,7 +442,7 @@ private Builder( private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessage .alwaysUseFieldBuilders) { - internalGetPushNotificationConfigFieldBuilder(); + internalGetTaskPushNotificationConfigFieldBuilder(); } } @java.lang.Override @@ -448,10 +451,10 @@ public Builder clear() { bitField0_ = 0; acceptedOutputModes_ = com.google.protobuf.LazyStringArrayList.emptyList(); - pushNotificationConfig_ = null; - if (pushNotificationConfigBuilder_ != null) { - pushNotificationConfigBuilder_.dispose(); - pushNotificationConfigBuilder_ = null; + taskPushNotificationConfig_ = null; + if (taskPushNotificationConfigBuilder_ != null) { + taskPushNotificationConfigBuilder_.dispose(); + taskPushNotificationConfigBuilder_ = null; } historyLength_ = 0; blocking_ = false; @@ -494,9 +497,9 @@ private void buildPartial0(io.a2a.grpc.SendMessageConfiguration result) { } int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000002) != 0)) { - result.pushNotificationConfig_ = pushNotificationConfigBuilder_ == null - ? pushNotificationConfig_ - : pushNotificationConfigBuilder_.build(); + result.taskPushNotificationConfig_ = taskPushNotificationConfigBuilder_ == null + ? taskPushNotificationConfig_ + : taskPushNotificationConfigBuilder_.build(); to_bitField0_ |= 0x00000001; } if (((from_bitField0_ & 0x00000004) != 0)) { @@ -531,8 +534,8 @@ public Builder mergeFrom(io.a2a.grpc.SendMessageConfiguration other) { } onChanged(); } - if (other.hasPushNotificationConfig()) { - mergePushNotificationConfig(other.getPushNotificationConfig()); + if (other.hasTaskPushNotificationConfig()) { + mergeTaskPushNotificationConfig(other.getTaskPushNotificationConfig()); } if (other.hasHistoryLength()) { setHistoryLength(other.getHistoryLength()); @@ -574,7 +577,7 @@ public Builder mergeFrom( } // case 10 case 18: { input.readMessage( - internalGetPushNotificationConfigFieldBuilder().getBuilder(), + internalGetTaskPushNotificationConfigFieldBuilder().getBuilder(), extensionRegistry); bitField0_ |= 0x00000002; break; @@ -762,50 +765,53 @@ public Builder addAcceptedOutputModesBytes( return this; } - private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; + private io.a2a.grpc.TaskPushNotificationConfig taskPushNotificationConfig_; private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> pushNotificationConfigBuilder_; + io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> taskPushNotificationConfigBuilder_; /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return Whether the pushNotificationConfig field is set. + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; + * @return Whether the taskPushNotificationConfig field is set. */ - public boolean hasPushNotificationConfig() { + public boolean hasTaskPushNotificationConfig() { return ((bitField0_ & 0x00000002) != 0); } /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return The pushNotificationConfig. + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; + * @return The taskPushNotificationConfig. */ - public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { - if (pushNotificationConfigBuilder_ == null) { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig() { + if (taskPushNotificationConfigBuilder_ == null) { + return taskPushNotificationConfig_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_; } else { - return pushNotificationConfigBuilder_.getMessage(); + return taskPushNotificationConfigBuilder_.getMessage(); } } /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ - public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { - if (pushNotificationConfigBuilder_ == null) { + public Builder setTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig value) { + if (taskPushNotificationConfigBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - pushNotificationConfig_ = value; + taskPushNotificationConfig_ = value; } else { - pushNotificationConfigBuilder_.setMessage(value); + taskPushNotificationConfigBuilder_.setMessage(value); } bitField0_ |= 0x00000002; onChanged(); @@ -814,16 +820,17 @@ public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig valu /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ - public Builder setPushNotificationConfig( - io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { - if (pushNotificationConfigBuilder_ == null) { - pushNotificationConfig_ = builderForValue.build(); + public Builder setTaskPushNotificationConfig( + io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) { + if (taskPushNotificationConfigBuilder_ == null) { + taskPushNotificationConfig_ = builderForValue.build(); } else { - pushNotificationConfigBuilder_.setMessage(builderForValue.build()); + taskPushNotificationConfigBuilder_.setMessage(builderForValue.build()); } bitField0_ |= 0x00000002; onChanged(); @@ -832,23 +839,24 @@ public Builder setPushNotificationConfig( /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ - public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { - if (pushNotificationConfigBuilder_ == null) { + public Builder mergeTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig value) { + if (taskPushNotificationConfigBuilder_ == null) { if (((bitField0_ & 0x00000002) != 0) && - pushNotificationConfig_ != null && - pushNotificationConfig_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { - getPushNotificationConfigBuilder().mergeFrom(value); + taskPushNotificationConfig_ != null && + taskPushNotificationConfig_ != io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance()) { + getTaskPushNotificationConfigBuilder().mergeFrom(value); } else { - pushNotificationConfig_ = value; + taskPushNotificationConfig_ = value; } } else { - pushNotificationConfigBuilder_.mergeFrom(value); + taskPushNotificationConfigBuilder_.mergeFrom(value); } - if (pushNotificationConfig_ != null) { + if (taskPushNotificationConfig_ != null) { bitField0_ |= 0x00000002; onChanged(); } @@ -857,16 +865,17 @@ public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig va /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ - public Builder clearPushNotificationConfig() { + public Builder clearTaskPushNotificationConfig() { bitField0_ = (bitField0_ & ~0x00000002); - pushNotificationConfig_ = null; - if (pushNotificationConfigBuilder_ != null) { - pushNotificationConfigBuilder_.dispose(); - pushNotificationConfigBuilder_ = null; + taskPushNotificationConfig_ = null; + if (taskPushNotificationConfigBuilder_ != null) { + taskPushNotificationConfigBuilder_.dispose(); + taskPushNotificationConfigBuilder_ = null; } onChanged(); return this; @@ -874,49 +883,52 @@ public Builder clearPushNotificationConfig() { /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ - public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuilder() { + public io.a2a.grpc.TaskPushNotificationConfig.Builder getTaskPushNotificationConfigBuilder() { bitField0_ |= 0x00000002; onChanged(); - return internalGetPushNotificationConfigFieldBuilder().getBuilder(); + return internalGetTaskPushNotificationConfigFieldBuilder().getBuilder(); } /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ - public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { - if (pushNotificationConfigBuilder_ != null) { - return pushNotificationConfigBuilder_.getMessageOrBuilder(); + public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder() { + if (taskPushNotificationConfigBuilder_ != null) { + return taskPushNotificationConfigBuilder_.getMessageOrBuilder(); } else { - return pushNotificationConfig_ == null ? - io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + return taskPushNotificationConfig_ == null ? + io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_; } } /** *
              * Configuration for the agent to send push notifications for task updates.
        +     * Task id should be empty when sending this configuration in a `SendMessage` request.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> - internalGetPushNotificationConfigFieldBuilder() { - if (pushNotificationConfigBuilder_ == null) { - pushNotificationConfigBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder>( - getPushNotificationConfig(), + io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> + internalGetTaskPushNotificationConfigFieldBuilder() { + if (taskPushNotificationConfigBuilder_ == null) { + taskPushNotificationConfigBuilder_ = new com.google.protobuf.SingleFieldBuilder< + io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder>( + getTaskPushNotificationConfig(), getParentForChildren(), isClean()); - pushNotificationConfig_ = null; + taskPushNotificationConfig_ = null; } - return pushNotificationConfigBuilder_; + return taskPushNotificationConfigBuilder_; } private int historyLength_ ; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java index 555708a45..3607e9093 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java @@ -58,29 +58,32 @@ public interface SendMessageConfigurationOrBuilder extends /** *
            * Configuration for the agent to send push notifications for task updates.
        +   * Task id should be empty when sending this configuration in a `SendMessage` request.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return Whether the pushNotificationConfig field is set. + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; + * @return Whether the taskPushNotificationConfig field is set. */ - boolean hasPushNotificationConfig(); + boolean hasTaskPushNotificationConfig(); /** *
            * Configuration for the agent to send push notifications for task updates.
        +   * Task id should be empty when sending this configuration in a `SendMessage` request.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return The pushNotificationConfig. + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; + * @return The taskPushNotificationConfig. */ - io.a2a.grpc.PushNotificationConfig getPushNotificationConfig(); + io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(); /** *
            * Configuration for the agent to send push notifications for task updates.
        +   * Task id should be empty when sending this configuration in a `SendMessage` request.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 2; + * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2; */ - io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder(); + io.a2a.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder(); /** *
        diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Task.java b/spec-grpc/src/main/java/io/a2a/grpc/Task.java
        index 87c24f027..7b0d12ca4 100644
        --- a/spec-grpc/src/main/java/io/a2a/grpc/Task.java
        +++ b/spec-grpc/src/main/java/io/a2a/grpc/Task.java
        @@ -110,10 +110,10 @@ public java.lang.String getId() {
           /**
            * 
            * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -   * (tasks and messages). Created by the A2A server.
        +   * (tasks and messages).
            * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @return The contextId. */ @java.lang.Override @@ -132,10 +132,10 @@ public java.lang.String getContextId() { /** *
            * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -   * (tasks and messages). Created by the A2A server.
        +   * (tasks and messages).
            * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @return The bytes for contextId. */ @java.lang.Override @@ -1010,10 +1010,10 @@ public Builder setIdBytes( /** *
              * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -     * (tasks and messages). Created by the A2A server.
        +     * (tasks and messages).
              * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @return The contextId. */ public java.lang.String getContextId() { @@ -1031,10 +1031,10 @@ public java.lang.String getContextId() { /** *
              * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -     * (tasks and messages). Created by the A2A server.
        +     * (tasks and messages).
              * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @return The bytes for contextId. */ public com.google.protobuf.ByteString @@ -1053,10 +1053,10 @@ public java.lang.String getContextId() { /** *
              * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -     * (tasks and messages). Created by the A2A server.
        +     * (tasks and messages).
              * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @param value The contextId to set. * @return This builder for chaining. */ @@ -1071,10 +1071,10 @@ public Builder setContextId( /** *
              * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -     * (tasks and messages). Created by the A2A server.
        +     * (tasks and messages).
              * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @return This builder for chaining. */ public Builder clearContextId() { @@ -1086,10 +1086,10 @@ public Builder clearContextId() { /** *
              * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -     * (tasks and messages). Created by the A2A server.
        +     * (tasks and messages).
              * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @param value The bytes for contextId to set. * @return This builder for chaining. */ diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java index cdca99dcf..09bdfc0ab 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java @@ -35,20 +35,20 @@ public interface TaskOrBuilder extends /** *
            * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -   * (tasks and messages). Created by the A2A server.
        +   * (tasks and messages).
            * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @return The contextId. */ java.lang.String getContextId(); /** *
            * Unique identifier (e.g. UUID) for the contextual collection of interactions
        -   * (tasks and messages). Created by the A2A server.
        +   * (tasks and messages).
            * 
        * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string context_id = 2; * @return The bytes for contextId. */ com.google.protobuf.ByteString diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java index fdf27bc57..a523424f3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java @@ -33,7 +33,10 @@ private TaskPushNotificationConfig(com.google.protobuf.GeneratedMessage.Builder< } private TaskPushNotificationConfig() { tenant_ = ""; + id_ = ""; taskId_ = ""; + url_ = ""; + token_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -97,7 +100,56 @@ public java.lang.String getTenant() { } } - public static final int TASK_ID_FIELD_NUMBER = 2; + public static final int ID_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object id_ = ""; + /** + *
        +   * The push notification configuration details.
        +   * A unique identifier (e.g. UUID) for this push notification configuration.
        +   * 
        + * + * string id = 2; + * @return The id. + */ + @java.lang.Override + public java.lang.String getId() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + *
        +   * The push notification configuration details.
        +   * A unique identifier (e.g. UUID) for this push notification configuration.
        +   * 
        + * + * string id = 2; + * @return The bytes for id. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TASK_ID_FIELD_NUMBER = 3; @SuppressWarnings("serial") private volatile java.lang.Object taskId_ = ""; /** @@ -105,7 +157,7 @@ public java.lang.String getTenant() { * The ID of the task this configuration is associated with. *
        * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @return The taskId. */ @java.lang.Override @@ -126,7 +178,7 @@ public java.lang.String getTaskId() { * The ID of the task this configuration is associated with. * * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @return The bytes for taskId. */ @java.lang.Override @@ -144,42 +196,136 @@ public java.lang.String getTaskId() { } } - public static final int PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 3; - private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; + public static final int URL_FIELD_NUMBER = 4; + @SuppressWarnings("serial") + private volatile java.lang.Object url_ = ""; /** *
        -   * The push notification configuration details.
        +   * The URL where the notification should be sent.
        +   * 
        + * + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The url. + */ + @java.lang.Override + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } + } + /** + *
        +   * The URL where the notification should be sent.
        +   * 
        + * + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for url. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TOKEN_FIELD_NUMBER = 5; + @SuppressWarnings("serial") + private volatile java.lang.Object token_ = ""; + /** + *
        +   * A token unique for this task or session.
        +   * 
        + * + * string token = 5; + * @return The token. + */ + @java.lang.Override + public java.lang.String getToken() { + java.lang.Object ref = token_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + token_ = s; + return s; + } + } + /** + *
        +   * A token unique for this task or session.
        +   * 
        + * + * string token = 5; + * @return The bytes for token. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTokenBytes() { + java.lang.Object ref = token_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + token_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int AUTHENTICATION_FIELD_NUMBER = 6; + private io.a2a.grpc.AuthenticationInfo authentication_; + /** + *
        +   * Authentication information required to send the notification.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the pushNotificationConfig field is set. + * .lf.a2a.v1.AuthenticationInfo authentication = 6; + * @return Whether the authentication field is set. */ @java.lang.Override - public boolean hasPushNotificationConfig() { + public boolean hasAuthentication() { return ((bitField0_ & 0x00000001) != 0); } /** *
        -   * The push notification configuration details.
        +   * Authentication information required to send the notification.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The pushNotificationConfig. + * .lf.a2a.v1.AuthenticationInfo authentication = 6; + * @return The authentication. */ @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + public io.a2a.grpc.AuthenticationInfo getAuthentication() { + return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; } /** *
        -   * The push notification configuration details.
        +   * Authentication information required to send the notification.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ @java.lang.Override - public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { + return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; } private byte memoizedIsInitialized = -1; @@ -199,11 +345,20 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, id_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, taskId_); + com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 4, url_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(token_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 5, token_); } if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(3, getPushNotificationConfig()); + output.writeMessage(6, getAuthentication()); } getUnknownFields().writeTo(output); } @@ -217,12 +372,21 @@ public int getSerializedSize() { if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, id_); + } if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, taskId_); + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(4, url_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(token_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(5, token_); } if (((bitField0_ & 0x00000001) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getPushNotificationConfig()); + .computeMessageSize(6, getAuthentication()); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -241,12 +405,18 @@ public boolean equals(final java.lang.Object obj) { if (!getTenant() .equals(other.getTenant())) return false; + if (!getId() + .equals(other.getId())) return false; if (!getTaskId() .equals(other.getTaskId())) return false; - if (hasPushNotificationConfig() != other.hasPushNotificationConfig()) return false; - if (hasPushNotificationConfig()) { - if (!getPushNotificationConfig() - .equals(other.getPushNotificationConfig())) return false; + if (!getUrl() + .equals(other.getUrl())) return false; + if (!getToken() + .equals(other.getToken())) return false; + if (hasAuthentication() != other.hasAuthentication()) return false; + if (hasAuthentication()) { + if (!getAuthentication() + .equals(other.getAuthentication())) return false; } if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; @@ -261,11 +431,17 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + TENANT_FIELD_NUMBER; hash = (53 * hash) + getTenant().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); hash = (37 * hash) + TASK_ID_FIELD_NUMBER; hash = (53 * hash) + getTaskId().hashCode(); - if (hasPushNotificationConfig()) { - hash = (37 * hash) + PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER; - hash = (53 * hash) + getPushNotificationConfig().hashCode(); + hash = (37 * hash) + URL_FIELD_NUMBER; + hash = (53 * hash) + getUrl().hashCode(); + hash = (37 * hash) + TOKEN_FIELD_NUMBER; + hash = (53 * hash) + getToken().hashCode(); + if (hasAuthentication()) { + hash = (37 * hash) + AUTHENTICATION_FIELD_NUMBER; + hash = (53 * hash) + getAuthentication().hashCode(); } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; @@ -401,7 +577,7 @@ private Builder( private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessage .alwaysUseFieldBuilders) { - internalGetPushNotificationConfigFieldBuilder(); + internalGetAuthenticationFieldBuilder(); } } @java.lang.Override @@ -409,11 +585,14 @@ public Builder clear() { super.clear(); bitField0_ = 0; tenant_ = ""; + id_ = ""; taskId_ = ""; - pushNotificationConfig_ = null; - if (pushNotificationConfigBuilder_ != null) { - pushNotificationConfigBuilder_.dispose(); - pushNotificationConfigBuilder_ = null; + url_ = ""; + token_ = ""; + authentication_ = null; + if (authenticationBuilder_ != null) { + authenticationBuilder_.dispose(); + authenticationBuilder_ = null; } return this; } @@ -452,13 +631,22 @@ private void buildPartial0(io.a2a.grpc.TaskPushNotificationConfig result) { result.tenant_ = tenant_; } if (((from_bitField0_ & 0x00000002) != 0)) { + result.id_ = id_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { result.taskId_ = taskId_; } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.url_ = url_; + } + if (((from_bitField0_ & 0x00000010) != 0)) { + result.token_ = token_; + } int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000004) != 0)) { - result.pushNotificationConfig_ = pushNotificationConfigBuilder_ == null - ? pushNotificationConfig_ - : pushNotificationConfigBuilder_.build(); + if (((from_bitField0_ & 0x00000020) != 0)) { + result.authentication_ = authenticationBuilder_ == null + ? authentication_ + : authenticationBuilder_.build(); to_bitField0_ |= 0x00000001; } result.bitField0_ |= to_bitField0_; @@ -481,13 +669,28 @@ public Builder mergeFrom(io.a2a.grpc.TaskPushNotificationConfig other) { bitField0_ |= 0x00000001; onChanged(); } + if (!other.getId().isEmpty()) { + id_ = other.id_; + bitField0_ |= 0x00000002; + onChanged(); + } if (!other.getTaskId().isEmpty()) { taskId_ = other.taskId_; - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000004; onChanged(); } - if (other.hasPushNotificationConfig()) { - mergePushNotificationConfig(other.getPushNotificationConfig()); + if (!other.getUrl().isEmpty()) { + url_ = other.url_; + bitField0_ |= 0x00000008; + onChanged(); + } + if (!other.getToken().isEmpty()) { + token_ = other.token_; + bitField0_ |= 0x00000010; + onChanged(); + } + if (other.hasAuthentication()) { + mergeAuthentication(other.getAuthentication()); } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); @@ -521,17 +724,32 @@ public Builder mergeFrom( break; } // case 10 case 18: { - taskId_ = input.readStringRequireUtf8(); + id_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000002; break; } // case 18 case 26: { - input.readMessage( - internalGetPushNotificationConfigFieldBuilder().getBuilder(), - extensionRegistry); + taskId_ = input.readStringRequireUtf8(); bitField0_ |= 0x00000004; break; } // case 26 + case 34: { + url_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000008; + break; + } // case 34 + case 42: { + token_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000010; + break; + } // case 42 + case 50: { + input.readMessage( + internalGetAuthenticationFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000020; + break; + } // case 50 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -641,13 +859,110 @@ public Builder setTenantBytes( return this; } + private java.lang.Object id_ = ""; + /** + *
        +     * The push notification configuration details.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
        +     * 
        + * + * string id = 2; + * @return The id. + */ + public java.lang.String getId() { + java.lang.Object ref = id_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
        +     * The push notification configuration details.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
        +     * 
        + * + * string id = 2; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
        +     * The push notification configuration details.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
        +     * 
        + * + * string id = 2; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + id_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
        +     * The push notification configuration details.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
        +     * 
        + * + * string id = 2; + * @return This builder for chaining. + */ + public Builder clearId() { + id_ = getDefaultInstance().getId(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
        +     * The push notification configuration details.
        +     * A unique identifier (e.g. UUID) for this push notification configuration.
        +     * 
        + * + * string id = 2; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + id_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + private java.lang.Object taskId_ = ""; /** *
              * The ID of the task this configuration is associated with.
              * 
        * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @return The taskId. */ public java.lang.String getTaskId() { @@ -667,7 +982,7 @@ public java.lang.String getTaskId() { * The ID of the task this configuration is associated with. * * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @return The bytes for taskId. */ public com.google.protobuf.ByteString @@ -688,7 +1003,7 @@ public java.lang.String getTaskId() { * The ID of the task this configuration is associated with. * * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @param value The taskId to set. * @return This builder for chaining. */ @@ -696,7 +1011,7 @@ public Builder setTaskId( java.lang.String value) { if (value == null) { throw new NullPointerException(); } taskId_ = value; - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000004; onChanged(); return this; } @@ -705,12 +1020,12 @@ public Builder setTaskId( * The ID of the task this configuration is associated with. * * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @return This builder for chaining. */ public Builder clearTaskId() { taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000004); onChanged(); return this; } @@ -719,7 +1034,7 @@ public Builder clearTaskId() { * The ID of the task this configuration is associated with. * * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @param value The bytes for taskId to set. * @return This builder for chaining. */ @@ -728,166 +1043,350 @@ public Builder setTaskIdBytes( if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); taskId_ = value; - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000004; onChanged(); return this; } - private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; + private java.lang.Object url_ = ""; + /** + *
        +     * The URL where the notification should be sent.
        +     * 
        + * + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The url. + */ + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
        +     * The URL where the notification should be sent.
        +     * 
        + * + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for url. + */ + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
        +     * The URL where the notification should be sent.
        +     * 
        + * + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @param value The url to set. + * @return This builder for chaining. + */ + public Builder setUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + url_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
        +     * The URL where the notification should be sent.
        +     * 
        + * + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearUrl() { + url_ = getDefaultInstance().getUrl(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + return this; + } + /** + *
        +     * The URL where the notification should be sent.
        +     * 
        + * + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for url to set. + * @return This builder for chaining. + */ + public Builder setUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + url_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + + private java.lang.Object token_ = ""; + /** + *
        +     * A token unique for this task or session.
        +     * 
        + * + * string token = 5; + * @return The token. + */ + public java.lang.String getToken() { + java.lang.Object ref = token_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + token_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
        +     * A token unique for this task or session.
        +     * 
        + * + * string token = 5; + * @return The bytes for token. + */ + public com.google.protobuf.ByteString + getTokenBytes() { + java.lang.Object ref = token_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + token_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
        +     * A token unique for this task or session.
        +     * 
        + * + * string token = 5; + * @param value The token to set. + * @return This builder for chaining. + */ + public Builder setToken( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + token_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
        +     * A token unique for this task or session.
        +     * 
        + * + * string token = 5; + * @return This builder for chaining. + */ + public Builder clearToken() { + token_ = getDefaultInstance().getToken(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + return this; + } + /** + *
        +     * A token unique for this task or session.
        +     * 
        + * + * string token = 5; + * @param value The bytes for token to set. + * @return This builder for chaining. + */ + public Builder setTokenBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + token_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + + private io.a2a.grpc.AuthenticationInfo authentication_; private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> pushNotificationConfigBuilder_; + io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> authenticationBuilder_; /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the pushNotificationConfig field is set. + * .lf.a2a.v1.AuthenticationInfo authentication = 6; + * @return Whether the authentication field is set. */ - public boolean hasPushNotificationConfig() { - return ((bitField0_ & 0x00000004) != 0); + public boolean hasAuthentication() { + return ((bitField0_ & 0x00000020) != 0); } /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The pushNotificationConfig. + * .lf.a2a.v1.AuthenticationInfo authentication = 6; + * @return The authentication. */ - public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { - if (pushNotificationConfigBuilder_ == null) { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + public io.a2a.grpc.AuthenticationInfo getAuthentication() { + if (authenticationBuilder_ == null) { + return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; } else { - return pushNotificationConfigBuilder_.getMessage(); + return authenticationBuilder_.getMessage(); } } /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ - public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { - if (pushNotificationConfigBuilder_ == null) { + public Builder setAuthentication(io.a2a.grpc.AuthenticationInfo value) { + if (authenticationBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - pushNotificationConfig_ = value; + authentication_ = value; } else { - pushNotificationConfigBuilder_.setMessage(value); + authenticationBuilder_.setMessage(value); } - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000020; onChanged(); return this; } /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ - public Builder setPushNotificationConfig( - io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { - if (pushNotificationConfigBuilder_ == null) { - pushNotificationConfig_ = builderForValue.build(); + public Builder setAuthentication( + io.a2a.grpc.AuthenticationInfo.Builder builderForValue) { + if (authenticationBuilder_ == null) { + authentication_ = builderForValue.build(); } else { - pushNotificationConfigBuilder_.setMessage(builderForValue.build()); + authenticationBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000020; onChanged(); return this; } /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ - public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { - if (pushNotificationConfigBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0) && - pushNotificationConfig_ != null && - pushNotificationConfig_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { - getPushNotificationConfigBuilder().mergeFrom(value); + public Builder mergeAuthentication(io.a2a.grpc.AuthenticationInfo value) { + if (authenticationBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0) && + authentication_ != null && + authentication_ != io.a2a.grpc.AuthenticationInfo.getDefaultInstance()) { + getAuthenticationBuilder().mergeFrom(value); } else { - pushNotificationConfig_ = value; + authentication_ = value; } } else { - pushNotificationConfigBuilder_.mergeFrom(value); + authenticationBuilder_.mergeFrom(value); } - if (pushNotificationConfig_ != null) { - bitField0_ |= 0x00000004; + if (authentication_ != null) { + bitField0_ |= 0x00000020; onChanged(); } return this; } /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ - public Builder clearPushNotificationConfig() { - bitField0_ = (bitField0_ & ~0x00000004); - pushNotificationConfig_ = null; - if (pushNotificationConfigBuilder_ != null) { - pushNotificationConfigBuilder_.dispose(); - pushNotificationConfigBuilder_ = null; + public Builder clearAuthentication() { + bitField0_ = (bitField0_ & ~0x00000020); + authentication_ = null; + if (authenticationBuilder_ != null) { + authenticationBuilder_.dispose(); + authenticationBuilder_ = null; } onChanged(); return this; } /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ - public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuilder() { - bitField0_ |= 0x00000004; + public io.a2a.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() { + bitField0_ |= 0x00000020; onChanged(); - return internalGetPushNotificationConfigFieldBuilder().getBuilder(); + return internalGetAuthenticationFieldBuilder().getBuilder(); } /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ - public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { - if (pushNotificationConfigBuilder_ != null) { - return pushNotificationConfigBuilder_.getMessageOrBuilder(); + public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { + if (authenticationBuilder_ != null) { + return authenticationBuilder_.getMessageOrBuilder(); } else { - return pushNotificationConfig_ == null ? - io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + return authentication_ == null ? + io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; } } /** *
        -     * The push notification configuration details.
        +     * Authentication information required to send the notification.
              * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> - internalGetPushNotificationConfigFieldBuilder() { - if (pushNotificationConfigBuilder_ == null) { - pushNotificationConfigBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder>( - getPushNotificationConfig(), + io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> + internalGetAuthenticationFieldBuilder() { + if (authenticationBuilder_ == null) { + authenticationBuilder_ = new com.google.protobuf.SingleFieldBuilder< + io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder>( + getAuthentication(), getParentForChildren(), isClean()); - pushNotificationConfig_ = null; + authentication_ = null; } - return pushNotificationConfigBuilder_; + return authenticationBuilder_; } // @@protoc_insertion_point(builder_scope:lf.a2a.v1.TaskPushNotificationConfig) diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java index 7bffa7a54..771d13522 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java @@ -30,12 +30,34 @@ public interface TaskPushNotificationConfigOrBuilder extends com.google.protobuf.ByteString getTenantBytes(); + /** + *
        +   * The push notification configuration details.
        +   * A unique identifier (e.g. UUID) for this push notification configuration.
        +   * 
        + * + * string id = 2; + * @return The id. + */ + java.lang.String getId(); + /** + *
        +   * The push notification configuration details.
        +   * A unique identifier (e.g. UUID) for this push notification configuration.
        +   * 
        + * + * string id = 2; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); + /** *
            * The ID of the task this configuration is associated with.
            * 
        * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @return The taskId. */ java.lang.String getTaskId(); @@ -44,7 +66,7 @@ public interface TaskPushNotificationConfigOrBuilder extends * The ID of the task this configuration is associated with. * * - * string task_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * string task_id = 3; * @return The bytes for taskId. */ com.google.protobuf.ByteString @@ -52,28 +74,68 @@ public interface TaskPushNotificationConfigOrBuilder extends /** *
        -   * The push notification configuration details.
        +   * The URL where the notification should be sent.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the pushNotificationConfig field is set. + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The url. */ - boolean hasPushNotificationConfig(); + java.lang.String getUrl(); /** *
        -   * The push notification configuration details.
        +   * The URL where the notification should be sent.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The pushNotificationConfig. + * string url = 4 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for url. */ - io.a2a.grpc.PushNotificationConfig getPushNotificationConfig(); + com.google.protobuf.ByteString + getUrlBytes(); + /** *
        -   * The push notification configuration details.
        +   * A token unique for this task or session.
        +   * 
        + * + * string token = 5; + * @return The token. + */ + java.lang.String getToken(); + /** + *
        +   * A token unique for this task or session.
        +   * 
        + * + * string token = 5; + * @return The bytes for token. + */ + com.google.protobuf.ByteString + getTokenBytes(); + + /** + *
        +   * Authentication information required to send the notification.
        +   * 
        + * + * .lf.a2a.v1.AuthenticationInfo authentication = 6; + * @return Whether the authentication field is set. + */ + boolean hasAuthentication(); + /** + *
        +   * Authentication information required to send the notification.
        +   * 
        + * + * .lf.a2a.v1.AuthenticationInfo authentication = 6; + * @return The authentication. + */ + io.a2a.grpc.AuthenticationInfo getAuthentication(); + /** + *
        +   * Authentication information required to send the notification.
            * 
        * - * .lf.a2a.v1.PushNotificationConfig push_notification_config = 3 [(.google.api.field_behavior) = REQUIRED]; + * .lf.a2a.v1.AuthenticationInfo authentication = 6; */ - io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder(); + io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder(); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java deleted file mode 100644 index ce74a8741..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.grpc.CreateTaskPushNotificationConfigRequest; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.TaskPushNotificationConfig; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * MapStruct mapper for CreateTaskPushNotificationConfigRequest → TaskPushNotificationConfig. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {PushNotificationConfigMapper.class}) -public interface CreateTaskPushNotificationConfigMapper { - - CreateTaskPushNotificationConfigMapper INSTANCE = A2AMappers.getMapper(CreateTaskPushNotificationConfigMapper.class); - - /** - * Converts CreateTaskPushNotificationConfigRequest to domain TaskPushNotificationConfig. - * - * @param request the protobuf CreateTaskPushNotificationConfigRequest - * @return domain TaskPushNotificationConfig - */ - @Mapping(target = "config", expression = "java(mapPushNotificationConfigWithId(request))") - TaskPushNotificationConfig fromProto(CreateTaskPushNotificationConfigRequest request); - - /** - * Converts domain TaskPushNotificationConfig to CreateTaskPushNotificationConfigRequest. - * - * @param config the domain TaskPushNotificationConfig - * @return proto CreateTaskPushNotificationConfigRequest - */ - CreateTaskPushNotificationConfigRequest toProto(TaskPushNotificationConfig config); - - /** - * Extracts the config ID from the configuration. - * - * @param config the TaskPushNotificationConfig - * @return the extracted config ID - */ - default String extractConfigId(TaskPushNotificationConfig config) { - return config.config() != null ? config.config().id() : null; - } - - /** - * Maps the protobuf PushNotificationConfig to domain, injecting config_id from request. - * - * @param request the protobuf CreateTaskPushNotificationConfigRequest - * @return domain PushNotificationConfig with config_id injected - */ - default PushNotificationConfig mapPushNotificationConfigWithId(CreateTaskPushNotificationConfigRequest request) { - if (!request.hasConfig()) { - return null; - } - - // Map the proto PushNotificationConfig - PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto(request.getConfig()); - - // Override ID with config_id from request - String configId = request.getConfig().getId(); - if (configId != null && !configId.isEmpty() && !configId.equals(result.id())) { - return new PushNotificationConfig( - result.url(), - result.token(), - result.authentication(), - configId - ); - } - - return result; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java index d615527d4..138ad346a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java @@ -10,12 +10,12 @@ /** * Mapper between {@link io.a2a.spec.MessageSendConfiguration} and {@link io.a2a.grpc.SendMessageConfiguration}. *

        - * Handles bidirectional mapping with null/empty list conversions and push notification config delegation. + * Handles bidirectional mapping with null/empty list conversions and task push notification config delegation. * Uses ADDER_PREFERRED strategy to avoid ProtocolStringList instantiation issues. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {PushNotificationConfigMapper.class, A2ACommonFieldMapper.class}) + uses = {TaskPushNotificationConfigMapper.class, A2ACommonFieldMapper.class}) public interface MessageSendConfigurationMapper { MessageSendConfigurationMapper INSTANCE = A2AMappers.getMapper(MessageSendConfigurationMapper.class); @@ -23,7 +23,7 @@ public interface MessageSendConfigurationMapper { /** * Converts domain MessageSendConfiguration to proto SendMessageConfiguration. */ - @Mapping(target = "pushNotificationConfig", source = "pushNotificationConfig", conditionExpression = "java(domain.pushNotificationConfig() != null)") + @Mapping(target = "taskPushNotificationConfig", source = "taskPushNotificationConfig", conditionExpression = "java(domain.taskPushNotificationConfig() != null)") io.a2a.grpc.SendMessageConfiguration toProto(MessageSendConfiguration domain); /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PushNotificationConfigMapper.java deleted file mode 100644 index 18ae705d5..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PushNotificationConfigMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.PushNotificationConfig} and {@link io.a2a.grpc.PushNotificationConfig}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {AuthenticationInfoMapper.class, A2ACommonFieldMapper.class}) -public interface PushNotificationConfigMapper { - - PushNotificationConfigMapper INSTANCE = A2AMappers.getMapper(PushNotificationConfigMapper.class); - - @Mapping(target = "url", source = "url", conditionExpression = "java(domain.url() != null)") - @Mapping(target = "token", source = "token", conditionExpression = "java(domain.token() != null)") - @Mapping(target = "authentication", source = "authentication", conditionExpression = "java(domain.authentication() != null)") - @Mapping(target = "id", source = "id", conditionExpression = "java(domain.id() != null)") - io.a2a.grpc.PushNotificationConfig toProto(io.a2a.spec.PushNotificationConfig domain); - - /** - * Converts proto PushNotificationConfig to domain. - * Uses declarative mappings with empty string → null conversion via CommonFieldMapper. - */ - @Mapping(target = "token", source = "token", qualifiedByName = "emptyToNull") - @Mapping(target = "id", source = "id", qualifiedByName = "emptyToNull") - @Mapping(target = "authentication", source = "authentication", conditionExpression = "java(proto.hasAuthentication())") - io.a2a.spec.PushNotificationConfig fromProto(io.a2a.grpc.PushNotificationConfig proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java index beeb9bfef..07b498ad0 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java @@ -1,7 +1,7 @@ package io.a2a.grpc.mapper; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; +import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -9,9 +9,11 @@ * MapStruct mapper for TaskPushNotificationConfig. *

        * Maps between domain TaskPushNotificationConfig and proto TaskPushNotificationConfig. - * The proto now has direct task_id and id fields instead of a resource name. + * The proto has direct id, task_id, url, token, authentication, and tenant fields. */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {PushNotificationConfigMapper.class}) +@Mapper(config = A2AProtoMapperConfig.class, + collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, + uses = {AuthenticationInfoMapper.class, A2ACommonFieldMapper.class}) public interface TaskPushNotificationConfigMapper { TaskPushNotificationConfigMapper INSTANCE = A2AMappers.getMapper(TaskPushNotificationConfigMapper.class); @@ -22,9 +24,12 @@ public interface TaskPushNotificationConfigMapper { * @param domain the domain TaskPushNotificationConfig * @return protobuf TaskPushNotificationConfig */ - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "pushNotificationConfig", source = "config") + @Mapping(target = "id", source = "id", conditionExpression = "java(domain.id() != null)") + @Mapping(target = "taskId", source = "taskId", conditionExpression = "java(domain.taskId() != null)") + @Mapping(target = "url", source = "url", conditionExpression = "java(domain.url() != null)") + @Mapping(target = "token", source = "token", conditionExpression = "java(domain.token() != null)") @Mapping(target = "tenant", source = "tenant", conditionExpression = "java(domain.tenant() != null)") + @Mapping(target = "authentication", source = "authentication", conditionExpression = "java(domain.authentication() != null)") io.a2a.grpc.TaskPushNotificationConfig toProto(TaskPushNotificationConfig domain); /** @@ -33,42 +38,9 @@ public interface TaskPushNotificationConfigMapper { * @param proto the protobuf TaskPushNotificationConfig * @return domain TaskPushNotificationConfig */ - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "config", expression = "java(mapPushNotificationConfigWithId(proto))") - @Mapping(target = "tenant", expression = "java(proto.getTenant().isEmpty() ? null : proto.getTenant())") + @Mapping(target = "token", source = "token", qualifiedByName = "emptyToNull") + @Mapping(target = "tenant", source = "tenant", qualifiedByName = "emptyToNull") + @Mapping(target = "taskId", source = "taskId", qualifiedByName = "emptyToNull") + @Mapping(target = "authentication", source = "authentication", conditionExpression = "java(proto.hasAuthentication())") TaskPushNotificationConfig fromProto(io.a2a.grpc.TaskPushNotificationConfig proto); - - /** - * Extracts the config ID from the PushNotificationConfig. - * - * @param config the domain TaskPushNotificationConfig - * @return the config ID - */ - default String extractId(TaskPushNotificationConfig config) { - return config.config()!= null ? config.config().id() : null; - } - - /** - * Maps the protobuf PushNotificationConfig to domain, ensuring the ID matches the proto's id field. - * - * @param proto the protobuf TaskPushNotificationConfig - * @return domain PushNotificationConfig with correct ID - */ - default PushNotificationConfig mapPushNotificationConfigWithId(io.a2a.grpc.TaskPushNotificationConfig proto) { - if (!proto.hasPushNotificationConfig() || - proto.getPushNotificationConfig().equals(io.a2a.grpc.PushNotificationConfig.getDefaultInstance())) { - return null; - } - - // Map the proto PushNotificationConfig - PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto(proto.getPushNotificationConfig()); - - // Override ID with the id from TaskPushNotificationConfig if they differ - String configId = proto.getPushNotificationConfig().getId(); - if (configId != null && !configId.isEmpty() && !configId.equals(result.id())) { - return new PushNotificationConfig(result.url(), result.token(), result.authentication(), configId); - } - - return result; - } } 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 6a0f4525a..dbfe89c89 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 @@ -229,12 +229,12 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new ListTasksRequest(version, id, ProtoUtils.FromProto.listTasksParams(builder)); } case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); + io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); } - return new CreateTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.CreateTaskPushNotificationConfig(builder)); + return new CreateTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.createTaskPushNotificationConfig(builder)); } case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); @@ -432,7 +432,7 @@ private static A2AError processError(JsonObject error) { case TASK_NOT_CANCELABLE_ERROR_CODE: return new TaskNotCancelableError(code, message, data); case TASK_NOT_FOUND_ERROR_CODE: - return new TaskNotFoundError(code, message, data); + return new TaskNotFoundError(message, data); default: return new A2AError(code, message == null ? "": message, data); } 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 6c48902a2..5cb52b96b 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 @@ -14,7 +14,6 @@ import io.a2a.grpc.mapper.MessageMapper; import io.a2a.grpc.mapper.MessageSendConfigurationMapper; import io.a2a.grpc.mapper.MessageSendParamsMapper; -import io.a2a.grpc.mapper.CreateTaskPushNotificationConfigMapper; import io.a2a.grpc.mapper.StreamResponseMapper; import io.a2a.grpc.mapper.TaskArtifactUpdateEventMapper; import io.a2a.grpc.mapper.TaskIdParamsMapper; @@ -77,8 +76,8 @@ public static io.a2a.grpc.SubscribeToTaskRequest subscribeToTaskRequest(TaskIdPa return TaskIdParamsMapper.INSTANCE.toProtoSubscribeToTaskRequest(params); } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest createTaskPushNotificationConfigRequest(TaskPushNotificationConfig config) { - return CreateTaskPushNotificationConfigMapper.INSTANCE.toProto(config); + public static io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfigRequest(TaskPushNotificationConfig config) { + return TaskPushNotificationConfigMapper.INSTANCE.toProto(config); } public static io.a2a.grpc.GetTaskPushNotificationConfigRequest getTaskPushNotificationConfigRequest(GetTaskPushNotificationConfigParams params) { @@ -237,11 +236,11 @@ public static MessageSendParams messageSendParams(io.a2a.grpc.SendMessageRequest return convert(() -> MessageSendParamsMapper.INSTANCE.fromProto(requestProto)); } - public static TaskPushNotificationConfig CreateTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequestOrBuilder config) { - io.a2a.grpc.CreateTaskPushNotificationConfigRequest reqProto = config instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest - ? (io.a2a.grpc.CreateTaskPushNotificationConfigRequest) config - : ((io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder) config).build(); - return convert(() -> CreateTaskPushNotificationConfigMapper.INSTANCE.fromProto(reqProto)); + public static TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfigOrBuilder config) { + io.a2a.grpc.TaskPushNotificationConfig proto = config instanceof io.a2a.grpc.TaskPushNotificationConfig + ? (io.a2a.grpc.TaskPushNotificationConfig) config + : ((io.a2a.grpc.TaskPushNotificationConfig.Builder) config).build(); + return convert(() -> TaskPushNotificationConfigMapper.INSTANCE.fromProto(proto)); } public static TaskPushNotificationConfig taskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfigOrBuilder config) { diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto index 7753faeb1..4119821ab 100644 --- a/spec-grpc/src/main/proto/a2a.proto +++ b/spec-grpc/src/main/proto/a2a.proto @@ -9,7 +9,7 @@ import "google/protobuf/empty.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; -// From commit 1997c9d63058ca0b89361a7d6e508f4641a6f68b +// From commit dec790a option csharp_namespace = "Lf.A2a.V1"; option go_package = "google.golang.org/lf/a2a/v1"; @@ -86,15 +86,16 @@ service A2AService { // (-- api-linter: client-libraries::4232::required-fields=disabled // api-linter: core::0133::method-signature=disabled + // api-linter: core::0133::request-message-name=disabled // aip.dev/not-precedent: method_signature preserved for backwards compatibility --) // Creates a push notification config for a task. - rpc CreateTaskPushNotificationConfig(CreateTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { + rpc CreateTaskPushNotificationConfig(TaskPushNotificationConfig) returns (TaskPushNotificationConfig) { option (google.api.http) = { post: "/tasks/{task_id=*}/pushNotificationConfigs" - body: "config" + body: "*" additional_bindings: { post: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs" - body: "config" + body: "*" } }; option (google.api.method_signature) = "task_id,config"; @@ -146,7 +147,8 @@ message SendMessageConfiguration { // Agents SHOULD use this to tailor their output. repeated string accepted_output_modes = 1; // Configuration for the agent to send push notifications for task updates. - PushNotificationConfig push_notification_config = 2; + // Task id should be empty when sending this configuration in a `SendMessage` request. + TaskPushNotificationConfig task_push_notification_config = 2; // The maximum number of most recent messages from the task's history to retrieve in // the response. An unset value means the client does not impose any limit. A // value of zero is a request to not include any messages. The server MUST NOT @@ -167,8 +169,8 @@ message Task { // new task. string id = 1 [(google.api.field_behavior) = REQUIRED]; // Unique identifier (e.g. UUID) for the contextual collection of interactions - // (tasks and messages). Created by the A2A server. - string context_id = 2 [(google.api.field_behavior) = REQUIRED]; + // (tasks and messages). + string context_id = 2; // The current status of a `Task`, including `state` and a `message`. TaskStatus status = 3 [(google.api.field_behavior) = REQUIRED]; // A set of output artifacts for a `Task`. @@ -319,18 +321,6 @@ message TaskArtifactUpdateEvent { google.protobuf.Struct metadata = 6; } -// Configuration for setting up push notifications for task updates. -message PushNotificationConfig { - // A unique identifier (e.g. UUID) for this push notification configuration. - string id = 1; - // The URL where the notification should be sent. - string url = 2 [(google.api.field_behavior) = REQUIRED]; - // A token unique for this task or session. - string token = 3; - // Authentication information required to send the notification. - AuthenticationInfo authentication = 4; -} - // Defines authentication details, used for push notifications. message AuthenticationInfo { // HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/). @@ -474,10 +464,17 @@ message AgentCardSignature { message TaskPushNotificationConfig { // Optional. Tenant ID. string tenant = 1; - // The ID of the task this configuration is associated with. - string task_id = 2 [(google.api.field_behavior) = REQUIRED]; // The push notification configuration details. - PushNotificationConfig push_notification_config = 3 [(google.api.field_behavior) = REQUIRED]; + // A unique identifier (e.g. UUID) for this push notification configuration. + string id = 2; + // The ID of the task this configuration is associated with. + string task_id = 3; + // The URL where the notification should be sent. + string url = 4 [(google.api.field_behavior) = REQUIRED]; + // A token unique for this task or session. + string token = 5; + // Authentication information required to send the notification. + AuthenticationInfo authentication = 6; } // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED @@ -735,16 +732,6 @@ message DeleteTaskPushNotificationConfigRequest { string id = 3 [(google.api.field_behavior) = REQUIRED]; } -// Represents a request for the `CreateTaskPushNotificationConfig` method. -message CreateTaskPushNotificationConfigRequest { - // Optional. Tenant ID, provided as a path parameter. - string tenant = 1; - // The parent task resource ID. - string task_id = 2 [(google.api.field_behavior) = REQUIRED]; - // The configuration to create. - PushNotificationConfig config = 3 [(google.api.field_behavior) = REQUIRED]; -} - // Represents a request for the `SubscribeToTask` method. message SubscribeToTaskRequest { // Optional. Tenant ID, provided as a path parameter. 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 b5bb95f4e..7428f693e 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 @@ -21,7 +21,6 @@ import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; import org.junit.jupiter.api.Test; @@ -37,12 +36,10 @@ public void testParseCreateTaskPushNotificationConfigRequest_ValidProtoFormat() "params": { "taskId": "task-123", "tenant": "", - "config": { - "id": "config-456", - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } + "id": "config-456", + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } } } @@ -60,8 +57,7 @@ public void testParseCreateTaskPushNotificationConfigRequest_ValidProtoFormat() TaskPushNotificationConfig config = setRequest.getParams(); assertNotNull(config); assertEquals("task-123", config.taskId()); - assertNotNull(config.config()); - assertEquals("https://example.com/callback", config.config().url()); + assertEquals("https://example.com/callback", config.url()); } @Test @@ -142,7 +138,7 @@ public void testParseInvalidProtoStructure_ThrowsInvalidParamsJsonMappingExcepti () -> JSONRPCUtils.parseRequestBody(invalidStructure, null) ); assertEquals(4, exception.getId()); - assertEquals(ERROR_MESSAGE.formatted("invalid_field in message lf.a2a.v1.CreateTaskPushNotificationConfigRequest"), exception.getMessage()); + assertEquals(ERROR_MESSAGE.formatted("invalid_field in message lf.a2a.v1.TaskPushNotificationConfig"), exception.getMessage()); } @Test @@ -300,15 +296,6 @@ public void testParseInvalidTypeWithValidId_PreservesId() throws Exception { @Test public void testGenerateCreateTaskPushNotificationConfigResponse_Success() throws Exception { - TaskPushNotificationConfig config = new TaskPushNotificationConfig( - "task-123", - PushNotificationConfig.builder() - .url("https://example.com/callback") - .id("config-456") - .build(), - "tenant" - ); - String responseJson = """ { "jsonrpc": "2.0", @@ -316,10 +303,8 @@ public void testGenerateCreateTaskPushNotificationConfigResponse_Success() throw "result": { "tenant": "tenant", "taskId": "task-123", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "id": "config-456" - } + "id": "config-456", + "url": "https://example.com/callback" } } """; @@ -331,7 +316,7 @@ public void testGenerateCreateTaskPushNotificationConfigResponse_Success() throw assertEquals(1, response.getId()); assertNotNull(response.getResult()); assertEquals("task-123", response.getResult().taskId()); - assertEquals("https://example.com/callback", response.getResult().config().url()); + assertEquals("https://example.com/callback", response.getResult().url()); } @Test @@ -343,10 +328,8 @@ public void testGenerateGetTaskPushNotificationConfigResponse_Success() throws E "result": { "tenant": "tenant", "taskId": "task-123", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "id": "config-456" - } + "id": "config-456", + "url": "https://example.com/callback" } } """; @@ -358,7 +341,7 @@ public void testGenerateGetTaskPushNotificationConfigResponse_Success() throws E assertEquals(2, response.getId()); assertNotNull(response.getResult()); assertEquals("task-123", response.getResult().taskId()); - assertEquals("https://example.com/callback", response.getResult().config().url()); + assertEquals("https://example.com/callback", response.getResult().url()); } @Test diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index ea0f320a0..4051cea82 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -25,7 +25,6 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskPushNotificationConfig; @@ -209,36 +208,31 @@ public void convertMessage() { @Test public void convertTaskPushNotificationConfig() { - TaskPushNotificationConfig taskPushConfig = new TaskPushNotificationConfig("push-task-123", - PushNotificationConfig.builder() - .url("http://example.com") - .id("xyz") - .build(), null); + TaskPushNotificationConfig taskPushConfig = TaskPushNotificationConfig.builder() + .id("xyz") + .taskId("push-task-123") + .url("http://example.com") + .build(); io.a2a.grpc.TaskPushNotificationConfig result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); assertEquals("push-task-123", result.getTaskId()); - assertNotNull(result.getPushNotificationConfig()); - assertEquals("xyz", result.getPushNotificationConfig().getId()); - assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); - assertEquals("xyz", result.getPushNotificationConfig().getId()); - assertEquals(false, result.getPushNotificationConfig().hasAuthentication()); - taskPushConfig - = new TaskPushNotificationConfig("push-task-123", - PushNotificationConfig.builder() - .token("AAAAAA") - .authentication(new AuthenticationInfo("jwt", "credentials")) - .url("http://example.com") - .id("xyz") - .build(), null); + assertEquals("xyz", result.getId()); + assertEquals("http://example.com", result.getUrl()); + assertEquals(false, result.hasAuthentication()); + taskPushConfig = TaskPushNotificationConfig.builder() + .id("xyz") + .taskId("push-task-123") + .url("http://example.com") + .token("AAAAAA") + .authentication(new AuthenticationInfo("jwt", "credentials")) + .build(); result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); assertEquals("push-task-123", result.getTaskId()); - assertNotNull(result.getPushNotificationConfig()); - assertEquals("xyz", result.getPushNotificationConfig().getId()); - assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); - assertEquals("xyz", result.getPushNotificationConfig().getId()); - assertEquals("AAAAAA", result.getPushNotificationConfig().getToken()); - assertEquals(true, result.getPushNotificationConfig().hasAuthentication()); - assertEquals("credentials", result.getPushNotificationConfig().getAuthentication().getCredentials()); - assertEquals("jwt", result.getPushNotificationConfig().getAuthentication().getScheme()); + assertEquals("xyz", result.getId()); + assertEquals("http://example.com", result.getUrl()); + assertEquals("AAAAAA", result.getToken()); + assertEquals(true, result.hasAuthentication()); + assertEquals("credentials", result.getAuthentication().getCredentials()); + assertEquals("jwt", result.getAuthentication().getScheme()); } @Test diff --git a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java b/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java index 29d1201d1..347b7d10e 100644 --- a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java +++ b/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java @@ -17,7 +17,7 @@ * @param scheme security scheme name for authentication (required) * @param credentials optional credentials string (format depends on scheme, e.g., base64-encoded for Basic auth) * @see AgentCard#securitySchemes() for available security schemes - * @see PushNotificationConfig for push notification configuration + * @see TaskPushNotificationConfig for push notification configuration * @see SecurityScheme for security scheme definitions * @see A2A Protocol Specification */ diff --git a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java index d8ea772a9..303cc6608 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java +++ b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java @@ -15,14 +15,15 @@ * * @param acceptedOutputModes list of output modes the client can handle (e.g., "text", "audio") * @param historyLength number of previous messages to include in conversation context (must be non-negative) - * @param pushNotificationConfig configuration for asynchronous push notifications when task state changes + * @param taskPushNotificationConfig configuration for asynchronous push notifications when task state changes. + * Task id should be empty when sending this configuration in a SendMessage request. * @param blocking whether the request should block until task completion (defaults to false) * @see MessageSendParams for the parameters that use this configuration - * @see PushNotificationConfig for push notification options + * @see TaskPushNotificationConfig for push notification options * @see A2A Protocol Specification */ public record MessageSendConfiguration(@Nullable List acceptedOutputModes, @Nullable Integer historyLength, - @Nullable PushNotificationConfig pushNotificationConfig, Boolean blocking) { + @Nullable TaskPushNotificationConfig taskPushNotificationConfig, Boolean blocking) { /** * Compact constructor for validation. @@ -30,7 +31,7 @@ public record MessageSendConfiguration(@Nullable List acceptedOutputMode * * @param acceptedOutputModes list of accepted output modes * @param historyLength maximum number of history items - * @param pushNotificationConfig push notification configuration + * @param taskPushNotificationConfig push notification configuration * @param blocking whether the request should block * @throws IllegalArgumentException if historyLength is negative */ @@ -58,7 +59,7 @@ public static class Builder { @Nullable List acceptedOutputModes; @Nullable Integer historyLength; - @Nullable PushNotificationConfig pushNotificationConfig; + @Nullable TaskPushNotificationConfig taskPushNotificationConfig; Boolean blocking = false; /** @@ -80,12 +81,13 @@ public Builder acceptedOutputModes(List acceptedOutputModes) { /** * Sets the push notification configuration. + * Task id should be empty when sending this configuration in a SendMessage request. * - * @param pushNotificationConfig configuration for push notifications + * @param taskPushNotificationConfig configuration for push notifications * @return this builder */ - public Builder pushNotificationConfig(@Nullable PushNotificationConfig pushNotificationConfig) { - this.pushNotificationConfig = pushNotificationConfig; + public Builder taskPushNotificationConfig(@Nullable TaskPushNotificationConfig taskPushNotificationConfig) { + this.taskPushNotificationConfig = taskPushNotificationConfig; return this; } @@ -124,7 +126,7 @@ public MessageSendConfiguration build() { return new MessageSendConfiguration( acceptedOutputModes, historyLength, - pushNotificationConfig, + taskPushNotificationConfig, blocking); } } diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java deleted file mode 100644 index d6c88dec5..000000000 --- a/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java +++ /dev/null @@ -1,145 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Configuration for asynchronous push notifications of task updates. - *

        - * This record defines the endpoint and authentication details for receiving task event - * notifications. When configured, the agent will POST task updates (status changes, - * artifact additions, completions) to the specified URL as they occur, enabling - * asynchronous workflows without polling. - *

        - * Authentication can be provided via either: - *

          - *
        • Simple bearer token in the {@code token} field
        • - *
        • More complex authentication via {@link AuthenticationInfo}
        • - *
        - * - * @param url the HTTP/HTTPS endpoint URL to receive push notifications (required) - * @param token optional bearer token for simple authentication - * @param authentication optional complex authentication configuration - * @param id optional client-provided identifier for this configuration - * @see AuthenticationInfo for authentication details - * @see TaskPushNotificationConfig for task-specific bindings - * @see MessageSendConfiguration for configuring push notifications on message send - * @see A2A Protocol Specification - */ -public record PushNotificationConfig(String url, @Nullable String token, @Nullable AuthenticationInfo authentication, @Nullable String id) { - - /** - * Compact constructor for validation. - * Validates that the URL is not null. - * - * @param url the notification endpoint URL - * @param token optional bearer token - * @param authentication optional authentication info - * @param id optional configuration identifier - */ - public PushNotificationConfig { - Assert.checkNotNullParam("url", url); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Create a new Builder initialized with values from an existing PushNotificationConfig. - * - * @param config the PushNotificationConfig to copy values from - * @return the builder - */ - public static Builder builder(PushNotificationConfig config) { - return new Builder(config); - } - - /** - * Builder for constructing {@link PushNotificationConfig} instances. - *

        - * Provides a fluent API for building push notification configurations with optional - * authentication and identification. - */ - public static class Builder { - private @Nullable String url; - private @Nullable String token; - private @Nullable AuthenticationInfo authentication; - private @Nullable String id; - - /** Creates an empty builder. */ - private Builder() { - } - - /** - * Creates a builder initialized from an existing configuration. - * - * @param notificationConfig the configuration to copy - */ - private Builder(PushNotificationConfig notificationConfig) { - this.url = notificationConfig.url; - this.token = notificationConfig.token; - this.authentication = notificationConfig.authentication; - this.id = notificationConfig.id; - } - - /** - * Sets the push notification endpoint URL. - * - * @param url the HTTP/HTTPS endpoint (required) - * @return this builder - */ - public Builder url(String url) { - this.url = url; - return this; - } - - /** - * Sets the bearer token for simple authentication. - * - * @param token the bearer token - * @return this builder - */ - public Builder token(String token) { - this.token = token; - return this; - } - - /** - * Sets complex authentication information. - * - * @param authenticationInfo the authentication configuration - * @return this builder - */ - public Builder authentication(AuthenticationInfo authenticationInfo) { - this.authentication = authenticationInfo; - return this; - } - - /** - * Sets the client-provided configuration identifier. - * - * @param id the configuration ID - * @return this builder - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Builds the {@link PushNotificationConfig}. - * - * @return a new push notification configuration - * @throws IllegalArgumentException if url is null - */ - public PushNotificationConfig build() { - return new PushNotificationConfig(Assert.checkNotNullParam("url", url), token, authentication, id); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java index 8bb8eea27..523d44f40 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java @@ -38,19 +38,18 @@ public class TaskNotFoundError extends A2AProtocolError { * Constructs error with default message. */ public TaskNotFoundError() { - this(null, null, null); + this(null, null); } /** * Constructs error with all parameters. * - * @param code the error code (defaults to -32001 if null) * @param message the error message (defaults to "Task not found" if null) - * @param data additional error data (optional) + * @param data additional error data (optional) */ - public TaskNotFoundError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public TaskNotFoundError(@Nullable String message, @Nullable Object data) { super( - defaultIfNull(code, TASK_NOT_FOUND_ERROR_CODE), + TASK_NOT_FOUND_ERROR_CODE, defaultIfNull(message, "Task not found"), data, "https://a2a-protocol.org/errors/task-not-found"); diff --git a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java index 9f973e897..7f1d21b91 100644 --- a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java +++ b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java @@ -4,35 +4,182 @@ import org.jspecify.annotations.Nullable; /** - * Associates a push notification configuration with a specific task. + * Push notification configuration associated with a specific task. *

        - * This record binds a {@link PushNotificationConfig} to a particular task ID, enabling - * the agent to send asynchronous updates about task progress to the configured endpoint. - * When task events occur (status changes, artifact updates), the agent will POST updates - * to the specified notification URL. + * This record defines the endpoint and authentication details for receiving task event + * notifications. When configured, the agent will POST task updates (status changes, + * artifact additions, completions) to the specified URL as they occur, enabling + * asynchronous workflows without polling. + *

        + * Authentication can be provided via either: + *

          + *
        • Simple bearer token in the {@code token} field
        • + *
        • More complex authentication via {@link AuthenticationInfo}
        • + *
        *

        * Used for managing task-specific push notification settings via the push notification * management methods ({@code tasks/pushNotificationConfig/set}, {@code tasks/pushNotificationConfig/get}, etc.). * - * @param taskId the unique identifier of the task to receive push notifications for (required) - * @param config the push notification endpoint and authentication configuration (required) + * @param id unique identifier (e.g. UUID) for this push notification configuration + * @param taskId the unique identifier of the task to receive push notifications for + * @param url the HTTP/HTTPS endpoint URL to receive push notifications (required) + * @param token optional bearer token for simple authentication + * @param authentication optional complex authentication configuration * @param tenant optional tenant identifier, provided as a path parameter - * @see PushNotificationConfig for notification endpoint details + * @see AuthenticationInfo for authentication details + * @see MessageSendConfiguration for configuring push notifications on message send * @see A2A Protocol Specification */ -public record TaskPushNotificationConfig(String taskId, PushNotificationConfig config, @Nullable String tenant) { +public record TaskPushNotificationConfig(String id, @Nullable String taskId, String url, @Nullable String token, + @Nullable AuthenticationInfo authentication, @Nullable String tenant) { /** * Compact constructor for validation. * Validates that required parameters are not null. * + * @param id the configuration identifier * @param taskId the task identifier - * @param config the push notification configuration + * @param url the notification endpoint URL + * @param token optional bearer token + * @param authentication optional authentication info * @param tenant the tenant identifier */ public TaskPushNotificationConfig { - Assert.checkNotNullParam("taskId", taskId); - Assert.checkNotNullParam("config", config); - Assert.checkNotNullParam("configId", config.id()); + Assert.checkNotNullParam("id", id); + Assert.checkNotNullParam("url", url); + } + + /** + * Create a new Builder + * + * @return the builder + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Create a new Builder initialized with values from an existing TaskPushNotificationConfig. + * + * @param config the TaskPushNotificationConfig to copy values from + * @return the builder + */ + public static Builder builder(TaskPushNotificationConfig config) { + return new Builder(config); + } + + /** + * Builder for constructing {@link TaskPushNotificationConfig} instances. + *

        + * Provides a fluent API for building push notification configurations with optional + * authentication and identification. + */ + public static class Builder { + private @Nullable String id; + private @Nullable String taskId; + private @Nullable String url; + private @Nullable String token; + private @Nullable AuthenticationInfo authentication; + private @Nullable String tenant; + + /** Creates an empty builder. */ + private Builder() { + } + + /** + * Creates a builder initialized from an existing configuration. + * + * @param config the configuration to copy + */ + private Builder(TaskPushNotificationConfig config) { + this.id = config.id; + this.taskId = config.taskId; + this.url = config.url; + this.token = config.token; + this.authentication = config.authentication; + this.tenant = config.tenant; + } + + /** + * Sets the configuration identifier. + * + * @param id the configuration ID + * @return this builder + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * Sets the task identifier. + * + * @param taskId the task ID + * @return this builder + */ + public Builder taskId(String taskId) { + this.taskId = taskId; + return this; + } + + /** + * Sets the push notification endpoint URL. + * + * @param url the HTTP/HTTPS endpoint (required) + * @return this builder + */ + public Builder url(String url) { + this.url = url; + return this; + } + + /** + * Sets the bearer token for simple authentication. + * + * @param token the bearer token + * @return this builder + */ + public Builder token(String token) { + this.token = token; + return this; + } + + /** + * Sets complex authentication information. + * + * @param authentication the authentication configuration + * @return this builder + */ + public Builder authentication(AuthenticationInfo authentication) { + this.authentication = authentication; + return this; + } + + /** + * Sets the tenant identifier. + * + * @param tenant the tenant ID + * @return this builder + */ + public Builder tenant(String tenant) { + this.tenant = tenant; + return this; + } + + /** + * Builds the {@link TaskPushNotificationConfig}. + * + * @return a new push notification configuration + * @throws IllegalArgumentException if id or url is null + */ + public TaskPushNotificationConfig build() { + return new TaskPushNotificationConfig( + Assert.checkNotNullParam("id", id), + taskId, + Assert.checkNotNullParam("url", url), + token, + authentication, + tenant); + } } } 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 ea1661ee9..7e29ce825 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 @@ -69,7 +69,6 @@ import io.a2a.spec.MessageSendParams; import io.a2a.spec.MethodNotFoundError; import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskIdParams; @@ -553,12 +552,16 @@ public void testSetPushNotificationSuccess() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); try { TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); + = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("") + .build(); TaskPushNotificationConfig config = getClient().createTaskPushNotificationConfiguration(taskPushConfig); assertEquals(MINIMAL_TASK.id(), config.taskId()); - assertEquals("http://example.com", config.config().url()); - assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", config.config().id()); + assertEquals("http://example.com", config.url()); + assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", config.id()); } catch (A2AClientException e) { fail("Unexpected exception during set push notification test: " + e.getMessage(), e); } finally { @@ -572,8 +575,12 @@ public void testGetPushNotificationSuccess() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); try { TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); + = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("") + .build(); TaskPushNotificationConfig setResult = getClient().createTaskPushNotificationConfiguration(taskPushConfig); assertNotNull(setResult); @@ -581,7 +588,7 @@ public void testGetPushNotificationSuccess() throws Exception { TaskPushNotificationConfig config = getClient().getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams(MINIMAL_TASK.id(), "c295ea44-7543-4f78-b524-7a38915ad6e4")); assertEquals(MINIMAL_TASK.id(), config.taskId()); - assertEquals("http://example.com", config.config().url()); + assertEquals("http://example.com", config.url()); } catch (A2AClientException e) { fail("Unexpected exception during get push notification test: " + e.getMessage(), e); } finally { @@ -1113,13 +1120,13 @@ private boolean waitForChildQueueCountToBe(String taskId, int expectedCount, lon @Test public void testListPushNotificationConfigWithConfigId() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig1 + = TaskPushNotificationConfig.builder() .url("http://example.com") .id("config1") .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig2 + = TaskPushNotificationConfig.builder() .url("http://example.com") .id("config2") .build(); @@ -1130,8 +1137,8 @@ public void testListPushNotificationConfigWithConfigId() throws Exception { ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations( new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); assertEquals(2, result.size()); - assertEquals(new TaskPushNotificationConfig(MINIMAL_TASK.id(), notificationConfig1, null), result.configs().get(0)); - assertEquals(new TaskPushNotificationConfig(MINIMAL_TASK.id(), notificationConfig2, null), result.configs().get(1)); + assertEquals(TaskPushNotificationConfig.builder(notificationConfig1).taskId(MINIMAL_TASK.id()).build(), result.configs().get(0)); + assertEquals(TaskPushNotificationConfig.builder(notificationConfig2).taskId(MINIMAL_TASK.id()).build(), result.configs().get(1)); } catch (Exception e) { fail(); } finally { @@ -1144,13 +1151,15 @@ public void testListPushNotificationConfigWithConfigId() throws Exception { @Test public void testListPushNotificationConfigWithoutConfigId() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig1 + = TaskPushNotificationConfig.builder() .url("http://1.example.com") + .id(MINIMAL_TASK.id()) .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig2 + = TaskPushNotificationConfig.builder() .url("http://2.example.com") + .id(MINIMAL_TASK.id()) .build(); savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); @@ -1161,12 +1170,12 @@ public void testListPushNotificationConfigWithoutConfigId() throws Exception { new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); assertEquals(1, result.size()); - PushNotificationConfig expectedNotificationConfig = PushNotificationConfig.builder() + TaskPushNotificationConfig expectedNotificationConfig = TaskPushNotificationConfig.builder() .url("http://2.example.com") .id(MINIMAL_TASK.id()) + .taskId(MINIMAL_TASK.id()) .build(); - assertEquals(new TaskPushNotificationConfig(MINIMAL_TASK.id(), expectedNotificationConfig, null), - result.configs().get(0)); + assertEquals(expectedNotificationConfig, result.configs().get(0)); } catch (Exception e) { fail(); } finally { @@ -1209,13 +1218,13 @@ public void testDeletePushNotificationConfigWithValidConfigId() throws Exception .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build()); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig1 + = TaskPushNotificationConfig.builder() .url("http://example.com") .id("config1") .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig2 + = TaskPushNotificationConfig.builder() .url("http://example.com") .id("config2") .build(); @@ -1251,13 +1260,13 @@ public void testDeletePushNotificationConfigWithValidConfigId() throws Exception @Test public void testDeletePushNotificationConfigWithNonExistingConfigId() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig1 + = TaskPushNotificationConfig.builder() .url("http://example.com") .id("config1") .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig2 + = TaskPushNotificationConfig.builder() .url("http://example.com") .id("config2") .build(); @@ -1296,13 +1305,15 @@ public void testDeletePushNotificationConfigTaskNotFound() { @Test public void testDeletePushNotificationConfigSetWithoutConfigId() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig1 + = TaskPushNotificationConfig.builder() .url("http://1.example.com") + .id(MINIMAL_TASK.id()) .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() + TaskPushNotificationConfig notificationConfig2 + = TaskPushNotificationConfig.builder() .url("http://2.example.com") + .id(MINIMAL_TASK.id()) .build(); savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); @@ -2239,7 +2250,7 @@ protected void deletePushNotificationConfigInStore(String taskId, String configI } } - protected void savePushNotificationConfigInStore(String taskId, PushNotificationConfig notificationConfig) throws Exception { + protected void savePushNotificationConfigInStore(String taskId, TaskPushNotificationConfig notificationConfig) throws Exception { HttpClient client = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) .build(); diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java index f94d93043..3ef300412 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java @@ -7,7 +7,7 @@ import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.server.tasks.TaskStore; import io.a2a.spec.Event; -import io.a2a.spec.PushNotificationConfig; +import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.Task; /** @@ -58,8 +58,8 @@ public void deleteTaskPushNotificationConfig(String taskId, String configId) { pushNotificationConfigStore.deleteInfo(taskId, configId); } - public void saveTaskPushNotificationConfig(String taskId, PushNotificationConfig notificationConfig) { - pushNotificationConfigStore.setInfo(taskId, notificationConfig); + public void saveTaskPushNotificationConfig(String taskId, TaskPushNotificationConfig notificationConfig) { + pushNotificationConfigStore.setInfo(TaskPushNotificationConfig.builder(notificationConfig).taskId(taskId).build()); } /** 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 4e34a1af2..cf58e9da9 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 @@ -274,7 +274,7 @@ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, } @Override - public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, + public void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request, StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().pushNotifications()) { handleError(responseObserver, new PushNotificationNotSupportedError()); @@ -283,7 +283,7 @@ public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificat try { ServerCallContext context = createCallContext(responseObserver); - TaskPushNotificationConfig config = FromProto.CreateTaskPushNotificationConfig(request); + TaskPushNotificationConfig config = FromProto.createTaskPushNotificationConfig(request); TaskPushNotificationConfig responseConfig = getRequestHandler().onCreateTaskPushNotificationConfig(config, context); responseObserver.onNext(ToProto.taskPushNotificationConfig(responseConfig)); responseObserver.onCompleted(); 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 1e52a925d..c0feac4d7 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 @@ -213,11 +213,10 @@ public void testSetPushNotificationConfigSuccess() throws Exception { Assertions.assertEquals(1, result.size()); TaskPushNotificationConfig response = result.get(0); assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), response.getTaskId()); - PushNotificationConfig responseConfig = response.getPushNotificationConfig(); - assertEquals("config456", responseConfig.getId()); - assertEquals("http://example.com", responseConfig.getUrl()); - assertEquals(AuthenticationInfo.getDefaultInstance(), responseConfig.getAuthentication()); - Assertions.assertTrue(responseConfig.getToken().isEmpty()); + assertEquals("config456", response.getId()); + assertEquals("http://example.com", response.getUrl()); + assertEquals(AuthenticationInfo.getDefaultInstance(), response.getAuthentication()); + Assertions.assertTrue(response.getToken().isEmpty()); } @Test @@ -240,11 +239,10 @@ public void testGetPushNotificationConfigSuccess() throws Exception { Assertions.assertEquals(1, result.size()); TaskPushNotificationConfig response = result.get(0); assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), response.getTaskId()); - PushNotificationConfig responseConfig = response.getPushNotificationConfig(); - assertEquals("config456", responseConfig.getId()); - assertEquals("http://example.com", responseConfig.getUrl()); - assertEquals(AuthenticationInfo.getDefaultInstance(), responseConfig.getAuthentication()); - Assertions.assertTrue(responseConfig.getToken().isEmpty()); + assertEquals("config456", response.getId()); + assertEquals("http://example.com", response.getUrl()); + assertEquals(AuthenticationInfo.getDefaultInstance(), response.getAuthentication()); + Assertions.assertTrue(response.getToken().isEmpty()); } @Test @@ -1144,12 +1142,9 @@ private StreamRecorder sendMessageRequest(GrpcHandler handl private StreamRecorder createTaskPushNotificationConfigRequest(GrpcHandler handler, String taskId, String id) throws Exception { taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - PushNotificationConfig config = PushNotificationConfig.newBuilder() + TaskPushNotificationConfig setRequest = TaskPushNotificationConfig.newBuilder() .setUrl("http://example.com") .setId("config456") - .build(); - CreateTaskPushNotificationConfigRequest setRequest = CreateTaskPushNotificationConfigRequest.newBuilder() - .setConfig(config) .setTaskId(MINIMAL_TASK.id()) .build(); 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 926b9b363..29a9e95f6 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 @@ -66,7 +66,6 @@ import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.PushNotificationNotSupportedError; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; @@ -651,18 +650,21 @@ public void testSetPushNotificationConfigSuccess() { taskStore.save(MINIMAL_TASK, false); TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder().url("http://example.com") - .id("c295ea44-7543-4f78-b524-7a38915ad6e4").build(), - "tenant"); + = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); CreateTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); TaskPushNotificationConfig taskPushConfigResult - = new TaskPushNotificationConfig( MINIMAL_TASK.id(), - PushNotificationConfig.builder().url("http://example.com") - .id("c295ea44-7543-4f78-b524-7a38915ad6e4").build(), - "tenant"); + = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); Assertions.assertEquals(taskPushConfigResult, response.getResult()); } @@ -676,9 +678,12 @@ public void testGetPushNotificationConfigSuccess() { }; TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), "tenant"); + = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); @@ -689,8 +694,12 @@ public void testGetPushNotificationConfigSuccess() { "c295ea44-7543-4f78-b524-7a38915ad6e4")); GetTaskPushNotificationConfigResponse getResponse = handler.getPushNotificationConfig(getRequest, callContext); - TaskPushNotificationConfig expectedConfig = new TaskPushNotificationConfig(MINIMAL_TASK.id(), - PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); + TaskPushNotificationConfig expectedConfig = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); assertEquals(expectedConfig, getResponse.getResult()); } @@ -731,9 +740,12 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex } }; - TaskPushNotificationConfig config = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), "tenant"); + TaskPushNotificationConfig config = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest stpnRequest = new CreateTaskPushNotificationConfigRequest("1", config); CreateTaskPushNotificationConfigResponse stpnResponse = handler.setPushNotificationConfig(stpnRequest, callContext); @@ -1114,12 +1126,12 @@ public void testPushNotificationsNotSupportedError() { taskStore.save(MINIMAL_TASK, false); TaskPushNotificationConfig config - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder() - .id("c295ea44-7543-4f78-b524-7a38915ad6e4") - .url("http://example.com") - .build(), "tenant"); + = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = CreateTaskPushNotificationConfigRequest.builder() .params(config) @@ -1157,12 +1169,12 @@ public void testOnSetPushNotificationNoPushNotifierConfig() { taskStore.save(MINIMAL_TASK, false); TaskPushNotificationConfig config - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder() - .id("c295ea44-7543-4f78-b524-7a38915ad6e4") - .url("http://example.com") - .build(), "tenant"); + = TaskPushNotificationConfig.builder() + .id("c295ea44-7543-4f78-b524-7a38915ad6e4") + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = CreateTaskPushNotificationConfigRequest.builder() .params(config) @@ -1348,18 +1360,20 @@ public void testListPushNotificationConfig() { }; TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") + = TaskPushNotificationConfig.builder() .id(MINIMAL_TASK.id()) - .build(), "tenant"); + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); - TaskPushNotificationConfig result = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") + TaskPushNotificationConfig result = TaskPushNotificationConfig.builder() .id(MINIMAL_TASK.id()) - .build(), ""); + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); ListTaskPushNotificationConfigsRequest listRequest = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); ListTaskPushNotificationConfigsResponse listResponse = handler.listPushNotificationConfig(listRequest, callContext); @@ -1379,11 +1393,12 @@ public void testListPushNotificationConfigNotSupported() { }; TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") + = TaskPushNotificationConfig.builder() .id(MINIMAL_TASK.id()) - .build(), "tenant"); + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); @@ -1442,11 +1457,12 @@ public void testDeletePushNotificationConfig() { }; TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") + = TaskPushNotificationConfig.builder() .id(MINIMAL_TASK.id()) - .build(), "tenant"); + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); @@ -1470,11 +1486,12 @@ public void testDeletePushNotificationConfigNotSupported() { }; TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") + = TaskPushNotificationConfig.builder() .id(MINIMAL_TASK.id()) - .build(), "tenant"); + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); @@ -1499,11 +1516,12 @@ public void testDeletePushNotificationConfigNoPushConfigStore() { }; TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") + = TaskPushNotificationConfig.builder() .id(MINIMAL_TASK.id()) - .build(), "tenant"); + .taskId(MINIMAL_TASK.id()) + .url("http://example.com") + .tenant("tenant") + .build(); CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); 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 68819d8d8..3e38d00a3 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 @@ -170,10 +170,10 @@ public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContex if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); } - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); + io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(body, builder); builder.setTenant(tenant); - TaskPushNotificationConfig result = requestHandler.onCreateTaskPushNotificationConfig(ProtoUtils.FromProto.CreateTaskPushNotificationConfig(builder), context); + TaskPushNotificationConfig result = requestHandler.onCreateTaskPushNotificationConfig(ProtoUtils.FromProto.createTaskPushNotificationConfig(builder), context); return createSuccessResponse(201, io.a2a.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(result))); } catch (A2AError e) { return createErrorResponse(e); 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 31dcb29f9..bb1f3fe37 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 @@ -346,13 +346,11 @@ public void testPushNotificationConfigSuccess() { String requestBody = """ { + "id": "default-config-id", "taskId": "%s", - "config": { - "id": "default-config-id", - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } }""".formatted(MINIMAL_TASK.id()); @@ -370,10 +368,9 @@ public void testPushNotificationConfigNotSupported() { String requestBody = """ { + "id": "default-config-id", "taskId": "%s", - "pushNotificationConfig": { - "url": "http://example.com" - } + "url": "http://example.com" } """.formatted(MINIMAL_TASK.id()); @@ -391,13 +388,11 @@ public void testGetPushNotificationConfig() { // First, create a push notification config String createRequestBody = """ { + "id": "default-config-id", "taskId": "%s", - "config": { - "id": "default-config-id", - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } + "url": "https://example.com/callback", + "authentication": { + "scheme": "jwt" } }""".formatted(MINIMAL_TASK.id()); RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", createRequestBody, MINIMAL_TASK.id()); From fb06d43b34b252ecd8df5c264e548f3eefb6edfd Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Mon, 9 Mar 2026 09:34:44 +0100 Subject: [PATCH 064/192] fix: Fixing Strimzi version to 0.50.1 instead of latest (#710) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Follow the [`CONTRIBUTING` Guide](../CONTRIBUTING.md). - [ ] Make your Pull Request title in the specification. - Important Prefixes for [release-please](https://github.com/googleapis/release-please): - `fix:` which represents bug fixes, and correlates to a [SemVer](https://semver.org/) patch. - `feat:` represents a new feature, and correlates to a SemVer minor. - `feat!:`, or `fix!:`, `refactor!:`, etc., which represent a breaking change (indicated by the `!`) and will result in a SemVer major. - [ ] Ensure the tests pass - [ ] Appropriate READMEs were updated (if necessary) Fixes # 🦕 Signed-off-by: Emmanuel Hugonnet --- .github/workflows/cloud-deployment-example.yml | 2 +- examples/cloud-deployment/scripts/deploy.sh | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cloud-deployment-example.yml b/.github/workflows/cloud-deployment-example.yml index 5c4e1e01a..7f84f6fc3 100644 --- a/.github/workflows/cloud-deployment-example.yml +++ b/.github/workflows/cloud-deployment-example.yml @@ -27,7 +27,7 @@ jobs: - name: Install Kind run: | - curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64 + curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.30.0/kind-linux-amd64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind kind version diff --git a/examples/cloud-deployment/scripts/deploy.sh b/examples/cloud-deployment/scripts/deploy.sh index fff2a6061..9fc890eee 100755 --- a/examples/cloud-deployment/scripts/deploy.sh +++ b/examples/cloud-deployment/scripts/deploy.sh @@ -177,8 +177,12 @@ if ! kubectl get namespace kafka > /dev/null 2>&1; then fi if ! kubectl get crd kafkas.kafka.strimzi.io > /dev/null 2>&1; then - echo "Installing Strimzi operator..." - kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka + echo "Installing Strimzi operator... at https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.50.1/strimzi-cluster-operator-0.50.1.yaml" + curl -sL 'https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.50.1/strimzi-cluster-operator-0.50.1.yaml' \ + | sed 's/namespace: .*/namespace: kafka/' \ + | kubectl apply -f - -n kafka +# echo "Installing Strimzi operator..." +# kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka echo "Waiting for Strimzi operator deployment to be created..." for i in {1..30}; do From fad1a1513dab33fee5b008c152abd2f6f2c89b9b Mon Sep 17 00:00:00 2001 From: Lee Chae Min Date: Mon, 9 Mar 2026 22:51:13 +0900 Subject: [PATCH 065/192] docs: fix extractTextFromMessage snippet to use record accessors (#713) # Description Replace getParts()/getText() with record accessor methods parts()/text(), use typed Part instead of raw Part, and remove redundant null check that is already enforced by Message's compact constructor. Signed-off-by: Chaemin Lee Co-authored-by: Emmanuel Hugonnet --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6b363d664..27466f91a 100644 --- a/README.md +++ b/README.md @@ -219,11 +219,9 @@ public class WeatherAgentExecutorProducer { private String extractTextFromMessage(Message message) { StringBuilder textBuilder = new StringBuilder(); - if (message.getParts() != null) { - for (Part part : message.getParts()) { - if (part instanceof TextPart textPart) { - textBuilder.append(textPart.getText()); - } + for (Part part : message.parts()) { + if (part instanceof TextPart textPart) { + textBuilder.append(textPart.text()); } } return textBuilder.toString(); From 5e133412c61db2b07f12142258a4fd9f803da92d Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Mon, 9 Mar 2026 17:53:02 +0100 Subject: [PATCH 066/192] feat: propagate OTel context in async ops and fix TransportProtocol config injection (#707) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace direct TransportProtocol enum injection in AgentCardProducer with String injection + TransportProtocol.fromString() to avoid SmallRye Config's HyphenateEnumConverter failing on "HTTP+JSON" values passed via -D flags - Add AsyncManagedExecutorProducer to the OpenTelemetry extras module, using MicroProfile ManagedExecutor to propagate OTel trace context across async boundaries (priority 20, overrides default AsyncExecutorProducer) - Add microprofile-context-propagation-api dependency to opentelemetry/server Fixes #698 🦕 Signed-off-by: Emmanuel Hugonnet --- .../helloworld/AgentCardProducer.java | 3 +- extras/opentelemetry/README.md | 215 ++++++++++++++++++ extras/opentelemetry/pom.xml | 1 + extras/opentelemetry/server/pom.xml | 6 + .../AsyncManagedExecutorProducer.java | 65 ++++++ .../AsyncManagedExecutorProducerTest.java | 181 +++++++++++++++ 6 files changed, 470 insertions(+), 1 deletion(-) create mode 100644 extras/opentelemetry/README.md create mode 100644 extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducer.java create mode 100644 extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducerTest.java diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java index 7ffb4dd09..fb66cc517 100644 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java +++ b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java @@ -17,7 +17,7 @@ public class AgentCardProducer { @ConfigProperty(name = "quarkus.agentcard.protocol", defaultValue = "JSONRPC") - TransportProtocol protocol; + String protocolStr; @Produces @PublicAgentCard @@ -48,6 +48,7 @@ public AgentCard agentCard() { } private AgentInterface getAgentInterface() { + TransportProtocol protocol = TransportProtocol.fromString(protocolStr); String url = switch (protocol) { case GRPC -> "localhost:9000"; case JSONRPC, HTTP_JSON -> "http://localhost:9999"; diff --git a/extras/opentelemetry/README.md b/extras/opentelemetry/README.md new file mode 100644 index 000000000..7ea5ed427 --- /dev/null +++ b/extras/opentelemetry/README.md @@ -0,0 +1,215 @@ +# OpenTelemetry Integration for A2A + +This module provides OpenTelemetry observability integration for A2A servers, including distributed tracing, metrics, and context propagation across asynchronous boundaries. + +## Features + +- **Distributed Tracing**: Automatic span creation for all A2A protocol methods +- **Context Propagation**: OpenTelemetry trace context propagation across async operations +- **Request/Response Logging**: Optional extraction of request and response data into spans +- **Error Tracking**: Automatic error status and error type attributes on failures + +## Modules + +### `opentelemetry-common` +Common utilities and constants shared across OpenTelemetry modules. + +### `opentelemetry-client` +OpenTelemetry integration for A2A clients. + +### `opentelemetry-client-propagation` +Context propagation support for A2A clients. + +### `opentelemetry-server` +OpenTelemetry integration for A2A servers, including the context-aware executor. + +### `opentelemetry-integration-tests` +Integration tests for OpenTelemetry functionality. + +## Usage + +### Basic Setup + +Add the OpenTelemetry server module to your dependencies: + +```xml + + io.a2a + a2a-extras-opentelemetry-server + ${a2a.version} + +``` + +### Context-Aware Async Executor + +The `AsyncManagedExecutorProducer` provides a `ManagedExecutor` that automatically propagates OpenTelemetry trace context across asynchronous boundaries. This ensures that spans created in async tasks are properly linked to their parent spans. + +#### How It Works + +When the OpenTelemetry server module is included, the `AsyncManagedExecutorProducer` automatically replaces the default `AsyncExecutorProducer` using CDI alternatives: + +- **Priority 20**: Takes precedence over the default executor producer (priority 10) +- **Automatic Activation**: No configuration needed - just include the module +- **Context Propagation**: Uses MicroProfile Context Propagation to maintain trace context + +#### Configuration + +The `ManagedExecutor` is container-managed and configured through your runtime environment: + +**Quarkus:** +```properties +# Configure the managed executor pool +quarkus.thread-pool.core-threads=10 +quarkus.thread-pool.max-threads=50 +quarkus.thread-pool.queue-size=100 +``` + +**Other Runtimes:** +Consult your MicroProfile Context Propagation implementation documentation for configuration options. + +> **Note**: Unlike the default `AsyncExecutorProducer`, the `AsyncManagedExecutorProducer` does not use the `a2a.executor.*` configuration properties. Pool sizing is controlled by the container's ManagedExecutor configuration. + +#### Example + +```java +@ApplicationScoped +public class MyAgent implements Agent { + + @Inject + @Internal + Executor executor; // Automatically uses ManagedExecutor with context propagation + + @Override + public void execute(RequestContext context, AgentEmitter emitter) { + // Current span context is automatically propagated + executor.execute(() -> { + // This code runs in a different thread but maintains the trace context + Span currentSpan = Span.current(); + currentSpan.addEvent("Processing in async task"); + + // Do async work... + }); + } +} +``` + +### Request/Response Extraction + +Enable request and response data extraction in spans: + +```properties +# Extract request parameters into span attributes +a2a.opentelemetry.extract-request=true + +# Extract response data into span attributes +a2a.opentelemetry.extract-response=true +``` + +> **Warning**: Extracting request/response data may expose sensitive information in traces. Use with caution in production environments. + +### Span Attributes + +The following attributes are automatically added to spans: + +- `genai.request`: Request parameters (if extraction enabled) +- `genai.response`: Response data (if extraction enabled) +- `error.type`: Error message (on failures) + +## Architecture + +### Request Handler Decoration + +The `OpenTelemetryRequestHandlerDecorator` wraps the default request handler and creates spans for each A2A protocol method: + +``` +Client Request + ↓ +OpenTelemetryRequestHandlerDecorator + ↓ (creates span) +Default RequestHandler + ↓ +Agent Execution (with context propagation) + ↓ +Response +``` + +### Context Propagation Flow + +``` +HTTP Request (with trace headers) + ↓ +OpenTelemetry extracts context + ↓ +Span created for A2A method + ↓ +ManagedExecutor propagates context + ↓ +Async agent execution (maintains trace context) + ↓ +Response (with trace headers) +``` + +## Testing + +The module includes comprehensive unit tests: + +- `AsyncManagedExecutorProducerTest`: Tests for the context-aware executor producer +- `OpenTelemetryRequestHandlerDecoratorTest`: Tests for span creation and error handling + +Run tests: +```bash +mvn test -pl extras/opentelemetry/server +``` + +## Troubleshooting + +### Context Not Propagating + +**Symptom**: Spans in async tasks are not linked to parent spans. + +**Solution**: Ensure the OpenTelemetry server module is included and the `ManagedExecutor` is being injected correctly. Check logs for: +``` +Initializing OpenTelemetry-aware ManagedExecutor for async operations +``` + +### ManagedExecutor Not Available + +**Symptom**: `IllegalStateException: ManagedExecutor not injected - ensure MicroProfile Context Propagation is available` + +**Solution**: Ensure your runtime provides MicroProfile Context Propagation support. For Quarkus, add: +```xml + + io.quarkus + quarkus-smallrye-context-propagation + +``` + +### Performance Impact + +**Symptom**: Increased latency with OpenTelemetry enabled. + +**Solution**: +- Disable request/response extraction in production +- Configure sampling rate to reduce trace volume +- Ensure your OpenTelemetry collector is properly sized + +## Best Practices + +1. **Sampling**: Configure appropriate sampling rates for production environments +2. **Sensitive Data**: Disable request/response extraction if handling sensitive data +3. **Resource Attributes**: Add service name and version as resource attributes +4. **Collector Configuration**: Use batch processors to reduce network overhead +5. **Monitoring**: Monitor the OpenTelemetry collector's health and performance + +## Dependencies + +- MicroProfile Telemetry 2.0.1+ +- MicroProfile Context Propagation 1.3+ +- OpenTelemetry API +- A2A Server Common + +## See Also + +- [OpenTelemetry Documentation](https://opentelemetry.io/docs/) +- [MicroProfile Telemetry Specification](https://github.com/eclipse/microprofile-telemetry) +- [MicroProfile Context Propagation](https://github.com/eclipse/microprofile-context-propagation) diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 0741ff55a..8d8ccd8da 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -19,6 +19,7 @@ 2.0.1 + 1.3 diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index afc62d631..3a7cb44a9 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -39,6 +39,12 @@ pom provided + + org.eclipse.microprofile.context-propagation + microprofile-context-propagation-api + ${version.org.eclipse.microprofile.context-propagation} + provided + jakarta.enterprise jakarta.enterprise.cdi-api diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducer.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducer.java new file mode 100644 index 000000000..cd30196e1 --- /dev/null +++ b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducer.java @@ -0,0 +1,65 @@ +package io.a2a.extras.opentelemetry; + +import io.a2a.server.util.async.Internal; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Priority; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Alternative; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import java.util.concurrent.Executor; +import org.eclipse.microprofile.context.ManagedExecutor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Alternative executor producer that provides a ManagedExecutor with OpenTelemetry context propagation. + *

        + * This producer replaces the default {@code AsyncExecutorProducer} when the OpenTelemetry extras module + * is included in the application. The ManagedExecutor ensures that OpenTelemetry trace context is + * properly propagated across asynchronous boundaries. + *

        + * Priority 20 ensures this alternative takes precedence over the default producer (priority 10). + * + *

        Configuration

        + * The ManagedExecutor is container-managed and injected via CDI. Its configuration depends on the + * runtime environment: + *
          + *
        • Quarkus: Configure via {@code quarkus.thread-pool.*} properties
        • + *
        • Other runtimes: Consult your MicroProfile Context Propagation implementation documentation
        • + *
        + *

        + * Unlike the default {@code AsyncExecutorProducer}, this producer does not use the {@code a2a.executor.*} + * configuration properties. The executor pool sizing and behavior are controlled by the container's + * ManagedExecutor configuration. + * + * @see org.eclipse.microprofile.context.ManagedExecutor + */ +@ApplicationScoped +@Alternative +@Priority(20) +public class AsyncManagedExecutorProducer { + private static final Logger LOGGER = LoggerFactory.getLogger(AsyncManagedExecutorProducer.class); + + @Inject + ManagedExecutor managedExecutor; + + @PostConstruct + public void init() { + LOGGER.info("Initializing OpenTelemetry-aware ManagedExecutor for async operations"); + if (managedExecutor == null) { + LOGGER.warn("ManagedExecutor not available - context propagation may not work correctly"); + } + } + + @Produces + @Internal + public Executor produce() { + LOGGER.debug("Using ManagedExecutor for async operations with OpenTelemetry context propagation"); + if (managedExecutor == null) { + throw new IllegalStateException("ManagedExecutor not injected - ensure MicroProfile Context Propagation is available"); + } + return managedExecutor; + } + +} diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducerTest.java b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducerTest.java new file mode 100644 index 000000000..ff4c86a16 --- /dev/null +++ b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducerTest.java @@ -0,0 +1,181 @@ +package io.a2a.extras.opentelemetry; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.concurrent.Executor; +import org.eclipse.microprofile.context.ManagedExecutor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class AsyncManagedExecutorProducerTest { + + @Mock + private ManagedExecutor managedExecutor; + + private AsyncManagedExecutorProducer producer; + + @BeforeEach + void setUp() { + producer = new AsyncManagedExecutorProducer(); + } + + @Nested + class InitializationTests { + @Test + void init_withValidManagedExecutor_logsSuccessfully() { + producer.managedExecutor = managedExecutor; + + assertDoesNotThrow(() -> producer.init()); + assertNotNull(producer.managedExecutor); + } + + @Test + void init_withNullManagedExecutor_logsWarning() { + producer.managedExecutor = null; + + // Should not throw, just log warning + assertDoesNotThrow(() -> producer.init()); + assertNull(producer.managedExecutor); + } + } + + @Nested + class ProduceTests { + @Test + void produce_withValidManagedExecutor_returnsExecutor() { + producer.managedExecutor = managedExecutor; + + Executor result = producer.produce(); + + assertNotNull(result); + assertSame(managedExecutor, result); + } + + @Test + void produce_withNullManagedExecutor_throwsIllegalStateException() { + producer.managedExecutor = null; + + IllegalStateException exception = assertThrows( + IllegalStateException.class, + () -> producer.produce() + ); + + assertEquals( + "ManagedExecutor not injected - ensure MicroProfile Context Propagation is available", + exception.getMessage() + ); + } + + @Test + void produce_returnsSameInstanceOnMultipleCalls() { + producer.managedExecutor = managedExecutor; + + Executor result1 = producer.produce(); + Executor result2 = producer.produce(); + + assertSame(result1, result2); + assertSame(managedExecutor, result1); + } + } + + @Nested + class CDIIntegrationTests { + @Test + void producer_hasCorrectAnnotations() { + // Verify class has @ApplicationScoped + assertTrue( + AsyncManagedExecutorProducer.class.isAnnotationPresent( + jakarta.enterprise.context.ApplicationScoped.class + ) + ); + + // Verify class has @Alternative + assertTrue( + AsyncManagedExecutorProducer.class.isAnnotationPresent( + jakarta.enterprise.inject.Alternative.class + ) + ); + + // Verify class has @Priority with value 20 + assertTrue( + AsyncManagedExecutorProducer.class.isAnnotationPresent( + jakarta.annotation.Priority.class + ) + ); + assertEquals( + 20, + AsyncManagedExecutorProducer.class.getAnnotation( + jakarta.annotation.Priority.class + ).value() + ); + } + + @Test + void produceMethod_hasCorrectAnnotations() throws NoSuchMethodException { + var method = AsyncManagedExecutorProducer.class.getMethod("produce"); + + // Verify method has @Produces + assertTrue( + method.isAnnotationPresent(jakarta.enterprise.inject.Produces.class) + ); + + // Verify method has @Internal + assertTrue( + method.isAnnotationPresent(io.a2a.server.util.async.Internal.class) + ); + } + + @Test + void initMethod_hasPostConstructAnnotation() throws NoSuchMethodException { + var method = AsyncManagedExecutorProducer.class.getMethod("init"); + + assertTrue( + method.isAnnotationPresent(jakarta.annotation.PostConstruct.class) + ); + } + + @Test + void managedExecutorField_hasInjectAnnotation() throws NoSuchFieldException { + var field = AsyncManagedExecutorProducer.class.getDeclaredField("managedExecutor"); + + assertTrue( + field.isAnnotationPresent(jakarta.inject.Inject.class) + ); + } + } + + @Nested + class ExecutorBehaviorTests { + @Test + void producedExecutor_canExecuteRunnables() { + producer.managedExecutor = managedExecutor; + Runnable task = mock(Runnable.class); + + Executor executor = producer.produce(); + executor.execute(task); + + verify(managedExecutor).execute(task); + } + + @Test + void producedExecutor_delegatesToManagedExecutor() { + producer.managedExecutor = managedExecutor; + Runnable task1 = mock(Runnable.class); + Runnable task2 = mock(Runnable.class); + + Executor executor = producer.produce(); + executor.execute(task1); + executor.execute(task2); + + verify(managedExecutor).execute(task1); + verify(managedExecutor).execute(task2); + verifyNoMoreInteractions(managedExecutor); + } + } +} From ad22286ad97222b97e317d8f4737987e4a65d9f7 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 9 Mar 2026 17:03:43 +0000 Subject: [PATCH 067/192] fix: Add Javadoc for the jsonrpc server-side components (#679) Fixes: #478 --- .../server/apps/quarkus/A2AServerRoutes.java | 420 +++++++++++++++++- .../apps/quarkus/CallContextFactory.java | 64 +++ .../QuarkusJSONRPCTransportMetadata.java | 37 ++ .../a2a/server/apps/quarkus/package-info.java | 170 +++++++ .../jsonrpc/context/JSONRPCContextKeys.java | 16 +- .../jsonrpc/handler/JSONRPCHandler.java | 415 +++++++++++++++++ .../jsonrpc/handler/package-info.java | 31 ++ 7 files changed, 1139 insertions(+), 14 deletions(-) create mode 100644 reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/package-info.java 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 ceded1fc4..a7b9f93e1 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 @@ -79,6 +79,93 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Quarkus routing configuration for JSON-RPC A2A protocol requests. + * + *

        This class defines Vert.x Web routes for handling JSON-RPC 2.0 requests over HTTP, + * processing them through the {@link JSONRPCHandler}, and returning responses in either + * standard JSON or Server-Sent Events (SSE) format for streaming operations. + * + *

        Request Flow

        + *
        + * HTTP POST / → invokeJSONRPCHandler()
        + *     ↓
        + * Parse JSON-RPC request body
        + *     ↓
        + * Route to handler method (blocking or streaming)
        + *     ↓
        + * JSONRPCHandler → RequestHandler → AgentExecutor
        + *     ↓
        + * Response (JSON or SSE stream)
        + * 
        + * + *

        Supported Operations

        + *

        Non-Streaming (JSON responses): + *

          + *
        • {@code sendMessage} - Send message and wait for completion
        • + *
        • {@code getTask} - Retrieve task by ID
        • + *
        • {@code cancelTask} - Cancel task execution
        • + *
        • {@code listTasks} - List tasks with filtering
        • + *
        • {@code setTaskPushNotificationConfig} - Configure push notifications
        • + *
        • {@code getTaskPushNotificationConfig} - Get push notification config
        • + *
        • {@code listTaskPushNotificationConfig} - List push notification configs
        • + *
        • {@code deleteTaskPushNotificationConfig} - Delete push notification config
        • + *
        • {@code getExtendedAgentCard} - Get extended agent capabilities
        • + *
        + * + *

        Streaming (SSE responses): + *

          + *
        • {@code sendStreamingMessage} - Send message with streaming response
        • + *
        • {@code subscribeToTask} - Subscribe to task events
        • + *
        + * + *

        JSON-RPC Request Format

        + *
        {@code
        + * POST /
        + * Content-Type: application/json
        + *
        + * {
        + *   "jsonrpc": "2.0",
        + *   "id": "req-123",
        + *   "method": "sendMessage",
        + *   "params": {
        + *     "message": {
        + *       "parts": [{"text": "Hello"}]
        + *     }
        + *   }
        + * }
        + * }
        + * + *

        Error Handling

        + *

        Errors are mapped to JSON-RPC 2.0 error responses: + *

          + *
        • {@link JsonSyntaxException} → {@link JSONParseError}
        • + *
        • {@link InvalidParamsJsonMappingException} → {@link io.a2a.spec.InvalidParamsError}
        • + *
        • {@link MethodNotFoundJsonMappingException} → {@link io.a2a.spec.MethodNotFoundError}
        • + *
        • {@link IdJsonMappingException} → {@link io.a2a.spec.InvalidRequestError}
        • + *
        • {@link Throwable} → {@link InternalError}
        • + *
        + * + *

        CDI Integration

        + *

        This class is a CDI {@code @Singleton} that automatically wires: + *

          + *
        • {@link JSONRPCHandler} - Core protocol handler
        • + *
        • {@link Executor} - Async execution for streaming
        • + *
        • {@link CallContextFactory} (optional) - Custom context creation
        • + *
        + * + *

        Multi-Tenancy Support

        + *

        Tenant identification is extracted from the request path: + *

          + *
        • {@code POST /} → empty tenant
        • + *
        • {@code POST /tenant1} → tenant "tenant1"
        • + *
        • {@code POST /tenant1/} → tenant "tenant1" (trailing slash stripped)
        • + *
        + * + * @see JSONRPCHandler + * @see CallContextFactory + * @see MultiSseSupport + */ @Singleton public class A2AServerRoutes { @@ -96,6 +183,78 @@ public class A2AServerRoutes { @Inject Instance callContextFactory; + /** + * Main entry point for all JSON-RPC requests. + * + *

        This route handler processes JSON-RPC 2.0 requests, dispatches them to the appropriate + * handler method based on the request type (streaming vs non-streaming), and returns either + * a JSON response or an SSE stream. + * + *

        Request Format: + *

        {@code
        +     * POST /[tenant]
        +     * Content-Type: application/json
        +     *
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "req-123",
        +     *   "method": "sendMessage",
        +     *   "params": { ... }
        +     * }
        +     * }
        + * + *

        Non-Streaming Response: + *

        {@code
        +     * HTTP/1.1 200 OK
        +     * Content-Type: application/json
        +     *
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "req-123",
        +     *   "result": { ... }
        +     * }
        +     * }
        + * + *

        Streaming Response (SSE): + *

        {@code
        +     * HTTP/1.1 200 OK
        +     * Content-Type: text/event-stream
        +     *
        +     * id: 0
        +     * data: {"jsonrpc":"2.0","id":"req-123","result":{...}}
        +     *
        +     * id: 1
        +     * data: {"jsonrpc":"2.0","id":"req-123","result":{...}}
        +     * }
        + * + *

        Error Response: + *

        {@code
        +     * HTTP/1.1 200 OK
        +     * Content-Type: application/json
        +     *
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "req-123",
        +     *   "error": {
        +     *     "code": -32602,
        +     *     "message": "Invalid params"
        +     *   }
        +     * }
        +     * }
        + * + *

        Processing Flow: + *

          + *
        1. Parse JSON-RPC request body using {@link JSONRPCUtils#parseRequestBody}
        2. + *
        3. Create {@link ServerCallContext} from routing context
        4. + *
        5. Route to streaming or non-streaming handler
        6. + *
        7. Handle errors with appropriate JSON-RPC error codes
        8. + *
        9. Return JSON response or start SSE stream
        10. + *
        + * + * @param body the raw JSON-RPC request body + * @param rc the Vert.x routing context containing HTTP request/response + * @throws A2AError if request processing fails + */ @Route(path = "/", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) @Authenticated public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { @@ -157,17 +316,64 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { } /** - * /** - * Handles incoming GET requests to the agent card endpoint. - * Returns the agent card in JSON format. + * Handles GET requests to the agent card endpoint. + * + *

        Returns the agent's capabilities and metadata in JSON format according to the + * A2A protocol specification. This endpoint is publicly accessible (no authentication). + * + *

        Request: + *

        {@code
        +     * GET /.well-known/agent-card.json
        +     * }
        + * + *

        Response: + *

        {@code
        +     * HTTP/1.1 200 OK
        +     * Content-Type: application/json
              *
        -     * @return the agent card
        +     * {
        +     *   "name": "My Agent",
        +     *   "description": "Agent description",
        +     *   "capabilities": {
        +     *     "streaming": true,
        +     *     "pushNotifications": false
        +     *   },
        +     *   ...
        +     * }
        +     * }
        + * + * @return the agent card as a JSON string + * @throws JsonProcessingException if serialization fails + * @see JSONRPCHandler#getAgentCard() */ @Route(path = "/.well-known/agent-card.json", methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) public String getAgentCard() throws JsonProcessingException { return JsonUtil.toJson(jsonRpcHandler.getAgentCard()); } + /** + * Routes non-streaming JSON-RPC requests to the appropriate handler method. + * + *

        This method uses pattern matching to dispatch requests based on their type, + * invoking the corresponding handler method in {@link JSONRPCHandler}. + * + *

        Supported Request Types: + *

          + *
        • {@link GetTaskRequest} → {@link JSONRPCHandler#onGetTask}
        • + *
        • {@link CancelTaskRequest} → {@link JSONRPCHandler#onCancelTask}
        • + *
        • {@link ListTasksRequest} → {@link JSONRPCHandler#onListTasks}
        • + *
        • {@link SendMessageRequest} → {@link JSONRPCHandler#onMessageSend}
        • + *
        • {@link CreateTaskPushNotificationConfigRequest} → {@link JSONRPCHandler#setPushNotificationConfig}
        • + *
        • {@link GetTaskPushNotificationConfigRequest} → {@link JSONRPCHandler#getPushNotificationConfig}
        • + *
        • {@link ListTaskPushNotificationConfigRequest} → {@link JSONRPCHandler#listPushNotificationConfig}
        • + *
        • {@link DeleteTaskPushNotificationConfigRequest} → {@link JSONRPCHandler#deletePushNotificationConfig}
        • + *
        • {@link GetExtendedAgentCardRequest} → {@link JSONRPCHandler#onGetExtendedCardRequest}
        • + *
        + * + * @param request the non-streaming JSON-RPC request + * @param context the server call context + * @return the JSON-RPC response + */ private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest request, ServerCallContext context) { if (request instanceof GetTaskRequest req) { return jsonRpcHandler.onGetTask(req, context); @@ -199,6 +405,22 @@ private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest return generateErrorResponse(request, new UnsupportedOperationError()); } + /** + * Routes streaming JSON-RPC requests to the appropriate handler method. + * + *

        This method dispatches streaming requests to handlers that return + * {@link Flow.Publisher} of responses, which are then converted to SSE streams. + * + *

        Supported Request Types: + *

          + *
        • {@link SendStreamingMessageRequest} → {@link JSONRPCHandler#onMessageSendStream}
        • + *
        • {@link SubscribeToTaskRequest} → {@link JSONRPCHandler#onSubscribeToTask}
        • + *
        + * + * @param request the streaming JSON-RPC request + * @param context the server call context + * @return a Multi stream of JSON-RPC responses + */ private Multi> processStreamingRequest( A2ARequest request, ServerCallContext context) { Flow.Publisher> publisher; @@ -212,14 +434,55 @@ private Multi> processStreamingRequest( return Multi.createFrom().publisher(publisher); } + /** + * Generates a JSON-RPC error response for the given request and error. + * + * @param request the original request + * @param error the A2A error to include in the response + * @return a JSON-RPC error response + */ private A2AResponse generateErrorResponse(A2ARequest request, A2AError error) { return new A2AErrorResponse(request.getId(), error); } + /** + * Sets a callback to be invoked when SSE streaming subscription starts. + * + *

        This is a testing hook used to synchronize test execution with streaming setup. + * In production, this remains null. + * + * @param runnable the callback to invoke on subscription + */ static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { streamingMultiSseSupportSubscribedRunnable = runnable; } + /** + * Creates a {@link ServerCallContext} from the Vert.x routing context. + * + *

        This method extracts authentication, headers, tenant, and protocol information + * from the HTTP request and packages them into a context object for use by the + * request handler and agent executor. + * + *

        Default Context Creation: + *

        If no {@link CallContextFactory} CDI bean is provided, creates a context with: + *

          + *
        • User authentication from Quarkus Security
        • + *
        • HTTP headers map
        • + *
        • Tenant ID from request path
        • + *
        • Transport protocol ({@link TransportProtocol#JSONRPC})
        • + *
        • A2A protocol version from {@code X-A2A-Version} header
        • + *
        • Required extensions from {@code X-A2A-Extensions} header
        • + *
        + * + *

        Custom Context Creation: + *

        If a {@link CallContextFactory} bean is present, delegates to + * {@link CallContextFactory#build(RoutingContext)} for custom context creation. + * + * @param rc the Vert.x routing context + * @return the server call context + * @see CallContextFactory + */ private ServerCallContext createCallContext(RoutingContext rc) { if (callContextFactory.isUnsatisfied()) { User user; @@ -264,6 +527,21 @@ public String getUsername() { } } + /** + * Extracts the tenant identifier from the request path. + * + *

        The tenant is determined by the normalized path, with leading and trailing + * slashes stripped: + *

          + *
        • {@code /} → empty tenant
        • + *
        • {@code /tenant1} → "tenant1"
        • + *
        • {@code /tenant1/} → "tenant1"
        • + *
        • {@code /org/team} → "org/team"
        • + *
        + * + * @param rc the routing context + * @return the tenant identifier, or empty string if no tenant in path + */ private String extractTenant(RoutingContext rc) { String tenantPath = rc.normalizedPath(); if (tenantPath == null || tenantPath.isBlank()) { @@ -278,6 +556,39 @@ private String extractTenant(RoutingContext rc) { return tenantPath; } + /** + * Serializes a JSON-RPC response to a JSON string. + * + *

        This method handles both success and error responses, converting domain objects + * to protobuf messages before JSON serialization for consistency with the gRPC transport. + * + *

        Success Response Format: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "req-123",
        +     *   "result": { ... }
        +     * }
        +     * }
        + * + *

        Error Response Format: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "req-123",
        +     *   "error": {
        +     *     "code": -32602,
        +     *     "message": "Invalid params",
        +     *     "data": { ... }
        +     *   }
        +     * }
        +     * }
        + * + * @param response the response to serialize + * @return the JSON string + * @see JSONRPCUtils#toJsonRPCResultResponse + * @see JSONRPCUtils#toJsonRPCErrorResponse + */ private static String serializeResponse(A2AResponse response) { // For error responses, use Jackson serialization (errors are standardized) if (response instanceof A2AErrorResponse error) { @@ -291,6 +602,32 @@ private static String serializeResponse(A2AResponse response) { return JSONRPCUtils.toJsonRPCResultResponse(response.getId(), protoMessage); } + /** + * Converts a domain response object to its protobuf representation. + * + *

        This method maps response types to their corresponding protobuf messages + * using {@link io.a2a.grpc.utils.ProtoUtils}, ensuring consistent serialization + * across all transports (JSON-RPC, gRPC, REST). + * + *

        Supported Response Types: + *

          + *
        • {@link GetTaskResponse} → Task protobuf message
        • + *
        • {@link CancelTaskResponse} → Task protobuf message
        • + *
        • {@link SendMessageResponse} → TaskOrMessage protobuf message
        • + *
        • {@link ListTasksResponse} → ListTasksResult protobuf message
        • + *
        • {@link CreateTaskPushNotificationConfigResponse} → CreateTaskPushNotificationConfigResponse protobuf message
        • + *
        • {@link GetTaskPushNotificationConfigResponse} → GetTaskPushNotificationConfigResponse protobuf message
        • + *
        • {@link ListTaskPushNotificationConfigResponse} → ListTaskPushNotificationConfigResponse protobuf message
        • + *
        • {@link DeleteTaskPushNotificationConfigResponse} → Empty protobuf message
        • + *
        • {@link GetExtendedAgentCardResponse} → GetExtendedCardResponse protobuf message
        • + *
        • {@link SendStreamingMessageResponse} → TaskOrMessageStream protobuf message
        • + *
        + * + * @param response the domain response object + * @return the protobuf message representation + * @throws IllegalArgumentException if the response type is unknown + * @see io.a2a.grpc.utils.ProtoUtils + */ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse response) { if (response instanceof GetTaskResponse r) { return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); @@ -319,10 +656,45 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse - * This class only handles HTTP-specific concerns (writing to response, backpressure, disconnect). - * SSE formatting and JSON serialization are handled by {@link SseFormatter}. + * Server-Sent Events (SSE) support for streaming JSON-RPC responses. + * + *

        This class handles the HTTP-specific aspects of SSE streaming, including: + *

          + *
        • Writing SSE-formatted events to the HTTP response
        • + *
        • Managing backpressure through reactive streams
        • + *
        • Detecting client disconnections and canceling upstream
        • + *
        • Setting appropriate HTTP headers for SSE
        • + *
        + * + *

        SSE Format

        + *

        Events are written in Server-Sent Events format: + *

        +     * id: 0
        +     * data: {"jsonrpc":"2.0","id":"req-123","result":{...}}
        +     *
        +     * id: 1
        +     * data: {"jsonrpc":"2.0","id":"req-123","result":{...}}
        +     * 
        + * + *

        Backpressure Handling

        + *

        Uses reactive streams subscription to handle backpressure: + *

          + *
        1. Request 1 event from upstream
        2. + *
        3. Write event to HTTP response
        4. + *
        5. Wait for write completion
        6. + *
        7. Request next event (backpressure)
        8. + *
        + * + *

        Disconnect Handling

        + *

        When the client disconnects: + *

          + *
        1. Vert.x closeHandler fires
        2. + *
        3. Invokes {@link ServerCallContext#invokeEventConsumerCancelCallback()}
        4. + *
        5. Cancels upstream subscription
        6. + *
        7. Stops event polling
        8. + *
        + * + * @see SseFormatter */ private static class MultiSseSupport { private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); @@ -332,11 +704,35 @@ private MultiSseSupport() { } /** - * Write SSE-formatted strings to HTTP response. + * Writes SSE-formatted strings to the HTTP response with backpressure handling. + * + *

        This method subscribes to the SSE event stream and writes each event to the + * HTTP response, managing backpressure through the reactive streams subscription. + * + *

        Subscription Flow: + *

          + *
        1. Subscribe to SSE stream
        2. + *
        3. Register disconnect handler
        4. + *
        5. Request first event
        6. + *
        7. Write event to response
        8. + *
        9. Wait for write completion
        10. + *
        11. Request next event (backpressure)
        12. + *
        + * + *

        HTTP Headers: + *

        Sets {@code Content-Type: text/event-stream} on first write + * + *

        Error Handling: + *

          + *
        • Client disconnect → cancel upstream, stop polling
        • + *
        • Write failure → cancel upstream, fail routing context
        • + *
        • Stream error → cancel upstream, fail routing context
        • + *
        * - * @param sseStrings Multi stream of SSE-formatted strings (from SseFormatter) - * @param rc Vert.x routing context - * @param context A2A server call context (for EventConsumer cancellation) + * @param sseStrings Multi stream of SSE-formatted strings from {@link SseFormatter} + * @param rc the Vert.x routing context + * @param context the A2A server call context (for EventConsumer cancellation) + * @see SseFormatter#formatResponseAsSSE */ public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { HttpServerResponse response = rc.response(); diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java index d40bc65f0..64b98c962 100644 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java +++ b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java @@ -3,6 +3,70 @@ import io.a2a.server.ServerCallContext; import io.vertx.ext.web.RoutingContext; +/** + * Factory interface for creating {@link ServerCallContext} from Vert.x routing context. + * + *

        This interface provides an extension point for customizing how {@link ServerCallContext} + * instances are created in Quarkus JSON-RPC applications. The default implementation in + * {@link A2AServerRoutes} extracts standard information (user, headers, tenant, protocol version), + * but applications can provide their own implementation to add custom context data. + * + *

        Default Behavior

        + *

        When no CDI bean implementing this interface is provided, {@link A2AServerRoutes} + * creates contexts with: + *

          + *
        • User authentication from Quarkus Security
        • + *
        • HTTP headers map
        • + *
        • Tenant ID from request path
        • + *
        • A2A protocol version from {@code X-A2A-Version} header
        • + *
        • Required extensions from {@code X-A2A-Extensions} header
        • + *
        + * + *

        Custom Implementation Example

        + *
        {@code
        + * @ApplicationScoped
        + * public class CustomCallContextFactory implements CallContextFactory {
        + *     @Override
        + *     public ServerCallContext build(RoutingContext rc) {
        + *         // Extract user from Quarkus security context
        + *         User user = (rc.user() == null) ? UnauthenticatedUser.INSTANCE :
        + *             new User() {
        + *                 public boolean isAuthenticated() { return rc.userContext().authenticated(); }
        + *                 public String getUsername() { return rc.user().subject(); }
        + *             };
        + *
        + *         // Extract custom data from routing context
        + *         String orgId = rc.request().getHeader("X-Organization-ID");
        + *
        + *         Map state = new HashMap<>();
        + *         state.put("organization", orgId);
        + *         state.put("requestId", UUID.randomUUID().toString());
        + *
        + *         // Extract A2A protocol version from header
        + *         String version = rc.request().getHeader(A2AHeaders.X_A2A_VERSION);
        + *
        + *         // Extract requested extensions from header
        + *         List extensionHeaders = rc.request().headers().getAll(A2AHeaders.X_A2A_EXTENSIONS);
        + *         Set extensions = A2AExtensions.getRequestedExtensions(extensionHeaders);
        + *
        + *         return new ServerCallContext(user, state, extensions, version);
        + *     }
        + * }
        + * }
        + * + * @see ServerCallContext + * @see A2AServerRoutes#createCallContext(RoutingContext) + */ public interface CallContextFactory { + /** + * Builds a {@link ServerCallContext} from a Vert.x routing context. + * + *

        This method is called for each incoming HTTP request to create the context + * that will be passed to the {@link io.a2a.server.requesthandlers.RequestHandler} + * and eventually to the {@link io.a2a.server.agentexecution.AgentExecutor}. + * + * @param rc the Vert.x routing context containing request data + * @return a new ServerCallContext with extracted authentication, headers, and metadata + */ ServerCallContext build(RoutingContext rc); } diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java index 5cff0d7f7..02f2bd3f5 100644 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java +++ b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java @@ -3,8 +3,45 @@ import io.a2a.server.TransportMetadata; import io.a2a.spec.TransportProtocol; +/** + * Transport metadata provider for the Quarkus JSON-RPC reference implementation. + * + *

        This class identifies the transport protocol used by the JSON-RPC server implementation. + * It is automatically discovered by the A2A server framework through CDI to provide + * protocol-specific metadata to components that need to distinguish between different + * transport implementations. + * + *

        CDI Integration

        + *

        This bean is automatically registered and can be injected where transport + * protocol information is needed: + *

        {@code
        + * @Inject
        + * TransportMetadata transportMetadata;
        + *
        + * public void logProtocol() {
        + *     String protocol = transportMetadata.getTransportProtocol();
        + *     // Returns "jsonrpc" for this implementation
        + * }
        + * }
        + * + *

        Use Cases

        + *
          + *
        • Identifying the active transport protocol in multi-transport deployments
        • + *
        • Conditional logic based on transport capabilities
        • + *
        • Logging and metrics collection with transport-specific tags
        • + *
        • Protocol-specific error handling or feature detection
        • + *
        + * + * @see io.a2a.server.TransportMetadata + * @see io.a2a.spec.TransportProtocol + */ public class QuarkusJSONRPCTransportMetadata implements TransportMetadata { + /** + * Returns the transport protocol identifier for JSON-RPC. + * + * @return the string "jsonrpc" identifying this transport implementation + */ @Override public String getTransportProtocol() { return TransportProtocol.JSONRPC.asString(); diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/package-info.java b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/package-info.java new file mode 100644 index 000000000..bf47f0340 --- /dev/null +++ b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/package-info.java @@ -0,0 +1,170 @@ +/** + * Quarkus JSON-RPC reference implementation for the A2A protocol. + * + *

        This package provides a production-ready JSON-RPC 2.0 server implementation built on + * Quarkus and Vert.x Web, demonstrating best practices for A2A protocol integration. + * + *

        Architecture

        + *
        + * HTTP Request (JSON-RPC 2.0)
        + *     ↓
        + * A2AServerRoutes (@Singleton)
        + *     ├─ Parse JSON-RPC request
        + *     ├─ Create ServerCallContext (via CallContextFactory)
        + *     ├─ Route to JSONRPCHandler
        + *     └─ Return JSON or SSE stream
        + *         ↓
        + * JSONRPCHandler (transport layer)
        + *     ↓
        + * DefaultRequestHandler (server-common)
        + *     ↓
        + * AgentExecutor (your implementation)
        + * 
        + * + *

        Core Components

        + *
          + *
        • {@link io.a2a.server.apps.quarkus.A2AServerRoutes A2AServerRoutes} - Vert.x Web routing and request handling
        • + *
        • {@link io.a2a.server.apps.quarkus.CallContextFactory CallContextFactory} - Extension point for custom context creation
        • + *
        • {@link io.a2a.server.apps.quarkus.QuarkusJSONRPCTransportMetadata QuarkusJSONRPCTransportMetadata} - Transport protocol identification
        • + *
        + * + *

        JSON-RPC Endpoint

        + *

        Main Endpoint: {@code POST /[tenant]} + *

        Agent Card: {@code GET /.well-known/agent-card.json} + * + *

        Request Format

        + *
        {@code
        + * POST /
        + * Content-Type: application/json
        + *
        + * {
        + *   "jsonrpc": "2.0",
        + *   "id": "req-123",
        + *   "method": "sendMessage",
        + *   "params": {
        + *     "message": {
        + *       "parts": [{"text": "Hello"}]
        + *     }
        + *   }
        + * }
        + * }
        + * + *

        Response Formats

        + * + *

        Non-Streaming (JSON): + *

        {@code
        + * HTTP/1.1 200 OK
        + * Content-Type: application/json
        + *
        + * {
        + *   "jsonrpc": "2.0",
        + *   "id": "req-123",
        + *   "result": {
        + *     "task": { ... }
        + *   }
        + * }
        + * }
        + * + *

        Streaming (SSE): + *

        {@code
        + * HTTP/1.1 200 OK
        + * Content-Type: text/event-stream
        + *
        + * id: 0
        + * data: {"jsonrpc":"2.0","id":"req-123","result":{...}}
        + *
        + * id: 1
        + * data: {"jsonrpc":"2.0","id":"req-123","result":{...}}
        + * }
        + * + *

        Error Response: + *

        {@code
        + * HTTP/1.1 200 OK
        + * Content-Type: application/json
        + *
        + * {
        + *   "jsonrpc": "2.0",
        + *   "id": "req-123",
        + *   "error": {
        + *     "code": -32602,
        + *     "message": "Invalid params"
        + *   }
        + * }
        + * }
        + * + *

        Supported Methods

        + *
          + *
        • {@code sendMessage} - Send message (blocking)
        • + *
        • {@code sendStreamingMessage} - Send message (streaming SSE)
        • + *
        • {@code subscribeToTask} - Subscribe to task events (streaming SSE)
        • + *
        • {@code getTask} - Get task by ID
        • + *
        • {@code listTasks} - List tasks with filtering
        • + *
        • {@code cancelTask} - Cancel task execution
        • + *
        • {@code getTaskPushNotificationConfig} - Get push notification config
        • + *
        • {@code setTaskPushNotificationConfig} - Create push notification config
        • + *
        • {@code listTaskPushNotificationConfig} - List push notification configs
        • + *
        • {@code deleteTaskPushNotificationConfig} - Delete push notification config
        • + *
        • {@code getExtendedAgentCard} - Get extended agent card
        • + *
        + * + *

        Multi-Tenancy

        + *

        Tenant identification from request path: + *

          + *
        • {@code POST /} → empty tenant
        • + *
        • {@code POST /tenant1} → tenant "tenant1"
        • + *
        • {@code POST /org/team} → tenant "org/team"
        • + *
        + * + *

        Customization

        + * + *

        Custom Context Creation: + *

        Provide a CDI bean implementing {@link io.a2a.server.apps.quarkus.CallContextFactory CallContextFactory}: + *

        {@code
        + * @ApplicationScoped
        + * public class CustomCallContextFactory implements CallContextFactory {
        + *     @Override
        + *     public ServerCallContext build(RoutingContext rc) {
        + *         // Extract user from Quarkus security context
        + *         User user = (rc.user() == null) ? UnauthenticatedUser.INSTANCE :
        + *             new User() {
        + *                 public boolean isAuthenticated() { return rc.userContext().authenticated(); }
        + *                 public String getUsername() { return rc.user().subject(); }
        + *             };
        + *
        + *         // Extract custom data from routing context
        + *         Map state = new HashMap<>();
        + *         state.put("organization", rc.request().getHeader("X-Org-ID"));
        + *
        + *         // Extract A2A protocol version from header
        + *         String version = rc.request().getHeader(A2AHeaders.X_A2A_VERSION);
        + *
        + *         // Extract requested extensions from header
        + *         List extensionHeaders = rc.request().headers().getAll(A2AHeaders.X_A2A_EXTENSIONS);
        + *         Set extensions = A2AExtensions.getRequestedExtensions(extensionHeaders);
        + *
        + *         return new ServerCallContext(user, state, extensions, version);
        + *     }
        + * }
        + * }
        + * + *

        Configuration

        + *

        No JSON-RPC-specific configuration required. Standard Quarkus HTTP configuration applies: + *

        + * quarkus.http.port=9999
        + * quarkus.http.host=0.0.0.0
        + * 
        + * + *

        Authentication

        + *

        Uses Quarkus Security with {@code @Authenticated} annotation on routes. + * Configure authentication in {@code application.properties}: + *

        + * quarkus.security.users.embedded.enabled=true
        + * quarkus.security.users.embedded.plain-text=true
        + * quarkus.security.users.embedded.users.alice=password
        + * 
        + * + * @see io.a2a.server.apps.quarkus.A2AServerRoutes + * @see io.a2a.server.apps.quarkus.CallContextFactory + * @see io.a2a.transport.jsonrpc.handler.JSONRPCHandler + */ +package io.a2a.server.apps.quarkus; diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java index fbed22192..963a1493e 100644 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java +++ b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java @@ -3,8 +3,20 @@ /** * Shared JSON-RPC context keys for A2A protocol data. * - * These keys provide access to JSON-RPC context information, - * enabling rich context access in service method implementations. + *

        These keys provide access to JSON-RPC context information stored in + * {@link io.a2a.server.ServerCallContext}, enabling rich context access + * in service method implementations and middleware. + * + *

        Usage Example

        + *
        {@code
        + * public void processRequest(ServerCallContext context) {
        + *     String tenant = context.get(JSONRPCContextKeys.TENANT_KEY);
        + *     String method = context.get(JSONRPCContextKeys.METHOD_NAME_KEY);
        + *     Map headers = context.get(JSONRPCContextKeys.HEADERS_KEY);
        + * }
        + * }
        + * + * @see io.a2a.server.ServerCallContext */ public final class JSONRPCContextKeys { 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 d4de45c82..e91be92d5 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 @@ -42,6 +42,7 @@ import io.a2a.server.version.A2AVersionValidator; import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; +import io.a2a.spec.CancelTaskParams; import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.EventKind; import io.a2a.spec.InternalError; @@ -56,6 +57,77 @@ import mutiny.zero.ZeroPublisher; import org.jspecify.annotations.Nullable; +/** + * JSON-RPC 2.0 transport handler for processing A2A protocol requests over HTTP. + * + *

        This handler converts JSON-RPC 2.0 requests into A2A protocol operations and + * manages the lifecycle of agent interactions. It supports both blocking request/response + * and streaming responses via Server-Sent Events. + * + *

        Request Flow

        + *

        JSON-RPC requests flow through this handler to the underlying {@link RequestHandler}, + * which coordinates with the agent executor and event queue system: + *

        + * JSON-RPC Request → JSONRPCHandler → RequestHandler → AgentExecutor
        + *                         ↓               ↓
        + *                   Validation      EventQueue → Response
        + * 
        + * + *

        JSON-RPC 2.0 Format

        + *

        Requests follow the JSON-RPC 2.0 specification: + *

        {@code
        + * {
        + *   "jsonrpc": "2.0",
        + *   "id": "request-123",
        + *   "method": "sendMessage",
        + *   "params": {
        + *     "message": {...}
        + *   }
        + * }
        + * }
        + * + *

        Responses include the request ID for correlation: + *

        {@code
        + * {
        + *   "jsonrpc": "2.0",
        + *   "id": "request-123",
        + *   "result": {
        + *     "task": {...}
        + *   }
        + * }
        + * }
        + * + *

        Supported Operations

        + *
          + *
        • Message sending (blocking and streaming)
        • + *
        • Task management (get, list, cancel, subscribe)
        • + *
        • Push notification configurations (create, get, list, delete)
        • + *
        + * + *

        Error Handling

        + *

        All A2A protocol errors are caught and converted to JSON-RPC error responses + * with the error object embedded in the response. Protocol version and required + * extensions are validated before processing requests. + * + *

        Streaming Support

        + *

        Streaming methods ({@code sendStreamingMessage}, {@code subscribeToTask}) return + * a {@link Flow.Publisher} of JSON-RPC responses, allowing Server-Sent Events delivery + * when used with Quarkus/Vert.x transport layers. + * + *

        CDI Integration

        + *

        This handler is an {@code @ApplicationScoped} CDI bean that requires: + *

          + *
        • {@link AgentCard} qualified with {@code @PublicAgentCard}
        • + *
        • {@link RequestHandler} for processing A2A operations
        • + *
        • {@link Executor} qualified with {@code @Internal} for async operations
        • + *
        • Optional {@link AgentCard} qualified with {@code @ExtendedAgentCard}
        • + *
        + * + * @see RequestHandler + * @see io.a2a.server.requesthandlers.DefaultRequestHandler + * @see io.a2a.spec.AgentCard + * @see ServerCallContext + */ @ApplicationScoped public class JSONRPCHandler { @@ -81,6 +153,14 @@ protected JSONRPCHandler() { this.executor = null; } + /** + * Creates a JSON-RPC handler with full CDI injection support. + * + * @param agentCard the public agent card containing agent capabilities + * @param extendedAgentCard optional extended agent card instance + * @param requestHandler the handler for processing A2A requests + * @param executor the executor for asynchronous operations + */ @Inject public JSONRPCHandler(@PublicAgentCard AgentCard agentCard, @Nullable @ExtendedAgentCard Instance extendedAgentCard, RequestHandler requestHandler, @Internal Executor executor) { @@ -93,10 +173,59 @@ public JSONRPCHandler(@PublicAgentCard AgentCard agentCard, @Nullable @ExtendedA AgentCardValidator.validateTransportConfiguration(agentCard); } + /** + * Creates a JSON-RPC handler with basic dependencies. + * + * @param agentCard the agent card containing agent capabilities + * @param requestHandler the handler for processing A2A requests + * @param executor the executor for asynchronous operations + */ public JSONRPCHandler(@PublicAgentCard AgentCard agentCard, RequestHandler requestHandler, Executor executor) { this(agentCard, null, requestHandler, executor); } + /** + * Handles a blocking message send request. + * + *

        This method processes a JSON-RPC {@code sendMessage} request containing a message + * to be sent to the agent. The method blocks until the agent produces a terminal event + * or requires authentication/input. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "msg-123",
        +     *   "method": "sendMessage",
        +     *   "params": {
        +     *     "message": {
        +     *       "parts": [{"text": "What is the weather?"}]
        +     *     }
        +     *   }
        +     * }
        +     * }
        + * + *

        Example Response: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "msg-123",
        +     *   "result": {
        +     *     "task": {
        +     *       "id": "task-456",
        +     *       "status": {"state": "COMPLETED"},
        +     *       "artifacts": [...]
        +     *     }
        +     *   }
        +     * }
        +     * }
        + * + * @param request the JSON-RPC request containing message params + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response with task or message result + * @see #onMessageSendStream(SendStreamingMessageRequest, ServerCallContext) + * @see RequestHandler#onMessageSend(io.a2a.spec.MessageSendParams, ServerCallContext) + */ public SendMessageResponse onMessageSend(SendMessageRequest request, ServerCallContext context) { try { A2AVersionValidator.validateProtocolVersion(agentCard, context); @@ -110,6 +239,42 @@ public SendMessageResponse onMessageSend(SendMessageRequest request, ServerCallC } } + /** + * Handles a streaming message send request. + * + *

        This method processes a JSON-RPC {@code sendStreamingMessage} request for streaming + * responses from the agent. The response is returned as a {@link Flow.Publisher} of + * JSON-RPC response objects, allowing Server-Sent Events delivery. + * + *

        This method requires the agent card to have {@code capabilities.streaming = true}. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "stream-123",
        +     *   "method": "sendStreamingMessage",
        +     *   "params": {
        +     *     "message": {
        +     *       "parts": [{"text": "Generate a story"}]
        +     *     }
        +     *   }
        +     * }
        +     * }
        + * + *

        Example Streaming Responses: + *

        {@code
        +     * {"jsonrpc":"2.0","id":"stream-123","result":{"taskStatusUpdate":{...}}}
        +     * {"jsonrpc":"2.0","id":"stream-123","result":{"taskArtifactUpdate":{...}}}
        +     * {"jsonrpc":"2.0","id":"stream-123","result":{"taskStatusUpdate":{...}}}
        +     * }
        + * + * @param request the JSON-RPC request containing message params + * @param context the server call context containing authentication and metadata + * @return publisher of JSON-RPC response objects containing streaming events + * @see #onMessageSend(SendMessageRequest, ServerCallContext) + * @see RequestHandler#onMessageSendStream(io.a2a.spec.MessageSendParams, ServerCallContext) + */ public Flow.Publisher onMessageSendStream( SendStreamingMessageRequest request, ServerCallContext context) { if (!agentCard.capabilities().streaming()) { @@ -134,6 +299,31 @@ public Flow.Publisher onMessageSendStream( } } + /** + * Handles a task cancellation request. + * + *

        Attempts to cancel a running task identified by the task ID in the request params. + * The cancellation request is forwarded to the {@link RequestHandler}, which signals the + * agent executor to stop processing. The agent should transition the task to {@code CANCELED} state. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "cancel-123",
        +     *   "method": "cancelTask",
        +     *   "params": {
        +     *     "taskId": "task-456"
        +     *   }
        +     * }
        +     * }
        + * + * @param request the JSON-RPC request containing task ID params + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response with the cancelled task + * @see RequestHandler#onCancelTask(CancelTaskParams, ServerCallContext) + * @see io.a2a.server.agentexecution.AgentExecutor#cancel + */ public CancelTaskResponse onCancelTask(CancelTaskRequest request, ServerCallContext context) { try { Task task = requestHandler.onCancelTask(request.getParams(), context); @@ -148,6 +338,40 @@ public CancelTaskResponse onCancelTask(CancelTaskRequest request, ServerCallCont } } + /** + * Subscribes to task updates via a streaming connection. + * + *

        Creates a stream that delivers real-time updates for an existing task. This allows + * clients to reconnect to ongoing or completed tasks and receive their event history + * and future updates. + * + *

        This method requires the agent card to have {@code capabilities.streaming = true}. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "subscribe-123",
        +     *   "method": "subscribeToTask",
        +     *   "params": {
        +     *     "taskId": "task-456"
        +     *   }
        +     * }
        +     * }
        + * + *

        Use Cases: + *

          + *
        • Reconnecting to a task after network interruption
        • + *
        • Monitoring long-running tasks from multiple clients
        • + *
        • Viewing historical events for completed tasks
        • + *
        + * + * @param request the JSON-RPC request containing task ID params + * @param context the server call context containing authentication and metadata + * @return publisher of JSON-RPC response objects containing task updates + * @see RequestHandler#onSubscribeToTask(io.a2a.spec.TaskIdParams, ServerCallContext) + * @see #onMessageSendStream(SendStreamingMessageRequest, ServerCallContext) + */ public Flow.Publisher onSubscribeToTask( SubscribeToTaskRequest request, ServerCallContext context) { if (!agentCard.capabilities().streaming()) { @@ -170,6 +394,30 @@ public Flow.Publisher onSubscribeToTask( } } + /** + * Retrieves a specific push notification configuration. + * + *

        Returns the push notification configuration for a task by config ID. + * This method requires the agent card to have {@code capabilities.pushNotifications = true}. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "get-config-123",
        +     *   "method": "getTaskPushNotificationConfig",
        +     *   "params": {
        +     *     "taskId": "task-456",
        +     *     "configId": "config-789"
        +     *   }
        +     * }
        +     * }
        + * + * @param request the JSON-RPC request containing task and config ID params + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response with the configuration + * @see RequestHandler#onGetTaskPushNotificationConfig + */ public GetTaskPushNotificationConfigResponse getPushNotificationConfig( GetTaskPushNotificationConfigRequest request, ServerCallContext context) { if (!agentCard.capabilities().pushNotifications()) { @@ -187,6 +435,31 @@ public GetTaskPushNotificationConfigResponse getPushNotificationConfig( } } + /** + * Creates a push notification configuration for a task. + * + *

        Creates a new push notification configuration specifying webhook URL and event filters. + * This method requires the agent card to have {@code capabilities.pushNotifications = true}. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "create-config-123",
        +     *   "method": "setTaskPushNotificationConfig",
        +     *   "params": {
        +     *     "taskId": "task-456",
        +     *     "url": "https://webhook.example.com/notify",
        +     *     "events": ["taskStatusUpdate", "taskArtifactUpdate"]
        +     *   }
        +     * }
        +     * }
        + * + * @param request the JSON-RPC request containing push notification config params + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response with the created configuration + * @see RequestHandler#onCreateTaskPushNotificationConfig + */ public CreateTaskPushNotificationConfigResponse setPushNotificationConfig( CreateTaskPushNotificationConfigRequest request, ServerCallContext context) { if (!agentCard.capabilities().pushNotifications()) { @@ -204,6 +477,30 @@ public CreateTaskPushNotificationConfigResponse setPushNotificationConfig( } } + /** + * Retrieves a specific task by ID. + * + *

        Returns the complete task object including status, artifacts, and optionally + * task history based on the {@code historyLength} parameter. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "get-123",
        +     *   "method": "getTask",
        +     *   "params": {
        +     *     "taskId": "task-456",
        +     *     "historyLength": 10
        +     *   }
        +     * }
        +     * }
        + * + * @param request the JSON-RPC request containing task query params + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response with the task object + * @see RequestHandler#onGetTask(io.a2a.spec.TaskQueryParams, ServerCallContext) + */ public GetTaskResponse onGetTask(GetTaskRequest request, ServerCallContext context) { try { Task task = requestHandler.onGetTask(request.getParams(), context); @@ -215,6 +512,42 @@ public GetTaskResponse onGetTask(GetTaskRequest request, ServerCallContext conte } } + /** + * Lists tasks with optional filtering and pagination. + * + *

        Retrieves a list of tasks with support for filtering by context, status, and timestamp, + * along with pagination controls. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "list-123",
        +     *   "method": "listTasks",
        +     *   "params": {
        +     *     "status": "COMPLETED",
        +     *     "pageSize": 10,
        +     *     "includeArtifacts": true
        +     *   }
        +     * }
        +     * }
        + * + *

        Query Parameters: + *

          + *
        • {@code contextId} - Filter tasks by conversation context
        • + *
        • {@code status} - Filter by task state
        • + *
        • {@code pageSize} - Maximum tasks to return
        • + *
        • {@code pageToken} - Token for pagination
        • + *
        • {@code historyLength} - Max history entries per task
        • + *
        • {@code statusTimestampAfter} - ISO-8601 timestamp filter
        • + *
        • {@code includeArtifacts} - Include task artifacts
        • + *
        + * + * @param request the JSON-RPC request containing list tasks params + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response with list of tasks + * @see RequestHandler#onListTasks(io.a2a.spec.ListTasksParams, ServerCallContext) + */ public ListTasksResponse onListTasks(ListTasksRequest request, ServerCallContext context) { try { ListTasksResult result = requestHandler.onListTasks(request.getParams(), context); @@ -226,6 +559,30 @@ public ListTasksResponse onListTasks(ListTasksRequest request, ServerCallContext } } + /** + * Lists push notification configurations for a task. + * + *

        Returns a paginated list of push notification configurations associated with a task. + * This method requires the agent card to have {@code capabilities.pushNotifications = true}. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "list-config-123",
        +     *   "method": "listTaskPushNotificationConfig",
        +     *   "params": {
        +     *     "taskId": "task-456",
        +     *     "pageSize": 10
        +     *   }
        +     * }
        +     * }
        + * + * @param request the JSON-RPC request containing task ID and pagination params + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response with list of configurations + * @see RequestHandler#onListTaskPushNotificationConfig + */ public ListTaskPushNotificationConfigsResponse listPushNotificationConfig( ListTaskPushNotificationConfigsRequest request, ServerCallContext context) { if ( !agentCard.capabilities().pushNotifications()) { @@ -243,6 +600,31 @@ public ListTaskPushNotificationConfigsResponse listPushNotificationConfig( } } + /** + * Deletes a push notification configuration. + * + *

        Removes a push notification configuration by config ID, stopping notifications + * for the associated task. + * This method requires the agent card to have {@code capabilities.pushNotifications = true}. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "delete-config-123",
        +     *   "method": "deleteTaskPushNotificationConfig",
        +     *   "params": {
        +     *     "taskId": "task-456",
        +     *     "configId": "config-789"
        +     *   }
        +     * }
        +     * }
        + * + * @param request the JSON-RPC request containing task and config ID params + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response confirming deletion + * @see RequestHandler#onDeleteTaskPushNotificationConfig + */ public DeleteTaskPushNotificationConfigResponse deletePushNotificationConfig( DeleteTaskPushNotificationConfigRequest request, ServerCallContext context) { if ( !agentCard.capabilities().pushNotifications()) { @@ -259,6 +641,29 @@ public DeleteTaskPushNotificationConfigResponse deletePushNotificationConfig( } } + /** + * Retrieves the extended agent card if configured. + * + *

        The extended agent card provides additional metadata beyond the public agent card, + * such as tenant-specific configurations or private capabilities. This endpoint requires + * the agent card to have {@code capabilities.extendedAgentCard = true} and a CDI-produced + * {@code @ExtendedAgentCard} instance. + * + *

        Example Request: + *

        {@code
        +     * {
        +     *   "jsonrpc": "2.0",
        +     *   "id": "ext-card-123",
        +     *   "method": "getExtendedAgentCard",
        +     *   "params": {}
        +     * }
        +     * }
        + * + * @param request the JSON-RPC request for extended agent card + * @param context the server call context containing authentication and metadata + * @return JSON-RPC response with the extended agent card + * @see #getAgentCard() + */ // TODO: Add authentication (https://github.com/a2aproject/a2a-java/issues/77) public GetExtendedAgentCardResponse onGetExtendedCardRequest( GetExtendedAgentCardRequest request, ServerCallContext context) { @@ -275,6 +680,16 @@ public GetExtendedAgentCardResponse onGetExtendedCardRequest( } } + /** + * Returns the public agent card. + * + *

        The agent card is a self-describing manifest that provides essential metadata about + * the agent, including its capabilities, supported skills, communication methods, and + * security requirements. + * + * @return the public agent card + * @see AgentCard + */ public AgentCard getAgentCard() { return agentCard; } diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java index 20b7a9dde..306e94d86 100644 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java +++ b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java @@ -1,3 +1,34 @@ +/** + * JSON-RPC transport handler implementations for the A2A protocol. + * + *

        This package contains the core JSON-RPC handler that processes JSON-RPC 2.0 requests + * over HTTP and translates them to A2A protocol operations. It supports both blocking and + * streaming responses with proper JSON-RPC error handling. + * + *

        JSON-RPC 2.0 Protocol

        + *

        This implementation follows the JSON-RPC 2.0 specification, supporting: + *

          + *
        • Request/response pairs with unique request IDs
        • + *
        • Error responses with code, message, and optional data
        • + *
        • Streaming via Server-Sent Events for applicable methods
        • + *
        + * + *

        Supported Methods

        + *
          + *
        • {@code sendMessage} - Send message (blocking)
        • + *
        • {@code sendStreamingMessage} - Send message (streaming)
        • + *
        • {@code subscribeToTask} - Subscribe to task updates (streaming)
        • + *
        • {@code getTask} - Get task by ID
        • + *
        • {@code listTasks} - List tasks with filtering
        • + *
        • {@code cancelTask} - Cancel task execution
        • + *
        • {@code getTaskPushNotificationConfig} - Get push notification config
        • + *
        • {@code setTaskPushNotificationConfig} - Create push notification config
        • + *
        • {@code listTaskPushNotificationConfig} - List push notification configs
        • + *
        • {@code deleteTaskPushNotificationConfig} - Delete push notification config
        • + *
        + * + * @see io.a2a.transport.jsonrpc.handler.JSONRPCHandler + */ @NullMarked package io.a2a.transport.jsonrpc.handler; From d7227f769a9c29abaaf459e002c55bec24da83e0 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 9 Mar 2026 17:06:07 +0000 Subject: [PATCH 068/192] fix: Add Javadoc for rest transport server-side components (#678) Fixes: #480 --------- Signed-off-by: Emmanuel Hugonnet Co-authored-by: Emmanuel Hugonnet --- .../server/rest/quarkus/A2AServerRoutes.java | 377 ++++++++++++++++- .../rest/quarkus/CallContextFactory.java | 55 +++ .../quarkus/QuarkusRestTransportMetadata.java | 23 + .../a2a/server/rest/quarkus/package-info.java | 62 +++ .../rest/context/RestContextKeys.java | 16 +- .../transport/rest/handler/RestHandler.java | 400 ++++++++++++++++++ .../transport/rest/handler/package-info.java | 12 + .../handler/RestTestTransportMetadata.java | 9 + 8 files changed, 940 insertions(+), 14 deletions(-) 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 074cd5ec6..05e352a18 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 @@ -63,6 +63,61 @@ import static io.a2a.transport.rest.context.RestContextKeys.TENANT_KEY; +/** + * Quarkus reactive routes for A2A protocol REST endpoints. + * + *

        This class defines all HTTP routes for the A2A protocol using Quarkus Reactive Routes + * (Vert.x web). Each method is annotated with {@code @Route} to map HTTP requests to + * A2A operations, delegating to {@link RestHandler} for processing. + * + *

        Route Mapping

        + *

        Routes support optional tenant prefixing and use regex patterns for flexible matching: + *

        + * POST   /{tenant}/message:send           → sendMessage()
        + * POST   /{tenant}/message:stream         → sendMessageStreaming()
        + * GET    /{tenant}/tasks                  → listTasks()
        + * GET    /{tenant}/tasks/{taskId}         → getTask()
        + * POST   /{tenant}/tasks/{taskId}:cancel  → cancelTask()
        + * POST   /{tenant}/tasks/{taskId}:subscribe → subscribeToTask()
        + * GET    /.well-known/agent-card.json     → getAgentCard()
        + * GET    /{tenant}/extendedAgentCard      → getExtendedAgentCard()
        + * 
        + * + *

        Authentication

        + *

        Most endpoints require authentication via {@code @Authenticated}, except: + *

          + *
        • {@code /.well-known/agent-card.json} - Public agent discovery endpoint ({@code @PermitAll})
        • + *
        + * + *

        Streaming Support

        + *

        Streaming endpoints ({@code message:stream}, {@code subscribe}) use Server-Sent Events (SSE) + * via the inner {@link MultiSseSupport} class. SSE responses are handled by: + *

          + *
        • Converting {@link Flow.Publisher} to Mutiny {@code Multi}
        • + *
        • Formatting events with {@link SseFormatter}
        • + *
        • Managing backpressure and client disconnection
        • + *
        + * + *

        Error Handling

        + *

        All errors are caught and converted to HTTP responses via {@link RestHandler#createErrorResponse(A2AError)}, + * ensuring consistent error format and status codes across all endpoints. + * + *

        Context Creation

        + *

        Each request creates a {@link ServerCallContext} via {@link #createCallContext(RoutingContext, String)}, + * extracting: + *

          + *
        • User authentication from Quarkus Security
        • + *
        • HTTP headers (including {@code X-A2A-Version}, {@code X-A2A-Extensions})
        • + *
        • Tenant ID from URL path
        • + *
        • Transport protocol metadata
        • + *
        + * + *

        Custom context creation is supported via CDI-provided {@link CallContextFactory}. + * + * @see RestHandler + * @see ServerCallContext + * @see CallContextFactory + */ @Singleton @Authenticated public class A2AServerRoutes { @@ -87,6 +142,29 @@ public class A2AServerRoutes { @Inject Instance callContextFactory; + /** + * Handles blocking message send requests. + * + *

        Maps {@code POST /{tenant}/message:send} to {@link RestHandler#sendMessage}. + * The request body must be JSON containing a message with parts. + * + *

        URL Pattern: {@code /message:send} or {@code /{tenant}/message:send} + * + *

        Example: + *

        {@code
        +     * POST /message:send
        +     * Content-Type: application/json
        +     *
        +     * {
        +     *   "message": {
        +     *     "parts": [{"text": "Hello"}]
        +     *   }
        +     * }
        +     * }
        + * + * @param body the JSON request body + * @param rc the Vert.x routing context + */ @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, SEND_MESSAGE_METHOD); @@ -100,6 +178,26 @@ public void sendMessage(@Body String body, RoutingContext rc) { } } + /** + * Handles streaming message send requests with Server-Sent Events. + * + *

        Maps {@code POST /{tenant}/message:stream} to {@link RestHandler#sendStreamingMessage}. + * Returns a stream of task updates and artifacts as SSE events. + * + *

        URL Pattern: {@code /message:stream} or {@code /{tenant}/message:stream} + * + *

        Response Format: {@code text/event-stream} with JSON events: + *

        {@code
        +     * data: {"taskStatusUpdate":{"task":{"status":{"state":"WORKING"}}}}
        +     *
        +     * data: {"taskArtifactUpdate":{"artifacts":[...]}}
        +     *
        +     * data: {"taskStatusUpdate":{"task":{"status":{"state":"COMPLETED"}}}}
        +     * }
        + * + * @param body the JSON request body + * @param rc the Vert.x routing context + */ @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, SEND_STREAMING_MESSAGE_METHOD); @@ -129,6 +227,27 @@ public void sendMessageStreaming(@Body String body, RoutingContext rc) { } } + /** + * Lists tasks with optional filtering and pagination. + * + *

        Maps {@code GET /{tenant}/tasks} to {@link RestHandler#listTasks}. + * Supports query parameters for filtering and pagination. + * + *

        URL Pattern: {@code /tasks?status=COMPLETED&pageSize=10} + * + *

        Query Parameters: + *

          + *
        • {@code contextId} - Filter by conversation context
        • + *
        • {@code status} - Filter by task state (SUBMITTED, WORKING, COMPLETED, etc.)
        • + *
        • {@code pageSize} - Maximum tasks to return
        • + *
        • {@code pageToken} - Pagination token
        • + *
        • {@code historyLength} - Max history entries per task
        • + *
        • {@code statusTimestampAfter} - ISO-8601 timestamp filter
        • + *
        • {@code includeArtifacts} - Include artifacts in response (boolean)
        • + *
        + * + * @param rc the Vert.x routing context + */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\??", order = 0, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void listTasks(RoutingContext rc) { ServerCallContext context = createCallContext(rc, LIST_TASK_METHOD); @@ -174,6 +293,16 @@ public void listTasks(RoutingContext rc) { } } + /** + * Retrieves a specific task by ID. + * + *

        Maps {@code GET /{tenant}/tasks/{taskId}} to {@link RestHandler#getTask}. + * Optionally includes task history via query parameter. + * + *

        URL Pattern: {@code /tasks/{taskId}?historyLength=10} + * + * @param rc the Vert.x routing context (taskId extracted from path) + */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^:^/]+)$", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void getTask(RoutingContext rc) { String taskId = rc.pathParam("taskId"); @@ -198,6 +327,16 @@ public void getTask(RoutingContext rc) { } } + /** + * Cancels a running task. + * + *

        Maps {@code POST /{tenant}/tasks/{taskId}:cancel} to {@link RestHandler#cancelTask}. + * Signals the agent executor to stop processing and transition to CANCELED state. + * + *

        URL Pattern: {@code /tasks/{taskId}:cancel} + * + * @param rc the Vert.x routing context (taskId extracted from path) + */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void cancelTask(@Body String body, RoutingContext rc) { String taskId = rc.pathParam("taskId"); @@ -220,6 +359,15 @@ public void cancelTask(@Body String body, RoutingContext rc) { } } + /** + * Sends an HTTP response from a {@link HTTPRestResponse} object. + * + *

        Helper method that sets status code, content type header, and body + * from the response object. Used by all blocking endpoints. + * + * @param rc the Vert.x routing context + * @param response the response to send, or null to end without body + */ private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response) { if (response != null) { rc.response() @@ -231,6 +379,23 @@ private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response } } + /** + * Subscribes to task updates via Server-Sent Events. + * + *

        Maps {@code POST /{tenant}/tasks/{taskId}:subscribe} to {@link RestHandler#subscribeToTask}. + * Returns a stream of task events allowing clients to reconnect to ongoing tasks. + * + *

        URL Pattern: {@code /tasks/{taskId}:subscribe} + * + *

        Use Cases: + *

          + *
        • Reconnecting after network interruption
        • + *
        • Monitoring long-running tasks
        • + *
        • Multiple clients observing same task
        • + *
        + * + * @param rc the Vert.x routing context (taskId extracted from path) + */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):subscribe$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void subscribeToTask(RoutingContext rc) { String taskId = rc.pathParam("taskId"); @@ -265,6 +430,19 @@ public void subscribeToTask(RoutingContext rc) { } } + /** + * Creates a push notification configuration for a task. + * + *

        Maps {@code POST /{tenant}/tasks/{taskId}/pushNotificationConfigs} to + * {@link RestHandler#createTaskPushNotificationConfiguration}. + * + *

        URL Pattern: {@code /tasks/{taskId}/pushNotificationConfigs} + * + *

        Request Body: JSON containing webhook URL and event filters + * + * @param body the JSON request body with notification configuration + * @param rc the Vert.x routing context (taskId extracted from path) + */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) public void CreateTaskPushNotificationConfiguration(@Body String body, RoutingContext rc) { String taskId = rc.pathParam("taskId"); @@ -283,6 +461,16 @@ public void CreateTaskPushNotificationConfiguration(@Body String body, RoutingCo } } + /** + * Retrieves a specific push notification configuration. + * + *

        Maps {@code GET /{tenant}/tasks/{taskId}/pushNotificationConfigs/{configId}} to + * {@link RestHandler#getTaskPushNotificationConfiguration}. + * + *

        URL Pattern: {@code /tasks/{taskId}/pushNotificationConfigs/{configId}} + * + * @param rc the Vert.x routing context (taskId and configId extracted from path) + */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^\\/]+)", order = 2, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void getTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("taskId"); @@ -304,6 +492,23 @@ public void getTaskPushNotificationConfiguration(RoutingContext rc) { } } + /** + * Lists push notification configurations for a task. + * + *

        Maps {@code GET /{tenant}/tasks/{taskId}/pushNotificationConfigs} to + * {@link RestHandler#listTaskPushNotificationConfigurations}. + * Supports pagination via query parameters. + * + *

        URL Pattern: {@code /tasks/{taskId}/pushNotificationConfigs?pageSize=10} + * + *

        Query Parameters: + *

          + *
        • {@code pageSize} - Maximum configurations to return
        • + *
        • {@code pageToken} - Pagination token for next page
        • + *
        + * + * @param rc the Vert.x routing context (taskId extracted from path) + */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/?$", order = 3, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void listTaskPushNotificationConfigurations(RoutingContext rc) { String taskId = rc.pathParam("taskId"); @@ -332,6 +537,18 @@ public void listTaskPushNotificationConfigurations(RoutingContext rc) { } } + /** + * Deletes a push notification configuration. + * + *

        Maps {@code DELETE /{tenant}/tasks/{taskId}/pushNotificationConfigs/{configId}} to + * {@link RestHandler#deleteTaskPushNotificationConfiguration}. + * + *

        URL Pattern: {@code /tasks/{taskId}/pushNotificationConfigs/{configId}} + * + *

        Response: HTTP 204 No Content on success + * + * @param rc the Vert.x routing context (taskId and configId extracted from path) + */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^/]+)", order = 1, methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("taskId"); @@ -353,6 +570,19 @@ public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { } } + /** + * Extracts tenant ID from the routing context path parameter. + * + *

        Handles optional tenant prefixes in URL paths, normalizing: + *

          + *
        • {@code /message:send} → empty string (default tenant)
        • + *
        • {@code /tenant-123/message:send} → "tenant-123"
        • + *
        • {@code /tenant-123} → "tenant-123" (strips leading/trailing slashes)
        • + *
        + * + * @param rc the Vert.x routing context + * @return the extracted tenant ID, or empty string if not specified + */ private String extractTenant(RoutingContext rc) { String tenantPath = rc.pathParam("tenant"); if (tenantPath == null || tenantPath.isBlank()) { @@ -368,11 +598,25 @@ private String extractTenant(RoutingContext rc) { } /** - * /** - * Handles incoming GET requests to the agent card endpoint. - * Returns the agent card in JSON format. + * Retrieves the public agent card for agent discovery. + * + *

        Maps {@code GET /.well-known/agent-card.json} to {@link RestHandler#getAgentCard}. + * This is the primary discovery endpoint that clients use to understand agent capabilities, + * supported skills, and communication methods. * - * @param rc the routing context + *

        URL Pattern: {@code /.well-known/agent-card.json} (well-known URI) + * + *

        Authentication: {@code @PermitAll} - Public endpoint requiring no authentication + * + *

        Response: JSON containing {@link io.a2a.spec.AgentCard} with: + *

          + *
        • Agent name, description, version
        • + *
        • Capabilities (streaming, push notifications)
        • + *
        • Supported skills
        • + *
        • Communication interfaces and protocols
        • + *
        + * + * @param rc the Vert.x routing context */ @Route(path = "/.well-known/agent-card.json", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) @PermitAll @@ -381,12 +625,35 @@ public void getAgentCard(RoutingContext rc) { sendResponse(rc, response); } + /** + * Retrieves the extended agent card with additional metadata. + * + *

        Maps {@code GET /{tenant}/extendedAgentCard} to {@link RestHandler#getExtendedAgentCard}. + * Provides tenant-specific or private capabilities beyond the public agent card. + * + *

        URL Pattern: {@code /extendedAgentCard} or {@code /{tenant}/extendedAgentCard} + * + *

        Authentication: Required (inherits {@code @Authenticated} from class) + * + * @param rc the Vert.x routing context + */ @Route(regex = "^\\/(?[^\\/]*\\/?)extendedAgentCard$", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) public void getExtendedAgentCard(RoutingContext rc) { HTTPRestResponse response = jsonRestHandler.getExtendedAgentCard(createCallContext(rc, GET_EXTENDED_AGENT_CARD_METHOD), extractTenant(rc)); sendResponse(rc, response); } + /** + * Catch-all route for undefined endpoints. + * + *

        Handles all HTTP methods on unmatched paths with order=100 (lowest priority). + * Returns a {@link io.a2a.spec.MethodNotFoundError} with HTTP 404 status. + * + *

        Purpose: Provides consistent error responses for invalid API calls + * instead of generic 404 HTML pages. + * + * @param rc the Vert.x routing context + */ @Route(path = "^/.*", order = 100, methods = {Route.HttpMethod.DELETE, Route.HttpMethod.GET, Route.HttpMethod.HEAD, Route.HttpMethod.OPTIONS, Route.HttpMethod.POST, Route.HttpMethod.PUT}, produces = APPLICATION_JSON) public void methodNotFoundMessage(RoutingContext rc) { HTTPRestResponse response = jsonRestHandler.createErrorResponse(new MethodNotFoundError()); @@ -397,6 +664,36 @@ static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { streamingMultiSseSupportSubscribedRunnable = runnable; } + /** + * Creates a {@link ServerCallContext} from Vert.x routing context. + * + *

        This method extracts authentication, headers, and protocol metadata from the + * HTTP request and builds a context object that flows through the request processing + * pipeline to the agent executor. + * + *

        Context Contents

        + *

        The created context includes: + *

          + *
        • User: From Quarkus Security (or {@link UnauthenticatedUser} if absent)
        • + *
        • Headers: All HTTP headers as a map
        • + *
        • Tenant: Extracted from URL path parameter
        • + *
        • Method Name: A2A method being invoked
        • + *
        • Transport: {@link TransportProtocol#HTTP_JSON}
        • + *
        • Protocol Version: From {@code X-A2A-Version} header
        • + *
        • Extensions: From {@code X-A2A-Extensions} header
        • + *
        + * + *

        Custom Context Factory

        + *

        If a CDI bean implementing {@link CallContextFactory} is provided, it will be + * used instead of the default implementation. This allows applications to add custom + * context data or modify the extraction logic. + * + * @param rc the Vert.x routing context containing request data + * @param jsonRpcMethodName the A2A method name (e.g., "sendMessage", "cancelTask") + * @return a new ServerCallContext with extracted request metadata + * @see CallContextFactory + * @see ServerCallContext + */ private ServerCallContext createCallContext(RoutingContext rc, String jsonRpcMethodName) { if (callContextFactory.isUnsatisfied()) { User user; @@ -449,10 +746,45 @@ public String getUsername() { } /** - * Simplified SSE support for Vert.x/Quarkus. - *

        - * This class only handles HTTP-specific concerns (writing to response, backpressure, disconnect). - * SSE formatting and JSON serialization are handled by {@link SseFormatter}. + * Server-Sent Events (SSE) streaming support for Vert.x/Quarkus. + * + *

        This inner class handles the HTTP-specific aspects of SSE streaming: + *

          + *
        • Writing SSE-formatted events to the HTTP response
        • + *
        • Managing backpressure via {@link Flow.Subscription#request(long)}
        • + *
        • Detecting client disconnection and canceling upstream
        • + *
        • Setting appropriate SSE headers and chunked encoding
        • + *
        + * + *

        SSE Format

        + *

        Events are formatted by {@link SseFormatter} before being passed to this class. + * Each event follows the SSE specification: + *

        +     * id: 0
        +     * data: {"taskStatusUpdate":{...}}
        +     *
        +     * id: 1
        +     * data: {"taskArtifactUpdate":{...}}
        +     * 
        + * + *

        Backpressure Handling

        + *

        The subscriber requests one event at a time ({@code request(1)}) and only + * requests the next event after the previous write completes. This ensures the + * HTTP connection doesn't buffer excessive data if the client is slow. + * + *

        Disconnect Detection

        + *

        When the client closes the connection, this class: + *

          + *
        1. Calls {@link ServerCallContext#invokeEventConsumerCancelCallback()} to stop the event producer
        2. + *
        3. Cancels the upstream subscription to stop event generation
        4. + *
        + * + *

        Write Queue Configuration

        + *

        Critical: Sets {@code setWriteQueueMaxSize(1)} to force immediate flushing + * of each event. Without this, Vert.x buffers writes, causing delays in SSE delivery. + * + * @see SseFormatter + * @see ServerCallContext#invokeEventConsumerCancelCallback() */ private static class MultiSseSupport { private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MultiSseSupport.class); @@ -462,11 +794,32 @@ private MultiSseSupport() { } /** - * Write SSE-formatted strings to HTTP response. + * Writes SSE-formatted event strings to the HTTP response with backpressure control. + * + *

        This method subscribes to the event stream and writes each SSE-formatted string + * to the Vert.x HTTP response. It implements reactive backpressure by requesting + * events one at a time and only requesting the next after the previous write completes. + * + *

        Execution Flow

        + *
          + *
        1. Subscribe to upstream {@code Multi} (SSE-formatted events)
        2. + *
        3. On first event: set SSE headers, disable buffering, write kickstart comment
        4. + *
        5. For each event: write to HTTP response asynchronously
        6. + *
        7. After write completes: request next event (backpressure control)
        8. + *
        9. On client disconnect or error: cancel upstream to stop event production
        10. + *
        + * + *

        Headers Set

        + *
          + *
        • {@code Content-Type: text/event-stream}
        • + *
        • {@code Cache-Control: no-cache}
        • + *
        • {@code X-Accel-Buffering: no} (disable nginx buffering)
        • + *
        • Chunked encoding enabled
        • + *
        * - * @param sseStrings Multi stream of SSE-formatted strings (from SseFormatter) - * @param rc Vert.x routing context - * @param context A2A server call context (for EventConsumer cancellation) + * @param sseStrings Multi stream of SSE-formatted strings (from {@link SseFormatter}) + * @param rc Vert.x routing context providing HTTP response + * @param context A2A server call context (for EventConsumer cancellation on disconnect) */ public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { HttpServerResponse response = rc.response(); diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java index 7aa5caf5e..b6432d1b3 100644 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java +++ b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java @@ -3,6 +3,61 @@ import io.a2a.server.ServerCallContext; import io.vertx.ext.web.RoutingContext; +/** + * Factory interface for creating {@link ServerCallContext} from Vert.x routing context. + * + *

        This interface provides an extension point for customizing how {@link ServerCallContext} + * instances are created in Quarkus REST applications. The default implementation in + * {@link A2AServerRoutes} extracts standard information (user, headers, tenant, protocol version), + * but applications can provide their own implementation to add custom context data. + * + *

        Default Behavior

        + *

        When no CDI bean implementing this interface is provided, {@link A2AServerRoutes} + * creates contexts with: + *

          + *
        • User authentication from Quarkus Security
        • + *
        • HTTP headers map
        • + *
        • Tenant ID from URL path
        • + *
        • A2A protocol version from {@code X-A2A-Version} header
        • + *
        • Required extensions from {@code X-A2A-Extensions} header
        • + *
        + * + *

        Custom Implementation Example

        + *
        {@code
        + * @ApplicationScoped
        + * public class CustomCallContextFactory implements CallContextFactory {
        + *     @Override
        + *     public ServerCallContext build(RoutingContext rc) {
        + *         // Extract custom data from routing context
        + *         String orgId = rc.request().getHeader("X-Organization-ID");
        + *
        + *         Map state = new HashMap<>();
        + *         state.put("organization", orgId);
        + *         state.put("requestId", UUID.randomUUID().toString());
        + *
        + *         return new ServerCallContext(
        + *             extractUser(rc),
        + *             state,
        + *             extractExtensions(rc),
        + *             extractVersion(rc)
        + *         );
        + *     }
        + * }
        + * }
        + * + * @see ServerCallContext + * @see A2AServerRoutes#createCallContext(RoutingContext, String) + */ public interface CallContextFactory { + /** + * Builds a {@link ServerCallContext} from a Vert.x routing context. + * + *

        This method is called for each incoming HTTP request to create the context + * that will be passed to the {@link io.a2a.server.requesthandlers.RequestHandler} + * and eventually to the {@link io.a2a.server.agentexecution.AgentExecutor}. + * + * @param rc the Vert.x routing context containing request data + * @return a new ServerCallContext with extracted authentication, headers, and metadata + */ ServerCallContext build(RoutingContext rc); } diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java index ee9d3ae98..65ab017d7 100644 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java +++ b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java @@ -3,7 +3,30 @@ import io.a2a.server.TransportMetadata; import io.a2a.spec.TransportProtocol; +/** + * Transport metadata implementation for Quarkus REST. + * + *

        This class provides transport protocol identification for the Quarkus REST + * reference implementation. It reports {@link TransportProtocol#HTTP_JSON} as + * the transport protocol, indicating that this implementation uses HTTP with + * JSON payloads for the A2A protocol. + * + *

        The transport metadata is used by the framework for: + *

          + *
        • Logging and monitoring (identifying which transport handled a request)
        • + *
        • Protocol negotiation and version compatibility checks
        • + *
        • Metrics and telemetry (transport-specific performance tracking)
        • + *
        + * + * @see TransportMetadata + * @see TransportProtocol + */ public class QuarkusRestTransportMetadata implements TransportMetadata { + /** + * Returns the transport protocol identifier. + * + * @return {@code "http+json"} indicating HTTP transport with JSON encoding + */ @Override public String getTransportProtocol() { return TransportProtocol.HTTP_JSON.asString(); diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java index 00ca87bd6..2e76b40eb 100644 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java +++ b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java @@ -1,3 +1,65 @@ +/** + * Quarkus REST reference implementation for the A2A protocol. + * + *

        This package provides a ready-to-use Quarkus-based REST transport implementation + * that maps HTTP endpoints to A2A protocol operations. It serves as both a reference + * implementation and a production-ready solution for deploying A2A agents over HTTP/REST. + * + *

        Key Components

        + *
          + *
        • {@link A2AServerRoutes} - Vert.x route definitions mapping HTTP paths to A2A operations
        • + *
        • {@link CallContextFactory} - Extensible factory for creating {@link io.a2a.server.ServerCallContext}
        • + *
        • {@link QuarkusRestTransportMetadata} - Transport protocol metadata implementation
        • + *
        + * + *

        Architecture

        + *
        + * HTTP Request (Quarkus/Vert.x)
        + *     ↓
        + * A2AServerRoutes (@Route methods)
        + *     ↓
        + * RestHandler (transport/rest)
        + *     ↓
        + * RequestHandler (server-common)
        + *     ↓
        + * AgentExecutor (user implementation)
        + * 
        + * + *

        Supported Endpoints

        + *
          + *
        • {@code POST /message:send} - Send message (blocking)
        • + *
        • {@code POST /message:stream} - Send message (streaming SSE)
        • + *
        • {@code GET /tasks} - List tasks
        • + *
        • {@code GET /tasks/{taskId}} - Get task by ID
        • + *
        • {@code POST /tasks/{taskId}:cancel} - Cancel task
        • + *
        • {@code POST /tasks/{taskId}:subscribe} - Subscribe to task updates (SSE)
        • + *
        • {@code GET /.well-known/agent-card.json} - Get agent card
        • + *
        + * + *

        Multi-tenancy Support

        + *

        All endpoints support optional tenant prefixes in the URL path: + *

          + *
        • {@code /message:send} - Default tenant (empty string)
        • + *
        • {@code /tenant-123/message:send} - Tenant "tenant-123"
        • + *
        + * + *

        Usage

        + *

        Add this module as a dependency to your Quarkus project: + *

        {@code
        + * 
        + *   io.github.a2asdk
        + *   a2a-java-sdk-reference-rest
        + *   ${a2a.version}
        + * 
        + * }
        + * + *

        Provide CDI beans for {@link io.a2a.spec.AgentCard} and + * {@link io.a2a.server.agentexecution.AgentExecutor}, and the REST endpoints + * will be automatically registered. + * + * @see io.a2a.transport.rest.handler + * @see io.a2a.server.requesthandlers + */ @NullMarked package io.a2a.server.rest.quarkus; diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java b/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java index f822607ef..86e78e1ad 100644 --- a/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java +++ b/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java @@ -3,8 +3,20 @@ /** * Shared REST context keys for A2A protocol data. * - * These keys provide access to REST context information, - * enabling rich context access in service method implementations. + *

        These keys provide access to REST context information stored in + * {@link io.a2a.server.ServerCallContext}, enabling rich context access + * in service method implementations and middleware. + * + *

        Usage Example

        + *
        {@code
        + * public void processRequest(ServerCallContext context) {
        + *     String tenant = context.get(RestContextKeys.TENANT_KEY);
        + *     String method = context.get(RestContextKeys.METHOD_NAME_KEY);
        + *     Map headers = context.get(RestContextKeys.HEADERS_KEY);
        + * }
        + * }
        + * + * @see io.a2a.server.ServerCallContext */ public final class RestContextKeys { 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 3e38d00a3..7c9ea6d4f 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 @@ -66,6 +66,49 @@ import mutiny.zero.ZeroPublisher; import org.jspecify.annotations.Nullable; +/** + * REST transport handler for processing A2A protocol requests over HTTP. + * + *

        This handler converts HTTP REST requests into A2A protocol operations and + * manages the lifecycle of agent interactions including message sending, task + * management, and push notification configurations. + * + *

        Request Flow

        + *

        HTTP REST requests flow through this handler to the underlying {@link RequestHandler}, + * which coordinates with the agent executor and event queue system: + *

        + * HTTP Request → RestHandler → RequestHandler → AgentExecutor
        + *                    ↓              ↓
        + *              Validation    EventQueue → Response
        + * 
        + * + *

        Supported Operations

        + *
          + *
        • Message sending (blocking and streaming)
        • + *
        • Task management (get, list, cancel, subscribe)
        • + *
        • Push notification configurations (create, get, list, delete)
        • + *
        • Agent card retrieval (public and extended)
        • + *
        + * + *

        Error Handling

        + *

        All A2A protocol errors are caught and converted to appropriate HTTP status codes + * via {@link #mapErrorToHttpStatus(A2AError)}. Protocol version and required extensions + * are validated before processing requests. + * + *

        CDI Integration

        + *

        This handler is an {@code @ApplicationScoped} CDI bean that requires: + *

          + *
        • {@link AgentCard} qualified with {@code @PublicAgentCard}
        • + *
        • {@link RequestHandler} for processing A2A operations
        • + *
        • {@link Executor} qualified with {@code @Internal} for async operations
        • + *
        • Optional {@link AgentCard} qualified with {@code @ExtendedAgentCard}
        • + *
        + * + * @see RequestHandler + * @see io.a2a.server.requesthandlers.DefaultRequestHandler + * @see io.a2a.spec.AgentCard + * @see ServerCallContext + */ @ApplicationScoped public class RestHandler { @@ -91,6 +134,14 @@ protected RestHandler() { this.executor = null; } + /** + * Creates a REST handler with full CDI injection support. + * + * @param agentCard the public agent card containing agent capabilities + * @param extendedAgentCard optional extended agent card instance + * @param requestHandler the handler for processing A2A requests + * @param executor the executor for asynchronous operations + */ @Inject public RestHandler(@PublicAgentCard AgentCard agentCard, @ExtendedAgentCard Instance extendedAgentCard, RequestHandler requestHandler, @Internal Executor executor) { @@ -103,12 +154,62 @@ public RestHandler(@PublicAgentCard AgentCard agentCard, @ExtendedAgentCard Inst AgentCardValidator.validateTransportConfiguration(agentCard); } + /** + * Creates a REST handler with basic dependencies. + * + * @param agentCard the agent card containing agent capabilities + * @param requestHandler the handler for processing A2A requests + * @param executor the executor for asynchronous operations + */ public RestHandler(AgentCard agentCard, RequestHandler requestHandler, Executor executor) { this.agentCard = agentCard; this.requestHandler = requestHandler; this.executor = executor; } + /** + * Handles a blocking message send request. + * + *

        This method processes an HTTP POST request containing a message to be sent to the agent. + * The request is validated for protocol version and required extensions before being forwarded + * to the {@link RequestHandler}. The method blocks until the agent produces a terminal event + * or requires authentication/input. + * + *

        Example Request:

        + *
        {@code
        +     * POST /v1/tenants/{tenant}/messages
        +     * Content-Type: application/json
        +     *
        +     * {
        +     *   "message": {
        +     *     "parts": [
        +     *       {"text": "What is the weather in San Francisco?"}
        +     *     ]
        +     *   }
        +     * }
        +     * }
        + * + *

        Example Response:

        + *
        {@code
        +     * HTTP/1.1 200 OK
        +     * Content-Type: application/json
        +     *
        +     * {
        +     *   "task": {
        +     *     "id": "task-123",
        +     *     "status": {"state": "COMPLETED"},
        +     *     "artifacts": [...]
        +     *   }
        +     * }
        +     * }
        + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param body the JSON request body containing the message to send + * @return the HTTP response containing the task or message result + * @see #sendStreamingMessage(ServerCallContext, String, String) + * @see RequestHandler#onMessageSend(io.a2a.spec.MessageSendParams, ServerCallContext) + */ public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, String body) { try { @@ -126,6 +227,51 @@ public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, St } } + /** + * Handles a streaming message send request. + * + *

        This method processes an HTTP POST request for streaming responses from the agent. + * The response is returned as Server-Sent Events (SSE) via {@link HTTPRestStreamingResponse}, + * allowing clients to receive task updates and artifacts as they are produced by the agent. + * + *

        This method requires the agent card to have {@code capabilities.streaming = true}. + * + *

        Example Request:

        + *
        {@code
        +     * POST /v1/tenants/{tenant}/messages/stream
        +     * Content-Type: application/json
        +     *
        +     * {
        +     *   "message": {
        +     *     "parts": [
        +     *       {"text": "Generate a long story"}
        +     *     ]
        +     *   }
        +     * }
        +     * }
        + * + *

        Example Streaming Response:

        + *
        {@code
        +     * HTTP/1.1 200 OK
        +     * Content-Type: text/event-stream
        +     *
        +     * data: {"taskStatusUpdate":{"task":{"id":"task-123","status":{"state":"WORKING"}}}}
        +     *
        +     * data: {"taskArtifactUpdate":{"taskId":"task-123","artifacts":[{"parts":[{"text":"Once upon"}]}]}}
        +     *
        +     * data: {"taskArtifactUpdate":{"taskId":"task-123","artifacts":[{"parts":[{"text":" a time..."}]}]}}
        +     *
        +     * data: {"taskStatusUpdate":{"task":{"id":"task-123","status":{"state":"COMPLETED"}}}}
        +     * }
        + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param body the JSON request body containing the message to send + * @return the streaming HTTP response containing a publisher of events + * @see #sendMessage(ServerCallContext, String, String) + * @see RequestHandler#onMessageSendStream(io.a2a.spec.MessageSendParams, ServerCallContext) + * @see HTTPRestStreamingResponse + */ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String tenant, String body) { try { if (!agentCard.capabilities().streaming()) { @@ -145,6 +291,27 @@ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String t } } + /** + * Handles a task cancellation request. + * + *

        Attempts to cancel a running task identified by the task ID. The cancellation + * request is forwarded to the {@link RequestHandler}, which signals the agent executor + * to stop processing. The agent should transition the task to {@code CANCELED} state. + * + *

        Example Request:

        + *
        {@code
        +     * POST /v1/tenants/{tenant}/tasks/{taskId}/cancel
        +     * }
        + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param body the JSON request body + * @param taskId the ID of the task to cancel + * @return the HTTP response containing the cancelled task + * @throws InvalidParamsError if taskId is null or empty + * @see RequestHandler#onCancelTask(CancelTaskParams, ServerCallContext) + * @see io.a2a.server.agentexecution.AgentExecutor#cancel + */ @SuppressWarnings("unchecked") public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, String body, String taskId) { try { @@ -165,6 +332,15 @@ public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, Str } } + /** + * Creates a push notification configuration for a task. + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param body the JSON request body containing the configuration + * @param taskId the ID of the task + * @return the HTTP response containing the created configuration + */ public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String body, String taskId) { try { if (!agentCard.capabilities().pushNotifications()) { @@ -182,6 +358,34 @@ public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContex } } + /** + * Subscribes to task updates via a streaming connection. + * + *

        Creates a Server-Sent Events (SSE) stream that delivers real-time updates for an + * existing task. This allows clients to reconnect to ongoing or completed tasks and + * receive their event history and future updates. + * + *

        This method requires the agent card to have {@code capabilities.streaming = true}. + * + *

        Example Request:

        + *
        {@code
        +     * GET /v1/tenants/{tenant}/tasks/{taskId}/subscribe
        +     * }
        + * + *

        Use Cases:

        + *
          + *
        • Reconnecting to a task after network interruption
        • + *
        • Monitoring long-running tasks from multiple clients
        • + *
        • Viewing historical events for completed tasks
        • + *
        + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param taskId the ID of the task to subscribe to + * @return the streaming HTTP response containing task updates + * @see RequestHandler#onSubscribeToTask(TaskIdParams, ServerCallContext) + * @see #sendStreamingMessage(ServerCallContext, String, String) + */ public HTTPRestResponse subscribeToTask(ServerCallContext context, String tenant, String taskId) { try { if (!agentCard.capabilities().streaming()) { @@ -197,6 +401,15 @@ public HTTPRestResponse subscribeToTask(ServerCallContext context, String tenant } } + /** + * Retrieves a task by ID. + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param taskId the ID of the task to retrieve + * @param historyLength the maximum number of history entries to include + * @return the HTTP response containing the task + */ public HTTPRestResponse getTask(ServerCallContext context, String tenant, String taskId, @Nullable Integer historyLength) { try { TaskQueryParams params = new TaskQueryParams(taskId, historyLength, tenant); @@ -212,6 +425,43 @@ public HTTPRestResponse getTask(ServerCallContext context, String tenant, String } } + /** + * Lists tasks with optional filtering and pagination. + * + *

        Retrieves a list of tasks with support for filtering by context, status, and timestamp, + * along with pagination controls. This method is useful for task management dashboards, + * monitoring systems, and task history retrieval. + * + *

        Example Request:

        + *
        {@code
        +     * GET /v1/tenants/{tenant}/tasks?status=COMPLETED&pageSize=10&includeArtifacts=true
        +     * }
        + * + *

        Query Parameters:

        + *
          + *
        • {@code contextId} - Filter tasks by conversation context
        • + *
        • {@code status} - Filter by task state (SUBMITTED, WORKING, COMPLETED, etc.)
        • + *
        • {@code pageSize} - Maximum tasks to return (for pagination)
        • + *
        • {@code pageToken} - Token for retrieving next page of results
        • + *
        • {@code historyLength} - Maximum history entries to include per task
        • + *
        • {@code statusTimestampAfter} - ISO-8601 timestamp for filtering recent tasks
        • + *
        • {@code includeArtifacts} - Whether to include task artifacts in response
        • + *
        + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param contextId optional context ID to filter by + * @param status optional task status to filter by (must be valid {@link TaskState} value) + * @param pageSize optional maximum number of tasks to return + * @param pageToken optional token for pagination + * @param historyLength optional maximum number of history entries per task + * @param statusTimestampAfter optional ISO-8601 timestamp to filter tasks updated after + * @param includeArtifacts optional flag to include task artifacts + * @return the HTTP response containing the list of tasks + * @throws InvalidParamsError if status is not a valid TaskState or timestamp is malformed + * @see RequestHandler#onListTasks(ListTasksParams, ServerCallContext) + * @see TaskState + */ public HTTPRestResponse listTasks(ServerCallContext context, String tenant, @Nullable String contextId, @Nullable String status, @Nullable Integer pageSize, @Nullable String pageToken, @@ -274,6 +524,15 @@ public HTTPRestResponse listTasks(ServerCallContext context, String tenant, } } + /** + * Retrieves a specific push notification configuration for a task. + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param taskId the ID of the task + * @param configId the ID of the configuration to retrieve + * @return the HTTP response containing the configuration + */ public HTTPRestResponse getTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String taskId, String configId) { try { if (!agentCard.capabilities().pushNotifications()) { @@ -289,6 +548,16 @@ public HTTPRestResponse getTaskPushNotificationConfiguration(ServerCallContext c } } + /** + * Lists push notification configurations for a task. + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param taskId the ID of the task + * @param pageSize the maximum number of configurations to return + * @param pageToken the token for pagination + * @return the HTTP response containing the list of configurations + */ public HTTPRestResponse listTaskPushNotificationConfigurations(ServerCallContext context, String tenant, String taskId, int pageSize, String pageToken) { try { if (!agentCard.capabilities().pushNotifications()) { @@ -304,6 +573,15 @@ public HTTPRestResponse listTaskPushNotificationConfigurations(ServerCallContext } } + /** + * Deletes a push notification configuration for a task. + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @param taskId the ID of the task + * @param configId the ID of the configuration to delete + * @return the HTTP response with no content on success + */ public HTTPRestResponse deleteTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String taskId, String configId) { try { if (!agentCard.capabilities().pushNotifications()) { @@ -351,6 +629,12 @@ private HTTPRestResponse createSuccessResponse(int statusCode, com.google.protob } } + /** + * Creates an HTTP error response from an A2A error. + * + * @param error the A2A error to convert + * @return the HTTP response with appropriate status code and error details + */ public HTTPRestResponse createErrorResponse(A2AError error) { int statusCode = mapErrorToHttpStatus(error); return createErrorResponse(statusCode, error); @@ -428,6 +712,24 @@ public void onComplete() { }); } + /** + * Maps A2A protocol errors to HTTP status codes. + * + *

        This method ensures consistent HTTP status code mapping for all A2A errors: + *

          + *
        • 400 - Invalid request, JSON parse errors, missing extensions
        • + *
        • 404 - Method not found, task not found
        • + *
        • 409 - Task not cancelable (conflict)
        • + *
        • 415 - Unsupported content type
        • + *
        • 422 - Invalid parameters (unprocessable entity)
        • + *
        • 500 - Internal errors
        • + *
        • 501 - Not implemented (unsupported operations, version)
        • + *
        • 502 - Bad gateway (invalid agent response)
        • + *
        + * + * @param error the A2A error to map + * @return the corresponding HTTP status code + */ private int mapErrorToHttpStatus(A2AError error) { if (error instanceof InvalidRequestError || error instanceof JSONParseError) { return 400; @@ -462,6 +764,26 @@ private int mapErrorToHttpStatus(A2AError error) { return 500; } + /** + * Retrieves the extended agent card if configured. + * + *

        The extended agent card provides additional metadata beyond the public agent card, + * such as tenant-specific configurations or private capabilities. This endpoint requires + * the agent card to have {@code capabilities.extendedAgentCard = true} and a CDI-produced + * {@code @ExtendedAgentCard} instance. + * + *

        Example Request:

        + *
        {@code
        +     * GET /v1/tenants/{tenant}/extended-agent-card
        +     * }
        + * + * @param context the server call context containing authentication and metadata + * @param tenant the tenant identifier + * @return the HTTP response containing the extended agent card + * @throws ExtendedAgentCardNotConfiguredError if extended agent card is not available + * @see #getAgentCard() + * @see AgentCard + */ public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String tenant) { try { if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { @@ -475,6 +797,38 @@ public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String t } } + /** + * Retrieves the public agent card. + * + *

        The agent card is a self-describing manifest that provides essential metadata about + * the agent, including its capabilities, supported skills, communication methods, and + * security requirements. This is the primary discovery endpoint for clients to understand + * what the agent can do and how to interact with it. + * + *

        Example Request:

        + *
        {@code
        +     * GET /v1/agent-card
        +     * }
        + * + *

        Example Response:

        + *
        {@code
        +     * {
        +     *   "name": "Weather Agent",
        +     *   "description": "Provides weather information",
        +     *   "version": "1.0.0",
        +     *   "capabilities": {
        +     *     "streaming": true,
        +     *     "pushNotifications": false
        +     *   },
        +     *   "skills": [...],
        +     *   "supportedInterfaces": [...]
        +     * }
        +     * }
        + * + * @return the HTTP response containing the agent card + * @see AgentCard + * @see #getExtendedAgentCard(ServerCallContext, String) + */ public HTTPRestResponse getAgentCard() { try { return new HTTPRestResponse(200, "application/json", JsonUtil.toJson(agentCard)); @@ -483,26 +837,51 @@ public HTTPRestResponse getAgentCard() { } } + /** + * Represents an HTTP REST response with status code, content type, and body. + */ public static class HTTPRestResponse { private final int statusCode; private final String contentType; private final String body; + /** + * Creates an HTTP REST response. + * + * @param statusCode the HTTP status code + * @param contentType the content type of the response + * @param body the response body + */ public HTTPRestResponse(int statusCode, String contentType, String body) { this.statusCode = statusCode; this.contentType = contentType; this.body = body; } + /** + * Returns the HTTP status code. + * + * @return the status code + */ public int getStatusCode() { return statusCode; } + /** + * Returns the content type. + * + * @return the content type + */ public String getContentType() { return contentType; } + /** + * Returns the response body. + * + * @return the body + */ public String getBody() { return body; } @@ -513,26 +892,47 @@ public String toString() { } } + /** + * Represents an HTTP streaming response with Server-Sent Events. + */ public static class HTTPRestStreamingResponse extends HTTPRestResponse { private final Flow.Publisher publisher; + /** + * Creates an HTTP streaming response. + * + * @param publisher the publisher of streaming events + */ public HTTPRestStreamingResponse(Flow.Publisher publisher) { super(200, "text/event-stream", ""); this.publisher = publisher; } + /** + * Returns the publisher for streaming events. + * + * @return the publisher + */ public Flow.Publisher getPublisher() { return publisher; } } + /** + * Represents an HTTP error response containing A2A error details. + */ private static class HTTPRestErrorResponse { private final String error; private final @Nullable String message; + /** + * Creates an error response from an A2A error. + * + * @param jsonRpcError the A2A error + */ private HTTPRestErrorResponse(A2AError jsonRpcError) { this.error = jsonRpcError.getClass().getName(); this.message = jsonRpcError.getMessage(); diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java b/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java index 8d4e4063c..d8ea46ac7 100644 --- a/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java +++ b/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java @@ -1,3 +1,15 @@ +/** + * REST transport handler implementations for the A2A protocol. + * + *

        This package contains the core REST handler that processes HTTP requests + * and translates them to A2A protocol operations. It includes support for: + *

          + *
        • Message sending (blocking and streaming)
        • + *
        • Task management and querying
        • + *
        • Push notification configurations
        • + *
        • Agent card retrieval
        • + *
        + */ @NullMarked package io.a2a.transport.rest.handler; diff --git a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java b/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java index 68aad41bb..d9401d68e 100644 --- a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java +++ b/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java @@ -3,7 +3,16 @@ import io.a2a.server.TransportMetadata; import io.a2a.spec.TransportProtocol; +/** + * Test implementation of TransportMetadata for REST transport testing. + */ public class RestTestTransportMetadata implements TransportMetadata { + + /** + * Returns the transport protocol used for REST communication. + * + * @return the HTTP JSON transport protocol identifier + */ @Override public String getTransportProtocol() { return TransportProtocol.HTTP_JSON.asString(); From 20b65551cb3ffe34d8816bf8dd36fdbab09998e3 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 9 Mar 2026 18:13:13 +0000 Subject: [PATCH 069/192] fix: Use Kafka 4.2.0 for Kubernetes example (#718) Partially revert fb06d43b34b252ecd8df5c264e548f3eefb6edfd / #710, since now we can use https://strimzi.io/install/latest?namespace=kafka again --- .github/workflows/cloud-deployment-example.yml | 2 +- examples/cloud-deployment/k8s/02-kafka.yaml | 4 ++-- examples/cloud-deployment/scripts/deploy.sh | 13 +++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cloud-deployment-example.yml b/.github/workflows/cloud-deployment-example.yml index 7f84f6fc3..5c4e1e01a 100644 --- a/.github/workflows/cloud-deployment-example.yml +++ b/.github/workflows/cloud-deployment-example.yml @@ -27,7 +27,7 @@ jobs: - name: Install Kind run: | - curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.30.0/kind-linux-amd64 + curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind kind version diff --git a/examples/cloud-deployment/k8s/02-kafka.yaml b/examples/cloud-deployment/k8s/02-kafka.yaml index 044aeb1ac..a4ad8eb0f 100644 --- a/examples/cloud-deployment/k8s/02-kafka.yaml +++ b/examples/cloud-deployment/k8s/02-kafka.yaml @@ -33,8 +33,8 @@ metadata: strimzi.io/kraft: enabled spec: kafka: - version: 4.0.0 - metadataVersion: 4.0-IV0 + version: 4.2.0 + metadataVersion: 4.2-IV0 listeners: - name: plain port: 9092 diff --git a/examples/cloud-deployment/scripts/deploy.sh b/examples/cloud-deployment/scripts/deploy.sh index 9fc890eee..448457221 100755 --- a/examples/cloud-deployment/scripts/deploy.sh +++ b/examples/cloud-deployment/scripts/deploy.sh @@ -177,12 +177,13 @@ if ! kubectl get namespace kafka > /dev/null 2>&1; then fi if ! kubectl get crd kafkas.kafka.strimzi.io > /dev/null 2>&1; then - echo "Installing Strimzi operator... at https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.50.1/strimzi-cluster-operator-0.50.1.yaml" - curl -sL 'https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.50.1/strimzi-cluster-operator-0.50.1.yaml' \ - | sed 's/namespace: .*/namespace: kafka/' \ - | kubectl apply -f - -n kafka -# echo "Installing Strimzi operator..." -# kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka +# Keep this around in case we need to hardcode operator version again in the future +# echo "Installing Strimzi operator... at https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.50.1/strimzi-cluster-operator-0.50.1.yaml" +# curl -sL 'https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.50.1/strimzi-cluster-operator-0.50.1.yaml' \ +# | sed 's/namespace: .*/namespace: kafka/' \ +# | kubectl apply -f - -n kafka + echo "Installing Strimzi operator..." + kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka echo "Waiting for Strimzi operator deployment to be created..." for i in {1..30}; do From 14fece4c184ecd03d163d99a97460da5a4e37cc4 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 10 Mar 2026 15:59:49 +0100 Subject: [PATCH 070/192] fix: Setting the proper content type for errors. (#720) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The expected content type is application/problem+json when there is an error and not application/json Fixes #719 🦕 Signed-off-by: Emmanuel Hugonnet --- .../main/java/io/a2a/common/MediaType.java | 7 +++ .../server/apps/quarkus/A2AServerRoutes.java | 5 +- .../apps/quarkus/A2AServerRoutesTest.java | 58 ++++++++++++++++--- .../transport/rest/handler/RestHandler.java | 15 +++-- .../rest/handler/RestHandlerTest.java | 18 +++--- 5 files changed, 78 insertions(+), 25 deletions(-) create mode 100644 common/src/main/java/io/a2a/common/MediaType.java diff --git a/common/src/main/java/io/a2a/common/MediaType.java b/common/src/main/java/io/a2a/common/MediaType.java new file mode 100644 index 000000000..9c7027f60 --- /dev/null +++ b/common/src/main/java/io/a2a/common/MediaType.java @@ -0,0 +1,7 @@ +package io.a2a.common; + +public interface MediaType { + + public static final String APPLICATION_JSON = "application/json"; + public static final String APPLICATION_PROBLEM_JSON = "application/problem+json"; +} 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 a7b9f93e1..096a8b80a 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 @@ -1,5 +1,6 @@ package io.a2a.server.apps.quarkus; +import static io.a2a.common.MediaType.APPLICATION_PROBLEM_JSON; import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; @@ -293,7 +294,7 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { if (error != null) { rc.response() .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .putHeader(CONTENT_TYPE, APPLICATION_PROBLEM_JSON) .end(serializeResponse(error)); } else if (streaming) { final Multi> finalStreamingResponse = streamingResponse; @@ -309,7 +310,7 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { } else { rc.response() .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .putHeader(CONTENT_TYPE, nonStreamingResponse.getError() != null ? APPLICATION_PROBLEM_JSON : APPLICATION_JSON) .end(serializeResponse(nonStreamingResponse)); } } 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 2e6d3562a..1b99213e6 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,11 +1,21 @@ package io.a2a.server.apps.quarkus; +import static io.a2a.common.MediaType.APPLICATION_PROBLEM_JSON; +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; 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.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; import static java.util.Collections.singletonList; +import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; @@ -59,14 +69,6 @@ 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. @@ -166,6 +168,7 @@ public void testSendMessage_MethodNameSetInContext() { ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(SEND_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test @@ -250,6 +253,7 @@ public void testGetTask_MethodNameSetInContext() { ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(GET_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test @@ -286,6 +290,7 @@ public void testCancelTask_MethodNameSetInContext() { ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(CANCEL_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test @@ -363,6 +368,7 @@ public void testCreateTaskPushNotificationConfig_MethodNameSetInContext() { ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test @@ -401,6 +407,7 @@ public void testGetTaskPushNotificationConfig_MethodNameSetInContext() { ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test @@ -440,6 +447,7 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() { ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test @@ -473,6 +481,7 @@ public void testDeleteTaskPushNotificationConfig_MethodNameSetInContext() { ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test @@ -509,6 +518,7 @@ public void testGetExtendedCard_MethodNameSetInContext() { ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); assertEquals(GET_EXTENDED_AGENT_CARD_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test @@ -707,6 +717,38 @@ public void testTenantExtraction_StreamingRequest() { assertEquals("myTenant/api", capturedContext.getState().get(TENANT_KEY)); } + @Test + public void testJsonParseError_ContentTypeIsProblemJson() { + // Arrange - invalid JSON + String invalidJson = "not valid json {{{"; + when(mockRequestBody.asString()).thenReturn(invalidJson); + + // Act + routes.invokeJSONRPCHandler(invalidJson, mockRoutingContext); + + // Assert + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_PROBLEM_JSON); + } + + @Test + public void testMethodNotFound_ContentTypeIsProblemJson() { + // Arrange - unknown method + String jsonRpcRequest = """ + { + "jsonrpc": "2.0", + "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", + "method": "UnknownMethod", + "params": {} + }"""; + when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); + + // Act + routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); + + // Assert + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_PROBLEM_JSON); + } + /** * Helper method to set a field via reflection for testing purposes. */ 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 7c9ea6d4f..ad4e29cc1 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 @@ -1,5 +1,7 @@ package io.a2a.transport.rest.handler; +import static io.a2a.common.MediaType.APPLICATION_JSON; +import static io.a2a.common.MediaType.APPLICATION_PROBLEM_JSON; import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; @@ -115,6 +117,7 @@ public class RestHandler { private static final Logger log = Logger.getLogger(RestHandler.class.getName()); private static final String TASK_STATE_PREFIX = "TASK_STATE_"; + // Fields set by constructor injection cannot be final. We need a noargs constructor for // Jakarta compatibility, and it seems that making fields set by constructor injection // final, is not proxyable in all runtimes @@ -589,7 +592,7 @@ public HTTPRestResponse deleteTaskPushNotificationConfiguration(ServerCallContex } DeleteTaskPushNotificationConfigParams params = new DeleteTaskPushNotificationConfigParams(taskId, configId, tenant); requestHandler.onDeleteTaskPushNotificationConfig(params, context); - return new HTTPRestResponse(204, "application/json", ""); + return new HTTPRestResponse(204, APPLICATION_JSON, ""); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { @@ -622,8 +625,8 @@ private void validate(String json) { private HTTPRestResponse createSuccessResponse(int statusCode, com.google.protobuf.Message.Builder builder) { try { // Include default value fields to ensure empty arrays, zeros, etc. are present in JSON - String jsonBody = JsonFormat.printer().includingDefaultValueFields().print(builder); - return new HTTPRestResponse(statusCode, "application/json", jsonBody); + String jsonBody = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().print(builder); + return new HTTPRestResponse(statusCode, APPLICATION_JSON, jsonBody); } catch (InvalidProtocolBufferException e) { return createErrorResponse(new InternalError("Failed to serialize response: " + e.getMessage())); } @@ -642,7 +645,7 @@ public HTTPRestResponse createErrorResponse(A2AError error) { private HTTPRestResponse createErrorResponse(int statusCode, A2AError error) { String jsonBody = new HTTPRestErrorResponse(error).toJson(); - return new HTTPRestResponse(statusCode, "application/json", jsonBody); + return new HTTPRestResponse(statusCode, APPLICATION_PROBLEM_JSON, jsonBody); } private HTTPRestStreamingResponse createStreamingResponse(Flow.Publisher publisher) { @@ -789,7 +792,7 @@ public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String t if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { throw new ExtendedAgentCardNotConfiguredError(null, "Extended Card not configured", null); } - return new HTTPRestResponse(200, "application/json", JsonUtil.toJson(extendedAgentCard.get())); + return new HTTPRestResponse(200, APPLICATION_JSON, JsonUtil.toJson(extendedAgentCard.get())); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable t) { @@ -831,7 +834,7 @@ public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String t */ public HTTPRestResponse getAgentCard() { try { - return new HTTPRestResponse(200, "application/json", JsonUtil.toJson(agentCard)); + return new HTTPRestResponse(200, APPLICATION_JSON, JsonUtil.toJson(agentCard)); } catch (Throwable t) { return createErrorResponse(500, new InternalError(t.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 bb1f3fe37..f896f0af2 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 @@ -54,7 +54,7 @@ public void testGetTaskNotFound() { RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", "nonexistent", 0); Assertions.assertEquals(404, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("TaskNotFoundError")); } @@ -79,7 +79,7 @@ public void testListTasksInvalidStatus() { null, null, null); Assertions.assertEquals(422, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); } @@ -122,7 +122,7 @@ public void testSendMessageInvalidBody() { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", invalidBody); Assertions.assertEquals(400, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("JSONParseError"),response.getBody()); } @@ -146,7 +146,7 @@ public void testSendMessageWrongValueBody() { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); Assertions.assertEquals(422, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); } @@ -157,7 +157,7 @@ public void testSendMessageEmptyBody() { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", ""); Assertions.assertEquals(400, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("InvalidRequestError")); } @@ -190,7 +190,7 @@ public void testCancelTaskNotFound() { RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, "nonexistent"); Assertions.assertEquals(404, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("TaskNotFoundError")); } @@ -564,7 +564,7 @@ public void testExtensionSupportRequiredErrorOnSendMessage() { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); Assertions.assertEquals(400, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("ExtensionSupportRequiredError")); Assertions.assertTrue(response.getBody().contains("https://example.com/test-extension")); } @@ -764,7 +764,7 @@ public void testVersionNotSupportedErrorOnSendMessage() { RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithVersion, "", requestBody); Assertions.assertEquals(501, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("VersionNotSupportedError")); Assertions.assertTrue(response.getBody().contains("2.0")); } @@ -969,7 +969,7 @@ public void testListTasksNegativeTimestampReturns422() { null, "-1", null); Assertions.assertEquals(422, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals("application/problem+json", response.getContentType()); Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); } From 81d7eae8e4d09f2c2c2885ce99ffafab7c3a90ff Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 10 Mar 2026 16:43:22 +0100 Subject: [PATCH 071/192] feat: add convenience constructors to FileWithBytes (#706) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add three constructors to FileWithBytes that accept a File, a Path, or a byte[] and handle base64 encoding internally, removing the need for callers to encode content before construction. Fixes #702 🦕 Signed-off-by: Emmanuel Hugonnet --- .../transport/jsonrpc/JsonMessages.java | 5 +- .../transport/rest/JsonRestMessages.java | 1 + .../io/a2a/jsonrpc/common/json/JsonUtil.java | 54 ++- .../common/json/TaskSerializationTest.java | 77 ++++ .../java/io/a2a/grpc/mapper/PartMapper.java | 4 +- .../a2a/grpc/utils/PartTypeAdapterTest.java | 37 ++ .../main/java/io/a2a/spec/FileWithBytes.java | 331 +++++++++++++++++- .../java/io/a2a/spec/FileWithBytesTest.java | 273 +++++++++++++++ spec/src/test/resources/a2a-logo-white.svg | 9 + 9 files changed, 776 insertions(+), 15 deletions(-) create mode 100644 spec/src/test/java/io/a2a/spec/FileWithBytesTest.java create mode 100644 spec/src/test/resources/a2a-logo-white.svg 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 71fac010e..67ef81346 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 @@ -1,7 +1,5 @@ package io.a2a.client.transport.jsonrpc; -import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; - /** * Request and response messages used by the tests. These have been created following examples from * the A2A sample messages. @@ -266,7 +264,8 @@ public class JsonMessages { }, { "raw":"aGVsbG8=", - "filename":"hello.txt" + "filename":"hello.txt", + "mediaType": "text/plain" } ], "messageId":"message-123" diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java index 471ac5d90..b9a6527e0 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java @@ -91,6 +91,7 @@ public class JsonRestMessages { }, { "raw": "aGVsbG8=", + "filename":"hello.txt", "mediaType": "text/plain" } ], diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index 76a23273a..9e8fb057f 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -746,9 +746,11 @@ StreamingEventKind read(JsonReader in) throws java.io.IOException { */ static class FileContentTypeAdapter extends TypeAdapter { - // Create separate Gson instance without the FileContent adapter to avoid recursion + // Create separate Gson instance without the FileContent adapter to avoid recursion, + // but with an explicit FileWithBytes adapter to prevent field/path leakage. private final Gson delegateGson = new GsonBuilder() .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) + .registerTypeAdapter(FileWithBytes.class, new FileWithBytesTypeAdapter()) .create(); @Override @@ -788,6 +790,56 @@ FileContent read(JsonReader in) throws java.io.IOException { } } + /** + * Gson TypeAdapter for serializing and deserializing {@link FileWithBytes}. + *

        + * Explicitly maps only the three protocol fields ({@code mimeType}, {@code name}, {@code bytes}) + * to and from JSON. This prevents internal implementation fields (such as the lazy-loading + * {@code source} or the {@code cachedBytes} soft reference) from leaking into serialized output, + * and ensures correct round-trip deserialization via the canonical + * {@link FileWithBytes#FileWithBytes(String, String, String)} constructor. + */ + static class FileWithBytesTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, FileWithBytes value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + out.beginObject(); + out.name("mimeType").value(value.mimeType()); + out.name("name").value(value.name()); + out.name("bytes").value(value.bytes()); + out.endObject(); + } + + @Override + public @Nullable FileWithBytes read(JsonReader in) throws java.io.IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + String mimeType = null; + String name = null; + String bytes = null; + in.beginObject(); + while (in.hasNext()) { + switch (in.nextName()) { + case "mimeType" -> mimeType = in.nextString(); + case "name" -> name = in.nextString(); + case "bytes" -> bytes = in.nextString(); + default -> in.skipValue(); + } + } + in.endObject(); + return new FileWithBytes( + mimeType != null ? mimeType : "", + name != null ? name : "", + bytes != null ? bytes : ""); + } + } + /** * Gson TypeAdapter for serializing and deserializing {@link APIKeySecurityScheme.Location} enum. *

        diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java index ff47e746b..c5199a1e1 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java @@ -2,16 +2,22 @@ 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.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.OffsetDateTime; +import java.util.Base64; import java.util.List; import java.util.Map; import io.a2a.spec.Artifact; import io.a2a.spec.DataPart; +import io.a2a.spec.FileContent; import io.a2a.spec.FilePart; import io.a2a.spec.FileWithBytes; import io.a2a.spec.FileWithUri; @@ -22,6 +28,7 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TextPart; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; /** * Tests for Task serialization and deserialization using Gson. @@ -706,4 +713,74 @@ void testTaskWithMixedPartTypes() throws JsonProcessingException { assertTrue(parts.get(2) instanceof DataPart); assertTrue(parts.get(3) instanceof FilePart); } + + // ========== FileContentTypeAdapter tests ========== + + @TempDir + Path tempDir; + + @Test + void testFileWithBytesSerializationDoesNotLeakInternalFields() throws Exception { + FileWithBytes fwb = new FileWithBytes("application/pdf", "doc.pdf", "base64data"); + + String json = JsonUtil.toJson(fwb); + + // Must contain the three protocol fields + assertTrue(json.contains("\"mimeType\""), "missing mimeType: " + json); + assertTrue(json.contains("\"name\""), "missing name: " + json); + assertTrue(json.contains("\"bytes\""), "missing bytes: " + json); + // Must NOT contain internal implementation fields + assertFalse(json.contains("\"source\""), "internal source field leaked: " + json); + assertFalse(json.contains("\"cachedBytes\""), "internal cachedBytes field leaked: " + json); + } + + @Test + void testFileWithBytesRoundTripViaFileContentTypeAdapter() throws Exception { + FileWithBytes original = new FileWithBytes("image/png", "photo.png", "abc123"); + + String json = JsonUtil.toJson(original); + FileContent deserialized = JsonUtil.fromJson(json, FileContent.class); + + assertInstanceOf(FileWithBytes.class, deserialized); + FileWithBytes result = (FileWithBytes) deserialized; + assertEquals("image/png", result.mimeType()); + assertEquals("photo.png", result.name()); + assertEquals("abc123", result.bytes()); + } + + @Test + void testPathBackedFileWithBytesDoesNotLeakFilePath() throws Exception { + byte[] content = "hello".getBytes(); + Path file = tempDir.resolve("secret.txt"); + Files.write(file, content); + + FileWithBytes fwb = new FileWithBytes("text/plain", file); + + String json = JsonUtil.toJson(fwb); + + // File path must not appear in the serialized JSON + assertFalse(json.contains(file.toString()), "file path leaked in JSON: " + json); + assertFalse(json.contains(tempDir.toString()), "temp dir path leaked in JSON: " + json); + // Must contain the three protocol fields, not internal implementation fields + assertTrue(json.contains("\"bytes\""), "missing bytes field: " + json); + assertFalse(json.contains("\"source\""), "internal source field leaked: " + json); + } + + @Test + void testPathBackedFileWithBytesRoundTrip() throws Exception { + byte[] content = "round-trip".getBytes(); + Path file = tempDir.resolve("data.bin"); + Files.write(file, content); + + FileWithBytes original = new FileWithBytes("application/octet-stream", file); + + String json = JsonUtil.toJson(original); + FileContent deserialized = JsonUtil.fromJson(json, FileContent.class); + + assertInstanceOf(FileWithBytes.class, deserialized); + FileWithBytes result = (FileWithBytes) deserialized; + assertEquals("application/octet-stream", result.mimeType()); + assertEquals("data.bin", result.name()); + assertEquals(Base64.getEncoder().encodeToString(content), result.bytes()); + } } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java index 8704f4699..79748f3c2 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java @@ -95,8 +95,8 @@ default Part fromProto(io.a2a.grpc.Part proto) { } else if (proto.hasRaw()) { // raw bytes → FilePart(FileWithBytes) String bytes = Base64.getEncoder().encodeToString(proto.getRaw().toByteArray()); - String mimeType = proto.getMediaType().isEmpty() ? null : proto.getMediaType(); - String name = proto.getFilename().isEmpty() ? null : proto.getFilename(); + String mimeType = proto.getMediaType().isEmpty() ? "" : proto.getMediaType(); + String name = proto.getFilename().isEmpty() ? "" : proto.getFilename(); return new FilePart(new FileWithBytes(mimeType, name, bytes), metadata); } else if (proto.hasUrl()) { // url → FilePart(FileWithUri) diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java index 8b7eb741b..3daea3a4a 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java @@ -22,12 +22,19 @@ import io.a2a.spec.FileWithUri; import io.a2a.spec.Part; import io.a2a.spec.TextPart; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Base64; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; public class PartTypeAdapterTest { + @TempDir + Path tempDir; + // ------------------------------------------------------------------------- // TextPart // ------------------------------------------------------------------------- @@ -134,6 +141,36 @@ public void shouldRoundTripFilePartWithBytes() throws JsonProcessingException { assertEquals("AAEC", bytes.bytes()); } + @Test + public void shouldRoundTripFilePartWithBytesFromRealFile() throws JsonProcessingException, IOException { + // Create a temporary file with some content + Path testFile = tempDir.resolve("test-file.txt"); + String fileContent = "This is test content for lazy loading verification"; + Files.writeString(testFile, fileContent); + + // Create FileWithBytes from the file path (lazy loading) + FileWithBytes fileWithBytes = new FileWithBytes("text/plain", testFile); + FilePart original = new FilePart(fileWithBytes); + + // Serialize to JSON (this triggers lazy loading) + String json = JsonUtil.toJson(original); + + // Deserialize and verify + Part deserialized = JsonUtil.fromJson(json, Part.class); + assertInstanceOf(FilePart.class, deserialized); + FilePart result = (FilePart) deserialized; + assertInstanceOf(FileWithBytes.class, result.file()); + FileWithBytes bytes = (FileWithBytes) result.file(); + + assertEquals("text/plain", bytes.mimeType()); + assertEquals("test-file.txt", bytes.name()); + + // Verify the content by decoding the base64 + byte[] decodedBytes = Base64.getDecoder().decode(bytes.bytes()); + String decodedContent = new String(decodedBytes); + assertEquals(fileContent, decodedContent); + } + // ------------------------------------------------------------------------- // FilePart – FileWithUri // ------------------------------------------------------------------------- diff --git a/spec/src/main/java/io/a2a/spec/FileWithBytes.java b/spec/src/main/java/io/a2a/spec/FileWithBytes.java index b5aef3813..53e448c5f 100644 --- a/spec/src/main/java/io/a2a/spec/FileWithBytes.java +++ b/spec/src/main/java/io/a2a/spec/FileWithBytes.java @@ -1,28 +1,341 @@ package io.a2a.spec; +import io.a2a.util.Assert; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ref.SoftReference; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Base64; +import java.util.Objects; + +import org.jspecify.annotations.Nullable; + /** * Represents file content embedded directly as base64-encoded bytes. *

        * FileWithBytes is used when file content needs to be transmitted inline with the message or * artifact, rather than requiring a separate download. This is appropriate for: *

          - *
        • Small files that fit comfortably in a JSON payload
        • - *
        • Generated content that doesn't exist as a standalone file
        • - *
        • Content that must be preserved exactly as created
        • - *
        • Scenarios where URI accessibility is uncertain
        • + *
        • Small files that fit comfortably in a JSON payload
        • + *
        • Generated content that doesn't exist as a standalone file
        • + *
        • Content that must be preserved exactly as created
        • + *
        • Scenarios where URI accessibility is uncertain
        • *
        *

        * The bytes field contains the base64-encoded file content. Decoders should handle the base64 * encoding/decoding transparently. *

        - * This class is immutable. + * This class uses lazy loading with soft-reference caching to reduce memory pressure: the + * base64-encoded content is computed on-demand and held via a {@link SoftReference}, allowing + * the JVM to reclaim it under memory pressure. If reclaimed, it is recomputed on next access. * - * @param mimeType the MIME type of the file (e.g., "image/png", "application/pdf") (required) - * @param name the file name (e.g., "report.pdf", "diagram.png") (required) - * @param bytes the base64-encoded file content (required) * @see FileContent * @see FilePart * @see FileWithUri */ -public record FileWithBytes(String mimeType, String name, String bytes) implements FileContent { +public final class FileWithBytes implements FileContent { + + /** + * Maximum file size that can be loaded (10 MB). + * Files larger than this will be rejected at construction time. + */ + private static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB + + private final String mimeType; + private final String name; + + // Source for (re)generating base64 content on-demand + private final ByteSource source; + + // Soft-reference cache: held in memory but reclaimable by GC under memory pressure + @Nullable + private volatile SoftReference cachedBytes; + + /** + * Creates a {@code FileWithBytes} with pre-encoded base64 content. + * This is the canonical constructor used by serialization frameworks. + * + * @param mimeType the MIME type of the file (e.g., "image/png", "application/pdf") + * @param name the file name (e.g., "report.pdf", "diagram.png") + * @param bytes the base64-encoded file content + */ + public FileWithBytes(String mimeType, String name, String bytes) { + this.mimeType = Assert.checkNotNullParam("mimeType", mimeType); + this.name = Assert.checkNotNullParam("name", name); + this.source = new PreEncodedSource(Assert.checkNotNullParam("bytes", bytes)); + this.cachedBytes = new SoftReference<>(bytes); + } + + /** + * Creates a {@code FileWithBytes} by reading the content of the given {@link File}. + * The file name is derived from {@link File#getName()}. + *

        + * The file is validated at construction time to ensure it exists, is readable, is a regular file, + * and does not exceed the maximum size limit ({@value #MAX_FILE_SIZE} bytes). + *

        + * The file content is read and base64-encoded on the first call to {@link #bytes()}, then + * cached via a soft reference. The cache may be cleared by GC under memory pressure, in + * which case the file is re-read on the next access. + * + * @param mimeType the MIME type of the file (e.g., {@code "image/png"}) + * @param file the file whose content will be read and encoded + * @throws IllegalArgumentException if the file does not exist, is not readable, is not a regular file, + * or exceeds the maximum size limit + * @throws RuntimeException if an I/O error occurs while checking the file + */ + public FileWithBytes(String mimeType, File file) { + this(mimeType, file.toPath()); + } + + /** + * Creates a {@code FileWithBytes} by reading the content of the given {@link Path}. + * The file name is derived from {@link Path#getFileName()}. + *

        + * The file is validated at construction time to ensure it exists, is readable, is a regular file, + * and does not exceed the maximum size limit ({@value #MAX_FILE_SIZE} bytes). + *

        + * The file content is read and base64-encoded on the first call to {@link #bytes()}, then + * cached via a soft reference. The cache may be cleared by GC under memory pressure, in + * which case the file is re-read on the next access. + * + * @param mimeType the MIME type of the file (e.g., {@code "image/png"}) + * @param file the path whose content will be read and encoded + * @throws IllegalArgumentException if the file does not exist, is not readable, is not a regular file, + * or exceeds the maximum size limit + * @throws RuntimeException if an I/O error occurs while checking the file + */ + public FileWithBytes(String mimeType, Path file) { + this.mimeType = Assert.checkNotNullParam("mimeType", mimeType); + validateFile(file); + this.name = file.getFileName().toString(); + this.source = new PathSource(file); + } + + /** + * Creates a {@code FileWithBytes} by base64-encoding the given raw byte array. + *

        + * A defensive copy of {@code content} is made at construction time, so subsequent mutations + * to the caller's array have no effect. The copy is base64-encoded on the first call to + * {@link #bytes()}, then cached via a soft reference. The cache may be cleared by GC under + * memory pressure, in which case the encoding is recomputed from the retained copy. + * + * @param mimeType the MIME type of the file (e.g., {@code "application/pdf"}) + * @param name the file name (e.g., {@code "report.pdf"}) + * @param content the raw file content to be base64-encoded + * @throws NullPointerException if {@code content} is null + */ + public FileWithBytes(String mimeType, String name, byte[] content) { + this.mimeType = Assert.checkNotNullParam("mimeType", mimeType); + this.name = Assert.checkNotNullParam("name", name); + this.source = new ByteArraySource(content); + } + + @Override + public String mimeType() { + return mimeType; + } + + @Override + public String name() { + return name; + } + + /** + * Returns the base64-encoded file content. + *

        + * The content is computed on the first call and cached via a soft reference. Subsequent calls + * return the cached value. If the JVM reclaims the cache under memory pressure, the content is + * recomputed transparently on the next access. + *

        + * For instances created from a {@link File} or {@link Path}, recomputation involves reading + * the file from disk. Callers in performance-sensitive paths should retain the returned value + * rather than calling this method repeatedly. + * + * @return the base64-encoded file content + * @throws RuntimeException if an I/O error occurs while reading a file-backed source + */ + public String bytes() { + // First check: fast path without locking + SoftReference ref = cachedBytes; + if (ref != null) { + String cached = ref.get(); + if (cached != null) { + return cached; + } + } + // Second check: slow path, synchronized to prevent redundant computation + // (especially costly for file-backed sources, which would re-read from disk) + synchronized (this) { + ref = cachedBytes; + if (ref != null) { + String cached = ref.get(); + if (cached != null) { + return cached; + } + } + try { + String computed = source.getBase64(); + cachedBytes = new SoftReference<>(computed); + return computed; + } catch (IOException e) { + throw new RuntimeException("Failed to load file content", e); + } + } + } + + /** + * Compares this FileWithBytes to another object for equality. + *

        + * Important: This method uses identity-based comparison to avoid triggering + * potentially expensive I/O operations. Two FileWithBytes instances are considered equal only + * if they are the same object (reference equality). + *

        + * This design choice prevents: + *

          + *
        • Unexpected file I/O during collection operations (HashMap, HashSet, etc.)
        • + *
        • Performance issues when comparing file-backed instances
        • + *
        • RuntimeExceptions from I/O errors during equality checks
        • + *
        + *

        + * If you need to compare the actual content of two FileWithBytes instances, use a separate + * method or compare the results of {@link #bytes()} explicitly. + * + * @param o the object to compare with + * @return true if this is the same object as o, false otherwise + */ + @Override + public boolean equals(Object o) { + return this == o; + } + + /** + * Returns the identity hash code for this FileWithBytes. + *

        + * This method uses {@link System#identityHashCode(Object)} to avoid triggering I/O operations + * that would be required to compute a content-based hash code. This ensures that using + * FileWithBytes instances as keys in HashMap or elements in HashSet remains safe and efficient. + * + * @return the identity hash code + */ + @Override + public int hashCode() { + return System.identityHashCode(this); + } + + @Override + public String toString() { + return "FileWithBytes[mimeType=" + mimeType + ", name=" + name + "]"; + } + + /** + * Validates that a file exists, is readable, is a regular file, and does not exceed the maximum size. + * + * @param file the file to validate + * @throws IllegalArgumentException if validation fails + * @throws RuntimeException if an I/O error occurs during validation + */ + private static void validateFile(Path file) { + if (!Files.exists(file)) { + throw new IllegalArgumentException("File does not exist: " + file); + } + if (!Files.isReadable(file)) { + throw new IllegalArgumentException("File is not readable: " + file); + } + if (!Files.isRegularFile(file)) { + throw new IllegalArgumentException("Not a regular file: " + file); + } + try { + long size = Files.size(file); + if (size > MAX_FILE_SIZE) { + throw new IllegalArgumentException( + String.format("File too large: %d bytes (maximum: %d bytes)", size, MAX_FILE_SIZE) + ); + } + } catch (IOException e) { + throw new RuntimeException("Failed to check file size: " + file, e); + } + } + + /** + * Internal interface for different byte sources. + */ + private interface ByteSource { + String getBase64() throws IOException; + } + + /** + * Source for pre-encoded base64 content. + */ + private static final class PreEncodedSource implements ByteSource { + private final String base64; + + PreEncodedSource(String base64) { + this.base64 = base64; + } + + @Override + public String getBase64() { + return base64; + } + } + + /** + * Source for file path that needs to be read and encoded. + */ + private static final class PathSource implements ByteSource { + private final Path path; + + PathSource(Path path) { + this.path = path; + } + + @Override + public String getBase64() throws IOException { + return encodeFileToBase64(path); + } + } + + /** + * Source for byte array that needs to be encoded. + */ + private static final class ByteArraySource implements ByteSource { + private final byte[] content; + + ByteArraySource(byte[] content) { + this.content = Objects.requireNonNull(content, "content must not be null").clone(); + } + + @Override + public String getBase64() { + return Base64.getEncoder().encodeToString(content); + } + } + + /** + * Encodes a file to base64 by streaming its content in chunks. + * This avoids loading the entire file into memory at once by using + * a wrapping output stream that encodes data as it's written. + * + * @param path the path to the file to encode + * @return the base64-encoded content + * @throws IOException if an I/O error occurs reading the file + */ + private static String encodeFileToBase64(Path path) throws IOException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(path)); + OutputStream base64OutputStream = Base64.getEncoder().wrap(outputStream)) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + base64OutputStream.write(buffer, 0, bytesRead); + } + } + return outputStream.toString(StandardCharsets.UTF_8); + } } diff --git a/spec/src/test/java/io/a2a/spec/FileWithBytesTest.java b/spec/src/test/java/io/a2a/spec/FileWithBytesTest.java new file mode 100644 index 000000000..5cf556198 --- /dev/null +++ b/spec/src/test/java/io/a2a/spec/FileWithBytesTest.java @@ -0,0 +1,273 @@ +package io.a2a.spec; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Base64; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +/** + * Unit tests for the convenience constructors added to {@link FileWithBytes}. + *

        + * The canonical {@code FileWithBytes(String, String, String)} constructor expects the bytes field + * to already be base64-encoded. The constructors under test accept raw sources ({@link java.io.File}, + * {@link java.nio.file.Path}, or {@code byte[]}) and handle the base64 encoding internally. + *

        + * Each group of tests verifies: + *

          + *
        • Correct base64 encoding of the provided content
        • + *
        • Correct derivation of the file name from the source
        • + *
        • Correct propagation of the MIME type
        • + *
        • Edge cases such as empty content
        • + *
        + * The cross-constructor consistency tests confirm that all three convenience constructors and the + * canonical constructor produce equivalent {@link FileWithBytes} instances when given the same data. + */ +class FileWithBytesTest { + + private static final String SVG_MIME_TYPE = "image/svg+xml"; + private static final String SVG_RESOURCE = "/a2a-logo-white.svg"; + + @TempDir + Path tempDir; + + private Path svgPath() throws URISyntaxException { + return Path.of(getClass().getResource(SVG_RESOURCE).toURI()); + } + + private String base64(byte[] content) { + return Base64.getEncoder().encodeToString(content); + } + + private Path writeTempFile(String name, byte[] content) throws IOException { + Path path = tempDir.resolve(name); + Files.write(path, content); + return path; + } + + // ========== File constructor ========== + + @Test + void testFileConstructor_encodesContentAsBase64() throws IOException { + byte[] content = "hello world".getBytes(); + File file = writeTempFile("test.txt", content).toFile(); + + FileWithBytes fwb = new FileWithBytes("text/plain", file); + + assertEquals("text/plain", fwb.mimeType()); + assertEquals("test.txt", fwb.name()); + assertEquals(base64(content), fwb.bytes()); + } + + @Test + void testFileConstructor_useFileNameFromPath() throws IOException, URISyntaxException { + File svgFile = svgPath().toFile(); + + FileWithBytes fwb = new FileWithBytes(SVG_MIME_TYPE, svgFile); + + assertEquals(SVG_MIME_TYPE, fwb.mimeType()); + assertEquals("a2a-logo-white.svg", fwb.name()); + assertEquals(base64(Files.readAllBytes(svgFile.toPath())), fwb.bytes()); + } + + @Test + void testFileConstructor_emptyFile() throws IOException { + File file = writeTempFile("empty.bin", new byte[0]).toFile(); + + FileWithBytes fwb = new FileWithBytes("application/octet-stream", file); + + assertEquals("application/octet-stream", fwb.mimeType()); + assertEquals("empty.bin", fwb.name()); + assertEquals("", fwb.bytes()); + } + + // ========== Path constructor ========== + + @Test + void testPathConstructor_encodesContentAsBase64() throws IOException { + byte[] content = "path content".getBytes(); + Path path = writeTempFile("data.txt", content); + + FileWithBytes fwb = new FileWithBytes("text/plain", path); + + assertEquals("text/plain", fwb.mimeType()); + assertEquals("data.txt", fwb.name()); + assertEquals(base64(content), fwb.bytes()); + } + + @Test + void testPathConstructor_usesFileNameFromPath() throws IOException, URISyntaxException { + Path path = svgPath(); + + FileWithBytes fwb = new FileWithBytes(SVG_MIME_TYPE, path); + + assertEquals(SVG_MIME_TYPE, fwb.mimeType()); + assertEquals("a2a-logo-white.svg", fwb.name()); + assertEquals(base64(Files.readAllBytes(path)), fwb.bytes()); + } + + @Test + void testPathConstructor_emptyFile() throws IOException { + Path path = writeTempFile("empty.txt", new byte[0]); + + FileWithBytes fwb = new FileWithBytes("text/plain", path); + + assertEquals("text/plain", fwb.mimeType()); + assertEquals("empty.txt", fwb.name()); + assertEquals("", fwb.bytes()); + } + + // ========== byte[] constructor ========== + + @Test + void testByteArrayConstructor_encodesContentAsBase64() throws IOException { + byte[] content = "binary data".getBytes(); + + FileWithBytes fwb = new FileWithBytes("application/octet-stream", "data.bin", content); + + assertEquals("application/octet-stream", fwb.mimeType()); + assertEquals("data.bin", fwb.name()); + assertEquals(base64(content), fwb.bytes()); + } + + @Test + void testByteArrayConstructor_emptyArray() throws IOException { + FileWithBytes fwb = new FileWithBytes("text/plain", "empty.txt", new byte[0]); + + assertEquals("text/plain", fwb.mimeType()); + assertEquals("empty.txt", fwb.name()); + assertEquals("", fwb.bytes()); + } + + @Test + void testByteArrayConstructor_binaryContent() throws IOException { + byte[] content = new byte[]{0, 1, 2, (byte) 0xFF, (byte) 0xFE}; + + FileWithBytes fwb = new FileWithBytes("application/octet-stream", "bin.dat", content); + + byte[] decoded = Base64.getDecoder().decode(fwb.bytes()); + assertArrayEquals(content, decoded); + } + + // ========== Consistency across constructors ========== + + @Test + void testFileAndPathConstructorsProduceSameResult() throws IOException { + Path path = writeTempFile("consistent.txt", "consistent content".getBytes()); + + FileWithBytes fromFile = new FileWithBytes("text/plain", path.toFile()); + FileWithBytes fromPath = new FileWithBytes("text/plain", path); + + assertEquals(fromFile.mimeType(), fromPath.mimeType()); + assertEquals(fromFile.name(), fromPath.name()); + assertEquals(fromFile.bytes(), fromPath.bytes()); + } + + @Test + void testByteArrayConstructorMatchesCanonicalConstructor() throws IOException { + byte[] content = "test".getBytes(); + + FileWithBytes fromCanonical = new FileWithBytes("text/plain", "test.txt", base64(content)); + FileWithBytes fromByteArray = new FileWithBytes("text/plain", "test.txt", content); + + assertEquals(fromCanonical.mimeType(), fromByteArray.mimeType()); + assertEquals(fromCanonical.name(), fromByteArray.name()); + assertEquals(fromCanonical.bytes(), fromByteArray.bytes()); + } + + @Test + void testFileConstructorMatchesCanonicalConstructor() throws IOException { + byte[] content = "file content".getBytes(); + Path path = writeTempFile("match.txt", content); + + FileWithBytes fromCanonical = new FileWithBytes("text/plain", "match.txt", base64(content)); + FileWithBytes fromFile = new FileWithBytes("text/plain", path.toFile()); + + assertEquals(fromCanonical.mimeType(), fromFile.mimeType()); + assertEquals(fromCanonical.name(), fromFile.name()); + assertEquals(fromCanonical.bytes(), fromFile.bytes()); + } + + // ========== File validation tests ========== + + @Test + void testPathConstructor_rejectsNonExistentFile() { + Path nonExistent = tempDir.resolve("does-not-exist.txt"); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new FileWithBytes("text/plain", nonExistent)); + + assertTrue(exception.getMessage().contains("does not exist")); + } + + @Test + void testPathConstructor_rejectsDirectory() throws IOException { + Path directory = tempDir.resolve("subdir"); + Files.createDirectory(directory); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new FileWithBytes("text/plain", directory)); + + assertTrue(exception.getMessage().contains("Not a regular file")); + } + + @Test + void testPathConstructor_rejectsTooLargeFile() throws IOException { + // Create a file larger than 10MB + Path largeFile = tempDir.resolve("large.bin"); + byte[] chunk = new byte[1024 * 1024]; // 1MB + try (var out = Files.newOutputStream(largeFile)) { + for (int i = 0; i < 11; i++) { // Write 11MB + out.write(chunk); + } + } + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new FileWithBytes("application/octet-stream", largeFile)); + + assertTrue(exception.getMessage().contains("too large")); + assertTrue(exception.getMessage().contains("maximum")); + } + + // ========== Identity-based equality tests ========== + + @Test + void testEquals_usesIdentityComparison() throws IOException { + byte[] content = "test content".getBytes(); + Path path = writeTempFile("test.txt", content); + + FileWithBytes fwb1 = new FileWithBytes("text/plain", path); + FileWithBytes fwb2 = new FileWithBytes("text/plain", path); + + // Same object should equal itself + assertEquals(fwb1, fwb1); + + // Different objects with same content should NOT be equal (identity-based) + assertNotEquals(fwb1, fwb2); + } + + @Test + void testHashCode_usesIdentityHashCode() throws IOException { + byte[] content = "test content".getBytes(); + Path path = writeTempFile("test.txt", content); + + FileWithBytes fwb1 = new FileWithBytes("text/plain", path); + FileWithBytes fwb2 = new FileWithBytes("text/plain", path); + + // Hash codes should be different for different objects (identity-based) + assertNotEquals(fwb1.hashCode(), fwb2.hashCode()); + + // Hash code should be consistent for same object + assertEquals(fwb1.hashCode(), fwb1.hashCode()); + } +} diff --git a/spec/src/test/resources/a2a-logo-white.svg b/spec/src/test/resources/a2a-logo-white.svg new file mode 100644 index 000000000..0d1a0a67a --- /dev/null +++ b/spec/src/test/resources/a2a-logo-white.svg @@ -0,0 +1,9 @@ + + + + + + + + + From d11484be406ce2f44c02ea89d509fc72307c2e53 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Tue, 10 Mar 2026 16:43:47 +0100 Subject: [PATCH 072/192] fix!: Update the name of A2A headers (#709) A2A-Version and A2A-Extensions are specified by the spec (as of dec790a) instead of the X-A2A-*. Also updates the gRPC context keys to get rid of the prefix. I did not change the `X-A2A-Notification-Token` header that is still present in the spec but I'll open a PR to verify if that's not an omission Signed-off-by: Jeff Mesnil --- .../client/transport/grpc/GrpcTransport.java | 16 ++++++------- .../main/java/io/a2a/common/A2AHeaders.java | 4 ++-- .../quarkus/A2AExtensionsInterceptor.java | 24 ++++++++++--------- .../server/apps/quarkus/A2AServerRoutes.java | 8 +++---- .../server/rest/quarkus/A2AServerRoutes.java | 8 +++---- .../grpc/context/GrpcContextKeys.java | 12 ++++++---- .../grpc/handler/CallContextFactory.java | 4 ++-- .../transport/grpc/handler/GrpcHandler.java | 8 +++---- 8 files changed, 45 insertions(+), 39 deletions(-) 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 474b7b784..351c3543a 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 @@ -61,10 +61,10 @@ public class GrpcTransport implements ClientTransport { AuthInterceptor.AUTHORIZATION, Metadata.ASCII_STRING_MARSHALLER); private static final Metadata.Key EXTENSIONS_KEY = Metadata.Key.of( - A2AHeaders.X_A2A_EXTENSIONS, + A2AHeaders.A2A_EXTENSIONS.toLowerCase(), Metadata.ASCII_STRING_MARSHALLER); private static final Metadata.Key VERSION_KEY = Metadata.Key.of( - A2AHeaders.X_A2A_VERSION, + A2AHeaders.A2A_VERSION.toLowerCase(), Metadata.ASCII_STRING_MARSHALLER); private final A2AServiceBlockingV2Stub blockingStub; private final A2AServiceStub asyncStub; @@ -380,8 +380,8 @@ private io.a2a.grpc.SendMessageRequest createGrpcSendMessageRequest(MessageSendP /** * Creates gRPC metadata from ClientCallContext headers. - * Extracts headers like X-A2A-Extensions and sets them as gRPC metadata. - * + * Extracts headers like a2a-extensions and sets them as gRPC metadata. + * The headers are lower-cased (compared to the HTTP headers). * @param context the client call context containing headers, may be null * @param payloadAndHeaders the payload and headers wrapper, may be null * @return the gRPC metadata @@ -390,14 +390,14 @@ private Metadata createGrpcMetadata(@Nullable ClientCallContext context, @Nullab Metadata metadata = new Metadata(); if (context != null && context.getHeaders() != null) { - // Set X-A2A-Version header if present - String versionHeader = context.getHeaders().get(A2AHeaders.X_A2A_VERSION); + // Set a2a-version header if present + String versionHeader = context.getHeaders().get(A2AHeaders.A2A_VERSION.toLowerCase()); if (versionHeader != null) { metadata.put(VERSION_KEY, versionHeader); } - // Set X-A2A-Extensions header if present - String extensionsHeader = context.getHeaders().get(A2AHeaders.X_A2A_EXTENSIONS); + // Set a2a-extensions header if present + String extensionsHeader = context.getHeaders().get(A2AHeaders.A2A_EXTENSIONS.toLowerCase()); if (extensionsHeader != null) { metadata.put(EXTENSIONS_KEY, extensionsHeader); } diff --git a/common/src/main/java/io/a2a/common/A2AHeaders.java b/common/src/main/java/io/a2a/common/A2AHeaders.java index f050333aa..ffbbebda9 100644 --- a/common/src/main/java/io/a2a/common/A2AHeaders.java +++ b/common/src/main/java/io/a2a/common/A2AHeaders.java @@ -9,13 +9,13 @@ public final class A2AHeaders { * HTTP header name for A2A protocol version. * Used to communicate the protocol version that the client is using. */ - public static final String X_A2A_VERSION = "X-A2A-Version"; + public static final String A2A_VERSION = "A2A-Version"; /** * HTTP header name for A2A extensions. * Used to communicate which extensions are requested by the client. */ - public static final String X_A2A_EXTENSIONS = "X-A2A-Extensions"; + public static final String A2A_EXTENSIONS = "A2A-Extensions"; /** * HTTP header name for a push notification token. 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 c024a92f0..f985e7cd1 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 @@ -21,8 +21,8 @@ * *

        Captured Information

        *
          - *
        • A2A Protocol Version: {@code X-A2A-Version} header
        • - *
        • A2A Extensions: {@code X-A2A-Extensions} header
        • + *
        • A2A Protocol Version: {@code a2a-version} header
        • + *
        • A2A Extensions: {@code a2a-extensions} header
        • *
        • Complete Metadata: All request headers via {@link io.grpc.Metadata}
        • *
        • Method Name: gRPC method being invoked
        • *
        • Peer Information: Client connection details
        • @@ -60,6 +60,13 @@ @ApplicationScoped public class A2AExtensionsInterceptor implements ServerInterceptor { + private static final Metadata.Key EXTENSIONS_KEY = Metadata.Key.of( + A2AHeaders.A2A_EXTENSIONS.toLowerCase(), + Metadata.ASCII_STRING_MARSHALLER); + private static final Metadata.Key VERSION_KEY = Metadata.Key.of( + A2AHeaders.A2A_VERSION.toLowerCase(), + Metadata.ASCII_STRING_MARSHALLER); + /** * Intercepts incoming gRPC calls to capture metadata and context information. * @@ -68,8 +75,8 @@ public class A2AExtensionsInterceptor implements ServerInterceptor { * *

          Extraction Process: *

            - *
          1. Extract {@code X-A2A-Version} header from metadata
          2. - *
          3. Extract {@code X-A2A-Extensions} header from metadata
          4. + *
          5. Extract {@code a2a-version} header from metadata
          6. + *
          7. Extract {@code a2a-extensions} header from metadata
          8. *
          9. Capture complete {@link Metadata} object
          10. *
          11. Capture gRPC method name from {@link ServerCall}
          12. *
          13. Map gRPC method to A2A protocol method name
          14. @@ -92,14 +99,9 @@ public ServerCall.Listener interceptCall( ServerCallHandler serverCallHandler) { // Extract A2A protocol version header - Metadata.Key versionKey = - Metadata.Key.of(A2AHeaders.X_A2A_VERSION, Metadata.ASCII_STRING_MARSHALLER); - String version = metadata.get(versionKey); - + String version = metadata.get(VERSION_KEY); // Extract A2A extensions header - Metadata.Key extensionsKey = - Metadata.Key.of(A2AHeaders.X_A2A_EXTENSIONS, Metadata.ASCII_STRING_MARSHALLER); - String extensions = metadata.get(extensionsKey); + String extensions = metadata.get(EXTENSIONS_KEY); // Create enhanced context with rich information (equivalent to Python's ServicerContext) Context context = Context.current() 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 096a8b80a..c1e831ebb 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 @@ -514,11 +514,11 @@ public String getUsername() { state.put(TENANT_KEY, extractTenant(rc)); state.put(TRANSPORT_KEY, TransportProtocol.JSONRPC); - // Extract requested protocol version from X-A2A-Version header - String requestedVersion = rc.request().getHeader(A2AHeaders.X_A2A_VERSION); + // Extract requested protocol version from A2A-Version header + String requestedVersion = rc.request().getHeader(A2AHeaders.A2A_VERSION); - // Extract requested extensions from X-A2A-Extensions header - List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders.X_A2A_EXTENSIONS); + // Extract requested extensions from A2A-Extensions header + List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders.A2A_EXTENSIONS); Set requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues); return new ServerCallContext(user, state, requestedExtensions, requestedVersion); 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 05e352a18..a2f81e1f7 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 @@ -731,11 +731,11 @@ public String getUsername() { state.put(TENANT_KEY, extractTenant(rc)); state.put(TRANSPORT_KEY, TransportProtocol.HTTP_JSON); - // Extract requested protocol version from X-A2A-Version header - String requestedVersion = rc.request().getHeader(A2AHeaders.X_A2A_VERSION); + // Extract requested protocol version from A2A-Version header + String requestedVersion = rc.request().getHeader(A2AHeaders.A2A_VERSION); - // Extract requested extensions from X-A2A-Extensions header - List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders.X_A2A_EXTENSIONS); + // Extract requested extensions from A2A-Extensions header + List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders.A2A_EXTENSIONS); Set requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues); return new ServerCallContext(user, state, requestedExtensions, requestedVersion); diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java index 58878c7a3..99062f6fe 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java @@ -1,8 +1,12 @@ package io.a2a.transport.grpc.context; +import static java.util.Locale.ROOT; + +import java.util.Locale; import java.util.Map; +import io.a2a.common.A2AHeaders; import io.a2a.spec.A2AMethods; import io.grpc.Context; @@ -40,18 +44,18 @@ public final class GrpcContextKeys { /** - * Context key for storing the X-A2A-Version header value. + * Context key for storing the a2a-version header value. * Set by server interceptors and accessed by service handlers. */ public static final Context.Key VERSION_HEADER_KEY = - Context.key("x-a2a-version"); + Context.key(A2AHeaders.A2A_VERSION.toLowerCase(ROOT)); /** - * Context key for storing the X-A2A-Extensions header value. + * Context key for storing the a2a-extensions header value. * Set by server interceptors and accessed by service handlers. */ public static final Context.Key EXTENSIONS_HEADER_KEY = - Context.key("x-a2a-extensions"); + Context.key(A2AHeaders.A2A_EXTENSIONS.toLowerCase(ROOT)); /** * Context key for storing the complete gRPC Metadata object. diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java index 1a52f41bb..11a8edfaf 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java @@ -18,8 +18,8 @@ *
          15. User authentication from security context
          16. *
          17. gRPC metadata (headers)
          18. *
          19. Method name and peer information
          20. - *
          21. A2A protocol version from {@code X-A2A-Version} header
          22. - *
          23. Required extensions from {@code X-A2A-Extensions} header
          24. + *
          25. A2A protocol version from {@code A2A-Version} header
          26. + *
          27. Required extensions from {@code A2A-Extensions} header
          28. *
          29. Response observer for gRPC streaming
          30. *
        * 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 cf58e9da9..159d687c2 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 @@ -600,8 +600,8 @@ public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificat *
      • HTTP headers extracted from metadata
      • *
      • gRPC method name
      • *
      • Peer information (client connection details)
      • - *
      • A2A protocol version from {@code X-A2A-Version} header (via context)
      • - *
      • Required extensions from {@code X-A2A-Extensions} header (via context)
      • + *
      • A2A protocol version from {@code A2A-Version} header (via context)
      • + *
      • Required extensions from {@code A2A-Extensions} header (via context)
      • * * *

        Custom Context Creation: @@ -901,7 +901,7 @@ public static void setStreamingSubscribedRunnable(Runnable runnable) { protected abstract Executor getExecutor(); /** - * Attempts to extract the X-A2A-Version header from the current gRPC context. + * Attempts to extract the A2A-Version header from the current gRPC context. * This will only work if a server interceptor has been configured to capture * the metadata and store it in the context. * @@ -917,7 +917,7 @@ public static void setStreamingSubscribedRunnable(Runnable runnable) { } /** - * Attempts to extract the X-A2A-Extensions header from the current gRPC context. + * Attempts to extract the A2A-Extensions header from the current gRPC context. * This will only work if a server interceptor has been configured to capture * the metadata and store it in the context. * From e252a0f95c01d0979efd2c4c29f6f981dbcb567b Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Wed, 11 Mar 2026 12:38:14 +0100 Subject: [PATCH 073/192] fix: Use case-insensitive matching for A2A headers in gRPC transport (#721) Follow-up to #709. Use equalsIgnoreCase when matching A2A headers instead of toLowerCase() key lookups. Co-authored-by: Claude Opus 4.6 --- .../client/transport/grpc/GrpcTransport.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) 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 351c3543a..0fe63efe1 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 @@ -390,16 +390,17 @@ private Metadata createGrpcMetadata(@Nullable ClientCallContext context, @Nullab Metadata metadata = new Metadata(); if (context != null && context.getHeaders() != null) { - // Set a2a-version header if present - String versionHeader = context.getHeaders().get(A2AHeaders.A2A_VERSION.toLowerCase()); - if (versionHeader != null) { - metadata.put(VERSION_KEY, versionHeader); - } - - // Set a2a-extensions header if present - String extensionsHeader = context.getHeaders().get(A2AHeaders.A2A_EXTENSIONS.toLowerCase()); - if (extensionsHeader != null) { - metadata.put(EXTENSIONS_KEY, extensionsHeader); + // Set a2a-version and a2a-extensions headers if present, ignoring case + for (Map.Entry header : context.getHeaders().entrySet()) { + if (A2AHeaders.A2A_VERSION.equalsIgnoreCase(header.getKey())) { + if (header.getValue() != null) { + metadata.put(VERSION_KEY, header.getValue()); + } + } else if (A2AHeaders.A2A_EXTENSIONS.equalsIgnoreCase(header.getKey())) { + if (header.getValue() != null) { + metadata.put(EXTENSIONS_KEY, header.getValue()); + } + } } // Add other headers as needed in the future From 5af2b29f6830bcd4f007e8584d62fa6cce03dfdf Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 11 Mar 2026 15:15:51 +0100 Subject: [PATCH 074/192] fix!: Rename `blocking` to `returnImmediately` in SendMessageConfiguration (#722) Sync a2a.proto with upstream (dec790a -> 601c408). The `blocking` field in `SendMessageConfiguration` has been renamed to `return_immediately` with inverted semantics: - `blocking=true` (wait) -> `returnImmediately=false` - `blocking=false` (return immediately) -> `returnImmediately=true` The default behavior changed: `false` now means "wait for completion" instead of "return immediately". BREAKING CHANGE: `MessageSendConfiguration.blocking()` renamed to `returnImmediately()`. Builder method `.blocking(boolean)` renamed to `.returnImmediately(boolean)` with inverted value. JSON wire format field changed from `"blocking"` to `"returnImmediately"`. --------- Signed-off-by: Emmanuel Hugonnet Co-authored-by: Kabir Khan Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../src/main/java/io/a2a/client/Client.java | 2 +- .../JSONRPCTransportStreamingTest.java | 4 +- .../jsonrpc/JSONRPCTransportTest.java | 16 +- .../transport/jsonrpc/JsonMessages.java | 10 +- .../transport/rest/RestTransportTest.java | 4 +- .../apps/quarkus/A2AServerRoutesTest.java | 6 +- .../server/agentexecution/RequestContext.java | 2 +- .../DefaultRequestHandler.java | 17 +- .../agentexecution/RequestContextTest.java | 2 +- .../DefaultRequestHandlerTest.java | 2 +- spec-grpc/src/main/java/io/a2a/grpc/A2A.java | 476 +++++++++--------- .../src/main/java/io/a2a/grpc/OAuthFlows.java | 16 +- .../java/io/a2a/grpc/OAuthFlowsOrBuilder.java | 8 +- .../io/a2a/grpc/SendMessageConfiguration.java | 94 ++-- .../SendMessageConfigurationOrBuilder.java | 14 +- spec-grpc/src/main/proto/a2a.proto | 12 +- .../grpc/mapper/A2ACommonFieldMapperTest.java | 2 +- .../java/io/a2a/grpc/utils/ToProtoTest.java | 2 +- .../io/a2a/spec/MessageSendConfiguration.java | 20 +- .../apps/common/AbstractA2AServerTest.java | 2 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 2 +- .../rest/handler/RestHandlerTest.java | 12 +- 22 files changed, 369 insertions(+), 356 deletions(-) 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 2ca01307b..5c0d3fce2 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -696,7 +696,7 @@ private ClientEvent getClientEvent(StreamingEventKind event, ClientTaskManager t private MessageSendConfiguration createMessageSendConfiguration(@Nullable TaskPushNotificationConfig taskPushNotificationConfig) { return MessageSendConfiguration.builder() .acceptedOutputModes(clientConfig.getAcceptedOutputModes()) - .blocking(!clientConfig.isPolling()) + .returnImmediately(clientConfig.isPolling()) .historyLength(clientConfig.getHistoryLength()) .taskPushNotificationConfig(taskPushNotificationConfig) .build(); 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 1f28d9201..594eac974 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 @@ -62,7 +62,7 @@ public void testSendStreamingMessageParams() { MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(false) + .returnImmediately(true) .build(); MessageSendParams params = MessageSendParams.builder() @@ -102,7 +102,7 @@ public void testA2AClientSendStreamingMessage() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(false) + .returnImmediately(true) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 23174820e..47c450506 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -111,7 +111,7 @@ public void testA2AClientSendMessage() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(true) + .returnImmediately(false) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) @@ -159,7 +159,7 @@ public void testA2AClientSendMessageWithMessageResponse() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(true) + .returnImmediately(false) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) @@ -201,7 +201,7 @@ public void testA2AClientSendMessageWithError() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(true) + .returnImmediately(false) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) @@ -446,7 +446,7 @@ public void testA2AClientSendMessageWithFilePart() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(true) + .returnImmediately(false) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) @@ -506,7 +506,7 @@ public void testA2AClientSendMessageWithDataPart() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(true) + .returnImmediately(false) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) @@ -564,7 +564,7 @@ public void testA2AClientSendMessageWithMixedParts() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(true) + .returnImmediately(false) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) @@ -625,7 +625,7 @@ public void testExtensionSupportRequiredErrorUnmarshalling() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(true) + .returnImmediately(false) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) @@ -681,7 +681,7 @@ public void testVersionNotSupportedErrorUnmarshalling() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(true) + .returnImmediately(false) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) 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 67ef81346..a9639b84c 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 @@ -151,7 +151,7 @@ public class JsonMessages { "acceptedOutputModes":[ "text" ], - "blocking":true + "returnImmediately":false }, "metadata":{ @@ -201,7 +201,7 @@ public class JsonMessages { "acceptedOutputModes":[ "text" ], - "blocking":true + "returnImmediately":false }, "metadata":{ @@ -385,7 +385,7 @@ public class JsonMessages { "acceptedOutputModes":[ "text" ], - "blocking":true + "returnImmediately":false }, "metadata":{ @@ -452,7 +452,7 @@ public class JsonMessages { "acceptedOutputModes":[ "text" ], - "blocking":true + "returnImmediately":false }, "metadata":{ @@ -523,7 +523,7 @@ public class JsonMessages { "acceptedOutputModes":[ "text" ], - "blocking":true + "returnImmediately":false }, "metadata":{ diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java index bf8e482fe..efa89006b 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java @@ -259,7 +259,7 @@ public void testSendMessageStreaming() throws Exception { .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(false) + .returnImmediately(true) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) @@ -577,7 +577,7 @@ public void testVersionNotSupportedErrorUnmarshallingStreaming() throws Exceptio .build(); MessageSendConfiguration configuration = MessageSendConfiguration.builder() .acceptedOutputModes(List.of("text")) - .blocking(false) + .returnImmediately(true) .build(); MessageSendParams params = MessageSendParams.builder() .message(message) 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 1b99213e6..94f67bc71 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 @@ -141,7 +141,7 @@ public void testSendMessage_MethodNameSetInContext() { }, "configuration": { "acceptedOutputModes": ["text"], - "blocking": true + "returnImmediately": false }, "metadata": {} } @@ -193,7 +193,7 @@ public void testSendStreamingMessage_MethodNameSetInContext() { }, "configuration": { "acceptedOutputModes": ["text"], - "blocking": true + "returnImmediately": false }, "metadata": {} } @@ -692,7 +692,7 @@ public void testTenantExtraction_StreamingRequest() { }, "configuration": { "acceptedOutputModes": ["text"], - "blocking": true + "returnImmediately": false }, "metadata": {} } 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 9d4798a05..b88709163 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 @@ -51,7 +51,7 @@ * * // Access configuration if needed * MessageSendConfiguration config = context.getConfiguration(); - * boolean isBlocking = config != null && config.blocking(); + * boolean returnImmediately = config != null && Boolean.TRUE.equals(config.returnImmediately()); * * // Process and respond... * } 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 1145a3092..f73c84a72 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 @@ -441,15 +441,16 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte final java.util.concurrent.atomic.AtomicReference<@NonNull String> taskId = new java.util.concurrent.atomic.AtomicReference<>(queueTaskId); ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); - // Default to blocking=false per A2A spec (return after task creation) - boolean blocking = params.configuration() != null && Boolean.TRUE.equals(params.configuration().blocking()); - - // Log blocking behavior from client request - if (params.configuration() != null && params.configuration().blocking() != null) { - LOGGER.debug("DefaultRequestHandler: Client requested blocking={} for task {}", - params.configuration().blocking(), taskId.get()); + // Default to blocking per A2A spec (returnImmediately defaults to false, meaning wait for completion) + boolean returnImmediately = params.configuration() != null && Boolean.TRUE.equals(params.configuration().returnImmediately()); + boolean blocking = !returnImmediately; + + // Log return behavior from client request + if (params.configuration() != null && params.configuration().returnImmediately() != null) { + LOGGER.debug("DefaultRequestHandler: Client requested returnImmediately={}, using blocking={} for task {}", + params.configuration().returnImmediately(), blocking, taskId.get()); } else if (params.configuration() != null) { - LOGGER.debug("DefaultRequestHandler: Client sent configuration but blocking=null, using default blocking={} for task {}", blocking, taskId.get()); + LOGGER.debug("DefaultRequestHandler: Client sent configuration but returnImmediately=null, using default blocking={} for task {}", blocking, taskId.get()); } else { LOGGER.debug("DefaultRequestHandler: Client sent no configuration, using default blocking={} for task {}", blocking, taskId.get()); } 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 7e05ea739..98cccbd55 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 @@ -30,7 +30,7 @@ public class RequestContextTest { private static MessageSendConfiguration defaultConfiguration() { return MessageSendConfiguration.builder() .acceptedOutputModes(List.of()) - .blocking(false) + .returnImmediately(true) .build(); } 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 00db599f2..f737eb1ee 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 @@ -55,7 +55,7 @@ public class DefaultRequestHandlerTest { private static final MessageSendConfiguration DEFAULT_CONFIG = MessageSendConfiguration.builder() - .blocking(false) + .returnImmediately(true) .acceptedOutputModes(List.of()) .build(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java index 5317db6ba..24a14b35c 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java @@ -295,248 +295,248 @@ public static void registerAllExtensions( "oogle/api/field_behavior.proto\032\033google/p" + "rotobuf/empty.proto\032\034google/protobuf/str" + "uct.proto\032\037google/protobuf/timestamp.pro" + - "to\"\311\001\n\030SendMessageConfiguration\022\035\n\025accep" + + "to\"\323\001\n\030SendMessageConfiguration\022\035\n\025accep" + "ted_output_modes\030\001 \003(\t\022L\n\035task_push_noti" + "fication_config\030\002 \001(\0132%.lf.a2a.v1.TaskPu" + "shNotificationConfig\022\033\n\016history_length\030\003" + - " \001(\005H\000\210\001\001\022\020\n\010blocking\030\004 \001(\010B\021\n\017_history_" + - "length\"\317\001\n\004Task\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\022\n\ncont" + - "ext_id\030\002 \001(\t\022*\n\006status\030\003 \001(\0132\025.lf.a2a.v1" + - ".TaskStatusB\003\340A\002\022&\n\tartifacts\030\004 \003(\0132\023.lf" + - ".a2a.v1.Artifact\022#\n\007history\030\005 \003(\0132\022.lf.a" + - "2a.v1.Message\022)\n\010metadata\030\006 \001(\0132\027.google" + - ".protobuf.Struct\"\212\001\n\nTaskStatus\022(\n\005state" + - "\030\001 \001(\0162\024.lf.a2a.v1.TaskStateB\003\340A\002\022#\n\007mes" + - "sage\030\002 \001(\0132\022.lf.a2a.v1.Message\022-\n\ttimest" + - "amp\030\003 \001(\0132\032.google.protobuf.Timestamp\"\270\001" + - "\n\004Part\022\016\n\004text\030\001 \001(\tH\000\022\r\n\003raw\030\002 \001(\014H\000\022\r\n" + - "\003url\030\003 \001(\tH\000\022&\n\004data\030\004 \001(\0132\026.google.prot" + - "obuf.ValueH\000\022)\n\010metadata\030\005 \001(\0132\027.google." + - "protobuf.Struct\022\020\n\010filename\030\006 \001(\t\022\022\n\nmed" + - "ia_type\030\007 \001(\tB\t\n\007content\"\353\001\n\007Message\022\027\n\n" + - "message_id\030\001 \001(\tB\003\340A\002\022\022\n\ncontext_id\030\002 \001(" + - "\t\022\017\n\007task_id\030\003 \001(\t\022\"\n\004role\030\004 \001(\0162\017.lf.a2" + - "a.v1.RoleB\003\340A\002\022#\n\005parts\030\005 \003(\0132\017.lf.a2a.v" + - "1.PartB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027.google.p" + - "rotobuf.Struct\022\022\n\nextensions\030\007 \003(\t\022\032\n\022re" + - "ference_task_ids\030\010 \003(\t\"\253\001\n\010Artifact\022\030\n\013a" + - "rtifact_id\030\001 \001(\tB\003\340A\002\022\014\n\004name\030\002 \001(\t\022\023\n\013d" + - "escription\030\003 \001(\t\022#\n\005parts\030\004 \003(\0132\017.lf.a2a" + - ".v1.PartB\003\340A\002\022)\n\010metadata\030\005 \001(\0132\027.google" + - ".protobuf.Struct\022\022\n\nextensions\030\006 \003(\t\"\235\001\n" + - "\025TaskStatusUpdateEvent\022\024\n\007task_id\030\001 \001(\tB" + - "\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022*\n\006status\030" + - "\003 \001(\0132\025.lf.a2a.v1.TaskStatusB\003\340A\002\022)\n\010met" + - "adata\030\004 \001(\0132\027.google.protobuf.Struct\"\303\001\n" + - "\027TaskArtifactUpdateEvent\022\024\n\007task_id\030\001 \001(" + - "\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022*\n\010artif" + - "act\030\003 \001(\0132\023.lf.a2a.v1.ArtifactB\003\340A\002\022\016\n\006a" + - "ppend\030\004 \001(\010\022\022\n\nlast_chunk\030\005 \001(\010\022)\n\010metad" + - "ata\030\006 \001(\0132\027.google.protobuf.Struct\">\n\022Au" + - "thenticationInfo\022\023\n\006scheme\030\001 \001(\tB\003\340A\002\022\023\n" + - "\013credentials\030\002 \001(\t\"p\n\016AgentInterface\022\020\n\003" + - "url\030\001 \001(\tB\003\340A\002\022\035\n\020protocol_binding\030\002 \001(\t" + - "B\003\340A\002\022\016\n\006tenant\030\003 \001(\t\022\035\n\020protocol_versio" + - "n\030\004 \001(\tB\003\340A\002\"\306\005\n\tAgentCard\022\021\n\004name\030\001 \001(\t" + - "B\003\340A\002\022\030\n\013description\030\002 \001(\tB\003\340A\002\022<\n\024suppo" + - "rted_interfaces\030\003 \003(\0132\031.lf.a2a.v1.AgentI" + - "nterfaceB\003\340A\002\022*\n\010provider\030\004 \001(\0132\030.lf.a2a" + - ".v1.AgentProvider\022\024\n\007version\030\005 \001(\tB\003\340A\002\022" + - "\036\n\021documentation_url\030\006 \001(\tH\000\210\001\001\0227\n\014capab" + - "ilities\030\007 \001(\0132\034.lf.a2a.v1.AgentCapabilit" + - "iesB\003\340A\002\022C\n\020security_schemes\030\010 \003(\0132).lf." + - "a2a.v1.AgentCard.SecuritySchemesEntry\022=\n" + - "\025security_requirements\030\t \003(\0132\036.lf.a2a.v1" + - ".SecurityRequirement\022 \n\023default_input_mo" + - "des\030\n \003(\tB\003\340A\002\022!\n\024default_output_modes\030\013" + - " \003(\tB\003\340A\002\022*\n\006skills\030\014 \003(\0132\025.lf.a2a.v1.Ag" + - "entSkillB\003\340A\002\0221\n\nsignatures\030\r \003(\0132\035.lf.a" + - "2a.v1.AgentCardSignature\022\025\n\010icon_url\030\016 \001" + - "(\tH\001\210\001\001\032Q\n\024SecuritySchemesEntry\022\013\n\003key\030\001" + - " \001(\t\022(\n\005value\030\002 \001(\0132\031.lf.a2a.v1.Security" + - "Scheme:\0028\001B\024\n\022_documentation_urlB\013\n\t_ico" + - "n_url\"<\n\rAgentProvider\022\020\n\003url\030\001 \001(\tB\003\340A\002" + - "\022\031\n\014organization\030\002 \001(\tB\003\340A\002\"\332\001\n\021AgentCap" + - "abilities\022\026\n\tstreaming\030\001 \001(\010H\000\210\001\001\022\037\n\022pus" + - "h_notifications\030\002 \001(\010H\001\210\001\001\022-\n\nextensions" + - "\030\003 \003(\0132\031.lf.a2a.v1.AgentExtension\022 \n\023ext" + - "ended_agent_card\030\004 \001(\010H\002\210\001\001B\014\n\n_streamin" + - "gB\025\n\023_push_notificationsB\026\n\024_extended_ag" + - "ent_card\"m\n\016AgentExtension\022\013\n\003uri\030\001 \001(\t\022" + - "\023\n\013description\030\002 \001(\t\022\020\n\010required\030\003 \001(\010\022\'" + - "\n\006params\030\004 \001(\0132\027.google.protobuf.Struct\"" + - "\331\001\n\nAgentSkill\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\021\n\004name\030" + - "\002 \001(\tB\003\340A\002\022\030\n\013description\030\003 \001(\tB\003\340A\002\022\021\n\004" + - "tags\030\004 \003(\tB\003\340A\002\022\020\n\010examples\030\005 \003(\t\022\023\n\013inp" + - "ut_modes\030\006 \003(\t\022\024\n\014output_modes\030\007 \003(\t\022=\n\025" + - "security_requirements\030\010 \003(\0132\036.lf.a2a.v1." + - "SecurityRequirement\"m\n\022AgentCardSignatur" + - "e\022\026\n\tprotected\030\001 \001(\tB\003\340A\002\022\026\n\tsignature\030\002" + - " \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\0132\027.google.proto" + - "buf.Struct\"\241\001\n\032TaskPushNotificationConfi" + - "g\022\016\n\006tenant\030\001 \001(\t\022\n\n\002id\030\002 \001(\t\022\017\n\007task_id" + - "\030\003 \001(\t\022\020\n\003url\030\004 \001(\tB\003\340A\002\022\r\n\005token\030\005 \001(\t\022" + - "5\n\016authentication\030\006 \001(\0132\035.lf.a2a.v1.Auth" + - "enticationInfo\"\032\n\nStringList\022\014\n\004list\030\001 \003" + - "(\t\"\232\001\n\023SecurityRequirement\022<\n\007schemes\030\001 " + - "\003(\0132+.lf.a2a.v1.SecurityRequirement.Sche" + - "mesEntry\032E\n\014SchemesEntry\022\013\n\003key\030\001 \001(\t\022$\n" + - "\005value\030\002 \001(\0132\025.lf.a2a.v1.StringList:\0028\001\"" + - "\200\003\n\016SecurityScheme\022B\n\027api_key_security_s" + - "cheme\030\001 \001(\0132\037.lf.a2a.v1.APIKeySecuritySc" + - "hemeH\000\022F\n\031http_auth_security_scheme\030\002 \001(" + - "\0132!.lf.a2a.v1.HTTPAuthSecuritySchemeH\000\022A" + - "\n\026oauth2_security_scheme\030\003 \001(\0132\037.lf.a2a." + - "v1.OAuth2SecuritySchemeH\000\022Q\n\037open_id_con" + - "nect_security_scheme\030\004 \001(\0132&.lf.a2a.v1.O" + - "penIdConnectSecuritySchemeH\000\022B\n\024mtls_sec" + - "urity_scheme\030\005 \001(\0132\".lf.a2a.v1.MutualTls" + - "SecuritySchemeH\000B\010\n\006scheme\"U\n\024APIKeySecu" + - "rityScheme\022\023\n\013description\030\001 \001(\t\022\025\n\010locat" + - "ion\030\002 \001(\tB\003\340A\002\022\021\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026HTT" + - "PAuthSecurityScheme\022\023\n\013description\030\001 \001(\t" + - "\022\023\n\006scheme\030\002 \001(\tB\003\340A\002\022\025\n\rbearer_format\030\003" + - " \001(\t\"s\n\024OAuth2SecurityScheme\022\023\n\013descript" + - "ion\030\001 \001(\t\022)\n\005flows\030\002 \001(\0132\025.lf.a2a.v1.OAu" + - "thFlowsB\003\340A\002\022\033\n\023oauth2_metadata_url\030\003 \001(" + - "\t\"T\n\033OpenIdConnectSecurityScheme\022\023\n\013desc" + - "ription\030\001 \001(\t\022 \n\023open_id_connect_url\030\002 \001" + - "(\tB\003\340A\002\".\n\027MutualTlsSecurityScheme\022\023\n\013de" + - "scription\030\001 \001(\t\"\301\002\n\nOAuthFlows\022C\n\022author" + - "ization_code\030\001 \001(\0132%.lf.a2a.v1.Authoriza" + - "tionCodeOAuthFlowH\000\022C\n\022client_credential" + - "s\030\002 \001(\0132%.lf.a2a.v1.ClientCredentialsOAu" + - "thFlowH\000\0224\n\010implicit\030\003 \001(\0132\034.lf.a2a.v1.I" + - "mplicitOAuthFlowB\002\030\001H\000\0224\n\010password\030\004 \001(\013" + - "2\034.lf.a2a.v1.PasswordOAuthFlowB\002\030\001H\000\0225\n\013" + - "device_code\030\005 \001(\0132\036.lf.a2a.v1.DeviceCode" + - "OAuthFlowH\000B\006\n\004flow\"\367\001\n\032AuthorizationCod" + - "eOAuthFlow\022\036\n\021authorization_url\030\001 \001(\tB\003\340" + - "A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_ur" + - "l\030\003 \001(\t\022F\n\006scopes\030\004 \003(\01321.lf.a2a.v1.Auth" + - "orizationCodeOAuthFlow.ScopesEntryB\003\340A\002\022" + - "\025\n\rpkce_required\030\005 \001(\010\032-\n\013ScopesEntry\022\013\n" + - "\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\300\001\n\032Client" + - "CredentialsOAuthFlow\022\026\n\ttoken_url\030\001 \001(\tB" + - "\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022F\n\006scopes\030\003 \003(" + - "\01321.lf.a2a.v1.ClientCredentialsOAuthFlow" + - ".ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003key\030" + - "\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\254\001\n\021ImplicitOAu" + - "thFlow\022\031\n\021authorization_url\030\001 \001(\t\022\023\n\013ref" + - "resh_url\030\002 \001(\t\0228\n\006scopes\030\003 \003(\0132(.lf.a2a." + - "v1.ImplicitOAuthFlow.ScopesEntry\032-\n\013Scop" + + " \001(\005H\000\210\001\001\022\032\n\022return_immediately\030\004 \001(\010B\021\n" + + "\017_history_length\"\317\001\n\004Task\022\017\n\002id\030\001 \001(\tB\003\340" + + "A\002\022\022\n\ncontext_id\030\002 \001(\t\022*\n\006status\030\003 \001(\0132\025" + + ".lf.a2a.v1.TaskStatusB\003\340A\002\022&\n\tartifacts\030" + + "\004 \003(\0132\023.lf.a2a.v1.Artifact\022#\n\007history\030\005 " + + "\003(\0132\022.lf.a2a.v1.Message\022)\n\010metadata\030\006 \001(" + + "\0132\027.google.protobuf.Struct\"\212\001\n\nTaskStatu" + + "s\022(\n\005state\030\001 \001(\0162\024.lf.a2a.v1.TaskStateB\003" + + "\340A\002\022#\n\007message\030\002 \001(\0132\022.lf.a2a.v1.Message" + + "\022-\n\ttimestamp\030\003 \001(\0132\032.google.protobuf.Ti" + + "mestamp\"\270\001\n\004Part\022\016\n\004text\030\001 \001(\tH\000\022\r\n\003raw\030" + + "\002 \001(\014H\000\022\r\n\003url\030\003 \001(\tH\000\022&\n\004data\030\004 \001(\0132\026.g" + + "oogle.protobuf.ValueH\000\022)\n\010metadata\030\005 \001(\013" + + "2\027.google.protobuf.Struct\022\020\n\010filename\030\006 " + + "\001(\t\022\022\n\nmedia_type\030\007 \001(\tB\t\n\007content\"\353\001\n\007M" + + "essage\022\027\n\nmessage_id\030\001 \001(\tB\003\340A\002\022\022\n\nconte" + + "xt_id\030\002 \001(\t\022\017\n\007task_id\030\003 \001(\t\022\"\n\004role\030\004 \001" + + "(\0162\017.lf.a2a.v1.RoleB\003\340A\002\022#\n\005parts\030\005 \003(\0132" + + "\017.lf.a2a.v1.PartB\003\340A\002\022)\n\010metadata\030\006 \001(\0132" + + "\027.google.protobuf.Struct\022\022\n\nextensions\030\007" + + " \003(\t\022\032\n\022reference_task_ids\030\010 \003(\t\"\253\001\n\010Art" + + "ifact\022\030\n\013artifact_id\030\001 \001(\tB\003\340A\002\022\014\n\004name\030" + + "\002 \001(\t\022\023\n\013description\030\003 \001(\t\022#\n\005parts\030\004 \003(" + + "\0132\017.lf.a2a.v1.PartB\003\340A\002\022)\n\010metadata\030\005 \001(" + + "\0132\027.google.protobuf.Struct\022\022\n\nextensions" + + "\030\006 \003(\t\"\235\001\n\025TaskStatusUpdateEvent\022\024\n\007task" + + "_id\030\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022" + + "*\n\006status\030\003 \001(\0132\025.lf.a2a.v1.TaskStatusB\003" + + "\340A\002\022)\n\010metadata\030\004 \001(\0132\027.google.protobuf." + + "Struct\"\303\001\n\027TaskArtifactUpdateEvent\022\024\n\007ta" + + "sk_id\030\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A" + + "\002\022*\n\010artifact\030\003 \001(\0132\023.lf.a2a.v1.Artifact" + + "B\003\340A\002\022\016\n\006append\030\004 \001(\010\022\022\n\nlast_chunk\030\005 \001(" + + "\010\022)\n\010metadata\030\006 \001(\0132\027.google.protobuf.St" + + "ruct\">\n\022AuthenticationInfo\022\023\n\006scheme\030\001 \001" + + "(\tB\003\340A\002\022\023\n\013credentials\030\002 \001(\t\"p\n\016AgentInt" + + "erface\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\035\n\020protocol_bin" + + "ding\030\002 \001(\tB\003\340A\002\022\016\n\006tenant\030\003 \001(\t\022\035\n\020proto" + + "col_version\030\004 \001(\tB\003\340A\002\"\306\005\n\tAgentCard\022\021\n\004" + + "name\030\001 \001(\tB\003\340A\002\022\030\n\013description\030\002 \001(\tB\003\340A" + + "\002\022<\n\024supported_interfaces\030\003 \003(\0132\031.lf.a2a" + + ".v1.AgentInterfaceB\003\340A\002\022*\n\010provider\030\004 \001(" + + "\0132\030.lf.a2a.v1.AgentProvider\022\024\n\007version\030\005" + + " \001(\tB\003\340A\002\022\036\n\021documentation_url\030\006 \001(\tH\000\210\001" + + "\001\0227\n\014capabilities\030\007 \001(\0132\034.lf.a2a.v1.Agen" + + "tCapabilitiesB\003\340A\002\022C\n\020security_schemes\030\010" + + " \003(\0132).lf.a2a.v1.AgentCard.SecuritySchem" + + "esEntry\022=\n\025security_requirements\030\t \003(\0132\036" + + ".lf.a2a.v1.SecurityRequirement\022 \n\023defaul" + + "t_input_modes\030\n \003(\tB\003\340A\002\022!\n\024default_outp" + + "ut_modes\030\013 \003(\tB\003\340A\002\022*\n\006skills\030\014 \003(\0132\025.lf" + + ".a2a.v1.AgentSkillB\003\340A\002\0221\n\nsignatures\030\r " + + "\003(\0132\035.lf.a2a.v1.AgentCardSignature\022\025\n\010ic" + + "on_url\030\016 \001(\tH\001\210\001\001\032Q\n\024SecuritySchemesEntr" + + "y\022\013\n\003key\030\001 \001(\t\022(\n\005value\030\002 \001(\0132\031.lf.a2a.v" + + "1.SecurityScheme:\0028\001B\024\n\022_documentation_u" + + "rlB\013\n\t_icon_url\"<\n\rAgentProvider\022\020\n\003url\030" + + "\001 \001(\tB\003\340A\002\022\031\n\014organization\030\002 \001(\tB\003\340A\002\"\332\001" + + "\n\021AgentCapabilities\022\026\n\tstreaming\030\001 \001(\010H\000" + + "\210\001\001\022\037\n\022push_notifications\030\002 \001(\010H\001\210\001\001\022-\n\n" + + "extensions\030\003 \003(\0132\031.lf.a2a.v1.AgentExtens" + + "ion\022 \n\023extended_agent_card\030\004 \001(\010H\002\210\001\001B\014\n" + + "\n_streamingB\025\n\023_push_notificationsB\026\n\024_e" + + "xtended_agent_card\"m\n\016AgentExtension\022\013\n\003" + + "uri\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022\020\n\010requir" + + "ed\030\003 \001(\010\022\'\n\006params\030\004 \001(\0132\027.google.protob" + + "uf.Struct\"\331\001\n\nAgentSkill\022\017\n\002id\030\001 \001(\tB\003\340A" + + "\002\022\021\n\004name\030\002 \001(\tB\003\340A\002\022\030\n\013description\030\003 \001(" + + "\tB\003\340A\002\022\021\n\004tags\030\004 \003(\tB\003\340A\002\022\020\n\010examples\030\005 " + + "\003(\t\022\023\n\013input_modes\030\006 \003(\t\022\024\n\014output_modes" + + "\030\007 \003(\t\022=\n\025security_requirements\030\010 \003(\0132\036." + + "lf.a2a.v1.SecurityRequirement\"m\n\022AgentCa" + + "rdSignature\022\026\n\tprotected\030\001 \001(\tB\003\340A\002\022\026\n\ts" + + "ignature\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\0132\027.go" + + "ogle.protobuf.Struct\"\241\001\n\032TaskPushNotific" + + "ationConfig\022\016\n\006tenant\030\001 \001(\t\022\n\n\002id\030\002 \001(\t\022" + + "\017\n\007task_id\030\003 \001(\t\022\020\n\003url\030\004 \001(\tB\003\340A\002\022\r\n\005to" + + "ken\030\005 \001(\t\0225\n\016authentication\030\006 \001(\0132\035.lf.a" + + "2a.v1.AuthenticationInfo\"\032\n\nStringList\022\014" + + "\n\004list\030\001 \003(\t\"\232\001\n\023SecurityRequirement\022<\n\007" + + "schemes\030\001 \003(\0132+.lf.a2a.v1.SecurityRequir" + + "ement.SchemesEntry\032E\n\014SchemesEntry\022\013\n\003ke" + + "y\030\001 \001(\t\022$\n\005value\030\002 \001(\0132\025.lf.a2a.v1.Strin" + + "gList:\0028\001\"\200\003\n\016SecurityScheme\022B\n\027api_key_" + + "security_scheme\030\001 \001(\0132\037.lf.a2a.v1.APIKey" + + "SecuritySchemeH\000\022F\n\031http_auth_security_s" + + "cheme\030\002 \001(\0132!.lf.a2a.v1.HTTPAuthSecurity" + + "SchemeH\000\022A\n\026oauth2_security_scheme\030\003 \001(\013" + + "2\037.lf.a2a.v1.OAuth2SecuritySchemeH\000\022Q\n\037o" + + "pen_id_connect_security_scheme\030\004 \001(\0132&.l" + + "f.a2a.v1.OpenIdConnectSecuritySchemeH\000\022B" + + "\n\024mtls_security_scheme\030\005 \001(\0132\".lf.a2a.v1" + + ".MutualTlsSecuritySchemeH\000B\010\n\006scheme\"U\n\024" + + "APIKeySecurityScheme\022\023\n\013description\030\001 \001(" + + "\t\022\025\n\010location\030\002 \001(\tB\003\340A\002\022\021\n\004name\030\003 \001(\tB\003" + + "\340A\002\"Y\n\026HTTPAuthSecurityScheme\022\023\n\013descrip" + + "tion\030\001 \001(\t\022\023\n\006scheme\030\002 \001(\tB\003\340A\002\022\025\n\rbeare" + + "r_format\030\003 \001(\t\"s\n\024OAuth2SecurityScheme\022\023" + + "\n\013description\030\001 \001(\t\022)\n\005flows\030\002 \001(\0132\025.lf." + + "a2a.v1.OAuthFlowsB\003\340A\002\022\033\n\023oauth2_metadat" + + "a_url\030\003 \001(\t\"T\n\033OpenIdConnectSecuritySche" + + "me\022\023\n\013description\030\001 \001(\t\022 \n\023open_id_conne" + + "ct_url\030\002 \001(\tB\003\340A\002\".\n\027MutualTlsSecuritySc" + + "heme\022\023\n\013description\030\001 \001(\t\"\301\002\n\nOAuthFlows" + + "\022C\n\022authorization_code\030\001 \001(\0132%.lf.a2a.v1" + + ".AuthorizationCodeOAuthFlowH\000\022C\n\022client_" + + "credentials\030\002 \001(\0132%.lf.a2a.v1.ClientCred" + + "entialsOAuthFlowH\000\0224\n\010implicit\030\003 \001(\0132\034.l" + + "f.a2a.v1.ImplicitOAuthFlowB\002\030\001H\000\0224\n\010pass" + + "word\030\004 \001(\0132\034.lf.a2a.v1.PasswordOAuthFlow" + + "B\002\030\001H\000\0225\n\013device_code\030\005 \001(\0132\036.lf.a2a.v1." + + "DeviceCodeOAuthFlowH\000B\006\n\004flow\"\367\001\n\032Author" + + "izationCodeOAuthFlow\022\036\n\021authorization_ur" + + "l\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013" + + "refresh_url\030\003 \001(\t\022F\n\006scopes\030\004 \003(\01321.lf.a" + + "2a.v1.AuthorizationCodeOAuthFlow.ScopesE" + + "ntryB\003\340A\002\022\025\n\rpkce_required\030\005 \001(\010\032-\n\013Scop" + "esEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"" + - "\244\001\n\021PasswordOAuthFlow\022\021\n\ttoken_url\030\001 \001(\t" + - "\022\023\n\013refresh_url\030\002 \001(\t\0228\n\006scopes\030\003 \003(\0132(." + - "lf.a2a.v1.PasswordOAuthFlow.ScopesEntry\032" + - "-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001" + - "(\t:\0028\001\"\331\001\n\023DeviceCodeOAuthFlow\022%\n\030device" + - "_authorization_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_u" + - "rl\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001(\t\022?\n\006sc" + - "opes\030\004 \003(\0132*.lf.a2a.v1.DeviceCodeOAuthFl" + - "ow.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003ke" + - "y\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\265\001\n\022SendMessa" + - "geRequest\022\016\n\006tenant\030\001 \001(\t\022(\n\007message\030\002 \001" + - "(\0132\022.lf.a2a.v1.MessageB\003\340A\002\022:\n\rconfigura" + - "tion\030\003 \001(\0132#.lf.a2a.v1.SendMessageConfig" + - "uration\022)\n\010metadata\030\004 \001(\0132\027.google.proto" + - "buf.Struct\"a\n\016GetTaskRequest\022\016\n\006tenant\030\001" + - " \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\022\033\n\016history_length\030" + - "\003 \001(\005H\000\210\001\001B\021\n\017_history_length\"\270\002\n\020ListTa" + - "sksRequest\022\016\n\006tenant\030\001 \001(\t\022\022\n\ncontext_id" + - "\030\002 \001(\t\022$\n\006status\030\003 \001(\0162\024.lf.a2a.v1.TaskS" + - "tate\022\026\n\tpage_size\030\004 \001(\005H\000\210\001\001\022\022\n\npage_tok" + - "en\030\005 \001(\t\022\033\n\016history_length\030\006 \001(\005H\001\210\001\001\022:\n" + - "\026status_timestamp_after\030\007 \001(\0132\032.google.p" + - "rotobuf.Timestamp\022\036\n\021include_artifacts\030\010" + - " \001(\010H\002\210\001\001B\014\n\n_page_sizeB\021\n\017_history_leng" + - "thB\024\n\022_include_artifacts\"\207\001\n\021ListTasksRe" + - "sponse\022#\n\005tasks\030\001 \003(\0132\017.lf.a2a.v1.TaskB\003" + - "\340A\002\022\034\n\017next_page_token\030\002 \001(\tB\003\340A\002\022\026\n\tpag" + - "e_size\030\003 \001(\005B\003\340A\002\022\027\n\ntotal_size\030\004 \001(\005B\003\340" + - "A\002\"_\n\021CancelTaskRequest\022\016\n\006tenant\030\001 \001(\t\022" + - "\017\n\002id\030\002 \001(\tB\003\340A\002\022)\n\010metadata\030\003 \001(\0132\027.goo" + - "gle.protobuf.Struct\"]\n$GetTaskPushNotifi" + - "cationConfigRequest\022\016\n\006tenant\030\001 \001(\t\022\024\n\007t" + - "ask_id\030\002 \001(\tB\003\340A\002\022\017\n\002id\030\003 \001(\tB\003\340A\002\"`\n\'De" + - "leteTaskPushNotificationConfigRequest\022\016\n" + - "\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A\002\022\017\n\002i" + - "d\030\003 \001(\tB\003\340A\002\"9\n\026SubscribeToTaskRequest\022\016" + - "\n\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\"u\n&ListT" + - "askPushNotificationConfigsRequest\022\016\n\006ten" + - "ant\030\004 \001(\t\022\024\n\007task_id\030\001 \001(\tB\003\340A\002\022\021\n\tpage_" + - "size\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t\"-\n\033GetExt" + - "endedAgentCardRequest\022\016\n\006tenant\030\001 \001(\t\"h\n" + - "\023SendMessageResponse\022\037\n\004task\030\001 \001(\0132\017.lf." + - "a2a.v1.TaskH\000\022%\n\007message\030\002 \001(\0132\022.lf.a2a." + - "v1.MessageH\000B\t\n\007payload\"\335\001\n\016StreamRespon" + - "se\022\037\n\004task\030\001 \001(\0132\017.lf.a2a.v1.TaskH\000\022%\n\007m" + - "essage\030\002 \001(\0132\022.lf.a2a.v1.MessageH\000\0229\n\rst" + - "atus_update\030\003 \001(\0132 .lf.a2a.v1.TaskStatus" + - "UpdateEventH\000\022=\n\017artifact_update\030\004 \001(\0132\"" + - ".lf.a2a.v1.TaskArtifactUpdateEventH\000B\t\n\007" + - "payload\"z\n\'ListTaskPushNotificationConfi" + - "gsResponse\0226\n\007configs\030\001 \003(\0132%.lf.a2a.v1." + - "TaskPushNotificationConfig\022\027\n\017next_page_" + - "token\030\002 \001(\t*\371\001\n\tTaskState\022\032\n\026TASK_STATE_" + - "UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMITTED\020\001\022" + - "\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_STATE_CO" + - "MPLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022\027\n\023TASK" + - "_STATE_CANCELED\020\005\022\035\n\031TASK_STATE_INPUT_RE" + - "QUIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020\007\022\034\n\030TAS" + - "K_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE_" + - "UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AGE" + - "NT\020\0022\227\017\n\nA2AService\022\203\001\n\013SendMessage\022\035.lf" + - ".a2a.v1.SendMessageRequest\032\036.lf.a2a.v1.S" + - "endMessageResponse\"5\202\323\344\223\002/\"\r/message:sen" + - "d:\001*Z\033\"\026/{tenant}/message:send:\001*\022\215\001\n\024Se" + - "ndStreamingMessage\022\035.lf.a2a.v1.SendMessa" + - "geRequest\032\031.lf.a2a.v1.StreamResponse\"9\202\323" + - "\344\223\0023\"\017/message:stream:\001*Z\035\"\030/{tenant}/me" + - "ssage:stream:\001*0\001\022k\n\007GetTask\022\031.lf.a2a.v1" + - ".GetTaskRequest\032\017.lf.a2a.v1.Task\"4\332A\002id\202" + - "\323\344\223\002)\022\r/tasks/{id=*}Z\030\022\026/{tenant}/tasks/" + - "{id=*}\022i\n\tListTasks\022\033.lf.a2a.v1.ListTask" + - "sRequest\032\034.lf.a2a.v1.ListTasksResponse\"!" + - "\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tenant}/tasks\022\200\001\n\nCa" + - "ncelTask\022\034.lf.a2a.v1.CancelTaskRequest\032\017" + - ".lf.a2a.v1.Task\"C\202\323\344\223\002=\"\024/tasks/{id=*}:c" + - "ancel:\001*Z\"\"\035/{tenant}/tasks/{id=*}:cance" + - "l:\001*\022\226\001\n\017SubscribeToTask\022!.lf.a2a.v1.Sub" + - "scribeToTaskRequest\032\031.lf.a2a.v1.StreamRe" + - "sponse\"C\202\323\344\223\002=\022\027/tasks/{id=*}:subscribeZ" + - "\"\022 /{tenant}/tasks/{id=*}:subscribe0\001\022\363\001" + - "\n CreateTaskPushNotificationConfig\022%.lf." + - "a2a.v1.TaskPushNotificationConfig\032%.lf.a" + - "2a.v1.TaskPushNotificationConfig\"\200\001\332A\016ta" + - "sk_id,config\202\323\344\223\002i\"*/tasks/{task_id=*}/p" + - "ushNotificationConfigs:\001*Z8\"3/{tenant}/t" + - "asks/{task_id=*}/pushNotificationConfigs" + - ":\001*\022\376\001\n\035GetTaskPushNotificationConfig\022/." + - "lf.a2a.v1.GetTaskPushNotificationConfigR" + - "equest\032%.lf.a2a.v1.TaskPushNotificationC" + - "onfig\"\204\001\332A\ntask_id,id\202\323\344\223\002q\0221/tasks/{tas" + - "k_id=*}/pushNotificationConfigs/{id=*}Z<" + - "\022:/{tenant}/tasks/{task_id=*}/pushNotifi" + - "cationConfigs/{id=*}\022\375\001\n\037ListTaskPushNot" + - "ificationConfigs\0221.lf.a2a.v1.ListTaskPus" + - "hNotificationConfigsRequest\0322.lf.a2a.v1." + - "ListTaskPushNotificationConfigsResponse\"" + - "s\332A\007task_id\202\323\344\223\002c\022*/tasks/{task_id=*}/pu" + - "shNotificationConfigsZ5\0223/{tenant}/tasks" + - "/{task_id=*}/pushNotificationConfigs\022\217\001\n" + - "\024GetExtendedAgentCard\022&.lf.a2a.v1.GetExt" + - "endedAgentCardRequest\032\024.lf.a2a.v1.AgentC" + - "ard\"9\202\323\344\223\0023\022\022/extendedAgentCardZ\035\022\033/{ten" + - "ant}/extendedAgentCard\022\365\001\n DeleteTaskPus" + - "hNotificationConfig\0222.lf.a2a.v1.DeleteTa" + - "skPushNotificationConfigRequest\032\026.google" + - ".protobuf.Empty\"\204\001\332A\ntask_id,id\202\323\344\223\002q*1/" + + "\300\001\n\032ClientCredentialsOAuthFlow\022\026\n\ttoken_" + + "url\030\001 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022F\n\006s" + + "copes\030\003 \003(\01321.lf.a2a.v1.ClientCredential" + + "sOAuthFlow.ScopesEntryB\003\340A\002\032-\n\013ScopesEnt" + + "ry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\254\001\n\021I" + + "mplicitOAuthFlow\022\031\n\021authorization_url\030\001 " + + "\001(\t\022\023\n\013refresh_url\030\002 \001(\t\0228\n\006scopes\030\003 \003(\013" + + "2(.lf.a2a.v1.ImplicitOAuthFlow.ScopesEnt" + + "ry\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030" + + "\002 \001(\t:\0028\001\"\244\001\n\021PasswordOAuthFlow\022\021\n\ttoken" + + "_url\030\001 \001(\t\022\023\n\013refresh_url\030\002 \001(\t\0228\n\006scope" + + "s\030\003 \003(\0132(.lf.a2a.v1.PasswordOAuthFlow.Sc" + + "opesEntry\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n" + + "\005value\030\002 \001(\t:\0028\001\"\331\001\n\023DeviceCodeOAuthFlow" + + "\022%\n\030device_authorization_url\030\001 \001(\tB\003\340A\002\022" + + "\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003" + + " \001(\t\022?\n\006scopes\030\004 \003(\0132*.lf.a2a.v1.DeviceC" + + "odeOAuthFlow.ScopesEntryB\003\340A\002\032-\n\013ScopesE" + + "ntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\265\001\n" + + "\022SendMessageRequest\022\016\n\006tenant\030\001 \001(\t\022(\n\007m" + + "essage\030\002 \001(\0132\022.lf.a2a.v1.MessageB\003\340A\002\022:\n" + + "\rconfiguration\030\003 \001(\0132#.lf.a2a.v1.SendMes" + + "sageConfiguration\022)\n\010metadata\030\004 \001(\0132\027.go" + + "ogle.protobuf.Struct\"a\n\016GetTaskRequest\022\016" + + "\n\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\022\033\n\016histo" + + "ry_length\030\003 \001(\005H\000\210\001\001B\021\n\017_history_length\"" + + "\270\002\n\020ListTasksRequest\022\016\n\006tenant\030\001 \001(\t\022\022\n\n" + + "context_id\030\002 \001(\t\022$\n\006status\030\003 \001(\0162\024.lf.a2" + + "a.v1.TaskState\022\026\n\tpage_size\030\004 \001(\005H\000\210\001\001\022\022" + + "\n\npage_token\030\005 \001(\t\022\033\n\016history_length\030\006 \001" + + "(\005H\001\210\001\001\022:\n\026status_timestamp_after\030\007 \001(\0132" + + "\032.google.protobuf.Timestamp\022\036\n\021include_a" + + "rtifacts\030\010 \001(\010H\002\210\001\001B\014\n\n_page_sizeB\021\n\017_hi" + + "story_lengthB\024\n\022_include_artifacts\"\207\001\n\021L" + + "istTasksResponse\022#\n\005tasks\030\001 \003(\0132\017.lf.a2a" + + ".v1.TaskB\003\340A\002\022\034\n\017next_page_token\030\002 \001(\tB\003" + + "\340A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022\027\n\ntotal_siz" + + "e\030\004 \001(\005B\003\340A\002\"_\n\021CancelTaskRequest\022\016\n\006ten" + + "ant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A\002\022)\n\010metadata\030\003" + + " \001(\0132\027.google.protobuf.Struct\"]\n$GetTask" + + "PushNotificationConfigRequest\022\016\n\006tenant\030" + + "\001 \001(\t\022\024\n\007task_id\030\002 \001(\tB\003\340A\002\022\017\n\002id\030\003 \001(\tB" + + "\003\340A\002\"`\n\'DeleteTaskPushNotificationConfig" + + "Request\022\016\n\006tenant\030\001 \001(\t\022\024\n\007task_id\030\002 \001(\t" + + "B\003\340A\002\022\017\n\002id\030\003 \001(\tB\003\340A\002\"9\n\026SubscribeToTas" + + "kRequest\022\016\n\006tenant\030\001 \001(\t\022\017\n\002id\030\002 \001(\tB\003\340A" + + "\002\"u\n&ListTaskPushNotificationConfigsRequ" + + "est\022\016\n\006tenant\030\004 \001(\t\022\024\n\007task_id\030\001 \001(\tB\003\340A" + + "\002\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t" + + "\"-\n\033GetExtendedAgentCardRequest\022\016\n\006tenan" + + "t\030\001 \001(\t\"h\n\023SendMessageResponse\022\037\n\004task\030\001" + + " \001(\0132\017.lf.a2a.v1.TaskH\000\022%\n\007message\030\002 \001(\013" + + "2\022.lf.a2a.v1.MessageH\000B\t\n\007payload\"\335\001\n\016St" + + "reamResponse\022\037\n\004task\030\001 \001(\0132\017.lf.a2a.v1.T" + + "askH\000\022%\n\007message\030\002 \001(\0132\022.lf.a2a.v1.Messa" + + "geH\000\0229\n\rstatus_update\030\003 \001(\0132 .lf.a2a.v1." + + "TaskStatusUpdateEventH\000\022=\n\017artifact_upda" + + "te\030\004 \001(\0132\".lf.a2a.v1.TaskArtifactUpdateE" + + "ventH\000B\t\n\007payload\"z\n\'ListTaskPushNotific" + + "ationConfigsResponse\0226\n\007configs\030\001 \003(\0132%." + + "lf.a2a.v1.TaskPushNotificationConfig\022\027\n\017" + + "next_page_token\030\002 \001(\t*\371\001\n\tTaskState\022\032\n\026T" + + "ASK_STATE_UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SU" + + "BMITTED\020\001\022\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TAS" + + "K_STATE_COMPLETED\020\003\022\025\n\021TASK_STATE_FAILED" + + "\020\004\022\027\n\023TASK_STATE_CANCELED\020\005\022\035\n\031TASK_STAT" + + "E_INPUT_REQUIRED\020\006\022\027\n\023TASK_STATE_REJECTE" + + "D\020\007\022\034\n\030TASK_STATE_AUTH_REQUIRED\020\010*;\n\004Rol" + + "e\022\024\n\020ROLE_UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016" + + "\n\nROLE_AGENT\020\0022\227\017\n\nA2AService\022\203\001\n\013SendMe" + + "ssage\022\035.lf.a2a.v1.SendMessageRequest\032\036.l" + + "f.a2a.v1.SendMessageResponse\"5\202\323\344\223\002/\"\r/m" + + "essage:send:\001*Z\033\"\026/{tenant}/message:send" + + ":\001*\022\215\001\n\024SendStreamingMessage\022\035.lf.a2a.v1" + + ".SendMessageRequest\032\031.lf.a2a.v1.StreamRe" + + "sponse\"9\202\323\344\223\0023\"\017/message:stream:\001*Z\035\"\030/{" + + "tenant}/message:stream:\001*0\001\022k\n\007GetTask\022\031" + + ".lf.a2a.v1.GetTaskRequest\032\017.lf.a2a.v1.Ta" + + "sk\"4\332A\002id\202\323\344\223\002)\022\r/tasks/{id=*}Z\030\022\026/{tena" + + "nt}/tasks/{id=*}\022i\n\tListTasks\022\033.lf.a2a.v" + + "1.ListTasksRequest\032\034.lf.a2a.v1.ListTasks" + + "Response\"!\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tenant}/ta" + + "sks\022\200\001\n\nCancelTask\022\034.lf.a2a.v1.CancelTas" + + "kRequest\032\017.lf.a2a.v1.Task\"C\202\323\344\223\002=\"\024/task" + + "s/{id=*}:cancel:\001*Z\"\"\035/{tenant}/tasks/{i" + + "d=*}:cancel:\001*\022\226\001\n\017SubscribeToTask\022!.lf." + + "a2a.v1.SubscribeToTaskRequest\032\031.lf.a2a.v" + + "1.StreamResponse\"C\202\323\344\223\002=\022\027/tasks/{id=*}:" + + "subscribeZ\"\022 /{tenant}/tasks/{id=*}:subs" + + "cribe0\001\022\363\001\n CreateTaskPushNotificationCo" + + "nfig\022%.lf.a2a.v1.TaskPushNotificationCon" + + "fig\032%.lf.a2a.v1.TaskPushNotificationConf" + + "ig\"\200\001\332A\016task_id,config\202\323\344\223\002i\"*/tasks/{ta" + + "sk_id=*}/pushNotificationConfigs:\001*Z8\"3/" + + "{tenant}/tasks/{task_id=*}/pushNotificat" + + "ionConfigs:\001*\022\376\001\n\035GetTaskPushNotificatio" + + "nConfig\022/.lf.a2a.v1.GetTaskPushNotificat" + + "ionConfigRequest\032%.lf.a2a.v1.TaskPushNot" + + "ificationConfig\"\204\001\332A\ntask_id,id\202\323\344\223\002q\0221/" + "tasks/{task_id=*}/pushNotificationConfig" + - "s/{id=*}Z<*:/{tenant}/tasks/{task_id=*}/" + - "pushNotificationConfigs/{id=*}B=\n\013io.a2a" + - ".grpcB\003A2AP\001Z\033google.golang.org/lf/a2a/v" + - "1\252\002\tLf.A2a.V1b\006proto3" + "s/{id=*}Z<\022:/{tenant}/tasks/{task_id=*}/" + + "pushNotificationConfigs/{id=*}\022\375\001\n\037ListT" + + "askPushNotificationConfigs\0221.lf.a2a.v1.L" + + "istTaskPushNotificationConfigsRequest\0322." + + "lf.a2a.v1.ListTaskPushNotificationConfig" + + "sResponse\"s\332A\007task_id\202\323\344\223\002c\022*/tasks/{tas" + + "k_id=*}/pushNotificationConfigsZ5\0223/{ten" + + "ant}/tasks/{task_id=*}/pushNotificationC" + + "onfigs\022\217\001\n\024GetExtendedAgentCard\022&.lf.a2a" + + ".v1.GetExtendedAgentCardRequest\032\024.lf.a2a" + + ".v1.AgentCard\"9\202\323\344\223\0023\022\022/extendedAgentCar" + + "dZ\035\022\033/{tenant}/extendedAgentCard\022\365\001\n Del" + + "eteTaskPushNotificationConfig\0222.lf.a2a.v" + + "1.DeleteTaskPushNotificationConfigReques" + + "t\032\026.google.protobuf.Empty\"\204\001\332A\ntask_id,i" + + "d\202\323\344\223\002q*1/tasks/{task_id=*}/pushNotifica" + + "tionConfigs/{id=*}Z<*:/{tenant}/tasks/{t" + + "ask_id=*}/pushNotificationConfigs/{id=*}" + + "B=\n\013io.a2a.grpcB\003A2AP\001Z\033google.golang.or" + + "g/lf/a2a/v1\252\002\tLf.A2a.V1b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -553,7 +553,7 @@ public static void registerAllExtensions( internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor, - new java.lang.String[] { "AcceptedOutputModes", "TaskPushNotificationConfig", "HistoryLength", "Blocking", }); + new java.lang.String[] { "AcceptedOutputModes", "TaskPushNotificationConfig", "HistoryLength", "ReturnImmediately", }); internal_static_lf_a2a_v1_Task_descriptor = getDescriptor().getMessageType(1); internal_static_lf_a2a_v1_Task_fieldAccessorTable = new diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java index e512a7f46..15c96acec 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java @@ -189,7 +189,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=567 + * See a2a.proto;l=569 * @return Whether the implicit field is set. */ @java.lang.Override @@ -203,7 +203,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=567 + * See a2a.proto;l=569 * @return The implicit. */ @java.lang.Override @@ -236,7 +236,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=569 + * See a2a.proto;l=571 * @return Whether the password field is set. */ @java.lang.Override @@ -250,7 +250,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=569 + * See a2a.proto;l=571 * @return The password. */ @java.lang.Override @@ -1159,7 +1159,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=567 + * See a2a.proto;l=569 * @return Whether the implicit field is set. */ @java.lang.Override @@ -1173,7 +1173,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=567 + * See a2a.proto;l=569 * @return The implicit. */ @java.lang.Override @@ -1341,7 +1341,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=569 + * See a2a.proto;l=571 * @return Whether the password field is set. */ @java.lang.Override @@ -1355,7 +1355,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=569 + * See a2a.proto;l=571 * @return The password. */ @java.lang.Override diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java index d4ee7267c..fbb2e96d9 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java @@ -71,7 +71,7 @@ public interface OAuthFlowsOrBuilder extends * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=567 + * See a2a.proto;l=569 * @return Whether the implicit field is set. */ @java.lang.Deprecated boolean hasImplicit(); @@ -82,7 +82,7 @@ public interface OAuthFlowsOrBuilder extends * * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=567 + * See a2a.proto;l=569 * @return The implicit. */ @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlow getImplicit(); @@ -102,7 +102,7 @@ public interface OAuthFlowsOrBuilder extends * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=569 + * See a2a.proto;l=571 * @return Whether the password field is set. */ @java.lang.Deprecated boolean hasPassword(); @@ -113,7 +113,7 @@ public interface OAuthFlowsOrBuilder extends * * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; * @deprecated lf.a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=569 + * See a2a.proto;l=571 * @return The password. */ @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlow getPassword(); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java index c622316de..bedda4ab3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java @@ -181,21 +181,23 @@ public int getHistoryLength() { return historyLength_; } - public static final int BLOCKING_FIELD_NUMBER = 4; - private boolean blocking_ = false; + public static final int RETURN_IMMEDIATELY_FIELD_NUMBER = 4; + private boolean returnImmediately_ = false; /** *

        -   * If `true`, the operation MUST wait until the task reaches a terminal state
        -   * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        -   * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
        +   * If `true`, the operation returns immediately after creating the task,
        +   * even if processing is still in progress.
        +   * If `false` (default), the operation MUST wait until the task reaches a
        +   * terminal (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or interrupted
        +   * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) state before returning.
            * 
        * - * bool blocking = 4; - * @return The blocking. + * bool return_immediately = 4; + * @return The returnImmediately. */ @java.lang.Override - public boolean getBlocking() { - return blocking_; + public boolean getReturnImmediately() { + return returnImmediately_; } private byte memoizedIsInitialized = -1; @@ -221,8 +223,8 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (((bitField0_ & 0x00000002) != 0)) { output.writeInt32(3, historyLength_); } - if (blocking_ != false) { - output.writeBool(4, blocking_); + if (returnImmediately_ != false) { + output.writeBool(4, returnImmediately_); } getUnknownFields().writeTo(output); } @@ -249,9 +251,9 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeInt32Size(3, historyLength_); } - if (blocking_ != false) { + if (returnImmediately_ != false) { size += com.google.protobuf.CodedOutputStream - .computeBoolSize(4, blocking_); + .computeBoolSize(4, returnImmediately_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -280,8 +282,8 @@ public boolean equals(final java.lang.Object obj) { if (getHistoryLength() != other.getHistoryLength()) return false; } - if (getBlocking() - != other.getBlocking()) return false; + if (getReturnImmediately() + != other.getReturnImmediately()) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -305,9 +307,9 @@ public int hashCode() { hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER; hash = (53 * hash) + getHistoryLength(); } - hash = (37 * hash) + BLOCKING_FIELD_NUMBER; + hash = (37 * hash) + RETURN_IMMEDIATELY_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getBlocking()); + getReturnImmediately()); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -457,7 +459,7 @@ public Builder clear() { taskPushNotificationConfigBuilder_ = null; } historyLength_ = 0; - blocking_ = false; + returnImmediately_ = false; return this; } @@ -507,7 +509,7 @@ private void buildPartial0(io.a2a.grpc.SendMessageConfiguration result) { to_bitField0_ |= 0x00000002; } if (((from_bitField0_ & 0x00000008) != 0)) { - result.blocking_ = blocking_; + result.returnImmediately_ = returnImmediately_; } result.bitField0_ |= to_bitField0_; } @@ -540,8 +542,8 @@ public Builder mergeFrom(io.a2a.grpc.SendMessageConfiguration other) { if (other.hasHistoryLength()) { setHistoryLength(other.getHistoryLength()); } - if (other.getBlocking() != false) { - setBlocking(other.getBlocking()); + if (other.getReturnImmediately() != false) { + setReturnImmediately(other.getReturnImmediately()); } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); @@ -588,7 +590,7 @@ public Builder mergeFrom( break; } // case 24 case 32: { - blocking_ = input.readBool(); + returnImmediately_ = input.readBool(); bitField0_ |= 0x00000008; break; } // case 32 @@ -999,52 +1001,58 @@ public Builder clearHistoryLength() { return this; } - private boolean blocking_ ; + private boolean returnImmediately_ ; /** *
        -     * If `true`, the operation MUST wait until the task reaches a terminal state
        -     * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        -     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
        +     * If `true`, the operation returns immediately after creating the task,
        +     * even if processing is still in progress.
        +     * If `false` (default), the operation MUST wait until the task reaches a
        +     * terminal (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or interrupted
        +     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) state before returning.
              * 
        * - * bool blocking = 4; - * @return The blocking. + * bool return_immediately = 4; + * @return The returnImmediately. */ @java.lang.Override - public boolean getBlocking() { - return blocking_; + public boolean getReturnImmediately() { + return returnImmediately_; } /** *
        -     * If `true`, the operation MUST wait until the task reaches a terminal state
        -     * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        -     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
        +     * If `true`, the operation returns immediately after creating the task,
        +     * even if processing is still in progress.
        +     * If `false` (default), the operation MUST wait until the task reaches a
        +     * terminal (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or interrupted
        +     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) state before returning.
              * 
        * - * bool blocking = 4; - * @param value The blocking to set. + * bool return_immediately = 4; + * @param value The returnImmediately to set. * @return This builder for chaining. */ - public Builder setBlocking(boolean value) { + public Builder setReturnImmediately(boolean value) { - blocking_ = value; + returnImmediately_ = value; bitField0_ |= 0x00000008; onChanged(); return this; } /** *
        -     * If `true`, the operation MUST wait until the task reaches a terminal state
        -     * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        -     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
        +     * If `true`, the operation returns immediately after creating the task,
        +     * even if processing is still in progress.
        +     * If `false` (default), the operation MUST wait until the task reaches a
        +     * terminal (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or interrupted
        +     * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) state before returning.
              * 
        * - * bool blocking = 4; + * bool return_immediately = 4; * @return This builder for chaining. */ - public Builder clearBlocking() { + public Builder clearReturnImmediately() { bitField0_ = (bitField0_ & ~0x00000008); - blocking_ = false; + returnImmediately_ = false; onChanged(); return this; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java index 3607e9093..affb9b361 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java @@ -112,13 +112,15 @@ public interface SendMessageConfigurationOrBuilder extends /** *
        -   * If `true`, the operation MUST wait until the task reaches a terminal state
        -   * (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state
        -   * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`.
        +   * If `true`, the operation returns immediately after creating the task,
        +   * even if processing is still in progress.
        +   * If `false` (default), the operation MUST wait until the task reaches a
        +   * terminal (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or interrupted
        +   * (`INPUT_REQUIRED`, `AUTH_REQUIRED`) state before returning.
            * 
        * - * bool blocking = 4; - * @return The blocking. + * bool return_immediately = 4; + * @return The returnImmediately. */ - boolean getBlocking(); + boolean getReturnImmediately(); } diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto index 4119821ab..a24b2943e 100644 --- a/spec-grpc/src/main/proto/a2a.proto +++ b/spec-grpc/src/main/proto/a2a.proto @@ -9,7 +9,7 @@ import "google/protobuf/empty.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; -// From commit dec790a +// From commit 601c408 option csharp_namespace = "Lf.A2a.V1"; option go_package = "google.golang.org/lf/a2a/v1"; @@ -154,10 +154,12 @@ message SendMessageConfiguration { // value of zero is a request to not include any messages. The server MUST NOT // return more messages than the provided value, but MAY apply a lower limit. optional int32 history_length = 3; - // If `true`, the operation MUST wait until the task reaches a terminal state - // (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or an interrupted state - // (`INPUT_REQUIRED`, `AUTH_REQUIRED`) before returning. Default is `false`. - bool blocking = 4; + // If `true`, the operation returns immediately after creating the task, + // even if processing is still in progress. + // If `false` (default), the operation MUST wait until the task reaches a + // terminal (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or interrupted + // (`INPUT_REQUIRED`, `AUTH_REQUIRED`) state before returning. + bool return_immediately = 4; } // `Task` is the core unit of action for A2A. It has a current status diff --git a/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java b/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java index 67b2a0ffd..206123103 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java @@ -57,7 +57,7 @@ void testValueToObject_WithEmptyStruct_ReturnsEmptyMap() throws InvalidProtocolB " }\n" + " },\n" + " \"configuration\": {\n" + - " \"blocking\": true\n" + + " \"returnImmediately\": false\n" + " },\n" + " \"metadata\": {\n" + " }\n" + diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java index 4051cea82..a9ef05edc 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java @@ -278,7 +278,7 @@ public void convertSendMessageConfiguration() { .acceptedOutputModes(List.of("text")) .build(); SendMessageConfiguration result = ProtoUtils.ToProto.messageSendConfiguration(configuration); - assertFalse(result.getBlocking()); + assertFalse(result.getReturnImmediately()); assertEquals(1, result.getAcceptedOutputModesCount()); assertEquals("text", result.getAcceptedOutputModesBytes(0).toStringUtf8()); } diff --git a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java index 303cc6608..a15e5da64 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java +++ b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java @@ -9,7 +9,7 @@ * Configuration options for {@code message/send} and {@code message/stream} requests. *

        * This record defines how the agent should process a message request, including output format - * preferences, conversation history context, push notification settings, and blocking behavior. + * preferences, conversation history context, push notification settings, and return behavior. *

        * All fields are optional and have sensible defaults when not specified. * @@ -17,13 +17,13 @@ * @param historyLength number of previous messages to include in conversation context (must be non-negative) * @param taskPushNotificationConfig configuration for asynchronous push notifications when task state changes. * Task id should be empty when sending this configuration in a SendMessage request. - * @param blocking whether the request should block until task completion (defaults to false) + * @param returnImmediately whether the operation should return immediately after creating the task (defaults to false) * @see MessageSendParams for the parameters that use this configuration * @see TaskPushNotificationConfig for push notification options * @see A2A Protocol Specification */ public record MessageSendConfiguration(@Nullable List acceptedOutputModes, @Nullable Integer historyLength, - @Nullable TaskPushNotificationConfig taskPushNotificationConfig, Boolean blocking) { + @Nullable TaskPushNotificationConfig taskPushNotificationConfig, Boolean returnImmediately) { /** * Compact constructor for validation. @@ -32,7 +32,7 @@ public record MessageSendConfiguration(@Nullable List acceptedOutputMode * @param acceptedOutputModes list of accepted output modes * @param historyLength maximum number of history items * @param taskPushNotificationConfig push notification configuration - * @param blocking whether the request should block + * @param returnImmediately whether to return immediately * @throws IllegalArgumentException if historyLength is negative */ public MessageSendConfiguration { @@ -60,7 +60,7 @@ public static class Builder { @Nullable List acceptedOutputModes; @Nullable Integer historyLength; @Nullable TaskPushNotificationConfig taskPushNotificationConfig; - Boolean blocking = false; + Boolean returnImmediately = false; /** * Creates a new Builder with all fields unset. @@ -107,13 +107,13 @@ public Builder historyLength(@Nullable Integer historyLength) { } /** - * Sets whether the request should block until completion. + * Sets whether the operation should return immediately after creating the task. * - * @param blocking true to block until task completes, false for fire-and-forget + * @param returnImmediately true to return immediately, false to wait for task completion * @return this builder */ - public Builder blocking(@NonNull Boolean blocking) { - this.blocking = blocking; + public Builder returnImmediately(@NonNull Boolean returnImmediately) { + this.returnImmediately = returnImmediately; return this; } @@ -127,7 +127,7 @@ public MessageSendConfiguration build() { acceptedOutputModes, historyLength, taskPushNotificationConfig, - blocking); + returnImmediately); } } } 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 7e29ce825..2c7b2ecee 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 @@ -2348,7 +2348,7 @@ private Client createPollingClient() throws A2AClientException { AgentCard agentCard = createTestAgentCard(); ClientConfig clientConfig = new ClientConfig.Builder() .setStreaming(false) // Non-streaming - .setPolling(true) // Polling mode (translates to blocking=false on server) + .setPolling(true) // Polling mode (translates to returnImmediately=true on server) .build(); ClientBuilder clientBuilder = Client 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 29a9e95f6..3578c96bd 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 @@ -96,7 +96,7 @@ public class JSONRPCHandlerTest extends AbstractA2ARequestHandlerTest { private static MessageSendConfiguration defaultConfiguration() { return MessageSendConfiguration.builder() .acceptedOutputModes(List.of()) - .blocking(false) + .returnImmediately(true) .build(); } 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 f896f0af2..d9b024d6b 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 @@ -104,7 +104,7 @@ public void testSendMessage() throws InvalidProtocolBufferException { }, "configuration": { - "blocking": true + "returnImmediately": false } }"""; @@ -557,7 +557,7 @@ public void testExtensionSupportRequiredErrorOnSendMessage() { "metadata": {} }, "configuration": { - "blocking": true + "returnImmediately": false } }"""; @@ -706,7 +706,7 @@ public void testRequiredExtensionProvidedSuccess() { "metadata": {} }, "configuration": { - "blocking": true + "returnImmediately": false } }"""; @@ -757,7 +757,7 @@ public void testVersionNotSupportedErrorOnSendMessage() { "metadata": {} }, "configuration": { - "blocking": true + "returnImmediately": false } }"""; @@ -900,7 +900,7 @@ public void testCompatibleVersionSuccess() { "metadata": {} }, "configuration": { - "blocking": true + "returnImmediately": false } }"""; @@ -948,7 +948,7 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { "metadata": {} }, "configuration": { - "blocking": true + "returnImmediately": false } }"""; From 3399bd3c67ec03d37c3263b7264be29755bdb1f7 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 11 Mar 2026 19:33:54 +0100 Subject: [PATCH 075/192] chore: Upgrade kind to 0.31.0 (#725) # Description Signed-off-by: Emmanuel Hugonnet --- .github/workflows/cloud-deployment-example.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cloud-deployment-example.yml b/.github/workflows/cloud-deployment-example.yml index 5c4e1e01a..237b2f390 100644 --- a/.github/workflows/cloud-deployment-example.yml +++ b/.github/workflows/cloud-deployment-example.yml @@ -27,7 +27,7 @@ jobs: - name: Install Kind run: | - curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64 + curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.31.0/kind-linux-amd64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind kind version From fbb83116933eaa2855adfcb72aebef288398f7a4 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 12 Mar 2026 13:05:54 +0000 Subject: [PATCH 076/192] docs: restructure AI documentation into .agents and .claude directories (#726) - Move skills to .agents/skills for universal agent access - Create .claude/architecture with EventQueue deep-dive docs - Add CLAUDE.md symlink to AGENTS.md for auto-discovery - Link .claude/skills to .agents/skills for Claude compatibility - Protect .claude/settings.local.json in .gitignore --------- Co-authored-by: Claude Sonnet 4.5 --- .../skills}/update-a2a-proto/SKILL.md | 0 .claude/architecture/EVENTQUEUE.md | 151 +++++++++ .claude/architecture/eventqueue/FLOWS.md | 228 +++++++++++++ .claude/architecture/eventqueue/LIFECYCLE.md | 202 ++++++++++++ .claude/architecture/eventqueue/SCENARIOS.md | 308 ++++++++++++++++++ .claude/skills | 1 + .gitignore | 4 +- AGENTS.md | 14 +- CLAUDE.md | 1 + 9 files changed, 905 insertions(+), 4 deletions(-) rename {skills => .agents/skills}/update-a2a-proto/SKILL.md (100%) create mode 100644 .claude/architecture/EVENTQUEUE.md create mode 100644 .claude/architecture/eventqueue/FLOWS.md create mode 100644 .claude/architecture/eventqueue/LIFECYCLE.md create mode 100644 .claude/architecture/eventqueue/SCENARIOS.md create mode 120000 .claude/skills create mode 120000 CLAUDE.md diff --git a/skills/update-a2a-proto/SKILL.md b/.agents/skills/update-a2a-proto/SKILL.md similarity index 100% rename from skills/update-a2a-proto/SKILL.md rename to .agents/skills/update-a2a-proto/SKILL.md diff --git a/.claude/architecture/EVENTQUEUE.md b/.claude/architecture/EVENTQUEUE.md new file mode 100644 index 000000000..a72ece048 --- /dev/null +++ b/.claude/architecture/EVENTQUEUE.md @@ -0,0 +1,151 @@ +# EventQueue Architecture - A2A Java SDK + +> **Quick Reference** for event processing, queue management, and task lifecycle + +## Overview + +The EventQueue architecture guarantees: +1. **Events persist BEFORE clients see them** (no unpersisted events visible) +2. **Serial processing** eliminates concurrent update race conditions +3. **Task state drives queue lifecycle** (fire-and-forget support, late reconnections) + +## Architecture Diagram + +``` +AgentExecutor.execute() [YOUR CODE] + ↓ +AgentEmitter → MainQueue.enqueueEvent() + ↓ +MainEventBus.submit() [ALL events queue here FIRST] + ↓ +MainEventBusProcessor.take() [single background thread] + ↓ +1. TaskStore.save() FIRST ← Persist before visibility +2. PushNotificationSender.send() +3. MainQueue.distributeToChildren() ← Clients see LAST + ↓ +ChildQueue → EventConsumer → ResultAggregator → Client +``` + +**Key Insight**: All events flow through a single-threaded processor that persists events BEFORE distributing to clients. + +--- + +## Core Components + +### MainEventBus +**Location**: `server-common/.../events/MainEventBus.java` + +- `@ApplicationScoped` CDI bean - single instance shared by all MainQueues +- `LinkedBlockingDeque` - thread-safe centralized queue +- `submit(taskId, eventQueue, item)` - enqueue events (called by MainQueue) +- `take()` - blocking consumption (called by MainEventBusProcessor) + +**Guarantees**: Events persist BEFORE distribution, serial processing, push notifications AFTER persistence + +### MainEventBusProcessor +**Location**: `server-common/.../events/MainEventBusProcessor.java` + +Single background thread "MainEventBusProcessor" that processes events in order: +1. `TaskManager.process(event)` → persist to TaskStore +2. `PushNotificationSender.send()` → notifications +3. `mainQueue.distributeToChildren()` → clients receive + +**Exception Handling**: Converts `TaskStoreException` to `InternalError` events, continues processing + +### EventQueue System +**Location**: `server-common/.../events/EventQueue.java` + +**Queue Types**: +- **MainQueue**: No local queue - events submit directly to MainEventBus +- **ChildQueue**: Has local queue for client consumption + +**Characteristics**: Bounded (1000 events), thread-safe, graceful shutdown, hook support + +### QueueManager +**Location**: `server-common/.../events/QueueManager.java` + +- `createOrTap(taskId)` → Get existing MainQueue or create new +- `tap(taskId)` → Create ChildQueue for existing MainQueue +- **Default**: InMemoryQueueManager (thread-safe ConcurrentHashMap) +- **Replicated**: ReplicatedQueueManager (Kafka-based) + +### EventConsumer & ResultAggregator +**Locations**: `server-common/.../events/EventConsumer.java`, `server-common/.../tasks/ResultAggregator.java` + +**EventConsumer**: Polls queue, returns `Flow.Publisher`, closes queue on final event + +**ResultAggregator** bridges EventConsumer and DefaultRequestHandler: +- `consumeAndBreakOnInterrupt()` - Non-streaming (polls until terminal/AUTH_REQUIRED) +- `consumeAndEmit()` - Streaming (returns Flow.Publisher immediately) +- `consumeAll()` - Simple consumption + +--- + +## Key Concepts + +### Queue Structure +- MainQueue has NO local queue (events → MainEventBus directly) +- Only ChildQueues have local queues +- `MainQueue.dequeueEventItem()` throws `UnsupportedOperationException` +- `MainQueue.size()` returns `mainEventBus.size()` +- `ChildQueue.size()` returns local queue size + +### Terminal Events +Events that cause polling loop exit: +- `TaskStatusUpdateEvent` with `isFinal() == true` +- `Message` (legacy) +- `Task` with state: COMPLETED, CANCELED, FAILED, REJECTED, UNKNOWN + +### AUTH_REQUIRED Special Case +- Returns task to client immediately +- Agent continues in background +- Queue stays open, async cleanup +- Future events update TaskStore + +--- + +## Deep Dives + +For detailed documentation on specific aspects: + +- **[Queue Lifecycle & Two-Level Protection](eventqueue/LIFECYCLE.md)** + - THE BIG IDEA: fire-and-forget, late reconnections + - TaskStateProvider interface and state-driven cleanup + - Memory management and cleanup modes + +- **[Request Flows](eventqueue/FLOWS.md)** + - Non-streaming vs streaming flows + - DefaultRequestHandler orchestration + - Background cleanup patterns + +- **[Usage Scenarios & Pitfalls](eventqueue/SCENARIOS.md)** + - Fire-and-forget pattern (TCK) + - Late resubscription scenarios + - Tapping and multiple consumers + - Common mistakes to avoid + +--- + +## Key Files Reference + +| Component | Path | +|-----------|------| +| MainEventBus | `server-common/.../events/MainEventBus.java` | +| MainEventBusProcessor | `server-common/.../events/MainEventBusProcessor.java` | +| EventQueue | `server-common/.../events/EventQueue.java` | +| QueueManager | `server-common/.../events/QueueManager.java` | +| InMemoryQueueManager | `server-common/.../events/InMemoryQueueManager.java` | +| EventConsumer | `server-common/.../events/EventConsumer.java` | +| ResultAggregator | `server-common/.../tasks/ResultAggregator.java` | +| DefaultRequestHandler | `server-common/.../requesthandlers/DefaultRequestHandler.java` | +| TaskStateProvider | `server-common/.../tasks/TaskStateProvider.java` | +| AgentEmitter | `server-common/.../tasks/AgentEmitter.java` | + +--- + +## Related Documentation + +- **Main Architecture**: `AGENTS.md` - High-level system overview +- **Task Persistence**: See TaskStore exception handling in main docs +- **Replication**: `extras/queue-manager-replicated/README.md` diff --git a/.claude/architecture/eventqueue/FLOWS.md b/.claude/architecture/eventqueue/FLOWS.md new file mode 100644 index 000000000..d2906a1f5 --- /dev/null +++ b/.claude/architecture/eventqueue/FLOWS.md @@ -0,0 +1,228 @@ +# Request Flows - EventQueue Processing + +> Deep-dive on streaming vs non-streaming request handling + +## Non-Streaming Flow (`onMessageSend()`) + +**Location**: `DefaultRequestHandler.java` + +``` +1. initMessageSend() + → Create TaskManager & RequestContext + +2. queueManager.createOrTap(taskId) + → Get/create EventQueue (MainQueue or ChildQueue) + +3. registerAndExecuteAgentAsync() + → Start AgentExecutor in background thread + +4. resultAggregator.consumeAndBreakOnInterrupt(consumer) + → Poll queue until terminal event or AUTH_REQUIRED + → Blocking wait for events + +5. cleanup(queue, task, async) + → Close queue immediately OR in background + +6. Return Task/Message to client +``` + +### Terminal Events + +Events that cause polling loop exit: +- `TaskStatusUpdateEvent` with `isFinal() == true` +- `Message` (legacy) +- `Task` with state: COMPLETED, CANCELED, FAILED, REJECTED, UNKNOWN + +### AUTH_REQUIRED Special Case + +**Behavior**: +- Returns current task to client immediately +- Agent continues running in background +- Queue stays open, cleanup happens async +- Future events update TaskStore + +**Why**: Allows client to handle authentication prompt while agent waits for credentials. + +--- + +## Streaming Flow (`onMessageSendStream()`) + +**Location**: `DefaultRequestHandler.java` + +``` +1. initMessageSend() + → Same as non-streaming + +2. queueManager.createOrTap(taskId) + → Same + +3. registerAndExecuteAgentAsync() + → Same + +4. resultAggregator.consumeAndEmit(consumer) + → Returns Flow.Publisher immediately + → Non-blocking + +5. processor() wraps publisher: + - Validates task ID + - Adds task to QueueManager + - Stores push notification config + - Sends push notifications + +6. cleanup(queue, task, true) + → ALWAYS async for streaming + +7. Return Flow.Publisher +``` + +### Key Difference + +**Non-Streaming**: Blocks until terminal event, then returns Task/Message +**Streaming**: Returns Flow.Publisher immediately, client receives events as they arrive + +**Cleanup**: Streaming ALWAYS uses async cleanup (background thread) + +--- + +## EventConsumer Details + +**Location**: `server-common/.../events/EventConsumer.java` + +**Purpose**: Consumes events from EventQueue and exposes as reactive stream + +**Key Methods**: +- `consume()` → Returns `Flow.Publisher` +- Polls queue with 500ms timeout +- Closes queue on final event +- Thread-safe concurrent consumption + +**Usage**: +```java +EventConsumer consumer = new EventConsumer(eventQueue); +Flow.Publisher publisher = consumer.consume(); +// Subscribe to receive events as they arrive +``` + +--- + +## ResultAggregator Modes + +**Location**: `server-common/.../tasks/ResultAggregator.java` + +Bridges EventConsumer and DefaultRequestHandler with three consumption modes: + +### 1. consumeAndBreakOnInterrupt() + +**Used by**: `onMessageSend()` (non-streaming) + +**Behavior**: +- Polls queue until terminal event or AUTH_REQUIRED +- Returns `EventTypeAndInterrupt(event, interrupted)` +- Blocking operation +- Exits early on AUTH_REQUIRED (interrupted = true) + +**Use Case**: Non-streaming requests that need single final response + +### 2. consumeAndEmit() + +**Used by**: `onMessageSendStream()` (streaming) + +**Behavior**: +- Returns all events as `Flow.Publisher` +- Non-blocking, immediate return +- Client subscribes to stream +- Events delivered as they arrive + +**Use Case**: Streaming requests where client wants all events in real-time + +### 3. consumeAll() + +**Used by**: `onCancelTask()` + +**Behavior**: +- Consumes all events from queue +- Returns first `Message` or final `Task` found +- Simple consumption without streaming +- Blocks until queue exhausted + +**Use Case**: Task cancellation where final state matters + +--- + +## Flow Comparison Table + +| Aspect | Non-Streaming | Streaming | +|--------|---------------|-----------| +| **ResultAggregator Mode** | consumeAndBreakOnInterrupt | consumeAndEmit | +| **Return Type** | Task/Message | Flow.Publisher | +| **Blocking** | Yes (until terminal event) | No (immediate return) | +| **Cleanup** | Immediate or async | Always async | +| **AUTH_REQUIRED** | Early exit, return task | Continue streaming | +| **Use Case** | Simple request/response | Real-time event updates | + +--- + +## Cleanup Integration + +### Actual Implementation: Always Asynchronous + +**Reality**: Cleanup is ALWAYS asynchronous in both streaming and non-streaming flows. The cleanup happens in the `finally` block via `cleanupProducer()`, which runs in a background thread. + +```java +// Both flows (in finally block): +cleanupProducer(agentFuture, consumptionFuture, taskId, queue, isStreaming) + .whenComplete((res, err) -> { + if (err != null) { + LOGGER.error("Error during async cleanup for task {}", taskId, err); + } + }); +``` + +**Key Points**: +- Cleanup is initiated in `finally` block regardless of flow outcome +- `cleanupProducer()` waits for both agent and consumption futures to complete +- Queue closure happens in background, never blocking the request thread +- For streaming: EventConsumer manages queue lifecycle via `agentCompleted` flag +- For non-streaming: Queue is closed directly after agent completes + +### Streaming Cleanup + +```java +cleanup(queue, task, true); // ALWAYS async for streaming +``` + +**Logic**: Streaming always uses async cleanup because: +- Publisher already returned to client +- Events may still be processing +- Queue cleanup happens in background + +--- + +## Thread Model + +### Agent Execution Thread +- `CompletableFuture.runAsync(agentExecutor::execute, executor)` +- Agent runs in background thread pool +- Enqueues events to MainQueue + +### MainEventBusProcessor Thread +- Single background thread: "MainEventBusProcessor" +- Processes events from MainEventBus +- Persists to TaskStore, distributes to ChildQueues + +### Consumer Thread +- Non-streaming: Request handler thread (blocking) +- Streaming: Subscriber thread (reactive) +- Polls ChildQueue for events + +### Cleanup Thread +- Async cleanup: Background thread pool +- Immediate cleanup: Request handler thread + +--- + +## Related Documentation + +- **[Main Overview](../EVENTQUEUE.md)** - Architecture and components +- **[Lifecycle](LIFECYCLE.md)** - Queue lifecycle and cleanup +- **[Scenarios](SCENARIOS.md)** - Real-world usage patterns diff --git a/.claude/architecture/eventqueue/LIFECYCLE.md b/.claude/architecture/eventqueue/LIFECYCLE.md new file mode 100644 index 000000000..9cca21349 --- /dev/null +++ b/.claude/architecture/eventqueue/LIFECYCLE.md @@ -0,0 +1,202 @@ +# Queue Lifecycle - THE BIG IDEA + +> Deep-dive on task state-driven queue lifecycle management + +## Problem Solved + +- **Fire-and-forget tasks**: Agent finishes without emitting final state +- **Client reconnections**: Late reconnections after disconnect +- **Replicated events**: Late-arriving events for ongoing tasks +- **Queue leaks**: Proper cleanup when tasks finalize + +## Solution: Two-Level Protection + +**Core Principle**: MainQueues stay open in QueueManager map as long as Task is in non-final state, enabling fire-and-forget and late resubscriptions. + +--- + +## Level 1: Cleanup Callback + +**When**: MainQueue closes +**Location**: `InMemoryQueueManager.getCleanupCallback()` + +```java +Runnable cleanupCallback = () -> { + if (taskStateProvider != null && !taskStateProvider.isUnsatisfied()) { + boolean isFinalized = taskStateProvider.isTaskFinalized(taskId); + if (!isFinalized) { + LOGGER.info("Task {} is not finalized, keeping queue in map", taskId); + return; // Don't remove from map - task still active + } + } + queues.remove(taskId); // Only remove if finalized +}; +``` + +**Purpose**: Prevents removal from QueueManager map for non-final tasks (enables resubscription). + +--- + +## Level 2: Auto-Close Prevention + +**When**: Last ChildQueue closes +**Location**: `MainQueue.childClosing()` + +```java +void childClosing(ChildQueue child, boolean immediate) { + children.remove(child); + + if (!children.isEmpty()) { + return; // Other children still active + } + + // No children left - check if task finalized before auto-closing + if (taskStateProvider != null && taskId != null) { + boolean isFinalized = taskStateProvider.isTaskFinalized(taskId); + if (!isFinalized) { + LOGGER.info("MainQueue for task {} has no children, but task is not finalized - keeping queue open", taskId); + return; // Keep MainQueue OPEN for resubscriptions! + } + } + + this.doClose(immediate); // Close only if task finalized +} +``` + +**Purpose**: Prevents auto-close when all children disconnect (keeps queue alive for late arrivals). + +--- + +## TaskStateProvider Interface + +**Location**: `server-common/.../tasks/TaskStateProvider.java` + +```java +public interface TaskStateProvider { + boolean isTaskActive(String taskId); // Is task still being worked on? + boolean isTaskFinalized(String taskId); // Is task in final state? +} +``` + +### Implementations +- `InMemoryTaskStore` implements TaskStateProvider +- `JpaDatabaseTaskStore` implements TaskStateProvider +- Injected via CDI: `Instance` + +### State Checks +- `isTaskActive()`: Used by ReplicatedQueueManager to skip events for inactive tasks +- `isTaskFinalized()`: Used by both protection levels to determine cleanup eligibility + +--- + +## Queue Close Modes + +### Graceful Close (`queue.close()`) + +- Drains remaining events before closing +- Used by normal termination +- ChildQueues close individually + +### Immediate Close (`queue.close(true)`) + +- Clears all pending events immediately +- Used by error conditions +- Forces all children to close + +--- + +## Background Cleanup + +**Location**: `DefaultRequestHandler.cleanup()` + +### Non-Streaming Cleanup + +```java +if (event instanceof Message || isFinalEvent(event)) { + if (!interrupted) { + cleanup(queue, task, false); // Immediate: wait for agent, close queue + } else { + cleanup(queue, task, true); // Async: close in background + } +} +``` + +### Streaming Cleanup (always async) + +```java +cleanup(queue, task, true); // Background cleanup after streaming completes +``` + +### Cleanup Implementation + +```java +private CompletableFuture cleanupProducer( + @Nullable CompletableFuture agentFuture, + @Nullable CompletableFuture consumptionFuture, + String taskId, + EventQueue queue, + boolean isStreaming) { + + if (agentFuture == null) { + return CompletableFuture.completedFuture(null); + } + + // Wait for BOTH agent AND consumption to complete before cleanup + CompletableFuture bothComplete = agentFuture; + if (consumptionFuture != null) { + bothComplete = CompletableFuture.allOf(agentFuture, consumptionFuture); + } + + return bothComplete.whenComplete((v, t) -> { + if (isStreaming) { + // EventConsumer manages queue lifecycle via agentCompleted flag + LOGGER.debug("Streaming: queue lifecycle managed by EventConsumer"); + } else { + // Close ChildQueue directly (triggers Level 2 check) + queue.close(false, true); + } + }); +} +``` + +--- + +## Memory Management + +### Non-Final Tasks +- Queues retained in QueueManager map +- Small memory footprint (queue object + taskId) +- Enables fire-and-forget and resubscription patterns + +### Finalized Tasks +- Queues cleaned up immediately +- Removed from QueueManager map +- Grace period in JpaDatabaseTaskStore (48 hours) + +### Replicated Scenario +- Late-arriving events can still be processed +- MainQueue stays in map until finalization +- Each instance manages own queue lifecycle + +--- + +## Why Two Levels? + +**Level 1** (Cleanup Callback): +- Prevents removal from map for non-final tasks +- Enables resubscription after queue close + +**Level 2** (Auto-Close Prevention): +- Prevents auto-close when all children disconnect +- Keeps queue alive for late arrivals +- Supports fire-and-forget pattern + +**Together**: Guarantee that queues stay available for non-final tasks while cleaning up promptly when tasks complete. + +--- + +## Related Documentation + +- **[Main Overview](../EVENTQUEUE.md)** - Architecture and components +- **[Request Flows](FLOWS.md)** - How cleanup integrates with request handling +- **[Scenarios](SCENARIOS.md)** - Real-world usage patterns diff --git a/.claude/architecture/eventqueue/SCENARIOS.md b/.claude/architecture/eventqueue/SCENARIOS.md new file mode 100644 index 000000000..5ca673750 --- /dev/null +++ b/.claude/architecture/eventqueue/SCENARIOS.md @@ -0,0 +1,308 @@ +# Usage Scenarios & Common Pitfalls + +> Real-world patterns and mistakes to avoid + +## Scenario 1: Fire-and-Forget Pattern (TCK) + +**Pattern**: Agent emits WORKING status but never completes + +```java +// Agent execution +agentExecutor.execute(context, queue) { + Task workingTask = new Task.Builder() + .id(taskId) + .status(new TaskStatus(TaskState.WORKING)) // Non-final! + .build(); + queue.enqueueEvent(workingTask); + // Agent finishes WITHOUT emitting COMPLETED/FAILED +} + +// What happens: +// 1. ChildQueue closes (client got WORKING event) +// 2. MainQueue.childClosing() checks: isTaskFinalized(taskId) → false +// 3. MainQueue stays OPEN in QueueManager map +// 4. Late resubscription works: queueManager.tap(taskId) → success! +``` + +**Note**: Queue numbers grow during TCK run - this is EXPECTED and intentional for resubscription support. + +**Why This Works**: +- Level 2 protection prevents auto-close when task is non-final +- MainQueue stays in map even with no children +- Later reconnections can tap into same MainQueue + +--- + +## Scenario 2: Late Resubscription + +**Pattern**: Client disconnects then reconnects to ongoing task + +``` +Time 0: Client sends message, gets ChildQueue +Time 1: Agent emits WORKING event +Time 2: Client disconnects, ChildQueue closes +Time 3: Agent still processing (non-final state) +Time 4: All ChildQueues closed, MainQueue.childClosing() fires + → Checks isTaskFinalized() → false + → MainQueue stays open +Time 5: Client reconnects: queueManager.tap(taskId) + → MainQueue still in map! + → New ChildQueue created + → Success! +``` + +**Key Insight**: The gap between Time 4 and Time 5 can be seconds, minutes, or hours. As long as task is non-final, MainQueue remains available. + +**Use Cases**: +- Mobile app loses network connection +- Browser tab closed and reopened +- Load balancer routes to different instance +- Debugging: stop client, fix bug, restart + +--- + +## Scenario 3: Normal Completion + +**Pattern**: Task completes successfully + +```java +// Agent completes +Task completed = new Task.Builder() + .id(taskId) + .status(new TaskStatus(TaskState.COMPLETED)) // Final state! + .build(); +queue.enqueueEvent(completed); + +// Lifecycle: +// 1. TaskStore persists COMPLETED task +// 2. ChildQueue closes after consuming final event +// 3. Level 2: MainQueue.childClosing() +// → isTaskFinalized(taskId) = true +// → mainQueue.doClose() +// 4. Level 1: Cleanup callback fires +// → isTaskFinalized(taskId) = true +// → queues.remove(taskId) +``` + +**Timeline**: +- Event enqueued → MainEventBus → persisted → distributed +- ChildQueue receives COMPLETED event → closes +- MainQueue detects no children + finalized task → closes +- Cleanup callback removes from QueueManager map + +**Result**: Prompt cleanup when task actually finishes + +--- + +## Scenario 4: Tapping (Multiple Consumers) + +**Pattern**: Multiple clients consuming same task events + +```java +// Initial request creates MainQueue +EventQueue mainQueue = queueManager.createOrTap(taskId); + +// Second client taps into existing MainQueue +EventQueue childQueue = queueManager.tap(taskId); + +// Event distribution (ASYNCHRONOUS via MainEventBus) +// NOTE: Distribution is NOT immediate! +public void enqueueEvent(Event event) { + // Step 1: Submit to MainEventBus (async processing) + mainEventBus.submit(event); + + // Step 2: MainEventBusProcessor thread (separate background thread): + // - Persists event to TaskStore + // - Distributes to all ChildQueues via child.internalEnqueueItem(item) + // - Invokes replication hook if configured + + // Key Point: Events are NOT immediately in ChildQueues! + // There's a delay while MainEventBusProcessor persists and distributes. +} +``` + +**Use Cases**: +- **Resubscribing to ongoing tasks**: Late reconnection scenario +- **Canceling tasks while receiving events**: Client sends cancel, still receives updates +- **Multiple concurrent consumers**: Admin dashboard + user client both watching same task +- **Testing/debugging**: Monitor task execution while client operates normally + +**Key Points**: +- All ChildQueues receive ALL events +- Each ChildQueue has independent consumption +- MainQueue doesn't close until ALL children close AND task finalizes + +--- + +## Common Pitfalls + +### 1. Closing EventQueue Before AgentExecutor Finishes + +**Problem**: +```java +// WRONG +agentExecutor.execute(context, queue); +queue.close(); // Too early! Agent may still be enqueueing events +``` + +**Solution**: +```java +// RIGHT - in DefaultRequestHandler.cleanup() +Runnable cleanupTask = () -> { + agentFuture.join(); // Wait for agent to finish + queue.close(); // Then close queue +}; +``` + +**Why**: Agent runs asynchronously. Closing queue before agent finishes loses events. + +--- + +### 2. Not Accounting for Async Cleanup in Streaming + +**Problem**: +```java +// WRONG assumption +onMessageSendStream() returns → queue is closed +``` + +**Reality**: +```java +// RIGHT understanding +onMessageSendStream() returns → queue still open +cleanup() happens in background → queue closes later +``` + +**Why**: Streaming returns publisher immediately. Queue cleanup happens asynchronously after streaming completes. + +**Impact**: Tests may see queues still open after streaming response sent. This is expected. + +--- + +### 3. Assuming MainQueue Has Local Queue + +**Problem**: +```java +// WRONG +Event event = mainQueue.dequeueEventItem(); // Throws UnsupportedOperationException! +``` + +**Reality**: +- MainQueue has NO local queue +- Events submit directly to MainEventBus +- Only ChildQueues have local queues + +**Why**: Design choice to centralize persistence through MainEventBus. + +**Correct Usage**: +```java +// Enqueue to MainQueue (goes to MainEventBus) +mainQueue.enqueueEvent(event); + +// Dequeue from ChildQueue only +Event event = childQueue.dequeueEventItem(); +``` + +--- + +### 4. Not Handling AUTH_REQUIRED Special Case + +**Problem**: +```java +// WRONG assumption +AUTH_REQUIRED received → agent stopped → cleanup can be immediate +``` + +**Reality**: +```java +// RIGHT understanding +AUTH_REQUIRED received → agent STILL RUNNING → cleanup must be async +``` + +**Why**: Agent waits for authentication credentials. It hasn't finished executing. + +**Impact**: +- Non-streaming: Returns task to client immediately, cleanup happens async +- Agent continues running in background +- Future events (COMPLETED, FAILED) update TaskStore + +--- + +### 5. Expecting Immediate Queue Cleanup + +**Problem**: +```java +// WRONG expectation +task emits WORKING (non-final) → queue should be cleaned up +``` + +**Reality**: +```java +// RIGHT understanding +task emits WORKING (non-final) → queue intentionally KEPT OPEN +task emits COMPLETED (final) → queue cleaned up +``` + +**Why**: Two-level protection checks task finality before cleanup. + +**Impact**: +- Non-final tasks: Queues retained intentionally (fire-and-forget support) +- Finalized tasks: Queues cleaned up promptly +- This is NOT a leak, it's intentional design + +**When to Worry**: If finalized tasks don't clean up queues (check TaskStateProvider implementation) + +--- + +## Scenario Comparison Table + +| Scenario | Task State | Queue Behavior | Use Case | +|----------|-----------|----------------|----------| +| **Fire-and-Forget** | Non-final (WORKING) | Stays open indefinitely | TCK compliance, async agents | +| **Late Resubscription** | Non-final | Stays open for reconnection | Network issues, debugging | +| **Normal Completion** | Final (COMPLETED) | Closes promptly | Standard request/response | +| **Tapping** | Any | Multiple ChildQueues share MainQueue | Monitoring, multi-client | + +--- + +## Debugging Tips + +### Check Queue State +```java +// Is MainQueue in map? +boolean exists = queueManager.tap(taskId) != null; + +// What's the queue size? +int size = eventQueue.size(); // MainQueue = MainEventBus size, ChildQueue = local size +``` + +### Check Task State +```java +// Is task finalized? +boolean finalized = taskStateProvider.isTaskFinalized(taskId); + +// Is task active? +boolean active = taskStateProvider.isTaskActive(taskId); +``` + +### Trace Event Flow +```java +// Add EventEnqueueHook for logging +EventQueue.builder() + .hook(event -> LOGGER.info("Event enqueued: {}", event)) + .build(); +``` + +### Monitor MainEventBus +```java +// Check queue depth +int depth = mainEventBus.size(); // High depth = processing backlog +``` + +--- + +## Related Documentation + +- **[Main Overview](../EVENTQUEUE.md)** - Architecture and components +- **[Lifecycle](LIFECYCLE.md)** - Queue lifecycle and two-level protection +- **[Flows](FLOWS.md)** - Request handling patterns diff --git a/.claude/skills b/.claude/skills new file mode 120000 index 000000000..2b7a412b8 --- /dev/null +++ b/.claude/skills @@ -0,0 +1 @@ +../.agents/skills \ No newline at end of file diff --git a/.gitignore b/.gitignore index 441ef20e1..a4a0b371f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,6 @@ release.properties .flattened-pom.xml *.args -#Claude -CLAUDE.md # Eclipse .project @@ -51,7 +49,7 @@ nbproject/ .certs/ # Private Claude config -.claude/ +.claude/settings.local.json .serena/ .bob/ claudedocs diff --git a/AGENTS.md b/AGENTS.md index c5d2d7eed..3974c88b7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -67,12 +67,24 @@ mvn clean install ### Skills -- [update-a2a-proto](skills/update-a2a-proto/SKILL.md) — Update the gRPC proto file `a2a.proto` from upstream and regenerate Java sources +- [update-a2a-proto](.agents/skills/update-a2a-proto/SKILL.md) — Update the gRPC proto file `a2a.proto` from upstream and regenerate Java sources ### Commands - `mvn clean install` — Clean build of the project +## Architecture Deep Dives + +For detailed architectural documentation: + +- **EventQueue & Event Processing**: `.claude/architecture/EVENTQUEUE.md` + - Quick reference with architecture diagram and core components + - **[Queue Lifecycle](.claude/architecture/eventqueue/LIFECYCLE.md)**: Two-level protection, fire-and-forget, late reconnections + - **[Request Flows](.claude/architecture/eventqueue/FLOWS.md)**: Non-streaming vs streaming, cleanup patterns + - **[Usage Scenarios](.claude/architecture/eventqueue/SCENARIOS.md)**: Real-world patterns and common pitfalls + +> 💡 Deep-dive docs are loaded on-demand when working in related areas. + ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md). Fork the repo, create a branch per issue, submit PRs against `main`. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 000000000..47dc3e3d8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file From a667e902d748646d4998b93b1929da682559b28d Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Thu, 12 Mar 2026 14:14:13 +0100 Subject: [PATCH 077/192] fix: Reject SendMessage with mismatching contextId and taskId (#728) When a message references an existing task but provides a contextId that doesn't match the task's context, reject it with an InvalidParamsError. This fixes #723 Co-authored-by: Claude Opus 4.6 --- .../DefaultRequestHandler.java | 8 +++ .../DefaultRequestHandlerTest.java | 53 +++++++++++++++++++ 2 files changed, 61 insertions(+) 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 f73c84a72..96c17eced 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 @@ -1026,6 +1026,14 @@ private MessageSendSetup initMessageSend(MessageSendParams params, ServerCallCon Task task = taskManager.getTask(); if (task != null) { + // Validate contextId matches the existing task's contextId + String messageContextId = params.message().contextId(); + if (messageContextId != null && !messageContextId.equals(task.contextId())) { + throw new InvalidParamsError(String.format( + "Message has a mismatched context ID (Task %s has contextId %s but message has contextId %s)", + task.id(), task.contextId(), messageContextId)); + } + LOGGER.debug("Found task updating with message {}", params.message()); task = taskManager.updateWithMessage(params.message(), task); 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 f737eb1ee..1e3217380 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 @@ -4,6 +4,7 @@ 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; @@ -30,6 +31,7 @@ import io.a2a.spec.A2AError; import io.a2a.spec.Event; import io.a2a.spec.EventKind; +import io.a2a.spec.InvalidParamsError; import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; import io.a2a.spec.MessageSendParams; @@ -509,4 +511,55 @@ void testAuthRequired_Resubscription() throws Exception { ((TaskStatusUpdateEvent) completionEvent).status().state(), "Task should be completed"); } + + /** + * Test: Reject SendMessage with mismatching contextId and taskId. + * When a message references an existing task but provides a different contextId, + * the request must be rejected with an InvalidParamsError. + */ + @Test + void testRejectMismatchingContextId() throws Exception { + // Arrange: Create an initial task to get valid identifiers + CountDownLatch agentCompleted = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + emitter.complete(); + agentCompleted.countDown(); + }; + + Message initialMessage = Message.builder() + .messageId("msg-1") + .role(Message.Role.ROLE_USER) + .contextId("original-context") + .parts(new TextPart("initial message")) + .build(); + + MessageSendParams initialParams = MessageSendParams.builder() + .message(initialMessage) + .configuration(DEFAULT_CONFIG) + .build(); + + EventKind result = requestHandler.onMessageSend(initialParams, NULL_CONTEXT); + assertInstanceOf(Task.class, result); + Task task = (Task) result; + assertTrue(agentCompleted.await(5, TimeUnit.SECONDS)); + + // Act & Assert: Send a follow-up message with matching taskId but wrong contextId + Message mismatchedMessage = Message.builder() + .messageId("msg-2") + .role(Message.Role.ROLE_USER) + .taskId(task.id()) + .contextId("wrong-context-does-not-exist") + .parts(new TextPart("follow-up message")) + .build(); + + MessageSendParams mismatchedParams = MessageSendParams.builder() + .message(mismatchedMessage) + .configuration(DEFAULT_CONFIG) + .build(); + + InvalidParamsError error = assertThrows(InvalidParamsError.class, + () -> requestHandler.onMessageSend(mismatchedParams, NULL_CONTEXT)); + assertTrue(error.getMessage().contains(task.id())); + } } From 56c1960e25449afd737b2c2ab3e71da9025c2bbe Mon Sep 17 00:00:00 2001 From: Charlie Zhang <117046135+Zhang-Charlie@users.noreply.github.com> Date: Thu, 12 Mar 2026 13:15:11 +0000 Subject: [PATCH 078/192] fix(rest): map invalid history length to InvalidParamsError (#715) ## Description Fixes REST `getTask` error handling when `historyLength` is invalid. Previously, invalid `historyLength` values could throw `IllegalArgumentException` and be returned as an internal error (500). This change maps that case to `InvalidParamsError`, returning the correct client error semantics (422). ## Changes - Update `RestHandler#getTask(...)` to catch `IllegalArgumentException` and return `InvalidParamsError` - Add regression test: - `RestHandlerTest#testGetTaskNegativeHistoryLengthReturns422` ## Validation - Ran targeted REST handler tests and verified they pass Fixes #714 --------- Co-authored-by: Emmanuel Hugonnet --- .../io/a2a/transport/rest/handler/RestHandler.java | 7 ++++++- .../a2a/transport/rest/handler/RestHandlerTest.java | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) 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 ad4e29cc1..4b93cfe22 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 @@ -415,7 +415,12 @@ public HTTPRestResponse subscribeToTask(ServerCallContext context, String tenant */ public HTTPRestResponse getTask(ServerCallContext context, String tenant, String taskId, @Nullable Integer historyLength) { try { - TaskQueryParams params = new TaskQueryParams(taskId, historyLength, tenant); + TaskQueryParams params; + try { + params = new TaskQueryParams(taskId, historyLength, tenant); + } catch (IllegalArgumentException e) { + throw new InvalidParamsError(e.getMessage()); + } Task task = requestHandler.onGetTask(params, context); if (task != null) { return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); 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 d9b024d6b..64c6636e1 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 @@ -58,6 +58,17 @@ public void testGetTaskNotFound() { Assertions.assertTrue(response.getBody().contains("TaskNotFoundError")); } + @Test + public void testGetTaskNegativeHistoryLengthReturns422() { + RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + + RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", MINIMAL_TASK.id(), -1); + + Assertions.assertEquals(422, response.getStatusCode()); + Assertions.assertEquals("application/problem+json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); + } + @Test public void testListTasksStatusWireString() { RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); From 5f742aef6cd0f866c586fa224a72f24c73f87fa5 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 12 Mar 2026 16:12:09 +0000 Subject: [PATCH 079/192] =?UTF-8?q?fix:=20Return=20UnsupportedOperationErr?= =?UTF-8?q?or=20when=20extendedAgentCard=20capabili=E2=80=A6=20(#736)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ty is disabled GetExtendedAgentCard now checks if the capability is enabled before checking if the card is configured. When capability is false, returns 501/UNIMPLEMENTED with UnsupportedOperationError instead of 400/FAILED_PRECONDITION. Applied to all three transports: HTTP+JSON, JSON-RPC, and gRPC. Fixes #733 Co-authored-by: Claude Sonnet 4.5 --- .../java/io/a2a/transport/grpc/handler/GrpcHandler.java | 4 ++++ .../io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java | 6 +++++- .../a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java | 2 +- .../java/io/a2a/transport/rest/handler/RestHandler.java | 5 ++++- 4 files changed, 14 insertions(+), 3 deletions(-) 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 159d687c2..4d652377c 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 @@ -546,6 +546,10 @@ public void onComplete() { public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, StreamObserver responseObserver) { try { + if (!getAgentCard().capabilities().extendedAgentCard()) { + handleError(responseObserver, new UnsupportedOperationError()); + return; + } AgentCard extendedAgentCard = getExtendedAgentCard(); if (extendedAgentCard != null) { responseObserver.onNext(ToProto.agentCard(extendedAgentCard)); 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 e91be92d5..0e30ac414 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 @@ -47,6 +47,7 @@ import io.a2a.spec.EventKind; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidRequestError; +import io.a2a.spec.UnsupportedOperationError; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.PushNotificationNotSupportedError; import io.a2a.spec.StreamingEventKind; @@ -667,7 +668,10 @@ public DeleteTaskPushNotificationConfigResponse deletePushNotificationConfig( // TODO: Add authentication (https://github.com/a2aproject/a2a-java/issues/77) public GetExtendedAgentCardResponse onGetExtendedCardRequest( GetExtendedAgentCardRequest request, ServerCallContext context) { - if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { + if (!agentCard.capabilities().extendedAgentCard()) { + return new GetExtendedAgentCardResponse(request.getId(), new UnsupportedOperationError()); + } + if (extendedAgentCard == null || !extendedAgentCard.isResolvable()) { return new GetExtendedAgentCardResponse(request.getId(), new ExtendedAgentCardNotConfiguredError(null, "Extended Card not configured", null)); } 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 3578c96bd..ac19034e0 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 @@ -1541,7 +1541,7 @@ public void testOnGetExtendedAgentCard() throws Exception { GetExtendedAgentCardRequest request = new GetExtendedAgentCardRequest("1"); GetExtendedAgentCardResponse response = handler.onGetExtendedCardRequest(request, callContext); assertEquals(request.getId(), response.getId()); - assertInstanceOf(ExtendedAgentCardNotConfiguredError.class, response.getError()); + assertInstanceOf(UnsupportedOperationError.class, response.getError()); assertNull(response.getResult()); } 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 4b93cfe22..75de9cda4 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 @@ -794,7 +794,10 @@ private int mapErrorToHttpStatus(A2AError error) { */ public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String tenant) { try { - if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { + if (!agentCard.capabilities().extendedAgentCard()) { + throw new UnsupportedOperationError(); + } + if (extendedAgentCard == null || !extendedAgentCard.isResolvable()) { throw new ExtendedAgentCardNotConfiguredError(null, "Extended Card not configured", null); } return new HTTPRestResponse(200, APPLICATION_JSON, JsonUtil.toJson(extendedAgentCard.get())); From 5be57f0ead6f999da02d28e7e5f0981685e4df42 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 12 Mar 2026 19:11:25 +0100 Subject: [PATCH 080/192] =?UTF-8?q?fix!:=20Rename=20`ListTaskPushNotificat?= =?UTF-8?q?ionConfig`=20to=20plural=20`ListTaskPush=E2=80=A6=20(#724)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …NotificationConfigs` for consistency Fixes #704 🦕 Signed-off-by: Emmanuel Hugonnet --- .../java/io/a2a/client/AbstractClient.java | 12 +-- .../src/main/java/io/a2a/client/Client.java | 16 ++-- .../client/transport/grpc/GrpcTransport.java | 12 +-- .../transport/jsonrpc/JSONRPCTransport.java | 10 +- .../client/transport/rest/RestTransport.java | 8 +- .../transport/rest/RestTransportTest.java | 8 +- .../client/transport/spi/ClientTransport.java | 8 +- ...penTelemetryClientPropagatorTransport.java | 6 +- .../client/OpenTelemetryClientTransport.java | 8 +- .../OpenTelemetryClientTransportTest.java | 10 +- .../OpenTelemetryRequestHandlerDecorator.java | 8 +- ...nTelemetryRequestHandlerDecoratorTest.java | 20 ++-- ...paDatabasePushNotificationConfigStore.java | 8 +- ...otificationConfigStoreIntegrationTest.java | 94 +++++++++---------- .../JpaPushNotificationConfigStoreTest.java | 32 +++---- ...istTaskPushNotificationConfigsRequest.java | 14 +-- ...stTaskPushNotificationConfigsResponse.java | 14 +-- .../a2a/server/grpc/quarkus/package-info.java | 2 +- .../server/apps/quarkus/A2AServerRoutes.java | 10 +- .../a2a/server/apps/quarkus/package-info.java | 2 +- .../apps/quarkus/A2AServerRoutesTest.java | 10 +- .../DefaultRequestHandler.java | 16 ++-- .../requesthandlers/RequestHandler.java | 8 +- .../tasks/BasePushNotificationSender.java | 6 +- .../InMemoryPushNotificationConfigStore.java | 14 +-- .../tasks/PushNotificationConfigStore.java | 18 ++-- .../io/a2a/server/util/sse/SseFormatter.java | 2 +- ...MemoryPushNotificationConfigStoreTest.java | 84 ++++++++--------- ...kPushNotificationConfigsParamsMapper.java} | 16 ++-- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 4 +- .../java/io/a2a/grpc/utils/ProtoUtils.java | 20 ++-- .../java/io/a2a/grpc/utils/ToProtoTest.java | 10 +- ...istTaskPushNotificationConfigsParams.java} | 14 +-- ...istTaskPushNotificationConfigsResult.java} | 6 +- .../apps/common/AbstractA2AServerTest.java | 42 ++++----- .../grpc/context/GrpcContextKeys.java | 2 +- .../transport/grpc/handler/GrpcHandler.java | 10 +- .../transport/grpc/handler/package-info.java | 2 +- .../jsonrpc/handler/JSONRPCHandler.java | 12 +-- .../jsonrpc/handler/package-info.java | 2 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 18 ++-- .../transport/rest/handler/RestHandler.java | 10 +- 42 files changed, 314 insertions(+), 314 deletions(-) rename spec-grpc/src/main/java/io/a2a/grpc/mapper/{ListTaskPushNotificationConfigParamsMapper.java => ListTaskPushNotificationConfigsParamsMapper.java} (56%) rename spec/src/main/java/io/a2a/spec/{ListTaskPushNotificationConfigParams.java => ListTaskPushNotificationConfigsParams.java} (88%) rename spec/src/main/java/io/a2a/spec/{ListTaskPushNotificationConfigResult.java => ListTaskPushNotificationConfigsResult.java} (87%) 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 3ef1747d5..bb43fb67c 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java @@ -14,8 +14,8 @@ import io.a2a.spec.CancelTaskParams; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; @@ -299,8 +299,8 @@ public abstract TaskPushNotificationConfig getTaskPushNotificationConfiguration( * @return the result containing the list of task push notification configs and pagination information * @throws A2AClientException if getting the task push notification configs fails for any reason */ - public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations( - ListTaskPushNotificationConfigParams request) throws A2AClientException { + public ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations( + ListTaskPushNotificationConfigsParams request) throws A2AClientException { return listTaskPushNotificationConfigurations(request, null); } @@ -312,8 +312,8 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio * @return the result containing the list of task push notification configs and pagination information * @throws A2AClientException if getting the task push notification configs fails for any reason */ - public abstract ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations( - ListTaskPushNotificationConfigParams request, + public abstract ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations( + ListTaskPushNotificationConfigsParams request, @Nullable ClientCallContext context) throws A2AClientException; /** 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 5c0d3fce2..32d00d629 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -20,8 +20,8 @@ import io.a2a.spec.EventKind; import io.a2a.spec.GetExtendedAgentCardParams; import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; @@ -512,9 +512,9 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration( * Example: *

        {@code
              * // List all configurations for a context
        -     * ListTaskPushNotificationConfigParams params =
        -     *     new ListTaskPushNotificationConfigParams("session-123", null, 10, null);
        -     * ListTaskPushNotificationConfigResult result =
        +     * ListTaskPushNotificationConfigsParams params =
        +     *     new ListTaskPushNotificationConfigsParams("session-123", null, 10, null);
        +     * ListTaskPushNotificationConfigsResult result =
              *     client.listTaskPushNotificationConfigurations(params);
              * for (TaskPushNotificationConfig config : result.configurations()) {
              *     System.out.println("Task " + config.taskId() + " -> " +
        @@ -526,11 +526,11 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(
              * @param context custom call context for request interceptors (optional)
              * @return the list of push notification configurations
              * @throws A2AClientException if the configurations cannot be retrieved
        -     * @see ListTaskPushNotificationConfigParams
        +     * @see ListTaskPushNotificationConfigsParams
              */
             @Override
        -    public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(
        -            ListTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException {
        +    public ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations(
        +            ListTaskPushNotificationConfigsParams request, @Nullable ClientCallContext context) throws A2AClientException {
                 return clientTransport.listTaskPushNotificationConfigurations(request, context);
             }
         
        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 0fe63efe1..802b9c0e6 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
        @@ -38,8 +38,8 @@
         import io.a2a.spec.EventKind;
         import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.MessageSendParams;
         import io.a2a.spec.StreamingEventKind;
        @@ -271,8 +271,8 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu
             }
         
             @Override
        -    public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(
        -            ListTaskPushNotificationConfigParams request,
        +    public ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations(
        +            ListTaskPushNotificationConfigsParams request,
                     @Nullable ClientCallContext context) throws A2AClientException {
                 checkNotNullParam("request", request);
         
        @@ -288,9 +288,9 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio
                 try {
                     A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders);
                     io.a2a.grpc.ListTaskPushNotificationConfigsResponse grpcResponse = stubWithMetadata.listTaskPushNotificationConfigs(grpcRequest);
        -            return FromProto.listTaskPushNotificationConfigResult(grpcResponse);
        +            return FromProto.listTaskPushNotificationConfigsResult(grpcResponse);
                 } catch (StatusRuntimeException | StatusException e) {
        -            throw GrpcErrorMapper.mapGrpcError(e, "Failed to list task push notification config: ");
        +            throw GrpcErrorMapper.mapGrpcError(e, "Failed to list task push notification configs: ");
                 }
             }
         
        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 3530dffea..2bbb25d87 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
        @@ -54,8 +54,8 @@
         import io.a2a.spec.EventKind;
         import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.MessageSendParams;
         import io.a2a.spec.StreamingEventKind;
        @@ -220,12 +220,12 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu
             }
         
             @Override
        -    public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(
        -            ListTaskPushNotificationConfigParams request,
        +    public ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations(
        +            ListTaskPushNotificationConfigsParams request,
                     @Nullable ClientCallContext context) throws A2AClientException {
                 checkNotNullParam("request", request);
                 PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD,
        -                ProtoUtils.ToProto.listTaskPushNotificationConfigRequest(request), agentCard, context);
        +                ProtoUtils.ToProto.listTaskPushNotificationConfigsRequest(request), agentCard, context);
         
                 try {
                     String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD);
        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 1eb15291e..bdb26b830 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
        @@ -48,8 +48,8 @@
         import io.a2a.spec.EventKind;
         import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.MessageSendParams;
         import io.a2a.spec.StreamingEventKind;
        @@ -326,7 +326,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu
             }
         
             @Override
        -    public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException {
        +    public ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigsParams request, @Nullable ClientCallContext context) throws A2AClientException {
                 checkNotNullParam("request", request);
                 io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder builder
                         = io.a2a.grpc.ListTaskPushNotificationConfigsRequest.newBuilder();
        @@ -348,7 +348,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio
                     String httpResponseBody = response.body();
                     io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder responseBuilder = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder();
                     JsonFormat.parser().merge(httpResponseBody, responseBuilder);
        -            return ProtoUtils.FromProto.listTaskPushNotificationConfigResult(responseBuilder);
        +            return ProtoUtils.FromProto.listTaskPushNotificationConfigsResult(responseBuilder);
                 } catch (A2AClientException e) {
                     throw e;
                 } catch (IOException | InterruptedException e) {
        diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java
        index efa89006b..a7f041237 100644
        --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java
        +++ b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java
        @@ -46,8 +46,8 @@
         import io.a2a.spec.FileWithBytes;
         import io.a2a.spec.FileWithUri;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.Message;
         import io.a2a.spec.MessageSendConfiguration;
         import io.a2a.spec.MessageSendParams;
        @@ -357,8 +357,8 @@ public void testListTaskPushNotificationConfigurations() throws Exception {
                         );
         
                 RestTransport client = new RestTransport(CARD);
        -        ListTaskPushNotificationConfigResult result = client.listTaskPushNotificationConfigurations(
        -                new ListTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null);
        +        ListTaskPushNotificationConfigsResult result = client.listTaskPushNotificationConfigurations(
        +                new ListTaskPushNotificationConfigsParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null);
                 assertEquals(2, result.configs().size());
                 TaskPushNotificationConfig config0 = result.configs().get(0);
                 assertNotNull(config0);
        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 ee85c1dca..cd63dadfb 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
        @@ -11,8 +11,8 @@
         import io.a2a.spec.EventKind;
         import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.MessageSendParams;
         import io.a2a.spec.StreamingEventKind;
        @@ -111,8 +111,8 @@ TaskPushNotificationConfig getTaskPushNotificationConfiguration(
              * @return the result containing the list of task push notification configs and pagination information
              * @throws A2AClientException if getting the task push notification configs fails for any reason
              */
        -    ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(
        -            ListTaskPushNotificationConfigParams request,
        +    ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations(
        +            ListTaskPushNotificationConfigsParams request,
                     @Nullable ClientCallContext context) throws A2AClientException;
         
             /**
        diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java
        index fd2f80587..20cb377fd 100644
        --- a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java
        +++ b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java
        @@ -10,8 +10,8 @@
         import io.a2a.spec.EventKind;
         import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.MessageSendParams;
         import io.a2a.spec.StreamingEventKind;
        @@ -96,7 +96,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu
             }
         
             @Override
        -    public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request,
        +    public ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigsParams request,
                     @Nullable ClientCallContext context) throws A2AClientException {
                 return delegate.listTaskPushNotificationConfigurations(request, propagateContext(context));
             }
        diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java
        index 9051e0c2d..e9b248737 100644
        --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java
        +++ b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java
        @@ -24,8 +24,8 @@
         import io.a2a.spec.EventKind;
         import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.MessageSendParams;
         import io.a2a.spec.StreamingEventKind;
        @@ -306,7 +306,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu
             }
         
             @Override
        -    public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request,
        +    public ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigsParams request,
                     @Nullable ClientCallContext context) throws A2AClientException {
                 ClientCallContext clientContext = createContext(context);
                 SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT);
        @@ -319,7 +319,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio
                 }
                 Span span = spanBuilder.startSpan();
                 try (Scope scope = span.makeCurrent()) {
        -            ListTaskPushNotificationConfigResult result = delegate.listTaskPushNotificationConfigurations(request, clientContext);
        +            ListTaskPushNotificationConfigsResult result = delegate.listTaskPushNotificationConfigurations(request, clientContext);
                     if (result != null && extractResponse()) {
                         String responseValue = result.configs().stream()
                                 .map(TaskPushNotificationConfig::toString)
        diff --git a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java b/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java
        index 37d04eeb6..2ef582ed6 100644
        --- a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java
        +++ b/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java
        @@ -14,8 +14,8 @@
         import io.a2a.spec.EventKind;
         import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.Message;
         import io.a2a.spec.MessageSendParams;
        @@ -262,16 +262,16 @@ void testGetTaskPushNotificationConfiguration_Success() throws A2AClientExceptio
         
             @Test
             void testListTaskPushNotificationConfigurations_Success() throws A2AClientException {
        -        ListTaskPushNotificationConfigParams request = mock(ListTaskPushNotificationConfigParams.class);
        +        ListTaskPushNotificationConfigsParams request = mock(ListTaskPushNotificationConfigsParams.class);
                 TaskPushNotificationConfig config1 = mock(TaskPushNotificationConfig.class);
                 TaskPushNotificationConfig config2 = mock(TaskPushNotificationConfig.class);
                 when(config1.toString()).thenReturn("config1");
                 when(config2.toString()).thenReturn("config2");
        -        ListTaskPushNotificationConfigResult expectedResult = new ListTaskPushNotificationConfigResult(List.of(config1, config2));
        +        ListTaskPushNotificationConfigsResult expectedResult = new ListTaskPushNotificationConfigsResult(List.of(config1, config2));
                 when(request.toString()).thenReturn("request-string");
                 when(delegate.listTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult);
         
        -        ListTaskPushNotificationConfigResult result = transport.listTaskPushNotificationConfigurations(request, context);
        +        ListTaskPushNotificationConfigsResult result = transport.listTaskPushNotificationConfigurations(request, context);
         
                 assertEquals(expectedResult, result);
                 verify(tracer).spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD);
        diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java
        index ffa7a1322..dfad8a531 100644
        --- a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java
        +++ b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java
        @@ -23,8 +23,8 @@
         import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
         import io.a2a.spec.EventKind;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.MessageSendParams;
         import io.a2a.spec.StreamingEventKind;
        @@ -396,7 +396,7 @@ public Flow.Publisher onSubscribeToTask(TaskIdParams params,
             }
         
             @Override
        -    public ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig(ListTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError {
        +    public ListTaskPushNotificationConfigsResult onListTaskPushNotificationConfigs(ListTaskPushNotificationConfigsParams params, ServerCallContext context) throws A2AError {
                 var spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD)
                         .setSpanKind(SpanKind.SERVER)
                         .setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD);
        @@ -411,7 +411,7 @@ public ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig(Lis
                 Span span = spanBuilder.startSpan();
         
                 try (Scope scope = span.makeCurrent()) {
        -            ListTaskPushNotificationConfigResult result = delegate.onListTaskPushNotificationConfig(params, context);
        +            ListTaskPushNotificationConfigsResult result = delegate.onListTaskPushNotificationConfigs(params, context);
         
                     if (result != null && extractResponse()) {
                         span.setAttribute(GENAI_RESPONSE, result.toString());
        diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java
        index 748bb3927..290b40c37 100644
        --- a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java
        +++ b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java
        @@ -393,14 +393,14 @@ void onResubscribeToTask_withError_setsErrorStatus() throws A2AError {
             }
         
             @Nested
        -    class ListTaskPushNotificationConfigTests {
        +    class ListTaskPushNotificationConfigsTests {
                 @Test
        -        void onListTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError {
        -            ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-123");
        -            ListTaskPushNotificationConfigResult result = new ListTaskPushNotificationConfigResult(Collections.emptyList(), null);
        -            when(delegate.onListTaskPushNotificationConfig(params, context)).thenReturn(result);
        +        void onListTaskPushNotificationConfigs_createsSpanAndDelegatesToHandler() throws A2AError {
        +            ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams("task-123");
        +            ListTaskPushNotificationConfigsResult result = new ListTaskPushNotificationConfigsResult(Collections.emptyList(), null);
        +            when(delegate.onListTaskPushNotificationConfigs(params, context)).thenReturn(result);
         
        -            ListTaskPushNotificationConfigResult actualResult = decorator.onListTaskPushNotificationConfig(params, context);
        +            ListTaskPushNotificationConfigsResult actualResult = decorator.onListTaskPushNotificationConfigs(params, context);
         
                     assertEquals(result, actualResult);
                     verify(tracer).spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD);
        @@ -411,12 +411,12 @@ void onListTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws
                 }
         
                 @Test
        -        void onListTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError {
        -            ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-123");
        +        void onListTaskPushNotificationConfigs_withError_setsErrorStatus() throws A2AError {
        +            ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams("task-123");
                     A2AError error = new InvalidRequestError("Invalid request");
        -            when(delegate.onListTaskPushNotificationConfig(params, context)).thenThrow(error);
        +            when(delegate.onListTaskPushNotificationConfigs(params, context)).thenThrow(error);
         
        -            assertThrows(InvalidRequestError.class, () -> decorator.onListTaskPushNotificationConfig(params, context));
        +            assertThrows(InvalidRequestError.class, () -> decorator.onListTaskPushNotificationConfigs(params, context));
         
                     verify(span).setAttribute(ERROR_TYPE, error.getMessage());
                     verify(span).setStatus(StatusCode.ERROR, error.getMessage());
        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 a34d0b55f..20d88e79c 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
        @@ -13,8 +13,8 @@
         
         import io.a2a.jsonrpc.common.json.JsonProcessingException;
         import io.a2a.server.tasks.PushNotificationConfigStore;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.util.Assert;
         import io.a2a.util.PageToken;
         import io.a2a.spec.TaskPushNotificationConfig;
        @@ -74,7 +74,7 @@ public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificatio
         
             @Transactional
             @Override
        -    public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConfigParams params) {
        +    public ListTaskPushNotificationConfigsResult getInfo(ListTaskPushNotificationConfigsParams params) {
                 String taskId = params.id();
                 LOGGER.debug("Retrieving PushNotificationConfigs for Task '{}' with params: pageSize={}, pageToken={}",
                     taskId, params.pageSize(), params.pageToken());
        @@ -136,7 +136,7 @@ public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConf
         
                     LOGGER.debug("Successfully retrieved {} PushNotificationConfigs for Task '{}'", taskPushNotificationConfigs.size(), taskId);
         
        -            return new ListTaskPushNotificationConfigResult(taskPushNotificationConfigs, nextPageToken);
        +            return new ListTaskPushNotificationConfigsResult(taskPushNotificationConfigs, nextPageToken);
                 } catch (Exception e) {
                     LOGGER.error("Failed to retrieve PushNotificationConfigs for Task '{}'", taskId, e);
                     throw e;
        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 3551f700a..59dc130f5 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
        @@ -25,8 +25,8 @@
         import io.a2a.spec.AgentCard;
         import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.Message;
         import io.a2a.spec.Task;
         import io.a2a.spec.TaskPushNotificationConfig;
        @@ -207,8 +207,8 @@ public void testPaginationWithPageSize() {
                 // Create 5 configs
                 createSamples(taskId, 5);
                 // Request first page with pageSize=2
        -        ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 2, "", "");
        -        ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +        ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, 2, "", "");
        +        ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
                 assertNotNull(result);
                 assertEquals(2, result.configs().size(), "Should return 2 configs");
        @@ -223,14 +223,14 @@ public void testPaginationWithPageToken() {
                 createSamples(taskId, 5);
         
                 // Get first page
        -        ListTaskPushNotificationConfigParams firstPageParams = new ListTaskPushNotificationConfigParams(taskId, 2, "", "");
        -        ListTaskPushNotificationConfigResult firstPage = pushNotificationConfigStore.getInfo(firstPageParams);
        +        ListTaskPushNotificationConfigsParams firstPageParams = new ListTaskPushNotificationConfigsParams(taskId, 2, "", "");
        +        ListTaskPushNotificationConfigsResult firstPage = pushNotificationConfigStore.getInfo(firstPageParams);
                 assertNotNull(firstPage.nextPageToken());
         
                 // Get second page using nextPageToken
        -        ListTaskPushNotificationConfigParams secondPageParams = new ListTaskPushNotificationConfigParams(
        +        ListTaskPushNotificationConfigsParams secondPageParams = new ListTaskPushNotificationConfigsParams(
                         taskId, 2, firstPage.nextPageToken(), "");
        -        ListTaskPushNotificationConfigResult secondPage = pushNotificationConfigStore.getInfo(secondPageParams);
        +        ListTaskPushNotificationConfigsResult secondPage = pushNotificationConfigStore.getInfo(secondPageParams);
         
                 assertNotNull(secondPage);
                 assertEquals(2, secondPage.configs().size(), "Should return 2 configs for second page");
        @@ -268,18 +268,18 @@ public void testPaginationLastPage() {
                 createSamples(taskId, 5);
         
                 // Get first page (2 items)
        -        ListTaskPushNotificationConfigParams firstPageParams = new ListTaskPushNotificationConfigParams(taskId, 2, "", "");
        -        ListTaskPushNotificationConfigResult firstPage = pushNotificationConfigStore.getInfo(firstPageParams);
        +        ListTaskPushNotificationConfigsParams firstPageParams = new ListTaskPushNotificationConfigsParams(taskId, 2, "", "");
        +        ListTaskPushNotificationConfigsResult firstPage = pushNotificationConfigStore.getInfo(firstPageParams);
         
                 // Get second page (2 items)
        -        ListTaskPushNotificationConfigParams secondPageParams = new ListTaskPushNotificationConfigParams(
        +        ListTaskPushNotificationConfigsParams secondPageParams = new ListTaskPushNotificationConfigsParams(
                         taskId, 2, firstPage.nextPageToken(), "");
        -        ListTaskPushNotificationConfigResult secondPage = pushNotificationConfigStore.getInfo(secondPageParams);
        +        ListTaskPushNotificationConfigsResult secondPage = pushNotificationConfigStore.getInfo(secondPageParams);
         
                 // Get last page (1 item remaining)
        -        ListTaskPushNotificationConfigParams lastPageParams = new ListTaskPushNotificationConfigParams(
        +        ListTaskPushNotificationConfigsParams lastPageParams = new ListTaskPushNotificationConfigsParams(
                         taskId, 2, secondPage.nextPageToken(), "");
        -        ListTaskPushNotificationConfigResult lastPage = pushNotificationConfigStore.getInfo(lastPageParams);
        +        ListTaskPushNotificationConfigsResult lastPage = pushNotificationConfigStore.getInfo(lastPageParams);
         
                 assertNotNull(lastPage);
                 assertEquals(1, lastPage.configs().size(), "Last page should have 1 remaining config");
        @@ -294,8 +294,8 @@ public void testPaginationWithZeroPageSize() {
                 createSamples(taskId, 5);
         
                 // Request with pageSize=0 should return all configs
        -        ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 0, "", "");
        -        ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +        ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, 0, "", "");
        +        ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
                 assertNotNull(result);
                 assertEquals(5, result.configs().size(), "Should return all 5 configs when pageSize=0");
        @@ -310,8 +310,8 @@ public void testPaginationWithNegativePageSize() {
                 createSamples(taskId, 3);
         
                 // Request with negative pageSize should return all configs
        -        ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, -1, "", "");
        -        ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +        ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, -1, "", "");
        +        ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
                 assertNotNull(result);
                 assertEquals(3, result.configs().size(), "Should return all configs when pageSize is negative");
        @@ -326,8 +326,8 @@ public void testPaginationPageSizeLargerThanConfigs() {
                 createSamples(taskId, 3);
         
                 // Request with pageSize larger than available configs
        -        ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 10, "", "");
        -        ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +        ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, 10, "", "");
        +        ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
                 assertNotNull(result);
                 assertEquals(3, result.configs().size(), "Should return all 3 configs");
        @@ -342,8 +342,8 @@ public void testPaginationExactlyPageSize() {
                 createSamples(taskId, 3);
         
                 // Request with pageSize equal to number of configs
        -        ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 3, "", "");
        -        ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +        ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, 3, "", "");
        +        ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
                 assertNotNull(result);
                 assertEquals(3, result.configs().size(), "Should return all 3 configs");
        @@ -358,7 +358,7 @@ public void testPaginationWithInvalidToken() {
                 createSamples(taskId, 5);
         
                 // Request with invalid pageToken - should throw InvalidParamsError for invalid format
        -        ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(
        +        ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(
                         taskId, 2, "invalid_token_that_does_not_exist", "");
         
                 assertThrows(io.a2a.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params),
        @@ -371,8 +371,8 @@ public void testPaginationEmptyTaskWithPageSize() {
                 String taskId = "task_pagination_empty_" + System.currentTimeMillis();
                 // No configs created
         
        -        ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 2, "", "");
        -        ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +        ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, 2, "", "");
        +        ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
                 assertNotNull(result);
                 assertTrue(result.configs().isEmpty(), "Should return empty list for non-existent task");
        @@ -392,8 +392,8 @@ public void testPaginationFullIteration() {
                 int pageCount = 0;
         
                 do {
        -            ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 3, pageToken, "");
        -            ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +            ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, 3, pageToken, "");
        +            ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
                     totalCollected += result.configs().size();
                     pageToken = result.nextPageToken();
        @@ -414,8 +414,8 @@ public void testPageTokenWithNonNumericTimestamp() {
               String taskId = "task_malformed_token_" + System.currentTimeMillis();
               createSamples(taskId, 3);
         
        -      ListTaskPushNotificationConfigParams params =
        -          new ListTaskPushNotificationConfigParams(taskId, 2, "not_a_number:cfg1", "");
        +      ListTaskPushNotificationConfigsParams params =
        +          new ListTaskPushNotificationConfigsParams(taskId, 2, "not_a_number:cfg1", "");
         
               assertThrows(io.a2a.spec.InvalidParamsError.class,
                   () -> pushNotificationConfigStore.getInfo(params),
        @@ -428,8 +428,8 @@ public void testPageTokenWithMissingColon() {
               String taskId = "task_missing_colon_" + System.currentTimeMillis();
               createSamples(taskId, 5);
         
        -      ListTaskPushNotificationConfigParams params =
        -          new ListTaskPushNotificationConfigParams(taskId, 2, "123456789cfg1", "");
        +      ListTaskPushNotificationConfigsParams params =
        +          new ListTaskPushNotificationConfigsParams(taskId, 2, "123456789cfg1", "");
         
               assertThrows(io.a2a.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params),
                   "Should throw InvalidParamsError for invalid pageToken format (missing colon)");
        @@ -442,9 +442,9 @@ public void testPaginationBoundaryExactlyMaxResultsPlusOne() {
         
               createSamples(taskId, 4);
         
        -      ListTaskPushNotificationConfigParams params =
        -          new ListTaskPushNotificationConfigParams(taskId, 4, "", "");
        -      ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +      ListTaskPushNotificationConfigsParams params =
        +          new ListTaskPushNotificationConfigsParams(taskId, 4, "", "");
        +      ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
               assertEquals(4, result.configs().size(),
                   "Should return all 4 configs when pageSize equals total count");
        @@ -461,10 +461,10 @@ public void testMultipleTasksDoNotInterfere() {
               createSamples(taskId1, 3);
               createSamples(taskId2, 2);
         
        -      ListTaskPushNotificationConfigResult result1 =
        -          pushNotificationConfigStore.getInfo(new ListTaskPushNotificationConfigParams(taskId1));
        -      ListTaskPushNotificationConfigResult result2 =
        -          pushNotificationConfigStore.getInfo(new ListTaskPushNotificationConfigParams(taskId2));
        +      ListTaskPushNotificationConfigsResult result1 =
        +          pushNotificationConfigStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId1));
        +      ListTaskPushNotificationConfigsResult result2 =
        +          pushNotificationConfigStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId2));
         
               assertEquals(3, result1.configs().size(), "Task1 should have 3 configs");
               assertEquals(2, result2.configs().size(), "Task2 should have 2 configs");
        @@ -487,9 +487,9 @@ public void testMultipleTasksDoNotInterfere() {
             public void testGetInfoWithNonExistentTaskIdDoesNotThrow() {
               String nonExistentTaskId = "non_existent_task_" + System.currentTimeMillis();
         
        -      ListTaskPushNotificationConfigParams params =
        -          new ListTaskPushNotificationConfigParams(nonExistentTaskId, 10, "", "");
        -      ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +      ListTaskPushNotificationConfigsParams params =
        +          new ListTaskPushNotificationConfigsParams(nonExistentTaskId, 10, "", "");
        +      ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
               assertNotNull(result, "Result should not be null");
               assertTrue(result.configs().isEmpty(),
        @@ -508,9 +508,9 @@ public void testGetInfoReturnsTenantFromParams() {
                   "http://url.com/callback", "cfg1", "token");
               pushNotificationConfigStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build());
         
        -      ListTaskPushNotificationConfigParams params =
        -          new ListTaskPushNotificationConfigParams(taskId, 0, "", tenant);
        -      ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +      ListTaskPushNotificationConfigsParams params =
        +          new ListTaskPushNotificationConfigsParams(taskId, 0, "", tenant);
        +      ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
               assertNotNull(result);
               assertEquals(1, result.configs().size());
        @@ -529,9 +529,9 @@ public void testPaginationOrderingConsistency() {
               int pageCount = 0;
         
               do {
        -        ListTaskPushNotificationConfigParams params =
        -            new ListTaskPushNotificationConfigParams(taskId, 3, pageToken, "");
        -        ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params);
        +        ListTaskPushNotificationConfigsParams params =
        +            new ListTaskPushNotificationConfigsParams(taskId, 3, pageToken, "");
        +        ListTaskPushNotificationConfigsResult result = pushNotificationConfigStore.getInfo(params);
         
                 result.configs().forEach(c ->
                     allConfigIds.add(c.id()));
        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 9e10e1910..9e0aff233 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
        @@ -20,8 +20,8 @@
         import io.a2a.client.http.A2AHttpResponse;
         import io.a2a.server.tasks.BasePushNotificationSender;
         import io.a2a.server.tasks.PushNotificationConfigStore;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.Task;
         import io.a2a.spec.TaskPushNotificationConfig;
         import io.a2a.spec.TaskState;
        @@ -90,7 +90,7 @@ public void testSetInfoAddsNewConfig() {
                 assertEquals(config.url(), result.url());
                 assertEquals(config.id(), result.id());
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertEquals(1, configResult.configs().size());
                 assertEquals(config.url(), configResult.configs().get(0).url());
        @@ -109,7 +109,7 @@ public void testSetInfoAppendsToExistingConfig() {
                         "http://updated.url/callback", "cfg_updated", null);
                 configStore.setInfo(TaskPushNotificationConfig.builder(updatedConfig).taskId(taskId).build());
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertEquals(2, configResult.configs().size());
         
        @@ -143,7 +143,7 @@ public void testSetInfoWithoutConfigId() {
                 TaskPushNotificationConfig result = configStore.setInfo(initialConfig);
                 assertEquals(taskId, result.id(), "Config ID should default to taskId when not provided");
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertEquals(1, configResult.configs().size());
                 assertEquals(taskId, configResult.configs().get(0).id());
         
        @@ -156,7 +156,7 @@ public void testSetInfoWithoutConfigId() {
                 TaskPushNotificationConfig updatedResult = configStore.setInfo(updatedConfig);
                 assertEquals(taskId, updatedResult.id());
         
        -        configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertEquals(1, configResult.configs().size(), "Should replace existing config with same ID rather than adding new one");
                 assertEquals(updatedConfig.url(), configResult.configs().get(0).url());
             }
        @@ -168,7 +168,7 @@ public void testGetInfoExistingConfig() {
                 TaskPushNotificationConfig config = createSamplePushConfig("http://get.this/callback", "cfg1", null);
                 configStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build());
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertEquals(1, configResult.configs().size());
                 assertEquals(config.url(), configResult.configs().get(0).url());
        @@ -179,7 +179,7 @@ public void testGetInfoExistingConfig() {
             @Transactional
             public void testGetInfoNonExistentConfig() {
                 String taskId = "task_get_non_exist";
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertTrue(configResult.configs().isEmpty(), "Should return empty list for non-existent task ID");
             }
        @@ -191,13 +191,13 @@ public void testDeleteInfoExistingConfig() {
                 TaskPushNotificationConfig config = createSamplePushConfig("http://delete.this/callback", "cfg1", null);
                 configStore.setInfo(TaskPushNotificationConfig.builder(config).taskId(taskId).build());
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertEquals(1, configResult.configs().size());
         
                 configStore.deleteInfo(taskId, config.id());
         
        -        ListTaskPushNotificationConfigResult configsAfterDelete = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configsAfterDelete = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configsAfterDelete);
                 assertTrue(configsAfterDelete.configs().isEmpty(), "Should return empty list when no configs remain after deletion");
             }
        @@ -209,7 +209,7 @@ public void testDeleteInfoNonExistentConfig() {
                 // Should not throw an error
                 configStore.deleteInfo(taskId, "non_existent_id");
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertTrue(configResult.configs().isEmpty(), "Should return empty list for non-existent task ID");
             }
        @@ -228,7 +228,7 @@ public void testDeleteInfoWithNullConfigId() {
                 // Delete with null configId should use taskId
                 configStore.deleteInfo(taskId, null);
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertTrue(configResult.configs().isEmpty(), "Should return empty list after deletion when using taskId as configId");
             }
        @@ -323,7 +323,7 @@ public void testMultipleConfigsForSameTask() {
                 configStore.setInfo(TaskPushNotificationConfig.builder(config1).taskId(taskId).build());
                 configStore.setInfo(TaskPushNotificationConfig.builder(config2).taskId(taskId).build());
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertEquals(2, configResult.configs().size());
         
        @@ -345,7 +345,7 @@ public void testDeleteSpecificConfigFromMultiple() {
                 // Delete only config1
                 configStore.deleteInfo(taskId, "cfg1");
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertNotNull(configResult);
                 assertEquals(1, configResult.configs().size());
                 assertEquals("cfg2", configResult.configs().get(0).id());
        @@ -362,13 +362,13 @@ public void testConfigStoreIntegration() {
                 assertEquals(config.url(), storedConfig.url());
                 assertEquals(config.token(), storedConfig.token());
         
        -        ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertEquals(1, configResult.configs().size());
                 assertEquals(config.url(), configResult.configs().get(0).url());
         
                 // Test deletion
                 configStore.deleteInfo(taskId, storedConfig.id());
        -        ListTaskPushNotificationConfigResult afterDeletion = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId));
        +        ListTaskPushNotificationConfigsResult afterDeletion = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId));
                 assertTrue(afterDeletion.configs().isEmpty());
             }
         }
        diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java
        index 66133f250..82b7a40bc 100644
        --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java
        +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java
        @@ -3,7 +3,7 @@
         
         import java.util.UUID;
         
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
         import io.a2a.spec.TaskPushNotificationConfig;
         
         import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD;
        @@ -17,11 +17,11 @@
          * This class implements the JSON-RPC {@code tasks/pushNotificationConfig/list} method.
          *
          * @see ListTaskPushNotificationConfigsResponse for the response
        - * @see ListTaskPushNotificationConfigParams for the parameter structure
        + * @see ListTaskPushNotificationConfigsParams for the parameter structure
          * @see TaskPushNotificationConfig for the configuration structure
          * @see A2A Protocol Specification
          */
        -public final class ListTaskPushNotificationConfigsRequest extends NonStreamingJSONRPCRequest {
        +public final class ListTaskPushNotificationConfigsRequest extends NonStreamingJSONRPCRequest {
         
             /**
              * Constructs request with all parameters.
        @@ -30,7 +30,7 @@ public final class ListTaskPushNotificationConfigsRequest extends NonStreamingJS
              * @param id the request ID
              * @param params the request parameters
              */
        -    public ListTaskPushNotificationConfigsRequest(String jsonrpc, Object id, ListTaskPushNotificationConfigParams params) {
        +    public ListTaskPushNotificationConfigsRequest(String jsonrpc, Object id, ListTaskPushNotificationConfigsParams params) {
                 super(jsonrpc, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params);
             }
         
        @@ -40,7 +40,7 @@ public ListTaskPushNotificationConfigsRequest(String jsonrpc, Object id, ListTas
              * @param id the request ID
              * @param params the request parameters
              */
        -    public ListTaskPushNotificationConfigsRequest(String id, ListTaskPushNotificationConfigParams params) {
        +    public ListTaskPushNotificationConfigsRequest(String id, ListTaskPushNotificationConfigsParams params) {
                 this(null, id, params);
             }
         
        @@ -59,7 +59,7 @@ public static Builder builder() {
             public static class Builder {
                 private String jsonrpc;
                 private Object id;
        -        private ListTaskPushNotificationConfigParams params;
        +        private ListTaskPushNotificationConfigsParams params;
         
                 /**
                  * Creates a new Builder with all fields unset.
        @@ -95,7 +95,7 @@ public Builder id(Object id) {
                  * @param params the params
                  * @return this builder for method chaining
                  */
        -        public Builder params(ListTaskPushNotificationConfigParams params) {
        +        public Builder params(ListTaskPushNotificationConfigsParams params) {
                     this.params = params;
                     return this;
                 }
        diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java
        index 30b983c06..eb1ef9ff7 100644
        --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java
        +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java
        @@ -1,24 +1,24 @@
         package io.a2a.jsonrpc.common.wrappers;
         
         import io.a2a.spec.A2AError;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.TaskPushNotificationConfig;
         
         /**
          * JSON-RPC response containing all push notification configurations for a task with pagination support.
          * 

        - * This response returns a {@link ListTaskPushNotificationConfigResult} containing + * This response returns a {@link ListTaskPushNotificationConfigsResult} containing * {@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 A2AError}. * * @see ListTaskPushNotificationConfigsRequest for the corresponding request - * @see ListTaskPushNotificationConfigResult for the result structure + * @see ListTaskPushNotificationConfigsResult for the result structure * @see TaskPushNotificationConfig for the configuration structure * @see A2A Protocol Specification */ -public final class ListTaskPushNotificationConfigsResponse extends A2AResponse { +public final class ListTaskPushNotificationConfigsResponse extends A2AResponse { /** * Constructs response with all parameters. @@ -28,8 +28,8 @@ public final class ListTaskPushNotificationConfigsResponse extends A2AResponse{@code CancelTask} - Cancel task execution *

      • {@code CreateTaskPushNotificationConfig} - Configure push notifications
      • *
      • {@code GetTaskPushNotificationConfig} - Get push notification config
      • - *
      • {@code ListTaskPushNotificationConfig} - List push notification configs
      • + *
      • {@code ListTaskPushNotificationConfigs} - List push notification configs
      • *
      • {@code DeleteTaskPushNotificationConfig} - Delete push notification config
      • *
      • {@code GetExtendedAgentCard} - Get extended agent card
      • * 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 c1e831ebb..6914dc5f9 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 @@ -109,7 +109,7 @@ *
      • {@code listTasks} - List tasks with filtering
      • *
      • {@code setTaskPushNotificationConfig} - Configure push notifications
      • *
      • {@code getTaskPushNotificationConfig} - Get push notification config
      • - *
      • {@code listTaskPushNotificationConfig} - List push notification configs
      • + *
      • {@code listTaskPushNotificationConfigs} - List push notification configs
      • *
      • {@code deleteTaskPushNotificationConfig} - Delete push notification config
      • *
      • {@code getExtendedAgentCard} - Get extended agent capabilities
      • * @@ -366,7 +366,7 @@ public String getAgentCard() throws JsonProcessingException { *
      • {@link SendMessageRequest} → {@link JSONRPCHandler#onMessageSend}
      • *
      • {@link CreateTaskPushNotificationConfigRequest} → {@link JSONRPCHandler#setPushNotificationConfig}
      • *
      • {@link GetTaskPushNotificationConfigRequest} → {@link JSONRPCHandler#getPushNotificationConfig}
      • - *
      • {@link ListTaskPushNotificationConfigRequest} → {@link JSONRPCHandler#listPushNotificationConfig}
      • + *
      • {@link ListTaskPushNotificationConfigsRequest} → {@link JSONRPCHandler#listPushNotificationConfigs}
      • *
      • {@link DeleteTaskPushNotificationConfigRequest} → {@link JSONRPCHandler#deletePushNotificationConfig}
      • *
      • {@link GetExtendedAgentCardRequest} → {@link JSONRPCHandler#onGetExtendedCardRequest}
      • * @@ -395,7 +395,7 @@ private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest return jsonRpcHandler.onMessageSend(req, context); } if (request instanceof ListTaskPushNotificationConfigsRequest req) { - return jsonRpcHandler.listPushNotificationConfig(req, context); + return jsonRpcHandler.listPushNotificationConfigs(req, context); } if (request instanceof DeleteTaskPushNotificationConfigRequest req) { return jsonRpcHandler.deletePushNotificationConfig(req, context); @@ -618,7 +618,7 @@ private static String serializeResponse(A2AResponse response) { *
      • {@link ListTasksResponse} → ListTasksResult protobuf message
      • *
      • {@link CreateTaskPushNotificationConfigResponse} → CreateTaskPushNotificationConfigResponse protobuf message
      • *
      • {@link GetTaskPushNotificationConfigResponse} → GetTaskPushNotificationConfigResponse protobuf message
      • - *
      • {@link ListTaskPushNotificationConfigResponse} → ListTaskPushNotificationConfigResponse protobuf message
      • + *
      • {@link ListTaskPushNotificationConfigsResponse} → ListTaskPushNotificationConfigsResponse protobuf message
      • *
      • {@link DeleteTaskPushNotificationConfigResponse} → Empty protobuf message
      • *
      • {@link GetExtendedAgentCardResponse} → GetExtendedCardResponse protobuf message
      • *
      • {@link SendStreamingMessageResponse} → TaskOrMessageStream protobuf message
      • @@ -643,7 +643,7 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse{@code cancelTask} - Cancel task execution *
      • {@code getTaskPushNotificationConfig} - Get push notification config
      • *
      • {@code setTaskPushNotificationConfig} - Create push notification config
      • - *
      • {@code listTaskPushNotificationConfig} - List push notification configs
      • + *
      • {@code listTaskPushNotificationConfigs} - List push notification configs
      • *
      • {@code deleteTaskPushNotificationConfig} - Delete push notification config
      • *
      • {@code getExtendedAgentCard} - Get extended agent card
      • * 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 94f67bc71..ab1566308 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 @@ -54,7 +54,7 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.Task; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskState; @@ -411,7 +411,7 @@ public void testGetTaskPushNotificationConfig_MethodNameSetInContext() { } @Test - public void testListTaskPushNotificationConfig_MethodNameSetInContext() { + public void testListTaskPushNotificationConfigs_MethodNameSetInContext() { // Arrange - using protobuf JSON format String jsonRpcRequest = """ { @@ -432,8 +432,8 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() { .taskId("de38c76d-d54c-436c-8b9f-4c2703648d64") .url("https://example.com/callback") .build(); - ListTaskPushNotificationConfigsResponse realResponse = new ListTaskPushNotificationConfigsResponse("1", new ListTaskPushNotificationConfigResult(singletonList(config))); - when(mockJsonRpcHandler.listPushNotificationConfig(any(ListTaskPushNotificationConfigsRequest.class), + ListTaskPushNotificationConfigsResponse realResponse = new ListTaskPushNotificationConfigsResponse("1", new ListTaskPushNotificationConfigsResult(singletonList(config))); + when(mockJsonRpcHandler.listPushNotificationConfigs(any(ListTaskPushNotificationConfigsRequest.class), any(ServerCallContext.class))).thenReturn(realResponse); ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); @@ -442,7 +442,7 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() { routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); // Assert - verify(mockJsonRpcHandler).listPushNotificationConfig(any(ListTaskPushNotificationConfigsRequest.class), + verify(mockJsonRpcHandler).listPushNotificationConfigs(any(ListTaskPushNotificationConfigsRequest.class), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); 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 96c17eced..fdc6ee11d 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 @@ -52,8 +52,8 @@ import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; @@ -794,16 +794,16 @@ public TaskPushNotificationConfig onGetTaskPushNotificationConfig( throw new TaskNotFoundError(); } - ListTaskPushNotificationConfigResult listTaskPushNotificationConfigResult = pushConfigStore.getInfo(new ListTaskPushNotificationConfigParams(params.taskId())); - if (listTaskPushNotificationConfigResult == null || listTaskPushNotificationConfigResult.isEmpty()) { + ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigsResult = pushConfigStore.getInfo(new ListTaskPushNotificationConfigsParams(params.taskId())); + if (listTaskPushNotificationConfigsResult == null || listTaskPushNotificationConfigsResult.isEmpty()) { throw new InternalError("No push notification config found"); } String configId = params.id(); - return getTaskPushNotificationConfig(listTaskPushNotificationConfigResult, configId); + return getTaskPushNotificationConfig(listTaskPushNotificationConfigsResult, configId); } - private TaskPushNotificationConfig getTaskPushNotificationConfig(ListTaskPushNotificationConfigResult notificationConfigList, + private TaskPushNotificationConfig getTaskPushNotificationConfig(ListTaskPushNotificationConfigsResult notificationConfigList, String configId) { for (TaskPushNotificationConfig notificationConfig : notificationConfigList.configs()) { if (configId.equals(notificationConfig.id())) { @@ -851,8 +851,8 @@ public Flow.Publisher onSubscribeToTask(TaskIdParams params, } @Override - public ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig( - ListTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { + public ListTaskPushNotificationConfigsResult onListTaskPushNotificationConfigs( + ListTaskPushNotificationConfigsParams 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 b41a8ac76..06bc11354 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 @@ -9,8 +9,8 @@ import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.ListTasksParams; import io.a2a.spec.MessageSendParams; import io.a2a.spec.StreamingEventKind; @@ -52,8 +52,8 @@ Flow.Publisher onSubscribeToTask( TaskIdParams params, ServerCallContext context) throws A2AError; - ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig( - ListTaskPushNotificationConfigParams params, + ListTaskPushNotificationConfigsResult onListTaskPushNotificationConfigs( + ListTaskPushNotificationConfigsParams params, ServerCallContext context) throws A2AError; void onDeleteTaskPushNotificationConfig( 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 ac64659ec..c11fb598f 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 @@ -19,8 +19,8 @@ import io.a2a.client.http.A2AHttpClient; import io.a2a.client.http.A2AHttpClientFactory; import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.Message; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; @@ -76,7 +76,7 @@ public void sendNotification(StreamingEventKind event) { List configs = new ArrayList<>(); String nextPageToken = null; do { - ListTaskPushNotificationConfigResult pageResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId, + ListTaskPushNotificationConfigsResult pageResult = configStore.getInfo(new ListTaskPushNotificationConfigsParams(taskId, DEFAULT_PAGE_SIZE, nextPageToken == null ? "" : nextPageToken, "")); if (!pageResult.configs().isEmpty()) { configs.addAll(pageResult.configs()); 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 8bdc82715..16ab9bf9f 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 @@ -11,8 +11,8 @@ import jakarta.inject.Inject; import io.a2a.util.Assert; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.TaskPushNotificationConfig; /** @@ -53,13 +53,13 @@ public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificatio } @Override - public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConfigParams params) { + public ListTaskPushNotificationConfigsResult getInfo(ListTaskPushNotificationConfigsParams params) { List configs = pushNotificationInfos.get(params.id()); if (configs == null) { - return new ListTaskPushNotificationConfigResult(Collections.emptyList()); + return new ListTaskPushNotificationConfigsResult(Collections.emptyList()); } if (params.pageSize() <= 0) { - return new ListTaskPushNotificationConfigResult(new ArrayList<>(configs), null); + return new ListTaskPushNotificationConfigsResult(new ArrayList<>(configs), null); } if (params.pageToken() != null && !params.pageToken().isBlank()) { //find first index @@ -69,10 +69,10 @@ public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConf } } if (configs.size() <= params.pageSize()) { - return new ListTaskPushNotificationConfigResult(new ArrayList<>(configs), null); + return new ListTaskPushNotificationConfigsResult(new ArrayList<>(configs), null); } String newToken = configs.get(params.pageSize()).id(); - return new ListTaskPushNotificationConfigResult(new ArrayList<>(configs.subList(0, params.pageSize())), newToken); + return new ListTaskPushNotificationConfigsResult(new ArrayList<>(configs.subList(0, params.pageSize())), newToken); } private int findFirstIndex(List configs, String id) { 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 50c3b2e28..4c5f35eda 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 @@ -1,7 +1,7 @@ package io.a2a.server.tasks; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.TaskPushNotificationConfig; /** @@ -21,12 +21,12 @@ * * *

        Pagination Support

        - * {@link #getInfo(ListTaskPushNotificationConfigParams)} supports pagination for tasks + * {@link #getInfo(ListTaskPushNotificationConfigsParams)} supports pagination for tasks * with many push notification configurations: *
          *
        • pageSize: Maximum number of configs to return (0 = unlimited)
        • *
        • pageToken: Continuation token from previous response
        • - *
        • Returns {@link ListTaskPushNotificationConfigResult} with configs and next page token
        • + *
        • Returns {@link ListTaskPushNotificationConfigsResult} with configs and next page token
        • *
        * *

        Default Implementation

        @@ -90,13 +90,13 @@ public interface PushNotificationConfigStore { * Pagination Example: *
        {@code
              * // First page
        -     * ListTaskPushNotificationConfigParams params =
        -     *     new ListTaskPushNotificationConfigParams(taskId, 10, null, tenant);
        -     * ListTaskPushNotificationConfigResult result = store.getInfo(params);
        +     * ListTaskPushNotificationConfigsParams params =
        +     *     new ListTaskPushNotificationConfigsParams(taskId, 10, null, tenant);
        +     * ListTaskPushNotificationConfigsResult result = store.getInfo(params);
              *
              * // Next page
              * if (result.nextPageToken() != null) {
        -     *     params = new ListTaskPushNotificationConfigParams(
        +     *     params = new ListTaskPushNotificationConfigsParams(
              *         taskId, 10, result.nextPageToken(), tenant);
              *     result = store.getInfo(params);
              * }
        @@ -105,7 +105,7 @@ public interface PushNotificationConfigStore {
              * @param params the query parameters including task ID, page size, and page token
              * @return the configurations for this task (empty list if none found)
              */
        -    ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConfigParams params);
        +    ListTaskPushNotificationConfigsResult getInfo(ListTaskPushNotificationConfigsParams params);
         
             /**
              * Deletes a push notification configuration for a task.
        diff --git a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java
        index fec2386cc..8777f0f80 100644
        --- a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java
        +++ b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java
        @@ -121,7 +121,7 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse parseMethodRequest(String version, Object id, Strin
                         if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) {
                             builder.setTenant(tenant);
                         }
        -                return new ListTaskPushNotificationConfigsRequest(version, id, ProtoUtils.FromProto.listTaskPushNotificationConfigParams(builder));
        +                return new ListTaskPushNotificationConfigsRequest(version, id, ProtoUtils.FromProto.listTaskPushNotificationConfigsParams(builder));
                     }
                     case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> {
                         io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder();
        @@ -352,7 +352,7 @@ public static A2AResponse parseResponseBody(String body, String method) throw
                     case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> {
                         io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder();
                         parseRequestBody(paramsNode, builder, id);
        -                return new ListTaskPushNotificationConfigsResponse(id, ProtoUtils.FromProto.listTaskPushNotificationConfigResult(builder));
        +                return new ListTaskPushNotificationConfigsResponse(id, ProtoUtils.FromProto.listTaskPushNotificationConfigsResult(builder));
                     }
                     case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> {
                         return new DeleteTaskPushNotificationConfigResponse(id);
        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 5cb52b96b..e2c98f47c 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
        @@ -8,7 +8,7 @@
         import io.a2a.grpc.mapper.AgentCardMapper;
         import io.a2a.grpc.mapper.DeleteTaskPushNotificationConfigParamsMapper;
         import io.a2a.grpc.mapper.GetTaskPushNotificationConfigParamsMapper;
        -import io.a2a.grpc.mapper.ListTaskPushNotificationConfigParamsMapper;
        +import io.a2a.grpc.mapper.ListTaskPushNotificationConfigsParamsMapper;
         import io.a2a.grpc.mapper.ListTasksParamsMapper;
         import io.a2a.grpc.mapper.ListTasksResultMapper;
         import io.a2a.grpc.mapper.MessageMapper;
        @@ -30,8 +30,8 @@
         import io.a2a.spec.GetExtendedAgentCardParams;
         import io.a2a.spec.GetTaskPushNotificationConfigParams;
         import io.a2a.spec.InvalidParamsError;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.Message;
         import io.a2a.spec.MessageSendConfiguration;
        @@ -88,8 +88,8 @@ public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest deleteTaskPush
                     return DeleteTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params);
                 }
         
        -        public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest listTaskPushNotificationConfigRequest(ListTaskPushNotificationConfigParams params) {
        -            return ListTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params);
        +        public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest listTaskPushNotificationConfigsRequest(ListTaskPushNotificationConfigsParams params) {
        +            return ListTaskPushNotificationConfigsParamsMapper.INSTANCE.toProto(params);
                 }
         
                 public static io.a2a.grpc.Task task(Task task) {
        @@ -132,7 +132,7 @@ public static io.a2a.grpc.SendMessageRequest sendMessageRequest(MessageSendParam
                     return MessageSendParamsMapper.INSTANCE.toProto(request);
                 }
         
        -        public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigResponse(ListTaskPushNotificationConfigResult result) {
        +        public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigsResponse(ListTaskPushNotificationConfigsResult result) {
                     List confs = new ArrayList<>(result.configs().size());
                     for (TaskPushNotificationConfig config : result.configs()) {
                         confs.add(taskPushNotificationConfig(config));
        @@ -264,7 +264,7 @@ public static TaskIdParams taskIdParams(io.a2a.grpc.SubscribeToTaskRequestOrBuil
                     return convert(() -> TaskIdParamsMapper.INSTANCE.fromProtoSubscribeToTaskRequest(reqProto));
                 }
         
        -        public static ListTaskPushNotificationConfigResult listTaskPushNotificationConfigResult(io.a2a.grpc.ListTaskPushNotificationConfigsResponseOrBuilder response) {
        +        public static ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigsResult(io.a2a.grpc.ListTaskPushNotificationConfigsResponseOrBuilder response) {
                     List configs = response.getConfigsList();
                     List result = new ArrayList<>(configs.size());
                     for (io.a2a.grpc.TaskPushNotificationConfig config : configs) {
        @@ -274,14 +274,14 @@ public static ListTaskPushNotificationConfigResult listTaskPushNotificationConfi
                     if (nextPageToken != null && nextPageToken.isEmpty()) {
                         nextPageToken = null;
                     }
        -            return new ListTaskPushNotificationConfigResult(result, nextPageToken);
        +            return new ListTaskPushNotificationConfigsResult(result, nextPageToken);
                 }
         
        -        public static ListTaskPushNotificationConfigParams listTaskPushNotificationConfigParams(io.a2a.grpc.ListTaskPushNotificationConfigsRequestOrBuilder request) {
        +        public static ListTaskPushNotificationConfigsParams listTaskPushNotificationConfigsParams(io.a2a.grpc.ListTaskPushNotificationConfigsRequestOrBuilder request) {
                     io.a2a.grpc.ListTaskPushNotificationConfigsRequest reqProto = request instanceof io.a2a.grpc.ListTaskPushNotificationConfigsRequest
                             ? (io.a2a.grpc.ListTaskPushNotificationConfigsRequest) request
                             : ((io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder) request).build();
        -            return convert(() -> ListTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto));
        +            return convert(() -> ListTaskPushNotificationConfigsParamsMapper.INSTANCE.fromProto(reqProto));
                 }
         
                 public static DeleteTaskPushNotificationConfigParams deleteTaskPushNotificationConfigParams(io.a2a.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder request) {
        diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java
        index a9ef05edc..06759af55 100644
        --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java
        +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java
        @@ -22,7 +22,7 @@
         import io.a2a.spec.AuthenticationInfo;
         import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
         import io.a2a.spec.HTTPAuthSecurityScheme;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
         import io.a2a.spec.Message;
         import io.a2a.spec.MessageSendConfiguration;
         import io.a2a.spec.Task;
        @@ -323,16 +323,16 @@ public void convertDeleteTaskPushNotificationConfigRequest() {
         
             @Test
             public void convertListTaskPushNotificationConfigsRequest() {
        -        ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-789");
        +        ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams("task-789");
         
                 io.a2a.grpc.ListTaskPushNotificationConfigsRequest result =
        -                ProtoUtils.ToProto.listTaskPushNotificationConfigRequest(params);
        +                ProtoUtils.ToProto.listTaskPushNotificationConfigsRequest(params);
         
                 assertEquals("task-789", result.getTaskId());
         
                 // Test round-trip conversion
        -        ListTaskPushNotificationConfigParams convertedBack =
        -                ProtoUtils.FromProto.listTaskPushNotificationConfigParams(result);
        +        ListTaskPushNotificationConfigsParams convertedBack =
        +                ProtoUtils.FromProto.listTaskPushNotificationConfigsParams(result);
                 assertEquals("task-789", convertedBack.id());
             }
         }
        diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsParams.java
        similarity index 88%
        rename from spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java
        rename to spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsParams.java
        index f24f3c4ce..9f39987fb 100644
        --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java
        +++ b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsParams.java
        @@ -17,7 +17,7 @@
          * @see TaskPushNotificationConfig for the configuration structure
          * @see A2A Protocol Specification
          */
        -public record ListTaskPushNotificationConfigParams(String id, int pageSize, String pageToken, String tenant) {
        +public record ListTaskPushNotificationConfigsParams(String id, int pageSize, String pageToken, String tenant) {
         
             /**
              * Compact constructor for validation.
        @@ -28,7 +28,7 @@ public record ListTaskPushNotificationConfigParams(String id, int pageSize, Stri
              * @param tenant the tenant identifier
              * @throws IllegalArgumentException if id or tenant is null
              */
        -    public ListTaskPushNotificationConfigParams {
        +    public ListTaskPushNotificationConfigsParams {
                 Assert.checkNotNullParam("id", id);
                 Assert.checkNotNullParam("tenant", tenant);
             }
        @@ -38,7 +38,7 @@ public record ListTaskPushNotificationConfigParams(String id, int pageSize, Stri
              *
              * @param id the task identifier (required)
              */
        -    public ListTaskPushNotificationConfigParams(String id) {
        +    public ListTaskPushNotificationConfigsParams(String id) {
                 this(id, 0, "", "");
             }
         
        @@ -123,13 +123,13 @@ public Builder tenant(String tenant) {
                 }
         
                 /**
        -         * Builds the ListTaskPushNotificationConfigParams.
        +         * Builds the ListTaskPushNotificationConfigsParams.
                  *
        -         * @return a new ListTaskPushNotificationConfigParams instance
        +         * @return a new ListTaskPushNotificationConfigsParams instance
                  * @throws IllegalArgumentException if id is null
                  */
        -        public ListTaskPushNotificationConfigParams build() {
        -            return new ListTaskPushNotificationConfigParams(
        +        public ListTaskPushNotificationConfigsParams build() {
        +            return new ListTaskPushNotificationConfigsParams(
                         Assert.checkNotNullParam("id", id),
                         pageSize != null ? pageSize : 0,
                         pageToken != null ? pageToken : "",
        diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsResult.java
        similarity index 87%
        rename from spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java
        rename to spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsResult.java
        index 1ae125713..a2b9ebb4f 100644
        --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java
        +++ b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsResult.java
        @@ -11,7 +11,7 @@
          * @param configs List of push notification configurations for the task
          * @param nextPageToken Token for retrieving the next page of results (null if no more results)
          */
        -public record ListTaskPushNotificationConfigResult(List configs,
        +public record ListTaskPushNotificationConfigsResult(List configs,
                 @Nullable String nextPageToken) {
             /**
              * Compact constructor for validation.
        @@ -21,7 +21,7 @@ public record ListTaskPushNotificationConfigResult(List configs) {
        +    public ListTaskPushNotificationConfigsResult(List configs) {
                 this(configs, null);
             }
         
        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 2c7b2ecee..f7cdacc61 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
        @@ -62,8 +62,8 @@
         import io.a2a.spec.InvalidParamsError;
         import io.a2a.spec.InvalidRequestError;
         import io.a2a.spec.JSONParseError;
        -import io.a2a.spec.ListTaskPushNotificationConfigParams;
        -import io.a2a.spec.ListTaskPushNotificationConfigResult;
        +import io.a2a.spec.ListTaskPushNotificationConfigsParams;
        +import io.a2a.spec.ListTaskPushNotificationConfigsResult;
         import io.a2a.spec.ListTasksParams;
         import io.a2a.spec.Message;
         import io.a2a.spec.MessageSendParams;
        @@ -1118,7 +1118,7 @@ private boolean waitForChildQueueCountToBe(String taskId, int expectedCount, lon
             }
         
             @Test
        -    public void testListPushNotificationConfigWithConfigId() throws Exception {
        +    public void testListPushNotificationConfigsWithConfigId() throws Exception {
                 saveTaskInTaskStore(MINIMAL_TASK);
                 TaskPushNotificationConfig notificationConfig1
                         = TaskPushNotificationConfig.builder()
        @@ -1134,8 +1134,8 @@ public void testListPushNotificationConfigWithConfigId() throws Exception {
                 savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2);
         
                 try {
        -            ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations(
        -                    new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id()));
        +            ListTaskPushNotificationConfigsResult result = getClient().listTaskPushNotificationConfigurations(
        +                    new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id()));
                     assertEquals(2, result.size());
                     assertEquals(TaskPushNotificationConfig.builder(notificationConfig1).taskId(MINIMAL_TASK.id()).build(), result.configs().get(0));
                     assertEquals(TaskPushNotificationConfig.builder(notificationConfig2).taskId(MINIMAL_TASK.id()).build(), result.configs().get(1));
        @@ -1149,7 +1149,7 @@ public void testListPushNotificationConfigWithConfigId() throws Exception {
             }
         
             @Test
        -    public void testListPushNotificationConfigWithoutConfigId() throws Exception {
        +    public void testListPushNotificationConfigsWithoutConfigId() throws Exception {
                 saveTaskInTaskStore(MINIMAL_TASK);
                 TaskPushNotificationConfig notificationConfig1
                         = TaskPushNotificationConfig.builder()
        @@ -1166,8 +1166,8 @@ public void testListPushNotificationConfigWithoutConfigId() throws Exception {
                 // will overwrite the previous one
                 savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2);
                 try {
        -            ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations(
        -                    new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id()));
        +            ListTaskPushNotificationConfigsResult result = getClient().listTaskPushNotificationConfigurations(
        +                    new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id()));
                     assertEquals(1, result.size());
         
                     TaskPushNotificationConfig expectedNotificationConfig = TaskPushNotificationConfig.builder()
        @@ -1185,10 +1185,10 @@ public void testListPushNotificationConfigWithoutConfigId() throws Exception {
             }
         
             @Test
        -    public void testListPushNotificationConfigTaskNotFound() {
        +    public void testListPushNotificationConfigsTaskNotFound() {
                 try {
        -            ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations(
        -                    new ListTaskPushNotificationConfigParams("non-existent-task"));
        +            ListTaskPushNotificationConfigsResult result = getClient().listTaskPushNotificationConfigurations(
        +                    new ListTaskPushNotificationConfigsParams("non-existent-task"));
                     fail();
                 } catch (A2AClientException e) {
                     assertInstanceOf(TaskNotFoundError.class, e.getCause());
        @@ -1196,11 +1196,11 @@ public void testListPushNotificationConfigTaskNotFound() {
             }
         
             @Test
        -    public void testListPushNotificationConfigEmptyList() throws Exception {
        +    public void testListPushNotificationConfigsEmptyList() throws Exception {
                 saveTaskInTaskStore(MINIMAL_TASK);
                 try {
        -            ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations(
        -                    new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id()));
        +            ListTaskPushNotificationConfigsResult result = getClient().listTaskPushNotificationConfigurations(
        +                    new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id()));
                     assertEquals(0, result.size());
                 } catch (Exception e) {
                     fail(e.getMessage());
        @@ -1238,13 +1238,13 @@ public void testDeletePushNotificationConfigWithValidConfigId() throws Exception
                             new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), "config1"));
         
                     // should now be 1 left
        -            ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations(
        -                    new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id()));
        +            ListTaskPushNotificationConfigsResult result = getClient().listTaskPushNotificationConfigurations(
        +                    new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id()));
                     assertEquals(1, result.size());
         
                     // should remain unchanged, this is a different task
                     result = getClient().listTaskPushNotificationConfigurations(
        -                    new ListTaskPushNotificationConfigParams("task-456"));
        +                    new ListTaskPushNotificationConfigsParams("task-456"));
                     assertEquals(1, result.size());
                 } catch (Exception e) {
                     fail(e.getMessage());
        @@ -1278,8 +1278,8 @@ public void testDeletePushNotificationConfigWithNonExistingConfigId() throws Exc
                             new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), "non-existent-config-id"));
         
                     // should remain unchanged
        -            ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations(
        -                    new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id()));
        +            ListTaskPushNotificationConfigsResult result = getClient().listTaskPushNotificationConfigurations(
        +                    new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id()));
                     assertEquals(2, result.size());
                 } catch (Exception e) {
                     fail();
        @@ -1325,8 +1325,8 @@ public void testDeletePushNotificationConfigSetWithoutConfigId() throws Exceptio
                             new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), MINIMAL_TASK.id()));
         
                     // should now be 0
        -            ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations(
        -                    new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id()), null);
        +            ListTaskPushNotificationConfigsResult result = getClient().listTaskPushNotificationConfigurations(
        +                    new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id()), null);
                     assertEquals(0, result.size());
                 } catch (Exception e) {
                     fail();
        diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java
        index 99062f6fe..bea363271 100644
        --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java
        +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java
        @@ -102,7 +102,7 @@ public final class GrpcContextKeys {
              *   
      • SubscribeToTask → SubscribeToTask
      • *
      • CreateTaskPushNotification → CreateTaskPushNotificationConfig
      • *
      • GetTaskPushNotification → GetTaskPushNotificationConfig
      • - *
      • ListTaskPushNotification → ListTaskPushNotificationConfig
      • + *
      • ListTaskPushNotification → ListTaskPushNotificationConfigs
      • *
      • DeleteTaskPushNotification → DeleteTaskPushNotificationConfig
      • * * 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 4d652377c..4eb8c7223 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 @@ -43,8 +43,8 @@ import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.MessageSendParams; import io.a2a.spec.MethodNotFoundError; import io.a2a.spec.PushNotificationNotSupportedError; @@ -329,9 +329,9 @@ public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotification try { ServerCallContext context = createCallContext(responseObserver); - ListTaskPushNotificationConfigParams params = FromProto.listTaskPushNotificationConfigParams(request); - ListTaskPushNotificationConfigResult result = getRequestHandler().onListTaskPushNotificationConfig(params, context); - io.a2a.grpc.ListTaskPushNotificationConfigsResponse response = ToProto.listTaskPushNotificationConfigResponse(result); + ListTaskPushNotificationConfigsParams params = FromProto.listTaskPushNotificationConfigsParams(request); + ListTaskPushNotificationConfigsResult result = getRequestHandler().onListTaskPushNotificationConfigs(params, context); + io.a2a.grpc.ListTaskPushNotificationConfigsResponse response = ToProto.listTaskPushNotificationConfigsResponse(result); responseObserver.onNext(response); responseObserver.onCompleted(); } catch (A2AError e) { diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java index b05417c46..3dfc56685 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java @@ -29,7 +29,7 @@ *
      • {@code CancelTask} - Cancel task execution
      • *
      • {@code GetTaskPushNotificationConfig} - Get push notification config
      • *
      • {@code CreateTaskPushNotificationConfig} - Create push notification config
      • - *
      • {@code ListTaskPushNotificationConfig} - List push notification configs
      • + *
      • {@code ListTaskPushNotificationConfigs} - List push notification configs
      • *
      • {@code DeleteTaskPushNotificationConfig} - Delete push notification config
      • *
      • {@code GetExtendedAgentCard} - Get extended agent card
      • * 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 0e30ac414..ec419f465 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 @@ -48,7 +48,7 @@ import io.a2a.spec.InternalError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.PushNotificationNotSupportedError; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; @@ -571,7 +571,7 @@ public ListTasksResponse onListTasks(ListTasksRequest request, ServerCallContext * { * "jsonrpc": "2.0", * "id": "list-config-123", - * "method": "listTaskPushNotificationConfig", + * "method": "listTaskPushNotificationConfigs", * "params": { * "taskId": "task-456", * "pageSize": 10 @@ -582,17 +582,17 @@ public ListTasksResponse onListTasks(ListTasksRequest request, ServerCallContext * @param request the JSON-RPC request containing task ID and pagination params * @param context the server call context containing authentication and metadata * @return JSON-RPC response with list of configurations - * @see RequestHandler#onListTaskPushNotificationConfig + * @see RequestHandler#onListTaskPushNotificationConfigs */ - public ListTaskPushNotificationConfigsResponse listPushNotificationConfig( + public ListTaskPushNotificationConfigsResponse listPushNotificationConfigs( ListTaskPushNotificationConfigsRequest request, ServerCallContext context) { if ( !agentCard.capabilities().pushNotifications()) { return new ListTaskPushNotificationConfigsResponse(request.getId(), new PushNotificationNotSupportedError()); } try { - ListTaskPushNotificationConfigResult result = - requestHandler.onListTaskPushNotificationConfig(request.getParams(), context); + ListTaskPushNotificationConfigsResult result = + requestHandler.onListTaskPushNotificationConfigs(request.getParams(), context); return new ListTaskPushNotificationConfigsResponse(request.getId(), result); } catch (A2AError e) { return new ListTaskPushNotificationConfigsResponse(request.getId(), e); diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java index 306e94d86..8bd8eeee7 100644 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java +++ b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java @@ -23,7 +23,7 @@ *
      • {@code cancelTask} - Cancel task execution
      • *
      • {@code getTaskPushNotificationConfig} - Get push notification config
      • *
      • {@code setTaskPushNotificationConfig} - Create push notification config
      • - *
      • {@code listTaskPushNotificationConfig} - List push notification configs
      • + *
      • {@code listTaskPushNotificationConfigs} - List push notification configs
      • *
      • {@code deleteTaskPushNotificationConfig} - Delete push notification config
      • * * 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 ac19034e0..72f94404b 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 @@ -61,7 +61,7 @@ import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; import io.a2a.spec.ListTasksParams; import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; @@ -1375,8 +1375,8 @@ public void testListPushNotificationConfig() { .tenant("tenant") .build(); ListTaskPushNotificationConfigsRequest listRequest - = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigsResponse listResponse = handler.listPushNotificationConfig(listRequest, callContext); + = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id())); + ListTaskPushNotificationConfigsResponse listResponse = handler.listPushNotificationConfigs(listRequest, callContext); assertEquals("111", listResponse.getId()); assertEquals(1, listResponse.getResult().size()); @@ -1403,9 +1403,9 @@ public void testListPushNotificationConfigNotSupported() { handler.setPushNotificationConfig(request, callContext); ListTaskPushNotificationConfigsRequest listRequest - = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id())); ListTaskPushNotificationConfigsResponse listResponse - = handler.listPushNotificationConfig(listRequest, callContext); + = handler.listPushNotificationConfigs(listRequest, callContext); assertEquals("111", listResponse.getId()); assertNull(listResponse.getResult()); @@ -1422,9 +1422,9 @@ public void testListPushNotificationConfigNoPushConfigStore() { }; ListTaskPushNotificationConfigsRequest listRequest - = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id())); ListTaskPushNotificationConfigsResponse listResponse - = handler.listPushNotificationConfig(listRequest, callContext); + = handler.listPushNotificationConfigs(listRequest, callContext); assertEquals("111", listResponse.getId()); assertNull(listResponse.getResult()); @@ -1439,9 +1439,9 @@ public void testListPushNotificationConfigTaskNotFound() { }; ListTaskPushNotificationConfigsRequest listRequest - = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); + = new ListTaskPushNotificationConfigsRequest("111", new ListTaskPushNotificationConfigsParams(MINIMAL_TASK.id())); ListTaskPushNotificationConfigsResponse listResponse - = handler.listPushNotificationConfig(listRequest, callContext); + = handler.listPushNotificationConfigs(listRequest, callContext); assertEquals("111", listResponse.getId()); assertNull(listResponse.getResult()); 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 75de9cda4..2de6ce675 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 @@ -49,8 +49,8 @@ import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.ListTasksParams; import io.a2a.spec.MethodNotFoundError; import io.a2a.spec.PushNotificationNotSupportedError; @@ -571,9 +571,9 @@ public HTTPRestResponse listTaskPushNotificationConfigurations(ServerCallContext if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); } - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, pageSize, pageToken, tenant); - ListTaskPushNotificationConfigResult result = requestHandler.onListTaskPushNotificationConfig(params, context); - return createSuccessResponse(200, io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(ProtoUtils.ToProto.listTaskPushNotificationConfigResponse(result))); + ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, pageSize, pageToken, tenant); + ListTaskPushNotificationConfigsResult result = requestHandler.onListTaskPushNotificationConfigs(params, context); + return createSuccessResponse(200, io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(ProtoUtils.ToProto.listTaskPushNotificationConfigsResponse(result))); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { From a73125fc346c6ef0e6e9ed3e8d76ebabfe2e032a Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 12 Mar 2026 22:26:41 +0000 Subject: [PATCH 081/192] =?UTF-8?q?fix:=20Extract=20taskId=20from=20URL=20?= =?UTF-8?q?path=20in=20HTTP+JSON=20CreateTaskPushNotifica=E2=80=A6=20(#734?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …tionConfig Per HTTP+JSON spec with body: "*", taskId should be extracted from the URL path /tasks/{taskId}/pushNotificationConfigs, not required in request body. Fixes #732 --------- Co-authored-by: Claude Sonnet 4.5 --- .../java/io/a2a/transport/rest/handler/RestHandler.java | 7 +++++++ 1 file changed, 7 insertions(+) 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 2de6ce675..b93c964c5 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 @@ -351,7 +351,14 @@ public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContex } io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(body, builder); + + String taskIdFromBody = builder.getTaskId(); + if (!taskIdFromBody.isEmpty() && !taskIdFromBody.equals(taskId)) { + throw new InvalidParamsError("Task ID in request body (" + taskIdFromBody + ") does not match task ID in URL path (" + taskId + ")."); + } + builder.setTenant(tenant); + builder.setTaskId(taskId); TaskPushNotificationConfig result = requestHandler.onCreateTaskPushNotificationConfig(ProtoUtils.FromProto.createTaskPushNotificationConfig(builder), context); return createSuccessResponse(201, io.a2a.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(result))); } catch (A2AError e) { From 26cb3adc0455bab5cb331291e1824cd9e43e762f Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Fri, 13 Mar 2026 11:57:04 +0100 Subject: [PATCH 082/192] fix: update RestErrorMapper to handle RFC 7807 Problem Details error format (#737) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This covers the core fix: the client's RestErrorMapper now reads the type URI from Problem Details responses (introduced by the server-side changes on this branch) instead of the old error/message fields, with backward compatibility for the legacy format. Fixes #727 Fixes #730 🦕 --------- Signed-off-by: Emmanuel Hugonnet --- .../transport/rest/RestErrorMapper.java | 49 ++- .../server/rest/quarkus/A2AServerRoutes.java | 35 +- .../rest/quarkus/A2AServerRoutesTest.java | 60 ++- .../rest/quarkus/QuarkusA2ARestTest.java | 33 ++ .../spec/ContentTypeNotSupportedError.java | 3 + transport/rest/README.md | 355 ++++++++++++++++++ .../transport/rest/handler/RestHandler.java | 242 ++++++++---- .../rest/handler/RestHandlerTest.java | 88 +++-- 8 files changed, 745 insertions(+), 120 deletions(-) create mode 100644 transport/rest/README.md 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 92ce45416..e749070af 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 @@ -36,11 +36,18 @@ public static A2AClientException mapRestError(String body, int code) { try { if (body != null && !body.isBlank()) { JsonObject node = JsonUtil.fromJson(body, JsonObject.class); + // Support RFC 7807 Problem Details format (type, title, details, status) + if (node.has("type")) { + String type = node.get("type").getAsString(); + String errorMessage = node.has("title") ? node.get("title").getAsString() : ""; + return mapRestErrorByType(type, errorMessage, code); + } + // Legacy format (error, message) String className = node.has("error") ? node.get("error").getAsString() : ""; String errorMessage = node.has("message") ? node.get("message").getAsString() : ""; - return mapRestError(className, errorMessage, code); + return mapRestErrorByClassName(className, errorMessage, code); } - return mapRestError("", "", code); + return mapRestErrorByClassName("", "", code); } catch (JsonProcessingException ex) { Logger.getLogger(RestErrorMapper.class.getName()).log(Level.SEVERE, null, ex); return new A2AClientException("Failed to parse error response: " + ex.getMessage()); @@ -48,6 +55,44 @@ public static A2AClientException mapRestError(String body, int code) { } public static A2AClientException mapRestError(String className, String errorMessage, int code) { + return mapRestErrorByClassName(className, errorMessage, code); + } + + /** + * Maps RFC 7807 Problem Details error type URIs to A2A exceptions. + *

        + * Note: Error constructors receive null for code and data parameters because: + *

          + *
        • Error codes are defaulted by each error class (e.g., -32007 for ExtendedAgentCardNotConfiguredError)
        • + *
        • The message comes from the RFC 7807 "title" field
        • + *
        • The data field is optional and not included in basic RFC 7807 responses
        • + *
        + * + * @param type the RFC 7807 error type URI (e.g., "https://a2a-protocol.org/errors/task-not-found") + * @param errorMessage the error message from the "title" field + * @param code the HTTP status code (currently unused, kept for consistency) + * @return an A2AClientException wrapping the appropriate A2A error + */ + private static A2AClientException mapRestErrorByType(String type, String errorMessage, int code) { + return switch (type) { + case "https://a2a-protocol.org/errors/task-not-found" -> new A2AClientException(errorMessage, new TaskNotFoundError()); + case "https://a2a-protocol.org/errors/extended-agent-card-not-configured" -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, null)); + case "https://a2a-protocol.org/errors/content-type-not-supported" -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, errorMessage, null)); + case "https://a2a-protocol.org/errors/internal-error" -> new A2AClientException(errorMessage, new InternalError(errorMessage)); + case "https://a2a-protocol.org/errors/invalid-agent-response" -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, errorMessage, null)); + case "https://a2a-protocol.org/errors/invalid-params" -> new A2AClientException(errorMessage, new InvalidParamsError()); + case "https://a2a-protocol.org/errors/invalid-request" -> new A2AClientException(errorMessage, new InvalidRequestError()); + case "https://a2a-protocol.org/errors/method-not-found" -> new A2AClientException(errorMessage, new MethodNotFoundError()); + case "https://a2a-protocol.org/errors/push-notification-not-supported" -> new A2AClientException(errorMessage, new PushNotificationNotSupportedError()); + case "https://a2a-protocol.org/errors/task-not-cancelable" -> new A2AClientException(errorMessage, new TaskNotCancelableError()); + case "https://a2a-protocol.org/errors/unsupported-operation" -> new A2AClientException(errorMessage, new UnsupportedOperationError()); + case "https://a2a-protocol.org/errors/extension-support-required" -> new A2AClientException(errorMessage, new ExtensionSupportRequiredError(null, errorMessage, null)); + case "https://a2a-protocol.org/errors/version-not-supported" -> new A2AClientException(errorMessage, new VersionNotSupportedError(null, errorMessage, null)); + default -> new A2AClientException(errorMessage); + }; + } + + private static A2AClientException mapRestErrorByClassName(String className, String errorMessage, int code) { return switch (className) { case "io.a2a.spec.TaskNotFoundError" -> new A2AClientException(errorMessage, new TaskNotFoundError()); case "io.a2a.spec.ExtendedCardNotConfiguredError" -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, null)); 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 a2f81e1f7..19399c18a 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 @@ -31,6 +31,7 @@ import io.a2a.server.extensions.A2AExtensions; import io.a2a.server.util.async.Internal; import io.a2a.spec.A2AError; +import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.MethodNotFoundError; @@ -165,8 +166,11 @@ public class A2AServerRoutes { * @param body the JSON request body * @param rc the Vert.x routing context */ - @Route(regex = "^\\/(?[^\\/]*\\/?)message:send$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + @Route(regex = "^\\/(?[^\\/]*\\/?)message:send$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void sendMessage(@Body String body, RoutingContext rc) { + if(!validateContentType(rc)) { + return; + } ServerCallContext context = createCallContext(rc, SEND_MESSAGE_METHOD); HTTPRestResponse response = null; try { @@ -198,8 +202,11 @@ public void sendMessage(@Body String body, RoutingContext rc) { * @param body the JSON request body * @param rc the Vert.x routing context */ - @Route(regex = "^\\/(?[^\\/]*\\/?)message:stream$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + @Route(regex = "^\\/(?[^\\/]*\\/?)message:stream$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void sendMessageStreaming(@Body String body, RoutingContext rc) { + if(!validateContentType(rc)) { + return; + } ServerCallContext context = createCallContext(rc, SEND_STREAMING_MESSAGE_METHOD); HTTPRestStreamingResponse streamingResponse = null; HTTPRestResponse error = null; @@ -339,6 +346,9 @@ public void getTask(RoutingContext rc) { */ @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void cancelTask(@Body String body, RoutingContext rc) { + if (!validateContentType(rc)) { + return; + } String taskId = rc.pathParam("taskId"); ServerCallContext context = createCallContext(rc, CANCEL_TASK_METHOD); HTTPRestResponse response = null; @@ -443,8 +453,11 @@ public void subscribeToTask(RoutingContext rc) { * @param body the JSON request body with notification configuration * @param rc the Vert.x routing context (taskId extracted from path) */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void CreateTaskPushNotificationConfiguration(@Body String body, RoutingContext rc) { + @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) + public void createTaskPushNotificationConfiguration(@Body String body, RoutingContext rc) { + if(!validateContentType(rc)) { + return; + } String taskId = rc.pathParam("taskId"); ServerCallContext context = createCallContext(rc, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); HTTPRestResponse response = null; @@ -597,6 +610,20 @@ private String extractTenant(RoutingContext rc) { return tenantPath; } + /** + * Check if the request content type is application/json. + * @param rc + * @return true if the content type is application/json - false otherwise. + */ + private boolean validateContentType(RoutingContext rc) { + String contentType = rc.request().getHeader(CONTENT_TYPE); + if (contentType == null || !contentType.trim().startsWith(APPLICATION_JSON)) { + sendResponse(rc, jsonRestHandler.createErrorResponse(new ContentTypeNotSupportedError(null, null, null))); + return false; + } + return true; + } + /** * Retrieves the public agent card for agent discovery. * 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 c3bc2e644..80a30e2f6 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 @@ -18,6 +18,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -26,6 +27,7 @@ import jakarta.enterprise.inject.Instance; import io.a2a.server.ServerCallContext; +import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.transport.rest.handler.RestHandler; import io.a2a.transport.rest.handler.RestHandler.HTTPRestResponse; import io.vertx.core.Future; @@ -80,6 +82,7 @@ public void setUp() { when(mockRoutingContext.user()).thenReturn(null); when(mockRequest.headers()).thenReturn(mockHeaders); when(mockRequest.params()).thenReturn(mockParams); + when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("application/json"); when(mockRoutingContext.body()).thenReturn(mockRequestBody); when(mockRequestBody.asString()).thenReturn("{}"); when(mockResponse.setStatusCode(any(Integer.class))).thenReturn(mockResponse); @@ -358,7 +361,7 @@ public void testCreateTaskPushNotificationConfiguration_MethodNameSetInContext() ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); // Act - routes.CreateTaskPushNotificationConfiguration("{}", mockRoutingContext); + routes.createTaskPushNotificationConfiguration("{}", mockRoutingContext); // Assert verify(mockRestHandler).createTaskPushNotificationConfiguration(contextCaptor.capture(), anyString(), eq("{}"), eq("task123")); @@ -438,6 +441,61 @@ public void testDeleteTaskPushNotificationConfiguration_MethodNameSetInContext() assertEquals(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } + @Test + public void testSendMessage_UnsupportedContentType_ReturnsContentTypeNotSupportedError() { + // Arrange + HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); + when(mockErrorResponse.getStatusCode()).thenReturn(415); + when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); + when(mockErrorResponse.getBody()).thenReturn("{\"type\":\"https://a2a-protocol.org/errors/content-type-not-supported\"}"); + when(mockRestHandler.createErrorResponse(any(ContentTypeNotSupportedError.class))).thenReturn(mockErrorResponse); + when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("text/plain"); + + // Act + routes.sendMessage("{}", mockRoutingContext); + + // Assert: createErrorResponse called with ContentTypeNotSupportedError, sendMessage NOT called + verify(mockRestHandler).createErrorResponse(any(ContentTypeNotSupportedError.class)); + verify(mockRestHandler, never()).sendMessage(any(ServerCallContext.class), anyString(), anyString()); + } + + @Test + public void testSendMessageStreaming_UnsupportedContentType_ReturnsContentTypeNotSupportedError() { + // Arrange + HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); + when(mockErrorResponse.getStatusCode()).thenReturn(415); + when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); + when(mockErrorResponse.getBody()).thenReturn("{\"type\":\"https://a2a-protocol.org/errors/content-type-not-supported\"}"); + when(mockRestHandler.createErrorResponse(any(ContentTypeNotSupportedError.class))).thenReturn(mockErrorResponse); + when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("text/plain"); + + // Act + routes.sendMessageStreaming("{}", mockRoutingContext); + + // Assert: createErrorResponse called with ContentTypeNotSupportedError, sendStreamingMessage NOT called + verify(mockRestHandler).createErrorResponse(any(ContentTypeNotSupportedError.class)); + verify(mockRestHandler, never()).sendStreamingMessage(any(ServerCallContext.class), anyString(), anyString()); + } + + @Test + public void testSendMessage_UnsupportedProtocolVersion_ReturnsVersionNotSupportedError() { + // Arrange: content type is OK, but RestHandler returns a VersionNotSupportedError response + HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); + when(mockErrorResponse.getStatusCode()).thenReturn(400); + when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); + when(mockErrorResponse.getBody()).thenReturn("{\"type\":\"https://a2a-protocol.org/errors/version-not-supported\"}"); + when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("application/json"); + when(mockRestHandler.sendMessage(any(ServerCallContext.class), anyString(), anyString())) + .thenReturn(mockErrorResponse); + + // Act + routes.sendMessage("{}", mockRoutingContext); + + // Assert: sendMessage was called and error response forwarded + verify(mockRestHandler).sendMessage(any(ServerCallContext.class), anyString(), eq("{}")); + verify(mockResponse).setStatusCode(400); + } + /** * Helper method to set a field via reflection for testing purposes. */ diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java index 0940c5afc..8e234f9f9 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java +++ b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java @@ -30,6 +30,39 @@ protected String getTransportUrl() { @Override protected abstract void configureTransport(ClientBuilder builder); + @Test + public void testSendMessageWithUnsupportedContentType() throws Exception { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/message:send")) + .POST(HttpRequest.BodyPublishers.ofString("test body")) + .header("Content-Type", "text/plain") + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + Assertions.assertEquals(415, response.statusCode()); + Assertions.assertTrue(response.body().contains("content-type-not-supported"), + "Expected content-type-not-supported in response body: " + response.body()); + } + + @Test + public void testSendMessageWithUnsupportedProtocolVersion() throws Exception { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/message:send")) + .POST(HttpRequest.BodyPublishers.ofString("{}")) + .header("Content-Type", APPLICATION_JSON) + .header("A2A-Version", "0.4.0") + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + Assertions.assertEquals(400, response.statusCode()); + Assertions.assertTrue(response.body().contains("version-not-supported"), + "Expected version-not-supported in response body: " + response.body()); + } + @Test public void testMethodNotFound() throws Exception { // Create the client diff --git a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java index 57a88c17c..cb657967c 100644 --- a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java @@ -40,6 +40,9 @@ */ public class ContentTypeNotSupportedError extends A2AProtocolError { + public ContentTypeNotSupportedError() { + this(null, null, null); + } /** * Constructs a content type not supported error. * diff --git a/transport/rest/README.md b/transport/rest/README.md new file mode 100644 index 000000000..5eef349ec --- /dev/null +++ b/transport/rest/README.md @@ -0,0 +1,355 @@ +# A2A REST Transport + +REST transport implementation for the A2A Protocol, providing HTTP-based (`HTTP+JSON` protocol binding) communication between agents and clients. + +## Overview + +This module implements the REST transport layer for A2A protocol operations. All request and response bodies use [Protobuf JSON](https://protobuf.dev/programming-guides/proto3/#json) serialization (camelCase field names). + +## API Endpoints + +The `{tenant}` path prefix is optional on all endpoints. When omitted, the leading slash is also omitted (e.g., `/message:send` instead of `/{tenant}/message:send`). + +### Send Message + +Sends a message to the agent and blocks until the agent reaches a terminal or interrupted state, or returns immediately if `returnImmediately` is set. + +``` +POST /{tenant}/message:send +Content-Type: application/json +``` + +**Request body** (`SendMessageRequest`): +```json +{ + "message": { + "messageId": "msg-1", + "role": "ROLE_USER", + "parts": [ + {"text": "Hello, what can you do?"} + ], + "contextId": "ctx-1" + }, + "configuration": { + "historyLength": 10, + "returnImmediately": false, + "acceptedOutputModes": ["text/plain"] + } +} +``` + +**Response** — one of: +- `{"task": { ... }}` — a `Task` object when the agent creates/updates a task +- `{"message": { ... }}` — a `Message` object when the agent replies without a task + +--- + +### Send Streaming Message + +Sends a message and streams task updates as Server-Sent Events (SSE). Requires `capabilities.streaming = true` in the agent card. + +``` +POST /{tenant}/message:stream +Content-Type: application/json +Accept: text/event-stream +``` + +Request body is identical to `message:send`. Response is a stream of SSE events: + +``` +: SSE stream started + +id: 0 +data: {"statusUpdate":{"taskId":"task-1","contextId":"ctx-1","status":{"state":"TASK_STATE_WORKING"}}} + +id: 1 +data: {"artifactUpdate":{"taskId":"task-1","contextId":"ctx-1","artifact":{"artifactId":"a-1","parts":[{"text":"Hello!"}]}}} + +id: 2 +data: {"statusUpdate":{"taskId":"task-1","contextId":"ctx-1","status":{"state":"TASK_STATE_COMPLETED"}}} +``` + +Each `data` field contains a JSON-serialized `StreamResponse` with one of the following fields set: +- `task` — full `Task` snapshot +- `message` — a `Message` from the agent +- `statusUpdate` — a `TaskStatusUpdateEvent` +- `artifactUpdate` — a `TaskArtifactUpdateEvent` + +--- + +### Get Task + +Retrieves the current state of a task by ID. + +``` +GET /{tenant}/tasks/{taskId}?historyLength=10 +``` + +| Query parameter | Type | Description | +|-----------------|---------|-----------------------------------------------------------------------------| +| `historyLength` | integer | Maximum number of history messages to include. Omit for no limit; `0` for none. | + +**Response** — a `Task` object: +```json +{ + "id": "task-1", + "contextId": "ctx-1", + "status": { + "state": "TASK_STATE_COMPLETED", + "timestamp": "2023-10-27T10:00:00Z" + }, + "artifacts": [], + "history": [] +} +``` + +--- + +### List Tasks + +Lists tasks with optional filtering and pagination. + +``` +GET /{tenant}/tasks +``` + +| Query parameter | Type | Description | +|------------------------|---------|--------------------------------------------------------------------------------------------| +| `contextId` | string | Filter by context ID. | +| `status` | string | Filter by task state. One of the `TaskState` enum values (e.g. `TASK_STATE_COMPLETED`). | +| `pageSize` | integer | Maximum number of tasks to return (server default: 50, max: 100). | +| `pageToken` | string | Pagination token from a previous `ListTasks` response. | +| `historyLength` | integer | Maximum history messages to include per task. | +| `statusTimestampAfter` | string | ISO-8601 timestamp. Only return tasks whose status was updated at or after this time. | +| `includeArtifacts` | boolean | Whether to include artifacts in results. Defaults to `false`. | + +**Response** (`ListTasksResponse`): +```json +{ + "tasks": [ ... ], + "nextPageToken": "", + "pageSize": 50, + "totalSize": 3 +} +``` + +**`TaskState` values:** + +| Value | Description | +|-------------------------------|--------------------------------------------------| +| `TASK_STATE_SUBMITTED` | Task acknowledged, not yet processing. | +| `TASK_STATE_WORKING` | Task is actively being processed. | +| `TASK_STATE_COMPLETED` | Task finished successfully (terminal). | +| `TASK_STATE_FAILED` | Task finished with an error (terminal). | +| `TASK_STATE_CANCELED` | Task was canceled (terminal). | +| `TASK_STATE_REJECTED` | Agent declined to perform the task (terminal). | +| `TASK_STATE_INPUT_REQUIRED` | Agent needs additional input (interrupted). | +| `TASK_STATE_AUTH_REQUIRED` | Authentication is required to proceed (interrupted). | + +--- + +### Cancel Task + +Requests cancellation of a running task. The agent should transition the task to `TASK_STATE_CANCELED`. + +``` +POST /{tenant}/tasks/{taskId}:cancel +Content-Type: application/json +``` + +Request body is optional (may be empty or contain a `metadata` field). + +**Response** — the updated `Task` object on success. + +--- + +### Subscribe to Task + +Opens an SSE stream to receive real-time updates for an existing task. Requires `capabilities.streaming = true`. Returns `UnsupportedOperationError` if the task is already in a terminal state. + +``` +POST /{tenant}/tasks/{taskId}:subscribe +Accept: text/event-stream +``` + +Response is an SSE stream with the same event format as `message:stream`. + +--- + +### Create Push Notification Config + +Creates a webhook configuration for push notifications on a task. + +``` +POST /{tenant}/tasks/{taskId}/pushNotificationConfigs +Content-Type: application/json +``` + +**Request body** (`TaskPushNotificationConfig`): +```json +{ + "url": "https://example.com/webhook", + "token": "optional-token", + "authentication": { + "scheme": "Bearer", + "credentials": "my-token" + } +} +``` + +**Response** — the created `TaskPushNotificationConfig` with its generated `id`. HTTP 201. + +--- + +### Get Push Notification Config + +``` +GET /{tenant}/tasks/{taskId}/pushNotificationConfigs/{configId} +``` + +**Response** — the `TaskPushNotificationConfig` object. + +--- + +### List Push Notification Configs + +``` +GET /{tenant}/tasks/{taskId}/pushNotificationConfigs +``` + +| Query parameter | Type | Description | +|-----------------|---------|------------------------------------| +| `pageSize` | integer | Maximum configurations to return. | +| `pageToken` | string | Pagination token. | + +**Response** (`ListTaskPushNotificationConfigsResponse`): +```json +{ + "configs": [ ... ], + "nextPageToken": "" +} +``` + +--- + +### Delete Push Notification Config + +``` +DELETE /{tenant}/tasks/{taskId}/pushNotificationConfigs/{configId} +``` + +**Response** — HTTP 204 No Content on success. + +--- + +### Get Agent Card + +Public discovery endpoint. Returns the agent's self-describing manifest. No authentication required. + +``` +GET /.well-known/agent-card.json +``` + +**Response** — an `AgentCard` object: +```json +{ + "name": "My Agent", + "description": "An example agent", + "version": "1.0.0", + "supportedInterfaces": [ ... ], + "capabilities": { + "streaming": true, + "pushNotifications": false + }, + "skills": [ ... ], + "defaultInputModes": ["text/plain"], + "defaultOutputModes": ["text/plain"] +} +``` + +--- + +### Get Extended Agent Card + +Returns additional agent metadata for authenticated clients. Requires `capabilities.extendedAgentCard = true` in the public agent card. + +``` +GET /{tenant}/extendedAgentCard +``` + +**Response** — an `AgentCard` object (same structure as the public card, potentially with additional fields). + +--- + +## Request Headers + +| Header | Description | +|--------------------|-------------------------------------------------------------------------------------------------| +| `X-A2A-Version` | Requested A2A protocol version (e.g., `1.0`). Validated against the agent's supported versions. | +| `X-A2A-Extensions` | Comma-separated list of extension URIs the client supports. Required when the agent declares required extensions. | + +--- + +## Error Handling + +All error responses use [RFC 7807 Problem Details](https://tools.ietf.org/html/rfc7807) with `Content-Type: application/problem+json`. + +```json +{ + "type": "https://a2a-protocol.org/errors/task-not-found", + "title": "Task not found", + "status": 404, + "details": "" +} +``` + +| Field | Type | Description | +|-----------|---------|---------------------------------------------| +| `type` | string | URI identifying the error type. | +| `title` | string | Human-readable summary of the error. | +| `status` | integer | HTTP status code. | +| `details` | string | Additional error context (may be empty). | + +### Error Types + +| `type` URI | HTTP Status | Description | +|----------------------------------------------------------------|-------------|------------------------------------------------------------| +| `https://a2a-protocol.org/errors/task-not-found` | 404 | The requested task does not exist. | +| `https://a2a-protocol.org/errors/method-not-found` | 404 | The endpoint does not exist. | +| `https://a2a-protocol.org/errors/invalid-request` | 400 | Malformed request, missing required fields, or JSON parse error. | +| `https://a2a-protocol.org/errors/invalid-params` | 422 | Invalid parameter values (e.g., negative `historyLength`). | +| `https://a2a-protocol.org/errors/extension-support-required` | 400 | The agent requires an extension the client did not declare.| +| `https://a2a-protocol.org/errors/task-not-cancelable` | 409 | The task cannot be canceled in its current state. | +| `https://a2a-protocol.org/errors/content-type-not-supported` | 415 | The requested content type is not supported. | +| `https://a2a-protocol.org/errors/push-notification-not-supported` | 501 | Push notifications are not configured for this agent. | +| `https://a2a-protocol.org/errors/unsupported-operation` | 501 | The operation is not implemented or not applicable (e.g., subscribing to a finalized task). | +| `https://a2a-protocol.org/errors/version-not-supported` | 400 | The requested protocol version is not supported. | +| `https://a2a-protocol.org/errors/invalid-agent-response` | 502 | The agent produced an invalid response. | +| `https://a2a-protocol.org/errors/extended-agent-card-not-configured` | 400 | The agent does not have an extended agent card configured. | +| `https://a2a-protocol.org/errors/internal-error` | 500 | An unexpected server-side error occurred. | + +--- + +## Client Integration + +The REST client (`client/transport/rest`) automatically maps error responses to typed A2A exceptions. It supports both the current RFC 7807 format and the legacy `{"error": "...", "message": "..."}` format for backward compatibility. + +```java +try { + Task task = client.getTask(new TaskQueryParams("task-123")); +} catch (A2AClientException e) { + if (e.getCause() instanceof TaskNotFoundError) { + // Handle task not found + } else if (e.getCause() instanceof UnsupportedOperationError) { + // Handle unsupported operation + } +} +``` + +--- + +## See Also + +- [A2A Protocol Specification](https://a2a-protocol.org/) +- [RFC 7807 Problem Details](https://tools.ietf.org/html/rfc7807) +- [Protobuf JSON Encoding](https://protobuf.dev/programming-guides/proto3/#json) 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 b93c964c5..8491d9216 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 @@ -26,6 +26,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; import io.a2a.grpc.utils.ProtoUtils; +import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.AgentCardValidator; @@ -71,12 +72,14 @@ /** * REST transport handler for processing A2A protocol requests over HTTP. * - *

        This handler converts HTTP REST requests into A2A protocol operations and + *

        + * This handler converts HTTP REST requests into A2A protocol operations and * manages the lifecycle of agent interactions including message sending, task * management, and push notification configurations. * *

        Request Flow

        - *

        HTTP REST requests flow through this handler to the underlying {@link RequestHandler}, + *

        + * HTTP REST requests flow through this handler to the underlying {@link RequestHandler}, * which coordinates with the agent executor and event queue system: *

          * HTTP Request → RestHandler → RequestHandler → AgentExecutor
        @@ -86,24 +89,26 @@
          *
          * 

        Supported Operations

        *
          - *
        • Message sending (blocking and streaming)
        • - *
        • Task management (get, list, cancel, subscribe)
        • - *
        • Push notification configurations (create, get, list, delete)
        • - *
        • Agent card retrieval (public and extended)
        • + *
        • Message sending (blocking and streaming)
        • + *
        • Task management (get, list, cancel, subscribe)
        • + *
        • Push notification configurations (create, get, list, delete)
        • + *
        • Agent card retrieval (public and extended)
        • *
        * *

        Error Handling

        - *

        All A2A protocol errors are caught and converted to appropriate HTTP status codes + *

        + * All A2A protocol errors are caught and converted to appropriate HTTP status codes * via {@link #mapErrorToHttpStatus(A2AError)}. Protocol version and required extensions * are validated before processing requests. * *

        CDI Integration

        - *

        This handler is an {@code @ApplicationScoped} CDI bean that requires: + *

        + * This handler is an {@code @ApplicationScoped} CDI bean that requires: *

          - *
        • {@link AgentCard} qualified with {@code @PublicAgentCard}
        • - *
        • {@link RequestHandler} for processing A2A operations
        • - *
        • {@link Executor} qualified with {@code @Internal} for async operations
        • - *
        • Optional {@link AgentCard} qualified with {@code @ExtendedAgentCard}
        • + *
        • {@link AgentCard} qualified with {@code @PublicAgentCard}
        • + *
        • {@link RequestHandler} for processing A2A operations
        • + *
        • {@link Executor} qualified with {@code @Internal} for async operations
        • + *
        • Optional {@link AgentCard} qualified with {@code @ExtendedAgentCard}
        • *
        * * @see RequestHandler @@ -117,7 +122,6 @@ public class RestHandler { private static final Logger log = Logger.getLogger(RestHandler.class.getName()); private static final String TASK_STATE_PREFIX = "TASK_STATE_"; - // Fields set by constructor injection cannot be final. We need a noargs constructor for // Jakarta compatibility, and it seems that making fields set by constructor injection // final, is not proxyable in all runtimes @@ -173,12 +177,14 @@ public RestHandler(AgentCard agentCard, RequestHandler requestHandler, Executor /** * Handles a blocking message send request. * - *

        This method processes an HTTP POST request containing a message to be sent to the agent. + *

        + * This method processes an HTTP POST request containing a message to be sent to the agent. * The request is validated for protocol version and required extensions before being forwarded * to the {@link RequestHandler}. The method blocks until the agent produces a terminal event * or requires authentication/input. * - *

        Example Request:

        + *

        + * Example Request:

        *
        {@code
              * POST /v1/tenants/{tenant}/messages
              * Content-Type: application/json
        @@ -192,7 +198,8 @@ public RestHandler(AgentCard agentCard, RequestHandler requestHandler, Executor
              * }
              * }
        * - *

        Example Response:

        + *

        + * Example Response:

        *
        {@code
              * HTTP/1.1 200 OK
              * Content-Type: application/json
        @@ -233,13 +240,16 @@ public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, St
             /**
              * Handles a streaming message send request.
              *
        -     * 

        This method processes an HTTP POST request for streaming responses from the agent. + *

        + * This method processes an HTTP POST request for streaming responses from the agent. * The response is returned as Server-Sent Events (SSE) via {@link HTTPRestStreamingResponse}, * allowing clients to receive task updates and artifacts as they are produced by the agent. * - *

        This method requires the agent card to have {@code capabilities.streaming = true}. + *

        + * This method requires the agent card to have {@code capabilities.streaming = true}. * - *

        Example Request:

        + *

        + * Example Request:

        *
        {@code
              * POST /v1/tenants/{tenant}/messages/stream
              * Content-Type: application/json
        @@ -253,7 +263,8 @@ public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, St
              * }
              * }
        * - *

        Example Streaming Response:

        + *

        + * Example Streaming Response:

        *
        {@code
              * HTTP/1.1 200 OK
              * Content-Type: text/event-stream
        @@ -297,11 +308,13 @@ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String t
             /**
              * Handles a task cancellation request.
              *
        -     * 

        Attempts to cancel a running task identified by the task ID. The cancellation + *

        + * Attempts to cancel a running task identified by the task ID. The cancellation * request is forwarded to the {@link RequestHandler}, which signals the agent executor * to stop processing. The agent should transition the task to {@code CANCELED} state. * - *

        Example Request:

        + *

        + * Example Request:

        *
        {@code
              * POST /v1/tenants/{tenant}/tasks/{taskId}/cancel
              * }
        @@ -312,7 +325,7 @@ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String t * @param taskId the ID of the task to cancel * @return the HTTP response containing the cancelled task * @throws InvalidParamsError if taskId is null or empty - * @see RequestHandler#onCancelTask(CancelTaskParams, ServerCallContext) + * @see RequestHandler#onCancelTask(CancelTaskParams, ServerCallContext) * @see io.a2a.server.agentexecution.AgentExecutor#cancel */ @SuppressWarnings("unchecked") @@ -321,7 +334,7 @@ public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, Str if (taskId == null || taskId.isEmpty()) { throw new InvalidParamsError(); } - Map metadata =JsonUtil.readMetadata(body); + Map metadata = JsonUtil.readMetadata(body); CancelTaskParams params = CancelTaskParams.builder().id(taskId).tenant(tenant).metadata(metadata).build(); Task task = requestHandler.onCancelTask(params, context); if (task != null) { @@ -371,22 +384,26 @@ public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContex /** * Subscribes to task updates via a streaming connection. * - *

        Creates a Server-Sent Events (SSE) stream that delivers real-time updates for an + *

        + * Creates a Server-Sent Events (SSE) stream that delivers real-time updates for an * existing task. This allows clients to reconnect to ongoing or completed tasks and * receive their event history and future updates. * - *

        This method requires the agent card to have {@code capabilities.streaming = true}. + *

        + * This method requires the agent card to have {@code capabilities.streaming = true}. * - *

        Example Request:

        + *

        + * Example Request:

        *
        {@code
              * GET /v1/tenants/{tenant}/tasks/{taskId}/subscribe
              * }
        * - *

        Use Cases:

        + *

        + * Use Cases:

        *
          - *
        • Reconnecting to a task after network interruption
        • - *
        • Monitoring long-running tasks from multiple clients
        • - *
        • Viewing historical events for completed tasks
        • + *
        • Reconnecting to a task after network interruption
        • + *
        • Monitoring long-running tasks from multiple clients
        • + *
        • Viewing historical events for completed tasks
        • *
        * * @param context the server call context containing authentication and metadata @@ -422,17 +439,14 @@ public HTTPRestResponse subscribeToTask(ServerCallContext context, String tenant */ public HTTPRestResponse getTask(ServerCallContext context, String tenant, String taskId, @Nullable Integer historyLength) { try { - TaskQueryParams params; - try { - params = new TaskQueryParams(taskId, historyLength, tenant); - } catch (IllegalArgumentException e) { - throw new InvalidParamsError(e.getMessage()); - } + TaskQueryParams params = new TaskQueryParams(taskId, historyLength, tenant); Task task = requestHandler.onGetTask(params, context); if (task != null) { return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); } throw new TaskNotFoundError(); + } catch (IllegalArgumentException e) { + return createErrorResponse(new InvalidParamsError(e.getMessage())); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { @@ -443,24 +457,27 @@ public HTTPRestResponse getTask(ServerCallContext context, String tenant, String /** * Lists tasks with optional filtering and pagination. * - *

        Retrieves a list of tasks with support for filtering by context, status, and timestamp, + *

        + * Retrieves a list of tasks with support for filtering by context, status, and timestamp, * along with pagination controls. This method is useful for task management dashboards, * monitoring systems, and task history retrieval. * - *

        Example Request:

        + *

        + * Example Request:

        *
        {@code
              * GET /v1/tenants/{tenant}/tasks?status=COMPLETED&pageSize=10&includeArtifacts=true
              * }
        * - *

        Query Parameters:

        + *

        + * Query Parameters:

        *
          - *
        • {@code contextId} - Filter tasks by conversation context
        • - *
        • {@code status} - Filter by task state (SUBMITTED, WORKING, COMPLETED, etc.)
        • - *
        • {@code pageSize} - Maximum tasks to return (for pagination)
        • - *
        • {@code pageToken} - Token for retrieving next page of results
        • - *
        • {@code historyLength} - Maximum history entries to include per task
        • - *
        • {@code statusTimestampAfter} - ISO-8601 timestamp for filtering recent tasks
        • - *
        • {@code includeArtifacts} - Whether to include task artifacts in response
        • + *
        • {@code contextId} - Filter tasks by conversation context
        • + *
        • {@code status} - Filter by task state (SUBMITTED, WORKING, COMPLETED, etc.)
        • + *
        • {@code pageSize} - Maximum tasks to return (for pagination)
        • + *
        • {@code pageToken} - Token for retrieving next page of results
        • + *
        • {@code historyLength} - Maximum history entries to include per task
        • + *
        • {@code statusTimestampAfter} - ISO-8601 timestamp for filtering recent tasks
        • + *
        • {@code includeArtifacts} - Whether to include task artifacts in response
        • *
        * * @param context the server call context containing authentication and metadata @@ -478,10 +495,10 @@ public HTTPRestResponse getTask(ServerCallContext context, String tenant, String * @see TaskState */ public HTTPRestResponse listTasks(ServerCallContext context, String tenant, - @Nullable String contextId, @Nullable String status, - @Nullable Integer pageSize, @Nullable String pageToken, - @Nullable Integer historyLength, @Nullable String statusTimestampAfter, - @Nullable Boolean includeArtifacts) { + @Nullable String contextId, @Nullable String status, + @Nullable Integer pageSize, @Nullable String pageToken, + @Nullable Integer historyLength, @Nullable String statusTimestampAfter, + @Nullable Boolean includeArtifacts) { try { // Build params ListTasksParams.Builder paramsBuilder = ListTasksParams.builder(); @@ -730,22 +747,23 @@ public void onComplete() { /** * Maps A2A protocol errors to HTTP status codes. * - *

        This method ensures consistent HTTP status code mapping for all A2A errors: + *

        + * This method ensures consistent HTTP status code mapping for all A2A errors: *

          - *
        • 400 - Invalid request, JSON parse errors, missing extensions
        • - *
        • 404 - Method not found, task not found
        • - *
        • 409 - Task not cancelable (conflict)
        • - *
        • 415 - Unsupported content type
        • - *
        • 422 - Invalid parameters (unprocessable entity)
        • - *
        • 500 - Internal errors
        • - *
        • 501 - Not implemented (unsupported operations, version)
        • - *
        • 502 - Bad gateway (invalid agent response)
        • + *
        • 400 - Invalid request, JSON parse errors, missing extensions
        • + *
        • 404 - Method not found, task not found
        • + *
        • 409 - Task not cancelable (conflict)
        • + *
        • 415 - Unsupported content type
        • + *
        • 422 - Invalid parameters (unprocessable entity)
        • + *
        • 500 - Internal errors
        • + *
        • 501 - Not implemented (unsupported operations, version)
        • + *
        • 502 - Bad gateway (invalid agent response)
        • *
        * * @param error the A2A error to map * @return the corresponding HTTP status code */ - private int mapErrorToHttpStatus(A2AError error) { + private static int mapErrorToHttpStatus(A2AError error) { if (error instanceof InvalidRequestError || error instanceof JSONParseError) { return 400; } @@ -759,8 +777,7 @@ private int mapErrorToHttpStatus(A2AError error) { return 409; } if (error instanceof PushNotificationNotSupportedError - || error instanceof UnsupportedOperationError - || error instanceof VersionNotSupportedError) { + || error instanceof UnsupportedOperationError) { return 501; } if (error instanceof ContentTypeNotSupportedError) { @@ -770,7 +787,8 @@ private int mapErrorToHttpStatus(A2AError error) { return 502; } if (error instanceof ExtendedAgentCardNotConfiguredError - || error instanceof ExtensionSupportRequiredError) { + || error instanceof ExtensionSupportRequiredError + || error instanceof VersionNotSupportedError) { return 400; } if (error instanceof InternalError) { @@ -779,15 +797,74 @@ private int mapErrorToHttpStatus(A2AError error) { return 500; } + /** + * Maps A2A protocol errors to RFC 7807 Problem Details type URIs. + * + *

        + * This method provides a unique URI for each A2A error type, which is used in the "type" + * field of RFC 7807 error responses. For example: + *

          + *
        • {@link InvalidRequestError} -> "https://a2a-protocol.org/errors/invalid-request"
        • + *
        • {@link TaskNotFoundError} -> "https://a2a-protocol.org/errors/task-not-found"
        • + *
        + * + * @param error the A2A error to map + * @return the corresponding RFC 7807 type URI + */ + private static String mapErrorToURI(A2AError error) { + if (error instanceof InvalidRequestError || error instanceof JSONParseError) { + return "https://a2a-protocol.org/errors/invalid-request"; + } + if (error instanceof InvalidParamsError) { + return "https://a2a-protocol.org/errors/invalid-params"; + } + if (error instanceof MethodNotFoundError) { + return "https://a2a-protocol.org/errors/method-not-found"; + } + if (error instanceof TaskNotFoundError) { + return "https://a2a-protocol.org/errors/task-not-found"; + } + if (error instanceof TaskNotCancelableError) { + return "https://a2a-protocol.org/errors/task-not-cancelable"; + } + if (error instanceof PushNotificationNotSupportedError) { + return "https://a2a-protocol.org/errors/push-notification-not-supported"; + } + if (error instanceof UnsupportedOperationError) { + return "https://a2a-protocol.org/errors/unsupported-operation"; + } + if (error instanceof VersionNotSupportedError) { + return "https://a2a-protocol.org/errors/version-not-supported"; + } + if (error instanceof ContentTypeNotSupportedError) { + return "https://a2a-protocol.org/errors/content-type-not-supported"; + } + if (error instanceof InvalidAgentResponseError) { + return "https://a2a-protocol.org/errors/invalid-agent-response"; + } + if (error instanceof ExtendedAgentCardNotConfiguredError) { + return "https://a2a-protocol.org/errors/extended-agent-card-not-configured"; + } + if (error instanceof ExtensionSupportRequiredError) { + return "https://a2a-protocol.org/errors/extension-support-required"; + } + if (error instanceof InternalError) { + return "https://a2a-protocol.org/errors/internal-error"; + } + return "https://a2a-protocol.org/errors/internal-error"; + } + /** * Retrieves the extended agent card if configured. * - *

        The extended agent card provides additional metadata beyond the public agent card, + *

        + * The extended agent card provides additional metadata beyond the public agent card, * such as tenant-specific configurations or private capabilities. This endpoint requires * the agent card to have {@code capabilities.extendedAgentCard = true} and a CDI-produced * {@code @ExtendedAgentCard} instance. * - *

        Example Request:

        + *

        + * Example Request:

        *
        {@code
              * GET /v1/tenants/{tenant}/extended-agent-card
              * }
        @@ -818,17 +895,20 @@ public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String t /** * Retrieves the public agent card. * - *

        The agent card is a self-describing manifest that provides essential metadata about + *

        + * The agent card is a self-describing manifest that provides essential metadata about * the agent, including its capabilities, supported skills, communication methods, and * security requirements. This is the primary discovery endpoint for clients to understand * what the agent can do and how to interact with it. * - *

        Example Request:

        + *

        + * Example Request:

        *
        {@code
              * GET /v1/agent-card
              * }
        * - *

        Example Response:

        + *

        + * Example Response:

        *
        {@code
              * {
              *   "name": "Weather Agent",
        @@ -942,9 +1022,11 @@ public Flow.Publisher getPublisher() {
              */
             private static class HTTPRestErrorResponse {
         
        -        private final String error;
        -        private final @Nullable
        -        String message;
        +        private final String title;
        +        private final String details;
        +        private final int status;
        +        private final String type;
        +
         
                 /**
                  * Creates an error response from an A2A error.
        @@ -952,17 +1034,25 @@ private static class HTTPRestErrorResponse {
                  * @param jsonRpcError the A2A error
                  */
                 private HTTPRestErrorResponse(A2AError jsonRpcError) {
        -            this.error = jsonRpcError.getClass().getName();
        -            this.message = jsonRpcError.getMessage();
        +            this.title = jsonRpcError.getMessage() == null ? jsonRpcError.getClass().getName() : jsonRpcError.getMessage();
        +            this.details = jsonRpcError.getData() == null ? "" : jsonRpcError.getData().toString();
        +            this.type = mapErrorToURI(jsonRpcError);
        +            this.status = mapErrorToHttpStatus(jsonRpcError);
                 }
         
                 private String toJson() {
        -            return "{\"error\": \"" + error + "\", \"message\": \"" + message + "\"}";
        +            try {
        +                return JsonUtil.toJson(this);
        +            } catch (JsonProcessingException ex) {
        +                log.log(Level.SEVERE, "Failed to serialize HTTPRestErrorResponse to JSON", ex);
        +                return "{\"title\":\"Internal Server Error\",\"details\":\"Failed to serialize error response.\",\"status\":500,\"type\":\"https://a2a-protocol.org/errors/internal-error\"}";
        +            }
                 }
         
                 @Override
                 public String toString() {
        -            return "HTTPRestErrorResponse{" + "error=" + error + ", message=" + message + '}';
        +            return "HTTPRestErrorResponse{" + "title=" + title + ", details=" + details + ", status=" + status + ", type=" + type + '}';
                 }
        +
             }
         }
        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 64c6636e1..738b027e7 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
        @@ -11,6 +11,8 @@
         import java.util.concurrent.TimeUnit;
         import java.util.concurrent.atomic.AtomicBoolean;
         
        +import com.google.gson.JsonObject;
        +import com.google.gson.JsonParser;
         import com.google.protobuf.InvalidProtocolBufferException;
         import io.a2a.server.ServerCallContext;
         import io.a2a.server.auth.UnauthenticatedUser;
        @@ -53,9 +55,8 @@ public void testGetTaskNotFound() {
         
                 RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", "nonexistent", 0);
         
        -        Assertions.assertEquals(404, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("TaskNotFoundError"));
        +        assertProblemDetail(response, 404,
        +                "https://a2a-protocol.org/errors/task-not-found", "Task not found");
             }
         
             @Test
        @@ -64,9 +65,8 @@ public void testGetTaskNegativeHistoryLengthReturns422() {
         
                 RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", MINIMAL_TASK.id(), -1);
         
        -        Assertions.assertEquals(422, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("InvalidParamsError"));
        +        assertProblemDetail(response, 422,
        +                "https://a2a-protocol.org/errors/invalid-params", "Invalid history length");
             }
         
             @Test
        @@ -89,9 +89,8 @@ public void testListTasksInvalidStatus() {
                 RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "not-a-status", null, null,
                         null, null, null);
         
        -        Assertions.assertEquals(422, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("InvalidParamsError"));
        +        assertProblemDetail(response, 422,
        +                "https://a2a-protocol.org/errors/invalid-params", "Invalid params");
             }
         
             @Test
        @@ -132,9 +131,8 @@ public void testSendMessageInvalidBody() {
                 String invalidBody = "invalid json";
                 RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", invalidBody);
         
        -        Assertions.assertEquals(400, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("JSONParseError"),response.getBody());
        +        assertProblemDetail(response, 400,
        +                "https://a2a-protocol.org/errors/invalid-request", "Failed to parse json");
             }
         
             @Test
        @@ -158,7 +156,11 @@ public void testSendMessageWrongValueBody() {
         
                 Assertions.assertEquals(422, response.getStatusCode());
                 Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("InvalidParamsError"));
        +        JsonObject body = JsonParser.parseString(response.getBody()).getAsJsonObject();
        +        Assertions.assertEquals(422, body.get("status").getAsInt());
        +        Assertions.assertEquals("https://a2a-protocol.org/errors/invalid-params", body.get("type").getAsString());
        +        Assertions.assertTrue(body.get("title").getAsString().startsWith("Failed to parse request body:"),
        +                "title should indicate parse failure: " + body.get("title").getAsString());
             }
         
             @Test
        @@ -167,9 +169,8 @@ public void testSendMessageEmptyBody() {
         
                 RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", "");
         
        -        Assertions.assertEquals(400, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("InvalidRequestError"));
        +        assertProblemDetail(response, 400,
        +                "https://a2a-protocol.org/errors/invalid-request", "Request body is required");
             }
         
             @Test
        @@ -200,9 +201,8 @@ public void testCancelTaskNotFound() {
                 String requestBody = "{\"id\":\"nonexistent\"}";
                 RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, "nonexistent");
         
        -        Assertions.assertEquals(404, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("TaskNotFoundError"));
        +        assertProblemDetail(response, 404,
        +                "https://a2a-protocol.org/errors/task-not-found", "Task not found");
             }
         
             @Test
        @@ -346,8 +346,9 @@ public void testSendStreamingMessageNotSupported() {
         
                 RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody);
         
        -        Assertions.assertEquals(400, response.getStatusCode());
        -        Assertions.assertTrue(response.getBody().contains("InvalidRequestError"));
        +        assertProblemDetail(response, 400,
        +                "https://a2a-protocol.org/errors/invalid-request",
        +                "Streaming is not supported by the agent");
             }
         
             @Test
        @@ -387,8 +388,9 @@ public void testPushNotificationConfigNotSupported() {
         
                 RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", requestBody, MINIMAL_TASK.id());
         
        -        Assertions.assertEquals(501, response.getStatusCode());
        -        Assertions.assertTrue(response.getBody().contains("PushNotificationNotSupportedError"));
        +        assertProblemDetail(response, 501,
        +                "https://a2a-protocol.org/errors/push-notification-not-supported",
        +                "Push Notification is not supported");
             }
         
             @Test
        @@ -574,10 +576,9 @@ public void testExtensionSupportRequiredErrorOnSendMessage() {
         
                 RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody);
         
        -        Assertions.assertEquals(400, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("ExtensionSupportRequiredError"));
        -        Assertions.assertTrue(response.getBody().contains("https://example.com/test-extension"));
        +        assertProblemDetail(response, 400,
        +                "https://a2a-protocol.org/errors/extension-support-required",
        +                "Required extension 'https://example.com/test-extension' was not requested by the client");
             }
         
             @Test
        @@ -641,7 +642,9 @@ public void onSubscribe(Flow.Subscription subscription) {
         
                     @Override
                     public void onNext(String item) {
        -                if (item.contains("ExtensionSupportRequiredError") && 
        +                JsonObject error = JsonParser.parseString(item).getAsJsonObject();
        +                if ("https://a2a-protocol.org/errors/extension-support-required".equals(
        +                        error.has("type") ? error.get("type").getAsString() : null) &&
                             item.contains("https://example.com/streaming-extension")) {
                             errorFound.set(true);
                         }
        @@ -774,10 +777,9 @@ public void testVersionNotSupportedErrorOnSendMessage() {
         
                 RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithVersion, "", requestBody);
         
        -        Assertions.assertEquals(501, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("VersionNotSupportedError"));
        -        Assertions.assertTrue(response.getBody().contains("2.0"));
        +        assertProblemDetail(response, 400,
        +                "https://a2a-protocol.org/errors/version-not-supported",
        +                "Protocol version '2.0' is not supported. Supported versions: [1.0]");
             }
         
             @Test
        @@ -843,8 +845,10 @@ public void onSubscribe(Flow.Subscription subscription) {
         
                     @Override
                     public void onNext(String item) {
        -                if (item.contains("VersionNotSupportedError") &&
        -                    item.contains("2.0")) {
        +                JsonObject error = JsonParser.parseString(item).getAsJsonObject();
        +                if ("https://a2a-protocol.org/errors/version-not-supported".equals(
        +                        error.has("type") ? error.get("type").getAsString() : null) &&
        +                    error.has("title") && error.get("title").getAsString().contains("2.0")) {
                             errorFound.set(true);
                         }
                     }
        @@ -979,9 +983,8 @@ public void testListTasksNegativeTimestampReturns422() {
                 RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, null, null, null,
                         null, "-1", null);
         
        -        Assertions.assertEquals(422, response.getStatusCode());
        -        Assertions.assertEquals("application/problem+json", response.getContentType());
        -        Assertions.assertTrue(response.getBody().contains("InvalidParamsError"));
        +        assertProblemDetail(response, 422,
        +                "https://a2a-protocol.org/errors/invalid-params", "Invalid params");
             }
         
             @Test
        @@ -1042,4 +1045,15 @@ public void testListTasksEmptyResultIncludesAllFields() {
                 Assertions.assertTrue(body.contains("\"tasks\":[]") || body.contains("\"tasks\": []"),
                         "tasks should be empty array");
             }
        +
        +    private static void assertProblemDetail(RestHandler.HTTPRestResponse response,
        +                                            int expectedStatus, String expectedType, String expectedTitle) {
        +        Assertions.assertEquals(expectedStatus, response.getStatusCode());
        +        Assertions.assertEquals("application/problem+json", response.getContentType());
        +        JsonObject body = JsonParser.parseString(response.getBody()).getAsJsonObject();
        +        Assertions.assertEquals(expectedStatus, body.get("status").getAsInt(), "status field mismatch");
        +        Assertions.assertEquals(expectedType, body.get("type").getAsString(), "type field mismatch");
        +        Assertions.assertEquals(expectedTitle, body.get("title").getAsString(), "title field mismatch");
        +        Assertions.assertTrue(body.has("details"), "details field should be present");
        +    }
         }
        
        From 4cf98673c919dfb494102f75f7aa786078ae45c2 Mon Sep 17 00:00:00 2001
        From: Kabir Khan 
        Date: Fri, 13 Mar 2026 11:28:41 +0000
        Subject: [PATCH 083/192] feat: add Docker/Podman test utilities for
         conditional test execution (#740)
        
        Add new test-utils-docker module with @RequiresDocker annotation for
        conditional execution of container-based tests.
        
        Features:
        - Detects both Docker and Podman availability
        - Fails tests when containers unavailable (clear error message)
        - Skips tests with -DskipDockerTests=true system property
        - Modules always compile regardless of container availability
        - No Testcontainers dependency (avoids classpath conflicts)
        
        Co-authored-by: Kabir 
        ---
         .../java/io/a2a/test/ExtrasBomVerifier.java   |  9 +-
         .../io/a2a/test/ReferenceBomVerifier.java     |  9 +-
         boms/sdk/pom.xml                              |  6 ++
         .../main/java/io/a2a/test/SdkBomVerifier.java |  9 +-
         .../tests-multi-instance/tests/pom.xml        |  8 ++
         .../MultiInstanceReplicationTest.java         |  4 +-
         .../tests-single-instance/pom.xml             |  7 ++
         .../KafkaReplicationIntegrationTest.java      |  2 +
         .../tests/ReplicatedQueueManagerTest.java     |  2 +
         pom.xml                                       |  6 ++
         test-utils-docker/README.md                   | 90 ++++++++++++++++++
         test-utils-docker/pom.xml                     | 33 +++++++
         .../testutils/docker/DockerAvailability.java  | 91 +++++++++++++++++++
         .../docker/DockerRequiredExtension.java       | 42 +++++++++
         .../a2a/testutils/docker/RequiresDocker.java  | 36 ++++++++
         15 files changed, 341 insertions(+), 13 deletions(-)
         create mode 100644 test-utils-docker/README.md
         create mode 100644 test-utils-docker/pom.xml
         create mode 100644 test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerAvailability.java
         create mode 100644 test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerRequiredExtension.java
         create mode 100644 test-utils-docker/src/main/java/io/a2a/testutils/docker/RequiresDocker.java
        
        diff --git a/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java b/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java
        index 81cd0b855..57fa62d12 100644
        --- a/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java
        +++ b/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java
        @@ -12,10 +12,11 @@
         public class ExtrasBomVerifier extends DynamicBomVerifier {
         
             private static final Set EXTRAS_EXCLUSIONS = Set.of(
        -        "boms/",       // BOM test modules themselves
        -        "examples/",   // Example applications
        -        "tck/",        // TCK test suite
        -        "tests/",      // Integration tests
        +        "boms/",            // BOM test modules themselves
        +        "examples/",        // Example applications
        +        "tck/",             // TCK test suite
        +        "tests/",           // Integration tests
        +        "test-utils-docker/", // Test utilities for Docker-based tests
                 "extras/queue-manager-replicated/tests-multi-instance/",   // Test harness applications
                 "extras/queue-manager-replicated/tests-single-instance/",   // Test harness applications
                 "extras/opentelemetry/integration-tests/"   // Test harness applications
        diff --git a/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java b/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java
        index af73ded93..cb74b0093 100644
        --- a/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java
        +++ b/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java
        @@ -12,10 +12,11 @@
         public class ReferenceBomVerifier extends DynamicBomVerifier {
         
             private static final Set REFERENCE_EXCLUSIONS = Set.of(
        -        "boms/",       // BOM test modules themselves
        -        "examples/",   // Example applications
        -        "tck/",        // TCK test suite
        -        "tests/"       // Integration tests
        +        "boms/",            // BOM test modules themselves
        +        "examples/",        // Example applications
        +        "tck/",             // TCK test suite
        +        "tests/",           // Integration tests
        +        "test-utils-docker/" // Test utilities for Docker-based tests
                 // Note: reference/ is NOT in this list - we want to verify those classes load
             );
         
        diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml
        index c89cdc836..4c21b9e05 100644
        --- a/boms/sdk/pom.xml
        +++ b/boms/sdk/pom.xml
        @@ -109,6 +109,12 @@
                     
         
                     
        +            
        +                ${project.groupId}
        +                a2a-java-test-utils-docker
        +                ${project.version}
        +                test
        +            
                     
                         ${project.groupId}
                         a2a-java-sdk-tests-server-common
        diff --git a/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java b/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java
        index 036626c3f..cf584659c 100644
        --- a/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java
        +++ b/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java
        @@ -12,10 +12,11 @@
         public class SdkBomVerifier extends DynamicBomVerifier {
         
             private static final Set SDK_EXCLUSIONS = Set.of(
        -        "boms/",       // BOM test modules themselves
        -        "examples/",   // Example applications
        -        "tck/",        // TCK test suite
        -        "tests/"       // Integration tests
        +        "boms/",            // BOM test modules themselves
        +        "examples/",        // Example applications
        +        "tck/",             // TCK test suite
        +        "tests/",           // Integration tests
        +        "test-utils-docker/" // Test utilities for Docker-based tests
             );
         
             private static final Set SDK_FORBIDDEN = Set.of(
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        index f3c2491e8..6cdc2ab05 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        @@ -74,6 +74,14 @@
                     logback-classic
                     test
                 
        +
        +        
        +        
        +            io.github.a2asdk
        +            a2a-java-test-utils-docker
        +            test
        +        
        +        
             
         
             
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java
        index 44b8d88b8..4104bdeb7 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java
        +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java
        @@ -31,6 +31,7 @@
         import io.a2a.spec.TaskQueryParams;
         import io.a2a.spec.TaskState;
         import io.a2a.spec.TransportProtocol;
        +import io.a2a.testutils.docker.RequiresDocker;
         import org.junit.jupiter.api.AfterAll;
         import org.junit.jupiter.api.AfterEach;
         import org.junit.jupiter.api.BeforeAll;
        @@ -47,7 +48,7 @@
         /**
          * Multi-instance replication test that validates event queue replication
          * between two running Quarkus instances using Testcontainers.
        - * 
        + *
          * Test Architecture:
          * - Shared KafkaContainer for event replication
          * - Shared PostgreSQLContainer for task persistence
        @@ -55,6 +56,7 @@
          * - A2A Client instances to interact with both applications
          */
         @Testcontainers
        +@RequiresDocker
         public class MultiInstanceReplicationTest {
         
             private static final String KAFKA_IMAGE = "confluentinc/cp-kafka:7.6.1";
        diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml
        index 93c6d88e5..0192e05f6 100644
        --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml
        +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml
        @@ -84,6 +84,13 @@
                     test
                 
         
        +        
        +        
        +            io.github.a2asdk
        +            a2a-java-test-utils-docker
        +            test
        +        
        +
             
         
             
        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 4add5540b..4e298905b 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
        @@ -42,6 +42,7 @@
         import io.a2a.spec.TaskStatus;
         import io.a2a.spec.TaskStatusUpdateEvent;
         import io.a2a.spec.TextPart;
        +import io.a2a.testutils.docker.RequiresDocker;
         import io.quarkus.test.junit.QuarkusTest;
         import org.eclipse.microprofile.reactive.messaging.Channel;
         import org.eclipse.microprofile.reactive.messaging.Emitter;
        @@ -56,6 +57,7 @@
          * Tests the full A2A message flow with Kafka replication verification.
          */
         @QuarkusTest
        +@RequiresDocker
         public class KafkaReplicationIntegrationTest {
         
             private static final Logger LOGGER = LoggerFactory.getLogger(KafkaReplicationIntegrationTest.class);
        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 547a731fd..55d650991 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
        @@ -5,6 +5,7 @@
         import jakarta.inject.Inject;
         
         import io.a2a.extras.queuemanager.replicated.core.ReplicatedQueueManager;
        +import io.a2a.testutils.docker.RequiresDocker;
         import io.a2a.server.events.QueueManager;
         import io.quarkus.test.junit.QuarkusTest;
         import org.junit.jupiter.api.Test;
        @@ -14,6 +15,7 @@
          * For full integration testing with Kafka replication, see KafkaReplicationIntegrationTest.
          */
         @QuarkusTest
        +@RequiresDocker
         public class ReplicatedQueueManagerTest {
         
             @Inject
        diff --git a/pom.xml b/pom.xml
        index 7b94e7b4b..fe927e7c5 100644
        --- a/pom.xml
        +++ b/pom.xml
        @@ -220,6 +220,11 @@
                         a2a-java-sdk-opentelemetry-client-propagation
                         ${project.version}
                     
        +            
        +                io.github.a2asdk
        +                a2a-java-test-utils-docker
        +                ${project.version}
        +            
                     
                         io.grpc
                         grpc-bom
        @@ -566,6 +571,7 @@
                 spec
                 spec-grpc
                 tck
        +        test-utils-docker
                 tests/server-common
                 transport/jsonrpc
                 transport/grpc
        diff --git a/test-utils-docker/README.md b/test-utils-docker/README.md
        new file mode 100644
        index 000000000..0599589b6
        --- /dev/null
        +++ b/test-utils-docker/README.md
        @@ -0,0 +1,90 @@
        +# Docker Test Utilities
        +
        +JUnit 5 utilities for conditional execution of Docker/Podman-based tests.
        +
        +## Overview
        +
        +This module provides a `@RequiresDocker` annotation that conditionally executes tests based on Docker or Podman availability and user preferences. It automatically checks for both Docker and Podman container engines.
        +
        +## Usage
        +
        +Add the dependency to your test module:
        +
        +```xml
        +
        +    io.github.a2asdk
        +    a2a-java-test-utils-docker
        +    test
        +
        +```
        +
        +Annotate test classes that require Docker:
        +
        +```java
        +import io.a2a.testutils.docker.RequiresDocker;
        +import io.quarkus.test.junit.QuarkusTest;
        +import org.junit.jupiter.api.Test;
        +
        +@QuarkusTest
        +@RequiresDocker
        +public class MyDockerBasedTest {
        +
        +    @Test
        +    public void testSomethingWithDocker() {
        +        // Test that requires Docker (e.g., Testcontainers, Quarkus Dev Services)
        +    }
        +}
        +```
        +
        +## Behavior
        +
        +| `-DskipDockerTests` | Docker/Podman Available | Behavior |
        +|---------------------|------------------------|----------|
        +| Not set | ✅ Yes | **RUN** tests normally |
        +| Not set | ❌ No | **ABORT** tests with error message |
        +| `true` | ✅ Yes | **SKIP** tests (shown as disabled) |
        +| `true` | ❌ No | **SKIP** tests (shown as disabled) |
        +
        +## Examples
        +
        +### Run all tests (requires Docker to be running)
        +```bash
        +mvn clean install
        +```
        +
        +### Skip Docker tests when Docker is not available
        +```bash
        +mvn clean install -DskipDockerTests=true
        +```
        +
        +### Expected behavior when Docker is NOT available
        +
        +**Without skip flag:**
        +```bash
        +mvn clean install
        +# Tests ABORT with: "Docker/Podman is not available. Use -DskipDockerTests=true to skip these tests."
        +```
        +
        +**With skip flag:**
        +```bash
        +mvn clean install -DskipDockerTests=true
        +# Tests are SKIPPED, build succeeds
        +# Modules still compile
        +```
        +
        +## Implementation Details
        +
        +- **Container Detection**: Checks for both `docker` and `podman` commands by executing `docker info` or `podman info`
        +- **JUnit 5 Extension**: Implements `ExecutionCondition` to control test execution
        +- **Class-Level Only**: Annotation is applied at the class level (not method level)
        +- **Compilation**: Modules are always compiled regardless of Docker/Podman availability or skip flag
        +- **No External Dependencies**: Uses only Java standard library for container detection (no Testcontainers dependency)
        +
        +## Use Cases
        +
        +This is useful for:
        +- **CI/CD pipelines** where Docker/Podman may not be available
        +- **Local development** when container daemon is not running
        +- **Quarkus Dev Services** tests that automatically start containers
        +- **Testcontainers-based** integration tests
        +- **Podman users** who use Podman instead of Docker
        diff --git a/test-utils-docker/pom.xml b/test-utils-docker/pom.xml
        new file mode 100644
        index 000000000..b35f73a58
        --- /dev/null
        +++ b/test-utils-docker/pom.xml
        @@ -0,0 +1,33 @@
        +
        +
        +    4.0.0
        +
        +    
        +        io.github.a2asdk
        +        a2a-java-sdk-parent
        +        1.0.0.Alpha4-SNAPSHOT
        +        ../pom.xml
        +    
        +
        +    a2a-java-test-utils-docker
        +    A2A Java SDK :: Test Utils :: Docker
        +    Test utilities for conditional Docker-based test execution
        +
        +    
        +        
        +        
        +            org.junit.jupiter
        +            junit-jupiter-api
        +            provided
        +        
        +
        +        
        +        
        +            org.slf4j
        +            slf4j-api
        +            provided
        +        
        +    
        +
        diff --git a/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerAvailability.java b/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerAvailability.java
        new file mode 100644
        index 000000000..3d5b6b4fb
        --- /dev/null
        +++ b/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerAvailability.java
        @@ -0,0 +1,91 @@
        +package io.a2a.testutils.docker;
        +
        +import org.slf4j.Logger;
        +import org.slf4j.LoggerFactory;
        +
        +import java.io.IOException;
        +import java.util.concurrent.TimeUnit;
        +
        +/**
        + * Utility class for checking Docker/Podman availability and test skip settings.
        + */
        +public final class DockerAvailability {
        +
        +    private static final Logger LOG = LoggerFactory.getLogger(DockerAvailability.class);
        +    private static final String SKIP_DOCKER_TESTS_PROPERTY = "skipDockerTests";
        +
        +    private static volatile Boolean dockerAvailable = null;
        +
        +    private DockerAvailability() {
        +        // Utility class
        +    }
        +
        +    /**
        +     * Checks if Docker or Podman is available in the current environment.
        +     * The result is cached after the first check.
        +     *
        +     * @return true if Docker or Podman is available, false otherwise
        +     */
        +    public static boolean isDockerAvailable() {
        +        if (dockerAvailable == null) {
        +            synchronized (DockerAvailability.class) {
        +                if (dockerAvailable == null) {
        +                    dockerAvailable = checkDockerAvailable();
        +                }
        +            }
        +        }
        +        return dockerAvailable;
        +    }
        +
        +    /**
        +     * Checks if Docker tests should be skipped based on the system property.
        +     * Tests are skipped when the system property "skipDockerTests" is set to "true".
        +     *
        +     * @return true if Docker tests should be skipped, false otherwise
        +     */
        +    public static boolean shouldSkipDockerTests() {
        +        return Boolean.parseBoolean(System.getProperty(SKIP_DOCKER_TESTS_PROPERTY, "false"));
        +    }
        +
        +    private static boolean checkDockerAvailable() {
        +        // Try docker first, then podman
        +        if (tryContainerCommand("docker")) {
        +            LOG.info("Docker is available");
        +            return true;
        +        }
        +
        +        if (tryContainerCommand("podman")) {
        +            LOG.info("Podman is available");
        +            return true;
        +        }
        +
        +        LOG.warn("Neither Docker nor Podman is available");
        +        return false;
        +    }
        +
        +    private static boolean tryContainerCommand(String command) {
        +        try {
        +            Process process = new ProcessBuilder(command, "info")
        +                    .redirectOutput(ProcessBuilder.Redirect.DISCARD)
        +                    .redirectError(ProcessBuilder.Redirect.DISCARD)
        +                    .start();
        +
        +            boolean finished = process.waitFor(5, TimeUnit.SECONDS);
        +            if (!finished) {
        +                LOG.debug("Timeout waiting for '{} info' command, destroying process", command);
        +                process.destroyForcibly();
        +                return false;
        +            }
        +
        +            int exitCode = process.exitValue();
        +            return exitCode == 0;
        +        } catch (IOException e) {
        +            LOG.debug("Failed to execute '{} info' command", command, e);
        +            return false;
        +        } catch (InterruptedException e) {
        +            Thread.currentThread().interrupt();
        +            LOG.debug("Interrupted while waiting for '{} info' command", command, e);
        +            return false;
        +        }
        +    }
        +}
        diff --git a/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerRequiredExtension.java b/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerRequiredExtension.java
        new file mode 100644
        index 000000000..f1b89b160
        --- /dev/null
        +++ b/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerRequiredExtension.java
        @@ -0,0 +1,42 @@
        +package io.a2a.testutils.docker;
        +
        +import org.junit.jupiter.api.extension.ConditionEvaluationResult;
        +import org.junit.jupiter.api.extension.ExecutionCondition;
        +import org.junit.jupiter.api.extension.ExtensionContext;
        +import org.opentest4j.TestAbortedException;
        +
        +/**
        + * JUnit 5 extension that conditionally executes tests based on Docker/Podman availability.
        + * 

        + * Checks for both Docker and Podman container engines. + *

        + * Behavior: + *

          + *
        • If -DskipDockerTests=true: tests are always skipped (regardless of Docker availability)
        • + *
        • If -DskipDockerTests is NOT set and Docker/Podman is available: tests run normally
        • + *
        • If -DskipDockerTests is NOT set and neither is available: tests abort with clear error message
        • + *
        + */ +public class DockerRequiredExtension implements ExecutionCondition { + + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + boolean skipDockerTests = DockerAvailability.shouldSkipDockerTests(); + + // Check skip flag first - if set, always skip regardless of Docker availability + if (skipDockerTests) { + return ConditionEvaluationResult.disabled( + "Docker tests skipped due to -DskipDockerTests=true"); + } + + boolean dockerAvailable = DockerAvailability.isDockerAvailable(); + if (!dockerAvailable) { + // Docker/Podman not available and skip NOT requested - ABORT test + throw new TestAbortedException( + "Docker/Podman is not available. Use -DskipDockerTests=true to skip these tests."); + } + + // Docker/Podman available and skip not requested - RUN test + return ConditionEvaluationResult.enabled("Docker/Podman is available"); + } +} diff --git a/test-utils-docker/src/main/java/io/a2a/testutils/docker/RequiresDocker.java b/test-utils-docker/src/main/java/io/a2a/testutils/docker/RequiresDocker.java new file mode 100644 index 000000000..d34e7104c --- /dev/null +++ b/test-utils-docker/src/main/java/io/a2a/testutils/docker/RequiresDocker.java @@ -0,0 +1,36 @@ +package io.a2a.testutils.docker; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.extension.ExtendWith; + +/** + * Annotation to mark test classes that require Docker or Podman to be available. + *

        + * Checks for both Docker and Podman container engines. + *

        + * When neither Docker nor Podman is available: + *

          + *
        • If -DskipDockerTests=true is set: tests are skipped
        • + *
        • If -DskipDockerTests is not set: tests fail with a clear error message
        • + *
        + *

        + * Example usage: + *

        + * {@code
        + * @QuarkusTest
        + * @RequiresDocker
        + * public class MyDockerTest {
        + *     // Tests that require Docker or Podman
        + * }
        + * }
        + * 
        + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@ExtendWith(DockerRequiredExtension.class) +public @interface RequiresDocker { +} From ab77fd0e7af00babd02807bf880277c27346e8b6 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 13 Mar 2026 11:29:35 +0000 Subject: [PATCH 084/192] docs: Add skill to fix TCK errors (#735) --- .agents/skills/fix-tck-issue/SKILL.md | 323 ++++++++++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 .agents/skills/fix-tck-issue/SKILL.md diff --git a/.agents/skills/fix-tck-issue/SKILL.md b/.agents/skills/fix-tck-issue/SKILL.md new file mode 100644 index 000000000..baf97aba8 --- /dev/null +++ b/.agents/skills/fix-tck-issue/SKILL.md @@ -0,0 +1,323 @@ +--- +name: fix-tck-issue +description: Analyzes and fixes A2A Transport Compatibility Kit (TCK) issues by understanding the specification, reproducing the failure, implementing the fix, and validating it works. +compatibility: Requires gh CLI and mvn +allowed-tools: Bash(gh:*) Bash(mvn:*) Bash(git:*) Bash(curl:*) Read Edit Write Glob Grep WebFetch +--- + +# Fix A2A TCK Compatibility Issue + +## Triggers +- Issue references TCK, compatibility, or transport-specific behavior +- Keywords: "TCK", "compatibility", "HTTP+JSON", "gRPC", "JSON-RPC", "specification", "proto" +- Issue mentions transport layer discrepancies + +## Input +- Issue number from a2aproject/a2a-java repository +- Optional: A2A spec reference (branch/tag/commit, defaults to `main`) + +## Workflow + +### 1. Fetch Issue Details +```bash +gh issue view --repo a2aproject/a2a-java --json title,body,labels,url +``` + +Parse issue to identify: +- Affected transport(s): HTTP+JSON, gRPC, JSON-RPC +- Expected behavior from specification +- Actual behavior (error message, reproducer) +- Specification section references +- **Spec commit checksum** (TCK issues include this in spec URLs) + +### 2. Read Specification (if needed) +TCK issues contain the spec checksum, but reading the spec is helpful if TCK lags behind or for additional context. + +Fetch from https://github.com/a2aproject/A2A with specified ref (use checksum from issue or default to main): +- `specification/grpc/a2a.proto` - for proto definitions and HTTP transcoding +- `docs/specification.md` - for detailed protocol requirements + +Focus on sections referenced in the issue. + +### 3. Analyze Code +Locate relevant code based on transport: +- **HTTP+JSON**: `transport/rest` +- **gRPC**: `transport/grpc` +- **JSON-RPC**: `transport/jsonrpc` + +Identify root cause by comparing: +- What the spec says should happen +- What the code currently does +- Why they differ + +**Optional**: If issue includes a curl/grpcurl reproducer, run it manually to validate the issue is genuine. + +### 4. Determine Affected Transports +**CRITICAL**: If issue doesn't specify a single transport, you MUST create reproducers for ALL affected transports. + +Issue mentions specific transport → Test that one only +Issue generic or mentions "all transports" → Test HTTP+JSON, gRPC, AND JSON-RPC + +### 5. Create Temporary Reproducer(s) +Create test in appropriate module. Choose location based on test complexity: + +**Option A: transport/* modules (Unit Tests)** - Use when: +- Testing handler logic directly +- Need custom AgentCard configuration (e.g., capability flags) +- Simpler to set up specific test conditions +- **HTTP+JSON** → `transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java` +- **gRPC** → `transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java` +- **JSON-RPC** → `transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java` + +**Option B: reference/* modules (Integration Tests)** - Use when: +- Testing full request/response cycle +- Need real server behavior +- Testing with standard agent configuration +- **HTTP+JSON** → `reference/rest/src/test/java/.../` +- **gRPC** → `reference/grpc/src/test/java/.../` +- **JSON-RPC** → `reference/jsonrpc/src/test/java/.../` + +Reproducer requirements: +- Follow the exact scenario from the issue +- Use request format per specification (e.g., NO taskId in body for HTTP+JSON) +- Be named clearly: `test_Issue_Reproducer()` +- Assert the WRONG behavior that issue reports (should fail) + +Example: +```java +@Test +public void test_Issue732_Reproducer() { + // Per spec: taskId should NOT be in request body for HTTP+JSON + String requestBody = """ + { + "id": "my-config-001", + "url": "https://example.com/webhook" + }"""; + + HTTPRestResponse response = handler.createTaskPushNotificationConfiguration( + context, "", requestBody, taskId); + + assertEquals(201, response.getStatusCode()); +} +``` + +### 6. Run Reproducer(s) - Confirm Failure +**CRITICAL**: You MUST run the reproducer and see it FAIL before proceeding to fix. + +For transport/* modules: +```bash +mvn test -Dtest=#test_Issue_Reproducer -pl transport/ +``` + +For reference/* modules: +```bash +mvn test -Dtest=#test_Issue_Reproducer -pl reference/ +``` + +**Required verification (DO NOT SKIP)**: +- ❌ Test MUST fail with the exact error mentioned in the issue +- ❌ Error message, status code, or exception type MUST match issue description +- ❌ If testing multiple transports, ALL reproducers must fail + +**If reproducer doesn't fail as expected**: +- STOP - Do not proceed to fix +- Reassess understanding of the issue +- Check if test conditions match issue scenario +- Verify you're testing the right transport/endpoint + +**Only proceed to step 7 after confirming all reproducers fail correctly.** + +### 7. Implement Fix +Make minimal code changes to fix the root cause. + +**If multiple transports are affected**: Fix ALL of them before proceeding to verification. + +Common patterns: +- **Missing path parameter extraction**: Add `builder.setFieldName(pathParam)` +- **Wrong validation**: Adjust validation logic to match spec +- **Incorrect mapping**: Fix proto/domain conversion +- **Wrong error type**: Return correct error based on failure reason + +### 8. Run Reproducer(s) - Confirm Fix +Run ALL reproducers you created in step 5. + +For transport/* modules: +```bash +mvn test -Dtest=#test_Issue_Reproducer -pl transport/ +``` + +For reference/* modules: +```bash +mvn test -Dtest=#test_Issue_Reproducer -pl reference/ +``` + +**Required verification**: +- ✅ ALL reproducers must now PASS +- ✅ Test output shows expected behavior (correct status, no error, etc.) + +If any reproducer still fails, debug and refine the fix. + +### 9. Verify Backward Compatibility +Run full test suite for ALL modified transport modules to ensure no regressions: + +```bash +mvn test -pl transport/rest,transport/jsonrpc,transport/grpc +``` + +If you also modified reference modules or only created reproducers there: +```bash +mvn test -pl reference/rest,reference/jsonrpc,reference/grpc +``` + +All existing tests must pass. + +### 10. Delete Temporary Reproducer(s) +Remove ALL test methods or files created in step 5. + +If you added a method to existing test class: +- Delete just the `test_Issue_Reproducer()` method + +If you created a new test file: +- Delete the entire file (e.g., `Issue733ReproducerTest.java`) + +### 11. Commit +Add only the impacted files (NOT the temporary reproducers): +```bash +git add +git commit -m "fix: + + + +Applied to . + +Fixes #" +``` + +Example for multi-transport fix: +```bash +git add transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java \ + transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java \ + transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java +git commit -m "fix: Return UnsupportedOperationError when capability is disabled + +Applied to all three transports: HTTP+JSON, JSON-RPC, and gRPC. + +Fixes #733" +``` + +## Common Root Causes + +### HTTP+JSON with `body: "*"` +Proto definition with path parameters and `body: "*"` means: +- Path parameters extracted from URL +- Body contains remaining fields only +- Handler must set path params into builder + +Example proto: +```protobuf +rpc CreateTaskPushNotificationConfig(...) { + option (google.api.http) = { + post: "/tasks/{task_id}/pushNotificationConfigs" + body: "*" + }; +} +``` + +Fix pattern: +```java +// Extract from URL path and set in builder +builder.setTaskId(taskId); +``` + +### Field Validation Errors +"X is required" errors often mean: +- Field should come from URL path, not body +- Handler isn't setting the path parameter +- Check proto's HTTP annotation + +## Test Location Decision Guide + +### transport/* modules (Unit Tests) +**Best for**: +- Testing handler logic with custom configurations +- Issues requiring specific AgentCard capabilities (e.g., streaming=false, extendedAgentCard=false) +- Faster test execution +- More control over test setup + +**Test file locations**: +- `transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java` +- `transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java` +- `transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java` + +### reference/* modules (Integration Tests) +**Best for**: +- Testing full request/response cycles +- Issues related to server behavior +- Testing with standard agent configuration +- Real-world scenario validation + +**Structure**: +``` +reference/ +├── rest/ # HTTP+JSON integration tests +├── grpc/ # gRPC integration tests +└── jsonrpc/ # JSON-RPC integration tests +``` + +## Examples + +### Example 1: Single Transport Issue +Issue #732: CreateTaskPushNotificationConfig required taskId in body (HTTP+JSON only) + +1. ✅ Fetched issue - HTTP+JSON transport, expects taskId from URL + - Issue references spec @ `0833a5f5fd1b715519c0aecf9e3055e3f9f38089` +2. ✅ Read spec - `body: "*"` means taskId from path +3. ✅ Found root cause - RestHandler wasn't setting taskId from path param +4. ✅ Issue specifies HTTP+JSON only - test only that transport +5. ✅ Created reproducer in reference/rest without taskId in body +6. ✅ **Ran reproducer - CONFIRMED FAILURE with 422 status** +7. ✅ Fixed - added `builder.setTaskId(taskId)` to RestHandler +8. ✅ **Ran reproducer - CONFIRMED PASS** +9. ✅ Ran full test suite - all tests pass +10. ✅ Deleted reproducer +11. ✅ Committed (RestHandler.java only) + +### Example 2: Multi-Transport Issue +Issue #733: GetExtendedAgentCard returns wrong error when capability disabled + +1. ✅ Fetched issue - affects all transports (not specified which) + - Issue references spec @ `0833a5f5fd1b715519c0aecf9e3055e3f9f38089` +2. ✅ Read spec - should return UnsupportedOperationError when capability=false +3. ✅ Found root cause - handlers check config before capability +4. ✅ **Issue affects all transports - must test all three** +5. ✅ Created reproducers in transport/rest, transport/jsonrpc, transport/grpc +6. ✅ **Ran all reproducers - CONFIRMED all fail (wrong error type)** +7. ✅ Fixed all three handlers - check capability before config +8. ✅ **Ran all reproducers - CONFIRMED all pass** +9. ✅ Ran full test suite - all tests pass +10. ✅ Deleted all three reproducers +11. ✅ Committed (all three handler files) + +## Critical Success Factors + +### Must Do +- ✅ **ALWAYS run reproducer BEFORE fixing** - Confirms you understand the issue +- ✅ **Test ALL affected transports** - Don't assume single transport unless issue specifies +- ✅ **Confirm exact failure** - Error type, status code, message must match issue +- ✅ **Verify fix with reproducers** - All must pass before proceeding +- ✅ **Delete all reproducers** - Keep test suites clean + +### Best Practices +- a2a.proto and spec are source of truth for compatibility +- Reproducers prove understanding before fixing +- Minimal, targeted fixes are better than broad changes +- Choose test location (transport/* vs reference/*) based on requirements +- Run full test suite to ensure no regressions +- Commit only code changes, never temporary reproducers + +### Common Pitfalls +- ❌ Fixing without running reproducer first +- ❌ Testing only one transport when issue affects multiple +- ❌ Not confirming exact error before proceeding +- ❌ Committing temporary reproducer tests +- ❌ Skipping backward compatibility verification From 7f50a9086f06502dc8165fcb844262addc577633 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 16 Mar 2026 10:04:49 +0000 Subject: [PATCH 085/192] =?UTF-8?q?fix:=20synchronize=20ClientTaskManager?= =?UTF-8?q?=20to=20prevent=20race=20condition=20in=20concu=E2=80=A6=20(#74?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …rrent SSE event processing ClientTaskManager was not thread-safe, causing intermittent test failures when SSE events were delivered concurrently by the HTTP client. The race condition occurred when multiple events (startWork, addArtifact, complete) were emitted rapidly in streaming mode. Without synchronization, concurrent threads could interleave read-modify-write operations on currentTask, resulting in lost updates. Specifically, the artifact update could be overwritten by a status update, leaving the final COMPLETED task with no artifacts. The fast time to failure of the test 0.017s, indicates that the COMPLETED status update was received, and that the latch did not time out. This manifested as intermittent failures in agent-to-agent tests where the test received a COMPLETED task but extractTextFromTask() returned an empty string because the artifact list was empty. Fix: Added synchronized keyword to all ClientTaskManager methods (getCurrentTask, saveTaskEvent variants, updateWithMessage) to ensure atomic processing of events regardless of HTTP client threading behavior. Impact: All client transports (JSON-RPC, gRPC, REST) in streaming mode Validated: 100 consecutive test iterations passed on CI Co-Authored-By: Claude Sonnet 4.5 --- .../src/main/java/io/a2a/client/ClientTaskManager.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java b/client/base/src/main/java/io/a2a/client/ClientTaskManager.java index 0e49fc4f7..e8e88eec4 100644 --- a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java +++ b/client/base/src/main/java/io/a2a/client/ClientTaskManager.java @@ -35,14 +35,14 @@ public ClientTaskManager() { this.contextId = null; } - public Task getCurrentTask() throws A2AClientInvalidStateError { + public synchronized Task getCurrentTask() throws A2AClientInvalidStateError { if (currentTask == null) { throw new A2AClientInvalidStateError("No current task"); } return currentTask; } - public Task saveTaskEvent(Task task) throws A2AClientInvalidArgsError { + public synchronized Task saveTaskEvent(Task task) throws A2AClientInvalidArgsError { if (currentTask != null) { throw new A2AClientInvalidArgsError("Task is already set, create new manager for new tasks."); } @@ -50,7 +50,7 @@ public Task saveTaskEvent(Task task) throws A2AClientInvalidArgsError { return task; } - public Task saveTaskEvent(TaskStatusUpdateEvent taskStatusUpdateEvent) throws A2AClientError { + public synchronized Task saveTaskEvent(TaskStatusUpdateEvent taskStatusUpdateEvent) throws A2AClientError { if (taskId == null) { taskId = taskStatusUpdateEvent.taskId(); } @@ -86,7 +86,7 @@ public Task saveTaskEvent(TaskStatusUpdateEvent taskStatusUpdateEvent) throws A2 return currentTask; } - public Task saveTaskEvent(TaskArtifactUpdateEvent taskArtifactUpdateEvent) { + public synchronized Task saveTaskEvent(TaskArtifactUpdateEvent taskArtifactUpdateEvent) { if (taskId == null) { taskId = taskArtifactUpdateEvent.taskId(); } @@ -113,7 +113,7 @@ public Task saveTaskEvent(TaskArtifactUpdateEvent taskArtifactUpdateEvent) { * @param task the task to update * @return the updated task */ - public Task updateWithMessage(Message message, Task task) { + public synchronized Task updateWithMessage(Message message, Task task) { Task.Builder taskBuilder = Task.builder(task); List history = new ArrayList<>(task.history()); if (task.status().message() != null) { From aa62eb61dc266db792764895a008c55edf719b3b Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 16 Mar 2026 15:40:07 +0000 Subject: [PATCH 086/192] feat!: New permanent groupId: org.a2aproject.sdk (#750) The old io.github.a2asdk was temporary. It was decided to not change the package names. Breaking Change: ------------------ Going forward `org.a2aproject.sdk` will be used as the groupId instead of `io.github.a2asdk` --- .../validate-jbang-versions.groovy | 2 +- .github/workflows/create-github-release.yml | 10 ++-- AGENTS.md | 2 +- README.md | 29 +++-------- RELEASE.md | 6 +-- boms/README.md | 22 ++++----- boms/extras/pom.xml | 4 +- boms/extras/src/it/extras-usage-test/pom.xml | 48 +++++++++---------- boms/reference/pom.xml | 4 +- .../src/it/reference-usage-test/pom.xml | 30 ++++++------ boms/sdk/pom.xml | 4 +- boms/sdk/src/it/sdk-usage-test/pom.xml | 32 ++++++------- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 4 +- client/transport/spi/pom.xml | 4 +- common/pom.xml | 2 +- examples/cloud-deployment/README.md | 8 ++-- examples/cloud-deployment/server/pom.xml | 14 +++--- examples/helloworld/client/pom.xml | 14 +++--- .../examples/helloworld/HelloWorldRunner.java | 12 ++--- examples/helloworld/pom.xml | 4 +- examples/helloworld/server/pom.xml | 12 ++--- extras/common/pom.xml | 2 +- extras/http-client-vertx/README.md | 2 +- extras/http-client-vertx/pom.xml | 2 +- .../opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- .../opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../README.md | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/README.md | 4 +- extras/queue-manager-replicated/core/pom.xml | 8 ++-- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 6 +-- .../tests-multi-instance/pom.xml | 2 +- .../quarkus-app-1/pom.xml | 12 ++--- .../quarkus-app-2/pom.xml | 12 ++--- .../quarkus-common/pom.xml | 6 +-- .../tests-multi-instance/tests/pom.xml | 8 ++-- .../tests-single-instance/pom.xml | 18 +++---- extras/task-store-database-jpa/README.md | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/README.md | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 16 +++---- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- .../a2a/server/grpc/quarkus/package-info.java | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- .../a2a/server/rest/quarkus/package-info.java | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 6 +-- test-utils-docker/README.md | 2 +- test-utils-docker/pom.xml | 2 +- tests/server-common/pom.xml | 8 ++-- transport/grpc/pom.xml | 4 +- transport/jsonrpc/pom.xml | 10 ++-- transport/rest/pom.xml | 10 ++-- update-version.sh | 12 ++--- 70 files changed, 229 insertions(+), 246 deletions(-) diff --git a/.enforcer-scripts/validate-jbang-versions.groovy b/.enforcer-scripts/validate-jbang-versions.groovy index b8f283319..9d7647599 100644 --- a/.enforcer-scripts/validate-jbang-versions.groovy +++ b/.enforcer-scripts/validate-jbang-versions.groovy @@ -14,7 +14,7 @@ if (!jbangFile.exists()) { } def expectedVersion = project.version -def groupPrefix = "//DEPS io.github.a2asdk:" +def groupPrefix = "//DEPS org.a2aproject.sdk:" def success = true jbangFile.eachLine { line -> diff --git a/.github/workflows/create-github-release.yml b/.github/workflows/create-github-release.yml index 15baee6c5..108296fab 100644 --- a/.github/workflows/create-github-release.yml +++ b/.github/workflows/create-github-release.yml @@ -60,19 +60,19 @@ jobs: // Add Maven Central installation instructions releaseNotes += `### Installation\n\n`; releaseNotes += `**Maven**:\n\`\`\`xml\n\n`; - releaseNotes += ` io.github.a2asdk\n`; + releaseNotes += ` org.a2aproject.sdk\n`; releaseNotes += ` a2a-java-sdk-client\n`; releaseNotes += ` ${version}\n`; releaseNotes += `\n\`\`\`\n\n`; releaseNotes += `**Gradle**:\n\`\`\`gradle\n`; - releaseNotes += `implementation 'io.github.a2asdk:a2a-java-sdk-client:${version}'\n`; + releaseNotes += `implementation 'org.a2aproject.sdk:a2a-java-sdk-client:${version}'\n`; releaseNotes += `\`\`\`\n\n`; // Add links releaseNotes += `### Links\n\n`; - releaseNotes += `- [Maven Central](https://central.sonatype.com/artifact/io.github.a2asdk/a2a-java-sdk-parent/${version})\n`; - releaseNotes += `- [JavaDoc](https://javadoc.io/doc/io.github.a2asdk/a2a-java-sdk-parent/${version})\n`; + releaseNotes += `- [Maven Central](https://central.sonatype.com/artifact/org.a2aproject.sdk/a2a-java-sdk-parent/${version})\n`; + releaseNotes += `- [JavaDoc](https://javadoc.io/doc/org.a2aproject.sdk/a2a-java-sdk-parent/${version})\n`; releaseNotes += `- [GitHub](https://github.com/a2aproject/a2a-java/tree/v${version})\n\n`; // Add changelog header @@ -115,7 +115,7 @@ jobs: core.summary .addHeading(`Release v${version} Created`) .addLink('View Release', release.html_url) - .addLink('Maven Central', `https://central.sonatype.com/artifact/io.github.a2asdk/a2a-java-sdk-parent/${version}`) + .addLink('Maven Central', `https://central.sonatype.com/artifact/org.a2aproject.sdk/a2a-java-sdk-parent/${version}`) .write(); } catch (error) { diff --git a/AGENTS.md b/AGENTS.md index 3974c88b7..c6c4c1020 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Project Overview -Java SDK for the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/). Multi-module Maven project (`io.github.a2asdk` group) providing client and server libraries for A2A agent communication over JSON-RPC, gRPC, and REST transports. +Java SDK for the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/). Multi-module Maven project (`org.a2aproject.sdk` group) providing client and server libraries for A2A agent communication over JSON-RPC, gRPC, and REST transports. ## Build diff --git a/README.md b/README.md index 27466f91a..36acab025 100644 --- a/README.md +++ b/README.md @@ -58,11 +58,9 @@ The A2A Java SDK Reference Server implementations support the following transpor To use the reference implementation with the JSON-RPC protocol, add the following dependency to your project: -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* - ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc ${io.a2a.sdk.version} @@ -71,11 +69,9 @@ To use the reference implementation with the JSON-RPC protocol, add the followin To use the reference implementation with the gRPC protocol, add the following dependency to your project: -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* - ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-grpc ${io.a2a.sdk.version} @@ -84,11 +80,9 @@ To use the reference implementation with the gRPC protocol, add the following de To use the reference implementation with the HTTP+JSON/REST protocol, add the following dependency to your project: -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* - ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-rest ${io.a2a.sdk.version} @@ -291,13 +285,9 @@ To make use of the Java `Client`: Adding a dependency on `a2a-java-sdk-client` will provide access to a `ClientBuilder` that you can use to create your A2A `Client`. ----- -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* ----- - ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client ${io.a2a.sdk.version} @@ -311,13 +301,9 @@ By default, the `sdk-client` artifact includes the JSONRPC transport dependency. If you want to use the gRPC transport, you'll need to add a relevant dependency: ----- -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* ----- - ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-grpc ${io.a2a.sdk.version} @@ -327,13 +313,10 @@ If you want to use the gRPC transport, you'll need to add a relevant dependency: If you want to use the HTTP+JSON/REST transport, you'll need to add a relevant dependency: ----- -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* ----- ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-rest ${io.a2a.sdk.version} diff --git a/RELEASE.md b/RELEASE.md index 079a18e94..eeb3a18d1 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -16,7 +16,7 @@ The release process involves: ### Required Accounts & Access - GitHub repository write access to `a2aproject/a2a-java` -- Maven Central account: namespace: `io.github.a2asdk` +- Maven Central account: namespace: `org.a2aproject.sdk` ### Required Secrets (Repository Maintainers) The following secrets must be configured in GitHub repository settings: @@ -140,7 +140,7 @@ Check that artifacts are available: **Maven Central**: ``` -https://central.sonatype.com/artifact/io.github.a2asdk/a2a-java-sdk-parent/0.4.0.Alpha1 +https://central.sonatype.com/artifact/org.a2aproject.sdk/a2a-java-sdk-parent/0.4.0.Alpha1 ``` **GitHub Release**: @@ -184,7 +184,7 @@ Open PR, wait for CI, and merge. ./update-version.sh OLD_VERSION NEW_VERSION # Or manually check: -grep -r "//DEPS io.github.a2asdk:" examples/ +grep -r "//DEPS org.a2aproject.sdk:" examples/ ``` ### GPG signing fails in workflow diff --git a/boms/README.md b/boms/README.md index 79b2639c9..dc6821d51 100644 --- a/boms/README.md +++ b/boms/README.md @@ -14,7 +14,7 @@ The A2A Java SDK provides three BOMs for different use cases: ### SDK BOM (`boms/sdk`) -**Artifact:** `io.github.a2asdk:a2a-java-sdk-bom` +**Artifact:** `org.a2aproject.sdk:a2a-java-sdk-bom` The SDK BOM includes: - All A2A SDK core modules (spec, server, client, transport) @@ -26,7 +26,7 @@ The SDK BOM includes: ### Extras BOM (`boms/extras`) -**Artifact:** `io.github.a2asdk:a2a-java-sdk-extras-bom` +**Artifact:** `org.a2aproject.sdk:a2a-java-sdk-extras-bom` The Extras BOM includes: - Everything from `a2a-java-sdk-bom` (via import) @@ -36,7 +36,7 @@ The Extras BOM includes: ### Reference BOM (`boms/reference`) -**Artifact:** `io.github.a2asdk:a2a-java-sdk-reference-bom` +**Artifact:** `org.a2aproject.sdk:a2a-java-sdk-reference-bom` The Reference BOM includes: - Everything from `a2a-java-sdk-bom` (via import) @@ -56,7 +56,7 @@ Add to your project's `pom.xml`: - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-bom ${io.a2a.sdk.version} pom @@ -68,11 +68,11 @@ Add to your project's `pom.xml`: - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-server-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-jsonrpc @@ -86,7 +86,7 @@ Add to your project's `pom.xml`: - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-extras-bom ${io.a2a.sdk.version} pom @@ -98,11 +98,11 @@ Add to your project's `pom.xml`: - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-server-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-task-store-database-jpa @@ -116,7 +116,7 @@ Add to your project's `pom.xml`: - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-bom ${io.a2a.sdk.version} pom @@ -128,7 +128,7 @@ Add to your project's `pom.xml`: - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 05549454a..64315c32a 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml @@ -111,7 +111,7 @@ invoker.properties - io.github.a2asdk:a2a-java-bom-test-utils:${project.version}:jar + org.a2aproject.sdk:a2a-java-bom-test-utils:${project.version}:jar diff --git a/boms/extras/src/it/extras-usage-test/pom.xml b/boms/extras/src/it/extras-usage-test/pom.xml index 5ec29b3a6..1005ce7d9 100644 --- a/boms/extras/src/it/extras-usage-test/pom.xml +++ b/boms/extras/src/it/extras-usage-test/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.github.a2asdk.it + org.a2aproject.sdk.it extras-bom-usage-test 1.0-SNAPSHOT jar @@ -22,7 +22,7 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-extras-bom @project.version@ pom @@ -34,96 +34,96 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-bom-test-utils @project.version@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-http-client-vertx - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-client - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-client-propagation - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-server - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-task-store-database-jpa - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-push-notification-config-store-database-jpa - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-core - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replication-mp-reactive - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-spec - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-spec-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-server-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-microprofile-config - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-rest - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-rest diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 7a70b7f61..40e0bbfe8 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml @@ -97,7 +97,7 @@ invoker.properties - io.github.a2asdk:a2a-java-bom-test-utils:${project.version}:jar + org.a2aproject.sdk:a2a-java-bom-test-utils:${project.version}:jar diff --git a/boms/reference/src/it/reference-usage-test/pom.xml b/boms/reference/src/it/reference-usage-test/pom.xml index 5e7a500f3..7f21c2e95 100644 --- a/boms/reference/src/it/reference-usage-test/pom.xml +++ b/boms/reference/src/it/reference-usage-test/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.github.a2asdk.it + org.a2aproject.sdk.it reference-bom-usage-test 1.0-SNAPSHOT jar @@ -21,7 +21,7 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-bom @project.version@ pom @@ -33,60 +33,60 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-bom-test-utils @project.version@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-rest - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-spec - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-spec-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-server-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-microprofile-config - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-rest - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-jsonrpc diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index 4c21b9e05..e5598ffb7 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml @@ -249,7 +249,7 @@ invoker.properties - io.github.a2asdk:a2a-java-bom-test-utils:${project.version}:jar + org.a2aproject.sdk:a2a-java-bom-test-utils:${project.version}:jar diff --git a/boms/sdk/src/it/sdk-usage-test/pom.xml b/boms/sdk/src/it/sdk-usage-test/pom.xml index d1e2388e4..884a62b9e 100644 --- a/boms/sdk/src/it/sdk-usage-test/pom.xml +++ b/boms/sdk/src/it/sdk-usage-test/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.github.a2asdk.it + org.a2aproject.sdk.it sdk-bom-usage-test 1.0-SNAPSHOT jar @@ -22,7 +22,7 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-bom @project.version@ pom @@ -34,72 +34,72 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-bom-test-utils @project.version@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-spec - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-spec-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-server-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-microprofile-config - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-spi - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-rest - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-rest diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 4e67b3374..4bea1ef57 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index 6de5dc8b9..e6a29e257 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 8ca49f274..527db653b 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index f0ffd3407..b8939edbe 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index ecdf7befd..a4057cbbc 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml @@ -39,7 +39,7 @@ a2a-java-sdk-client-transport-spi - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-http-client diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index 393d044d6..1a19f27c7 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml @@ -18,7 +18,7 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-spec diff --git a/common/pom.xml b/common/pom.xml index 9ceff362f..6afa46732 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT diff --git a/examples/cloud-deployment/README.md b/examples/cloud-deployment/README.md index fe146a6e9..8ec47925c 100644 --- a/examples/cloud-deployment/README.md +++ b/examples/cloud-deployment/README.md @@ -545,23 +545,23 @@ From `pom.xml`: ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-task-store-database-jpa - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-core - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replication-mp-reactive diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index a1e080420..5cc51d4d3 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../../pom.xml @@ -19,35 +19,35 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-task-store-database-jpa ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-push-notification-config-store-database-jpa ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-core ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replication-mp-reactive ${project.version} @@ -80,7 +80,7 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client test diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index 73932409c..b525287ac 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-examples-parent 1.0.0.Alpha4-SNAPSHOT @@ -21,27 +21,27 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-jsonrpc-common - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client-transport-rest - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-client - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-client-propagation diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java index 9616b8da6..904e0d221 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha4-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Alpha4-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha4-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha4-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha4-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha4-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha4-SNAPSHOT //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 4401ccbe6..87588e368 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml @@ -27,7 +27,7 @@ import - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 381704fb9..ff360365e 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-examples-parent 1.0.0.Alpha4-SNAPSHOT @@ -17,11 +17,11 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc @@ -30,11 +30,11 @@ provided - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-grpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-rest @@ -75,7 +75,7 @@ opentelemetry - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index 0b829fac0..9d4551333 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/extras/http-client-vertx/README.md b/extras/http-client-vertx/README.md index a1b48afbf..9af9a1cae 100644 --- a/extras/http-client-vertx/README.md +++ b/extras/http-client-vertx/README.md @@ -62,7 +62,7 @@ Add this module to your project's `pom.xml`: ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-http-client-vertx ${a2a.version} diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 38d745f91..b27734568 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index f4a802155..ebd62f3c0 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent 1.0.0.Alpha4-SNAPSHOT diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index e4039385f..67698e6e7 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent 1.0.0.Alpha4-SNAPSHOT diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index 41d3f50eb..d0a50f2eb 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent 1.0.0.Alpha4-SNAPSHOT diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index 14ea7f8f9..342b13350 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent 1.0.0.Alpha4-SNAPSHOT diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 8d8ccd8da..4a154308b 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index 3a7cb44a9..48d9de60b 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent 1.0.0.Alpha4-SNAPSHOT diff --git a/extras/push-notification-config-store-database-jpa/README.md b/extras/push-notification-config-store-database-jpa/README.md index 3e1d49143..52becb117 100644 --- a/extras/push-notification-config-store-database-jpa/README.md +++ b/extras/push-notification-config-store-database-jpa/README.md @@ -12,7 +12,7 @@ Add this module to your project's `pom.xml`: ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-push-notification-config-store-database-jpa ${a2a.version} diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 41bae5d6b..8714d4595 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/extras/queue-manager-replicated/README.md b/extras/queue-manager-replicated/README.md index 8756be0a2..de9f929c1 100644 --- a/extras/queue-manager-replicated/README.md +++ b/extras/queue-manager-replicated/README.md @@ -25,7 +25,7 @@ Add the core replicated queue manager module to your project's `pom.xml`: ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-core ${a2a.version} @@ -39,7 +39,7 @@ You must also include a replication strategy implementation. Currently, we provi ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replication-mp-reactive ${a2a.version} diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index cdb383d52..782fee809 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-parent 1.0.0.Alpha4-SNAPSHOT ../pom.xml @@ -16,17 +16,17 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-server-common ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-jsonrpc-common ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-common ${project.version} diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 7503e1340..dd4430a77 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index e756812f7..81545365d 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-parent 1.0.0.Alpha4-SNAPSHOT ../pom.xml @@ -16,12 +16,12 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-core ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-jsonrpc-common ${project.version} diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index ed8731542..3ea310f06 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-parent 1.0.0.Alpha4-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index c6b46b7a4..bc0024e40 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent 1.0.0.Alpha4-SNAPSHOT ../pom.xml @@ -17,32 +17,32 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-common ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-core ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replication-mp-reactive ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-task-store-database-jpa ${project.version} diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index 39cf7e944..092ca2724 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent 1.0.0.Alpha4-SNAPSHOT ../pom.xml @@ -17,32 +17,32 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-common ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-core ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replication-mp-reactive ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-task-store-database-jpa ${project.version} diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index c1b6d6a6a..4432e2581 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent 1.0.0.Alpha4-SNAPSHOT ../pom.xml @@ -17,13 +17,13 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-spec - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-server-common diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index 6cdc2ab05..55aada4e4 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent 1.0.0.Alpha4-SNAPSHOT ../pom.xml @@ -17,12 +17,12 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client test - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-jsonrpc test @@ -77,7 +77,7 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-test-utils-docker test diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index 0192e05f6..0a1d46419 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-parent 1.0.0.Alpha4-SNAPSHOT ../pom.xml @@ -16,30 +16,30 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replicated-core ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-queue-manager-replication-mp-reactive ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-jsonrpc-common ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-task-store-database-jpa ${project.version} test @@ -57,12 +57,12 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-client test - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-transport-jsonrpc test @@ -86,7 +86,7 @@ - io.github.a2asdk + org.a2aproject.sdk a2a-java-test-utils-docker test diff --git a/extras/task-store-database-jpa/README.md b/extras/task-store-database-jpa/README.md index eb89611bd..117e357dd 100644 --- a/extras/task-store-database-jpa/README.md +++ b/extras/task-store-database-jpa/README.md @@ -12,7 +12,7 @@ Add this module to your project's `pom.xml`: ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-extras-task-store-database-jpa ${a2a.version} diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 9bfbd8a15..78b0b704a 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/http-client/pom.xml b/http-client/pom.xml index 394ab2a0d..bef9bf193 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT diff --git a/integrations/microprofile-config/README.md b/integrations/microprofile-config/README.md index 501a0dd78..48559894d 100644 --- a/integrations/microprofile-config/README.md +++ b/integrations/microprofile-config/README.md @@ -18,7 +18,7 @@ This module provides `MicroProfileConfigProvider`, which integrates with MicroPr ```xml - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-microprofile-config ${io.a2a.sdk.version} diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 1578f5c58..435b1b21a 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index 4ffaaefde..b64d70620 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT diff --git a/pom.xml b/pom.xml index fe927e7c5..3fb8e2794 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT @@ -191,37 +191,37 @@ ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-spring ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-common ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-client ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-server ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-opentelemetry-client-propagation ${project.version} - io.github.a2asdk + org.a2aproject.sdk a2a-java-test-utils-docker ${project.version} diff --git a/reference/common/pom.xml b/reference/common/pom.xml index 1a88d7dd4..fa3978d69 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index 50cf450c3..84c99a8c1 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 - io.github.a2asdk + org.a2aproject.sdk a2a-java-sdk-parent 1.0.0.Alpha4-SNAPSHOT ../../pom.xml diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java index 81f06d914..273eb5586 100644 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java +++ b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java @@ -71,7 +71,7 @@ *

        Add Dependency: *

        {@code
          * 
        - *   io.github.a2asdk
        + *   org.a2aproject.sdk
          *   a2a-java-sdk-reference-grpc
          *   ${a2a.version}
          * 
        diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml
        index 8f4c5fb87..0b7de7043 100644
        --- a/reference/jsonrpc/pom.xml
        +++ b/reference/jsonrpc/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
                 ../../pom.xml
        diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml
        index 412a11239..7fb566423 100644
        --- a/reference/rest/pom.xml
        +++ b/reference/rest/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
                 ../../pom.xml
        diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java
        index 2e76b40eb..dbfa24145 100644
        --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java
        +++ b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java
        @@ -47,7 +47,7 @@
          * 

        Add this module as a dependency to your Quarkus project: *

        {@code
          * 
        - *   io.github.a2asdk
        + *   org.a2aproject.sdk
          *   a2a-java-sdk-reference-rest
          *   ${a2a.version}
          * 
        diff --git a/server-common/pom.xml b/server-common/pom.xml
        index 378337b9d..745845cca 100644
        --- a/server-common/pom.xml
        +++ b/server-common/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
             
        diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml
        index 2aaaf8760..1ad5d0c00 100644
        --- a/spec-grpc/pom.xml
        +++ b/spec-grpc/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
             
        diff --git a/spec/pom.xml b/spec/pom.xml
        index 89a06c9ce..5fe08ac69 100644
        --- a/spec/pom.xml
        +++ b/spec/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
             
        diff --git a/tck/pom.xml b/tck/pom.xml
        index e7f7cefcd..a5d38f38d 100644
        --- a/tck/pom.xml
        +++ b/tck/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
             
        @@ -21,11 +21,11 @@
                     a2a-java-sdk-reference-jsonrpc
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-reference-grpc
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-reference-rest
                 
                 
        diff --git a/test-utils-docker/README.md b/test-utils-docker/README.md
        index 0599589b6..9544fc3e1 100644
        --- a/test-utils-docker/README.md
        +++ b/test-utils-docker/README.md
        @@ -12,7 +12,7 @@ Add the dependency to your test module:
         
         ```xml
         
        -    io.github.a2asdk
        +    org.a2aproject.sdk
             a2a-java-test-utils-docker
             test
         
        diff --git a/test-utils-docker/pom.xml b/test-utils-docker/pom.xml
        index b35f73a58..10368d309 100644
        --- a/test-utils-docker/pom.xml
        +++ b/test-utils-docker/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
                 ../pom.xml
        diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml
        index 5d091ee23..4741518d2 100644
        --- a/tests/server-common/pom.xml
        +++ b/tests/server-common/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
                 ../../pom.xml
        @@ -56,17 +56,17 @@
                     test
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-client-transport-jsonrpc
                     test
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-client-transport-grpc
                     test
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-client-transport-rest
                     test
                 
        diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml
        index a84002823..838856e41 100644
        --- a/transport/grpc/pom.xml
        +++ b/transport/grpc/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
                 ../../pom.xml
        @@ -19,7 +19,7 @@
         
             
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-server-common
                 
                 
        diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml
        index b8a285572..991ee067f 100644
        --- a/transport/jsonrpc/pom.xml
        +++ b/transport/jsonrpc/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
                 ../../pom.xml
        @@ -19,19 +19,19 @@
         
             
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-server-common
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-spec-grpc
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-spec
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-jsonrpc-common
                     ${project.version}
                 
        diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml
        index 4bc82fb52..54926d667 100644
        --- a/transport/rest/pom.xml
        +++ b/transport/rest/pom.xml
        @@ -5,7 +5,7 @@
             4.0.0
         
             
        -        io.github.a2asdk
        +        org.a2aproject.sdk
                 a2a-java-sdk-parent
                 1.0.0.Alpha4-SNAPSHOT
                 ../../pom.xml
        @@ -19,19 +19,19 @@
         
             
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-server-common
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-spec-grpc
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-spec
                 
                 
        -            io.github.a2asdk
        +            org.a2aproject.sdk
                     a2a-java-sdk-jsonrpc-common
                     ${project.version}
                 
        diff --git a/update-version.sh b/update-version.sh
        index 8e7f3d9db..6eb5ffd2b 100755
        --- a/update-version.sh
        +++ b/update-version.sh
        @@ -44,7 +44,7 @@ echo ""
         
         # Find all files to update
         POM_FILES=$(find . -type f -name "pom.xml" | sort)
        -JBANG_FILES=$(find . -type f -name "*.java" -path "*/examples/*" -exec grep -l "//DEPS io.github.a2asdk:" {} \; | sort)
        +JBANG_FILES=$(find . -type f -name "*.java" -path "*/examples/*" -exec grep -l "//DEPS org.a2aproject.sdk:" {} \; | sort)
         
         POM_COUNT=$(echo "$POM_FILES" | wc -l | tr -d ' ')
         JBANG_COUNT=$(echo "$JBANG_FILES" | wc -l | tr -d ' ')
        @@ -69,9 +69,9 @@ if [ "$DRY_RUN" = true ]; then
         
             echo "=== JBang files with version $FROM_VERSION ==="
             for file in $JBANG_FILES; do
        -        if grep -q "//DEPS io.github.a2asdk:.*:$FROM_VERSION" "$file"; then
        +        if grep -q "//DEPS org.a2aproject.sdk:.*:$FROM_VERSION" "$file"; then
                     echo "  📝 $file"
        -            grep -n "//DEPS io.github.a2asdk:.*:$FROM_VERSION" "$file" | sed 's/^/      /'
        +            grep -n "//DEPS org.a2aproject.sdk:.*:$FROM_VERSION" "$file" | sed 's/^/      /'
                 fi
             done
             echo ""
        @@ -107,13 +107,13 @@ echo ""
         # Update JBang files
         echo "Updating JBang script files..."
         for file in $JBANG_FILES; do
        -    if grep -q "//DEPS io.github.a2asdk:.*:$FROM_VERSION" "$file"; then
        +    if grep -q "//DEPS org.a2aproject.sdk:.*:$FROM_VERSION" "$file"; then
                 if [[ "$OSTYPE" == "darwin"* ]]; then
                     # macOS requires empty string after -i
        -            sed -i "" -e "s/\(\/\/DEPS io.github.a2asdk:.*:\)$FROM_VERSION/\1$TO_VERSION/g" "$file"
        +            sed -i "" -e "s/\(\/\/DEPS org.a2aproject.sdk:.*:\)$FROM_VERSION/\1$TO_VERSION/g" "$file"
                 else
                     # Linux doesn't need it
        -            sed -i "s/\(\/\/DEPS io.github.a2asdk:.*:\)$FROM_VERSION/\1$TO_VERSION/g" "$file"
        +            sed -i "s/\(\/\/DEPS org.a2aproject.sdk:.*:\)$FROM_VERSION/\1$TO_VERSION/g" "$file"
                 fi
                 echo "  ✅ $file"
                 UPDATED_JBANGS=$((UPDATED_JBANGS + 1))
        
        From eb7a25c9d4a36f9154491eb01fb9c153f098d050 Mon Sep 17 00:00:00 2001
        From: Kabir Khan 
        Date: Mon, 16 Mar 2026 16:42:46 +0000
        Subject: [PATCH 087/192] chore: Release 1.0.0.Alpha4 (#751)
        
        Main aim is to make sure the automated Maven deploy works with the new
        groupId
        ---
         boms/extras/pom.xml                                  |  2 +-
         boms/reference/pom.xml                               |  2 +-
         boms/sdk/pom.xml                                     |  2 +-
         boms/test-utils/pom.xml                              |  2 +-
         client/base/pom.xml                                  |  2 +-
         client/transport/grpc/pom.xml                        |  2 +-
         client/transport/jsonrpc/pom.xml                     |  2 +-
         client/transport/rest/pom.xml                        |  2 +-
         client/transport/spi/pom.xml                         |  2 +-
         common/pom.xml                                       |  2 +-
         examples/cloud-deployment/server/pom.xml             |  2 +-
         examples/helloworld/client/pom.xml                   |  2 +-
         .../io/a2a/examples/helloworld/HelloWorldRunner.java | 12 ++++++------
         examples/helloworld/pom.xml                          |  2 +-
         examples/helloworld/server/pom.xml                   |  2 +-
         extras/common/pom.xml                                |  2 +-
         extras/http-client-vertx/pom.xml                     |  2 +-
         extras/opentelemetry/client-propagation/pom.xml      |  2 +-
         extras/opentelemetry/client/pom.xml                  |  2 +-
         extras/opentelemetry/common/pom.xml                  |  2 +-
         extras/opentelemetry/integration-tests/pom.xml       |  2 +-
         extras/opentelemetry/pom.xml                         |  2 +-
         extras/opentelemetry/server/pom.xml                  |  2 +-
         .../pom.xml                                          |  2 +-
         extras/queue-manager-replicated/core/pom.xml         |  2 +-
         extras/queue-manager-replicated/pom.xml              |  2 +-
         .../replication-mp-reactive/pom.xml                  |  2 +-
         .../tests-multi-instance/pom.xml                     |  2 +-
         .../tests-multi-instance/quarkus-app-1/pom.xml       |  2 +-
         .../tests-multi-instance/quarkus-app-2/pom.xml       |  2 +-
         .../tests-multi-instance/quarkus-common/pom.xml      |  2 +-
         .../tests-multi-instance/tests/pom.xml               |  2 +-
         .../tests-single-instance/pom.xml                    |  2 +-
         extras/task-store-database-jpa/pom.xml               |  2 +-
         http-client/pom.xml                                  |  2 +-
         integrations/microprofile-config/pom.xml             |  2 +-
         jsonrpc-common/pom.xml                               |  2 +-
         pom.xml                                              |  2 +-
         reference/common/pom.xml                             |  2 +-
         reference/grpc/pom.xml                               |  2 +-
         reference/jsonrpc/pom.xml                            |  2 +-
         reference/rest/pom.xml                               |  2 +-
         server-common/pom.xml                                |  2 +-
         spec-grpc/pom.xml                                    |  2 +-
         spec/pom.xml                                         |  2 +-
         tck/pom.xml                                          |  2 +-
         test-utils-docker/pom.xml                            |  2 +-
         tests/server-common/pom.xml                          |  2 +-
         transport/grpc/pom.xml                               |  2 +-
         transport/jsonrpc/pom.xml                            |  2 +-
         transport/rest/pom.xml                               |  2 +-
         51 files changed, 56 insertions(+), 56 deletions(-)
        
        diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml
        index 64315c32a..672375b25 100644
        --- a/boms/extras/pom.xml
        +++ b/boms/extras/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml
        index 40e0bbfe8..16506180e 100644
        --- a/boms/reference/pom.xml
        +++ b/boms/reference/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml
        index e5598ffb7..204e53e0f 100644
        --- a/boms/sdk/pom.xml
        +++ b/boms/sdk/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml
        index 4bea1ef57..87a6ead67 100644
        --- a/boms/test-utils/pom.xml
        +++ b/boms/test-utils/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/client/base/pom.xml b/client/base/pom.xml
        index e6a29e257..bb609081a 100644
        --- a/client/base/pom.xml
        +++ b/client/base/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-client
        diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml
        index 527db653b..3e9ac437c 100644
        --- a/client/transport/grpc/pom.xml
        +++ b/client/transport/grpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../../pom.xml
             
             a2a-java-sdk-client-transport-grpc
        diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml
        index b8939edbe..225d32f35 100644
        --- a/client/transport/jsonrpc/pom.xml
        +++ b/client/transport/jsonrpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../../pom.xml
             
             a2a-java-sdk-client-transport-jsonrpc
        diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml
        index a4057cbbc..9a9d7c80d 100644
        --- a/client/transport/rest/pom.xml
        +++ b/client/transport/rest/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../../pom.xml
             
             a2a-java-sdk-client-transport-rest
        diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml
        index 1a19f27c7..79d489290 100644
        --- a/client/transport/spi/pom.xml
        +++ b/client/transport/spi/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../../pom.xml
             
             a2a-java-sdk-client-transport-spi
        diff --git a/common/pom.xml b/common/pom.xml
        index 6afa46732..213bd4b24 100644
        --- a/common/pom.xml
        +++ b/common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
             a2a-java-sdk-common
         
        diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml
        index 5cc51d4d3..6a46f3c70 100644
        --- a/examples/cloud-deployment/server/pom.xml
        +++ b/examples/cloud-deployment/server/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../../pom.xml
             
         
        diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml
        index b525287ac..37723ea7d 100644
        --- a/examples/helloworld/client/pom.xml
        +++ b/examples/helloworld/client/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-examples-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
         
             a2a-java-sdk-examples-client
        diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java
        index 904e0d221..9a8acd191 100644
        --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java
        +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java
        @@ -1,12 +1,12 @@
         
         ///usr/bin/env jbang "$0" "$@" ; exit $?
         
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Alpha4-SNAPSHOT
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha4-SNAPSHOT
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha4-SNAPSHOT
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha4-SNAPSHOT
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha4-SNAPSHOT
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha4-SNAPSHOT
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Alpha4
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha4
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha4
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha4
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha4
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha4
         //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0
         //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0
         //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0
        diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml
        index 87588e368..5f33fddd3 100644
        --- a/examples/helloworld/pom.xml
        +++ b/examples/helloworld/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml
        index ff360365e..afad0b661 100644
        --- a/examples/helloworld/server/pom.xml
        +++ b/examples/helloworld/server/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-examples-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
         
             a2a-java-sdk-examples-server
        diff --git a/extras/common/pom.xml b/extras/common/pom.xml
        index 9d4551333..64a844763 100644
        --- a/extras/common/pom.xml
        +++ b/extras/common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml
        index b27734568..7937e0c73 100644
        --- a/extras/http-client-vertx/pom.xml
        +++ b/extras/http-client-vertx/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-http-client-vertx
        diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml
        index ebd62f3c0..9aa7f2401 100644
        --- a/extras/opentelemetry/client-propagation/pom.xml
        +++ b/extras/opentelemetry/client-propagation/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
         
             a2a-java-sdk-opentelemetry-client-propagation
        diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml
        index 67698e6e7..3d899dc4f 100644
        --- a/extras/opentelemetry/client/pom.xml
        +++ b/extras/opentelemetry/client/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
         
             a2a-java-sdk-opentelemetry-client
        diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml
        index d0a50f2eb..f4fbcb903 100644
        --- a/extras/opentelemetry/common/pom.xml
        +++ b/extras/opentelemetry/common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
         
             a2a-java-sdk-opentelemetry-common
        diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml
        index 342b13350..296d10a5e 100644
        --- a/extras/opentelemetry/integration-tests/pom.xml
        +++ b/extras/opentelemetry/integration-tests/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
         
             a2a-java-sdk-opentelemetry-integration-tests
        diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml
        index 4a154308b..76c30113e 100644
        --- a/extras/opentelemetry/pom.xml
        +++ b/extras/opentelemetry/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml
        index 48d9de60b..86c1e0ac0 100644
        --- a/extras/opentelemetry/server/pom.xml
        +++ b/extras/opentelemetry/server/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
         
             a2a-java-sdk-opentelemetry-server
        diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml
        index 8714d4595..9bce57210 100644
        --- a/extras/push-notification-config-store-database-jpa/pom.xml
        +++ b/extras/push-notification-config-store-database-jpa/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-extras-push-notification-config-store-database-jpa
        diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml
        index 782fee809..ef75b9ea8 100644
        --- a/extras/queue-manager-replicated/core/pom.xml
        +++ b/extras/queue-manager-replicated/core/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml
        index dd4430a77..26fc177fc 100644
        --- a/extras/queue-manager-replicated/pom.xml
        +++ b/extras/queue-manager-replicated/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml
        index 81545365d..b2f311d63 100644
        --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml
        +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml
        index 3ea310f06..776a1d559 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml
        index bc0024e40..1b1768e0a 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-tests-multi-instance-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml
        index 092ca2724..2ad4777b2 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-tests-multi-instance-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml
        index 4432e2581..e7af3be18 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-tests-multi-instance-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        index 55aada4e4..22bb2a285 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-tests-multi-instance-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml
        index 0a1d46419..69454d539 100644
        --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml
        +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml
        @@ -6,7 +6,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml
        index 78b0b704a..d58d58653 100644
        --- a/extras/task-store-database-jpa/pom.xml
        +++ b/extras/task-store-database-jpa/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-extras-task-store-database-jpa
        diff --git a/http-client/pom.xml b/http-client/pom.xml
        index bef9bf193..9bf690cfb 100644
        --- a/http-client/pom.xml
        +++ b/http-client/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
             a2a-java-sdk-http-client
         
        diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml
        index 435b1b21a..0c01a8bc7 100644
        --- a/integrations/microprofile-config/pom.xml
        +++ b/integrations/microprofile-config/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-microprofile-config
        diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml
        index b64d70620..023bea96c 100644
        --- a/jsonrpc-common/pom.xml
        +++ b/jsonrpc-common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
             a2a-java-sdk-jsonrpc-common
         
        diff --git a/pom.xml b/pom.xml
        index 3fb8e2794..a241e6262 100644
        --- a/pom.xml
        +++ b/pom.xml
        @@ -6,7 +6,7 @@
         
             org.a2aproject.sdk
             a2a-java-sdk-parent
        -    1.0.0.Alpha4-SNAPSHOT
        +    1.0.0.Alpha4
         
             pom
         
        diff --git a/reference/common/pom.xml b/reference/common/pom.xml
        index fa3978d69..4c1cd9115 100644
        --- a/reference/common/pom.xml
        +++ b/reference/common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-reference-common
        diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml
        index 84c99a8c1..1e6ae57a0 100644
        --- a/reference/grpc/pom.xml
        +++ b/reference/grpc/pom.xml
        @@ -6,7 +6,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
         
        diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml
        index 0b7de7043..44ee95a22 100644
        --- a/reference/jsonrpc/pom.xml
        +++ b/reference/jsonrpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-reference-jsonrpc
        diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml
        index 7fb566423..34d14f9cc 100644
        --- a/reference/rest/pom.xml
        +++ b/reference/rest/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-reference-rest
        diff --git a/server-common/pom.xml b/server-common/pom.xml
        index 745845cca..1c5bf2fc1 100644
        --- a/server-common/pom.xml
        +++ b/server-common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
             a2a-java-sdk-server-common
         
        diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml
        index 1ad5d0c00..c136514b6 100644
        --- a/spec-grpc/pom.xml
        +++ b/spec-grpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
             a2a-java-sdk-spec-grpc
         
        diff --git a/spec/pom.xml b/spec/pom.xml
        index 5fe08ac69..70b1c6a6a 100644
        --- a/spec/pom.xml
        +++ b/spec/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
             a2a-java-sdk-spec
         
        diff --git a/tck/pom.xml b/tck/pom.xml
        index a5d38f38d..0dc845f36 100644
        --- a/tck/pom.xml
        +++ b/tck/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
             
         
             a2a-tck-server
        diff --git a/test-utils-docker/pom.xml b/test-utils-docker/pom.xml
        index 10368d309..e82042b52 100644
        --- a/test-utils-docker/pom.xml
        +++ b/test-utils-docker/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../pom.xml
             
         
        diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml
        index 4741518d2..1b5bb2192 100644
        --- a/tests/server-common/pom.xml
        +++ b/tests/server-common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-tests-server-common
        diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml
        index 838856e41..a025c0f95 100644
        --- a/transport/grpc/pom.xml
        +++ b/transport/grpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-transport-grpc
        diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml
        index 991ee067f..9c862f8f4 100644
        --- a/transport/jsonrpc/pom.xml
        +++ b/transport/jsonrpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-transport-jsonrpc
        diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml
        index 54926d667..5b7568112 100644
        --- a/transport/rest/pom.xml
        +++ b/transport/rest/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4-SNAPSHOT
        +        1.0.0.Alpha4
                 ../../pom.xml
             
             a2a-java-sdk-transport-rest
        
        From 03e4458f7c75b405b6f446873ff674a494ebebe3 Mon Sep 17 00:00:00 2001
        From: Kabir Khan 
        Date: Mon, 16 Mar 2026 17:06:37 +0000
        Subject: [PATCH 088/192] chore: Next Snapshot (#752)
        
        Main aim is to make sure the automated Maven deploy works with the new
        groupId
        ---
         boms/extras/pom.xml                                  |  2 +-
         boms/reference/pom.xml                               |  2 +-
         boms/sdk/pom.xml                                     |  2 +-
         boms/test-utils/pom.xml                              |  2 +-
         client/base/pom.xml                                  |  2 +-
         client/transport/grpc/pom.xml                        |  2 +-
         client/transport/jsonrpc/pom.xml                     |  2 +-
         client/transport/rest/pom.xml                        |  2 +-
         client/transport/spi/pom.xml                         |  2 +-
         common/pom.xml                                       |  2 +-
         examples/cloud-deployment/server/pom.xml             |  2 +-
         examples/helloworld/client/pom.xml                   |  2 +-
         .../io/a2a/examples/helloworld/HelloWorldRunner.java | 12 ++++++------
         examples/helloworld/pom.xml                          |  2 +-
         examples/helloworld/server/pom.xml                   |  2 +-
         extras/common/pom.xml                                |  2 +-
         extras/http-client-vertx/pom.xml                     |  2 +-
         extras/opentelemetry/client-propagation/pom.xml      |  2 +-
         extras/opentelemetry/client/pom.xml                  |  2 +-
         extras/opentelemetry/common/pom.xml                  |  2 +-
         extras/opentelemetry/integration-tests/pom.xml       |  2 +-
         extras/opentelemetry/pom.xml                         |  2 +-
         extras/opentelemetry/server/pom.xml                  |  2 +-
         .../pom.xml                                          |  2 +-
         extras/queue-manager-replicated/core/pom.xml         |  2 +-
         extras/queue-manager-replicated/pom.xml              |  2 +-
         .../replication-mp-reactive/pom.xml                  |  2 +-
         .../tests-multi-instance/pom.xml                     |  2 +-
         .../tests-multi-instance/quarkus-app-1/pom.xml       |  2 +-
         .../tests-multi-instance/quarkus-app-2/pom.xml       |  2 +-
         .../tests-multi-instance/quarkus-common/pom.xml      |  2 +-
         .../tests-multi-instance/tests/pom.xml               |  2 +-
         .../tests-single-instance/pom.xml                    |  2 +-
         extras/task-store-database-jpa/pom.xml               |  2 +-
         http-client/pom.xml                                  |  2 +-
         integrations/microprofile-config/pom.xml             |  2 +-
         jsonrpc-common/pom.xml                               |  2 +-
         pom.xml                                              |  2 +-
         reference/common/pom.xml                             |  2 +-
         reference/grpc/pom.xml                               |  2 +-
         reference/jsonrpc/pom.xml                            |  2 +-
         reference/rest/pom.xml                               |  2 +-
         server-common/pom.xml                                |  2 +-
         spec-grpc/pom.xml                                    |  2 +-
         spec/pom.xml                                         |  2 +-
         tck/pom.xml                                          |  2 +-
         test-utils-docker/pom.xml                            |  2 +-
         tests/server-common/pom.xml                          |  2 +-
         transport/grpc/pom.xml                               |  2 +-
         transport/jsonrpc/pom.xml                            |  2 +-
         transport/rest/pom.xml                               |  2 +-
         51 files changed, 56 insertions(+), 56 deletions(-)
        
        diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml
        index 672375b25..099cf8b7c 100644
        --- a/boms/extras/pom.xml
        +++ b/boms/extras/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml
        index 16506180e..36ef852d9 100644
        --- a/boms/reference/pom.xml
        +++ b/boms/reference/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml
        index 204e53e0f..cbc5fb075 100644
        --- a/boms/sdk/pom.xml
        +++ b/boms/sdk/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml
        index 87a6ead67..f71e33b50 100644
        --- a/boms/test-utils/pom.xml
        +++ b/boms/test-utils/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/client/base/pom.xml b/client/base/pom.xml
        index bb609081a..93daf1a10 100644
        --- a/client/base/pom.xml
        +++ b/client/base/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-client
        diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml
        index 3e9ac437c..45d27e74b 100644
        --- a/client/transport/grpc/pom.xml
        +++ b/client/transport/grpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../../pom.xml
             
             a2a-java-sdk-client-transport-grpc
        diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml
        index 225d32f35..3cea636cb 100644
        --- a/client/transport/jsonrpc/pom.xml
        +++ b/client/transport/jsonrpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../../pom.xml
             
             a2a-java-sdk-client-transport-jsonrpc
        diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml
        index 9a9d7c80d..ea69e52e0 100644
        --- a/client/transport/rest/pom.xml
        +++ b/client/transport/rest/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../../pom.xml
             
             a2a-java-sdk-client-transport-rest
        diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml
        index 79d489290..aaf1dc9f4 100644
        --- a/client/transport/spi/pom.xml
        +++ b/client/transport/spi/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../../pom.xml
             
             a2a-java-sdk-client-transport-spi
        diff --git a/common/pom.xml b/common/pom.xml
        index 213bd4b24..3303b94f4 100644
        --- a/common/pom.xml
        +++ b/common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
             a2a-java-sdk-common
         
        diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml
        index 6a46f3c70..d4850fc2a 100644
        --- a/examples/cloud-deployment/server/pom.xml
        +++ b/examples/cloud-deployment/server/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../../pom.xml
             
         
        diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml
        index 37723ea7d..8d472ebd3 100644
        --- a/examples/helloworld/client/pom.xml
        +++ b/examples/helloworld/client/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-examples-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
         
             a2a-java-sdk-examples-client
        diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java
        index 9a8acd191..e4a52ffdd 100644
        --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java
        +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java
        @@ -1,12 +1,12 @@
         
         ///usr/bin/env jbang "$0" "$@" ; exit $?
         
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Alpha4
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha4
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha4
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha4
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha4
        -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha4
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Beta1-SNAPSHOT
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Beta1-SNAPSHOT
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Beta1-SNAPSHOT
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Beta1-SNAPSHOT
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Beta1-SNAPSHOT
        +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Beta1-SNAPSHOT
         //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0
         //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0
         //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0
        diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml
        index 5f33fddd3..b0d652df3 100644
        --- a/examples/helloworld/pom.xml
        +++ b/examples/helloworld/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml
        index afad0b661..79c06db81 100644
        --- a/examples/helloworld/server/pom.xml
        +++ b/examples/helloworld/server/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-examples-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
         
             a2a-java-sdk-examples-server
        diff --git a/extras/common/pom.xml b/extras/common/pom.xml
        index 64a844763..3f121f0ae 100644
        --- a/extras/common/pom.xml
        +++ b/extras/common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml
        index 7937e0c73..9dfecd261 100644
        --- a/extras/http-client-vertx/pom.xml
        +++ b/extras/http-client-vertx/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-http-client-vertx
        diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml
        index 9aa7f2401..9d09aa7d4 100644
        --- a/extras/opentelemetry/client-propagation/pom.xml
        +++ b/extras/opentelemetry/client-propagation/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
         
             a2a-java-sdk-opentelemetry-client-propagation
        diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml
        index 3d899dc4f..f93398818 100644
        --- a/extras/opentelemetry/client/pom.xml
        +++ b/extras/opentelemetry/client/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
         
             a2a-java-sdk-opentelemetry-client
        diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml
        index f4fbcb903..0c14ecb43 100644
        --- a/extras/opentelemetry/common/pom.xml
        +++ b/extras/opentelemetry/common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
         
             a2a-java-sdk-opentelemetry-common
        diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml
        index 296d10a5e..06f70ff24 100644
        --- a/extras/opentelemetry/integration-tests/pom.xml
        +++ b/extras/opentelemetry/integration-tests/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
         
             a2a-java-sdk-opentelemetry-integration-tests
        diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml
        index 76c30113e..73c393bea 100644
        --- a/extras/opentelemetry/pom.xml
        +++ b/extras/opentelemetry/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml
        index 86c1e0ac0..9b1c69bc9 100644
        --- a/extras/opentelemetry/server/pom.xml
        +++ b/extras/opentelemetry/server/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-opentelemetry-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
         
             a2a-java-sdk-opentelemetry-server
        diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml
        index 9bce57210..c6bdb6f76 100644
        --- a/extras/push-notification-config-store-database-jpa/pom.xml
        +++ b/extras/push-notification-config-store-database-jpa/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-extras-push-notification-config-store-database-jpa
        diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml
        index ef75b9ea8..7a5f06a73 100644
        --- a/extras/queue-manager-replicated/core/pom.xml
        +++ b/extras/queue-manager-replicated/core/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml
        index 26fc177fc..39cbc82c7 100644
        --- a/extras/queue-manager-replicated/pom.xml
        +++ b/extras/queue-manager-replicated/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml
        index b2f311d63..91ea1c53b 100644
        --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml
        +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml
        index 776a1d559..de60e9dea 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml
        index 1b1768e0a..90ff65774 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-tests-multi-instance-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml
        index 2ad4777b2..f0776700b 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-tests-multi-instance-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml
        index e7af3be18..f80647a36 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-tests-multi-instance-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        index 22bb2a285..6a1d8292d 100644
        --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-tests-multi-instance-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml
        index 69454d539..f8c1ca0e5 100644
        --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml
        +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml
        @@ -6,7 +6,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-queue-manager-replicated-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml
        index d58d58653..0332ed906 100644
        --- a/extras/task-store-database-jpa/pom.xml
        +++ b/extras/task-store-database-jpa/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-extras-task-store-database-jpa
        diff --git a/http-client/pom.xml b/http-client/pom.xml
        index 9bf690cfb..af41894f7 100644
        --- a/http-client/pom.xml
        +++ b/http-client/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
             a2a-java-sdk-http-client
         
        diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml
        index 0c01a8bc7..8cf8ddbca 100644
        --- a/integrations/microprofile-config/pom.xml
        +++ b/integrations/microprofile-config/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-microprofile-config
        diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml
        index 023bea96c..5c032c743 100644
        --- a/jsonrpc-common/pom.xml
        +++ b/jsonrpc-common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
             a2a-java-sdk-jsonrpc-common
         
        diff --git a/pom.xml b/pom.xml
        index a241e6262..8078b339a 100644
        --- a/pom.xml
        +++ b/pom.xml
        @@ -6,7 +6,7 @@
         
             org.a2aproject.sdk
             a2a-java-sdk-parent
        -    1.0.0.Alpha4
        +    1.0.0.Beta1-SNAPSHOT
         
             pom
         
        diff --git a/reference/common/pom.xml b/reference/common/pom.xml
        index 4c1cd9115..6cba35a4a 100644
        --- a/reference/common/pom.xml
        +++ b/reference/common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-reference-common
        diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml
        index 1e6ae57a0..b37623553 100644
        --- a/reference/grpc/pom.xml
        +++ b/reference/grpc/pom.xml
        @@ -6,7 +6,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
         
        diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml
        index 44ee95a22..9cf3d567b 100644
        --- a/reference/jsonrpc/pom.xml
        +++ b/reference/jsonrpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-reference-jsonrpc
        diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml
        index 34d14f9cc..9e6375d7d 100644
        --- a/reference/rest/pom.xml
        +++ b/reference/rest/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-reference-rest
        diff --git a/server-common/pom.xml b/server-common/pom.xml
        index 1c5bf2fc1..21f078782 100644
        --- a/server-common/pom.xml
        +++ b/server-common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
             a2a-java-sdk-server-common
         
        diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml
        index c136514b6..bf41e3cc1 100644
        --- a/spec-grpc/pom.xml
        +++ b/spec-grpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
             a2a-java-sdk-spec-grpc
         
        diff --git a/spec/pom.xml b/spec/pom.xml
        index 70b1c6a6a..82dfa2278 100644
        --- a/spec/pom.xml
        +++ b/spec/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
             a2a-java-sdk-spec
         
        diff --git a/tck/pom.xml b/tck/pom.xml
        index 0dc845f36..026715dfb 100644
        --- a/tck/pom.xml
        +++ b/tck/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
             
         
             a2a-tck-server
        diff --git a/test-utils-docker/pom.xml b/test-utils-docker/pom.xml
        index e82042b52..6f8c021bd 100644
        --- a/test-utils-docker/pom.xml
        +++ b/test-utils-docker/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../pom.xml
             
         
        diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml
        index 1b5bb2192..74930c263 100644
        --- a/tests/server-common/pom.xml
        +++ b/tests/server-common/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-tests-server-common
        diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml
        index a025c0f95..718430633 100644
        --- a/transport/grpc/pom.xml
        +++ b/transport/grpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-transport-grpc
        diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml
        index 9c862f8f4..de91da75d 100644
        --- a/transport/jsonrpc/pom.xml
        +++ b/transport/jsonrpc/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-transport-jsonrpc
        diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml
        index 5b7568112..ffcdc2115 100644
        --- a/transport/rest/pom.xml
        +++ b/transport/rest/pom.xml
        @@ -7,7 +7,7 @@
             
                 org.a2aproject.sdk
                 a2a-java-sdk-parent
        -        1.0.0.Alpha4
        +        1.0.0.Beta1-SNAPSHOT
                 ../../pom.xml
             
             a2a-java-sdk-transport-rest
        
        From 4b1bc190f923b4427081368c03287d1a62a4241b Mon Sep 17 00:00:00 2001
        From: Jeff Mesnil 
        Date: Tue, 17 Mar 2026 18:26:00 +0100
        Subject: [PATCH 089/192] chore: update a2a.proto to v1.0.0 tag (#755)
        
        The proto definitions did not change betwee the previous commit
        (601c408) and the v1.0.0 tag.
        
        Update the tracking comment to reference the
        official release tag.
        ---
         spec-grpc/src/main/proto/a2a.proto | 2 +-
         1 file changed, 1 insertion(+), 1 deletion(-)
        
        diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto
        index a24b2943e..4f12d54fb 100644
        --- a/spec-grpc/src/main/proto/a2a.proto
        +++ b/spec-grpc/src/main/proto/a2a.proto
        @@ -9,7 +9,7 @@ import "google/protobuf/empty.proto";
         import "google/protobuf/struct.proto";
         import "google/protobuf/timestamp.proto";
         
        -// From commit 601c408
        +// From tag v1.0.0
         
         option csharp_namespace = "Lf.A2a.V1";
         option go_package = "google.golang.org/lf/a2a/v1";
        
        From df907c6bb123cfd8bcc6ebb037e7d6408c33d1f1 Mon Sep 17 00:00:00 2001
        From: brucearctor <5032356+brucearctor@users.noreply.github.com>
        Date: Tue, 17 Mar 2026 10:28:11 -0700
        Subject: [PATCH 090/192] fix: reject SendMessage to tasks in terminal state
         with UnsupportedOperationError (#746)
        MIME-Version: 1.0
        Content-Type: text/plain; charset=UTF-8
        Content-Transfer-Encoding: 8bit
        
        ## Summary
        
        SendMessage to a task in a terminal state (completed, canceled,
        rejected, failed) succeeds instead of returning
        `UnsupportedOperationError`. Fails on all three transports (JSON-RPC,
        gRPC, HTTP+JSON).
        
        ## Requirement
        
        - ID: CORE-SEND-002
        - Section: 3.1.1 — SendMessage rejects messages to terminal tasks
        - Level: MUST
        
        ## Changes
        
        Added a guard in `DefaultRequestHandler.initMessageSend()`, which is
        invoked by both `onMessageSend` (blocking) and `onMessageSendStream`
        (streaming). The guard checks whether the referenced task is in a final
        state before forwarding the message to `AgentExecutor`:
        
        ```java
        if (task.status().state().isFinal()) {
            throw new UnsupportedOperationError(null,
                "Cannot send message to task " + task.id() +
                " - task is in a terminal state: " + task.status().state(), null);
        }
        ```
        
        ## Tests
        
        Added 5 new tests in `DefaultRequestHandlerTest`:
        - `testSendMessage_ToCompletedTask_ThrowsUnsupportedOperationError`
        - `testSendMessage_ToCanceledTask_ThrowsUnsupportedOperationError`
        - `testSendMessage_ToRejectedTask_ThrowsUnsupportedOperationError`
        - `testSendMessage_ToFailedTask_ThrowsUnsupportedOperationError`
        -
        `testSendMessageStream_ToCompletedTask_ThrowsUnsupportedOperationError`
        (streaming path)
        
        All 11 tests in `DefaultRequestHandlerTest` pass.
        
        This fixes #741
        
        Co-authored-by: brucearctor 
        ---
         .../DefaultRequestHandler.java                |  13 +-
         .../DefaultRequestHandlerTest.java            | 206 ++++++++++++++++--
         2 files changed, 204 insertions(+), 15 deletions(-)
        
        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 fdc6ee11d..5e72d224d 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
        @@ -1001,7 +1001,7 @@ private CompletableFuture cleanupProducer(@Nullable CompletableFuture {
        +            emitter.startWork();
        +            agentStarted.countDown();
        +            try {
        +                agentRelease.await(10, TimeUnit.SECONDS);
        +            } catch (InterruptedException e) {
        +                Thread.currentThread().interrupt();
        +            }
                     emitter.complete();
        -            agentCompleted.countDown();
                 };
         
                 Message initialMessage = Message.builder()
        @@ -534,6 +543,164 @@ void testRejectMismatchingContextId() throws Exception {
                     .parts(new TextPart("initial message"))
                     .build();
         
        +        // returnImmediately=true so onMessageSend returns quickly (on first event)
        +        MessageSendParams initialParams = MessageSendParams.builder()
        +            .message(initialMessage)
        +            .configuration(DEFAULT_CONFIG)
        +            .build();
        +
        +        EventKind result = requestHandler.onMessageSend(initialParams, NULL_CONTEXT);
        +        assertInstanceOf(Task.class, result);
        +        Task task = (Task) result;
        +
        +        // Wait until agent has started (task is in WORKING state, not terminal)
        +        assertTrue(agentStarted.await(5, TimeUnit.SECONDS));
        +
        +        try {
        +            // Act & Assert: Send a follow-up message with matching taskId but wrong contextId
        +            // The task is still WORKING, so the terminal guard does NOT fire.
        +            // The contextId mismatch guard should fire instead.
        +            Message mismatchedMessage = Message.builder()
        +                .messageId("msg-2")
        +                .role(Message.Role.ROLE_USER)
        +                .taskId(task.id())
        +                .contextId("wrong-context-does-not-exist")
        +                .parts(new TextPart("follow-up message"))
        +                .build();
        +
        +            MessageSendParams mismatchedParams = MessageSendParams.builder()
        +                .message(mismatchedMessage)
        +                .configuration(DEFAULT_CONFIG)
        +                .build();
        +
        +            InvalidParamsError error = assertThrows(InvalidParamsError.class,
        +                () -> requestHandler.onMessageSend(mismatchedParams, NULL_CONTEXT));
        +            assertTrue(error.getMessage().contains(task.id()));
        +        } finally {
        +            // Release agent so it completes and doesn't leak
        +            agentRelease.countDown();
        +        }
        +    }
        +
        +    /**
        +     * Helper: creates a task, drives it to the given terminal state, then asserts that a
        +     * follow-up SendMessage to that task throws UnsupportedOperationError (CORE-SEND-002).
        +     */
        +    private void assertSendMessageToTerminalStateThrows(TaskState terminalState) throws Exception {
        +        CountDownLatch agentCompleted = new CountDownLatch(1);
        +
        +        agentExecutorExecute = (context, emitter) -> {
        +            switch (terminalState) {
        +                case TASK_STATE_COMPLETED -> emitter.complete();
        +                case TASK_STATE_CANCELED  -> emitter.cancel();
        +                case TASK_STATE_REJECTED  -> emitter.reject();
        +                // Use fail() (no-arg) which emits TaskStatusUpdateEvent(FAILED) via the normal path,
        +                // ensuring the task state is persisted to the store before we query it.
        +                case TASK_STATE_FAILED    -> emitter.fail();
        +                default -> throw new IllegalArgumentException("Unexpected state: " + terminalState);
        +            }
        +            agentCompleted.countDown();
        +        };
        +
        +        Message initialMessage = Message.builder()
        +            .messageId("msg-initial-" + terminalState)
        +            .role(Message.Role.ROLE_USER)
        +            .parts(new TextPart("create task"))
        +            .build();
        +
        +        EventKind result = requestHandler.onMessageSend(
        +            MessageSendParams.builder().message(initialMessage).configuration(DEFAULT_CONFIG).build(),
        +            NULL_CONTEXT);
        +        assertInstanceOf(Task.class, result);
        +        Task task = (Task) result;
        +        final String finalTaskId = task.id();
        +
        +        assertTrue(agentCompleted.await(5, TimeUnit.SECONDS), "Agent should complete");
        +        Thread.sleep(200); // allow MainEventBusProcessor to persist the final state
        +
        +        Task storedTask = taskStore.get(finalTaskId);
        +        assertNotNull(storedTask);
        +        assertEquals(terminalState, storedTask.status().state(),
        +            "Task should be in " + terminalState + " state");
        +
        +        // Reset: agent executor must NOT be called on the follow-up
        +        agentExecutorExecute = (context, emitter) -> {
        +            throw new AssertionError("AgentExecutor must NOT be invoked for a terminal task");
        +        };
        +
        +        Message followUpMessage = Message.builder()
        +            .messageId("msg-followup-" + terminalState)
        +            .role(Message.Role.ROLE_USER)
        +            .taskId(finalTaskId)
        +            .parts(new TextPart("follow-up to terminal task"))
        +            .build();
        +
        +        MessageSendParams followUpParams = MessageSendParams.builder()
        +            .message(followUpMessage)
        +            .configuration(DEFAULT_CONFIG)
        +            .build();
        +
        +        UnsupportedOperationError error = assertThrows(UnsupportedOperationError.class,
        +            () -> requestHandler.onMessageSend(followUpParams, NULL_CONTEXT),
        +            "Expected UnsupportedOperationError when sending message to a " + terminalState + " task");
        +
        +        assertNotNull(error.getMessage(), "Error message should not be null");
        +        assertTrue(error.getMessage().contains(finalTaskId),
        +            "Error message should reference the task id");
        +    }
        +
        +    /**
        +     * CORE-SEND-002: SendMessage to a completed task must return UnsupportedOperationError.
        +     */
        +    @Test
        +    void testSendMessage_ToCompletedTask_ThrowsUnsupportedOperationError() throws Exception {
        +        assertSendMessageToTerminalStateThrows(TaskState.TASK_STATE_COMPLETED);
        +    }
        +
        +    /**
        +     * CORE-SEND-002: SendMessage to a canceled task must return UnsupportedOperationError.
        +     */
        +    @Test
        +    void testSendMessage_ToCanceledTask_ThrowsUnsupportedOperationError() throws Exception {
        +        assertSendMessageToTerminalStateThrows(TaskState.TASK_STATE_CANCELED);
        +    }
        +
        +    /**
        +     * CORE-SEND-002: SendMessage to a rejected task must return UnsupportedOperationError.
        +     */
        +    @Test
        +    void testSendMessage_ToRejectedTask_ThrowsUnsupportedOperationError() throws Exception {
        +        assertSendMessageToTerminalStateThrows(TaskState.TASK_STATE_REJECTED);
        +    }
        +
        +    /**
        +     * CORE-SEND-002: SendMessage to a failed task must return UnsupportedOperationError.
        +     */
        +    @Test
        +    void testSendMessage_ToFailedTask_ThrowsUnsupportedOperationError() throws Exception {
        +        assertSendMessageToTerminalStateThrows(TaskState.TASK_STATE_FAILED);
        +    }
        +
        +    /**
        +     * Test: SendStreamingMessage to a task in a terminal state must also return UnsupportedOperationError
        +     * (CORE-SEND-002, streaming path).
        +     */
        +    @Test
        +    void testSendMessageStream_ToCompletedTask_ThrowsUnsupportedOperationError() throws Exception {
        +        // Arrange: Create and complete an initial task
        +        CountDownLatch agentCompleted = new CountDownLatch(1);
        +
        +        agentExecutorExecute = (context, emitter) -> {
        +            emitter.complete();
        +            agentCompleted.countDown();
        +        };
        +
        +        Message initialMessage = Message.builder()
        +            .messageId("msg-initial-stream")
        +            .role(Message.Role.ROLE_USER)
        +            .parts(new TextPart("create task for stream test"))
        +            .build();
        +
                 MessageSendParams initialParams = MessageSendParams.builder()
                     .message(initialMessage)
                     .configuration(DEFAULT_CONFIG)
        @@ -542,24 +709,35 @@ void testRejectMismatchingContextId() throws Exception {
                 EventKind result = requestHandler.onMessageSend(initialParams, NULL_CONTEXT);
                 assertInstanceOf(Task.class, result);
                 Task task = (Task) result;
        -        assertTrue(agentCompleted.await(5, TimeUnit.SECONDS));
         
        -        // Act & Assert: Send a follow-up message with matching taskId but wrong contextId
        -        Message mismatchedMessage = Message.builder()
        -            .messageId("msg-2")
        +        assertTrue(agentCompleted.await(5, TimeUnit.SECONDS), "Agent should complete");
        +        Thread.sleep(200); // allow MainEventBusProcessor to persist
        +
        +        // Verify task is in terminal state
        +        Task storedTask = taskStore.get(task.id());
        +        assertNotNull(storedTask);
        +        assertEquals(TaskState.TASK_STATE_COMPLETED, storedTask.status().state());
        +
        +        // Reset: agent executor must NOT be called
        +        agentExecutorExecute = (context, emitter) -> {
        +            throw new AssertionError("AgentExecutor must NOT be invoked for a terminal task");
        +        };
        +
        +        // Act & Assert: streaming follow-up to a terminal task must also be rejected
        +        Message followUpMessage = Message.builder()
        +            .messageId("msg-followup-stream")
                     .role(Message.Role.ROLE_USER)
                     .taskId(task.id())
        -            .contextId("wrong-context-does-not-exist")
        -            .parts(new TextPart("follow-up message"))
        +            .parts(new TextPart("streaming follow-up to completed task"))
                     .build();
         
        -        MessageSendParams mismatchedParams = MessageSendParams.builder()
        -            .message(mismatchedMessage)
        +        MessageSendParams followUpParams = MessageSendParams.builder()
        +            .message(followUpMessage)
                     .configuration(DEFAULT_CONFIG)
                     .build();
         
        -        InvalidParamsError error = assertThrows(InvalidParamsError.class,
        -            () -> requestHandler.onMessageSend(mismatchedParams, NULL_CONTEXT));
        -        assertTrue(error.getMessage().contains(task.id()));
        +        assertThrows(UnsupportedOperationError.class,
        +            () -> requestHandler.onMessageSendStream(followUpParams, NULL_CONTEXT),
        +            "Expected UnsupportedOperationError when streaming message to a completed task");
             }
         }
        
        From c14ec7f09b7bc63882b69cfd07d2c597ddd5c1d6 Mon Sep 17 00:00:00 2001
        From: Kabir Khan 
        Date: Wed, 18 Mar 2026 10:53:00 +0000
        Subject: [PATCH 091/192] fix: Use correct HTTP status code for
         PushNotificationNotSupportedError (#758)
        MIME-Version: 1.0
        Content-Type: text/plain; charset=UTF-8
        Content-Transfer-Encoding: 8bit
        
        Fixes #748  🦕
        ---
         .../java/io/a2a/transport/rest/handler/RestHandler.java     | 6 +++---
         .../java/io/a2a/transport/rest/handler/RestHandlerTest.java | 2 +-
         2 files changed, 4 insertions(+), 4 deletions(-)
        
        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 8491d9216..a5a9b6d77 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
        @@ -776,8 +776,7 @@ private static int mapErrorToHttpStatus(A2AError error) {
                 if (error instanceof TaskNotCancelableError) {
                     return 409;
                 }
        -        if (error instanceof PushNotificationNotSupportedError
        -                || error instanceof UnsupportedOperationError) {
        +        if (error instanceof UnsupportedOperationError) {
                     return 501;
                 }
                 if (error instanceof ContentTypeNotSupportedError) {
        @@ -788,7 +787,8 @@ private static int mapErrorToHttpStatus(A2AError error) {
                 }
                 if (error instanceof ExtendedAgentCardNotConfiguredError
                         || error instanceof ExtensionSupportRequiredError
        -                || error instanceof VersionNotSupportedError) {
        +                || error instanceof VersionNotSupportedError
        +                || error instanceof PushNotificationNotSupportedError) {
                     return 400;
                 }
                 if (error instanceof InternalError) {
        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 738b027e7..5d42c436b 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
        @@ -388,7 +388,7 @@ public void testPushNotificationConfigNotSupported() {
         
                 RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", requestBody, MINIMAL_TASK.id());
         
        -        assertProblemDetail(response, 501,
        +        assertProblemDetail(response, 400,
                         "https://a2a-protocol.org/errors/push-notification-not-supported",
                         "Push Notification is not supported");
             }
        
        From 79cea44f83c0baa30a149d5402b8875a83794cb9 Mon Sep 17 00:00:00 2001
        From: Kabir Khan 
        Date: Wed, 18 Mar 2026 10:53:13 +0000
        Subject: [PATCH 092/192] fix: Allow POST requests without Content-Type header
         when body is empty (#759)
        MIME-Version: 1.0
        Content-Type: text/plain; charset=UTF-8
        Content-Transfer-Encoding: 8bit
        
        Per RFC 9110 §8.3, Content-Type header is only meaningful when a message
        body is present. The HTTP+JSON transport was incorrectly returning 415
        (ContentTypeNotSupportedError) for POST requests with no body and no
        Content-Type header.
        
        This fix adds validateContentTypeForOptionalBody() method to handle
        endpoints like POST /tasks/{id}:cancel where the body is optional. When
        the body is null or empty, Content-Type validation is skipped. When body
        content is present, Content-Type must still be application/json.
        
        This allows bodyless POST requests to be processed correctly and return
        appropriate errors (404 TaskNotFoundError, 409 TaskNotCancelableError)
        instead of 415.
        
        Fixes #747 🦕
        
        ---------
        
        Co-authored-by: Claude Sonnet 4.5 
        Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
        ---
         .../server/rest/quarkus/A2AServerRoutes.java  | 21 ++++++++++++++++++-
         1 file changed, 20 insertions(+), 1 deletion(-)
        
        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 19399c18a..11f5ab299 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
        @@ -346,7 +346,7 @@ public void getTask(RoutingContext rc) {
              */
             @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING)
             public void cancelTask(@Body String body, RoutingContext rc) {
        -        if (!validateContentType(rc)) {
        +        if (!validateContentTypeForOptionalBody(rc, body)) {
                     return;
                 }
                 String taskId = rc.pathParam("taskId");
        @@ -624,6 +624,25 @@ private boolean validateContentType(RoutingContext rc) {
                 return true;
             }
         
        +    /**
        +     * Check if the request content type is application/json when body content is present.
        +     * Per RFC 9110 §8.3, Content-Type is only meaningful when a message body is present.
        +     * Use this for endpoints where the body is optional.
        +     *
        +     * @param rc the routing context
        +     * @param body the request body (may be null or empty)
        +     * @return true if validation passes, false if Content-Type error should be returned
        +     */
        +    private boolean validateContentTypeForOptionalBody(RoutingContext rc, @Nullable String body) {
        +        // If body is null or empty, Content-Type is not required
        +        if (body == null || body.isBlank()) {
        +            return true;
        +        }
        +
        +        // Body has content - validate Content-Type
        +        return validateContentType(rc);
        +    }
        +
             /**
              * Retrieves the public agent card for agent discovery.
              *
        
        From f81ffd157b81c7750ebc4f8d7e0117e7fd81c3ce Mon Sep 17 00:00:00 2001
        From: Kabir Khan 
        Date: Wed, 18 Mar 2026 10:53:26 +0000
        Subject: [PATCH 093/192] fix: Reject messages to tasks in terminal states
         (#760)
        MIME-Version: 1.0
        Content-Type: text/plain; charset=UTF-8
        Content-Transfer-Encoding: 8bit
        
        Per A2A spec CORE-SEND-002, SendMessage must return
        UnsupportedOperationError when attempting to send messages to tasks in
        terminal states (completed, canceled, rejected, failed).
        
        Added validation in DefaultRequestHandler.initMessageSend() to check if
        the existing task is in a terminal state (using TaskState.isFinal()) and
        throw UnsupportedOperationError before the message reaches the
        AgentExecutor.
        
        This fixes the issue on all three transports (JSON-RPC, gRPC, HTTP+JSON)
        since they all use the same DefaultRequestHandler code path.
        
        Fixes #741 🦕
        
        Co-authored-by: Claude Sonnet 4.5 
        ---
         .../a2a/server/requesthandlers/DefaultRequestHandler.java  | 7 +++++++
         1 file changed, 7 insertions(+)
        
        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 5e72d224d..9a480c44f 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
        @@ -1045,6 +1045,13 @@ private MessageSendSetup initMessageSend(MessageSendParams params, ServerCallCon
                                 task.id(), task.contextId(), messageContextId));
                     }
         
        +            // Per spec CORE-SEND-002: Reject messages to tasks in terminal states
        +            if (task.status().state().isFinal()) {
        +                throw new UnsupportedOperationError(null, String.format(
        +                        "Cannot send message to task %s: task is in terminal state %s and cannot accept further messages",
        +                        task.id(), task.status().state()), null);
        +            }
        +
                     LOGGER.debug("Found task updating with message {}", params.message());
                     task = taskManager.updateWithMessage(params.message(), task);
         
        
        From fd33b3d0803f41da1a15508a735c7e4d6a766fcf Mon Sep 17 00:00:00 2001
        From: Mathias Geat 
        Date: Fri, 20 Mar 2026 19:17:42 +0100
        Subject: [PATCH 094/192] feat(http-client): allow to construct a
         JdkA2AHttpClient with a prebuilt HttpClient (#745)
        MIME-Version: 1.0
        Content-Type: text/plain; charset=UTF-8
        Content-Transfer-Encoding: 8bit
        
        # Description
        
        A prebuilt HttpClient can be used to adapt for environment specific
        circumstances, e.g. by configuring a proxy or a specific SSL context.
        
        - [x] Follow the [`CONTRIBUTING` Guide](../CONTRIBUTING.md).
        - [x] Make your Pull Request title in the
         specification.
        - Important Prefixes for
        [release-please](https://github.com/googleapis/release-please):
        - `fix:` which represents bug fixes, and correlates to a
        [SemVer](https://semver.org/) patch.
        - `feat:` represents a new feature, and correlates to a SemVer minor.
        - `feat!:`, or `fix!:`, `refactor!:`, etc., which represent a breaking
        change (indicated by the `!`) and will result in a SemVer major.
        - [x] Ensure the tests pass
        - [x] Appropriate READMEs were updated (if necessary)
        
        Fixes #744 🦕
        ---
         README.md                                     | 17 ++++
         .../io/a2a/client/http/JdkA2AHttpClient.java  | 15 ++-
         .../a2a/client/http/JdkA2AHttpClientTest.java | 91 +++++++++++++++++++
         3 files changed, 121 insertions(+), 2 deletions(-)
         create mode 100644 http-client/src/test/java/io/a2a/client/http/JdkA2AHttpClientTest.java
        
        diff --git a/README.md b/README.md
        index 36acab025..2ac7761de 100644
        --- a/README.md
        +++ b/README.md
        @@ -395,6 +395,23 @@ Client client = Client
                 .build();
         ```
         
        +To customize the default JDK HTTP client without replacing the SDK implementation, provide
        +your own `java.net.http.HttpClient` to `JdkA2AHttpClient`:
        +
        +```java
        +HttpClient jdkHttpClient = HttpClient.newBuilder()
        +        .connectTimeout(Duration.ofSeconds(5))
        +        .followRedirects(HttpClient.Redirect.NORMAL)
        +        .version(HttpClient.Version.HTTP_2)
        +        .build();
        +
        +Client client = Client
        +        .builder(agentCard)
        +        .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig(
        +                new JdkA2AHttpClient(jdkHttpClient)))
        +        .build();
        +```
        +
         ##### gRPC Transport Configuration
         
         For the gRPC transport, you must configure a channel factory:
        diff --git a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java b/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java
        index c04596360..e41f36a1c 100644
        --- a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java
        +++ b/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java
        @@ -1,5 +1,6 @@
         package io.a2a.client.http;
         
        +import static io.a2a.util.Assert.checkNotNullParam;
         import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
         import static java.net.HttpURLConnection.HTTP_MULT_CHOICE;
         import static java.net.HttpURLConnection.HTTP_OK;
        @@ -61,10 +62,20 @@ public class JdkA2AHttpClient implements A2AHttpClient {
              * 
              */
             public JdkA2AHttpClient() {
        -        httpClient = HttpClient.newBuilder()
        +        this(HttpClient.newBuilder()
                         .version(HttpClient.Version.HTTP_2)
                         .followRedirects(HttpClient.Redirect.NORMAL)
        -                .build();
        +                .build());
        +    }
        +
        +    /**
        +     * Creates a new JDK-based HTTP client using a caller-provided JDK {@link HttpClient}.
        +     *
        +     * @param httpClient the JDK HTTP client to delegate requests to
        +     * @throws IllegalArgumentException if {@code httpClient} is {@code null}
        +     */
        +    public JdkA2AHttpClient(HttpClient httpClient) {
        +        this.httpClient = checkNotNullParam("httpClient", httpClient);
             }
         
             @Override
        diff --git a/http-client/src/test/java/io/a2a/client/http/JdkA2AHttpClientTest.java b/http-client/src/test/java/io/a2a/client/http/JdkA2AHttpClientTest.java
        new file mode 100644
        index 000000000..48e10a86c
        --- /dev/null
        +++ b/http-client/src/test/java/io/a2a/client/http/JdkA2AHttpClientTest.java
        @@ -0,0 +1,91 @@
        +package io.a2a.client.http;
        +
        +import org.junit.jupiter.api.AfterEach;
        +import org.junit.jupiter.api.BeforeEach;
        +import org.junit.jupiter.api.Test;
        +import org.mockserver.integration.ClientAndServer;
        +
        +import java.io.IOException;
        +import java.net.Proxy;
        +import java.net.ProxySelector;
        +import java.net.SocketAddress;
        +import java.net.URI;
        +import java.net.http.HttpClient;
        +import java.util.List;
        +import java.util.concurrent.atomic.AtomicInteger;
        +
        +import static org.junit.jupiter.api.Assertions.assertEquals;
        +import static org.junit.jupiter.api.Assertions.assertThrows;
        +import static org.mockserver.model.HttpRequest.request;
        +import static org.mockserver.model.HttpResponse.response;
        +
        +public class JdkA2AHttpClientTest {
        +
        +    private ClientAndServer server;
        +
        +    @AfterEach
        +    public void tearDown() {
        +        if (server != null) {
        +            server.stop();
        +        }
        +    }
        +
        +    @Test
        +    public void testDefaultConstructorCreatesUsableClient() throws Exception {
        +        server = ClientAndServer.startClientAndServer(0);
        +        server.when(request().withMethod("GET").withPath("/default"))
        +                .respond(response().withStatusCode(200).withBody("ok"));
        +
        +        JdkA2AHttpClient client = new JdkA2AHttpClient();
        +
        +        A2AHttpResponse response = client.createGet()
        +                .url("http://localhost:" + server.getLocalPort() + "/default")
        +                .get();
        +
        +        assertEquals(200, response.status());
        +        assertEquals("ok", response.body());
        +    }
        +
        +    @Test
        +    public void testConstructorUsesProvidedHttpClient() throws Exception {
        +        server = ClientAndServer.startClientAndServer(0);
        +        server.when(request().withMethod("GET").withPath("/custom"))
        +                .respond(response().withStatusCode(200).withBody("ok"));
        +
        +        TrackingProxySelector proxySelector = new TrackingProxySelector();
        +        HttpClient providedClient = HttpClient.newBuilder()
        +                .proxy(proxySelector)
        +                .build();
        +
        +        JdkA2AHttpClient client = new JdkA2AHttpClient(providedClient);
        +
        +        A2AHttpResponse response = client.createGet()
        +                .url("http://localhost:" + server.getLocalPort() + "/custom")
        +                .get();
        +
        +        assertEquals(200, response.status());
        +        assertEquals("ok", response.body());
        +        assertEquals(1, proxySelector.selectCount.get(),
        +                "Provided HttpClient should be used for request execution");
        +    }
        +
        +    @Test
        +    public void testConstructorRejectsNullHttpClient() {
        +        assertThrows(IllegalArgumentException.class, () -> new JdkA2AHttpClient(null), "foo");
        +    }
        +
        +    private static final class TrackingProxySelector extends ProxySelector {
        +        private final AtomicInteger selectCount = new AtomicInteger();
        +
        +        @Override
        +        public List select(URI uri) {
        +            selectCount.incrementAndGet();
        +            return List.of(Proxy.NO_PROXY);
        +        }
        +
        +        @Override
        +        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
        +            throw new AssertionError("Proxy connection should not fail in this test", ioe);
        +        }
        +    }
        +}
        
        From f668b77c032a110786afe8580cbf45f8b0cc2b73 Mon Sep 17 00:00:00 2001
        From: Kabir Khan 
        Date: Mon, 23 Mar 2026 15:46:07 +0000
        Subject: [PATCH 095/192] fix: Keep stream open on interrupted state changes
         (#756)
        
        Fixes #754
        ---
         .../io/a2a/server/events/EventConsumer.java   |  37 ++++-
         .../a2a/server/events/EventConsumerTest.java  |  25 ++-
         spec/src/main/java/io/a2a/spec/TaskState.java |  59 +++++--
         .../apps/common/AbstractA2AServerTest.java    | 157 ++++++++++++++++++
         .../apps/common/AgentExecutorProducer.java    |  30 ++--
         5 files changed, 261 insertions(+), 47 deletions(-)
        
        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 6fdfe8ea4..0577e4f28 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
        @@ -23,6 +23,7 @@ public class EventConsumer {
             private volatile boolean cancelled = false;
             private volatile boolean agentCompleted = false;
             private volatile int pollTimeoutsAfterAgentCompleted = 0;
        +    private volatile @Nullable TaskState lastSeenTaskState = null;
         
             private static final String ERROR_MSG = "Agent did not return any response";
             private static final int NO_WAIT = -1;
        @@ -89,7 +90,12 @@ public Flow.Publisher consumeAll() {
                                     //
                                     // IMPORTANT: In replicated scenarios, remote events may arrive AFTER local agent completes!
                                     // Use grace period to allow for Kafka replication delays (can be 400-500ms)
        -                            if (agentCompleted && queueSize == 0) {
        +                            //
        +                            // CRITICAL: Do NOT close if task is in interrupted state (INPUT_REQUIRED, AUTH_REQUIRED)
        +                            // Per A2A spec, interrupted states are NOT terminal - the stream must stay open
        +                            // for future state updates even after agent completes (agent will be re-invoked later).
        +                            boolean isInterruptedState = lastSeenTaskState != null && lastSeenTaskState.isInterrupted();
        +                            if (agentCompleted && queueSize == 0 && !isInterruptedState) {
                                         pollTimeoutsAfterAgentCompleted++;
                                         if (pollTimeoutsAfterAgentCompleted >= MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED) {
                                             LOGGER.debug("Agent completed with {} consecutive poll timeouts and empty queue, closing for graceful completion (queue={})",
        @@ -102,6 +108,10 @@ public Flow.Publisher consumeAll() {
                                             LOGGER.debug("Agent completed but grace period active ({}/{} timeouts), continuing to poll (queue={})",
                                                 pollTimeoutsAfterAgentCompleted, MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED, System.identityHashCode(queue));
                                         }
        +                            } else if (agentCompleted && isInterruptedState) {
        +                                LOGGER.debug("Agent completed but task is in interrupted state ({}), stream must remain open (queue={})",
        +                                    lastSeenTaskState, System.identityHashCode(queue));
        +                                pollTimeoutsAfterAgentCompleted = 0; // Reset counter
                                     } else if (agentCompleted && queueSize > 0) {
                                         LOGGER.debug("Agent completed but queue has {} pending events, resetting timeout counter and continuing to poll (queue={})",
                                             queueSize, System.identityHashCode(queue));
        @@ -115,6 +125,13 @@ public Flow.Publisher consumeAll() {
                                 LOGGER.debug("EventConsumer received event: {} (queue={})",
                                     event.getClass().getSimpleName(), System.identityHashCode(queue));
         
        +                        // Track the latest task state for grace period logic
        +                        if (event instanceof Task task) {
        +                            lastSeenTaskState = task.status().state();
        +                        } else if (event instanceof TaskStatusUpdateEvent tue) {
        +                            lastSeenTaskState = tue.status().state();
        +                        }
        +
                                 // Defensive logging for error handling
                                 if (event instanceof Throwable thr) {
                                     LOGGER.debug("EventConsumer detected Throwable event: {} - triggering tube.fail()",
        @@ -195,17 +212,21 @@ public Flow.Publisher consumeAll() {
         
             /**
              * Determines if a task is in a state for terminating the stream.
        -     * 

        A task is terminating if:

        - *
          - *
        • Its state is final (e.g., completed, canceled, rejected, failed), OR
        • - *
        • Its state is interrupted (e.g., input-required)
        • - *
        + *

        + * Per A2A Protocol Specification 3.1.6 (SubscribeToTask): + * "The stream MUST terminate when the task reaches a terminal state + * (completed, failed, canceled, or rejected)." + *

        + * Interrupted states (INPUT_REQUIRED, AUTH_REQUIRED) are NOT terminal. + * The stream should remain open to deliver future state updates when + * the task resumes after receiving the required input or authorization. + * * @param task the task to check - * @return true if the task has a final state or an interrupted state, false otherwise + * @return true if the task has a terminal/final state, false otherwise */ private boolean isStreamTerminatingTask(Task task) { TaskState state = task.status().state(); - return state.isFinal() || state == TaskState.TASK_STATE_INPUT_REQUIRED; + return state.isFinal(); } public EnhancedRunnable.DoneCallback createAgentRunnableDoneCallback() { 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 e31fa9b4b..17242ba89 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 @@ -238,26 +238,32 @@ public void testConsumeMessageEvents() throws Exception { @Test public void testConsumeTaskInputRequired() { + // Per A2A Protocol Specification 3.1.6 (SubscribeToTask): + // "The stream MUST terminate when the task reaches a terminal state + // (completed, failed, canceled, or rejected)." + // + // INPUT_REQUIRED is an interrupted state, NOT a terminal state. + // The stream should remain open to deliver future state updates. Task task = Task.builder() .id(TASK_ID) .contextId("session-xyz") .status(new TaskStatus(TaskState.TASK_STATE_INPUT_REQUIRED)) .build(); - List events = List.of( - task, - TaskArtifactUpdateEvent.builder() + TaskArtifactUpdateEvent artifactEvent = TaskArtifactUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") .artifact(Artifact.builder() .artifactId("11") .parts(new TextPart("text")) .build()) - .build(), - TaskStatusUpdateEvent.builder() + .build(); + TaskStatusUpdateEvent completedEvent = TaskStatusUpdateEvent.builder() .taskId(TASK_ID) .contextId("session-xyz") .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build()); + .build(); + List events = List.of(task, artifactEvent, completedEvent); + for (Event event : events) { eventQueue.enqueueEvent(event); } @@ -269,9 +275,12 @@ public void testConsumeTaskInputRequired() { publisher.subscribe(getSubscriber(receivedEvents, error)); assertNull(error.get()); - // The stream is closed after the input_required task - assertEquals(1, receivedEvents.size()); + // Stream should remain open for INPUT_REQUIRED and deliver all events + // until the terminal COMPLETED state is reached + assertEquals(3, receivedEvents.size()); assertSame(task, receivedEvents.get(0)); + assertSame(artifactEvent, receivedEvents.get(1)); + assertSame(completedEvent, receivedEvents.get(2)); } private Flow.Subscriber getSubscriber(List receivedEvents, AtomicReference error) { diff --git a/spec/src/main/java/io/a2a/spec/TaskState.java b/spec/src/main/java/io/a2a/spec/TaskState.java index ca5354167..831ac0fb5 100644 --- a/spec/src/main/java/io/a2a/spec/TaskState.java +++ b/spec/src/main/java/io/a2a/spec/TaskState.java @@ -6,11 +6,17 @@ * TaskState represents the discrete states a task can be in during its execution lifecycle. * States are categorized as either transitional (non-final) or terminal (final), where * terminal states indicate that the task has reached its end state and will not transition further. + * A subset of transitional states are also marked as interrupted, indicating the task execution + * has paused and requires external action before proceeding. *

        - * Transitional States: + * Active Transitional States: *

          *
        • TASK_STATE_SUBMITTED: Task has been received by the agent and is queued for processing
        • *
        • TASK_STATE_WORKING: Agent is actively processing the task and may produce incremental results
        • + *
        + *

        + * Interrupted States: + *

          *
        • TASK_STATE_INPUT_REQUIRED: Agent needs additional input from the user to continue
        • *
        • TASK_STATE_AUTH_REQUIRED: Agent requires authentication or authorization before proceeding
        • *
        @@ -25,7 +31,8 @@ * *

        * The {@link #isFinal()} method can be used to determine if a state is terminal, which is - * important for event queue management and client polling logic. + * important for event queue management and client polling logic. The {@link #isInterrupted()} + * method identifies states where the task is paused awaiting external action. * * @see TaskStatus * @see Task @@ -33,36 +40,38 @@ */ public enum TaskState { /** Task has been received and is queued for processing (transitional state). */ - TASK_STATE_SUBMITTED(false), + TASK_STATE_SUBMITTED(false, false), /** Agent is actively processing the task (transitional state). */ - TASK_STATE_WORKING(false), + TASK_STATE_WORKING(false, false), - /** Agent requires additional input from the user to continue (transitional state). */ - TASK_STATE_INPUT_REQUIRED(false), + /** Agent requires additional input from the user to continue (interrupted state). */ + TASK_STATE_INPUT_REQUIRED(false, true), - /** Agent requires authentication or authorization to proceed (transitional state). */ - TASK_STATE_AUTH_REQUIRED(false), + /** Agent requires authentication or authorization to proceed (interrupted state). */ + TASK_STATE_AUTH_REQUIRED(false, true), /** Task completed successfully (terminal state). */ - TASK_STATE_COMPLETED(true), + TASK_STATE_COMPLETED(true, false), /** Task was canceled by user or system (terminal state). */ - TASK_STATE_CANCELED(true), + TASK_STATE_CANCELED(true, false), /** Task failed due to an error (terminal state). */ - TASK_STATE_FAILED(true), + TASK_STATE_FAILED(true, false), /** Task was rejected by the agent (terminal state). */ - TASK_STATE_REJECTED(true), + TASK_STATE_REJECTED(true, false), /** Task state is unknown or cannot be determined (terminal state). */ - UNRECOGNIZED(true); + UNRECOGNIZED(true, false); private final boolean isFinal; + private final boolean isInterrupted; - TaskState(boolean isFinal) { + TaskState(boolean isFinal, boolean isInterrupted) { this.isFinal = isFinal; + this.isInterrupted = isInterrupted; } /** @@ -71,10 +80,32 @@ public enum TaskState { * Terminal states indicate that the task has completed its lifecycle and will * not transition to any other state. This is used by the event queue system * to determine when to close queues and by clients to know when to stop polling. + *

        + * Terminal states: COMPLETED, FAILED, CANCELED, REJECTED, UNRECOGNIZED. * * @return {@code true} if this is a terminal state, {@code false} else. */ public boolean isFinal(){ return isFinal; } + + /** + * Determines whether this state is an interrupted state. + *

        + * Interrupted states indicate that the task execution has paused and requires + * external action before proceeding. The task may resume after the required + * action is provided. Interrupted states are NOT terminal - streams should + * remain open to deliver state updates. + *

        + * Interrupted states: INPUT_REQUIRED, AUTH_REQUIRED. + *

        + * Per A2A Protocol Specification 4.1.3 (TaskState): + * "TASK_STATE_INPUT_REQUIRED: This is an interrupted state." + * "TASK_STATE_AUTH_REQUIRED: This is an interrupted state." + * + * @return {@code true} if this is an interrupted state, {@code false} else. + */ + public boolean isInterrupted() { + return isInterrupted; + } } \ No newline at end of file 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 f7cdacc61..35f60ec29 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 @@ -875,6 +875,163 @@ public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Excepti } } + /** + * Tests that SubscribeToTask stream stays open for interrupted states (INPUT_REQUIRED, AUTH_REQUIRED) + * and only terminates on terminal states. + *

        + * Per A2A Protocol Specification 3.1.6 (SubscribeToTask): + * "The stream MUST terminate when the task reaches a terminal state (completed, failed, canceled, or rejected)." + *

        + * Interrupted states are NOT terminal - the stream should remain open to deliver future state updates. + *

        + * This test addresses issue #754: Stream was incorrectly closing immediately for INPUT_REQUIRED state. + * The bug had two parts: + * 1. isStreamTerminatingTask() incorrectly treated INPUT_REQUIRED as terminating + * 2. Grace period logic closed queue after agent completion, even for interrupted states + */ + @Test + @Timeout(value = 3, unit = TimeUnit.MINUTES) + public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exception { + // Use a taskId with the pattern the test agent recognizes + // When we send a message with a taskId to a non-existent task, it creates + // a new task with that ID, and context.getTask() is still null on first invocation + String taskId = "input-required-test-" + UUID.randomUUID(); + + try { + // Create initial message with the special taskId pattern + // Use non-streaming client so agent can emit INPUT_REQUIRED and return immediately + // This ensures context.getTask() == null on first agent invocation + Message message = Message.builder(MESSAGE) + .taskId(taskId) + .contextId("test-context") + .parts(new TextPart("Trigger INPUT_REQUIRED")) + .build(); + + // Send message with non-streaming client - agent will emit INPUT_REQUIRED and complete + AtomicReference finalStateRef = new AtomicReference<>(); + AtomicReference sendErrorRef = new AtomicReference<>(); + CountDownLatch sendLatch = new CountDownLatch(1); + + getNonStreamingClient().sendMessage(message, List.of((event, agentCard) -> { + if (event instanceof TaskEvent te) { + finalStateRef.set(te.getTask().status().state()); + sendLatch.countDown(); + } else if (event instanceof TaskUpdateEvent tue) { + if (tue.getUpdateEvent() instanceof TaskStatusUpdateEvent statusUpdate) { + finalStateRef.set(statusUpdate.status().state()); + } + } + }), error -> { + if (!isStreamClosedError(error)) { + sendErrorRef.set(error); + } + sendLatch.countDown(); + }); + + assertTrue(sendLatch.await(15, TimeUnit.SECONDS), "SendMessage should complete"); + assertNull(sendErrorRef.get(), "SendMessage should not error"); + TaskState finalState = finalStateRef.get(); + assertNotNull(finalState, "Final state should be captured"); + assertEquals(TaskState.TASK_STATE_INPUT_REQUIRED, finalState, + "Task should be in INPUT_REQUIRED state after agent completes"); + + // CRITICAL: At this point the agent has completed with INPUT_REQUIRED state + // The grace period logic should NOT close the queue because INPUT_REQUIRED + // is an interrupted state, not a terminal state + + // Wait 2 seconds - longer than the grace period (1.5 seconds) + // Before fix: queue would close after grace period + // After fix: queue stays open because task is in interrupted state + Thread.sleep(2000); + + // Track events received through subscription stream + CopyOnWriteArrayList receivedEvents = new CopyOnWriteArrayList<>(); + AtomicBoolean receivedInitialTask = new AtomicBoolean(false); + AtomicBoolean streamClosedPrematurely = new AtomicBoolean(false); + AtomicReference subscribeErrorRef = new AtomicReference<>(); + CountDownLatch completionLatch = new CountDownLatch(1); + + // Consumer to track all events from subscription + BiConsumer consumer = (event, agentCard) -> { + if (event instanceof TaskEvent taskEvent) { + if (!receivedInitialTask.get()) { + receivedInitialTask.set(true); + // First event should be the initial task snapshot in INPUT_REQUIRED state + assertEquals(TaskState.TASK_STATE_INPUT_REQUIRED, + taskEvent.getTask().status().state(), + "Initial task should be in INPUT_REQUIRED state"); + return; + } + } else if (event instanceof TaskUpdateEvent taskUpdateEvent) { + io.a2a.spec.UpdateEvent updateEvent = taskUpdateEvent.getUpdateEvent(); + receivedEvents.add(updateEvent); + + // Check if this is the final terminal state + if (updateEvent instanceof TaskStatusUpdateEvent tue && tue.isFinal()) { + completionLatch.countDown(); + } + } + }; + + // Error handler to detect premature stream closure + Consumer errorHandler = error -> { + if (!isStreamClosedError(error)) { + subscribeErrorRef.set(error); + } + // If completion latch hasn't been counted down yet, stream closed prematurely + if (completionLatch.getCount() > 0) { + streamClosedPrematurely.set(true); + } + completionLatch.countDown(); + }; + + // Subscribe to the task - this is AFTER agent completed with INPUT_REQUIRED + CountDownLatch subscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); + + getClient().subscribeToTask(new TaskIdParams(taskId), List.of(consumer), errorHandler); + + // Wait for subscription to be established + assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS), "Subscription should be established"); + + // Verify stream received initial task and is still open + assertTrue(receivedInitialTask.get(), "Should receive initial task snapshot"); + assertFalse(streamClosedPrematurely.get(), + "Stream should NOT close for INPUT_REQUIRED state (interrupted, not terminal)"); + + // Send a follow-up message to provide the required input + // This will trigger the agent again, which will emit COMPLETED + Message followUpMessage = Message.builder() + .messageId("input-response-" + UUID.randomUUID()) + .role(Message.Role.ROLE_USER) + .parts(new TextPart("User input")) + .taskId(taskId) + .build(); + + getClient().sendMessage(followUpMessage, List.of(), error -> {}); + + // Stream should now close after receiving COMPLETED event + assertTrue(completionLatch.await(30, TimeUnit.SECONDS), + "Stream should close after terminal state"); + + // Verify we received the COMPLETED update + assertTrue(receivedEvents.size() >= 1, + "Should receive at least COMPLETED status update"); + + // Find the COMPLETED event + boolean foundCompleted = receivedEvents.stream() + .filter(e -> e instanceof TaskStatusUpdateEvent) + .map(e -> (TaskStatusUpdateEvent) e) + .anyMatch(tue -> tue.status().state() == TaskState.TASK_STATE_COMPLETED); + assertTrue(foundCompleted, "Should receive COMPLETED status update"); + + assertNull(subscribeErrorRef.get(), "Should not have any errors"); + } finally { + deleteTaskInTaskStore(taskId); + } + } + @Test public void testSubscribeNoExistingTaskError() throws Exception { CountDownLatch errorLatch = new CountDownLatch(1); 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 74fe78eab..d69d49b9b 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 @@ -74,27 +74,23 @@ public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2 // Special handling for input-required test if (taskId != null && taskId.startsWith("input-required-test")) { - // First call: context.getTask() == null (new task) - if (context.getTask() == null) { - // Go directly to INPUT_REQUIRED without intermediate WORKING state - // This avoids race condition where blocking call interrupts on WORKING - // before INPUT_REQUIRED is persisted to TaskStore - agentEmitter.requiresInput(agentEmitter.newAgentMessage( - List.of(new TextPart("Please provide additional information")), - context.getMessage().metadata())); - // Return immediately - queue stays open because task is in INPUT_REQUIRED state - return; - } else { - String input = extractTextFromMessage(context.getMessage()); - if(! "User input".equals(input)) { - throw new InvalidParamsError("We didn't get the expected input"); - } - // Second call: context.getTask() != null (input provided) + String input = extractTextFromMessage(context.getMessage()); + // Second call: user provided the required input - complete the task + if ("User input".equals(input)) { // Go directly to COMPLETED without intermediate WORKING state - // This avoids the same race condition as the first call + // This avoids race condition where blocking call interrupts on WORKING agentEmitter.complete(); return; } + // First call: any other message - emit INPUT_REQUIRED + // Go directly to INPUT_REQUIRED without intermediate WORKING state + // This avoids race condition where blocking call interrupts on WORKING + // before INPUT_REQUIRED is persisted to TaskStore + agentEmitter.requiresInput(agentEmitter.newAgentMessage( + List.of(new TextPart("Please provide additional information")), + context.getMessage().metadata())); + // Return immediately - queue stays open because task is in INPUT_REQUIRED state + return; } // Special handling for auth-required test From d1578d35987eb7092f89344b3b4db4aba3bc8976 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 25 Mar 2026 11:25:40 +0100 Subject: [PATCH 096/192] feat(errors): add structured error codes and details to A2A error types (#743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace brittle string-matching error detection in gRPC and REST transports with a structured approach using error codes (A2AErrorCodes) and a details field. The GrpcErrorMapper now extracts ErrorInfo from gRPC status details via a REASON_MAP lookup, and error types carry richer context through a dedicated details field. 🦕 Signed-off-by: Emmanuel Hugonnet --- .../transport/grpc/GrpcErrorMapper.java | 136 ++++++++++------ .../transport/grpc/GrpcErrorMapperTest.java | 103 ++++++------ .../transport/jsonrpc/JSONRPCTransport.java | 2 +- .../jsonrpc/JSONRPCTransportTest.java | 2 +- .../transport/jsonrpc/JsonMessages.java | 2 +- .../jsonrpc/JsonStreamingMessages.java | 2 +- .../jsonrpc/sse/SSEEventListenerTest.java | 2 +- .../transport/rest/RestErrorMapper.java | 121 +++++++++----- .../io/a2a/jsonrpc/common/json/JsonUtil.java | 139 ++++++----------- .../json/A2AErrorSerializationTest.java | 39 ++--- .../server/apps/quarkus/A2AServerRoutes.java | 2 +- .../rest/quarkus/A2AServerRoutesTest.java | 6 +- .../rest/quarkus/QuarkusA2ARestTest.java | 8 +- .../java/io/a2a/grpc/utils/JSONRPCUtils.java | 81 ++++------ spec/src/main/java/io/a2a/spec/A2AError.java | 26 ++-- .../main/java/io/a2a/spec/A2AErrorCodes.java | 94 +++++++++-- .../java/io/a2a/spec/A2AProtocolError.java | 38 ++--- .../spec/ContentTypeNotSupportedError.java | 12 +- .../ExtendedAgentCardNotConfiguredError.java | 12 +- .../spec/ExtensionSupportRequiredError.java | 12 +- .../main/java/io/a2a/spec/InternalError.java | 11 +- .../a2a/spec/InvalidAgentResponseError.java | 12 +- .../java/io/a2a/spec/InvalidParamsError.java | 11 +- .../java/io/a2a/spec/InvalidRequestError.java | 11 +- .../main/java/io/a2a/spec/JSONParseError.java | 11 +- .../java/io/a2a/spec/MethodNotFoundError.java | 13 +- .../PushNotificationNotSupportedError.java | 12 +- .../io/a2a/spec/TaskNotCancelableError.java | 12 +- .../java/io/a2a/spec/TaskNotFoundError.java | 12 +- .../a2a/spec/UnsupportedOperationError.java | 12 +- .../io/a2a/spec/VersionNotSupportedError.java | 12 +- .../transport/grpc/handler/GrpcHandler.java | 70 +++------ .../grpc/handler/GrpcHandlerTest.java | 15 +- .../transport/rest/handler/RestHandler.java | 147 +++++++----------- .../rest/handler/RestHandlerTest.java | 81 ++++++---- 35 files changed, 649 insertions(+), 632 deletions(-) diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java index b9ad3325b..781242426 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java +++ b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java @@ -1,7 +1,13 @@ package io.a2a.client.transport.grpc; +import java.util.HashMap; +import java.util.Map; + +import com.google.protobuf.InvalidProtocolBufferException; +import org.jspecify.annotations.Nullable; import io.a2a.common.A2AErrorMessages; import io.a2a.spec.A2AClientException; +import io.a2a.spec.A2AErrorCodes; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ExtensionSupportRequiredError; @@ -16,12 +22,33 @@ import io.a2a.spec.UnsupportedOperationError; import io.a2a.spec.VersionNotSupportedError; import io.grpc.Status; +import io.grpc.protobuf.StatusProto; /** - * Utility class to map gRPC exceptions to appropriate A2A error types + * Utility class to map gRPC exceptions to appropriate A2A error types. + *

        + * Extracts {@code google.rpc.ErrorInfo} from gRPC status details to identify the + * specific A2A error type via the {@code reason} field. */ public class GrpcErrorMapper { + private static final Map REASON_MAP = Map.ofEntries( + Map.entry("TASK_NOT_FOUND", A2AErrorCodes.TASK_NOT_FOUND), + Map.entry("TASK_NOT_CANCELABLE", A2AErrorCodes.TASK_NOT_CANCELABLE), + Map.entry("PUSH_NOTIFICATION_NOT_SUPPORTED", A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED), + Map.entry("UNSUPPORTED_OPERATION", A2AErrorCodes.UNSUPPORTED_OPERATION), + Map.entry("CONTENT_TYPE_NOT_SUPPORTED", A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED), + Map.entry("INVALID_AGENT_RESPONSE", A2AErrorCodes.INVALID_AGENT_RESPONSE), + Map.entry("EXTENDED_AGENT_CARD_NOT_CONFIGURED", A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED), + Map.entry("EXTENSION_SUPPORT_REQUIRED", A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED), + Map.entry("VERSION_NOT_SUPPORTED", A2AErrorCodes.VERSION_NOT_SUPPORTED), + Map.entry("INVALID_REQUEST", A2AErrorCodes.INVALID_REQUEST), + Map.entry("METHOD_NOT_FOUND", A2AErrorCodes.METHOD_NOT_FOUND), + Map.entry("INVALID_PARAMS", A2AErrorCodes.INVALID_PARAMS), + Map.entry("INTERNAL", A2AErrorCodes.INTERNAL), + Map.entry("JSON_PARSE", A2AErrorCodes.JSON_PARSE) + ); + public static A2AClientException mapGrpcError(Throwable e) { return mapGrpcError(e, "gRPC error: "); } @@ -29,57 +56,68 @@ public static A2AClientException mapGrpcError(Throwable e) { public static A2AClientException mapGrpcError(Throwable e, String errorPrefix) { Status status = Status.fromThrowable(e); Status.Code code = status.getCode(); - String description = status.getDescription(); - - // Extract the actual error type from the description if possible - // (using description because the same code can map to multiple errors - - // see GrpcHandler#handleError) - if (description != null) { - if (description.contains("TaskNotFoundError")) { - return new A2AClientException(errorPrefix + description, new TaskNotFoundError()); - } else if (description.contains("UnsupportedOperationError")) { - return new A2AClientException(errorPrefix + description, new UnsupportedOperationError()); - } else if (description.contains("InvalidParamsError")) { - return new A2AClientException(errorPrefix + description, new InvalidParamsError()); - } else if (description.contains("InvalidRequestError")) { - return new A2AClientException(errorPrefix + description, new InvalidRequestError()); - } else if (description.contains("MethodNotFoundError")) { - return new A2AClientException(errorPrefix + description, new MethodNotFoundError()); - } else if (description.contains("TaskNotCancelableError")) { - return new A2AClientException(errorPrefix + description, new TaskNotCancelableError()); - } else if (description.contains("PushNotificationNotSupportedError")) { - return new A2AClientException(errorPrefix + description, new PushNotificationNotSupportedError()); - } else if (description.contains("JSONParseError")) { - return new A2AClientException(errorPrefix + description, new JSONParseError()); - } else if (description.contains("ContentTypeNotSupportedError")) { - return new A2AClientException(errorPrefix + description, new ContentTypeNotSupportedError(null, description, null)); - } else if (description.contains("InvalidAgentResponseError")) { - return new A2AClientException(errorPrefix + description, new InvalidAgentResponseError(null, description, null)); - } else if (description.contains("ExtendedCardNotConfiguredError")) { - return new A2AClientException(errorPrefix + description, new ExtendedAgentCardNotConfiguredError(null, description, null)); - } else if (description.contains("ExtensionSupportRequiredError")) { - return new A2AClientException(errorPrefix + description, new ExtensionSupportRequiredError(null, description, null)); - } else if (description.contains("VersionNotSupportedError")) { - return new A2AClientException(errorPrefix + description, new VersionNotSupportedError(null, description, null)); + String message = status.getDescription(); + + // Try to extract ErrorInfo from status details + com.google.rpc.@Nullable ErrorInfo errorInfo = extractErrorInfo(e); + if (errorInfo != null) { + A2AErrorCodes errorCode = REASON_MAP.get(errorInfo.getReason()); + if (errorCode != null) { + String errorMessage = message != null ? message : (e.getMessage() != null ? e.getMessage() : ""); + Map metadata = errorInfo.getMetadataMap().isEmpty() ? null + : new HashMap(errorInfo.getMetadataMap()); + return mapByErrorCode(errorCode, errorPrefix + errorMessage, errorMessage, metadata); } } - + // Fall back to mapping based on status code - switch (code) { - case NOT_FOUND: - return new A2AClientException(errorPrefix + (description != null ? description : e.getMessage()), new TaskNotFoundError()); - case UNIMPLEMENTED: - return new A2AClientException(errorPrefix + (description != null ? description : e.getMessage()), new UnsupportedOperationError()); - case INVALID_ARGUMENT: - return new A2AClientException(errorPrefix + (description != null ? description : e.getMessage()), new InvalidParamsError()); - case INTERNAL: - return new A2AClientException(errorPrefix + (description != null ? description : e.getMessage()), new io.a2a.spec.InternalError(null, e.getMessage(), null)); - case UNAUTHENTICATED: - return new A2AClientException(errorPrefix + A2AErrorMessages.AUTHENTICATION_FAILED); - case PERMISSION_DENIED: - return new A2AClientException(errorPrefix + A2AErrorMessages.AUTHORIZATION_FAILED); - default: - return new A2AClientException(errorPrefix + e.getMessage(), e); + String desc = message != null ? message : e.getMessage() == null ? "" : e.getMessage(); + return switch (code) { + case NOT_FOUND -> new A2AClientException(errorPrefix + desc, new TaskNotFoundError()); + case UNIMPLEMENTED -> new A2AClientException(errorPrefix + desc, new UnsupportedOperationError()); + case INVALID_ARGUMENT -> new A2AClientException(errorPrefix + desc, new InvalidParamsError()); + case INTERNAL -> new A2AClientException(errorPrefix + desc, new io.a2a.spec.InternalError(null, desc, null)); + case UNAUTHENTICATED -> new A2AClientException(errorPrefix + A2AErrorMessages.AUTHENTICATION_FAILED); + case PERMISSION_DENIED -> new A2AClientException(errorPrefix + A2AErrorMessages.AUTHORIZATION_FAILED); + default -> new A2AClientException(errorPrefix + e.getMessage(), e); + }; + } + + private static com.google.rpc.@Nullable ErrorInfo extractErrorInfo(Throwable e) { + try { + com.google.rpc.Status rpcStatus = StatusProto.fromThrowable(e); + if (rpcStatus != null) { + for (com.google.protobuf.Any detail : rpcStatus.getDetailsList()) { + if (detail.is(com.google.rpc.ErrorInfo.class)) { + com.google.rpc.ErrorInfo errorInfo = detail.unpack(com.google.rpc.ErrorInfo.class); + if ("a2a-protocol.org".equals(errorInfo.getDomain())) { + return errorInfo; + } + } + } + } + } catch (InvalidProtocolBufferException ignored) { + // Fall through to status code-based mapping } + return null; + } + + private static A2AClientException mapByErrorCode(A2AErrorCodes errorCode, String fullMessage, String errorMessage, @Nullable Map metadata) { + return switch (errorCode) { + case TASK_NOT_FOUND -> new A2AClientException(fullMessage, new TaskNotFoundError(errorMessage, metadata)); + case TASK_NOT_CANCELABLE -> new A2AClientException(fullMessage, new TaskNotCancelableError(null, errorMessage, metadata)); + case PUSH_NOTIFICATION_NOT_SUPPORTED -> new A2AClientException(fullMessage, new PushNotificationNotSupportedError(null, errorMessage, metadata)); + case UNSUPPORTED_OPERATION -> new A2AClientException(fullMessage, new UnsupportedOperationError(null, errorMessage, metadata)); + case CONTENT_TYPE_NOT_SUPPORTED -> new A2AClientException(fullMessage, new ContentTypeNotSupportedError(null, errorMessage, metadata)); + case INVALID_AGENT_RESPONSE -> new A2AClientException(fullMessage, new InvalidAgentResponseError(null, errorMessage, metadata)); + case EXTENDED_AGENT_CARD_NOT_CONFIGURED -> new A2AClientException(fullMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, metadata)); + case EXTENSION_SUPPORT_REQUIRED -> new A2AClientException(fullMessage, new ExtensionSupportRequiredError(null, errorMessage, metadata)); + case VERSION_NOT_SUPPORTED -> new A2AClientException(fullMessage, new VersionNotSupportedError(null, errorMessage, metadata)); + case INVALID_REQUEST -> new A2AClientException(fullMessage, new InvalidRequestError(null, errorMessage, metadata)); + case JSON_PARSE -> new A2AClientException(fullMessage, new JSONParseError(null, errorMessage, metadata)); + case METHOD_NOT_FOUND -> new A2AClientException(fullMessage, new MethodNotFoundError(null, errorMessage, metadata)); + case INVALID_PARAMS -> new A2AClientException(fullMessage, new InvalidParamsError(null, errorMessage, metadata)); + case INTERNAL -> new A2AClientException(fullMessage, new io.a2a.spec.InternalError(null, errorMessage, metadata)); + }; } } diff --git a/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java b/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java index 864e406d2..151ca7b91 100644 --- a/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java +++ b/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java @@ -1,10 +1,11 @@ package io.a2a.client.transport.grpc; -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.assertTrue; +import com.google.protobuf.Any; +import com.google.rpc.ErrorInfo; import io.a2a.spec.A2AClientException; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.ExtendedAgentCardNotConfiguredError; @@ -15,25 +16,38 @@ import io.a2a.spec.VersionNotSupportedError; import io.grpc.Status; import io.grpc.StatusRuntimeException; +import io.grpc.protobuf.StatusProto; import org.junit.jupiter.api.Test; /** * Tests for GrpcErrorMapper - verifies correct unmarshalling of gRPC errors to A2A error types + * using google.rpc.ErrorInfo in status details. */ public class GrpcErrorMapperTest { + private static StatusRuntimeException createA2AStatusException(int grpcCode, String message, String reason) { + ErrorInfo errorInfo = ErrorInfo.newBuilder() + .setReason(reason) + .setDomain("a2a-protocol.org") + .build(); + + com.google.rpc.Status rpcStatus = com.google.rpc.Status.newBuilder() + .setCode(grpcCode) + .setMessage(message) + .addDetails(Any.pack(errorInfo)) + .build(); + + return StatusProto.toStatusRuntimeException(rpcStatus); + } + @Test public void testExtensionSupportRequiredErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with ExtensionSupportRequiredError in description - String errorMessage = "ExtensionSupportRequiredError: Extension required: https://example.com/test-extension"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); + String errorMessage = "Extension required: https://example.com/test-extension"; + StatusRuntimeException grpcException = createA2AStatusException( + Status.Code.FAILED_PRECONDITION.value(), errorMessage, "EXTENSION_SUPPORT_REQUIRED"); - // Map the gRPC error to A2A error A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - // Verify the result assertNotNull(result); assertNotNull(result.getCause()); assertInstanceOf(ExtensionSupportRequiredError.class, result.getCause()); @@ -46,16 +60,12 @@ public void testExtensionSupportRequiredErrorUnmarshalling() { @Test public void testVersionNotSupportedErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with VersionNotSupportedError in description - String errorMessage = "VersionNotSupportedError: Version 2.0 is not supported"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); + String errorMessage = "Version 2.0 is not supported"; + StatusRuntimeException grpcException = createA2AStatusException( + Status.Code.UNIMPLEMENTED.value(), errorMessage, "VERSION_NOT_SUPPORTED"); - // Map the gRPC error to A2A error A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - // Verify the result assertNotNull(result); assertNotNull(result.getCause()); assertInstanceOf(VersionNotSupportedError.class, result.getCause()); @@ -67,16 +77,12 @@ public void testVersionNotSupportedErrorUnmarshalling() { @Test public void testExtendedCardNotConfiguredErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with ExtendedCardNotConfiguredError in description - String errorMessage = "ExtendedCardNotConfiguredError: Extended card not configured for this agent"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); + String errorMessage = "Extended card not configured for this agent"; + StatusRuntimeException grpcException = createA2AStatusException( + Status.Code.FAILED_PRECONDITION.value(), errorMessage, "EXTENDED_AGENT_CARD_NOT_CONFIGURED"); - // Map the gRPC error to A2A error A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - // Verify the result assertNotNull(result); assertNotNull(result.getCause()); assertInstanceOf(ExtendedAgentCardNotConfiguredError.class, result.getCause()); @@ -88,16 +94,12 @@ public void testExtendedCardNotConfiguredErrorUnmarshalling() { @Test public void testTaskNotFoundErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with TaskNotFoundError in description - String errorMessage = "TaskNotFoundError: Task task-123 not found"; - StatusRuntimeException grpcException = Status.NOT_FOUND - .withDescription(errorMessage) - .asRuntimeException(); + String errorMessage = "Task task-123 not found"; + StatusRuntimeException grpcException = createA2AStatusException( + Status.Code.NOT_FOUND.value(), errorMessage, "TASK_NOT_FOUND"); - // Map the gRPC error to A2A error A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - // Verify the result assertNotNull(result); assertNotNull(result.getCause()); assertInstanceOf(TaskNotFoundError.class, result.getCause()); @@ -105,16 +107,12 @@ public void testTaskNotFoundErrorUnmarshalling() { @Test public void testUnsupportedOperationErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with UnsupportedOperationError in description - String errorMessage = "UnsupportedOperationError: Operation not supported"; - StatusRuntimeException grpcException = Status.UNIMPLEMENTED - .withDescription(errorMessage) - .asRuntimeException(); + String errorMessage = "Operation not supported"; + StatusRuntimeException grpcException = createA2AStatusException( + Status.Code.UNIMPLEMENTED.value(), errorMessage, "UNSUPPORTED_OPERATION"); - // Map the gRPC error to A2A error A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - // Verify the result assertNotNull(result); assertNotNull(result.getCause()); assertInstanceOf(UnsupportedOperationError.class, result.getCause()); @@ -122,16 +120,12 @@ public void testUnsupportedOperationErrorUnmarshalling() { @Test public void testInvalidParamsErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with InvalidParamsError in description - String errorMessage = "InvalidParamsError: Invalid parameters provided"; - StatusRuntimeException grpcException = Status.INVALID_ARGUMENT - .withDescription(errorMessage) - .asRuntimeException(); + String errorMessage = "Invalid parameters provided"; + StatusRuntimeException grpcException = createA2AStatusException( + Status.Code.INVALID_ARGUMENT.value(), errorMessage, "INVALID_PARAMS"); - // Map the gRPC error to A2A error A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - // Verify the result assertNotNull(result); assertNotNull(result.getCause()); assertInstanceOf(InvalidParamsError.class, result.getCause()); @@ -139,16 +133,12 @@ public void testInvalidParamsErrorUnmarshalling() { @Test public void testContentTypeNotSupportedErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with ContentTypeNotSupportedError in description - String errorMessage = "ContentTypeNotSupportedError: Content type application/xml not supported"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); + String errorMessage = "Content type application/xml not supported"; + StatusRuntimeException grpcException = createA2AStatusException( + Status.Code.INVALID_ARGUMENT.value(), errorMessage, "CONTENT_TYPE_NOT_SUPPORTED"); - // Map the gRPC error to A2A error A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - // Verify the result assertNotNull(result); assertNotNull(result.getCause()); assertInstanceOf(ContentTypeNotSupportedError.class, result.getCause()); @@ -160,12 +150,11 @@ public void testContentTypeNotSupportedErrorUnmarshalling() { @Test public void testFallbackToStatusCodeMapping() { - // Create a gRPC StatusRuntimeException without specific error type in description + // Create a gRPC StatusRuntimeException without ErrorInfo details StatusRuntimeException grpcException = Status.NOT_FOUND .withDescription("Generic not found error") .asRuntimeException(); - // Map the gRPC error to A2A error A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); // Verify fallback to status code mapping @@ -176,17 +165,13 @@ public void testFallbackToStatusCodeMapping() { @Test public void testCustomErrorPrefix() { - // Create a gRPC StatusRuntimeException - String errorMessage = "ExtensionSupportRequiredError: Extension required: https://example.com/ext"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); + String errorMessage = "Extension required: https://example.com/ext"; + StatusRuntimeException grpcException = createA2AStatusException( + Status.Code.FAILED_PRECONDITION.value(), errorMessage, "EXTENSION_SUPPORT_REQUIRED"); - // Map with custom error prefix String customPrefix = "Custom Error: "; A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException, customPrefix); - // Verify custom prefix is used assertNotNull(result); assertTrue(result.getMessage().startsWith(customPrefix)); assertInstanceOf(ExtensionSupportRequiredError.class, result.getCause()); 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 2bbb25d87..63100ee09 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 @@ -364,7 +364,7 @@ private > T unmarshalResponse(String response, String m A2AResponse value = JSONRPCUtils.parseResponseBody(response, method); A2AError error = value.getError(); if (error != null) { - throw new A2AClientException(error.getMessage() + (error.getData() != null ? ": " + error.getData() : ""), error); + throw new A2AClientException(error.getMessage() + (!error.getDetails().isEmpty() ? ": " + error.getDetails() : ""), error); } // Safe cast: JSONRPCUtils.parseResponseBody returns the correct concrete type based on method return (T) value; diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java index 47c450506..55c20bc55 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -212,7 +212,7 @@ public void testA2AClientSendMessageWithError() throws Exception { client.sendMessage(params, null); fail(); // should not reach here } catch (A2AClientException e) { - assertTrue(e.getMessage().contains("Invalid parameters: \"Hello world\""),e.getMessage()); + assertTrue(e.getMessage().contains("Invalid parameters: {info=Hello world}"),e.getMessage()); } } 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 a9639b84c..a0be30e0d 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 @@ -216,7 +216,7 @@ public class JsonMessages { "error": { "code": -32702, "message": "Invalid parameters", - "data": "Hello world" + "details": {"info": "Hello world"} } }"""; diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java index 39f2d7859..df6fee000 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java @@ -99,7 +99,7 @@ public class JsonStreamingMessages { "error": { "code": -32602, "message": "Invalid parameters", - "data": "Missing required field" + "details": {"info": "Missing required field"} } }"""; 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 e9e74d12f..389c7df8d 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 @@ -161,7 +161,7 @@ public void testOnEventWithError() throws Exception { A2AError jsonrpcError = (A2AError) receivedError.get(); assertEquals(-32602, jsonrpcError.getCode()); assertEquals("Invalid parameters", jsonrpcError.getMessage()); - assertEquals("\"Missing required field\"", jsonrpcError.getData()); + assertEquals("Missing required field", jsonrpcError.getDetails().get("info")); } @Test 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 e749070af..009255f66 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,5 +1,7 @@ package io.a2a.client.transport.rest; +import java.util.HashMap; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -8,8 +10,9 @@ import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.A2AClientException; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; +import io.a2a.spec.A2AErrorCodes; import io.a2a.spec.ContentTypeNotSupportedError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidAgentResponseError; @@ -28,6 +31,25 @@ */ public class RestErrorMapper { + private record ReasonAndMetadata(String reason, @org.jspecify.annotations.Nullable Map metadata) {} + + private static final Map REASON_MAP = Map.ofEntries( + Map.entry("TASK_NOT_FOUND", A2AErrorCodes.TASK_NOT_FOUND), + Map.entry("TASK_NOT_CANCELABLE", A2AErrorCodes.TASK_NOT_CANCELABLE), + Map.entry("PUSH_NOTIFICATION_NOT_SUPPORTED", A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED), + Map.entry("UNSUPPORTED_OPERATION", A2AErrorCodes.UNSUPPORTED_OPERATION), + Map.entry("CONTENT_TYPE_NOT_SUPPORTED", A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED), + Map.entry("INVALID_AGENT_RESPONSE", A2AErrorCodes.INVALID_AGENT_RESPONSE), + Map.entry("EXTENDED_AGENT_CARD_NOT_CONFIGURED", A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED), + Map.entry("EXTENSION_SUPPORT_REQUIRED", A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED), + Map.entry("VERSION_NOT_SUPPORTED", A2AErrorCodes.VERSION_NOT_SUPPORTED), + Map.entry("INVALID_REQUEST", A2AErrorCodes.INVALID_REQUEST), + Map.entry("METHOD_NOT_FOUND", A2AErrorCodes.METHOD_NOT_FOUND), + Map.entry("INVALID_PARAMS", A2AErrorCodes.INVALID_PARAMS), + Map.entry("INTERNAL", A2AErrorCodes.INTERNAL), + Map.entry("JSON_PARSE", A2AErrorCodes.JSON_PARSE) + ); + public static A2AClientException mapRestError(A2AHttpResponse response) { return RestErrorMapper.mapRestError(response.body(), response.status()); } @@ -36,13 +58,17 @@ public static A2AClientException mapRestError(String body, int code) { try { if (body != null && !body.isBlank()) { JsonObject node = JsonUtil.fromJson(body, JsonObject.class); - // Support RFC 7807 Problem Details format (type, title, details, status) - if (node.has("type")) { - String type = node.get("type").getAsString(); - String errorMessage = node.has("title") ? node.get("title").getAsString() : ""; - return mapRestErrorByType(type, errorMessage, code); + // Google Cloud API error format: { "error": { "code", "status", "message", "details" } } + if (node.has("error") && node.get("error").isJsonObject()) { + JsonObject errorObj = node.getAsJsonObject("error"); + String errorMessage = errorObj.has("message") ? errorObj.get("message").getAsString() : ""; + ReasonAndMetadata reasonAndMetadata = extractReasonAndMetadata(errorObj); + if (reasonAndMetadata != null) { + return mapRestErrorByReason(reasonAndMetadata.reason(), errorMessage, reasonAndMetadata.metadata()); + } + return new A2AClientException(errorMessage); } - // Legacy format (error, message) + // Legacy format (error class name, message) String className = node.has("error") ? node.get("error").getAsString() : ""; String errorMessage = node.has("message") ? node.get("message").getAsString() : ""; return mapRestErrorByClassName(className, errorMessage, code); @@ -59,36 +85,59 @@ public static A2AClientException mapRestError(String className, String errorMess } /** - * Maps RFC 7807 Problem Details error type URIs to A2A exceptions. - *

        - * Note: Error constructors receive null for code and data parameters because: - *

          - *
        • Error codes are defaulted by each error class (e.g., -32007 for ExtendedAgentCardNotConfiguredError)
        • - *
        • The message comes from the RFC 7807 "title" field
        • - *
        • The data field is optional and not included in basic RFC 7807 responses
        • - *
        + * Extracts the "reason" and "metadata" fields from the first entry in the "details" array. + */ + private static @org.jspecify.annotations.Nullable ReasonAndMetadata extractReasonAndMetadata(JsonObject errorObj) { + if (errorObj.has("details") && errorObj.get("details").isJsonArray()) { + var details = errorObj.getAsJsonArray("details"); + if (!details.isEmpty() && details.get(0).isJsonObject()) { + JsonObject detail = details.get(0).getAsJsonObject(); + if (detail.has("reason")) { + String reason = detail.get("reason").getAsString(); + Map metadata = null; + if (detail.has("metadata") && detail.get("metadata").isJsonObject()) { + JsonObject metaObj = detail.getAsJsonObject("metadata"); + Map metaMap = new HashMap<>(); + for (var entry : metaObj.entrySet()) { + metaMap.put(entry.getKey(), JsonUtil.OBJECT_MAPPER.fromJson(entry.getValue(), Object.class)); + } + metadata = metaMap; + } + return new ReasonAndMetadata(reason, metadata); + } + } + } + return null; + } + + /** + * Maps error reason strings to A2A exceptions. * - * @param type the RFC 7807 error type URI (e.g., "https://a2a-protocol.org/errors/task-not-found") - * @param errorMessage the error message from the "title" field - * @param code the HTTP status code (currently unused, kept for consistency) + * @param reason the error reason (e.g., "TASK_NOT_FOUND") + * @param errorMessage the error message + * @param metadata additional metadata extracted from the error details * @return an A2AClientException wrapping the appropriate A2A error */ - private static A2AClientException mapRestErrorByType(String type, String errorMessage, int code) { - return switch (type) { - case "https://a2a-protocol.org/errors/task-not-found" -> new A2AClientException(errorMessage, new TaskNotFoundError()); - case "https://a2a-protocol.org/errors/extended-agent-card-not-configured" -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, null)); - case "https://a2a-protocol.org/errors/content-type-not-supported" -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, errorMessage, null)); - case "https://a2a-protocol.org/errors/internal-error" -> new A2AClientException(errorMessage, new InternalError(errorMessage)); - case "https://a2a-protocol.org/errors/invalid-agent-response" -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, errorMessage, null)); - case "https://a2a-protocol.org/errors/invalid-params" -> new A2AClientException(errorMessage, new InvalidParamsError()); - case "https://a2a-protocol.org/errors/invalid-request" -> new A2AClientException(errorMessage, new InvalidRequestError()); - case "https://a2a-protocol.org/errors/method-not-found" -> new A2AClientException(errorMessage, new MethodNotFoundError()); - case "https://a2a-protocol.org/errors/push-notification-not-supported" -> new A2AClientException(errorMessage, new PushNotificationNotSupportedError()); - case "https://a2a-protocol.org/errors/task-not-cancelable" -> new A2AClientException(errorMessage, new TaskNotCancelableError()); - case "https://a2a-protocol.org/errors/unsupported-operation" -> new A2AClientException(errorMessage, new UnsupportedOperationError()); - case "https://a2a-protocol.org/errors/extension-support-required" -> new A2AClientException(errorMessage, new ExtensionSupportRequiredError(null, errorMessage, null)); - case "https://a2a-protocol.org/errors/version-not-supported" -> new A2AClientException(errorMessage, new VersionNotSupportedError(null, errorMessage, null)); - default -> new A2AClientException(errorMessage); + private static A2AClientException mapRestErrorByReason(String reason, String errorMessage, @org.jspecify.annotations.Nullable Map metadata) { + A2AErrorCodes errorCode = REASON_MAP.get(reason); + if (errorCode == null) { + return new A2AClientException(errorMessage); + } + return switch (errorCode) { + case TASK_NOT_FOUND -> new A2AClientException(errorMessage, new TaskNotFoundError(errorMessage, metadata)); + case TASK_NOT_CANCELABLE -> new A2AClientException(errorMessage, new TaskNotCancelableError(null, errorMessage, metadata)); + case PUSH_NOTIFICATION_NOT_SUPPORTED -> new A2AClientException(errorMessage, new PushNotificationNotSupportedError(null, errorMessage, metadata)); + case UNSUPPORTED_OPERATION -> new A2AClientException(errorMessage, new UnsupportedOperationError(null, errorMessage, metadata)); + case CONTENT_TYPE_NOT_SUPPORTED -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, errorMessage, metadata)); + case INVALID_AGENT_RESPONSE -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, errorMessage, metadata)); + case EXTENDED_AGENT_CARD_NOT_CONFIGURED -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, metadata)); + case EXTENSION_SUPPORT_REQUIRED -> new A2AClientException(errorMessage, new ExtensionSupportRequiredError(null, errorMessage, metadata)); + case VERSION_NOT_SUPPORTED -> new A2AClientException(errorMessage, new VersionNotSupportedError(null, errorMessage, metadata)); + case INVALID_REQUEST -> new A2AClientException(errorMessage, new InvalidRequestError(null, errorMessage, metadata)); + case JSON_PARSE -> new A2AClientException(errorMessage, new JSONParseError(null, errorMessage, metadata)); + case METHOD_NOT_FOUND -> new A2AClientException(errorMessage, new MethodNotFoundError(null, errorMessage, metadata)); + case INVALID_PARAMS -> new A2AClientException(errorMessage, new InvalidParamsError(null, errorMessage, metadata)); + case INTERNAL -> new A2AClientException(errorMessage, new InternalError(null, errorMessage, metadata)); }; } @@ -96,9 +145,9 @@ private static A2AClientException mapRestErrorByClassName(String className, Stri return switch (className) { case "io.a2a.spec.TaskNotFoundError" -> new A2AClientException(errorMessage, new TaskNotFoundError()); case "io.a2a.spec.ExtendedCardNotConfiguredError" -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, null)); - case "io.a2a.spec.ContentTypeNotSupportedError" -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, null, errorMessage)); + case "io.a2a.spec.ContentTypeNotSupportedError" -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, errorMessage, null)); case "io.a2a.spec.InternalError" -> new A2AClientException(errorMessage, new InternalError(errorMessage)); - case "io.a2a.spec.InvalidAgentResponseError" -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, null, errorMessage)); + case "io.a2a.spec.InvalidAgentResponseError" -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, errorMessage, null)); case "io.a2a.spec.InvalidParamsError" -> new A2AClientException(errorMessage, new InvalidParamsError()); case "io.a2a.spec.InvalidRequestError" -> new A2AClientException(errorMessage, new InvalidRequestError()); case "io.a2a.spec.JSONParseError" -> new A2AClientException(errorMessage, new JSONParseError()); diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index 9e8fb057f..3967cbf80 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -1,23 +1,12 @@ 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; -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.jsonrpc.common.json.JsonUtil.ThrowableTypeAdapter.THROWABLE_MARKER_FIELD; +import io.a2a.spec.A2AErrorCodes; import static io.a2a.spec.DataPart.DATA; import static io.a2a.spec.TextPart.TEXT; import static java.lang.String.format; import static java.util.Collections.emptyMap; -import java.io.StringReader; import java.lang.reflect.Type; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; @@ -44,6 +33,8 @@ import io.a2a.spec.APIKeySecurityScheme; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.DataPart; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; +import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.FileContent; import io.a2a.spec.FilePart; import io.a2a.spec.FileWithBytes; @@ -70,6 +61,7 @@ import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; +import io.a2a.spec.VersionNotSupportedError; import org.jspecify.annotations.Nullable; @@ -218,6 +210,8 @@ OffsetDateTime read(JsonReader in) throws java.io.IOException { */ static class ThrowableTypeAdapter extends TypeAdapter { + static final String THROWABLE_MARKER_FIELD = "__throwable"; + @Override public void write(JsonWriter out, Throwable value) throws java.io.IOException { if (value == null) { @@ -305,10 +299,8 @@ Throwable read(JsonReader in) throws java.io.IOException { */ static class A2AErrorTypeAdapter extends TypeAdapter { - private static final ThrowableTypeAdapter THROWABLE_ADAPTER = new ThrowableTypeAdapter(); - static final String THROWABLE_MARKER_FIELD = "__throwable"; private static final String CODE_FIELD = "code"; - private static final String DATA_FIELD = "data"; + private static final String DETAILS_FIELD = "details"; private static final String MESSAGE_FIELD = "message"; private static final String TYPE_FIELD = "type"; @@ -321,15 +313,9 @@ public void write(JsonWriter out, A2AError value) throws java.io.IOException { out.beginObject(); out.name(CODE_FIELD).value(value.getCode()); out.name(MESSAGE_FIELD).value(value.getMessage()); - if (value.getData() != null) { - out.name(DATA_FIELD); - // If data is a Throwable, use ThrowableTypeAdapter to avoid reflection issues - if (value.getData() instanceof Throwable throwable) { - THROWABLE_ADAPTER.write(out, throwable); - } else { - // Use Gson to serialize the data field for non-Throwable types - OBJECT_MAPPER.toJson(value.getData(), Object.class, out); - } + if (!value.getDetails().isEmpty()) { + out.name(DETAILS_FIELD); + OBJECT_MAPPER.toJson(value.getDetails(), Map.class, out); } out.endObject(); } @@ -344,7 +330,7 @@ A2AError read(JsonReader in) throws java.io.IOException { Integer code = null; String message = null; - Object data = null; + Map details = null; in.beginObject(); while (in.hasNext()) { @@ -354,9 +340,9 @@ A2AError read(JsonReader in) throws java.io.IOException { code = in.nextInt(); case MESSAGE_FIELD -> message = in.nextString(); - case DATA_FIELD -> { - // Read data as a generic object (could be string, number, object, etc.) - data = readDataValue(in); + case DETAILS_FIELD -> { + // Read details as a map + details = readDetailsValue(in); } default -> in.skipValue(); @@ -365,82 +351,53 @@ A2AError read(JsonReader in) throws java.io.IOException { in.endObject(); // Create the appropriate subclass based on the error code - return createErrorInstance(code, message, data); + return createErrorInstance(code, message, details); } /** - * Reads the data field value, which can be of any JSON type. + * Reads the details field value as a map. */ + @SuppressWarnings("unchecked") private @Nullable - Object readDataValue(JsonReader in) throws java.io.IOException { - return switch (in.peek()) { - case STRING -> - in.nextString(); - case NUMBER -> - in.nextDouble(); - case BOOLEAN -> - in.nextBoolean(); - case NULL -> { - in.nextNull(); - yield null; - } - case BEGIN_OBJECT -> { - // Parse as JsonElement to check if it's a Throwable - com.google.gson.JsonElement element = com.google.gson.JsonParser.parseReader(in); - if (element.isJsonObject()) { - com.google.gson.JsonObject obj = element.getAsJsonObject(); - // Check if it has the structure of a serialized Throwable (type + message) - if (obj.has(TYPE_FIELD) && obj.has(MESSAGE_FIELD) && obj.has(THROWABLE_MARKER_FIELD)) { - // Deserialize as Throwable using ThrowableTypeAdapter - yield THROWABLE_ADAPTER.read(new JsonReader(new StringReader(element.toString()))); - } - } - // Otherwise, deserialize as generic object - yield OBJECT_MAPPER.fromJson(element, Object.class); - } - case BEGIN_ARRAY -> - // For arrays, read as raw JSON using Gson - OBJECT_MAPPER.fromJson(in, Object.class); - default -> { - in.skipValue(); - yield null; - } - }; + Map readDetailsValue(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + if (in.peek() == com.google.gson.stream.JsonToken.BEGIN_OBJECT) { + return (Map) OBJECT_MAPPER.fromJson(in, Map.class); + } + in.skipValue(); + return null; } /** * Creates the appropriate A2AError subclass based on the error code. */ - private A2AError createErrorInstance(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + private A2AError createErrorInstance(@Nullable Integer code, @Nullable String message, @Nullable Map details) { if (code == null) { throw new JsonSyntaxException("A2AError must have a code field"); } - return switch (code) { - case JSON_PARSE_ERROR_CODE -> - new JSONParseError(code, message, data); - case INVALID_REQUEST_ERROR_CODE -> - new InvalidRequestError(code, message, data); - case METHOD_NOT_FOUND_ERROR_CODE -> - new MethodNotFoundError(code, message, data); - case INVALID_PARAMS_ERROR_CODE -> - new InvalidParamsError(code, message, data); - case INTERNAL_ERROR_CODE -> - new io.a2a.spec.InternalError(code, message, data); - case TASK_NOT_FOUND_ERROR_CODE -> - new TaskNotFoundError(message, data); - case TASK_NOT_CANCELABLE_ERROR_CODE -> - new TaskNotCancelableError(code, message, data); - case PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE -> - new PushNotificationNotSupportedError(code, message, data); - case UNSUPPORTED_OPERATION_ERROR_CODE -> - new UnsupportedOperationError(code, message, data); - case CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE -> - new ContentTypeNotSupportedError(code, message, data); - case INVALID_AGENT_RESPONSE_ERROR_CODE -> - new InvalidAgentResponseError(code, message, data); - default -> - new A2AError(code, message == null ? "" : message, data); + A2AErrorCodes errorCode = A2AErrorCodes.fromCode(code); + if (errorCode == null) { + return new A2AError(code, message == null ? "" : message, details); + } + return switch (errorCode) { + case JSON_PARSE -> new JSONParseError(code, message, details); + case INVALID_REQUEST -> new InvalidRequestError(code, message, details); + case METHOD_NOT_FOUND -> new MethodNotFoundError(code, message, details); + case INVALID_PARAMS -> new InvalidParamsError(code, message, details); + case INTERNAL -> new io.a2a.spec.InternalError(code, message, details); + case TASK_NOT_FOUND -> new TaskNotFoundError(message, details); + case TASK_NOT_CANCELABLE -> new TaskNotCancelableError(code, message, details); + case PUSH_NOTIFICATION_NOT_SUPPORTED -> new PushNotificationNotSupportedError(code, message, details); + case UNSUPPORTED_OPERATION -> new UnsupportedOperationError(code, message, details); + case CONTENT_TYPE_NOT_SUPPORTED -> new ContentTypeNotSupportedError(code, message, details); + case INVALID_AGENT_RESPONSE -> new InvalidAgentResponseError(code, message, details); + case EXTENDED_AGENT_CARD_NOT_CONFIGURED -> new ExtendedAgentCardNotConfiguredError(code, message, details); + case EXTENSION_SUPPORT_REQUIRED -> new ExtensionSupportRequiredError(code, message, details); + case VERSION_NOT_SUPPORTED -> new VersionNotSupportedError(code, message, details); }; } } diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java index ff7ee5cc1..734ff47e0 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java @@ -1,22 +1,12 @@ package io.a2a.jsonrpc.common.json; -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 org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import java.util.List; import io.a2a.spec.A2AError; +import io.a2a.spec.A2AErrorCodes; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidAgentResponseError; @@ -35,22 +25,23 @@ public class A2AErrorSerializationTest { @Test public void shouldDeserializeToCorrectA2AErrorSubclass() throws JsonProcessingException { String jsonTemplate = """ - {"code": %s, "message": "error", "data": "anything"} + {"code": %s, "message": "error", "details": {"key": "anything"}} """; 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), - new ErrorCase(METHOD_NOT_FOUND_ERROR_CODE, MethodNotFoundError.class), - new ErrorCase(INVALID_PARAMS_ERROR_CODE, InvalidParamsError.class), - new ErrorCase(INTERNAL_ERROR_CODE, InternalError.class), - new ErrorCase(PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE, PushNotificationNotSupportedError.class), - new ErrorCase(UNSUPPORTED_OPERATION_ERROR_CODE, UnsupportedOperationError.class), - new ErrorCase(CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE, ContentTypeNotSupportedError.class), - 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), + List cases = List.of( + new ErrorCase(A2AErrorCodes.JSON_PARSE.code(), JSONParseError.class), + new ErrorCase(A2AErrorCodes.INVALID_REQUEST.code(), InvalidRequestError.class), + new ErrorCase(A2AErrorCodes.METHOD_NOT_FOUND.code(), MethodNotFoundError.class), + new ErrorCase(A2AErrorCodes.INVALID_PARAMS.code(), InvalidParamsError.class), + new ErrorCase(A2AErrorCodes.INTERNAL.code(), InternalError.class), + new ErrorCase(A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED.code(), PushNotificationNotSupportedError.class), + new ErrorCase(A2AErrorCodes.UNSUPPORTED_OPERATION.code(), UnsupportedOperationError.class), + new ErrorCase(A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED.code(), ContentTypeNotSupportedError.class), + new ErrorCase(A2AErrorCodes.INVALID_AGENT_RESPONSE.code(), InvalidAgentResponseError.class), + new ErrorCase(A2AErrorCodes.TASK_NOT_CANCELABLE.code(), TaskNotCancelableError.class), + new ErrorCase(A2AErrorCodes.TASK_NOT_FOUND.code(), TaskNotFoundError.class), new ErrorCase(Integer.MAX_VALUE, A2AError.class) // Any unknown code will be treated as A2AError ); @@ -59,7 +50,7 @@ record ErrorCase(int code, Class clazz) {} A2AError error = JsonUtil.fromJson(json, A2AError.class); assertInstanceOf(errorCase.clazz(), error); assertEquals("error", error.getMessage()); - assertEquals("anything", error.getData().toString()); + assertEquals("anything", error.getDetails().get("key")); } } 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 6914dc5f9..eaf6c02b3 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 @@ -580,7 +580,7 @@ private String extractTenant(RoutingContext rc) { * "error": { * "code": -32602, * "message": "Invalid params", - * "data": { ... } + * "details": { ... } * } * } * }
        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 80a30e2f6..09a45c828 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 @@ -447,7 +447,7 @@ public void testSendMessage_UnsupportedContentType_ReturnsContentTypeNotSupporte HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); when(mockErrorResponse.getStatusCode()).thenReturn(415); when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); - when(mockErrorResponse.getBody()).thenReturn("{\"type\":\"https://a2a-protocol.org/errors/content-type-not-supported\"}"); + when(mockErrorResponse.getBody()).thenReturn("{\"error\":{\"code\":415,\"status\":\"INVALID_ARGUMENT\",\"message\":\"Incompatible content types\",\"details\":[{\"reason\":\"CONTENT_TYPE_NOT_SUPPORTED\",\"domain\":\"a2a-protocol.org\"}]}}"); when(mockRestHandler.createErrorResponse(any(ContentTypeNotSupportedError.class))).thenReturn(mockErrorResponse); when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("text/plain"); @@ -465,7 +465,7 @@ public void testSendMessageStreaming_UnsupportedContentType_ReturnsContentTypeNo HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); when(mockErrorResponse.getStatusCode()).thenReturn(415); when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); - when(mockErrorResponse.getBody()).thenReturn("{\"type\":\"https://a2a-protocol.org/errors/content-type-not-supported\"}"); + when(mockErrorResponse.getBody()).thenReturn("{\"error\":{\"code\":415,\"status\":\"INVALID_ARGUMENT\",\"message\":\"Incompatible content types\",\"details\":[{\"reason\":\"CONTENT_TYPE_NOT_SUPPORTED\",\"domain\":\"a2a-protocol.org\"}]}}"); when(mockRestHandler.createErrorResponse(any(ContentTypeNotSupportedError.class))).thenReturn(mockErrorResponse); when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("text/plain"); @@ -483,7 +483,7 @@ public void testSendMessage_UnsupportedProtocolVersion_ReturnsVersionNotSupporte HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); when(mockErrorResponse.getStatusCode()).thenReturn(400); when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); - when(mockErrorResponse.getBody()).thenReturn("{\"type\":\"https://a2a-protocol.org/errors/version-not-supported\"}"); + when(mockErrorResponse.getBody()).thenReturn("{\"error\":{\"code\":400,\"status\":\"UNIMPLEMENTED\",\"message\":\"Protocol version not supported\",\"details\":[{\"reason\":\"VERSION_NOT_SUPPORTED\",\"domain\":\"a2a-protocol.org\"}]}}"); when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("application/json"); when(mockRestHandler.sendMessage(any(ServerCallContext.class), anyString(), anyString())) .thenReturn(mockErrorResponse); diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java index 8e234f9f9..15f5178a3 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java +++ b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java @@ -42,8 +42,8 @@ public void testSendMessageWithUnsupportedContentType() throws Exception { .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); Assertions.assertEquals(415, response.statusCode()); - Assertions.assertTrue(response.body().contains("content-type-not-supported"), - "Expected content-type-not-supported in response body: " + response.body()); + Assertions.assertTrue(response.body().contains("CONTENT_TYPE_NOT_SUPPORTED"), + "Expected CONTENT_TYPE_NOT_SUPPORTED in response body: " + response.body()); } @Test @@ -59,8 +59,8 @@ public void testSendMessageWithUnsupportedProtocolVersion() throws Exception { .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); Assertions.assertEquals(400, response.statusCode()); - Assertions.assertTrue(response.body().contains("version-not-supported"), - "Expected version-not-supported in response body: " + response.body()); + Assertions.assertTrue(response.body().contains("VERSION_NOT_SUPPORTED"), + "Expected VERSION_NOT_SUPPORTED in response body: " + response.body()); } @Test 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 9ea4a2a38..a21008bda 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,25 +1,13 @@ package io.a2a.grpc.utils; -import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED_ERROR; -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.A2AErrorCodes.VERSION_NOT_SUPPORTED_ERROR_CODE; +import io.a2a.spec.A2AErrorCodes; 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.Map; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; @@ -399,45 +387,37 @@ public static A2AResponse parseError(JsonObject error, Object id, String meth } } + @SuppressWarnings("unchecked") 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; + Map details = null; + if (error.has("details") && error.get("details").isJsonObject()) { + details =GSON.fromJson(error.get("details"), Map.class); + } if (code != null) { - switch (code) { - case JSON_PARSE_ERROR_CODE: - return new JSONParseError(code, message, data); - case INVALID_REQUEST_ERROR_CODE: - return new InvalidRequestError(code, message, data); - case METHOD_NOT_FOUND_ERROR_CODE: - return new MethodNotFoundError(code, message, data); - case INVALID_PARAMS_ERROR_CODE: - return new InvalidParamsError(code, message, data); - case INTERNAL_ERROR_CODE: - return new io.a2a.spec.InternalError(code, message, data); - case PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE: - return new PushNotificationNotSupportedError(code, message, data); - case UNSUPPORTED_OPERATION_ERROR_CODE: - return new UnsupportedOperationError(code, message, data); - case CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE: - return new ContentTypeNotSupportedError(code, message, data); - case INVALID_AGENT_RESPONSE_ERROR_CODE: - return new InvalidAgentResponseError(code, message, data); - case EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE: - return new ExtendedAgentCardNotConfiguredError(code, message, data); - case EXTENSION_SUPPORT_REQUIRED_ERROR: - return new ExtensionSupportRequiredError(code, message, data); - case VERSION_NOT_SUPPORTED_ERROR_CODE: - return new VersionNotSupportedError(code, message, data); - case TASK_NOT_CANCELABLE_ERROR_CODE: - return new TaskNotCancelableError(code, message, data); - case TASK_NOT_FOUND_ERROR_CODE: - return new TaskNotFoundError(message, data); - default: - return new A2AError(code, message == null ? "": message, data); - } + A2AErrorCodes errorCode = A2AErrorCodes.fromCode(code); + if (errorCode != null) { + return switch (errorCode) { + case JSON_PARSE -> new JSONParseError(code, message, details); + case INVALID_REQUEST -> new InvalidRequestError(code, message, details); + case METHOD_NOT_FOUND -> new MethodNotFoundError(code, message, details); + case INVALID_PARAMS -> new InvalidParamsError(code, message, details); + case INTERNAL -> new io.a2a.spec.InternalError(code, message, details); + case PUSH_NOTIFICATION_NOT_SUPPORTED -> new PushNotificationNotSupportedError(code, message, details); + case UNSUPPORTED_OPERATION -> new UnsupportedOperationError(code, message, details); + case CONTENT_TYPE_NOT_SUPPORTED -> new ContentTypeNotSupportedError(code, message, details); + case INVALID_AGENT_RESPONSE -> new InvalidAgentResponseError(code, message, details); + case EXTENDED_AGENT_CARD_NOT_CONFIGURED -> new ExtendedAgentCardNotConfiguredError(code, message, details); + case EXTENSION_SUPPORT_REQUIRED -> new ExtensionSupportRequiredError(code, message, details); + case VERSION_NOT_SUPPORTED -> new VersionNotSupportedError(code, message, details); + case TASK_NOT_CANCELABLE -> new TaskNotCancelableError(code, message, details); + case TASK_NOT_FOUND -> new TaskNotFoundError(message, details); + }; + } + return new A2AError(code, message == null ? "" : message, details); } - return new A2AError(INTERNAL_ERROR_CODE, message == null ? "": message, data); + return new A2AError(A2AErrorCodes.INTERNAL.code(), message == null ? "" : message, details); } protected static void parseRequestBody(JsonElement jsonRpc, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException { @@ -625,8 +605,9 @@ public static String toJsonRPCErrorResponse(Object requestId, A2AError error) { output.beginObject(); output.name("code").value(error.getCode()); output.name("message").value(error.getMessage()); - if (error.getData() != null) { - output.name("data").value(error.getData().toString()); + if (!error.getDetails().isEmpty()) { + output.name("details"); + GSON.toJson(error.getDetails(), Map.class, output); } output.endObject(); output.endObject(); diff --git a/spec/src/main/java/io/a2a/spec/A2AError.java b/spec/src/main/java/io/a2a/spec/A2AError.java index c81bbbe32..eaec2b0fe 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 java.util.Map; + import io.a2a.util.Assert; import org.jspecify.annotations.Nullable; @@ -35,24 +37,24 @@ public class A2AError extends RuntimeException implements Event { private final Integer code; /** - * Additional error information (structure defined by the error code). + * Additional error details as key-value pairs. */ - private final @Nullable Object data; + private final Map details; /** - * Constructs a JSON-RPC error with the specified code, message, and optional data. + * Constructs a JSON-RPC error with the specified code, message, and optional details. *

        * 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) + * @param details additional error details as key-value pairs (defaults to empty map if null) * @throws IllegalArgumentException if code or message is null */ - public A2AError(Integer code, String message, @Nullable Object data) { + public A2AError(Integer code, String message, @Nullable Map details) { super(Assert.checkNotNullParam("message", message)); this.code = Assert.checkNotNullParam("code", code); - this.data = data; + this.details = details == null ? Map.of() : Map.copyOf(details); } /** @@ -75,15 +77,11 @@ public Integer getCode() { } /** - * 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. + * Gets additional details about the error as key-value pairs. * - * @return the error data, or null if not provided + * @return the error details, never null (empty map if no details provided) */ - public @Nullable Object getData() { - return data; + public Map getDetails() { + return details; } } diff --git a/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java b/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java index 8eb4c6584..1143d7dfc 100644 --- a/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java +++ b/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java @@ -1,51 +1,115 @@ package io.a2a.spec; +import org.jspecify.annotations.Nullable; + /** * All the error codes for A2A errors. + *

        + * Each constant provides: + *

          + *
        • {@link #code()} - the JSON-RPC error code
        • + *
        • {@link #grpcStatus()} - the corresponding gRPC status name
        • + *
        • {@link #httpCode()} - the HTTP status code
        • + *
        + * + * @see A2A Protocol Specification - Error Code Mappings */ -public interface A2AErrorCodes { +public enum A2AErrorCodes { /** Error code indicating the requested task was not found (-32001). */ - int TASK_NOT_FOUND_ERROR_CODE = -32001; + TASK_NOT_FOUND(-32001, "NOT_FOUND", 404), /** Error code indicating the task cannot be canceled in its current state (-32002). */ - int TASK_NOT_CANCELABLE_ERROR_CODE = -32002; + TASK_NOT_CANCELABLE(-32002, "FAILED_PRECONDITION", 409), /** Error code indicating push notifications are not supported by this agent (-32003). */ - int PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE = -32003; + PUSH_NOTIFICATION_NOT_SUPPORTED(-32003, "UNIMPLEMENTED", 400), /** Error code indicating the requested operation is not supported (-32004). */ - int UNSUPPORTED_OPERATION_ERROR_CODE = -32004; + UNSUPPORTED_OPERATION(-32004, "UNIMPLEMENTED", 400), /** Error code indicating the content type is not supported (-32005). */ - int CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE = -32005; + CONTENT_TYPE_NOT_SUPPORTED(-32005, "INVALID_ARGUMENT", 415), /** Error code indicating the agent returned an invalid response (-32006). */ - int INVALID_AGENT_RESPONSE_ERROR_CODE = -32006; + INVALID_AGENT_RESPONSE(-32006, "INTERNAL", 502), /** Error code indicating extended agent card is not configured (-32007). */ - int EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE = -32007; + EXTENDED_AGENT_CARD_NOT_CONFIGURED(-32007, "FAILED_PRECONDITION", 400), /** Error code indicating client requested use of an extension marked as required: true in the Agent Card * but the client did not declare support for it in the request (-32008). */ - int EXTENSION_SUPPORT_REQUIRED_ERROR = -32008; + EXTENSION_SUPPORT_REQUIRED(-32008, "FAILED_PRECONDITION", 400), /** Error code indicating the A2A protocol version specified in the request (via A2A-Version service parameter) * is not supported by the agent (-32009). */ - int VERSION_NOT_SUPPORTED_ERROR_CODE = -32009; + VERSION_NOT_SUPPORTED(-32009, "UNIMPLEMENTED", 400), /** JSON-RPC error code for invalid request structure (-32600). */ - int INVALID_REQUEST_ERROR_CODE = -32600; + INVALID_REQUEST(-32600, "INVALID_ARGUMENT", 400), /** JSON-RPC error code for method not found (-32601). */ - int METHOD_NOT_FOUND_ERROR_CODE = -32601; + METHOD_NOT_FOUND(-32601, "NOT_FOUND", 404), /** JSON-RPC error code for invalid method parameters (-32602). */ - int INVALID_PARAMS_ERROR_CODE = -32602; + INVALID_PARAMS(-32602, "INVALID_ARGUMENT", 422), /** JSON-RPC error code for internal server errors (-32603). */ - int INTERNAL_ERROR_CODE = -32603; + INTERNAL(-32603, "INTERNAL", 500), /** JSON-RPC error code for JSON parsing errors (-32700). */ - int JSON_PARSE_ERROR_CODE = -32700; + JSON_PARSE(-32700, "INVALID_ARGUMENT", 400); + + private final int code; + private final String grpcStatus; + private final int httpCode; + + A2AErrorCodes(int code, String grpcStatus, int httpCode) { + this.code = code; + this.grpcStatus = grpcStatus; + this.httpCode = httpCode; + } + + /** + * Returns the JSON-RPC error code. + * + * @return the numeric error code + */ + public int code() { + return code; + } + + /** + * Returns the corresponding gRPC status name. + * + * @return the gRPC status string (e.g., "NOT_FOUND", "INTERNAL") + */ + public String grpcStatus() { + return grpcStatus; + } + + /** + * Returns the HTTP status code. + * + * @return the HTTP status code + */ + public int httpCode() { + return httpCode; + } + + /** + * Looks up an error code enum constant by its JSON-RPC numeric code. + * + * @param code the JSON-RPC error code + * @return the matching enum constant, or {@code null} if not found + */ + public static @Nullable A2AErrorCodes fromCode(int code) { + for (A2AErrorCodes e : values()) { + if (e.code == code) { + return e; + } + } + return null; + } + } diff --git a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java b/spec/src/main/java/io/a2a/spec/A2AProtocolError.java index b03ba4080..dfa4e961e 100644 --- a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java +++ b/spec/src/main/java/io/a2a/spec/A2AProtocolError.java @@ -1,46 +1,28 @@ package io.a2a.spec; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** - * Represents a protocol-level error in the A2A Protocol with a reference URL. + * Represents a protocol-level error in the A2A Protocol. *

        - * This error extends {@link A2AError} to include a URL field that provides a reference - * to documentation, specification details, or additional context about the protocol error. - * This is particularly useful for protocol version mismatches, unsupported features, or - * other situations where pointing to the protocol specification would help diagnose the issue. + * This error extends {@link A2AError} to distinguish A2A protocol-specific errors + * from standard JSON-RPC errors. Protocol errors have dedicated error codes in the + * A2A specification. * * @see A2AError for the base error implementation */ public class A2AProtocolError extends A2AError { /** - * URL reference for additional information about this protocol error. - */ - private final @Nullable String url; - - /** - * Constructs a protocol error with the specified code, message, data, and reference URL. + * Constructs a protocol error with the specified code, message, and details. * * @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) - * @param url URL reference providing additional context about this protocol error (optional) - */ - public A2AProtocolError(Integer code, String message, @Nullable Object data, @Nullable String url) { - super(code, message, data); - this.url = url; - } - - /** - * Gets the URL reference for additional information about this protocol error. - *

        - * This URL typically points to protocol specification documentation or other resources - * that provide context about the error condition. - * - * @return the reference URL, or null if not provided + * @param details additional error details as key-value pairs (defaults to empty map if null) */ - public @Nullable String getUrl() { - return url; + public A2AProtocolError(Integer code, String message, @Nullable Map details) { + super(code, message, details); } } diff --git a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java index cb657967c..b87addb87 100644 --- a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** @@ -48,12 +49,11 @@ public ContentTypeNotSupportedError() { * * @param code the error code * @param message the error message - * @param data additional error data + * @param details additional error details */ - public ContentTypeNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super(defaultIfNull(code, CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE), + public ContentTypeNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { + super(defaultIfNull(code, A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED.code()), defaultIfNull(message, "Incompatible content types"), - data, - "https://a2a-protocol.org/errors/content-type-not-supported"); + details); } } diff --git a/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java b/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java index 5b961e2bf..941788abd 100644 --- a/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java +++ b/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; @@ -36,13 +37,12 @@ public class ExtendedAgentCardNotConfiguredError extends A2AProtocolError { * * @param code the error code * @param message the error message - * @param data additional error data + * @param details additional error details */ - public ExtendedAgentCardNotConfiguredError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public ExtendedAgentCardNotConfiguredError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED.code()), defaultIfNull(message, "Extended Card not configured"), - data, - "https://a2a-protocol.org/errors/extended-agent-card-not-configured"); + details); } } diff --git a/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java b/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java index abb11aa9f..fd7882202 100644 --- a/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java +++ b/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED_ERROR; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; @@ -36,13 +37,12 @@ public class ExtensionSupportRequiredError extends A2AProtocolError { * * @param code the error code (defaults to -32008 if null) * @param message the error message (defaults to standard message if null) - * @param data additional error data (optional) + * @param details additional error details (optional) */ - public ExtensionSupportRequiredError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public ExtensionSupportRequiredError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, EXTENSION_SUPPORT_REQUIRED_ERROR), + defaultIfNull(code, A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED.code()), defaultIfNull(message, "Extension support required but not declared"), - data, - "https://a2a-protocol.org/errors/extension-support-required"); + details); } } diff --git a/spec/src/main/java/io/a2a/spec/InternalError.java b/spec/src/main/java/io/a2a/spec/InternalError.java index 5d9793972..d6809f314 100644 --- a/spec/src/main/java/io/a2a/spec/InternalError.java +++ b/spec/src/main/java/io/a2a/spec/InternalError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; @@ -34,13 +35,13 @@ public class InternalError extends A2AError { * * @param code the error code * @param message the error message - * @param data additional error data + * @param details additional error details */ - public InternalError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public InternalError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, INTERNAL_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.INTERNAL.code()), defaultIfNull(message, "Internal Error"), - data); + details); } /** diff --git a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java b/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java index d6d8508d9..c6c2c2cc2 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; @@ -44,13 +45,12 @@ public class InvalidAgentResponseError extends A2AProtocolError { * * @param code the error code * @param message the error message - * @param data additional error data + * @param details additional error details */ - public InvalidAgentResponseError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public InvalidAgentResponseError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, INVALID_AGENT_RESPONSE_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.INVALID_AGENT_RESPONSE.code()), defaultIfNull(message, "Invalid agent response"), - data, - "https://a2a-protocol.org/errors/invalid-agent-response"); + details); } } diff --git a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java index a56f1ac91..6c6751d41 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.INVALID_PARAMS_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** @@ -37,13 +38,13 @@ public class InvalidParamsError extends A2AError { * * @param code the error code * @param message the error message - * @param data additional error data + * @param details additional error details */ - public InvalidParamsError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public InvalidParamsError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, INVALID_PARAMS_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.INVALID_PARAMS.code()), defaultIfNull(message, "Invalid parameters"), - data); + details); } /** diff --git a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java index 512c21b59..151f0631f 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.INVALID_REQUEST_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; @@ -45,13 +46,13 @@ public InvalidRequestError() { * * @param code the error code * @param message the error message - * @param data additional error data + * @param details additional error details */ - public InvalidRequestError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public InvalidRequestError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, INVALID_REQUEST_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.INVALID_REQUEST.code()), defaultIfNull(message, "Request payload validation error"), - data); + details); } /** diff --git a/spec/src/main/java/io/a2a/spec/JSONParseError.java b/spec/src/main/java/io/a2a/spec/JSONParseError.java index 72e4aaf02..5349add2d 100644 --- a/spec/src/main/java/io/a2a/spec/JSONParseError.java +++ b/spec/src/main/java/io/a2a/spec/JSONParseError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** @@ -51,12 +52,12 @@ public JSONParseError(String message) { * * @param code the error code * @param message the error message - * @param data additional error data + * @param details additional error details */ - public JSONParseError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public JSONParseError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, JSON_PARSE_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.JSON_PARSE.code()), defaultIfNull(message, "Invalid JSON payload"), - data); + details); } } diff --git a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java index c69aaa572..b97f5acae 100644 --- a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.METHOD_NOT_FOUND_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** @@ -29,19 +30,19 @@ public class MethodNotFoundError extends A2AError { * * @param code the error code (defaults to -32601 if null) * @param message the error message (defaults to "Method not found" if null) - * @param data additional error data (optional) + * @param details additional error details (optional) */ - public MethodNotFoundError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public MethodNotFoundError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, METHOD_NOT_FOUND_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.METHOD_NOT_FOUND.code()), defaultIfNull(message, "Method not found"), - data); + details); } /** * Constructs error with default message. */ public MethodNotFoundError() { - this(METHOD_NOT_FOUND_ERROR_CODE, null, null); + this(A2AErrorCodes.METHOD_NOT_FOUND.code(), null, null); } } diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java b/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java index c84f4d79f..e167bb64a 100644 --- a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** @@ -42,13 +43,12 @@ public PushNotificationNotSupportedError() { * * @param code the error code (defaults to -32003 if null) * @param message the error message (defaults to "Push Notification is not supported" if null) - * @param data additional error data (optional) + * @param details additional error details (optional) */ - public PushNotificationNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public PushNotificationNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED.code()), defaultIfNull(message, "Push Notification is not supported"), - data, - "https://a2a-protocol.org/errors/push-notification-not-supported"); + details); } } diff --git a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java index 83e19ec54..49d86fa52 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** @@ -45,14 +46,13 @@ public TaskNotCancelableError() { * * @param code the error code (defaults to -32002 if null) * @param message the error message (defaults to "Task cannot be canceled" if null) - * @param data additional error data (optional) + * @param details additional error details (optional) */ - public TaskNotCancelableError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public TaskNotCancelableError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, TASK_NOT_CANCELABLE_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.TASK_NOT_CANCELABLE.code()), defaultIfNull(message, "Task cannot be canceled"), - data, - "https://a2a-protocol.org/errors/task-not-cancelable"); + details); } /** diff --git a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java index 523d44f40..817175f84 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** @@ -45,13 +46,12 @@ public TaskNotFoundError() { * Constructs error with all parameters. * * @param message the error message (defaults to "Task not found" if null) - * @param data additional error data (optional) + * @param details additional error details (optional) */ - public TaskNotFoundError(@Nullable String message, @Nullable Object data) { + public TaskNotFoundError(@Nullable String message, @Nullable Map details) { super( - TASK_NOT_FOUND_ERROR_CODE, + A2AErrorCodes.TASK_NOT_FOUND.code(), defaultIfNull(message, "Task not found"), - data, - "https://a2a-protocol.org/errors/task-not-found"); + details); } } diff --git a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java index 65bdbed9a..a0ced6f74 100644 --- a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java +++ b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; /** @@ -40,14 +41,13 @@ public class UnsupportedOperationError extends A2AProtocolError { * * @param code the error code (defaults to -32004 if null) * @param message the error message (defaults to "This operation is not supported" if null) - * @param data additional error data (optional) + * @param details additional error details (optional) */ - public UnsupportedOperationError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public UnsupportedOperationError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, UNSUPPORTED_OPERATION_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.UNSUPPORTED_OPERATION.code()), defaultIfNull(message, "This operation is not supported"), - data, - "https://a2a-protocol.org/errors/unsupported-operation"); + details); } /** diff --git a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java index f4caf5e77..41dbed471 100644 --- a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java @@ -1,8 +1,9 @@ package io.a2a.spec; -import static io.a2a.spec.A2AErrorCodes.VERSION_NOT_SUPPORTED_ERROR_CODE; import static io.a2a.util.Utils.defaultIfNull; +import java.util.Map; + import org.jspecify.annotations.Nullable; @@ -35,13 +36,12 @@ public class VersionNotSupportedError extends A2AProtocolError { * * @param code the error code (defaults to -32009 if null) * @param message the error message (defaults to standard message if null) - * @param data additional error data (optional) + * @param details additional error details (optional) */ - public VersionNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + public VersionNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Map details) { super( - defaultIfNull(code, VERSION_NOT_SUPPORTED_ERROR_CODE), + defaultIfNull(code, A2AErrorCodes.VERSION_NOT_SUPPORTED.code()), defaultIfNull(message, "Protocol version not supported"), - data, - "https://a2a-protocol.org/errors/version-not-supported"); + details); } } 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 4eb8c7223..fe21c5ce3 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 @@ -21,6 +21,7 @@ import io.a2a.common.A2AErrorMessages; import io.a2a.grpc.A2AServiceGrpc; import io.a2a.grpc.StreamResponse; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.AgentCardValidator; import io.a2a.server.ServerCallContext; @@ -56,12 +57,14 @@ import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TransportProtocol; +import io.a2a.spec.A2AErrorCodes; import io.a2a.spec.UnsupportedOperationError; import io.a2a.spec.VersionNotSupportedError; import io.a2a.transport.grpc.context.GrpcContextKeys; import io.grpc.Context; import io.grpc.Metadata; import io.grpc.Status; +import io.grpc.protobuf.StatusProto; import io.grpc.stub.StreamObserver; import org.jspecify.annotations.Nullable; @@ -719,55 +722,26 @@ private ServerCallContext createCallContext(StreamObserver responseObserv * @param error the A2A protocol error */ private void handleError(StreamObserver responseObserver, A2AError error) { - Status status; - String description; - if (error instanceof InvalidRequestError) { - status = Status.INVALID_ARGUMENT; - description = "InvalidRequestError: " + error.getMessage(); - } else if (error instanceof MethodNotFoundError) { - status = Status.NOT_FOUND; - description = "MethodNotFoundError: " + error.getMessage(); - } else if (error instanceof InvalidParamsError) { - status = Status.INVALID_ARGUMENT; - description = "InvalidParamsError: " + error.getMessage(); - } else if (error instanceof InternalError) { - status = Status.INTERNAL; - description = "InternalError: " + error.getMessage(); - } else if (error instanceof TaskNotFoundError) { - status = Status.NOT_FOUND; - description = "TaskNotFoundError: " + error.getMessage(); - } else if (error instanceof TaskNotCancelableError) { - status = Status.FAILED_PRECONDITION; - description = "TaskNotCancelableError: " + error.getMessage(); - } else if (error instanceof PushNotificationNotSupportedError) { - status = Status.UNIMPLEMENTED; - description = "PushNotificationNotSupportedError: " + error.getMessage(); - } else if (error instanceof UnsupportedOperationError) { - status = Status.UNIMPLEMENTED; - description = "UnsupportedOperationError: " + error.getMessage(); - } else if (error instanceof JSONParseError) { - status = Status.INTERNAL; - description = "JSONParseError: " + error.getMessage(); - } else if (error instanceof ContentTypeNotSupportedError) { - status = Status.INVALID_ARGUMENT; - description = "ContentTypeNotSupportedError: " + error.getMessage(); - } else if (error instanceof InvalidAgentResponseError) { - status = Status.INTERNAL; - description = "InvalidAgentResponseError: " + error.getMessage(); - } else if (error instanceof ExtendedAgentCardNotConfiguredError) { - status = Status.FAILED_PRECONDITION; - description = "ExtendedCardNotConfiguredError: " + error.getMessage(); - } else if (error instanceof ExtensionSupportRequiredError) { - status = Status.FAILED_PRECONDITION; - description = "ExtensionSupportRequiredError: " + error.getMessage(); - } else if (error instanceof VersionNotSupportedError) { - status = Status.UNIMPLEMENTED; - description = "VersionNotSupportedError: " + error.getMessage(); - } else { - status = Status.UNKNOWN; - description = "Unknown error type: " + error.getMessage(); + A2AErrorCodes errorCode = A2AErrorCodes.fromCode(error.getCode()); + String grpcStatusName = errorCode != null ? errorCode.grpcStatus() : "UNKNOWN"; + String reason = errorCode != null ? errorCode.name() : "UNKNOWN"; + int grpcCode = Status.Code.valueOf(grpcStatusName).value(); + + com.google.rpc.ErrorInfo.Builder errorInfoBuilder = com.google.rpc.ErrorInfo.newBuilder() + .setReason(reason) + .setDomain("a2a-protocol.org"); + if (!error.getDetails().isEmpty()) { + error.getDetails().forEach((k, v) -> + errorInfoBuilder.putMetadata(k, v instanceof String s ? s : JsonUtil.OBJECT_MAPPER.toJson(v))); } - responseObserver.onError(status.withDescription(description).asRuntimeException()); + + com.google.rpc.Status rpcStatus = com.google.rpc.Status.newBuilder() + .setCode(grpcCode) + .setMessage(error.getMessage() != null ? error.getMessage() : "") + .addDetails(com.google.protobuf.Any.pack(errorInfoBuilder.build())) + .build(); + + responseObserver.onError(StatusProto.toStatusRuntimeException(rpcStatus)); } /** 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 c0feac4d7..b26b58c53 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 @@ -1185,8 +1185,21 @@ private void sendStreamingMessageRequest(GrpcHandler handler, StreamObserver void assertGrpcError(StreamRecorder streamRecorder, Status.Code expectedStatusCode) { Assertions.assertNotNull(streamRecorder.getError()); Assertions.assertInstanceOf(StatusRuntimeException.class, streamRecorder.getError()); - Assertions.assertEquals(expectedStatusCode, ((StatusRuntimeException) streamRecorder.getError()).getStatus().getCode()); + StatusRuntimeException sre = (StatusRuntimeException) streamRecorder.getError(); + Assertions.assertEquals(expectedStatusCode, sre.getStatus().getCode()); Assertions.assertTrue(streamRecorder.getValues().isEmpty()); + + // Verify ErrorInfo is present in status details + com.google.rpc.Status rpcStatus = io.grpc.protobuf.StatusProto.fromThrowable(sre); + Assertions.assertNotNull(rpcStatus, "rpc status should be present"); + Assertions.assertFalse(rpcStatus.getDetailsList().isEmpty(), "details should not be empty"); + try { + com.google.rpc.ErrorInfo errorInfo = rpcStatus.getDetails(0).unpack(com.google.rpc.ErrorInfo.class); + Assertions.assertEquals("a2a-protocol.org", errorInfo.getDomain()); + Assertions.assertFalse(errorInfo.getReason().isEmpty(), "reason should not be empty"); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + Assertions.fail("Failed to unpack ErrorInfo: " + e.getMessage()); + } } @Test 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 a5a9b6d77..9cb20bea6 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,12 +3,14 @@ import static io.a2a.common.MediaType.APPLICATION_JSON; import static io.a2a.common.MediaType.APPLICATION_PROBLEM_JSON; import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; -import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; + +import io.a2a.spec.A2AErrorCodes; import java.time.Instant; import java.time.format.DateTimeParseException; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -40,10 +42,11 @@ import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.ContentTypeNotSupportedError; +import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; +import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidAgentResponseError; @@ -64,7 +67,6 @@ import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TaskState; import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.VersionNotSupportedError; import mutiny.zero.ZeroPublisher; import org.jspecify.annotations.Nullable; @@ -647,7 +649,7 @@ private void validate(String json) { try { JsonParser.parseString(json); } catch (JsonSyntaxException e) { - throw new JSONParseError(JSON_PARSE_ERROR_CODE, "Failed to parse json", e.getMessage()); + throw new JSONParseError(A2AErrorCodes.JSON_PARSE.code(), "Failed to parse json", null); } } @@ -745,27 +747,15 @@ public void onComplete() { } /** - * Maps A2A protocol errors to HTTP status codes. - * - *

        - * This method ensures consistent HTTP status code mapping for all A2A errors: - *

          - *
        • 400 - Invalid request, JSON parse errors, missing extensions
        • - *
        • 404 - Method not found, task not found
        • - *
        • 409 - Task not cancelable (conflict)
        • - *
        • 415 - Unsupported content type
        • - *
        • 422 - Invalid parameters (unprocessable entity)
        • - *
        • 500 - Internal errors
        • - *
        • 501 - Not implemented (unsupported operations, version)
        • - *
        • 502 - Bad gateway (invalid agent response)
        • - *
        + * Maps A2A protocol errors to HTTP status codes using {@link A2AErrorCodes}. * * @param error the A2A error to map * @return the corresponding HTTP status code */ private static int mapErrorToHttpStatus(A2AError error) { - if (error instanceof InvalidRequestError || error instanceof JSONParseError) { - return 400; + A2AErrorCodes errorCode = A2AErrorCodes.fromCode(error.getCode()); + if (errorCode != null) { + return errorCode.httpCode(); } if (error instanceof InvalidParamsError) { return 422; @@ -797,63 +787,6 @@ private static int mapErrorToHttpStatus(A2AError error) { return 500; } - /** - * Maps A2A protocol errors to RFC 7807 Problem Details type URIs. - * - *

        - * This method provides a unique URI for each A2A error type, which is used in the "type" - * field of RFC 7807 error responses. For example: - *

          - *
        • {@link InvalidRequestError} -> "https://a2a-protocol.org/errors/invalid-request"
        • - *
        • {@link TaskNotFoundError} -> "https://a2a-protocol.org/errors/task-not-found"
        • - *
        - * - * @param error the A2A error to map - * @return the corresponding RFC 7807 type URI - */ - private static String mapErrorToURI(A2AError error) { - if (error instanceof InvalidRequestError || error instanceof JSONParseError) { - return "https://a2a-protocol.org/errors/invalid-request"; - } - if (error instanceof InvalidParamsError) { - return "https://a2a-protocol.org/errors/invalid-params"; - } - if (error instanceof MethodNotFoundError) { - return "https://a2a-protocol.org/errors/method-not-found"; - } - if (error instanceof TaskNotFoundError) { - return "https://a2a-protocol.org/errors/task-not-found"; - } - if (error instanceof TaskNotCancelableError) { - return "https://a2a-protocol.org/errors/task-not-cancelable"; - } - if (error instanceof PushNotificationNotSupportedError) { - return "https://a2a-protocol.org/errors/push-notification-not-supported"; - } - if (error instanceof UnsupportedOperationError) { - return "https://a2a-protocol.org/errors/unsupported-operation"; - } - if (error instanceof VersionNotSupportedError) { - return "https://a2a-protocol.org/errors/version-not-supported"; - } - if (error instanceof ContentTypeNotSupportedError) { - return "https://a2a-protocol.org/errors/content-type-not-supported"; - } - if (error instanceof InvalidAgentResponseError) { - return "https://a2a-protocol.org/errors/invalid-agent-response"; - } - if (error instanceof ExtendedAgentCardNotConfiguredError) { - return "https://a2a-protocol.org/errors/extended-agent-card-not-configured"; - } - if (error instanceof ExtensionSupportRequiredError) { - return "https://a2a-protocol.org/errors/extension-support-required"; - } - if (error instanceof InternalError) { - return "https://a2a-protocol.org/errors/internal-error"; - } - return "https://a2a-protocol.org/errors/internal-error"; - } - /** * Retrieves the extended agent card if configured. * @@ -1017,27 +950,46 @@ public Flow.Publisher getPublisher() { } } + private static final String ERROR_INFO_TYPE = "type.googleapis.com/google.rpc.ErrorInfo"; + private static final String ERROR_DOMAIN = "a2a-protocol.org"; + /** - * Represents an HTTP error response containing A2A error details. + * Represents an HTTP error response containing A2A error details in the Google Cloud API error format. + *

        + * Produces JSON of the form: + *

        {@code
        +     * {
        +     *   "error": {
        +     *     "code": 404,
        +     *     "status": "NOT_FOUND",
        +     *     "message": "Task not found",
        +     *     "details": [
        +     *       {
        +     *         "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        +     *         "reason": "TASK_NOT_FOUND",
        +     *         "domain": "a2a-protocol.org",
        +     *         "metadata": { ... }
        +     *       }
        +     *     ]
        +     *   }
        +     * }
        +     * }
        */ private static class HTTPRestErrorResponse { - private final String title; - private final String details; - private final int status; - private final String type; + private final ErrorBody error; + private HTTPRestErrorResponse(A2AError a2aError) { + A2AErrorCodes errorCode = A2AErrorCodes.fromCode(a2aError.getCode()); + int httpCode = mapErrorToHttpStatus(a2aError); + String status = errorCode != null + ? errorCode.grpcStatus() + : A2AErrorCodes.INTERNAL.grpcStatus(); + String reason = errorCode != null ? errorCode.name() : "INTERNAL"; + String message = a2aError.getMessage() == null ? a2aError.getClass().getName() : a2aError.getMessage(); - /** - * Creates an error response from an A2A error. - * - * @param jsonRpcError the A2A error - */ - private HTTPRestErrorResponse(A2AError jsonRpcError) { - this.title = jsonRpcError.getMessage() == null ? jsonRpcError.getClass().getName() : jsonRpcError.getMessage(); - this.details = jsonRpcError.getData() == null ? "" : jsonRpcError.getData().toString(); - this.type = mapErrorToURI(jsonRpcError); - this.status = mapErrorToHttpStatus(jsonRpcError); + ErrorDetail detail = new ErrorDetail(ERROR_INFO_TYPE, reason, ERROR_DOMAIN, a2aError.getDetails()); + this.error = new ErrorBody(httpCode, status, message, List.of(detail)); } private String toJson() { @@ -1045,14 +997,21 @@ private String toJson() { return JsonUtil.toJson(this); } catch (JsonProcessingException ex) { log.log(Level.SEVERE, "Failed to serialize HTTPRestErrorResponse to JSON", ex); - return "{\"title\":\"Internal Server Error\",\"details\":\"Failed to serialize error response.\",\"status\":500,\"type\":\"https://a2a-protocol.org/errors/internal-error\"}"; + return "{\"error\":{\"code\":500,\"status\":\"INTERNAL\",\"message\":\"Internal Server Error\",\"details\":[]}}"; } } @Override public String toString() { - return "HTTPRestErrorResponse{" + "title=" + title + ", details=" + details + ", status=" + status + ", type=" + type + '}'; + return "HTTPRestErrorResponse{error=" + error + '}'; } + private record ErrorBody(int code, String status, String message, List details) {} + + private record ErrorDetail( + @com.google.gson.annotations.SerializedName("@type") String type, + String reason, + String domain, + Map metadata) {} } } 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 5d42c436b..d07f5a42c 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 @@ -56,7 +56,7 @@ public void testGetTaskNotFound() { RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", "nonexistent", 0); assertProblemDetail(response, 404, - "https://a2a-protocol.org/errors/task-not-found", "Task not found"); + "TASK_NOT_FOUND", "Task not found"); } @Test @@ -66,7 +66,7 @@ public void testGetTaskNegativeHistoryLengthReturns422() { RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", MINIMAL_TASK.id(), -1); assertProblemDetail(response, 422, - "https://a2a-protocol.org/errors/invalid-params", "Invalid history length"); + "INVALID_PARAMS", "Invalid history length"); } @Test @@ -90,7 +90,7 @@ public void testListTasksInvalidStatus() { null, null, null); assertProblemDetail(response, 422, - "https://a2a-protocol.org/errors/invalid-params", "Invalid params"); + "INVALID_PARAMS", "Invalid params"); } @Test @@ -132,7 +132,7 @@ public void testSendMessageInvalidBody() { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", invalidBody); assertProblemDetail(response, 400, - "https://a2a-protocol.org/errors/invalid-request", "Failed to parse json"); + "JSON_PARSE", "Failed to parse json"); } @Test @@ -157,10 +157,11 @@ public void testSendMessageWrongValueBody() { Assertions.assertEquals(422, response.getStatusCode()); Assertions.assertEquals("application/problem+json", response.getContentType()); JsonObject body = JsonParser.parseString(response.getBody()).getAsJsonObject(); - Assertions.assertEquals(422, body.get("status").getAsInt()); - Assertions.assertEquals("https://a2a-protocol.org/errors/invalid-params", body.get("type").getAsString()); - Assertions.assertTrue(body.get("title").getAsString().startsWith("Failed to parse request body:"), - "title should indicate parse failure: " + body.get("title").getAsString()); + JsonObject error = body.getAsJsonObject("error"); + Assertions.assertEquals(422, error.get("code").getAsInt()); + Assertions.assertEquals("INVALID_PARAMS", error.getAsJsonArray("details").get(0).getAsJsonObject().get("reason").getAsString()); + Assertions.assertTrue(error.get("message").getAsString().startsWith("Failed to parse request body:"), + "message should indicate parse failure: " + error.get("message").getAsString()); } @Test @@ -170,7 +171,7 @@ public void testSendMessageEmptyBody() { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", ""); assertProblemDetail(response, 400, - "https://a2a-protocol.org/errors/invalid-request", "Request body is required"); + "INVALID_REQUEST", "Request body is required"); } @Test @@ -202,7 +203,7 @@ public void testCancelTaskNotFound() { RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, "nonexistent"); assertProblemDetail(response, 404, - "https://a2a-protocol.org/errors/task-not-found", "Task not found"); + "TASK_NOT_FOUND", "Task not found"); } @Test @@ -347,7 +348,7 @@ public void testSendStreamingMessageNotSupported() { RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); assertProblemDetail(response, 400, - "https://a2a-protocol.org/errors/invalid-request", + "INVALID_REQUEST", "Streaming is not supported by the agent"); } @@ -389,7 +390,7 @@ public void testPushNotificationConfigNotSupported() { RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", requestBody, MINIMAL_TASK.id()); assertProblemDetail(response, 400, - "https://a2a-protocol.org/errors/push-notification-not-supported", + "PUSH_NOTIFICATION_NOT_SUPPORTED", "Push Notification is not supported"); } @@ -577,7 +578,7 @@ public void testExtensionSupportRequiredErrorOnSendMessage() { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); assertProblemDetail(response, 400, - "https://a2a-protocol.org/errors/extension-support-required", + "EXTENSION_SUPPORT_REQUIRED", "Required extension 'https://example.com/test-extension' was not requested by the client"); } @@ -642,11 +643,17 @@ public void onSubscribe(Flow.Subscription subscription) { @Override public void onNext(String item) { - JsonObject error = JsonParser.parseString(item).getAsJsonObject(); - if ("https://a2a-protocol.org/errors/extension-support-required".equals( - error.has("type") ? error.get("type").getAsString() : null) && - item.contains("https://example.com/streaming-extension")) { - errorFound.set(true); + JsonObject body = JsonParser.parseString(item).getAsJsonObject(); + if (body.has("error")) { + JsonObject error = body.getAsJsonObject("error"); + var details = error.has("details") ? error.getAsJsonArray("details") : null; + if (details != null && !details.isEmpty()) { + String reason = details.get(0).getAsJsonObject().get("reason").getAsString(); + if ("EXTENSION_SUPPORT_REQUIRED".equals(reason) && + item.contains("https://example.com/streaming-extension")) { + errorFound.set(true); + } + } } latch.countDown(); } @@ -778,7 +785,7 @@ public void testVersionNotSupportedErrorOnSendMessage() { RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithVersion, "", requestBody); assertProblemDetail(response, 400, - "https://a2a-protocol.org/errors/version-not-supported", + "VERSION_NOT_SUPPORTED", "Protocol version '2.0' is not supported. Supported versions: [1.0]"); } @@ -845,11 +852,17 @@ public void onSubscribe(Flow.Subscription subscription) { @Override public void onNext(String item) { - JsonObject error = JsonParser.parseString(item).getAsJsonObject(); - if ("https://a2a-protocol.org/errors/version-not-supported".equals( - error.has("type") ? error.get("type").getAsString() : null) && - error.has("title") && error.get("title").getAsString().contains("2.0")) { - errorFound.set(true); + JsonObject body = JsonParser.parseString(item).getAsJsonObject(); + if (body.has("error")) { + JsonObject error = body.getAsJsonObject("error"); + var details = error.has("details") ? error.getAsJsonArray("details") : null; + if (details != null && !details.isEmpty()) { + String reason = details.get(0).getAsJsonObject().get("reason").getAsString(); + if ("VERSION_NOT_SUPPORTED".equals(reason) && + error.has("message") && error.get("message").getAsString().contains("2.0")) { + errorFound.set(true); + } + } } } @@ -984,7 +997,7 @@ public void testListTasksNegativeTimestampReturns422() { null, "-1", null); assertProblemDetail(response, 422, - "https://a2a-protocol.org/errors/invalid-params", "Invalid params"); + "INVALID_PARAMS", "Invalid params"); } @Test @@ -1047,13 +1060,21 @@ public void testListTasksEmptyResultIncludesAllFields() { } private static void assertProblemDetail(RestHandler.HTTPRestResponse response, - int expectedStatus, String expectedType, String expectedTitle) { + int expectedStatus, String expectedReason, String expectedMessage) { Assertions.assertEquals(expectedStatus, response.getStatusCode()); Assertions.assertEquals("application/problem+json", response.getContentType()); JsonObject body = JsonParser.parseString(response.getBody()).getAsJsonObject(); - Assertions.assertEquals(expectedStatus, body.get("status").getAsInt(), "status field mismatch"); - Assertions.assertEquals(expectedType, body.get("type").getAsString(), "type field mismatch"); - Assertions.assertEquals(expectedTitle, body.get("title").getAsString(), "title field mismatch"); - Assertions.assertTrue(body.has("details"), "details field should be present"); + Assertions.assertTrue(body.has("error"), "error wrapper should be present"); + JsonObject error = body.getAsJsonObject("error"); + Assertions.assertEquals(expectedStatus, error.get("code").getAsInt(), "code field mismatch"); + Assertions.assertEquals(expectedMessage, error.get("message").getAsString(), "message field mismatch"); + Assertions.assertTrue(error.has("status"), "status field should be present"); + Assertions.assertTrue(error.has("details"), "details field should be present"); + var details = error.getAsJsonArray("details"); + Assertions.assertFalse(details.isEmpty(), "details array should not be empty"); + JsonObject detail = details.get(0).getAsJsonObject(); + Assertions.assertEquals("type.googleapis.com/google.rpc.ErrorInfo", detail.get("@type").getAsString(), "@type field mismatch"); + Assertions.assertEquals(expectedReason, detail.get("reason").getAsString(), "reason field mismatch"); + Assertions.assertEquals("a2a-protocol.org", detail.get("domain").getAsString(), "domain field mismatch"); } } From 100bf867e2a51f663a4e0cf05cc4fedc0895f7da Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 26 Mar 2026 09:24:58 +0000 Subject: [PATCH 097/192] feat: Add HTTP caching headers to Agent Card endpoint (#761) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements A2A specification section 8.6 caching requirements: - Cache-Control header with configurable max-age - ETag header derived from Agent Card content hash - Last-Modified header with initialization timestamp **Implementation:** - Created AgentCardCacheMetadata bean in server-common to compute and cache HTTP headers at initialization - Enhanced HTTPRestResponse to support additional headers via Map - Updated RestHandler and JSON-RPC A2AServerRoutes to include caching headers - Caching headers applied to both REST and JSON-RPC transports (gRPC out of scope per spec) **Configuration:** - Max-age configurable via `a2a.agent-card.cache.max-age` (default: 3600 seconds) - ETag calculated as MD5 hash of serialized Agent Card JSON - Last-Modified set to bean initialization time in RFC 1123 format **Testing:** - Added testAgentCardHeaders() to AbstractA2AServerTest - Validates all three caching headers are present and correctly formatted - gRPC test overrides to skip (HTTP-only requirement) Fixes #749 🦕 Co-authored-by: Claude Sonnet 4.5 --- .../grpc/quarkus/QuarkusA2AGrpcTest.java | 6 + .../server/apps/quarkus/A2AServerRoutes.java | 18 +- .../server/rest/quarkus/A2AServerRoutes.java | 10 +- .../io/a2a/server/AgentCardCacheMetadata.java | 190 ++++++++++++++++++ .../apps/common/AbstractA2AServerTest.java | 42 ++++ .../transport/rest/handler/RestHandler.java | 39 +++- .../rest/handler/RestHandlerTest.java | 82 ++++---- 7 files changed, 343 insertions(+), 44 deletions(-) create mode 100644 server-common/src/main/java/io/a2a/server/AgentCardCacheMetadata.java 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 24320b94d..7423edda0 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 @@ -50,4 +50,10 @@ public static void closeChannel() { Thread.currentThread().interrupt(); } } + + @Override + public void testAgentCardHeaders() { + // Skip - gRPC doesn't use HTTP caching headers for Agent Card + // The A2A spec section 8.6 caching requirements apply only to HTTP endpoints + } } \ No newline at end of file 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 eaf6c02b3..56fd4dea9 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 @@ -173,6 +173,9 @@ public class A2AServerRoutes { @Inject JSONRPCHandler jsonRpcHandler; + @Inject + io.a2a.server.AgentCardCacheMetadata cacheMetadata; + // Hook so testing can wait until the MultiSseSupport is subscribed. // Without this we get intermittent failures private static volatile Runnable streamingMultiSseSupportSubscribedRunnable; @@ -322,6 +325,13 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { *

        Returns the agent's capabilities and metadata in JSON format according to the * A2A protocol specification. This endpoint is publicly accessible (no authentication). * + *

        Includes HTTP caching headers per A2A specification section 8.6: + *

          + *
        • {@code Cache-Control} - with max-age directive
        • + *
        • {@code ETag} - content hash for validation
        • + *
        • {@code Last-Modified} - timestamp when agent card was initialized
        • + *
        + * *

        Request: *

        {@code
              * GET /.well-known/agent-card.json
        @@ -331,6 +341,9 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) {
              * 
        {@code
              * HTTP/1.1 200 OK
              * Content-Type: application/json
        +     * Cache-Control: public, max-age=3600
        +     * ETag: "a1b2c3d4..."
        +     * Last-Modified: Mon, 17 Mar 2025 10:00:00 GMT
              *
              * {
              *   "name": "My Agent",
        @@ -343,12 +356,15 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) {
              * }
              * }
        * + * @param rc the Vert.x routing context * @return the agent card as a JSON string * @throws JsonProcessingException if serialization fails * @see JSONRPCHandler#getAgentCard() */ @Route(path = "/.well-known/agent-card.json", methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) - public String getAgentCard() throws JsonProcessingException { + public String getAgentCard(RoutingContext rc) throws JsonProcessingException { + // Add caching headers per A2A specification section 8.6 + cacheMetadata.getHttpHeadersMap().forEach((k, v) -> rc.response().putHeader(k, v)); return JsonUtil.toJson(jsonRpcHandler.getAgentCard()); } 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 11f5ab299..03bdbd5e5 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 @@ -380,10 +380,14 @@ public void cancelTask(@Body String body, RoutingContext rc) { */ private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response) { if (response != null) { - rc.response() + var httpResponse = rc.response() .setStatusCode(response.getStatusCode()) - .putHeader(CONTENT_TYPE, response.getContentType()) - .end(response.getBody()); + .putHeader(CONTENT_TYPE, response.getContentType()); + + // Add any additional headers from the response + response.getHeaders().forEach(httpResponse::putHeader); + + httpResponse.end(response.getBody()); } else { rc.response().end(); } diff --git a/server-common/src/main/java/io/a2a/server/AgentCardCacheMetadata.java b/server-common/src/main/java/io/a2a/server/AgentCardCacheMetadata.java new file mode 100644 index 000000000..573ac9384 --- /dev/null +++ b/server-common/src/main/java/io/a2a/server/AgentCardCacheMetadata.java @@ -0,0 +1,190 @@ +package io.a2a.server; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.HexFormat; +import java.util.Map; +import java.util.function.Consumer; + +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.jspecify.annotations.Nullable; + +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; +import io.a2a.server.config.A2AConfigProvider; +import io.a2a.spec.AgentCard; + +/** + * Provides HTTP caching metadata for Agent Card responses. + * + *

        This bean computes and caches HTTP caching headers (Cache-Control, ETag, Last-Modified) + * for the Agent Card endpoint as specified in the A2A protocol specification section 8.6. + * + *

        The metadata is computed once at initialization: + *

          + *
        • Cache-Control: Configured via {@code a2a.agent-card.cache.max-age} (default: 3600 seconds)
        • + *
        • ETag: MD5 hash of the serialized Agent Card JSON
        • + *
        • Last-Modified: Timestamp when the bean was initialized (RFC 1123 format)
        • + *
        + * + *

        Since the Agent Card is {@code @ApplicationScoped}, these values remain stable + * throughout the application lifecycle unless the application is restarted. + * + * @see A2A Specification - Agent Card Caching + */ +@ApplicationScoped +public class AgentCardCacheMetadata { + + private static final String CONFIG_KEY_MAX_AGE = "a2a.agent-card.cache.max-age"; + private static final String DEFAULT_MAX_AGE = "3600"; // 1 hour + private static final DateTimeFormatter RFC_1123_FORMATTER = DateTimeFormatter.RFC_1123_DATE_TIME; + + @Inject + @PublicAgentCard + Instance agentCardInstance; + + @Inject + Instance configInstance; + + private @Nullable AgentCard agentCard; + private @Nullable A2AConfigProvider config; + + @SuppressWarnings("NullAway") // Initialized in @PostConstruct when agentCard is available + private String etag; + @SuppressWarnings("NullAway") // Initialized in @PostConstruct when agentCard is available + private String lastModified; + @SuppressWarnings("NullAway") // Initialized in @PostConstruct when agentCard is available + private String cacheControl; + + /** + * Package-private no-arg constructor for CDI. + */ + AgentCardCacheMetadata() { + // For CDI + } + + /** + * Public constructor for testing purposes. + * + * @param agentCard the agent card + * @param config the configuration provider + */ + public AgentCardCacheMetadata(AgentCard agentCard, A2AConfigProvider config) { + this.agentCard = agentCard; + this.config = config; + init(); + } + + @PostConstruct + @SuppressWarnings("NullAway") // agentCard and config are guaranteed non-null in both paths + void init() { + // Handle two initialization paths: + // 1. CDI injection: get beans from Instance if available + // 2. Direct constructor: agentCard and config already set + + if (agentCard == null && agentCardInstance != null) { + // CDI path - only initialize if AgentCard bean is available + if (agentCardInstance.isUnsatisfied() || configInstance.isUnsatisfied()) { + return; + } + this.agentCard = agentCardInstance.get(); + this.config = configInstance.get(); + } + + // At this point, agentCard and config should be set (either via CDI or constructor) + if (agentCard == null || config == null) { + return; + } + + // Calculate ETag from the serialized JSON representation + this.etag = calculateETag(agentCard); + + // Set Last-Modified to the initialization time + this.lastModified = RFC_1123_FORMATTER.format(Instant.now().atZone(ZoneOffset.UTC)); + + // Configure Cache-Control with max-age directive + String maxAge = config.getOptionalValue(CONFIG_KEY_MAX_AGE).orElse(DEFAULT_MAX_AGE); + this.cacheControl = "public, max-age=" + maxAge; + } + + /** + * Returns the ETag header value for the Agent Card. + * + *

        The ETag is an MD5 hash of the serialized Agent Card JSON, quoted per HTTP specification. + * + * @return the ETag header value (e.g., {@code "a1b2c3d4..."}) + */ + public String getETag() { + return etag; + } + + /** + * Returns the Last-Modified header value for the Agent Card. + * + *

        The timestamp represents when the bean was initialized, in RFC 1123 format. + * + * @return the Last-Modified header value (e.g., {@code "Mon, 17 Mar 2025 10:00:00 GMT"}) + */ + public String getLastModified() { + return lastModified; + } + + /** + * Returns the Cache-Control header value for the Agent Card. + * + *

        The value includes {@code public} and a {@code max-age} directive configured + * via {@code a2a.agent-card.cache.max-age} (default: 3600 seconds). + * + * @return the Cache-Control header value (e.g., {@code "public, max-age=3600"}) + */ + public String getCacheControl() { + return cacheControl; + } + + /** + * Calculates an MD5 hash of the Agent Card JSON for use as an ETag. + * + * @param card the agent card to hash + * @return the hex-encoded MD5 hash, quoted per HTTP specification + */ + private String calculateETag(AgentCard card) { + try { + String json = JsonUtil.toJson(card); + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] hash = md.digest(json.getBytes(StandardCharsets.UTF_8)); + return "\"" + HexFormat.of().formatHex(hash) + "\""; + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("MD5 algorithm not available", e); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Failed to serialize Agent Card for ETag calculation", e); + } + } + + /** + * Populates a map with header names and header values stored in this instance. + * + * @return a map of the headers + */ + public Map getHttpHeadersMap() { + Map headers = new HashMap<>(); + if (cacheControl != null) { + headers.put("Cache-Control", cacheControl); + } + if (lastModified != null) { + headers.put("Last-Modified", lastModified); + } + if (etag != null) { + headers.put("ETag", etag); + } + return headers; + } +} 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 35f60ec29..fc621bdb6 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 @@ -636,6 +636,48 @@ public void testGetExtendedAgentCard() throws A2AClientException { assertTrue(agentCard.skills().isEmpty()); } + /** + * Tests that the Agent Card endpoint returns HTTP caching headers. + * + *

        Per A2A specification section 8.6, Agent Card HTTP endpoints SHOULD include: + *

          + *
        • Cache-Control header with max-age directive (CARD-CACHE-001)
        • + *
        • ETag header for conditional request support (CARD-CACHE-002)
        • + *
        • Last-Modified header (CARD-CACHE-003, MAY requirement)
        • + *
        + * + * @throws Exception if HTTP request fails + */ + @Test + public void testAgentCardHeaders() throws Exception { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/.well-known/agent-card.json")) + .GET() + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + assertEquals(200, response.statusCode()); + + // Verify Cache-Control header with max-age directive (CARD-CACHE-001) + Optional cacheControl = response.headers().firstValue("Cache-Control"); + assertTrue(cacheControl.isPresent(), "Cache-Control header should be present"); + assertTrue(cacheControl.get().contains("max-age"), + "Cache-Control should contain max-age directive, got: " + cacheControl.get()); + + // Verify ETag header (CARD-CACHE-002) + Optional etag = response.headers().firstValue("ETag"); + assertTrue(etag.isPresent(), "ETag header should be present"); + assertTrue(etag.get().startsWith("\"") && etag.get().endsWith("\""), + "ETag should be quoted per HTTP specification, got: " + etag.get()); + + // Verify Last-Modified header in RFC 1123 format (CARD-CACHE-003) + Optional lastModified = response.headers().firstValue("Last-Modified"); + assertTrue(lastModified.isPresent(), "Last-Modified header should be present"); + assertTrue(lastModified.get().contains("GMT"), + "Last-Modified should be in RFC 1123 format (containing GMT), got: " + lastModified.get()); + } + @Test public void testSendMessageStreamNewMessageSuccess() throws Exception { testSendStreamingMessage(false); 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 9cb20bea6..ef4a95f42 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 @@ -31,6 +31,7 @@ import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.jsonrpc.common.wrappers.ListTasksResult; +import io.a2a.server.AgentCardCacheMetadata; import io.a2a.server.AgentCardValidator; import io.a2a.server.ExtendedAgentCard; import io.a2a.server.PublicAgentCard; @@ -129,6 +130,7 @@ public class RestHandler { // final, is not proxyable in all runtimes private AgentCard agentCard; private @Nullable Instance extendedAgentCard; + private AgentCardCacheMetadata cacheMetadata; private RequestHandler requestHandler; private Executor executor; @@ -148,14 +150,16 @@ protected RestHandler() { * * @param agentCard the public agent card containing agent capabilities * @param extendedAgentCard optional extended agent card instance + * @param cacheMetadata the agent card caching metadata * @param requestHandler the handler for processing A2A requests * @param executor the executor for asynchronous operations */ @Inject public RestHandler(@PublicAgentCard AgentCard agentCard, @ExtendedAgentCard Instance extendedAgentCard, - RequestHandler requestHandler, @Internal Executor executor) { + AgentCardCacheMetadata cacheMetadata, RequestHandler requestHandler, @Internal Executor executor) { this.agentCard = agentCard; this.extendedAgentCard = extendedAgentCard; + this.cacheMetadata = cacheMetadata; this.requestHandler = requestHandler; this.executor = executor; @@ -167,11 +171,14 @@ public RestHandler(@PublicAgentCard AgentCard agentCard, @ExtendedAgentCard Inst * Creates a REST handler with basic dependencies. * * @param agentCard the agent card containing agent capabilities + * @param cacheMetadata the agent card caching metadata * @param requestHandler the handler for processing A2A requests * @param executor the executor for asynchronous operations */ - public RestHandler(AgentCard agentCard, RequestHandler requestHandler, Executor executor) { + public RestHandler(AgentCard agentCard, AgentCardCacheMetadata cacheMetadata, + RequestHandler requestHandler, Executor executor) { this.agentCard = agentCard; + this.cacheMetadata = cacheMetadata; this.requestHandler = requestHandler; this.executor = executor; } @@ -862,7 +869,8 @@ public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String t */ public HTTPRestResponse getAgentCard() { try { - return new HTTPRestResponse(200, APPLICATION_JSON, JsonUtil.toJson(agentCard)); + return new HTTPRestResponse(200, APPLICATION_JSON, JsonUtil.toJson(agentCard), + cacheMetadata.getHttpHeadersMap()); } catch (Throwable t) { return createErrorResponse(500, new InternalError(t.getMessage())); } @@ -876,6 +884,7 @@ public static class HTTPRestResponse { private final int statusCode; private final String contentType; private final String body; + private final Map headers; /** * Creates an HTTP REST response. @@ -885,9 +894,22 @@ public static class HTTPRestResponse { * @param body the response body */ public HTTPRestResponse(int statusCode, String contentType, String body) { + this(statusCode, contentType, body, Map.of()); + } + + /** + * Creates an HTTP REST response with custom headers. + * + * @param statusCode the HTTP status code + * @param contentType the content type of the response + * @param body the response body + * @param headers additional HTTP headers + */ + public HTTPRestResponse(int statusCode, String contentType, String body, Map headers) { this.statusCode = statusCode; this.contentType = contentType; this.body = body; + this.headers = Map.copyOf(headers); } /** @@ -917,9 +939,18 @@ public String getBody() { return body; } + /** + * Returns additional HTTP headers. + * + * @return the headers map + */ + public Map getHeaders() { + return headers; + } + @Override public String toString() { - return "HTTPRestResponse{" + "statusCode=" + statusCode + ", contentType=" + contentType + ", body=" + body + '}'; + return "HTTPRestResponse{" + "statusCode=" + statusCode + ", contentType=" + contentType + ", body=" + body + ", headers=" + headers + '}'; } } 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 d07f5a42c..e71dd6169 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 @@ -14,8 +14,10 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.protobuf.InvalidProtocolBufferException; +import io.a2a.server.AgentCardCacheMetadata; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; +import io.a2a.server.config.DefaultValuesConfigProvider; import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; @@ -31,9 +33,17 @@ public class RestHandlerTest extends AbstractA2ARequestHandlerTest { private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + private static AgentCardCacheMetadata createCacheMetadata() { + return createCacheMetadata(CARD); + } + + private static AgentCardCacheMetadata createCacheMetadata(AgentCard card) { + return new AgentCardCacheMetadata(card, new DefaultValuesConfigProvider()); + } + @Test public void testGetTaskSuccess() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", MINIMAL_TASK.id(), 0); @@ -51,7 +61,7 @@ public void testGetTaskSuccess() { @Test public void testGetTaskNotFound() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", "nonexistent", 0); @@ -61,7 +71,7 @@ public void testGetTaskNotFound() { @Test public void testGetTaskNegativeHistoryLengthReturns422() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", MINIMAL_TASK.id(), -1); @@ -71,7 +81,7 @@ public void testGetTaskNegativeHistoryLengthReturns422() { @Test public void testListTasksStatusWireString() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "TASK_STATE_SUBMITTED", null, null, @@ -84,7 +94,7 @@ public void testListTasksStatusWireString() { @Test public void testListTasksInvalidStatus() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "not-a-status", null, null, null, null, null); @@ -95,7 +105,7 @@ public void testListTasksInvalidStatus() { @Test public void testSendMessage() throws InvalidProtocolBufferException { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); }; @@ -126,7 +136,7 @@ public void testSendMessage() throws InvalidProtocolBufferException { @Test public void testSendMessageInvalidBody() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); String invalidBody = "invalid json"; RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", invalidBody); @@ -137,7 +147,7 @@ public void testSendMessageInvalidBody() { @Test public void testSendMessageWrongValueBody() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); String requestBody = """ { "message": @@ -166,7 +176,7 @@ public void testSendMessageWrongValueBody() { @Test public void testSendMessageEmptyBody() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", ""); @@ -176,7 +186,7 @@ public void testSendMessageEmptyBody() { @Test public void testCancelTaskSuccess() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); agentExecutorCancel = (context, agentEmitter) -> { @@ -197,7 +207,7 @@ public void testCancelTaskSuccess() { @Test public void testCancelTaskNotFound() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); String requestBody = "{\"id\":\"nonexistent\"}"; RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, "nonexistent"); @@ -208,7 +218,7 @@ public void testCancelTaskNotFound() { @Test public void testCancelTaskWithMetadata() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); agentExecutorCancel = (context, agentEmitter) -> { @@ -239,7 +249,7 @@ public void testCancelTaskWithMetadata() { @Test public void testCancelTaskWithEmptyMetadata() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); agentExecutorCancel = (context, agentEmitter) -> { @@ -263,7 +273,7 @@ public void testCancelTaskWithEmptyMetadata() { @Test public void testCancelTaskWithNoMetadata() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); agentExecutorCancel = (context, agentEmitter) -> { @@ -283,7 +293,7 @@ public void testCancelTaskWithNoMetadata() { @Test public void testCancelTaskWithNullBody() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); agentExecutorCancel = (context, agentEmitter) -> { @@ -301,7 +311,7 @@ public void testCancelTaskWithNullBody() { @Test public void testSendStreamingMessageSuccess() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); }; @@ -333,7 +343,7 @@ public void testSendStreamingMessageSuccess() { @Test public void testSendStreamingMessageNotSupported() { AgentCard card = createAgentCard(false, true); - RestHandler handler = new RestHandler(card, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(card, createCacheMetadata(card), requestHandler, internalExecutor); String requestBody = """ { @@ -354,7 +364,7 @@ public void testSendStreamingMessageNotSupported() { @Test public void testPushNotificationConfigSuccess() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); String requestBody = """ @@ -377,7 +387,7 @@ public void testPushNotificationConfigSuccess() { @Test public void testPushNotificationConfigNotSupported() { AgentCard card = createAgentCard(true, false); - RestHandler handler = new RestHandler(card, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(card, createCacheMetadata(card), requestHandler, internalExecutor); String requestBody = """ { @@ -396,7 +406,7 @@ public void testPushNotificationConfigNotSupported() { @Test public void testGetPushNotificationConfig() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); // First, create a push notification config @@ -420,7 +430,7 @@ public void testGetPushNotificationConfig() { @Test public void testDeletePushNotificationConfig() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); RestHandler.HTTPRestResponse response = handler.deleteTaskPushNotificationConfiguration(callContext, "", MINIMAL_TASK.id(), "default-config-id"); Assertions.assertEquals(204, response.getStatusCode()); @@ -428,7 +438,7 @@ public void testDeletePushNotificationConfig() { @Test public void testListPushNotificationConfigs() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); RestHandler.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(callContext, "", MINIMAL_TASK.id(), 0, ""); @@ -440,7 +450,7 @@ public void testListPushNotificationConfigs() { @Test public void testHttpStatusCodeMapping() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); // Test 400 for invalid request RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", ""); @@ -453,7 +463,7 @@ public void testHttpStatusCodeMapping() { @Test public void testStreamingDoesNotBlockMainThread() throws Exception { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); // Track if the main thread gets blocked during streaming AtomicBoolean eventReceived = new AtomicBoolean(false); @@ -557,7 +567,7 @@ public void testExtensionSupportRequiredErrorOnSendMessage() { .skills(List.of()) .build(); - RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(cardWithExtension, createCacheMetadata(cardWithExtension), requestHandler, internalExecutor); String requestBody = """ { @@ -605,7 +615,7 @@ public void testExtensionSupportRequiredErrorOnSendStreamingMessage() { .skills(List.of()) .build(); - RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(cardWithExtension, createCacheMetadata(cardWithExtension), requestHandler, internalExecutor); String requestBody = """ { @@ -700,7 +710,7 @@ public void testRequiredExtensionProvidedSuccess() { .skills(List.of()) .build(); - RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(cardWithExtension, createCacheMetadata(cardWithExtension), requestHandler, internalExecutor); // Create context WITH the required extension Set requestedExtensions = new HashSet<>(); @@ -756,7 +766,7 @@ public void testVersionNotSupportedErrorOnSendMessage() { .skills(List.of()) .build(); - RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(agentCard, createCacheMetadata(agentCard), requestHandler, internalExecutor); // Create context with incompatible version 2.0 ServerCallContext contextWithVersion = new ServerCallContext( @@ -806,7 +816,7 @@ public void testVersionNotSupportedErrorOnSendStreamingMessage() { .skills(List.of()) .build(); - RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(agentCard, createCacheMetadata(agentCard), requestHandler, internalExecutor); // Create context with incompatible version 2.0 ServerCallContext contextWithVersion = new ServerCallContext( @@ -902,7 +912,7 @@ public void testCompatibleVersionSuccess() { .skills(List.of()) .build(); - RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(agentCard, createCacheMetadata(agentCard), requestHandler, internalExecutor); // Create context with compatible version 1.1 ServerCallContext contextWithVersion = new ServerCallContext( @@ -957,7 +967,7 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { .skills(List.of()) .build(); - RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(agentCard, createCacheMetadata(agentCard), requestHandler, internalExecutor); // Use default callContext (no version - should default to 1.0) agentExecutorExecute = (context, agentEmitter) -> { @@ -990,7 +1000,7 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { @Test public void testListTasksNegativeTimestampReturns422() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); // Negative timestamp should return 422 (Invalid params) RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, null, null, null, @@ -1002,7 +1012,7 @@ public void testListTasksNegativeTimestampReturns422() { @Test public void testListTasksUnixMillisecondsTimestamp() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); // Unix milliseconds timestamp are no longer accepted RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, null, null, null, null, "1234567", null); @@ -1011,7 +1021,7 @@ public void testListTasksUnixMillisecondsTimestamp() { @Test public void testListTasksProtobufEnumStatus() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); // Protobuf enum format (TASK_STATE_SUBMITTED) should be accepted @@ -1025,7 +1035,7 @@ public void testListTasksProtobufEnumStatus() { @Test public void testListTasksEnumConstantStatus() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); // Enum constant format (TASK_STATE_SUBMITTED) should be accepted @@ -1039,7 +1049,7 @@ public void testListTasksEnumConstantStatus() { @Test public void testListTasksEmptyResultIncludesAllFields() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); + RestHandler handler = new RestHandler(CARD, createCacheMetadata(), requestHandler, internalExecutor); // Query for a context that doesn't exist - should return empty result with all fields RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", "nonexistent-context-id", null, null, null, From ed23f55febf5bf5573da58e8754d72be506e3a14 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 26 Mar 2026 11:11:13 +0100 Subject: [PATCH 098/192] chore: Updating actions to new versions nort running on node20 (#763) Signed-off-by: Emmanuel Hugonnet --- .github/workflows/build-and-test.yml | 6 +++--- .github/workflows/build-with-release-profile-run.yml | 4 ++-- .github/workflows/build-with-release-profile.yml | 2 +- .github/workflows/cloud-deployment-example.yml | 3 +-- .github/workflows/create-github-release.yml | 2 +- .github/workflows/release-to-maven-central.yml | 4 ++-- .github/workflows/run-tck.yml | 8 ++++---- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index e2fb7253d..69cc8a178 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -18,7 +18,7 @@ jobs: matrix: java-version: ['17', '21', '25'] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up JDK ${{ matrix.java-version }} uses: actions/setup-java@v4 with: @@ -29,7 +29,7 @@ jobs: run: mvn -B package --file pom.xml -fae - name: Upload Test Reports if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: surefire-reports-java-${{ matrix.java-version }} path: | @@ -39,7 +39,7 @@ jobs: if-no-files-found: warn - name: Upload Build Logs if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: build-logs-java-${{ matrix.java-version }} path: | diff --git a/.github/workflows/build-with-release-profile-run.yml b/.github/workflows/build-with-release-profile-run.yml index 7da02cf66..83cace348 100644 --- a/.github/workflows/build-with-release-profile-run.yml +++ b/.github/workflows/build-with-release-profile-run.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Download PR info - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: pr-info github-token: ${{ github.token }} @@ -68,7 +68,7 @@ jobs: }); - name: Checkout PR code - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: # Checkout the exact commit from the PR (or push) # This is safe because the workflow code (this file) is always from main diff --git a/.github/workflows/build-with-release-profile.yml b/.github/workflows/build-with-release-profile.yml index 0f4c05687..70737fca9 100644 --- a/.github/workflows/build-with-release-profile.yml +++ b/.github/workflows/build-with-release-profile.yml @@ -43,7 +43,7 @@ jobs: cat pr_info/* - name: Upload PR info - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: pr-info path: pr_info/ diff --git a/.github/workflows/cloud-deployment-example.yml b/.github/workflows/cloud-deployment-example.yml index 237b2f390..57a97a638 100644 --- a/.github/workflows/cloud-deployment-example.yml +++ b/.github/workflows/cloud-deployment-example.yml @@ -16,8 +16,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v4 - + uses: actions/checkout@v6 - name: Set up JDK 17 uses: actions/setup-java@v5 with: diff --git a/.github/workflows/create-github-release.yml b/.github/workflows/create-github-release.yml index 108296fab..c86b139a5 100644 --- a/.github/workflows/create-github-release.yml +++ b/.github/workflows/create-github-release.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 # Fetch all history for changelog generation diff --git a/.github/workflows/release-to-maven-central.yml b/.github/workflows/release-to-maven-central.yml index c0f5a9724..c8995e953 100644 --- a/.github/workflows/release-to-maven-central.yml +++ b/.github/workflows/release-to-maven-central.yml @@ -15,10 +15,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up JDK 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v6 with: java-version: '17' distribution: 'temurin' diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index 75ed7819f..87a16980d 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -37,9 +37,9 @@ jobs: java-version: [17, 21, 25] steps: - name: Checkout a2a-java - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Checkout a2a-tck - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: a2aproject/a2a-tck path: tck/a2a-tck @@ -157,7 +157,7 @@ jobs: sleep 2 - name: Upload TCK Diagnostics if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: tck-diagnostics-java-${{ matrix.java-version }} path: | @@ -167,7 +167,7 @@ jobs: if-no-files-found: warn - name: Upload TCK Compliance Report if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: tck-compliance-report-java-${{ matrix.java-version }} path: tck/a2a-tck/report.json From c8ba7df73f15063498413b00c1923f0dc6a73941 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 30 Mar 2026 15:18:45 +0200 Subject: [PATCH 099/192] fix: use application/json Content-Type for HTTP+JSON error responses (#769) The spec is not explicit on that but the error responses should all use `application/json`. * in JSON-RPC, an error response is a regular JSON-RPC response * in HTTP+JSON, the error payload was moved from RFC 9457 to AIP-193 so the RFC-9457's `application/problem+json` no longer makes sense. This fixes #768 --------- Signed-off-by: Jeff Mesnil --- .../main/java/io/a2a/common/MediaType.java | 3 +- .../server/apps/quarkus/A2AServerRoutes.java | 7 ++- .../apps/quarkus/A2AServerRoutesTest.java | 9 ++-- .../rest/quarkus/A2AServerRoutesTest.java | 39 ++++++++-------- .../transport/rest/handler/RestHandler.java | 3 +- .../rest/handler/RestHandlerTest.java | 46 ++++++++++--------- 6 files changed, 54 insertions(+), 53 deletions(-) diff --git a/common/src/main/java/io/a2a/common/MediaType.java b/common/src/main/java/io/a2a/common/MediaType.java index 9c7027f60..9cdc48211 100644 --- a/common/src/main/java/io/a2a/common/MediaType.java +++ b/common/src/main/java/io/a2a/common/MediaType.java @@ -2,6 +2,5 @@ public interface MediaType { - public static final String APPLICATION_JSON = "application/json"; - public static final String APPLICATION_PROBLEM_JSON = "application/problem+json"; + String APPLICATION_JSON = "application/json"; } 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 56fd4dea9..7ca65cb35 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 @@ -1,6 +1,5 @@ package io.a2a.server.apps.quarkus; -import static io.a2a.common.MediaType.APPLICATION_PROBLEM_JSON; import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; @@ -248,7 +247,7 @@ public class A2AServerRoutes { * *

        Processing Flow: *

          - *
        1. Parse JSON-RPC request body using {@link JSONRPCUtils#parseRequestBody}
        2. + *
        3. Parse JSON-RPC request body using {@link JSONRPCUtils#parseRequestBody(String, String)}
        4. *
        5. Create {@link ServerCallContext} from routing context
        6. *
        7. Route to streaming or non-streaming handler
        8. *
        9. Handle errors with appropriate JSON-RPC error codes
        10. @@ -297,7 +296,7 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { if (error != null) { rc.response() .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_PROBLEM_JSON) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) .end(serializeResponse(error)); } else if (streaming) { final Multi> finalStreamingResponse = streamingResponse; @@ -313,7 +312,7 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { } else { rc.response() .setStatusCode(200) - .putHeader(CONTENT_TYPE, nonStreamingResponse.getError() != null ? APPLICATION_PROBLEM_JSON : APPLICATION_JSON) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) .end(serializeResponse(nonStreamingResponse)); } } 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 ab1566308..bc1b717e5 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,6 +1,5 @@ package io.a2a.server.apps.quarkus; -import static io.a2a.common.MediaType.APPLICATION_PROBLEM_JSON; 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; @@ -718,7 +717,7 @@ public void testTenantExtraction_StreamingRequest() { } @Test - public void testJsonParseError_ContentTypeIsProblemJson() { + public void testJsonParseError_ContentTypeIsApplicationJson() { // Arrange - invalid JSON String invalidJson = "not valid json {{{"; when(mockRequestBody.asString()).thenReturn(invalidJson); @@ -727,11 +726,11 @@ public void testJsonParseError_ContentTypeIsProblemJson() { routes.invokeJSONRPCHandler(invalidJson, mockRoutingContext); // Assert - verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_PROBLEM_JSON); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } @Test - public void testMethodNotFound_ContentTypeIsProblemJson() { + public void testMethodNotFound_ContentTypeIsApplicationJson() { // Arrange - unknown method String jsonRpcRequest = """ { @@ -746,7 +745,7 @@ public void testMethodNotFound_ContentTypeIsProblemJson() { routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); // Assert - verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_PROBLEM_JSON); + verify(mockHttpResponse).putHeader(CONTENT_TYPE, APPLICATION_JSON); } /** 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 09a45c828..968c93ef0 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,6 @@ package io.a2a.server.rest.quarkus; +import static io.a2a.common.MediaType.APPLICATION_JSON; 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; @@ -82,7 +83,7 @@ public void setUp() { when(mockRoutingContext.user()).thenReturn(null); when(mockRequest.headers()).thenReturn(mockHeaders); when(mockRequest.params()).thenReturn(mockParams); - when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("application/json"); + when(mockRequest.getHeader(any(CharSequence.class))).thenReturn(APPLICATION_JSON); when(mockRoutingContext.body()).thenReturn(mockRequestBody); when(mockRequestBody.asString()).thenReturn("{}"); when(mockResponse.setStatusCode(any(Integer.class))).thenReturn(mockResponse); @@ -96,7 +97,7 @@ public void testSendMessage_MethodNameSetInContext() { // Arrange HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{}"); when(mockRestHandler.sendMessage(any(ServerCallContext.class), anyString(), anyString())).thenReturn(mockHttpResponse); @@ -117,7 +118,7 @@ public void testSendMessageStreaming_MethodNameSetInContext() { // Arrange HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{}"); when(mockRestHandler.sendStreamingMessage(any(ServerCallContext.class), anyString(), anyString())) .thenReturn(mockHttpResponse); @@ -140,7 +141,7 @@ public void testGetTask_MethodNameSetInContext() { when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{test:value}"); when(mockRestHandler.getTask(any(ServerCallContext.class), anyString(), anyString(), any())).thenReturn(mockHttpResponse); @@ -162,7 +163,7 @@ public void testCancelTask_MethodNameSetInContext() { when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{}"); when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); @@ -184,7 +185,7 @@ public void testCancelTask_WithMetadata() { when(mockRoutingContext.pathParam("taskId")).thenReturn("task456"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task456\",\"status\":\"cancelled\"}"); String requestBody = """ @@ -217,7 +218,7 @@ public void testCancelTask_WithEmptyMetadata() { when(mockRoutingContext.pathParam("taskId")).thenReturn("task789"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task789\"}"); String requestBody = """ @@ -246,7 +247,7 @@ public void testCancelTask_WithNoMetadataField() { when(mockRoutingContext.pathParam("taskId")).thenReturn("task999"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task999\"}"); String requestBody = "{}"; @@ -271,7 +272,7 @@ public void testCancelTask_WithNullBody() { when(mockRoutingContext.pathParam("taskId")).thenReturn("task111"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task111\"}"); ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); @@ -293,7 +294,7 @@ public void testCancelTask_WithComplexMetadata() { when(mockRoutingContext.pathParam("taskId")).thenReturn("task222"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{\"id\":\"task222\"}"); String requestBody = """ @@ -331,7 +332,7 @@ public void testSubscribeTask_MethodNameSetInContext() { when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{}"); when(mockRestHandler.subscribeToTask(any(ServerCallContext.class), anyString(), anyString())) .thenReturn(mockHttpResponse); @@ -354,7 +355,7 @@ public void testCreateTaskPushNotificationConfiguration_MethodNameSetInContext() when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{}"); when(mockRestHandler.createTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); @@ -377,7 +378,7 @@ public void testGetTaskPushNotificationConfiguration_MethodNameSetInContext() { when(mockRoutingContext.pathParam("configId")).thenReturn("config456"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{}"); when(mockRestHandler.getTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); @@ -400,7 +401,7 @@ public void testListTaskPushNotificationConfigurations_MethodNameSetInContext() when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{}"); when(mockRestHandler.listTaskPushNotificationConfigurations(any(ServerCallContext.class), anyString(), anyString(), anyInt(), anyString())) .thenReturn(mockHttpResponse); @@ -424,7 +425,7 @@ public void testDeleteTaskPushNotificationConfiguration_MethodNameSetInContext() when(mockRoutingContext.pathParam("configId")).thenReturn("config456"); HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); + when(mockHttpResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockHttpResponse.getBody()).thenReturn("{}"); when(mockRestHandler.deleteTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); @@ -446,7 +447,7 @@ public void testSendMessage_UnsupportedContentType_ReturnsContentTypeNotSupporte // Arrange HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); when(mockErrorResponse.getStatusCode()).thenReturn(415); - when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); + when(mockErrorResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockErrorResponse.getBody()).thenReturn("{\"error\":{\"code\":415,\"status\":\"INVALID_ARGUMENT\",\"message\":\"Incompatible content types\",\"details\":[{\"reason\":\"CONTENT_TYPE_NOT_SUPPORTED\",\"domain\":\"a2a-protocol.org\"}]}}"); when(mockRestHandler.createErrorResponse(any(ContentTypeNotSupportedError.class))).thenReturn(mockErrorResponse); when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("text/plain"); @@ -464,7 +465,7 @@ public void testSendMessageStreaming_UnsupportedContentType_ReturnsContentTypeNo // Arrange HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); when(mockErrorResponse.getStatusCode()).thenReturn(415); - when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); + when(mockErrorResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockErrorResponse.getBody()).thenReturn("{\"error\":{\"code\":415,\"status\":\"INVALID_ARGUMENT\",\"message\":\"Incompatible content types\",\"details\":[{\"reason\":\"CONTENT_TYPE_NOT_SUPPORTED\",\"domain\":\"a2a-protocol.org\"}]}}"); when(mockRestHandler.createErrorResponse(any(ContentTypeNotSupportedError.class))).thenReturn(mockErrorResponse); when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("text/plain"); @@ -482,9 +483,9 @@ public void testSendMessage_UnsupportedProtocolVersion_ReturnsVersionNotSupporte // Arrange: content type is OK, but RestHandler returns a VersionNotSupportedError response HTTPRestResponse mockErrorResponse = mock(HTTPRestResponse.class); when(mockErrorResponse.getStatusCode()).thenReturn(400); - when(mockErrorResponse.getContentType()).thenReturn("application/problem+json"); + when(mockErrorResponse.getContentType()).thenReturn(APPLICATION_JSON); when(mockErrorResponse.getBody()).thenReturn("{\"error\":{\"code\":400,\"status\":\"UNIMPLEMENTED\",\"message\":\"Protocol version not supported\",\"details\":[{\"reason\":\"VERSION_NOT_SUPPORTED\",\"domain\":\"a2a-protocol.org\"}]}}"); - when(mockRequest.getHeader(any(CharSequence.class))).thenReturn("application/json"); + when(mockRequest.getHeader(any(CharSequence.class))).thenReturn(APPLICATION_JSON); when(mockRestHandler.sendMessage(any(ServerCallContext.class), anyString(), anyString())) .thenReturn(mockErrorResponse); 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 ef4a95f42..ea16f3aa4 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 @@ -1,7 +1,6 @@ package io.a2a.transport.rest.handler; import static io.a2a.common.MediaType.APPLICATION_JSON; -import static io.a2a.common.MediaType.APPLICATION_PROBLEM_JSON; import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; import io.a2a.spec.A2AErrorCodes; @@ -683,7 +682,7 @@ public HTTPRestResponse createErrorResponse(A2AError error) { private HTTPRestResponse createErrorResponse(int statusCode, A2AError error) { String jsonBody = new HTTPRestErrorResponse(error).toJson(); - return new HTTPRestResponse(statusCode, APPLICATION_PROBLEM_JSON, jsonBody); + return new HTTPRestResponse(statusCode, APPLICATION_JSON, jsonBody); } private HTTPRestStreamingResponse createStreamingResponse(Flow.Publisher publisher) { 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 e71dd6169..f5184b2f4 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,6 +1,8 @@ package io.a2a.transport.rest.handler; +import static io.a2a.common.MediaType.APPLICATION_JSON; + import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -14,6 +16,8 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.protobuf.InvalidProtocolBufferException; + +import io.a2a.common.MediaType; import io.a2a.server.AgentCardCacheMetadata; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; @@ -49,13 +53,13 @@ public void testGetTaskSuccess() { RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", MINIMAL_TASK.id(), 0); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); response = handler.getTask(callContext, "", MINIMAL_TASK.id(), 2); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -88,7 +92,7 @@ public void testListTasksStatusWireString() { null, null, null); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -130,7 +134,7 @@ public void testSendMessage() throws InvalidProtocolBufferException { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); Assertions.assertEquals(200, response.getStatusCode(), response.toString()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertNotNull(response.getBody()); } @@ -165,7 +169,7 @@ public void testSendMessageWrongValueBody() { RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); Assertions.assertEquals(422, response.getStatusCode()); - Assertions.assertEquals("application/problem+json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); JsonObject body = JsonParser.parseString(response.getBody()).getAsJsonObject(); JsonObject error = body.getAsJsonObject("error"); Assertions.assertEquals(422, error.get("code").getAsInt()); @@ -201,7 +205,7 @@ public void testCancelTaskSuccess() { RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, MINIMAL_TASK.id()); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -243,7 +247,7 @@ public void testCancelTaskWithMetadata() { RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, MINIMAL_TASK.id()); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -267,7 +271,7 @@ public void testCancelTaskWithEmptyMetadata() { RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, MINIMAL_TASK.id()); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -287,7 +291,7 @@ public void testCancelTaskWithNoMetadata() { RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", requestBody, MINIMAL_TASK.id()); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -305,7 +309,7 @@ public void testCancelTaskWithNullBody() { RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", null, MINIMAL_TASK.id()); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -380,7 +384,7 @@ public void testPushNotificationConfigSuccess() { RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", requestBody, MINIMAL_TASK.id()); Assertions.assertEquals(201, response.getStatusCode(), response.toString()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertNotNull(response.getBody()); } @@ -421,11 +425,11 @@ public void testGetPushNotificationConfig() { }""".formatted(MINIMAL_TASK.id()); RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", createRequestBody, MINIMAL_TASK.id()); Assertions.assertEquals(201, response.getStatusCode(), response.toString()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); // Now get it response = handler.getTaskPushNotificationConfiguration(callContext, "", MINIMAL_TASK.id(), "default-config-id"); Assertions.assertEquals(200, response.getStatusCode(), response.toString()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); } @Test @@ -444,7 +448,7 @@ public void testListPushNotificationConfigs() { RestHandler.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(callContext, "", MINIMAL_TASK.id(), 0, ""); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertNotNull(response.getBody()); } @@ -745,7 +749,7 @@ public void testRequiredExtensionProvidedSuccess() { // Should succeed without error Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertNotNull(response.getBody()); } @@ -946,7 +950,7 @@ public void testCompatibleVersionSuccess() { // Should succeed without error Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertNotNull(response.getBody()); } @@ -994,7 +998,7 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { // Should succeed without error (defaults to 1.0) Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertNotNull(response.getBody()); } @@ -1029,7 +1033,7 @@ public void testListTasksProtobufEnumStatus() { null, null, null); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -1043,7 +1047,7 @@ public void testListTasksEnumConstantStatus() { null, null, null); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @@ -1056,7 +1060,7 @@ public void testListTasksEmptyResultIncludesAllFields() { null, null, null); Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); String body = response.getBody(); // Verify all required fields are present (not missing) @@ -1072,7 +1076,7 @@ public void testListTasksEmptyResultIncludesAllFields() { private static void assertProblemDetail(RestHandler.HTTPRestResponse response, int expectedStatus, String expectedReason, String expectedMessage) { Assertions.assertEquals(expectedStatus, response.getStatusCode()); - Assertions.assertEquals("application/problem+json", response.getContentType()); + Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); JsonObject body = JsonParser.parseString(response.getBody()).getAsJsonObject(); Assertions.assertTrue(body.has("error"), "error wrapper should be present"); JsonObject error = body.getAsJsonObject("error"); From adfb93e12520b2d45d7465a6b94b8f7cef4712bf Mon Sep 17 00:00:00 2001 From: Luke <54602706+Lirons01@users.noreply.github.com> Date: Wed, 1 Apr 2026 03:16:52 -0400 Subject: [PATCH 100/192] fix: preserve tenant and protocolVersion from AgentInterface in ClientBuilder (#773) # Description `ClientBuilder.findBestClientTransport()` was creating a new AgentInterface with only protocolBinding and url, discarding tenant and protocolVersion from the matched interface. This broke the intended fallback behavior where the AgentCard's default tenant should be used when no request-level tenant is provided. The fix returns the actual matched AgentInterface from the AgentCard's supportedInterfaces list instead of creating a new one. In addition, I added some tests in order to validate some of this behavior. In order to have the tests actually test this thing, I had to make the `findBestClientTransport()` method package-private. LMK if any of this needs edits or does not match the actual intended behavior and I can make appropriate updates! Fixes #772 --------- Co-authored-by: Luke Irons --- .../java/io/a2a/client/ClientBuilder.java | 48 ++++---- .../java/io/a2a/client/ClientBuilderTest.java | 111 +++++++++++++++--- 2 files changed, 120 insertions(+), 39 deletions(-) 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 81c812c91..a383c5f21 100644 --- a/client/base/src/main/java/io/a2a/client/ClientBuilder.java +++ b/client/base/src/main/java/io/a2a/client/ClientBuilder.java @@ -328,15 +328,17 @@ private ClientTransport buildClientTransport() throws A2AClientException { return wrap(clientTransportProvider.create(clientTransportConfig, agentCard, agentInterface), clientTransportConfig); } - private Map getServerPreferredTransports() throws A2AClientException { - Map serverPreferredTransports = new LinkedHashMap<>(); - if(agentCard.supportedInterfaces() == null || agentCard.supportedInterfaces().isEmpty()) { + private Map getServerInterfacesMap() throws A2AClientException { + List serverInterfaces = agentCard.supportedInterfaces(); + if (serverInterfaces == null || serverInterfaces.isEmpty()) { throw new A2AClientException("No server interface available in the AgentCard"); } - for (AgentInterface agentInterface : agentCard.supportedInterfaces()) { - serverPreferredTransports.putIfAbsent(agentInterface.protocolBinding(), agentInterface.url()); + // If there are multiple interfaces with the same protocol binding, only the first is considered + Map serverInterfacesMap = new LinkedHashMap<>(); + for (AgentInterface iface : serverInterfaces) { + serverInterfacesMap.putIfAbsent(iface.protocolBinding(), iface); } - return serverPreferredTransports; + return serverInterfacesMap; } private List getClientPreferredTransports() { @@ -351,40 +353,38 @@ private List getClientPreferredTransports() { return supportedClientTransports; } - private AgentInterface findBestClientTransport() throws A2AClientException { - // Retrieve transport supported by the A2A server - Map serverPreferredTransports = getServerPreferredTransports(); - - // Retrieve transport configured for this client (using withTransport methods) + // Package-private for testing + AgentInterface findBestClientTransport() throws A2AClientException { + Map serverInterfacesMap = getServerInterfacesMap(); List clientPreferredTransports = getClientPreferredTransports(); - String transportProtocol = null; - String transportUrl = null; + AgentInterface matchedInterface = null; if (clientConfig.isUseClientPreference()) { + // Client preference: iterate client transports first, find first server match for (String clientPreferredTransport : clientPreferredTransports) { - if (serverPreferredTransports.containsKey(clientPreferredTransport)) { - transportProtocol = clientPreferredTransport; - transportUrl = serverPreferredTransports.get(transportProtocol); + if (serverInterfacesMap.containsKey(clientPreferredTransport)) { + matchedInterface = serverInterfacesMap.get(clientPreferredTransport); break; } } } else { - for (Map.Entry transport : serverPreferredTransports.entrySet()) { - if (clientPreferredTransports.contains(transport.getKey())) { - transportProtocol = transport.getKey(); - transportUrl = transport.getValue(); + // Server preference: iterate server interfaces first, find first client match + for (AgentInterface iface : serverInterfacesMap.values()) { + if (clientPreferredTransports.contains(iface.protocolBinding())) { + matchedInterface = iface; break; } } } - if (transportProtocol == null || transportUrl == null) { + + if (matchedInterface == null) { throw new A2AClientException("No compatible transport found"); } - if (!transportProviderRegistry.containsKey(transportProtocol)) { - throw new A2AClientException("No client available for " + transportProtocol); + if (!transportProviderRegistry.containsKey(matchedInterface.protocolBinding())) { + throw new A2AClientException("No client available for " + matchedInterface.protocolBinding()); } - return new AgentInterface(transportProtocol, transportUrl); + return matchedInterface; } /** diff --git a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java index 3be9d4918..bea7c5823 100644 --- a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java +++ b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java @@ -1,6 +1,5 @@ package io.a2a.client; - import java.util.Collections; import java.util.List; @@ -22,8 +21,9 @@ public class ClientBuilderTest { - private AgentCard card = AgentCard.builder() - .name("Hello World Agent") + private static AgentCard buildCard(List interfaces) { + return AgentCard.builder() + .name("Hello World Agent") .description("Just a hello world agent") .version("1.0.0") .documentationUrl("http://example.com/docs") @@ -31,18 +31,28 @@ public class ClientBuilderTest { .streaming(true) .pushNotifications(true) .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(AgentSkill.builder() - .id("hello_world") - .name("Returns hello world") - .description("just returns hello world") - .tags(Collections.singletonList("hello world")) - .examples(List.of("hi", "hello world")) - .build())) - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))) - .build(); + .defaultInputModes(Collections.singletonList("text")) + .defaultOutputModes(Collections.singletonList("text")) + .skills(Collections.singletonList(AgentSkill.builder() + .id("hello_world") + .name("Returns hello world") + .description("just returns hello world") + .tags(Collections.singletonList("hello world")) + .examples(List.of("hi", "hello world")) + .build())) + .supportedInterfaces(interfaces) + .build(); + } + + private final AgentCard card = buildCard(List.of( + new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))); + + private final AgentCard cardWithTenant = buildCard(List.of( + new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999", "/default-tenant"))); + + private final AgentCard cardWithMultipleInterfaces = buildCard(List.of( + new AgentInterface(TransportProtocol.GRPC.asString(), "http://localhost:9998", "/grpc-tenant", "1.0"), + new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999", "/jsonrpc-tenant", "1.0"))); @Test public void shouldNotFindCompatibleTransport() throws A2AClientException { @@ -91,4 +101,75 @@ public void shouldCreateClient_differentConfigurations() throws A2AClientExcepti Assertions.assertNotNull(client); } + + @Test + public void shouldPreserveTenantFromAgentInterface() throws A2AClientException { + ClientBuilder builder = Client + .builder(cardWithTenant) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()); + + AgentInterface selectedInterface = builder.findBestClientTransport(); + + Assertions.assertEquals("/default-tenant", selectedInterface.tenant()); + Assertions.assertEquals("http://localhost:9999", selectedInterface.url()); + Assertions.assertEquals(TransportProtocol.JSONRPC.asString(), selectedInterface.protocolBinding()); + } + + @Test + public void shouldPreserveProtocolVersionFromAgentInterface() throws A2AClientException { + ClientBuilder builder = Client + .builder(cardWithMultipleInterfaces) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()); + + AgentInterface selectedInterface = builder.findBestClientTransport(); + + Assertions.assertEquals("/jsonrpc-tenant", selectedInterface.tenant()); + Assertions.assertEquals("1.0", selectedInterface.protocolVersion()); + } + + @Test + public void shouldSelectCorrectInterfaceWithServerPreference() throws A2AClientException { + // Server preference (default): iterates server interfaces in order, picks first that client supports + // cardWithMultipleInterfaces has [GRPC, JSONRPC] - GRPC is first + // Client supports both GRPC and JSONRPC, so GRPC should be selected (server's first choice) + ClientBuilder builder = Client + .builder(cardWithMultipleInterfaces) + .withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder().channelFactory(s -> null)) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()); + + AgentInterface selectedInterface = builder.findBestClientTransport(); + + Assertions.assertEquals(TransportProtocol.GRPC.asString(), selectedInterface.protocolBinding()); + Assertions.assertEquals("http://localhost:9998", selectedInterface.url()); + Assertions.assertEquals("/grpc-tenant", selectedInterface.tenant()); + } + + @Test + public void shouldSelectCorrectInterfaceWithClientPreference() throws A2AClientException { + // Client preference: iterates client transports in registration order, picks first that server supports + // Client registers [JSONRPC, GRPC] - JSONRPC is first + // Server supports both, so JSONRPC should be selected (client's first choice) + ClientBuilder builder = Client + .builder(cardWithMultipleInterfaces) + .clientConfig(new ClientConfig.Builder().setUseClientPreference(true).build()) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) + .withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder().channelFactory(s -> null)); + + AgentInterface selectedInterface = builder.findBestClientTransport(); + + Assertions.assertEquals(TransportProtocol.JSONRPC.asString(), selectedInterface.protocolBinding()); + Assertions.assertEquals("http://localhost:9999", selectedInterface.url()); + Assertions.assertEquals("/jsonrpc-tenant", selectedInterface.tenant()); + } + + @Test + public void shouldPreserveEmptyTenant() throws A2AClientException { + ClientBuilder builder = Client + .builder(card) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()); + + AgentInterface selectedInterface = builder.findBestClientTransport(); + + Assertions.assertEquals("", selectedInterface.tenant()); + } } From c12888d97d9640c441e08acb3c949544bee48726 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Wed, 1 Apr 2026 09:17:21 +0200 Subject: [PATCH 101/192] feat: add DataPart.fromJson() factory method for raw JSON strings (#778) Allow developers to create a DataPart directly from a JSON string without manually deserializing it into Java objects first. This fixes #753 Co-authored-by: Claude Opus 4.6 --- spec/src/main/java/io/a2a/spec/DataPart.java | 59 +++++++++++ .../test/java/io/a2a/spec/DataPartTest.java | 97 +++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 spec/src/test/java/io/a2a/spec/DataPartTest.java diff --git a/spec/src/main/java/io/a2a/spec/DataPart.java b/spec/src/main/java/io/a2a/spec/DataPart.java index 0e41bec23..3ed726d68 100644 --- a/spec/src/main/java/io/a2a/spec/DataPart.java +++ b/spec/src/main/java/io/a2a/spec/DataPart.java @@ -1,6 +1,10 @@ package io.a2a.spec; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; +import com.google.gson.ToNumberPolicy; import io.a2a.util.Assert; import java.util.Map; import org.jspecify.annotations.Nullable; @@ -77,4 +81,59 @@ public DataPart (Object data, @Nullable Map metadata) { public DataPart(Object data) { this(data, null); } + + /** + * Creates a DataPart by parsing a JSON string into its corresponding Java type. + *

          + * The JSON string is parsed using Gson with {@code ToNumberPolicy.LONG_OR_DOUBLE}, + * producing the following mappings: + *

            + *
          • JSON objects → {@code Map}
          • + *
          • JSON arrays → {@code List} + *
          • JSON strings → {@code String}
          • + *
          • JSON integers → {@code Long}
          • + *
          • JSON decimals → {@code Double}
          • + *
          • JSON booleans → {@code Boolean}
          • + * + *

            + * Example usage: + *

            {@code
            +     * DataPart dataPart = DataPart.fromJson("""
            +     *     {
            +     *         "temperature": 22.5,
            +     *         "humidity": 65
            +     *     }""");
            +     * }
            + * + * @param json the JSON string to parse (must not be null or the JSON literal "null") + * @return a new DataPart containing the parsed data + * @throws IllegalArgumentException if json is null, parses to null, or is not valid + */ + public static DataPart fromJson(String json) { + return fromJson(json, null); + } + + /** + * Creates a DataPart by parsing a JSON string into its corresponding Java type, + * with optional metadata. + * + * @param json the JSON string to parse (must not be null or the JSON literal "null") + * @param metadata additional metadata for the part + * @return a new DataPart containing the parsed data and metadata + * @throws IllegalArgumentException if json is null, parses to null, or is not valid + * @see #fromJson(String) + */ + public static DataPart fromJson(String json, @Nullable Map metadata) { + Assert.checkNotNullParam("json", json); + try { + Object data = JSON_PARSER.fromJson(json, Object.class); + return new DataPart(data, metadata); + } catch (JsonSyntaxException e) { + throw new IllegalArgumentException("Invalid JSON: " + json, e); + } + } + + private static final Gson JSON_PARSER = new GsonBuilder() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create(); } diff --git a/spec/src/test/java/io/a2a/spec/DataPartTest.java b/spec/src/test/java/io/a2a/spec/DataPartTest.java new file mode 100644 index 000000000..93f8d477a --- /dev/null +++ b/spec/src/test/java/io/a2a/spec/DataPartTest.java @@ -0,0 +1,97 @@ +package io.a2a.spec; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +class DataPartTest { + + @Test + void testFromJson_object() { + DataPart part = DataPart.fromJson(""" + {"temperature": 22.5, "humidity": 65}"""); + + Map data = assertInstanceOf(Map.class, part.data()); + assertEquals(22.5, data.get("temperature")); + assertEquals(65L, data.get("humidity")); + assertNull(part.metadata()); + } + + @Test + void testFromJson_array() { + DataPart part = DataPart.fromJson(""" + ["a", "b", "c"]"""); + + List data = assertInstanceOf(List.class, part.data()); + assertEquals(List.of("a", "b", "c"), data); + } + + @Test + void testFromJson_string() { + DataPart part = DataPart.fromJson("\"hello\""); + + assertEquals("hello", part.data()); + } + + @Test + void testFromJson_integerNumber() { + DataPart part = DataPart.fromJson("42"); + + assertEquals(42L, part.data()); + } + + @Test + void testFromJson_decimalNumber() { + DataPart part = DataPart.fromJson("3.14"); + + assertEquals(3.14, part.data()); + } + + @Test + void testFromJson_boolean() { + DataPart part = DataPart.fromJson("true"); + + assertEquals(true, part.data()); + } + + @Test + void testFromJson_withMetadata() { + Map metadata = Map.of("source", "sensor"); + DataPart part = DataPart.fromJson(""" + {"temperature": 22.5}""", metadata); + + assertInstanceOf(Map.class, part.data()); + assertEquals("sensor", part.metadata().get("source")); + } + + @Test + void testFromJson_nestedObject() { + DataPart part = DataPart.fromJson(""" + {"outer": {"inner": [1, 2, 3]}}"""); + + Map data = assertInstanceOf(Map.class, part.data()); + Map outer = assertInstanceOf(Map.class, data.get("outer")); + assertEquals(List.of(1L, 2L, 3L), outer.get("inner")); + } + + @Test + void testFromJson_nullJsonThrows() { + assertThrows(IllegalArgumentException.class, () -> DataPart.fromJson(null)); + } + + @Test + void testFromJson_nullLiteralThrows() { + assertThrows(IllegalArgumentException.class, () -> DataPart.fromJson("null")); + } + + @Test + void testFromJson_invalidJsonThrows() { + assertThrows(IllegalArgumentException.class, () -> DataPart.fromJson("{invalid}")); + } +} From d3f88cb1f54501ae1d64147cd4709c1e1f1c81f2 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 10 Apr 2026 09:43:40 +0200 Subject: [PATCH 102/192] =?UTF-8?q?fix:=20resolve=20event=20stream=20race?= =?UTF-8?q?=20conditions=20in=20EventConsumer=20and=20SSE=20tr=E2=80=A6=20?= =?UTF-8?q?(#782)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ansport Fixed multiple race conditions causing intermittent test failures in streaming and subscription scenarios. These fixes reduced the failure rate from ~33% to 0% across 1,500+ test iterations in CI. Removed executor.execute() wrapper in REST/JSONRPC routes that delayed subscription by 100-600ms, causing events to be lost when EventConsumer started emitting before subscriber was ready. Changed onCancelTask to use consumeAndBreakOnInterrupt() instead of consumeAll(). Removed unused ResultAggregator.consumeAll() method since cancel was its only caller. Moved EventConsumer polling loop to executor thread to prevent blocking caller, ensuring subscription happens immediately without delay. Fixed race in onSubscribeToTask where initial task snapshot was enqueued but EventConsumer polling hadn't started yet. Added insertingProcessor() utility to AsyncUtils that prepends initial items synchronously to reactive streams using mutiny-zero ZeroPublisher, ensuring subscriber receives initial task snapshot immediately on subscription. Updated transport layer unit tests (JSONRPCHandlerTest, GrpcHandlerTest) to expect initial task snapshot per A2A Protocol Specification 3.1.6. Fixed insertingProcessor() to respect reactive streams semantics by sending inserted items in the source's onSubscribe() callback after subscription is established, rather than immediately in the ZeroPublisher creation lambda. Fixed two test race conditions where tests checked for received events immediately after subscription was established (server-side metric), without waiting for consumer callbacks to actually process events: - testSubscribeToTaskWithInterruptedStateKeepsStreamOpen: Added initialTaskLatch to wait for initial TaskEvent reception - testNonBlockingWithMultipleMessages: Added streamConsumerReadyLatch to wait for streaming consumer to start receiving events Enhanced awaitingFinalEvent tracking with timeout guards (max 3s wait) to prevent infinite waiting if final event never arrives due to distribution delays in replicated scenarios. Increased sleep delay from 50ms to 150ms to account for CI environment latency and ensure buffered events flush before stream ends. Improved pollTimeoutsWhileAwaitingFinal reset logic to only reset when not awaiting final event. Calculated timeout constant from base timeout value for better maintainability. Tests fixed: - testNonBlockingWithMultipleMessages - testCancelTaskSuccess - testSubscribeToTaskWithInterruptedStateKeepsStreamOpen --- .../server/apps/quarkus/A2AServerRoutes.java | 28 +- .../server/rest/quarkus/A2AServerRoutes.java | 36 +- .../io/a2a/server/events/EventConsumer.java | 342 ++++++++++-------- .../java/io/a2a/server/events/EventQueue.java | 45 +++ .../DefaultRequestHandler.java | 54 +-- .../io/a2a/server/tasks/ResultAggregator.java | 51 +-- .../io/a2a/server/util/async/AsyncUtils.java | 59 +++ .../a2a/server/events/EventConsumerTest.java | 8 +- .../server/tasks/ResultAggregatorTest.java | 10 +- .../apps/common/AbstractA2AServerTest.java | 19 +- .../grpc/handler/GrpcHandlerTest.java | 17 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 10 +- 12 files changed, 422 insertions(+), 257 deletions(-) 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 7ca65cb35..b3d51ea4a 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 @@ -299,15 +299,15 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { .putHeader(CONTENT_TYPE, APPLICATION_JSON) .end(serializeResponse(error)); } else if (streaming) { - final Multi> finalStreamingResponse = streamingResponse; - executor.execute(() -> { - // Convert Multi to Multi with SSE formatting - AtomicLong eventIdCounter = new AtomicLong(0); - Multi sseEvents = finalStreamingResponse - .map(response -> SseFormatter.formatResponseAsSSE(response, eventIdCounter.getAndIncrement())); - // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); - }); + // Convert Multi to Multi with SSE formatting + // CRITICAL: Subscribe synchronously to avoid race condition where EventConsumer + // starts emitting events before MultiSseSupport subscribes. The executor.execute() + // wrapper caused 100-600ms delays before subscription, causing events to be lost. + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = streamingResponse + .map(response -> SseFormatter.formatResponseAsSSE(response, eventIdCounter.getAndIncrement())); + // Write SSE-formatted strings to HTTP response + MultiSseSupport.writeSseStrings(sseEvents, rc, context); } else { rc.response() @@ -783,7 +783,17 @@ public void onNext(String sseEvent) { if (headers.get(CONTENT_TYPE) == null) { headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); } + // Additional SSE headers to prevent buffering + headers.set("Cache-Control", "no-cache"); + headers.set("X-Accel-Buffering", "no"); // Disable nginx buffering response.setChunked(true); + + // CRITICAL: Disable write queue max size to prevent buffering + // Vert.x buffers writes by default - we need immediate flushing for SSE + response.setWriteQueueMaxSize(1); + + // Send initial SSE comment to kickstart the stream + response.write(": SSE stream started\n\n"); } // Write SSE-formatted string to response 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 03bdbd5e5..94deae2b3 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 @@ -221,15 +221,15 @@ public void sendMessageStreaming(@Body String body, RoutingContext rc) { if (error != null) { sendResponse(rc, error); } else if (streamingResponse != null) { - final HTTPRestStreamingResponse finalStreamingResponse = streamingResponse; - executor.execute(() -> { - // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) - AtomicLong eventIdCounter = new AtomicLong(0); - Multi sseEvents = Multi.createFrom().publisher(finalStreamingResponse.getPublisher()) - .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); - // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); - }); + // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) + // CRITICAL: Subscribe synchronously to avoid race condition where EventConsumer + // starts emitting events before MultiSseSupport subscribes. The executor.execute() + // wrapper caused 100-600ms delays before subscription, causing events to be lost. + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = Multi.createFrom().publisher(streamingResponse.getPublisher()) + .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); + // Write SSE-formatted strings to HTTP response + MultiSseSupport.writeSseStrings(sseEvents, rc, context); } } } @@ -431,15 +431,15 @@ public void subscribeToTask(RoutingContext rc) { if (error != null) { sendResponse(rc, error); } else if (streamingResponse != null) { - final HTTPRestStreamingResponse finalStreamingResponse = streamingResponse; - executor.execute(() -> { - // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) - AtomicLong eventIdCounter = new AtomicLong(0); - Multi sseEvents = Multi.createFrom().publisher(finalStreamingResponse.getPublisher()) - .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); - // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); - }); + // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) + // CRITICAL: Subscribe synchronously to avoid race condition where EventConsumer + // starts emitting events before MultiSseSupport subscribes. The executor.execute() + // wrapper caused 100-600ms delays before subscription, causing events to be lost. + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = Multi.createFrom().publisher(streamingResponse.getPublisher()) + .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); + // Write SSE-formatted strings to HTTP response + MultiSseSupport.writeSseStrings(sseEvents, rc, context); } } } 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 0577e4f28..324d6e2d0 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 @@ -1,5 +1,6 @@ package io.a2a.server.events; +import java.util.concurrent.Executor; import java.util.concurrent.Flow; import io.a2a.spec.A2AError; @@ -19,22 +20,37 @@ public class EventConsumer { private static final Logger LOGGER = LoggerFactory.getLogger(EventConsumer.class); private final EventQueue queue; + private final Executor executor; private volatile @Nullable Throwable error; private volatile boolean cancelled = false; private volatile boolean agentCompleted = false; private volatile int pollTimeoutsAfterAgentCompleted = 0; private volatile @Nullable TaskState lastSeenTaskState = null; + private volatile int pollTimeoutsWhileAwaitingFinal = 0; private static final String ERROR_MSG = "Agent did not return any response"; private static final int NO_WAIT = -1; private static final int QUEUE_WAIT_MILLISECONDS = 500; // In replicated scenarios, events can arrive hundreds of milliseconds after local agent completes // Grace period allows Kafka replication to deliver late-arriving events - // 3 timeouts * 500ms = 1500ms grace period for replication delays + // Calculation: MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED * QUEUE_WAIT_MILLISECONDS = 1500ms private static final int MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED = 3; + // Maximum time to wait for final event when awaitingFinalEvent is set + // If event doesn't arrive after this many timeouts, assume it won't arrive + // Calculation uses ceiling division to ensure timeout is at least MAX_AWAITING_FINAL_TIMEOUT_MS + private static final int MAX_AWAITING_FINAL_TIMEOUT_MS = 3000; + private static final int MAX_POLL_TIMEOUTS_AWAITING_FINAL = + (MAX_AWAITING_FINAL_TIMEOUT_MS + QUEUE_WAIT_MILLISECONDS - 1) / QUEUE_WAIT_MILLISECONDS; + // WORKAROUND: Sleep delay to allow SSE buffer flush before stream completion + // This is a temporary workaround for a race condition where tube.complete() can arrive + // before the final event is flushed from the SSE buffer. Ideally, this should be handled + // at the transport layer (e.g., MultiSseSupport) with proper write completion callbacks. + // TODO: Move buffer flush handling to transport layer to avoid this latency penalty + private static final int BUFFER_FLUSH_DELAY_MS = 150; - public EventConsumer(EventQueue queue) { + public EventConsumer(EventQueue queue, Executor executor) { this.queue = queue; + this.executor = executor; LOGGER.debug("EventConsumer created with queue {}", System.identityHashCode(queue)); } @@ -51,162 +67,204 @@ public Flow.Publisher consumeAll() { .withBackpressureStrategy(BackpressureStrategy.BUFFER) .withBufferSize(256); return ZeroPublisher.create(conf, tube -> { - boolean completed = false; - try { - while (true) { - // Check if cancelled by client disconnect - if (cancelled) { - LOGGER.debug("EventConsumer detected cancellation, exiting polling loop for queue {}", System.identityHashCode(queue)); - completed = true; - tube.complete(); - return; - } + // CRITICAL: Spawn polling loop on executor to avoid blocking the calling thread + // The lambda returns immediately, but polling continues on separate thread + executor.execute(() -> { + boolean completed = false; + try { + while (true) { + // Check if cancelled by client disconnect + if (cancelled) { + LOGGER.debug("EventConsumer detected cancellation, exiting polling loop for queue {}", System.identityHashCode(queue)); + completed = true; + tube.complete(); + return; + } - if (error != null) { - completed = true; - tube.fail(error); - return; - } - // We use a timeout when waiting for an event from the queue. - // This is required because it allows the loop to check if - // `self._exception` has been set by the `agent_task_callback`. - // Without the timeout, loop might hang indefinitely if no events are - // enqueued by the agent and the agent simply threw an exception + if (error != null) { + completed = true; + tube.fail(error); + return; + } + // We use a timeout when waiting for an event from the queue. + // This is required because it allows the loop to check if + // `self._exception` has been set by the `agent_task_callback`. + // Without the timeout, loop might hang indefinitely if no events are + // enqueued by the agent and the agent simply threw an exception - // TODO the callback mentioned above seems unused in the Python 0.2.1 tag - EventQueueItem item; - Event event; - try { - LOGGER.debug("EventConsumer polling queue {} (error={}, agentCompleted={})", - System.identityHashCode(queue), error, agentCompleted); - item = queue.dequeueEventItem(QUEUE_WAIT_MILLISECONDS); - if (item == null) { - int queueSize = queue.size(); - LOGGER.debug("EventConsumer poll timeout (null item), agentCompleted={}, queue.size()={}, timeoutCount={}", - agentCompleted, queueSize, pollTimeoutsAfterAgentCompleted); - // If agent completed, a poll timeout means no more events are coming - // MainEventBusProcessor has 500ms to distribute events from MainEventBus - // If we timeout with agentCompleted=true, all events have been distributed - // - // IMPORTANT: In replicated scenarios, remote events may arrive AFTER local agent completes! - // Use grace period to allow for Kafka replication delays (can be 400-500ms) - // - // CRITICAL: Do NOT close if task is in interrupted state (INPUT_REQUIRED, AUTH_REQUIRED) - // Per A2A spec, interrupted states are NOT terminal - the stream must stay open - // for future state updates even after agent completes (agent will be re-invoked later). - boolean isInterruptedState = lastSeenTaskState != null && lastSeenTaskState.isInterrupted(); - if (agentCompleted && queueSize == 0 && !isInterruptedState) { - pollTimeoutsAfterAgentCompleted++; - if (pollTimeoutsAfterAgentCompleted >= MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED) { - LOGGER.debug("Agent completed with {} consecutive poll timeouts and empty queue, closing for graceful completion (queue={})", - pollTimeoutsAfterAgentCompleted, System.identityHashCode(queue)); - queue.close(); - completed = true; - tube.complete(); - return; - } else { - LOGGER.debug("Agent completed but grace period active ({}/{} timeouts), continuing to poll (queue={})", - pollTimeoutsAfterAgentCompleted, MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED, System.identityHashCode(queue)); + // TODO the callback mentioned above seems unused in the Python 0.2.1 tag + EventQueueItem item; + Event event; + try { + LOGGER.debug("EventConsumer polling queue {} (error={}, agentCompleted={})", + System.identityHashCode(queue), error, agentCompleted); + item = queue.dequeueEventItem(QUEUE_WAIT_MILLISECONDS); + if (item == null) { + int queueSize = queue.size(); + boolean awaitingFinal = queue.isAwaitingFinalEvent(); + LOGGER.debug("EventConsumer poll timeout (null item), agentCompleted={}, queue.size()={}, awaitingFinalEvent={}, timeoutCount={}, awaitingTimeoutCount={}", + agentCompleted, queueSize, awaitingFinal, pollTimeoutsAfterAgentCompleted, pollTimeoutsWhileAwaitingFinal); + // If agent completed, a poll timeout means no more events are coming + // MainEventBusProcessor has 500ms to distribute events from MainEventBus + // If we timeout with agentCompleted=true, all events have been distributed + // + // IMPORTANT: In replicated scenarios, remote events may arrive AFTER local agent completes! + // Use grace period to allow for Kafka replication delays (can be 400-500ms) + // + // CRITICAL: Do NOT close if task is in interrupted state (INPUT_REQUIRED, AUTH_REQUIRED) + // Per A2A spec, interrupted states are NOT terminal - the stream must stay open + // for future state updates even after agent completes (agent will be re-invoked later). + // + // CRITICAL: Don't start timeout counter if we're awaiting a final event. + // The awaitingFinalEvent flag is set when MainQueue enqueues a final event + // but it hasn't been distributed to this ChildQueue yet. + // HOWEVER: If we've been waiting too long for the final event (>3s), give up and + // proceed with normal timeout logic to prevent infinite waiting. + boolean isInterruptedState = lastSeenTaskState != null && lastSeenTaskState.isInterrupted(); + + // Track how long we've been waiting for the final event. + // Three cases for the awaiting counter: + // awaitingFinal && queueSize == 0: final event enqueued in MainQueue but not yet + // distributed here — increment timeout counter and give up after MAX timeout. + // awaitingFinal && queueSize > 0: events are still in transit, do nothing — + // the counter is reset below once an event is successfully dequeued. + // !awaitingFinal: not waiting for anything — reset the counter (timeout case; + // the successful-dequeue reset happens below at the event-received path). + if (awaitingFinal && queueSize == 0) { + pollTimeoutsWhileAwaitingFinal++; + if (pollTimeoutsWhileAwaitingFinal >= MAX_POLL_TIMEOUTS_AWAITING_FINAL) { + LOGGER.debug("Waited {} timeouts for final event but it hasn't arrived - proceeding with normal timeout logic (queue={})", + pollTimeoutsWhileAwaitingFinal, System.identityHashCode(queue)); + // Clear the flag on the queue itself, not just the local variable + queue.clearAwaitingFinalEvent(); + awaitingFinal = false; // Also update local variable for this iteration + } + } else if (!awaitingFinal) { + // Poll timed out and we are not awaiting a final event: reset the counter. + // (The successful-dequeue reset is handled separately below.) + pollTimeoutsWhileAwaitingFinal = 0; + } + + if (agentCompleted && queueSize == 0 && !isInterruptedState && !awaitingFinal) { + pollTimeoutsAfterAgentCompleted++; + if (pollTimeoutsAfterAgentCompleted >= MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED) { + LOGGER.debug("Agent completed with {} consecutive poll timeouts and empty queue, closing for graceful completion (queue={})", + pollTimeoutsAfterAgentCompleted, System.identityHashCode(queue)); + queue.close(); + completed = true; + tube.complete(); + return; + } else { + LOGGER.debug("Agent completed but grace period active ({}/{} timeouts), continuing to poll (queue={})", + pollTimeoutsAfterAgentCompleted, MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED, System.identityHashCode(queue)); + } + } else if (agentCompleted && isInterruptedState) { + LOGGER.debug("Agent completed but task is in interrupted state ({}), stream must remain open (queue={})", + lastSeenTaskState, System.identityHashCode(queue)); + pollTimeoutsAfterAgentCompleted = 0; // Reset counter + } else if (agentCompleted && queueSize > 0) { + LOGGER.debug("Agent completed but queue has {} pending events, resetting timeout counter and continuing to poll (queue={})", + queueSize, System.identityHashCode(queue)); + pollTimeoutsAfterAgentCompleted = 0; // Reset counter when events arrive + } else if (agentCompleted && awaitingFinal) { + LOGGER.debug("Agent completed, awaiting final event (timeout {}/{}), continuing to poll (queue={})", + pollTimeoutsWhileAwaitingFinal, MAX_POLL_TIMEOUTS_AWAITING_FINAL, System.identityHashCode(queue)); + pollTimeoutsAfterAgentCompleted = 0; // Reset counter while awaiting final } - } else if (agentCompleted && isInterruptedState) { - LOGGER.debug("Agent completed but task is in interrupted state ({}), stream must remain open (queue={})", - lastSeenTaskState, System.identityHashCode(queue)); - pollTimeoutsAfterAgentCompleted = 0; // Reset counter - } else if (agentCompleted && queueSize > 0) { - LOGGER.debug("Agent completed but queue has {} pending events, resetting timeout counter and continuing to poll (queue={})", - queueSize, System.identityHashCode(queue)); - pollTimeoutsAfterAgentCompleted = 0; // Reset counter when events arrive + continue; } - continue; - } - // Event received - reset timeout counter - pollTimeoutsAfterAgentCompleted = 0; - event = item.getEvent(); - LOGGER.debug("EventConsumer received event: {} (queue={})", - event.getClass().getSimpleName(), System.identityHashCode(queue)); + // Event received - reset timeout counters + pollTimeoutsAfterAgentCompleted = 0; + pollTimeoutsWhileAwaitingFinal = 0; + event = item.getEvent(); + LOGGER.debug("EventConsumer received event: {} (queue={})", + event.getClass().getSimpleName(), System.identityHashCode(queue)); - // Track the latest task state for grace period logic - if (event instanceof Task task) { - lastSeenTaskState = task.status().state(); - } else if (event instanceof TaskStatusUpdateEvent tue) { - lastSeenTaskState = tue.status().state(); - } + // Track the latest task state for grace period logic + if (event instanceof Task task) { + lastSeenTaskState = task.status().state(); + } else if (event instanceof TaskStatusUpdateEvent tue) { + lastSeenTaskState = tue.status().state(); + } - // Defensive logging for error handling - if (event instanceof Throwable thr) { - LOGGER.debug("EventConsumer detected Throwable event: {} - triggering tube.fail()", - thr.getClass().getSimpleName()); - tube.fail(thr); - return; - } + // Defensive logging for error handling + if (event instanceof Throwable thr) { + LOGGER.debug("EventConsumer detected Throwable event: {} - triggering tube.fail()", + thr.getClass().getSimpleName()); + tube.fail(thr); + return; + } - // Check for QueueClosedEvent BEFORE sending to avoid delivering it to subscribers - boolean isFinalEvent = false; - if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) { - isFinalEvent = true; - } else if (event instanceof Message) { - isFinalEvent = true; - } else if (event instanceof Task task) { - isFinalEvent = isStreamTerminatingTask(task); - } else if (event instanceof QueueClosedEvent) { - // Poison pill event - signals queue closure from remote node - // Do NOT send to subscribers - just close the queue - LOGGER.debug("Received QueueClosedEvent for task {}, treating as final event", - ((QueueClosedEvent) event).getTaskId()); - isFinalEvent = true; - } else if (event instanceof A2AError) { - // A2AError events are terminal - they trigger automatic FAILED state transition - LOGGER.debug("Received A2AError event, treating as final event"); - isFinalEvent = true; - } + // Check for QueueClosedEvent BEFORE sending to avoid delivering it to subscribers + boolean isFinalEvent = false; + if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) { + isFinalEvent = true; + } else if (event instanceof Message) { + isFinalEvent = true; + } else if (event instanceof Task task) { + isFinalEvent = isStreamTerminatingTask(task); + } else if (event instanceof QueueClosedEvent) { + // Poison pill event - signals queue closure from remote node + // Do NOT send to subscribers - just close the queue + LOGGER.debug("Received QueueClosedEvent for task {}, treating as final event", + ((QueueClosedEvent) event).getTaskId()); + isFinalEvent = true; + } else if (event instanceof A2AError) { + // A2AError events are terminal - they trigger automatic FAILED state transition + LOGGER.debug("Received A2AError event, treating as final event"); + isFinalEvent = true; + } - // Only send event if it's not a QueueClosedEvent - // QueueClosedEvent is an internal coordination event used for replication - // and should not be exposed to API consumers - boolean isFinalSent = false; - if (!(event instanceof QueueClosedEvent)) { - tube.send(item); - isFinalSent = isFinalEvent; - } + // Only send event if it's not a QueueClosedEvent + // QueueClosedEvent is an internal coordination event used for replication + // and should not be exposed to API consumers + boolean isFinalSent = false; + if (!(event instanceof QueueClosedEvent)) { + tube.send(item); + isFinalSent = isFinalEvent; + } - if (isFinalEvent) { - LOGGER.debug("Final or interrupted event detected, closing queue and breaking loop for queue {}", System.identityHashCode(queue)); - queue.close(); - LOGGER.debug("Queue closed, breaking loop for queue {}", System.identityHashCode(queue)); + if (isFinalEvent) { + LOGGER.debug("Final or interrupted event detected, closing queue and breaking loop for queue {}", System.identityHashCode(queue)); + queue.close(); + LOGGER.debug("Queue closed, breaking loop for queue {}", System.identityHashCode(queue)); - // CRITICAL: Allow tube buffer to flush before calling tube.complete() - // tube.send() buffers events asynchronously. If we call tube.complete() immediately, - // the stream-end signal can reach the client BEFORE the buffered final event, - // causing the client to close the connection and never receive the final event. - // This is especially important in replicated scenarios where events arrive via Kafka - // and timing is less deterministic. A small delay ensures the buffer flushes. - if (isFinalSent) { - try { - Thread.sleep(50); // 50ms to allow SSE buffer flush - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + // CRITICAL: Allow tube buffer to flush before calling tube.complete() + // tube.send() buffers events asynchronously. If we call tube.complete() immediately, + // the stream-end signal can reach the client BEFORE the buffered final event, + // causing the client to close the connection and never receive the final event. + // This is especially important in replicated scenarios where events arrive via Kafka + // and timing is less deterministic. + if (isFinalSent) { + try { + Thread.sleep(BUFFER_FLUSH_DELAY_MS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } + break; } - break; + } catch (EventQueueClosedException e) { + completed = true; + tube.complete(); + return; + } catch (Throwable t) { + completed = true; + tube.fail(t); + return; } - } catch (EventQueueClosedException e) { - completed = true; + } + } finally { + if (!completed) { + LOGGER.debug("EventConsumer finally block: calling tube.complete() for queue {}", System.identityHashCode(queue)); tube.complete(); - return; - } catch (Throwable t) { - tube.fail(t); - return; + LOGGER.debug("EventConsumer finally block: tube.complete() returned for queue {}", System.identityHashCode(queue)); + } else { + LOGGER.debug("EventConsumer finally block: completed=true, skipping tube.complete() for queue {}", System.identityHashCode(queue)); } } - } finally { - if (!completed) { - LOGGER.debug("EventConsumer finally block: calling tube.complete() for queue {}", System.identityHashCode(queue)); - tube.complete(); - LOGGER.debug("EventConsumer finally block: tube.complete() returned for queue {}", System.identityHashCode(queue)); - } else { - LOGGER.debug("EventConsumer finally block: completed=true, skipping tube.complete() for queue {}", System.identityHashCode(queue)); - } - } + }); + // Lambda returns immediately - polling continues on executor thread }); } 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 53ae22da4..6226f72e2 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 @@ -304,6 +304,36 @@ public void taskDone() { */ public abstract int size(); + /** + * Returns whether this queue is awaiting a final event to be delivered. + *

            + * This is used by EventConsumer to determine if it should keep polling even when + * the queue is empty. A final event may still be in-transit through MainEventBusProcessor. + *

            + *

            + * For MainQueue: always returns false (MainQueue cannot be consumed). + * For ChildQueue: returns true if {@link ChildQueue#expectFinalEvent()} was called + * but the final event hasn't been received yet. + *

            + * + * @return true if awaiting a final event, false otherwise + */ + public boolean isAwaitingFinalEvent() { + // Default implementation - overridden by ChildQueue + return false; + } + + /** + * Clears the awaiting final event flag. + *

            + * Default implementation is a no-op for queues that don't track this state. + * ChildQueue overrides this to actually clear the flag. + *

            + */ + public void clearAwaitingFinalEvent() { + // Default no-op implementation - overridden by ChildQueue + } + /** * Closes this event queue gracefully, allowing pending events to be consumed. */ @@ -757,6 +787,11 @@ public int size() { return queue.size(); } + @Override + public boolean isAwaitingFinalEvent() { + return awaitingFinalEvent; + } + @Override public void awaitQueuePollerStart() throws InterruptedException { parent.awaitQueuePollerStart(); @@ -790,6 +825,16 @@ void expectFinalEvent() { LOGGER.debug("ChildQueue {} now awaiting final event", System.identityHashCode(this)); } + /** + * Called by EventConsumer when it has waited too long for the final event. + * This allows normal timeout logic to proceed if the final event never arrives. + */ + @Override + public void clearAwaitingFinalEvent() { + awaitingFinalEvent = false; + LOGGER.debug("ChildQueue {} cleared awaitingFinalEvent flag (timeout)", System.identityHashCode(this)); + } + @Override public void close() { close(false); 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 9a480c44f..d67301023 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 @@ -2,6 +2,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.insertingProcessor; import static io.a2a.server.util.async.AsyncUtils.processor; import static java.util.concurrent.TimeUnit.SECONDS; @@ -67,7 +68,6 @@ import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.UnsupportedOperationError; - import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; @@ -380,6 +380,9 @@ public Task onCancelTask(CancelTaskParams params, ServerCallContext context) thr ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor, eventConsumerExecutor); EventQueue queue = queueManager.createOrTap(task.id()); + EventConsumer consumer = new EventConsumer(queue, eventConsumerExecutor); + + // Call agentExecutor.cancel() to enqueue the CANCELED event RequestContext cancelRequestContext = requestContextBuilder.get() .setTaskId(task.id()) .setContextId(task.contextId()) @@ -387,29 +390,37 @@ public Task onCancelTask(CancelTaskParams params, ServerCallContext context) thr .setServerCallContext(context) .build(); AgentEmitter emitter = new AgentEmitter(cancelRequestContext, queue); + + // Call agentExecutor.cancel() with error handling + // AgentExecutor is user-provided, so catch all exceptions try { agentExecutor.cancel(cancelRequestContext, emitter); } catch (TaskNotCancelableError e) { - // Expected error - log at INFO level - LOGGER.info("Task {} is not cancelable", task.id()); - throw e; + // Expected error - log and enqueue + LOGGER.info("Task {} is not cancelable, agent threw: {}", task.id(), e.getMessage()); + emitter.fail(e); } catch (A2AError e) { - // Other A2A errors - log at WARN level with stack trace - LOGGER.warn("Agent cancellation threw A2AError for task {}: {} - {}", + // Other A2A errors - log and enqueue + LOGGER.warn("Agent cancellation threw A2AError for task {}: {} - {}", task.id(), e.getClass().getSimpleName(), e.getMessage(), e); - throw e; + emitter.fail(e); } catch (Exception e) { - // Unexpected errors - log at ERROR level + // Unexpected errors - log and enqueue as InternalError LOGGER.error("Agent cancellation threw unexpected exception for task {}", task.id(), e); - throw new io.a2a.spec.InternalError("Agent cancellation failed: " + e.getMessage()); + emitter.fail(new io.a2a.spec.InternalError("Agent cancellation failed: " + e.getMessage())); } + // Cancel any running agent future Optional.ofNullable(runningAgents.get(task.id())) .ifPresent(cf -> cf.cancel(true)); - EventConsumer consumer = new EventConsumer(queue); - EventKind type = resultAggregator.consumeAll(consumer); - if (!(type instanceof Task tempTask)) { + // Consume events with blocking=true to wait for CANCELED state + // The latch in consumeAndBreakOnInterrupt ensures EventConsumer starts before we wait + // CANCELED is a final state, so loop will break naturally when event arrives + // If agentExecutor.cancel() threw TaskNotCancelableError, that A2AError event will also break the loop + ResultAggregator.EventTypeAndInterrupt etai = resultAggregator.consumeAndBreakOnInterrupt(consumer, true); + + if (!(etai.eventType() instanceof Task tempTask)) { throw new InternalError("Agent did not return valid response for cancel"); } @@ -459,7 +470,7 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte boolean interruptedOrNonBlocking = false; // Create consumer BEFORE starting agent - callback is registered inside registerAndExecuteAgentAsync - EventConsumer consumer = new EventConsumer(queue); + EventConsumer consumer = new EventConsumer(queue, eventConsumerExecutor); EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue, consumer.createAgentRunnableDoneCallback()); @@ -653,7 +664,7 @@ public Flow.Publisher onMessageSendStream( ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); // Create consumer BEFORE starting agent - callback is registered inside registerAndExecuteAgentAsync - EventConsumer consumer = new EventConsumer(queue); + EventConsumer consumer = new EventConsumer(queue, eventConsumerExecutor); EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue, consumer.createAgentRunnableDoneCallback()); @@ -840,14 +851,15 @@ public Flow.Publisher onSubscribeToTask(TaskIdParams params, // Per A2A Protocol Spec 3.1.6 (Subscribe to Task): // "The operation MUST return a Task object as the first event in the stream, // representing the current state of the task at the time of subscription." - // Enqueue the current task state directly to this ChildQueue only (already persisted, no need for MainEventBus) - queue.enqueueEventLocalOnly(task); - LOGGER.debug("onSubscribeToTask - enqueued current task state as first event for taskId: {}", params.id()); - - EventConsumer consumer = new EventConsumer(queue); + // Instead of enqueuing and hoping EventConsumer polls it in time, we prepend it + // directly to the Publisher stream, ensuring synchronous delivery to subscriber + EventConsumer consumer = new EventConsumer(queue, eventConsumerExecutor); Flow.Publisher results = resultAggregator.consumeAndEmit(consumer); - LOGGER.debug("onSubscribeToTask - returning publisher for taskId: {}", params.id()); - return convertingProcessor(results, item -> (StreamingEventKind) item.getEvent()); + LOGGER.debug("onSubscribeToTask - prepending initial task snapshot to stream, taskId: {}", params.id()); + return insertingProcessor( + convertingProcessor(results, item -> (StreamingEventKind) item.getEvent()), + task + ); } @Override 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 06c689eb2..f1f15021e 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 @@ -9,6 +9,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import io.a2a.server.events.EventConsumer; @@ -58,54 +59,12 @@ public Flow.Publisher consumeAndEmit(EventConsumer consumer) { return true; }); - // Wrap the publisher to ensure subscription happens on eventConsumerExecutor - // This prevents EventConsumer polling loop from running on AgentExecutor threads - // which caused thread accumulation when those threads didn't timeout - return new Flow.Publisher() { - @Override - public void subscribe(Flow.Subscriber subscriber) { - // Submit subscription to eventConsumerExecutor to isolate polling work - eventConsumerExecutor.execute(() -> processed.subscribe(subscriber)); - } - }; + // No wrapper needed - EventConsumer.consumeAll() now handles thread offloading internally + // This ensures subscription happens immediately without delay, preventing race condition + // where EventConsumer starts emitting before subscriber is ready + return processed; } - public EventKind consumeAll(EventConsumer consumer) throws A2AError { - AtomicReference returnedEvent = new AtomicReference<>(); - Flow.Publisher allItems = consumer.consumeAll(); - AtomicReference error = new AtomicReference<>(); - consumer( - createTubeConfig(), - allItems, - (item) -> { - Event event = item.getEvent(); - if (event instanceof Message msg) { - message = msg; - if (returnedEvent.get() == null) { - returnedEvent.set(msg); - return false; - } - } - // TaskStore update moved to MainEventBusProcessor - return true; - }, - error::set); - - Throwable err = error.get(); - if (err != null) { - Utils.rethrow(err); - } - - EventKind result = returnedEvent.get(); - if (result != null) { - return result; - } - Task task = taskManager.getTask(); - if (task == null) { - throw new io.a2a.spec.InternalError("No task or message available after consuming all events"); - } - return task; - } public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, boolean blocking) throws A2AError { Flow.Publisher allItems = consumer.consumeAll(); 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 4d1d4f9c4..4e0a6ea5b 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 @@ -91,6 +91,65 @@ public static Flow.Publisher convertingProcessor(Flow.Publisher sou return new Transform<>(source, converterFunction); } + /** + * Creates a publisher that first emits the given items, then emits all items from the source publisher. + *

            + * This is useful for prepending initial items to a stream, ensuring they are delivered + * synchronously when the subscriber subscribes, before any items from the source publisher. + *

            + *

            + * The inserted items are sent after the source publisher's onSubscribe is called, ensuring + * proper reactive streams semantics where items are only sent after subscription is established. + *

            + * + * @param source the source publisher whose items will be emitted after the inserted items + * @param inserted the items to emit first (in order) + * @param the type of items + * @return a new publisher that emits inserted items first, then source items + */ + @SafeVarargs + public static Flow.Publisher insertingProcessor(Flow.Publisher source, T... inserted) { + return ZeroPublisher.create(createTubeConfig(), tube -> { + // Subscribe to source publisher and intercept the subscription flow + source.subscribe(new Flow.Subscriber() { + private Flow.@Nullable Subscription subscription; + private boolean insertedItemsSent = false; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + + // CRITICAL: Send inserted items BEFORE requesting from source + // This ensures they are emitted first, after subscription is established + if (!insertedItemsSent) { + insertedItemsSent = true; + for (T item : inserted) { + tube.send(item); + } + } + + // Now request all items from source + subscription.request(Long.MAX_VALUE); + } + + @Override + public void onNext(T item) { + tube.send(item); // Forward source items to our tube + } + + @Override + public void onError(Throwable throwable) { + tube.fail(throwable); + } + + @Override + public void onComplete() { + tube.complete(); + } + }); + }); + } + private static abstract class AbstractSubscriber implements Flow.Subscriber { private Flow.@Nullable Subscription subscription; 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 17242ba89..29c3c6ce9 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 @@ -72,7 +72,7 @@ public void init() { .taskId(TASK_ID) .mainEventBus(mainEventBus) .build().tap(); - eventConsumer = new EventConsumer(eventQueue); + eventConsumer = new EventConsumer(eventQueue, Runnable::run); } @AfterEach @@ -397,7 +397,7 @@ public void testConsumeAllStopsOnQueueClosed() throws Exception { EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) .mainEventBus(mainEventBus) .build().tap(); - EventConsumer consumer = new EventConsumer(queue); + EventConsumer consumer = new EventConsumer(queue, Runnable::run); // Close the queue immediately queue.close(); @@ -445,7 +445,7 @@ public void testConsumeAllHandlesQueueClosedException() throws Exception { EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) .mainEventBus(mainEventBus) .build().tap(); - EventConsumer consumer = new EventConsumer(queue); + EventConsumer consumer = new EventConsumer(queue, Runnable::run); // Add a message event (which will complete the stream) Event message = fromJson(MESSAGE_PAYLOAD, Message.class); @@ -499,7 +499,7 @@ public void testConsumeAllTerminatesOnQueueClosedEvent() throws Exception { EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) .mainEventBus(mainEventBus) .build().tap(); - EventConsumer consumer = new EventConsumer(queue); + EventConsumer consumer = new EventConsumer(queue, Runnable::run); // Enqueue a QueueClosedEvent (poison pill) QueueClosedEvent queueClosedEvent = new QueueClosedEvent(TASK_ID); diff --git a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java index a347d9cd0..fcd3e9381 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java @@ -258,7 +258,7 @@ void testConsumeAndBreakNonBlocking() throws Exception { // Create real EventConsumer with the queue EventConsumer eventConsumer = - new EventConsumer(queue); + new EventConsumer(queue, Runnable::run); // Close queue after first event to simulate stream ending after processing queue.close(); @@ -306,7 +306,7 @@ void testConsumeAndBreakOnAuthRequired_Blocking() throws Exception { waitForEventProcessing(processor, () -> queue.enqueueEvent(authRequiredTask)); // Create EventConsumer - EventConsumer eventConsumer = new EventConsumer(queue); + EventConsumer eventConsumer = new EventConsumer(queue, Runnable::run); // Call consumeAndBreakOnInterrupt with blocking=true ResultAggregator.EventTypeAndInterrupt result = @@ -348,7 +348,7 @@ void testConsumeAndBreakOnAuthRequired_NonBlocking() throws Exception { waitForEventProcessing(processor, () -> queue.enqueueEvent(authRequiredTask)); // Create EventConsumer - EventConsumer eventConsumer = new EventConsumer(queue); + EventConsumer eventConsumer = new EventConsumer(queue, Runnable::run); // Call consumeAndBreakOnInterrupt with blocking=false ResultAggregator.EventTypeAndInterrupt result = @@ -396,7 +396,7 @@ void testAuthRequiredWithTaskStatusUpdateEvent() throws Exception { waitForEventProcessing(processor, () -> queue.enqueueEvent(authRequiredEvent)); // Create EventConsumer - EventConsumer eventConsumer = new EventConsumer(queue); + EventConsumer eventConsumer = new EventConsumer(queue, Runnable::run); // Call consumeAndBreakOnInterrupt ResultAggregator.EventTypeAndInterrupt result = @@ -442,7 +442,7 @@ void testAuthRequiredWithTaskEvent() throws Exception { waitForEventProcessing(processor, () -> queue.enqueueEvent(authRequiredTask)); // Create EventConsumer - EventConsumer eventConsumer = new EventConsumer(queue); + EventConsumer eventConsumer = new EventConsumer(queue, Runnable::run); // Call consumeAndBreakOnInterrupt ResultAggregator.EventTypeAndInterrupt result = 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 fc621bdb6..3b7cbb8c2 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 @@ -992,6 +992,7 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce AtomicBoolean streamClosedPrematurely = new AtomicBoolean(false); AtomicReference subscribeErrorRef = new AtomicReference<>(); CountDownLatch completionLatch = new CountDownLatch(1); + CountDownLatch initialTaskLatch = new CountDownLatch(1); // Consumer to track all events from subscription BiConsumer consumer = (event, agentCard) -> { @@ -1002,6 +1003,7 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce assertEquals(TaskState.TASK_STATE_INPUT_REQUIRED, taskEvent.getTask().status().state(), "Initial task should be in INPUT_REQUIRED state"); + initialTaskLatch.countDown(); return; } } else if (event instanceof TaskUpdateEvent taskUpdateEvent) { @@ -1037,8 +1039,11 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce // Wait for subscription to be established assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS), "Subscription should be established"); + // Wait for initial task to be received + assertTrue(initialTaskLatch.await(5, TimeUnit.SECONDS), "Should receive initial task snapshot"); + // Verify stream received initial task and is still open - assertTrue(receivedInitialTask.get(), "Should receive initial task snapshot"); + assertTrue(receivedInitialTask.get(), "Should have received initial task snapshot"); assertFalse(streamClosedPrematurely.get(), "Stream should NOT close for INPUT_REQUIRED state (interrupted, not terminal)"); @@ -1634,6 +1639,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { .build(); CountDownLatch streamEventLatch = new CountDownLatch(2); // artifact-2 + completion + CountDownLatch streamConsumerReadyLatch = new CountDownLatch(1); List streamReceivedEvents = new CopyOnWriteArrayList<>(); AtomicBoolean streamUnexpectedEvent = new AtomicBoolean(false); @@ -1642,6 +1648,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { if (event instanceof TaskUpdateEvent tue) { streamReceivedEvents.add(tue.getUpdateEvent()); streamEventLatch.countDown(); + streamConsumerReadyLatch.countDown(); // Signal that consumer is receiving events } else { streamUnexpectedEvent.set(true); } @@ -1659,6 +1666,10 @@ public void testNonBlockingWithMultipleMessages() throws Exception { assertTrue(streamSubscriptionLatch.await(15, TimeUnit.SECONDS), "Stream subscription should be established"); + // Wait for stream consumer to start receiving events + assertTrue(streamConsumerReadyLatch.await(5, TimeUnit.SECONDS), + "Stream consumer should start receiving events"); + // 4. Verify both consumers received artifact-2 and completion assertTrue(resubEventLatch.await(15, TimeUnit.SECONDS)); assertTrue(streamEventLatch.await(15, TimeUnit.SECONDS)); @@ -1921,7 +1932,11 @@ public void testAuthRequiredWorkflow() throws Exception { } }; - Consumer errorHandler = errorRef::set; + Consumer errorHandler = error -> { + if (!isStreamClosedError(error)) { + errorRef.set(error); + } + }; // Wait for subscription to be established CountDownLatch subscriptionLatch = new CountDownLatch(1); 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 b26b58c53..7c5a132fe 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 @@ -575,15 +575,20 @@ public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); } List result = streamRecorder.getValues(); - Assertions.assertEquals(events.size(), result.size()); + // Per A2A Protocol Spec 3.1.6: First event must be initial Task snapshot + // insertingProcessor prepends MINIMAL_TASK, then mock events follow + Assertions.assertEquals(3, result.size()); StreamResponse first = result.get(0); - Assertions.assertTrue(first.hasArtifactUpdate()); - io.a2a.grpc.TaskArtifactUpdateEvent event = first.getArtifactUpdate(); + Assertions.assertTrue(first.hasTask(), "First event must be initial Task snapshot"); + assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), first.getTask().getId()); + StreamResponse second = result.get(1); + Assertions.assertTrue(second.hasArtifactUpdate()); + io.a2a.grpc.TaskArtifactUpdateEvent event = second.getArtifactUpdate(); assertEquals("11", event.getArtifact().getArtifactId()); assertEquals("text", (event.getArtifact().getParts(0)).getText()); - StreamResponse second = result.get(1); - Assertions.assertTrue(second.hasStatusUpdate()); - assertEquals(TaskState.TASK_STATE_WORKING, second.getStatusUpdate().getStatus().getState()); + StreamResponse third = result.get(2); + Assertions.assertTrue(third.hasStatusUpdate()); + assertEquals(TaskState.TASK_STATE_WORKING, third.getStatusUpdate().getStatus().getState()); } @Test 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 72f94404b..8bb841ffc 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 @@ -972,10 +972,12 @@ public void onComplete() { future.join(); - // The Python implementation has several events emitted since it uses mocks. - // - // See testOnMessageStreamNewMessageExistingTaskSuccessMocks() for a test more similar to the Python implementation - assertEquals(events, results); + // Per A2A Protocol Spec 3.1.6: First event must be initial Task snapshot + // insertingProcessor prepends MINIMAL_TASK, then mock events follow + assertEquals(3, results.size()); + assertInstanceOf(Task.class, results.get(0), "First event must be initial Task snapshot"); + assertEquals(events.get(0), results.get(1), "Second event should be TaskArtifactUpdateEvent"); + assertEquals(events.get(1), results.get(2), "Third event should be TaskStatusUpdateEvent"); } @Test From 8f31f874e9f7b180f0d1fb63b95e212defa484b6 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 10 Apr 2026 09:48:39 +0200 Subject: [PATCH 103/192] fix: return UnsupportedOperationError when subscribing to terminal tasks (#784) Per A2A spec, attempting to subscribe to a task in a terminal state (completed, failed, canceled, rejected) must return UnsupportedOperationError. The issue had two parts: 1. DefaultRequestHandler checked terminal state AFTER queue operations began, causing errors to be delivered via SSE stream instead of immediately. 2. For streaming endpoints (subscribeToTask), immediate errors must be wrapped in SSE format so the client's SSE parser can process them and deliver to the error handler callback. Previously they were sent as plain JSON/HTTP responses which the SSE parser couldn't handle. Changes: - Move terminal state validation BEFORE queue operations in DefaultRequestHandler - Wrap all immediate errors in SSE format for JSON-RPC routing layer - Wrap all immediate errors in SSE format for REST transport - Add integration test to verify fix across all three transports Applied to HTTP+JSON, JSON-RPC, and gRPC transports. Fixes #767 --------- Co-authored-by: Claude Sonnet 4.5 --- .../server/apps/quarkus/A2AServerRoutes.java | 22 ++++--- .../DefaultRequestHandler.java | 15 +++-- .../apps/common/AbstractA2AServerTest.java | 60 +++++++++++++++++++ .../jsonrpc/handler/JSONRPCHandler.java | 4 ++ .../jsonrpc/handler/JSONRPCHandlerTest.java | 39 ++---------- 5 files changed, 95 insertions(+), 45 deletions(-) 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 b3d51ea4a..2e63d0982 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 @@ -439,15 +439,21 @@ private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest */ 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) { - publisher = jsonRpcHandler.onSubscribeToTask(req, context); - } else { - return Multi.createFrom().item(generateErrorResponse(request, new UnsupportedOperationError())); + try { + Flow.Publisher> publisher; + if (request instanceof SendStreamingMessageRequest req) { + publisher = jsonRpcHandler.onMessageSendStream(req, context); + } else if (request instanceof SubscribeToTaskRequest req) { + publisher = jsonRpcHandler.onSubscribeToTask(req, context); + } else { + return Multi.createFrom().item(generateErrorResponse(request, new UnsupportedOperationError())); + } + return Multi.createFrom().publisher(publisher); + } catch (A2AError error) { + // For streaming endpoints, wrap immediate errors (like TaskNotFoundError, + // UnsupportedOperationError) in error response and send as first SSE event + return Multi.createFrom().item(generateErrorResponse(request, error)); } - return Multi.createFrom().publisher(publisher); } /** 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 d67301023..bd78b6159 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 @@ -832,16 +832,23 @@ public Flow.Publisher onSubscribeToTask(TaskIdParams params, throw new TaskNotFoundError(); } + // Per A2A spec: subscription to tasks in terminal state (completed, failed, canceled, + // rejected) MUST return UnsupportedOperationError. + // Check BEFORE any queue operations to ensure immediate error response. + if (task.status().state().isFinal()) { + throw new UnsupportedOperationError( + null, + String.format("Cannot subscribe to task %s - task is in terminal state: %s", + task.id(), task.status().state()), + null); + } + TaskManager taskManager = new TaskManager(task.id(), task.contextId(), taskStore, null); ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor, eventConsumerExecutor); EventQueue queue = queueManager.tap(task.id()); LOGGER.debug("onSubscribeToTask - tapped queue: {}", queue != null ? System.identityHashCode(queue) : "null"); if (queue == null) { - // If task is in final state, queue legitimately doesn't exist anymore - if (task.status().state().isFinal()) { - throw new TaskNotFoundError(); - } // For non-final tasks, recreate the queue so client can receive future events // (Note: historical events from before queue closed are not available) LOGGER.debug("Queue not found for active task {}, creating new queue for future events", task.id()); 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 3b7cbb8c2..8f44d045b 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 @@ -1130,6 +1130,66 @@ public void testSubscribeNoExistingTaskError() throws Exception { } } + @Test + public void testSubscribeToTerminalTaskError() throws Exception { + // Create a task in terminal state (COMPLETED) + Task completedTask = Task.builder() + .id("terminal-task-test") + .contextId("session-xyz") + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) + .build(); + saveTaskInTaskStore(completedTask); + + try { + CountDownLatch errorLatch = new CountDownLatch(1); + AtomicReference errorRef = new AtomicReference<>(); + + // Create error handler to capture the UnsupportedOperationError + Consumer errorHandler = error -> { + if (error == null) { + // Stream completed successfully - ignore, we're waiting for an error + return; + } + if (!isStreamClosedError(error)) { + errorRef.set(error); + } + errorLatch.countDown(); + }; + + getClient().subscribeToTask(new TaskIdParams(completedTask.id()), List.of(), errorHandler); + + // Wait for error to be captured + boolean errorReceived = errorLatch.await(10, TimeUnit.SECONDS); + + if (errorReceived) { + // Error came via error handler + Throwable error = errorRef.get(); + assertNotNull(error, "Should receive an error when subscribing to terminal task"); + + // Per spec STREAM-SUB-003: should return UnsupportedOperationError for terminal tasks + if (error instanceof A2AClientException) { + assertInstanceOf(UnsupportedOperationError.class, ((A2AClientException) error).getCause(), + "Error should be UnsupportedOperationError for terminal task"); + } else { + // Check if it's directly an UnsupportedOperationError or walk the cause chain + Throwable cause = error; + boolean foundUnsupportedOperation = false; + while (cause != null && !foundUnsupportedOperation) { + if (cause instanceof UnsupportedOperationError) { + foundUnsupportedOperation = true; + } + cause = cause.getCause(); + } + assertTrue(foundUnsupportedOperation, "Expected UnsupportedOperationError in error chain"); + } + } else { + fail("Expected UnsupportedOperationError when subscribing to terminal task"); + } + } finally { + deleteTaskInTaskStore(completedTask.id()); + } + } + /** * Regression test for race condition where MainQueue closed when first ChildQueue closed, * preventing resubscription. With reference counting, MainQueue stays alive while any 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 ec419f465..be670e6df 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 @@ -388,7 +388,11 @@ 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 (TaskNotFoundError | UnsupportedOperationError e) { + // Re-throw initial validation errors for routing layer to wrap in SSE format + throw e; } catch (A2AError e) { + // Other A2AError types - wrap inline as part of the stream return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), e)); } catch (Throwable throwable) { return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), new InternalError(throwable.getMessage()))); 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 8bb841ffc..55b7aad91 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 @@ -985,41 +985,14 @@ public void testOnSubscribeNoExistingTaskError() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); - Flow.Publisher response = handler.onSubscribeToTask(request, callContext); - - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - response.subscribe(new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - } - @Override - public void onComplete() { - subscription.cancel(); - } - }); + // Per spec: TaskNotFoundError should be thrown immediately for non-existent tasks + // The routing layer will catch this and convert to JSON-RPC error response + TaskNotFoundError thrown = Assertions.assertThrows( + TaskNotFoundError.class, + () -> handler.onSubscribeToTask(request, callContext)); - assertEquals(1, results.size()); - assertNull(results.get(0).getResult()); - assertInstanceOf(TaskNotFoundError.class, results.get(0).getError()); + Assertions.assertNotNull(thrown); } @Test From 6c76a931ed6d7c323a0723843609902e555329ba Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Fri, 10 Apr 2026 09:54:21 +0200 Subject: [PATCH 104/192] fix: HTTP+JSON transport returns 501 instead of 400 for UnsupportedOperationError. (#787) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returning the proper status code. Fixes #765 🦕 Signed-off-by: Emmanuel Hugonnet --- .../transport/rest/handler/RestHandler.java | 35 +------------------ 1 file changed, 1 insertion(+), 34 deletions(-) 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 ea16f3aa4..abb4adbb2 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 @@ -42,32 +42,26 @@ import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.ExtendedAgentCardNotConfiguredError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; -import io.a2a.spec.ExtensionSupportRequiredError; import io.a2a.spec.GetTaskPushNotificationConfigParams; 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.ListTaskPushNotificationConfigsParams; import io.a2a.spec.ListTaskPushNotificationConfigsResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MethodNotFoundError; import io.a2a.spec.PushNotificationNotSupportedError; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotCancelableError; import io.a2a.spec.TaskNotFoundError; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TaskState; import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; import mutiny.zero.ZeroPublisher; import org.jspecify.annotations.Nullable; @@ -763,34 +757,7 @@ private static int mapErrorToHttpStatus(A2AError error) { if (errorCode != null) { return errorCode.httpCode(); } - if (error instanceof InvalidParamsError) { - return 422; - } - if (error instanceof MethodNotFoundError || error instanceof TaskNotFoundError) { - return 404; - } - if (error instanceof TaskNotCancelableError) { - return 409; - } - if (error instanceof UnsupportedOperationError) { - return 501; - } - if (error instanceof ContentTypeNotSupportedError) { - return 415; - } - if (error instanceof InvalidAgentResponseError) { - return 502; - } - if (error instanceof ExtendedAgentCardNotConfiguredError - || error instanceof ExtensionSupportRequiredError - || error instanceof VersionNotSupportedError - || error instanceof PushNotificationNotSupportedError) { - return 400; - } - if (error instanceof InternalError) { - return 500; - } - return 500; + return A2AErrorCodes.INTERNAL.httpCode(); } /** From 5ae111febe8d292e880b32030d4b48252dfdae31 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 10 Apr 2026 10:57:28 +0200 Subject: [PATCH 105/192] feat!: Rename root package to org.a2aproject.sdk (#786) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #757 🦕 --- .agents/skills/fix-tck-issue/SKILL.md | 18 +- .agents/skills/update-a2a-proto/SKILL.md | 4 +- .../workflows/cloud-deployment-example.yml | 2 +- AGENTS.md | 4 +- CONTRIBUTING_INTEGRATIONS.md | 2 +- README.md | 50 +- boms/README.md | 6 +- boms/extras/src/it/extras-usage-test/pom.xml | 2 +- .../sdk}/test/ExtrasBomVerifier.java | 4 +- .../src/it/reference-usage-test/pom.xml | 2 +- .../sdk}/test/ReferenceBomVerifier.java | 4 +- boms/sdk/src/it/sdk-usage-test/pom.xml | 2 +- .../a2aproject/sdk}/test/SdkBomVerifier.java | 4 +- .../sdk}/bom/test/DynamicBomVerifier.java | 14 +- .../sdk/bom/test}/package-info.java | 2 +- .../{io/a2a => org/a2aproject/sdk}/A2A.java | 48 +- .../sdk}/client/AbstractClient.java | 36 +- .../a2aproject/sdk}/client/Client.java | 70 +-- .../a2aproject/sdk}/client/ClientBuilder.java | 24 +- .../a2aproject/sdk}/client/ClientEvent.java | 2 +- .../sdk}/client/ClientTaskManager.java | 22 +- .../a2aproject/sdk}/client/MessageEvent.java | 8 +- .../a2aproject/sdk}/client/TaskEvent.java | 10 +- .../sdk}/client/TaskUpdateEvent.java | 26 +- .../sdk}/client/config/ClientConfig.java | 22 +- .../sdk/client/config}/package-info.java | 2 +- .../a2aproject/sdk/client}/package-info.java | 2 +- .../a2a => org/a2aproject/sdk}/A2ATest.java | 8 +- .../AuthenticationAuthorizationTest.java | 40 +- .../sdk}/client/ClientBuilderTest.java | 28 +- .../sdk}/client/ClientTaskManagerTest.java | 22 +- .../transport/grpc/EventStreamObserver.java | 8 +- .../transport/grpc/GrpcErrorMapper.java | 38 +- .../client/transport/grpc/GrpcTransport.java | 124 ++--- .../transport/grpc/GrpcTransportConfig.java | 8 +- .../grpc/GrpcTransportConfigBuilder.java | 8 +- .../transport/grpc/GrpcTransportProvider.java | 12 +- .../client/transport/grpc/package-info.java | 2 +- ...ient.transport.spi.ClientTransportProvider | 1 - ...ient.transport.spi.ClientTransportProvider | 1 + .../transport/grpc/GrpcErrorMapperTest.java | 18 +- .../transport/jsonrpc/sse/package-info.java | 5 - .../transport/jsonrpc/JSONRPCTransport.java | 112 ++--- .../jsonrpc/JSONRPCTransportConfig.java | 8 +- .../JSONRPCTransportConfigBuilder.java | 10 +- .../jsonrpc/JSONRPCTransportProvider.java | 14 +- .../transport/jsonrpc/package-info.java | 5 + .../jsonrpc/sse/SSEEventListener.java | 16 +- .../transport/jsonrpc/sse/package-info.java | 5 + ...ient.transport.spi.ClientTransportProvider | 1 - ...ient.transport.spi.ClientTransportProvider | 1 + .../JSONRPCTransportStreamingTest.java | 30 +- .../jsonrpc/JSONRPCTransportTest.java | 108 ++-- .../transport/jsonrpc/JsonMessages.java | 2 +- .../jsonrpc/JsonStreamingMessages.java | 2 +- .../jsonrpc/sse/SSEEventListenerTest.java | 24 +- .../transport/rest/sse/package-info.java | 5 - .../transport/rest/RestErrorMapper.java | 68 +-- .../client/transport/rest/RestTransport.java | 126 ++--- .../transport/rest/RestTransportConfig.java | 8 +- .../rest/RestTransportConfigBuilder.java | 10 +- .../transport/rest/RestTransportProvider.java | 14 +- .../client/transport/rest/package-info.java | 5 + .../transport/rest/sse/SSEEventListener.java | 14 +- .../transport/rest/sse/package-info.java | 5 + ...ient.transport.spi.ClientTransportProvider | 1 - ...ient.transport.spi.ClientTransportProvider | 1 + .../transport/rest/JsonRestMessages.java | 2 +- .../transport/rest/RestTransportTest.java | 104 ++-- .../rest/sse/SSEEventListenerTest.java | 14 +- .../spi/interceptors/auth/package-info.java | 5 - .../spi/interceptors/package-info.java | 5 - .../transport/spi/sse/package-info.java | 5 - .../client/transport/spi/ClientTransport.java | 38 +- .../transport/spi/ClientTransportConfig.java | 6 +- .../spi/ClientTransportConfigBuilder.java | 8 +- .../spi/ClientTransportProvider.java | 10 +- .../transport/spi/ClientTransportWrapper.java | 4 +- .../spi/interceptors/ClientCallContext.java | 2 +- .../interceptors/ClientCallInterceptor.java | 4 +- .../spi/interceptors/PayloadAndHeaders.java | 2 +- .../interceptors/auth/AuthInterceptor.java | 22 +- .../interceptors/auth/CredentialService.java | 4 +- .../InMemoryContextCredentialService.java | 4 +- .../spi/interceptors/auth/package-info.java | 5 + .../spi/interceptors/package-info.java | 5 + .../client/transport/spi/package-info.java | 5 + .../spi/sse/AbstractSSEEventListener.java | 10 +- .../transport/spi/sse/package-info.java | 5 + .../auth/AuthInterceptorTest.java | 28 +- .../spi/sse/SSEEventListenerTest.java | 16 +- .../main/java/io/a2a/util/package-info.java | 5 - .../sdk}/common/A2AErrorMessages.java | 2 +- .../a2aproject/sdk}/common/A2AHeaders.java | 2 +- .../a2aproject/sdk}/common/MediaType.java | 2 +- .../a2aproject/sdk/common}/package-info.java | 2 +- .../a2aproject/sdk}/util/Assert.java | 2 +- .../a2aproject/sdk}/util/NotNull.java | 2 +- .../a2aproject/sdk/util}/package-info.java | 2 +- examples/cloud-deployment/README.md | 6 +- examples/cloud-deployment/scripts/deploy.sh | 2 +- examples/cloud-deployment/scripts/verify.sh | 2 +- .../cloud/CloudAgentCardProducer.java | 12 +- .../cloud/CloudAgentExecutorProducer.java | 18 +- .../src/main/resources/application.properties | 12 +- .../examples/cloud/A2ACloudExampleClient.java | 36 +- examples/helloworld/client/README.md | 18 +- examples/helloworld/client/pom.xml | 4 +- .../examples/helloworld/HelloWorldClient.java | 44 +- .../examples/helloworld/HelloWorldRunner.java | 2 +- .../sdk}/examples/helloworld/INSTALL_JBANG.md | 0 .../helloworld/AgentCardProducer.java | 14 +- .../helloworld/AgentExecutorProducer.java | 12 +- .../common/events/TaskFinalizedEvent.java | 4 +- extras/http-client-vertx/README.md | 16 +- .../sdk}/client/http/VertxA2AHttpClient.java | 4 +- .../http/VertxA2AHttpClientProvider.java | 4 +- .../io.a2a.client.http.A2AHttpClientProvider | 1 - ...ject.sdk.client.http.A2AHttpClientProvider | 1 + .../http/VertxA2AHttpClientFactoryTest.java | 2 +- .../VertxA2AHttpClientIntegrationTest.java | 4 +- .../http/VertxA2AHttpClientSSETest.java | 4 +- .../client/http/VertxA2AHttpClientTest.java | 2 +- extras/opentelemetry/README.md | 2 +- .../client/propagation/package-info.java | 5 - ...penTelemetryClientPropagatorTransport.java | 42 +- ...metryClientPropagatorTransportWrapper.java | 12 +- .../client/propagation/package-info.java | 5 + ...lient.transport.spi.ClientTransportWrapper | 1 - ...lient.transport.spi.ClientTransportWrapper | 1 + .../opentelemetry/client/package-info.java | 5 - .../client/OpenTelemetryClientTransport.java | 66 +-- .../OpenTelemetryClientTransportWrapper.java | 10 +- .../opentelemetry/client/package-info.java | 5 + ...lient.transport.spi.ClientTransportWrapper | 1 - ...lient.transport.spi.ClientTransportWrapper | 1 + .../OpenTelemetryClientTransportTest.java | 58 +-- .../opentelemetry/A2AObservabilityNames.java | 6 +- .../extras/opentelemetry/package-info.java | 2 +- .../opentelemetry/it/A2ATestRoutes.java | 10 +- .../opentelemetry/it/SimpleAgentExecutor.java | 14 +- .../it/TestAgentCardProducer.java | 12 +- .../opentelemetry/it/TestUtilsBean.java | 10 +- .../src/main/resources/META-INF/beans.xml | 2 +- .../src/main/resources/application.properties | 2 +- .../extras/opentelemetry/it/BaseTest.java | 2 +- .../it/OpenTelemetryA2ABaseTest.java | 18 +- .../opentelemetry/it/OpenTelemetryA2AIT.java | 2 +- .../it/OpenTelemetryA2ATest.java | 2 +- .../opentelemetry/it/OpenTelemetryTest.java | 2 +- .../src/test/resources/application.properties | 2 +- .../extras/opentelemetry/package-info.java | 5 - .../AsyncManagedExecutorProducer.java | 4 +- .../OpenTelemetryRequestHandlerDecorator.java | 70 +-- .../extras/opentelemetry/package-info.java | 5 + .../src/main/resources/META-INF/beans.xml | 2 +- .../AsyncManagedExecutorProducerTest.java | 4 +- ...nTelemetryRequestHandlerDecoratorTest.java | 20 +- .../README.md | 2 +- ...paDatabasePushNotificationConfigStore.java | 16 +- .../jpa/JpaPushNotificationConfig.java | 8 +- .../database/jpa/TaskConfigId.java | 2 +- ...otificationConfigStoreIntegrationTest.java | 48 +- ...ationConfigStoreTestAgentCardProducer.java | 12 +- ...ificationConfigStoreTestAgentExecutor.java | 20 +- .../JpaPushNotificationConfigStoreTest.java | 26 +- .../jpa/MockPushNotificationSender.java | 8 +- .../test/resources/META-INF/persistence.xml | 2 +- extras/queue-manager-replicated/README.md | 14 +- .../replicated/core/ReplicationStrategy.java | 7 - .../core/ReplicatedEventQueueItem.java | 16 +- .../core/ReplicatedQueueManager.java | 26 +- .../replicated/core/ReplicationStrategy.java | 7 + .../core/EventSerializationTest.java | 50 +- .../core/ReplicatedQueueManagerTest.java | 50 +- .../server/events/EventQueueTestHelper.java | 4 +- .../sdk}/server/events/EventQueueUtil.java | 2 +- .../ReactiveMessagingReplicationStrategy.java | 10 +- ...ctiveMessagingReplicationStrategyTest.java | 14 +- ...tanceReplicationApp1AgentCardProducer.java | 8 +- ...eReplicationApp1AgentExecutorProducer.java | 6 +- .../src/main/resources/application.properties | 14 +- ...tanceReplicationApp2AgentCardProducer.java | 8 +- ...eReplicationApp2AgentExecutorProducer.java | 6 +- .../src/main/resources/application.properties | 14 +- .../MultiInstanceReplicationAgentCards.java | 12 +- ...MultiInstanceReplicationAgentExecutor.java | 14 +- .../MultiInstanceReplicationTest.java | 50 +- .../KafkaReplicationIntegrationTest.java | 50 +- .../tests/ReplicatedQueueManagerTest.java | 8 +- .../ReplicationTestAgentCardProducer.java | 12 +- .../tests/ReplicationTestAgentExecutor.java | 18 +- .../tests/TestKafkaEventConsumer.java | 6 +- .../src/test/resources/application.properties | 10 +- extras/task-store-database-jpa/README.md | 2 +- .../database/jpa/JpaDatabaseTaskStore.java | 28 +- .../taskstore/database/jpa/JpaTask.java | 10 +- .../JpaDatabaseTaskStoreIntegrationTest.java | 34 +- .../jpa/JpaDatabaseTaskStoreTest.java | 24 +- ...atabaseTaskStoreTestAgentCardProducer.java | 12 +- ...JpaDatabaseTaskStoreTestAgentExecutor.java | 18 +- .../test/resources/META-INF/persistence.xml | 2 +- .../sdk}/client/http/A2ACardResolver.java | 24 +- .../sdk}/client/http/A2AHttpClient.java | 2 +- .../client/http/A2AHttpClientFactory.java | 4 +- .../client/http/A2AHttpClientProvider.java | 4 +- .../sdk}/client/http/A2AHttpResponse.java | 2 +- .../sdk}/client/http/JdkA2AHttpClient.java | 6 +- .../client/http/JdkA2AHttpClientProvider.java | 2 +- .../sdk}/client/http/package-info.java | 18 +- .../io.a2a.client.http.A2AHttpClientProvider | 1 - ...ject.sdk.client.http.A2AHttpClientProvider | 1 + .../sdk}/client/http/A2ACardResolverTest.java | 16 +- .../client/http/A2AHttpClientFactoryTest.java | 2 +- .../A2AHttpClientFactoryUsageExample.java | 2 +- .../http/A2AHttpClientProviderTest.java | 2 +- .../client/http/JdkA2AHttpClientTest.java | 2 +- .../sdk}/client/http/JsonMessages.java | 2 +- integrations/microprofile-config/README.md | 8 +- .../MicroProfileConfigProvider.java | 6 +- .../MicroProfileConfigProviderTest.java | 4 +- .../src/test/resources/application.properties | 2 +- .../common/json/IdJsonMappingException.java | 2 +- .../InvalidParamsJsonMappingException.java | 2 +- .../common/json/JsonMappingException.java | 2 +- .../common/json/JsonProcessingException.java | 2 +- .../sdk}/jsonrpc/common/json/JsonUtil.java | 78 +-- .../MethodNotFoundJsonMappingException.java | 4 +- .../jsonrpc/common/json/package-info.java | 2 +- .../common/wrappers/A2AErrorResponse.java | 6 +- .../jsonrpc/common/wrappers/A2AMessage.java | 2 +- .../jsonrpc/common/wrappers/A2ARequest.java | 6 +- .../jsonrpc/common/wrappers/A2AResponse.java | 8 +- .../common/wrappers/CancelTaskRequest.java | 12 +- .../common/wrappers/CancelTaskResponse.java | 14 +- ...eateTaskPushNotificationConfigRequest.java | 6 +- ...ateTaskPushNotificationConfigResponse.java | 8 +- ...leteTaskPushNotificationConfigRequest.java | 6 +- ...eteTaskPushNotificationConfigResponse.java | 4 +- .../wrappers/GetExtendedAgentCardRequest.java | 10 +- .../GetExtendedAgentCardResponse.java | 8 +- .../GetTaskPushNotificationConfigRequest.java | 8 +- ...GetTaskPushNotificationConfigResponse.java | 6 +- .../common/wrappers/GetTaskRequest.java | 8 +- .../common/wrappers/GetTaskResponse.java | 8 +- ...istTaskPushNotificationConfigsRequest.java | 8 +- ...stTaskPushNotificationConfigsResponse.java | 8 +- .../common/wrappers/ListTasksRequest.java | 6 +- .../common/wrappers/ListTasksResponse.java | 4 +- .../common/wrappers/ListTasksResult.java | 6 +- .../wrappers/NonStreamingJSONRPCRequest.java | 2 +- .../common/wrappers/SendMessageRequest.java | 8 +- .../common/wrappers/SendMessageResponse.java | 6 +- .../wrappers/SendStreamingMessageRequest.java | 8 +- .../SendStreamingMessageResponse.java | 14 +- .../wrappers/StreamingJSONRPCRequest.java | 4 +- .../wrappers/SubscribeToTaskRequest.java | 8 +- .../jsonrpc/common/wrappers/package-info.java | 6 +- .../json/A2AErrorSerializationTest.java | 28 +- .../jsonrpc/common/json/JsonUtilTest.java | 2 +- .../SecurityRequirementSerializationTest.java | 4 +- .../json/SecuritySchemeSerializationTest.java | 18 +- .../StreamingEventKindSerializationTest.java | 20 +- .../common/json/TaskSerializationTest.java | 26 +- .../common/quarkus/DefaultProducers.java | 8 +- .../quarkus/A2AExtensionsInterceptor.java | 26 +- .../grpc/quarkus/QuarkusGrpcHandler.java | 18 +- .../quarkus/QuarkusGrpcTransportMetadata.java | 10 +- .../server/grpc/quarkus/package-info.java | 32 +- .../services/io.a2a.server.TransportMetadata | 1 - ...rg.a2aproject.sdk.server.TransportMetadata | 1 + .../server/grpc/quarkus/A2ATestResource.java | 16 +- .../grpc/quarkus/QuarkusA2AGrpcTest.java | 12 +- .../server/apps/quarkus/A2AServerRoutes.java | 138 ++--- .../apps/quarkus/CallContextFactory.java | 8 +- .../QuarkusJSONRPCTransportMetadata.java | 10 +- .../server/apps/quarkus/package-info.java | 16 +- .../services/io.a2a.server.TransportMetadata | 1 - ...rg.a2aproject.sdk.server.TransportMetadata | 1 + .../apps/quarkus/A2AServerRoutesTest.java | 88 ++-- .../server/apps/quarkus/A2ATestRoutes.java | 14 +- .../quarkus/QuarkusA2AJSONRPCJdkTest.java | 10 +- .../apps/quarkus/QuarkusA2AJSONRPCTest.java | 8 +- .../quarkus/QuarkusA2AJSONRPCVertxTest.java | 10 +- .../src/test/resources/application.properties | 8 +- .../server/rest/quarkus/A2AServerRoutes.java | 70 +-- .../rest/quarkus/CallContextFactory.java | 8 +- .../quarkus/QuarkusRestTransportMetadata.java | 6 +- .../server/rest/quarkus/package-info.java | 12 +- .../services/io.a2a.server.TransportMetadata | 1 - ...rg.a2aproject.sdk.server.TransportMetadata | 1 + .../rest/quarkus/A2AServerRoutesTest.java | 34 +- .../server/rest/quarkus/A2ATestRoutes.java | 14 +- .../rest/quarkus/QuarkusA2ARestJdkTest.java | 10 +- .../rest/quarkus/QuarkusA2ARestTest.java | 8 +- .../rest/quarkus/QuarkusA2ARestVertxTest.java | 10 +- .../src/test/resources/application.properties | 2 +- .../server/agentexecution/package-info.java | 4 - .../java/io/a2a/server/auth/package-info.java | 4 - .../io/a2a/server/config/package-info.java | 4 - .../io/a2a/server/events/package-info.java | 4 - .../a2a/server/extensions/package-info.java | 4 - .../main/java/io/a2a/server/package-info.java | 4 - .../server/requesthandlers/package-info.java | 4 - .../io/a2a/server/tasks/package-info.java | 4 - .../a2a/server/util/async/package-info.java | 4 - .../java/io/a2a/server/util/package-info.java | 4 - .../sdk}/server/AgentCardCacheMetadata.java | 10 +- .../sdk}/server/AgentCardValidator.java | 16 +- .../sdk}/server/ExtendedAgentCard.java | 2 +- .../sdk}/server/JSONRPCException.java | 4 +- .../sdk}/server/PublicAgentCard.java | 2 +- .../sdk}/server/ServerCallContext.java | 8 +- .../sdk}/server/TransportMetadata.java | 2 +- .../server/agentexecution/AgentExecutor.java | 22 +- .../server/agentexecution/RequestContext.java | 18 +- .../SimpleRequestContextBuilder.java | 6 +- .../server/agentexecution/package-info.java | 4 + .../sdk}/server/auth/UnauthenticatedUser.java | 2 +- .../a2aproject/sdk}/server/auth/User.java | 2 +- .../sdk/server/auth/package-info.java | 4 + .../sdk}/server/config/A2AConfigProvider.java | 2 +- .../config/DefaultValuesConfigProvider.java | 2 +- .../sdk/server/config/package-info.java | 4 + .../sdk}/server/events/EnhancedRunnable.java | 2 +- .../sdk}/server/events/EventConsumer.java | 16 +- .../sdk}/server/events/EventEnqueueHook.java | 2 +- .../sdk}/server/events/EventQueue.java | 12 +- .../events/EventQueueClosedException.java | 2 +- .../sdk}/server/events/EventQueueFactory.java | 2 +- .../sdk}/server/events/EventQueueItem.java | 4 +- .../server/events/InMemoryQueueManager.java | 4 +- .../server/events/LocalEventQueueItem.java | 6 +- .../sdk}/server/events/MainEventBus.java | 2 +- .../server/events/MainEventBusContext.java | 2 +- .../server/events/MainEventBusProcessor.java | 30 +- .../events/MainEventBusProcessorCallback.java | 4 +- .../MainEventBusProcessorInitializer.java | 2 +- .../server/events/NoTaskQueueException.java | 2 +- .../sdk}/server/events/QueueClosedEvent.java | 4 +- .../sdk}/server/events/QueueManager.java | 12 +- .../events/TaskQueueExistsException.java | 2 +- .../sdk/server/events/package-info.java | 4 + .../sdk}/server/extensions/A2AExtensions.java | 10 +- .../sdk/server/extensions/package-info.java | 4 + .../a2aproject/sdk/server}/package-info.java | 3 +- .../DefaultRequestHandler.java | 120 ++--- .../requesthandlers/RequestHandler.java | 34 +- .../server/requesthandlers/package-info.java | 4 + .../sdk}/server/tasks/AgentEmitter.java | 34 +- .../tasks/BasePushNotificationSender.java | 30 +- .../InMemoryPushNotificationConfigStore.java | 10 +- .../sdk}/server/tasks/InMemoryTaskStore.java | 14 +- .../tasks/PushNotificationConfigStore.java | 10 +- .../server/tasks/PushNotificationSender.java | 16 +- .../sdk}/server/tasks/ResultAggregator.java | 34 +- .../sdk}/server/tasks/TaskManager.java | 28 +- .../tasks/TaskPersistenceException.java | 2 +- .../tasks/TaskSerializationException.java | 2 +- .../sdk}/server/tasks/TaskStateProvider.java | 2 +- .../sdk}/server/tasks/TaskStore.java | 20 +- .../sdk}/server/tasks/TaskStoreException.java | 8 +- .../sdk/server/tasks/package-info.java | 4 + .../sdk}/server/util/ArtifactUtils.java | 10 +- .../util/async/AsyncExecutorProducer.java | 4 +- .../sdk}/server/util/async/AsyncUtils.java | 4 +- .../async/EventConsumerExecutorProducer.java | 2 +- .../sdk}/server/util/async/Internal.java | 2 +- .../sdk/server/util/async/package-info.java | 4 + .../sdk/server/util/package-info.java | 4 + .../sdk}/server/util/sse/SseFormatter.java | 46 +- .../sdk}/server/util/sse/package-info.java | 2 +- .../server/version/A2AVersionValidator.java | 10 +- .../sdk}/server/AgentCardValidatorTest.java | 10 +- .../sdk}/server/ServerCallContextTest.java | 4 +- .../agentexecution/RequestContextTest.java | 18 +- .../server/events/EnhancedRunnableTest.java | 2 +- .../sdk}/server/events/EventConsumerTest.java | 32 +- .../sdk}/server/events/EventQueueTest.java | 34 +- .../sdk}/server/events/EventQueueUtil.java | 2 +- .../events/InMemoryQueueManagerTest.java | 8 +- .../MainEventBusProcessorExceptionTest.java | 22 +- .../server/extensions/A2AExtensionsTest.java | 10 +- .../AbstractA2ARequestHandlerTest.java | 60 +-- .../DefaultRequestHandlerTest.java | 60 +-- .../tasks/AbstractTaskStoreExceptionTest.java | 2 +- .../tasks/AgentEmitterConcurrencyTest.java | 8 +- .../sdk}/server/tasks/AgentEmitterTest.java | 32 +- ...MemoryPushNotificationConfigStoreTest.java | 24 +- .../server/tasks/InMemoryTaskStoreTest.java | 0 .../server/tasks/MockTaskStateProvider.java | 2 +- .../tasks/PushNotificationSenderTest.java | 36 +- .../server/tasks/ResultAggregatorTest.java | 32 +- .../sdk}/server/tasks/TaskManagerTest.java | 22 +- .../tasks/TaskPersistenceExceptionTest.java | 2 +- .../tasks/TaskSerializationExceptionTest.java | 2 +- .../server/tasks/TaskStoreExceptionTest.java | 2 +- .../sdk}/server/util/ArtifactUtilsTest.java | 10 +- .../server/util/async/AsyncUtilsTest.java | 10 +- .../version/A2AVersionValidatorTest.java | 14 +- .../a2a/grpc/mapper/AgentProviderMapper.java | 18 - .../AuthorizationCodeOAuthFlowMapper.java | 19 - .../ClientCredentialsOAuthFlowMapper.java | 18 - .../io/a2a/grpc/mapper/TaskStateMapper.java | 68 --- .../java/io/a2a/grpc/utils/ProtoUtils.java | 340 ------------- .../java/io/a2a/grpc/utils/package-info.java | 5 - .../a2a => org/a2aproject/sdk}/grpc/A2A.java | 7 +- .../a2aproject/sdk}/grpc/A2AServiceGrpc.java | 470 +++++++++--------- .../sdk}/grpc/APIKeySecurityScheme.java | 80 +-- .../grpc/APIKeySecuritySchemeOrBuilder.java | 2 +- .../sdk}/grpc/AgentCapabilities.java | 140 +++--- .../sdk}/grpc/AgentCapabilitiesOrBuilder.java | 10 +- .../a2aproject/sdk}/grpc/AgentCard.java | 470 +++++++++--------- .../sdk}/grpc/AgentCardOrBuilder.java | 52 +- .../sdk}/grpc/AgentCardSignature.java | 80 +-- .../grpc/AgentCardSignatureOrBuilder.java | 2 +- .../a2aproject/sdk}/grpc/AgentExtension.java | 80 +-- .../sdk}/grpc/AgentExtensionOrBuilder.java | 2 +- .../a2aproject/sdk}/grpc/AgentInterface.java | 80 +-- .../sdk}/grpc/AgentInterfaceOrBuilder.java | 2 +- .../a2aproject/sdk}/grpc/AgentProvider.java | 80 +-- .../sdk}/grpc/AgentProviderOrBuilder.java | 2 +- .../a2aproject/sdk}/grpc/AgentSkill.java | 140 +++--- .../sdk}/grpc/AgentSkillOrBuilder.java | 10 +- .../a2aproject/sdk}/grpc/Artifact.java | 140 +++--- .../sdk}/grpc/ArtifactOrBuilder.java | 10 +- .../sdk}/grpc/AuthenticationInfo.java | 80 +-- .../grpc/AuthenticationInfoOrBuilder.java | 2 +- .../sdk}/grpc/AuthorizationCodeOAuthFlow.java | 82 +-- .../AuthorizationCodeOAuthFlowOrBuilder.java | 2 +- .../sdk}/grpc/CancelTaskRequest.java | 80 +-- .../sdk}/grpc/CancelTaskRequestOrBuilder.java | 2 +- .../sdk}/grpc/ClientCredentialsOAuthFlow.java | 82 +-- .../ClientCredentialsOAuthFlowOrBuilder.java | 2 +- ...leteTaskPushNotificationConfigRequest.java | 80 +-- ...ushNotificationConfigRequestOrBuilder.java | 2 +- .../sdk}/grpc/DeviceCodeOAuthFlow.java | 82 +-- .../grpc/DeviceCodeOAuthFlowOrBuilder.java | 2 +- .../grpc/GetExtendedAgentCardRequest.java | 80 +-- .../GetExtendedAgentCardRequestOrBuilder.java | 2 +- .../GetTaskPushNotificationConfigRequest.java | 80 +-- ...ushNotificationConfigRequestOrBuilder.java | 2 +- .../a2aproject/sdk}/grpc/GetTaskRequest.java | 80 +-- .../sdk}/grpc/GetTaskRequestOrBuilder.java | 2 +- .../sdk}/grpc/HTTPAuthSecurityScheme.java | 80 +-- .../grpc/HTTPAuthSecuritySchemeOrBuilder.java | 2 +- .../sdk}/grpc/ImplicitOAuthFlow.java | 82 +-- .../sdk}/grpc/ImplicitOAuthFlowOrBuilder.java | 2 +- ...istTaskPushNotificationConfigsRequest.java | 80 +-- ...shNotificationConfigsRequestOrBuilder.java | 2 +- ...stTaskPushNotificationConfigsResponse.java | 140 +++--- ...hNotificationConfigsResponseOrBuilder.java | 10 +- .../sdk}/grpc/ListTasksRequest.java | 98 ++-- .../sdk}/grpc/ListTasksRequestOrBuilder.java | 4 +- .../sdk}/grpc/ListTasksResponse.java | 140 +++--- .../sdk}/grpc/ListTasksResponseOrBuilder.java | 10 +- .../a2aproject/sdk}/grpc/Message.java | 158 +++--- .../sdk}/grpc/MessageOrBuilder.java | 12 +- .../sdk}/grpc/MutualTlsSecurityScheme.java | 80 +-- .../MutualTlsSecuritySchemeOrBuilder.java | 2 +- .../sdk}/grpc/OAuth2SecurityScheme.java | 116 ++--- .../grpc/OAuth2SecuritySchemeOrBuilder.java | 6 +- .../a2aproject/sdk}/grpc/OAuthFlows.java | 342 ++++++------- .../sdk}/grpc/OAuthFlowsOrBuilder.java | 24 +- .../grpc/OpenIdConnectSecurityScheme.java | 80 +-- .../OpenIdConnectSecuritySchemeOrBuilder.java | 2 +- .../a2a => org/a2aproject/sdk}/grpc/Part.java | 82 +-- .../a2aproject/sdk}/grpc/PartOrBuilder.java | 4 +- .../sdk}/grpc/PasswordOAuthFlow.java | 82 +-- .../sdk}/grpc/PasswordOAuthFlowOrBuilder.java | 2 +- .../a2a => org/a2aproject/sdk}/grpc/Role.java | 4 +- .../sdk}/grpc/SecurityRequirement.java | 164 +++--- .../grpc/SecurityRequirementOrBuilder.java | 12 +- .../a2aproject/sdk}/grpc/SecurityScheme.java | 342 ++++++------- .../sdk}/grpc/SecuritySchemeOrBuilder.java | 24 +- .../sdk}/grpc/SendMessageConfiguration.java | 116 ++--- .../SendMessageConfigurationOrBuilder.java | 6 +- .../sdk}/grpc/SendMessageRequest.java | 152 +++--- .../grpc/SendMessageRequestOrBuilder.java | 10 +- .../sdk}/grpc/SendMessageResponse.java | 186 +++---- .../grpc/SendMessageResponseOrBuilder.java | 12 +- .../a2aproject/sdk}/grpc/StreamResponse.java | 290 +++++------ .../sdk}/grpc/StreamResponseOrBuilder.java | 20 +- .../a2aproject/sdk}/grpc/StringList.java | 80 +-- .../sdk}/grpc/StringListOrBuilder.java | 2 +- .../sdk}/grpc/SubscribeToTaskRequest.java | 80 +-- .../grpc/SubscribeToTaskRequestOrBuilder.java | 2 +- .../a2a => org/a2aproject/sdk}/grpc/Task.java | 234 ++++----- .../sdk}/grpc/TaskArtifactUpdateEvent.java | 116 ++--- .../TaskArtifactUpdateEventOrBuilder.java | 6 +- .../a2aproject/sdk}/grpc/TaskOrBuilder.java | 22 +- .../sdk}/grpc/TaskPushNotificationConfig.java | 116 ++--- .../TaskPushNotificationConfigOrBuilder.java | 6 +- .../a2aproject/sdk}/grpc/TaskState.java | 4 +- .../a2aproject/sdk}/grpc/TaskStatus.java | 134 ++--- .../sdk}/grpc/TaskStatusOrBuilder.java | 8 +- .../sdk}/grpc/TaskStatusUpdateEvent.java | 116 ++--- .../grpc/TaskStatusUpdateEventOrBuilder.java | 6 +- .../grpc/mapper/A2ACommonFieldMapper.java | 16 +- .../sdk}/grpc/mapper/A2AMappers.java | 2 +- .../grpc/mapper/A2AProtoMapperConfig.java | 4 +- .../mapper/APIKeySecuritySchemeMapper.java | 14 +- .../grpc/mapper/AgentCapabilitiesMapper.java | 8 +- .../sdk}/grpc/mapper/AgentCardMapper.java | 8 +- .../grpc/mapper/AgentCardSignatureMapper.java | 8 +- .../grpc/mapper/AgentExtensionMapper.java | 8 +- .../grpc/mapper/AgentInterfaceMapper.java | 8 +- .../sdk/grpc/mapper/AgentProviderMapper.java | 18 + .../sdk}/grpc/mapper/AgentSkillMapper.java | 8 +- .../sdk}/grpc/mapper/ArtifactMapper.java | 10 +- .../grpc/mapper/AuthenticationInfoMapper.java | 8 +- .../AuthorizationCodeOAuthFlowMapper.java | 19 + .../ClientCredentialsOAuthFlowMapper.java | 18 + ...askPushNotificationConfigParamsMapper.java | 10 +- ...askPushNotificationConfigParamsMapper.java | 10 +- .../mapper/HTTPAuthSecuritySchemeMapper.java | 10 +- ...skPushNotificationConfigsParamsMapper.java | 10 +- .../grpc/mapper/ListTasksParamsMapper.java | 8 +- .../grpc/mapper/ListTasksResultMapper.java | 10 +- .../sdk}/grpc/mapper/MessageMapper.java | 14 +- .../MessageSendConfigurationMapper.java | 12 +- .../grpc/mapper/MessageSendParamsMapper.java | 10 +- .../mapper/MutualTLSSecuritySchemeMapper.java | 10 +- .../mapper/OAuth2SecuritySchemeMapper.java | 12 +- .../sdk}/grpc/mapper/OAuthFlowsMapper.java | 8 +- .../OpenIdConnectSecuritySchemeMapper.java | 10 +- .../sdk}/grpc/mapper/PartMapper.java | 26 +- .../sdk}/grpc/mapper/ResourceNameParser.java | 2 +- .../sdk}/grpc/mapper/RoleMapper.java | 20 +- .../mapper/SecurityRequirementMapper.java | 22 +- .../grpc/mapper/SecuritySchemeMapper.java | 28 +- .../grpc/mapper/StreamResponseMapper.java | 26 +- .../mapper/SubscribeToTaskRequestMapper.java | 14 +- .../mapper/TaskArtifactUpdateEventMapper.java | 10 +- .../sdk}/grpc/mapper/TaskIdParamsMapper.java | 16 +- .../sdk}/grpc/mapper/TaskMapper.java | 10 +- .../TaskPushNotificationConfigMapper.java | 8 +- .../grpc/mapper/TaskQueryParamsMapper.java | 10 +- .../sdk/grpc/mapper/TaskStateMapper.java | 68 +++ .../sdk}/grpc/mapper/TaskStatusMapper.java | 10 +- .../mapper/TaskStatusUpdateEventMapper.java | 12 +- .../sdk}/grpc/utils/JSONRPCUtils.java | 156 +++--- .../a2aproject/sdk/grpc/utils/ProtoUtils.java | 340 +++++++++++++ .../sdk/grpc/utils}/package-info.java | 2 +- spec-grpc/src/main/proto/a2a.proto | 2 +- .../grpc/mapper/A2ACommonFieldMapperTest.java | 10 +- .../grpc/mapper/StreamResponseMapperTest.java | 80 +-- .../sdk}/grpc/utils/JSONRPCUtilsTest.java | 30 +- .../sdk}/grpc/utils/PartTypeAdapterTest.java | 30 +- .../sdk}/grpc/utils/ToProtoTest.java | 72 +-- .../a2aproject/sdk}/spec/A2AClientError.java | 2 +- .../sdk}/spec/A2AClientException.java | 2 +- .../sdk}/spec/A2AClientHTTPError.java | 4 +- .../sdk}/spec/A2AClientInvalidArgsError.java | 2 +- .../sdk}/spec/A2AClientInvalidStateError.java | 2 +- .../sdk}/spec/A2AClientJSONError.java | 4 +- .../a2aproject/sdk}/spec/A2AError.java | 4 +- .../a2aproject/sdk}/spec/A2AErrorCodes.java | 2 +- .../a2aproject/sdk}/spec/A2AException.java | 2 +- .../a2aproject/sdk}/spec/A2AMethods.java | 2 +- .../sdk}/spec/A2AProtocolError.java | 2 +- .../sdk}/spec/A2AServerException.java | 2 +- .../sdk}/spec/APIKeySecurityScheme.java | 4 +- .../sdk}/spec/AgentCapabilities.java | 2 +- .../a2aproject/sdk}/spec/AgentCard.java | 4 +- .../sdk}/spec/AgentCardSignature.java | 4 +- .../a2aproject/sdk}/spec/AgentExtension.java | 4 +- .../a2aproject/sdk}/spec/AgentInterface.java | 4 +- .../a2aproject/sdk}/spec/AgentProvider.java | 4 +- .../a2aproject/sdk}/spec/AgentSkill.java | 4 +- .../a2aproject/sdk}/spec/Artifact.java | 4 +- .../sdk}/spec/AuthenticationInfo.java | 4 +- .../sdk}/spec/AuthorizationCodeOAuthFlow.java | 4 +- .../sdk}/spec/CancelTaskParams.java | 6 +- .../sdk}/spec/ClientCredentialsOAuthFlow.java | 4 +- .../spec/ContentTypeNotSupportedError.java | 4 +- .../a2aproject/sdk}/spec/DataPart.java | 4 +- ...eleteTaskPushNotificationConfigParams.java | 6 +- .../sdk}/spec/DeviceCodeOAuthFlow.java | 4 +- .../a2aproject/sdk}/spec/Event.java | 2 +- .../a2aproject/sdk}/spec/EventKind.java | 2 +- .../ExtendedAgentCardNotConfiguredError.java | 4 +- .../spec/ExtensionSupportRequiredError.java | 4 +- .../a2aproject/sdk}/spec/FileContent.java | 2 +- .../a2aproject/sdk}/spec/FilePart.java | 4 +- .../a2aproject/sdk}/spec/FileWithBytes.java | 4 +- .../a2aproject/sdk}/spec/FileWithUri.java | 2 +- .../sdk}/spec/GetExtendedAgentCardParams.java | 2 +- .../GetTaskPushNotificationConfigParams.java | 6 +- .../sdk}/spec/HTTPAuthSecurityScheme.java | 4 +- .../a2aproject/sdk}/spec/InternalError.java | 4 +- .../sdk}/spec/InvalidAgentResponseError.java | 4 +- .../sdk}/spec/InvalidParamsError.java | 4 +- .../sdk}/spec/InvalidRequestError.java | 4 +- .../a2aproject/sdk}/spec/JSONParseError.java | 6 +- ...ListTaskPushNotificationConfigsParams.java | 6 +- ...ListTaskPushNotificationConfigsResult.java | 4 +- .../a2aproject/sdk}/spec/ListTasksParams.java | 4 +- .../a2aproject/sdk}/spec/Message.java | 4 +- .../sdk}/spec/MessageSendConfiguration.java | 2 +- .../sdk}/spec/MessageSendParams.java | 4 +- .../sdk}/spec/MethodNotFoundError.java | 4 +- .../sdk}/spec/MutualTLSSecurityScheme.java | 2 +- .../sdk}/spec/OAuth2SecurityScheme.java | 4 +- .../a2aproject/sdk}/spec/OAuthFlows.java | 2 +- .../spec/OpenIdConnectSecurityScheme.java | 4 +- .../a2a => org/a2aproject/sdk}/spec/Part.java | 2 +- .../PushNotificationNotSupportedError.java | 4 +- .../sdk}/spec/SecurityRequirement.java | 4 +- .../a2aproject/sdk}/spec/SecurityScheme.java | 2 +- .../sdk}/spec/StreamingEventKind.java | 2 +- .../a2a => org/a2aproject/sdk}/spec/Task.java | 4 +- .../sdk}/spec/TaskArtifactUpdateEvent.java | 4 +- .../a2aproject/sdk}/spec/TaskIdParams.java | 6 +- .../sdk}/spec/TaskNotCancelableError.java | 4 +- .../sdk}/spec/TaskNotFoundError.java | 4 +- .../sdk}/spec/TaskPushNotificationConfig.java | 4 +- .../a2aproject/sdk}/spec/TaskQueryParams.java | 6 +- .../a2aproject/sdk}/spec/TaskState.java | 2 +- .../a2aproject/sdk}/spec/TaskStatus.java | 4 +- .../sdk}/spec/TaskStatusUpdateEvent.java | 14 +- .../a2aproject/sdk}/spec/TextPart.java | 4 +- .../sdk}/spec/TransportProtocol.java | 2 +- .../sdk}/spec/UnsupportedOperationError.java | 4 +- .../a2aproject/sdk}/spec/UpdateEvent.java | 2 +- .../sdk}/spec/VersionNotSupportedError.java | 4 +- .../a2aproject/sdk}/spec/package-info.java | 2 +- .../a2aproject/sdk}/util/PageToken.java | 4 +- .../a2aproject/sdk}/util/Utils.java | 18 +- .../a2aproject/sdk}/util/package-info.java | 2 +- .../a2aproject/sdk}/spec/DataPartTest.java | 2 +- .../sdk}/spec/FileWithBytesTest.java | 2 +- .../a2aproject/sdk}/util/PageTokenTest.java | 4 +- .../a2aproject/sdk}/util/UtilsTest.java | 4 +- .../sdk}/tck/server/AgentCardProducer.java | 14 +- .../tck/server/AgentExecutorProducer.java | 18 +- .../sdk}/tck/server/package-info.java | 2 +- tck/src/main/resources/application.properties | 8 +- test-utils-docker/README.md | 2 +- .../testutils/docker/DockerAvailability.java | 2 +- .../docker/DockerRequiredExtension.java | 2 +- .../sdk}/testutils/docker/RequiresDocker.java | 2 +- .../apps/common/A2AGsonObjectMapper.java | 6 +- .../apps/common/AbstractA2AServerTest.java | 122 ++--- .../server/apps/common/AgentCardProducer.java | 14 +- .../apps/common/AgentExecutorProducer.java | 48 +- .../common/AgentToAgentClientFactory.java | 34 +- .../server/apps/common/TestHttpClient.java | 12 +- .../server/apps/common/TestUtilsBean.java | 14 +- .../grpc/context/GrpcContextKeys.java | 10 +- .../grpc/handler/CallContextFactory.java | 12 +- .../transport/grpc/handler/GrpcHandler.java | 182 +++---- .../transport/grpc/handler/package-info.java | 6 +- .../grpc/handler/GrpcHandlerTest.java | 84 ++-- .../handler/GrpcTestTransportMetadata.java | 6 +- .../services/io.a2a.server.TransportMetadata | 2 - ...rg.a2aproject.sdk.server.TransportMetadata | 2 + .../jsonrpc/context/JSONRPCContextKeys.java | 6 +- .../jsonrpc/handler/JSONRPCHandler.java | 108 ++-- .../jsonrpc/handler/package-info.java | 4 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 122 ++--- .../handler/JSONRPCTestTransportMetadata.java | 6 +- .../services/io.a2a.server.TransportMetadata | 2 - ...rg.a2aproject.sdk.server.TransportMetadata | 2 + .../rest/context/RestContextKeys.java | 6 +- .../transport/rest/handler/RestHandler.java | 111 ++--- .../transport/rest/handler/package-info.java | 2 +- .../rest/handler/RestHandlerTest.java | 26 +- .../handler/RestTestTransportMetadata.java | 6 +- .../services/io.a2a.server.TransportMetadata | 2 - ...rg.a2aproject.sdk.server.TransportMetadata | 2 + 671 files changed, 7464 insertions(+), 7448 deletions(-) rename boms/extras/src/it/extras-usage-test/src/main/java/{io/a2a => org/a2aproject/sdk}/test/ExtrasBomVerifier.java (94%) rename boms/reference/src/it/reference-usage-test/src/main/java/{io/a2a => org/a2aproject/sdk}/test/ReferenceBomVerifier.java (92%) rename boms/sdk/src/it/sdk-usage-test/src/main/java/{io/a2a => org/a2aproject/sdk}/test/SdkBomVerifier.java (92%) rename boms/test-utils/src/main/java/{io/a2a => org/a2aproject/sdk}/bom/test/DynamicBomVerifier.java (91%) rename {client/transport/spi/src/main/java/io/a2a/client/transport/spi => boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test}/package-info.java (61%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/A2A.java (88%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/AbstractClient.java (95%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/Client.java (93%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/ClientBuilder.java (96%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/ClientEvent.java (98%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/ClientTaskManager.java (89%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/MessageEvent.java (95%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/TaskEvent.java (93%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/TaskUpdateEvent.java (85%) rename client/base/src/main/java/{io/a2a => org/a2aproject/sdk}/client/config/ClientConfig.java (93%) rename client/{transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc => base/src/main/java/org/a2aproject/sdk/client/config}/package-info.java (58%) rename {common/src/main/java/io/a2a/common => client/base/src/main/java/org/a2aproject/sdk/client}/package-info.java (62%) rename client/base/src/test/java/{io/a2a => org/a2aproject/sdk}/A2ATest.java (97%) rename client/base/src/test/java/{io/a2a => org/a2aproject/sdk}/client/AuthenticationAuthorizationTest.java (92%) rename client/base/src/test/java/{io/a2a => org/a2aproject/sdk}/client/ClientBuilderTest.java (90%) rename client/base/src/test/java/{io/a2a => org/a2aproject/sdk}/client/ClientTaskManagerTest.java (93%) rename client/transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/grpc/EventStreamObserver.java (90%) rename client/transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/grpc/GrpcErrorMapper.java (85%) rename client/transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/grpc/GrpcTransport.java (78%) rename client/transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/grpc/GrpcTransportConfig.java (94%) rename client/transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/grpc/GrpcTransportConfigBuilder.java (96%) rename client/transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/grpc/GrpcTransportProvider.java (76%) rename client/transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/grpc/package-info.java (52%) delete mode 100644 client/transport/grpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider create mode 100644 client/transport/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider rename client/transport/grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/grpc/GrpcErrorMapperTest.java (93%) delete mode 100644 client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/package-info.java rename client/transport/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/JSONRPCTransport.java (82%) rename client/transport/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/JSONRPCTransportConfig.java (91%) rename client/transport/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java (92%) rename client/transport/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/JSONRPCTransportProvider.java (72%) create mode 100644 client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/package-info.java rename client/transport/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/sse/SSEEventListener.java (84%) create mode 100644 client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/package-info.java delete mode 100644 client/transport/jsonrpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider create mode 100644 client/transport/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider rename client/transport/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java (86%) rename client/transport/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/JSONRPCTransportTest.java (88%) rename client/transport/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/JsonMessages.java (99%) rename client/transport/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/JsonStreamingMessages.java (98%) rename client/transport/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/jsonrpc/sse/SSEEventListenerTest.java (95%) delete mode 100644 client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/package-info.java rename client/transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/RestErrorMapper.java (71%) rename client/transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/RestTransport.java (80%) rename client/transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/RestTransportConfig.java (91%) rename client/transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/RestTransportConfigBuilder.java (92%) rename client/transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/RestTransportProvider.java (69%) create mode 100644 client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/package-info.java rename client/transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/sse/SSEEventListener.java (85%) create mode 100644 client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/package-info.java delete mode 100644 client/transport/rest/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider create mode 100644 client/transport/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider rename client/transport/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/JsonRestMessages.java (99%) rename client/transport/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/RestTransportTest.java (87%) rename client/transport/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/rest/sse/SSEEventListenerTest.java (97%) delete mode 100644 client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/package-info.java delete mode 100644 client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/package-info.java delete mode 100644 client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/ClientTransport.java (86%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/ClientTransportConfig.java (94%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/ClientTransportConfigBuilder.java (91%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/ClientTransportProvider.java (68%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/ClientTransportWrapper.java (95%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/interceptors/ClientCallContext.java (90%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/interceptors/ClientCallInterceptor.java (90%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/interceptors/PayloadAndHeaders.java (91%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/interceptors/auth/AuthInterceptor.java (82%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/interceptors/auth/CredentialService.java (79%) rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java (92%) create mode 100644 client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/package-info.java create mode 100644 client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/package-info.java create mode 100644 client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/package-info.java rename client/transport/spi/src/main/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/sse/AbstractSSEEventListener.java (94%) create mode 100644 client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/package-info.java rename client/transport/spi/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/interceptors/auth/AuthInterceptorTest.java (93%) rename client/transport/spi/src/test/java/{io/a2a => org/a2aproject/sdk}/client/transport/spi/sse/SSEEventListenerTest.java (96%) delete mode 100644 common/src/main/java/io/a2a/util/package-info.java rename common/src/main/java/{io/a2a => org/a2aproject/sdk}/common/A2AErrorMessages.java (91%) rename common/src/main/java/{io/a2a => org/a2aproject/sdk}/common/A2AHeaders.java (95%) rename common/src/main/java/{io/a2a => org/a2aproject/sdk}/common/MediaType.java (70%) rename {client/base/src/main/java/io/a2a/client/config => common/src/main/java/org/a2aproject/sdk/common}/package-info.java (62%) rename common/src/main/java/{io/a2a => org/a2aproject/sdk}/util/Assert.java (97%) rename common/src/main/java/{io/a2a => org/a2aproject/sdk}/util/NotNull.java (92%) rename {boms/test-utils/src/main/java/io/a2a/bom/test => common/src/main/java/org/a2aproject/sdk/util}/package-info.java (63%) rename examples/cloud-deployment/server/src/main/java/{io/a2a => org/a2aproject/sdk}/examples/cloud/CloudAgentCardProducer.java (89%) rename examples/cloud-deployment/server/src/main/java/{io/a2a => org/a2aproject/sdk}/examples/cloud/CloudAgentExecutorProducer.java (92%) rename examples/cloud-deployment/server/src/test/java/{io/a2a => org/a2aproject/sdk}/examples/cloud/A2ACloudExampleClient.java (95%) rename examples/helloworld/client/src/main/java/{io/a2a => org/a2aproject/sdk}/examples/helloworld/HelloWorldClient.java (86%) rename examples/helloworld/client/src/main/java/{io/a2a => org/a2aproject/sdk}/examples/helloworld/HelloWorldRunner.java (95%) rename examples/helloworld/client/src/main/java/{io/a2a => org/a2aproject/sdk}/examples/helloworld/INSTALL_JBANG.md (100%) rename examples/helloworld/server/src/main/java/{io/a2a => org/a2aproject/sdk}/examples/helloworld/AgentCardProducer.java (86%) rename examples/helloworld/server/src/main/java/{io/a2a => org/a2aproject/sdk}/examples/helloworld/AgentExecutorProducer.java (66%) rename extras/common/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/common/events/TaskFinalizedEvent.java (84%) rename extras/http-client-vertx/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/VertxA2AHttpClient.java (99%) rename extras/http-client-vertx/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/VertxA2AHttpClientProvider.java (93%) delete mode 100644 extras/http-client-vertx/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider create mode 100644 extras/http-client-vertx/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider rename extras/http-client-vertx/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/VertxA2AHttpClientFactoryTest.java (98%) rename extras/http-client-vertx/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/VertxA2AHttpClientIntegrationTest.java (98%) rename extras/http-client-vertx/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/VertxA2AHttpClientSSETest.java (99%) rename extras/http-client-vertx/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/VertxA2AHttpClientTest.java (98%) delete mode 100644 extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java rename extras/opentelemetry/client-propagation/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java (80%) rename extras/opentelemetry/client-propagation/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java (76%) create mode 100644 extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/package-info.java delete mode 100644 extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper create mode 100644 extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper delete mode 100644 extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java rename extras/opentelemetry/client/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/client/OpenTelemetryClientTransport.java (89%) rename extras/opentelemetry/client/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java (80%) create mode 100644 extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/package-info.java delete mode 100644 extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper create mode 100644 extras/opentelemetry/client/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper rename extras/opentelemetry/client/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java (93%) rename extras/opentelemetry/common/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/A2AObservabilityNames.java (80%) rename extras/opentelemetry/common/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/package-info.java (84%) rename extras/opentelemetry/integration-tests/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/A2ATestRoutes.java (97%) rename extras/opentelemetry/integration-tests/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/SimpleAgentExecutor.java (74%) rename extras/opentelemetry/integration-tests/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/TestAgentCardProducer.java (84%) rename extras/opentelemetry/integration-tests/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/TestUtilsBean.java (80%) rename extras/opentelemetry/integration-tests/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/BaseTest.java (88%) rename extras/opentelemetry/integration-tests/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java (95%) rename extras/opentelemetry/integration-tests/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/OpenTelemetryA2AIT.java (83%) rename extras/opentelemetry/integration-tests/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/OpenTelemetryA2ATest.java (81%) rename extras/opentelemetry/integration-tests/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/it/OpenTelemetryTest.java (95%) delete mode 100644 extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java rename extras/opentelemetry/server/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/AsyncManagedExecutorProducer.java (96%) rename extras/opentelemetry/server/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java (87%) create mode 100644 extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/package-info.java rename extras/opentelemetry/server/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/AsyncManagedExecutorProducerTest.java (97%) rename extras/opentelemetry/server/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java (96%) rename extras/push-notification-config-store-database-jpa/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java (94%) rename extras/push-notification-config-store-database-jpa/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java (90%) rename extras/push-notification-config-store-database-jpa/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java (94%) rename extras/push-notification-config-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java (93%) rename extras/push-notification-config-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java (82%) rename extras/push-notification-config-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java (80%) rename extras/push-notification-config-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java (95%) rename extras/push-notification-config-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java (84%) delete mode 100644 extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java rename extras/queue-manager-replicated/core/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java (90%) rename extras/queue-manager-replicated/core/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/core/ReplicatedQueueManager.java (90%) create mode 100644 extras/queue-manager-replicated/core/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicationStrategy.java rename extras/queue-manager-replicated/core/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/core/EventSerializationTest.java (93%) rename extras/queue-manager-replicated/core/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java (94%) rename extras/queue-manager-replicated/core/src/test/java/{io/a2a => org/a2aproject/sdk}/server/events/EventQueueTestHelper.java (51%) rename extras/queue-manager-replicated/core/src/test/java/{io/a2a => org/a2aproject/sdk}/server/events/EventQueueUtil.java (84%) rename extras/queue-manager-replicated/replication-mp-reactive/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java (86%) rename extras/queue-manager-replicated/replication-mp-reactive/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java (90%) rename extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java (53%) rename extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java (53%) rename extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java (53%) rename extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java (53%) rename extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java (84%) rename extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java (77%) rename extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java (93%) rename extras/queue-manager-replicated/tests-single-instance/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java (94%) rename extras/queue-manager-replicated/tests-single-instance/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java (71%) rename extras/queue-manager-replicated/tests-single-instance/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java (79%) rename extras/queue-manager-replicated/tests-single-instance/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java (83%) rename extras/queue-manager-replicated/tests-single-instance/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java (96%) rename extras/task-store-database-jpa/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java (95%) rename extras/task-store-database-jpa/src/main/java/{io/a2a => org/a2aproject/sdk}/extras/taskstore/database/jpa/JpaTask.java (93%) rename extras/task-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java (85%) rename extras/task-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java (98%) rename extras/task-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java (78%) rename extras/task-store-database-jpa/src/test/java/{io/a2a => org/a2aproject/sdk}/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java (80%) rename http-client/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/A2ACardResolver.java (90%) rename http-client/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/A2AHttpClient.java (99%) rename http-client/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/A2AHttpClientFactory.java (96%) rename http-client/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/A2AHttpClientProvider.java (89%) rename http-client/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/A2AHttpResponse.java (96%) rename http-client/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/JdkA2AHttpClient.java (98%) rename http-client/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/JdkA2AHttpClientProvider.java (93%) rename http-client/src/main/java/{io/a2a => org/a2aproject/sdk}/client/http/package-info.java (67%) delete mode 100644 http-client/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider create mode 100644 http-client/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider rename http-client/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/A2ACardResolverTest.java (92%) rename http-client/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/A2AHttpClientFactoryTest.java (98%) rename http-client/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/A2AHttpClientFactoryUsageExample.java (99%) rename http-client/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/A2AHttpClientProviderTest.java (95%) rename http-client/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/JdkA2AHttpClientTest.java (98%) rename http-client/src/test/java/{io/a2a => org/a2aproject/sdk}/client/http/JsonMessages.java (99%) rename integrations/microprofile-config/src/main/java/{io/a2a => org/a2aproject/sdk}/integrations/microprofile/MicroProfileConfigProvider.java (93%) rename integrations/microprofile-config/src/test/java/{io/a2a => org/a2aproject/sdk}/integrations/microprofile/MicroProfileConfigProviderTest.java (97%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/IdJsonMappingException.java (95%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/InvalidParamsJsonMappingException.java (93%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/JsonMappingException.java (98%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/JsonProcessingException.java (97%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/JsonUtil.java (95%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/MethodNotFoundJsonMappingException.java (91%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/package-info.java (85%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/A2AErrorResponse.java (94%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/A2AMessage.java (97%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/A2ARequest.java (96%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/A2AResponse.java (92%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/CancelTaskRequest.java (93%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/CancelTaskResponse.java (80%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java (94%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java (89%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java (95%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java (95%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java (91%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java (89%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java (92%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java (91%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/GetTaskRequest.java (93%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/GetTaskResponse.java (89%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java (92%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java (89%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/ListTasksRequest.java (93%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/ListTasksResponse.java (91%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/ListTasksResult.java (96%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java (93%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/SendMessageRequest.java (95%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/SendMessageResponse.java (87%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/SendStreamingMessageRequest.java (94%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/SendStreamingMessageResponse.java (85%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java (93%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/SubscribeToTaskRequest.java (93%) rename jsonrpc-common/src/main/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/wrappers/package-info.java (77%) rename jsonrpc-common/src/test/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/A2AErrorSerializationTest.java (75%) rename jsonrpc-common/src/test/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/JsonUtilTest.java (97%) rename jsonrpc-common/src/test/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/SecurityRequirementSerializationTest.java (96%) rename jsonrpc-common/src/test/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/SecuritySchemeSerializationTest.java (93%) rename jsonrpc-common/src/test/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/StreamingEventKindSerializationTest.java (95%) rename jsonrpc-common/src/test/java/{io/a2a => org/a2aproject/sdk}/jsonrpc/common/json/TaskSerializationTest.java (98%) rename reference/common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/common/quarkus/DefaultProducers.java (84%) rename reference/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/server/grpc/quarkus/A2AExtensionsInterceptor.java (83%) rename reference/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/server/grpc/quarkus/QuarkusGrpcHandler.java (91%) rename reference/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java (85%) rename reference/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/server/grpc/quarkus/package-info.java (72%) delete mode 100644 reference/grpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata create mode 100644 reference/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata rename reference/grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/server/grpc/quarkus/A2ATestResource.java (93%) rename reference/grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/server/grpc/quarkus/QuarkusA2AGrpcTest.java (81%) rename reference/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/A2AServerRoutes.java (85%) rename reference/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/CallContextFactory.java (90%) rename reference/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java (85%) rename reference/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/package-info.java (85%) delete mode 100644 reference/jsonrpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata create mode 100644 reference/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata rename reference/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/A2AServerRoutesTest.java (90%) rename reference/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/A2ATestRoutes.java (95%) rename reference/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java (52%) rename reference/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/QuarkusA2AJSONRPCTest.java (67%) rename reference/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java (58%) rename reference/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/A2AServerRoutes.java (94%) rename reference/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/CallContextFactory.java (88%) rename reference/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/QuarkusRestTransportMetadata.java (87%) rename reference/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/package-info.java (84%) delete mode 100644 reference/rest/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata create mode 100644 reference/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata rename reference/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/A2AServerRoutesTest.java (95%) rename reference/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/A2ATestRoutes.java (95%) rename reference/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/QuarkusA2ARestJdkTest.java (52%) rename reference/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/QuarkusA2ARestTest.java (94%) rename reference/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/server/rest/quarkus/QuarkusA2ARestVertxTest.java (59%) delete mode 100644 server-common/src/main/java/io/a2a/server/agentexecution/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/auth/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/config/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/events/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/extensions/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/requesthandlers/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/tasks/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/util/async/package-info.java delete mode 100644 server-common/src/main/java/io/a2a/server/util/package-info.java rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/AgentCardCacheMetadata.java (96%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/AgentCardValidator.java (91%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/ExtendedAgentCard.java (93%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/JSONRPCException.java (89%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/PublicAgentCard.java (93%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/ServerCallContext.java (95%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/TransportMetadata.java (95%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/agentexecution/AgentExecutor.java (86%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/agentexecution/RequestContext.java (97%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/agentexecution/SimpleRequestContextBuilder.java (88%) create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/package-info.java rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/auth/UnauthenticatedUser.java (89%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/auth/User.java (67%) create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/auth/package-info.java rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/config/A2AConfigProvider.java (96%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/config/DefaultValuesConfigProvider.java (98%) create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/config/package-info.java rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/EnhancedRunnable.java (97%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/EventConsumer.java (98%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/EventEnqueueHook.java (91%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/EventQueue.java (99%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/EventQueueClosedException.java (84%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/EventQueueFactory.java (90%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/EventQueueItem.java (92%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/InMemoryQueueManager.java (98%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/LocalEventQueueItem.java (83%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/MainEventBus.java (97%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/MainEventBusContext.java (90%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/MainEventBusProcessor.java (96%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/MainEventBusProcessorCallback.java (95%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/MainEventBusProcessorInitializer.java (97%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/NoTaskQueueException.java (97%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/QueueClosedEvent.java (92%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/QueueManager.java (94%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/events/TaskQueueExistsException.java (93%) create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/events/package-info.java rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/extensions/A2AExtensions.java (90%) create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/extensions/package-info.java rename {client/base/src/main/java/io/a2a/client => server-common/src/main/java/org/a2aproject/sdk/server}/package-info.java (61%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/requesthandlers/DefaultRequestHandler.java (93%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/requesthandlers/RequestHandler.java (62%) create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/package-info.java rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/AgentEmitter.java (95%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/BasePushNotificationSender.java (86%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/InMemoryPushNotificationConfigStore.java (93%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/InMemoryTaskStore.java (97%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/PushNotificationConfigStore.java (93%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/PushNotificationSender.java (86%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/ResultAggregator.java (93%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskManager.java (92%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskPersistenceException.java (98%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskSerializationException.java (98%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskStateProvider.java (98%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskStore.java (91%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskStoreException.java (92%) create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/tasks/package-info.java rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/util/ArtifactUtils.java (94%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/util/async/AsyncExecutorProducer.java (98%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/util/async/AsyncUtils.java (99%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/util/async/EventConsumerExecutorProducer.java (98%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/util/async/Internal.java (89%) create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/util/async/package-info.java create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/util/package-info.java rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/util/sse/SseFormatter.java (69%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/util/sse/package-info.java (89%) rename server-common/src/main/java/{io/a2a => org/a2aproject/sdk}/server/version/A2AVersionValidator.java (95%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/AgentCardValidatorTest.java (97%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/ServerCallContextTest.java (98%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/agentexecution/RequestContextTest.java (97%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/events/EnhancedRunnableTest.java (99%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/events/EventConsumerTest.java (96%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/events/EventQueueTest.java (95%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/events/EventQueueUtil.java (96%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/events/InMemoryQueueManagerTest.java (97%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/events/MainEventBusProcessorExceptionTest.java (95%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/extensions/A2AExtensionsTest.java (95%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/requesthandlers/AbstractA2ARequestHandlerTest.java (84%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/requesthandlers/DefaultRequestHandlerTest.java (94%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/AbstractTaskStoreExceptionTest.java (99%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/AgentEmitterConcurrencyTest.java (97%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/AgentEmitterTest.java (95%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/InMemoryPushNotificationConfigStoreTest.java (97%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/InMemoryTaskStoreTest.java (100%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/MockTaskStateProvider.java (96%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/PushNotificationSenderTest.java (95%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/ResultAggregatorTest.java (96%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskManagerTest.java (98%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskPersistenceExceptionTest.java (99%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskSerializationExceptionTest.java (99%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/tasks/TaskStoreExceptionTest.java (99%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/util/ArtifactUtilsTest.java (95%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/util/async/AsyncUtilsTest.java (98%) rename server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/version/A2AVersionValidatorTest.java (95%) delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentProviderMapper.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/ClientCredentialsOAuthFlowMapper.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java delete mode 100644 spec-grpc/src/main/java/io/a2a/grpc/utils/package-info.java rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/A2A.java (99%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/A2AServiceGrpc.java (64%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/APIKeySecurityScheme.java (87%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/APIKeySecuritySchemeOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentCapabilities.java (84%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentCapabilitiesOrBuilder.java (90%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentCard.java (86%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentCardOrBuilder.java (88%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentCardSignature.java (89%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentCardSignatureOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentExtension.java (90%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentExtensionOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentInterface.java (91%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentInterfaceOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentProvider.java (86%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentProviderOrBuilder.java (97%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentSkill.java (91%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AgentSkillOrBuilder.java (95%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/Artifact.java (91%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ArtifactOrBuilder.java (94%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AuthenticationInfo.java (86%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AuthenticationInfoOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AuthorizationCodeOAuthFlow.java (91%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/AuthorizationCodeOAuthFlowOrBuilder.java (99%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/CancelTaskRequest.java (89%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/CancelTaskRequestOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ClientCredentialsOAuthFlow.java (89%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ClientCredentialsOAuthFlowOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/DeleteTaskPushNotificationConfigRequest.java (85%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/DeviceCodeOAuthFlow.java (91%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/DeviceCodeOAuthFlowOrBuilder.java (99%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/GetExtendedAgentCardRequest.java (79%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/GetExtendedAgentCardRequestOrBuilder.java (96%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/GetTaskPushNotificationConfigRequest.java (85%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/GetTaskRequest.java (88%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/GetTaskRequestOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/HTTPAuthSecurityScheme.java (88%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/HTTPAuthSecuritySchemeOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ImplicitOAuthFlow.java (90%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ImplicitOAuthFlowOrBuilder.java (99%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ListTaskPushNotificationConfigsRequest.java (86%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ListTaskPushNotificationConfigsResponse.java (78%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java (84%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ListTasksRequest.java (92%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ListTasksRequestOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ListTasksResponse.java (85%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/ListTasksResponseOrBuilder.java (90%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/Message.java (91%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/MessageOrBuilder.java (95%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/MutualTlsSecurityScheme.java (80%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/MutualTlsSecuritySchemeOrBuilder.java (96%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/OAuth2SecurityScheme.java (84%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/OAuth2SecuritySchemeOrBuilder.java (93%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/OAuthFlows.java (73%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/OAuthFlowsOrBuilder.java (80%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/OpenIdConnectSecurityScheme.java (84%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/OpenIdConnectSecuritySchemeOrBuilder.java (97%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/Part.java (94%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/PartOrBuilder.java (97%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/PasswordOAuthFlow.java (90%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/PasswordOAuthFlowOrBuilder.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/Role.java (97%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SecurityRequirement.java (73%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SecurityRequirementOrBuilder.java (81%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SecurityScheme.java (72%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SecuritySchemeOrBuilder.java (78%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SendMessageConfiguration.java (86%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SendMessageConfigurationOrBuilder.java (95%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SendMessageRequest.java (83%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SendMessageRequestOrBuilder.java (89%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SendMessageResponse.java (75%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SendMessageResponseOrBuilder.java (80%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/StreamResponse.java (74%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/StreamResponseOrBuilder.java (80%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/StringList.java (84%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/StringListOrBuilder.java (97%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SubscribeToTaskRequest.java (84%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/SubscribeToTaskRequestOrBuilder.java (97%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/Task.java (86%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskArtifactUpdateEvent.java (88%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskArtifactUpdateEventOrBuilder.java (95%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskOrBuilder.java (88%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskPushNotificationConfig.java (87%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskPushNotificationConfigOrBuilder.java (94%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskState.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskStatus.java (83%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskStatusOrBuilder.java (91%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskStatusUpdateEvent.java (86%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/TaskStatusUpdateEventOrBuilder.java (94%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/A2ACommonFieldMapper.java (96%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/A2AMappers.java (95%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/A2AProtoMapperConfig.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/APIKeySecuritySchemeMapper.java (52%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/AgentCapabilitiesMapper.java (51%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/AgentCardMapper.java (80%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/AgentCardSignatureMapper.java (76%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/AgentExtensionMapper.java (73%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/AgentInterfaceMapper.java (51%) create mode 100644 spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentProviderMapper.java rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/AgentSkillMapper.java (53%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/ArtifactMapper.java (84%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/AuthenticationInfoMapper.java (72%) create mode 100644 spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java create mode 100644 spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ClientCredentialsOAuthFlowMapper.java rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java (65%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java (66%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/HTTPAuthSecuritySchemeMapper.java (63%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/ListTaskPushNotificationConfigsParamsMapper.java (63%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/ListTasksParamsMapper.java (91%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/ListTasksResultMapper.java (72%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/MessageMapper.java (74%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/MessageSendConfigurationMapper.java (70%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/MessageSendParamsMapper.java (76%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/MutualTLSSecuritySchemeMapper.java (57%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/OAuth2SecuritySchemeMapper.java (61%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/OAuthFlowsMapper.java (63%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java (55%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/PartMapper.java (86%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/ResourceNameParser.java (98%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/RoleMapper.java (63%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/SecurityRequirementMapper.java (77%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/SecuritySchemeMapper.java (80%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/StreamResponseMapper.java (75%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/SubscribeToTaskRequestMapper.java (74%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/TaskArtifactUpdateEventMapper.java (74%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/TaskIdParamsMapper.java (71%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/TaskMapper.java (85%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/TaskPushNotificationConfigMapper.java (87%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/TaskQueryParamsMapper.java (72%) create mode 100644 spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStateMapper.java rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/TaskStatusMapper.java (81%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/TaskStatusUpdateEventMapper.java (76%) rename spec-grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/grpc/utils/JSONRPCUtils.java (80%) create mode 100644 spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/ProtoUtils.java rename {client/transport/rest/src/main/java/io/a2a/client/transport/rest => spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils}/package-info.java (59%) rename spec-grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/A2ACommonFieldMapperTest.java (90%) rename spec-grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/grpc/mapper/StreamResponseMapperTest.java (70%) rename spec-grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/grpc/utils/JSONRPCUtilsTest.java (92%) rename spec-grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/grpc/utils/PartTypeAdapterTest.java (93%) rename spec-grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/grpc/utils/ToProtoTest.java (86%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AClientError.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AClientException.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AClientHTTPError.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AClientInvalidArgsError.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AClientInvalidStateError.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AClientJSONError.java (93%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AError.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AErrorCodes.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AException.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AMethods.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AProtocolError.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/A2AServerException.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/APIKeySecurityScheme.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AgentCapabilities.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AgentCard.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AgentCardSignature.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AgentExtension.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AgentInterface.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AgentProvider.java (94%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AgentSkill.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/Artifact.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AuthenticationInfo.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/AuthorizationCodeOAuthFlow.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/CancelTaskParams.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/ClientCredentialsOAuthFlow.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/ContentTypeNotSupportedError.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/DataPart.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/DeleteTaskPushNotificationConfigParams.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/DeviceCodeOAuthFlow.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/Event.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/EventKind.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/ExtendedAgentCardNotConfiguredError.java (94%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/ExtensionSupportRequiredError.java (94%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/FileContent.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/FilePart.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/FileWithBytes.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/FileWithUri.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/GetExtendedAgentCardParams.java (90%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/GetTaskPushNotificationConfigParams.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/HTTPAuthSecurityScheme.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/InternalError.java (94%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/InvalidAgentResponseError.java (94%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/InvalidParamsError.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/InvalidRequestError.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/JSONParseError.java (92%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/ListTaskPushNotificationConfigsParams.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/ListTaskPushNotificationConfigsResult.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/ListTasksParams.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/Message.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/MessageSendConfiguration.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/MessageSendParams.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/MethodNotFoundError.java (94%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/MutualTLSSecurityScheme.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/OAuth2SecurityScheme.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/OAuthFlows.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/OpenIdConnectSecurityScheme.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/Part.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/PushNotificationNotSupportedError.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/SecurityRequirement.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/SecurityScheme.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/StreamingEventKind.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/Task.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskArtifactUpdateEvent.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskIdParams.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskNotCancelableError.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskNotFoundError.java (94%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskPushNotificationConfig.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskQueryParams.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskState.java (99%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskStatus.java (97%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TaskStatusUpdateEvent.java (92%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TextPart.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/TransportProtocol.java (98%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/UnsupportedOperationError.java (95%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/UpdateEvent.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/VersionNotSupportedError.java (94%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/spec/package-info.java (89%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/util/PageToken.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/util/Utils.java (96%) rename spec/src/main/java/{io/a2a => org/a2aproject/sdk}/util/package-info.java (78%) rename spec/src/test/java/{io/a2a => org/a2aproject/sdk}/spec/DataPartTest.java (98%) rename spec/src/test/java/{io/a2a => org/a2aproject/sdk}/spec/FileWithBytesTest.java (99%) rename spec/src/test/java/{io/a2a => org/a2aproject/sdk}/util/PageTokenTest.java (98%) rename spec/src/test/java/{io/a2a => org/a2aproject/sdk}/util/UtilsTest.java (99%) rename tck/src/main/java/{io/a2a => org/a2aproject/sdk}/tck/server/AgentCardProducer.java (87%) rename tck/src/main/java/{io/a2a => org/a2aproject/sdk}/tck/server/AgentExecutorProducer.java (89%) rename tck/src/main/java/{io/a2a => org/a2aproject/sdk}/tck/server/package-info.java (84%) rename test-utils-docker/src/main/java/{io/a2a => org/a2aproject/sdk}/testutils/docker/DockerAvailability.java (98%) rename test-utils-docker/src/main/java/{io/a2a => org/a2aproject/sdk}/testutils/docker/DockerRequiredExtension.java (97%) rename test-utils-docker/src/main/java/{io/a2a => org/a2aproject/sdk}/testutils/docker/RequiresDocker.java (95%) rename tests/server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/common/A2AGsonObjectMapper.java (85%) rename tests/server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/common/AbstractA2AServerTest.java (97%) rename tests/server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/common/AgentCardProducer.java (87%) rename tests/server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/common/AgentExecutorProducer.java (92%) rename tests/server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/common/AgentToAgentClientFactory.java (81%) rename tests/server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/common/TestHttpClient.java (88%) rename tests/server-common/src/test/java/{io/a2a => org/a2aproject/sdk}/server/apps/common/TestUtilsBean.java (91%) rename transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/grpc/context/GrpcContextKeys.java (95%) rename transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/grpc/handler/CallContextFactory.java (85%) rename transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/grpc/handler/GrpcHandler.java (84%) rename transport/grpc/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/grpc/handler/package-info.java (91%) rename transport/grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/transport/grpc/handler/GrpcHandlerTest.java (95%) rename transport/grpc/src/test/java/{io/a2a => org/a2aproject/sdk}/transport/grpc/handler/GrpcTestTransportMetadata.java (55%) delete mode 100644 transport/grpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata create mode 100644 transport/grpc/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata rename transport/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/jsonrpc/context/JSONRPCContextKeys.java (84%) rename transport/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/jsonrpc/handler/JSONRPCHandler.java (88%) rename transport/jsonrpc/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/jsonrpc/handler/package-info.java (92%) rename transport/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/transport/jsonrpc/handler/JSONRPCHandlerTest.java (95%) rename transport/jsonrpc/src/test/java/{io/a2a => org/a2aproject/sdk}/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java (55%) delete mode 100644 transport/jsonrpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata create mode 100644 transport/jsonrpc/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata rename transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/rest/context/RestContextKeys.java (84%) rename transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/rest/handler/RestHandler.java (90%) rename transport/rest/src/main/java/{io/a2a => org/a2aproject/sdk}/transport/rest/handler/package-info.java (90%) rename transport/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/transport/rest/handler/RestHandlerTest.java (98%) rename transport/rest/src/test/java/{io/a2a => org/a2aproject/sdk}/transport/rest/handler/RestTestTransportMetadata.java (73%) delete mode 100644 transport/rest/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata create mode 100644 transport/rest/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata diff --git a/.agents/skills/fix-tck-issue/SKILL.md b/.agents/skills/fix-tck-issue/SKILL.md index baf97aba8..8be87c7d3 100644 --- a/.agents/skills/fix-tck-issue/SKILL.md +++ b/.agents/skills/fix-tck-issue/SKILL.md @@ -65,9 +65,9 @@ Create test in appropriate module. Choose location based on test complexity: - Testing handler logic directly - Need custom AgentCard configuration (e.g., capability flags) - Simpler to set up specific test conditions -- **HTTP+JSON** → `transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java` -- **gRPC** → `transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java` -- **JSON-RPC** → `transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java` +- **HTTP+JSON** → `transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java` +- **gRPC** → `transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java` +- **JSON-RPC** → `transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java` **Option B: reference/* modules (Integration Tests)** - Use when: - Testing full request/response cycle @@ -195,9 +195,9 @@ Fixes #" Example for multi-transport fix: ```bash -git add transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java \ - transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java \ - transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java +git add transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java \ + transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java \ + transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java git commit -m "fix: Return UnsupportedOperationError when capability is disabled Applied to all three transports: HTTP+JSON, JSON-RPC, and gRPC. @@ -245,9 +245,9 @@ builder.setTaskId(taskId); - More control over test setup **Test file locations**: -- `transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java` -- `transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java` -- `transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java` +- `transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java` +- `transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java` +- `transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java` ### reference/* modules (Integration Tests) **Best for**: diff --git a/.agents/skills/update-a2a-proto/SKILL.md b/.agents/skills/update-a2a-proto/SKILL.md index b3cef1c7b..e64707a5e 100644 --- a/.agents/skills/update-a2a-proto/SKILL.md +++ b/.agents/skills/update-a2a-proto/SKILL.md @@ -22,7 +22,7 @@ Before updating, record what we have now so we can diff later. 2. Download the latest `a2a.proto` from the upstream A2A repository at https://github.com/a2aproject/A2A/blob/main/specification/a2a.proto and save it to `spec-grpc/src/main/proto/a2a.proto`. 3. Update the `java_package` option in the downloaded proto file to: ``` - option java_package = "io.a2a.grpc"; + option java_package = "org.a2aproject.sdk.grpc"; ``` 4. Update the comment tracking the upstream commit hash (line starting with `// From commit`) to the commit hash / tag of the downloaded proto file. @@ -39,7 +39,7 @@ Compare the old and new versions of the specification to identify changes: 1. Delete all the generated gRPC Java classes (in case of resources removed from the Protobuf definitions): ```bash - find spec-grpc/src/main/java/io/a2a/grpc -maxdepth 1 -name "*.java" -delete``` + find spec-grpc/src/main/java/org/a2aproject/sdk/grpc -maxdepth 1 -name "*.java" -delete``` ``` 2. Regenerate gRPC Java classes by running: diff --git a/.github/workflows/cloud-deployment-example.yml b/.github/workflows/cloud-deployment-example.yml index 57a97a638..9bfe1da95 100644 --- a/.github/workflows/cloud-deployment-example.yml +++ b/.github/workflows/cloud-deployment-example.yml @@ -55,7 +55,7 @@ jobs: working-directory: examples/cloud-deployment/server run: | mvn test-compile exec:java \ - -Dexec.mainClass="io.a2a.examples.cloud.A2ACloudExampleClient" \ + -Dexec.mainClass="org.a2aproject.sdk.examples.cloud.A2ACloudExampleClient" \ -Dexec.classpathScope=test \ -Dagent.url=http://localhost:8080 \ -Dci.mode=true diff --git a/AGENTS.md b/AGENTS.md index c6c4c1020..2a4cf6586 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,7 +38,7 @@ mvn clean install ## Key Conventions -- Package root: `io.a2a` +- Package root: `org.a2aproject.sdk` - Serialization: Gson (see `gson.version` in parent POM) - Null safety: NullAway + JSpecify annotations enforced via Error Prone - Reference server runtime: Quarkus @@ -51,7 +51,7 @@ mvn clean install - Do not use "star" imports (eg `import java.util.*`) - Use Java `record` for immutable data types - Use `@Nullable` (from org.jspecify.annotations) for optional fields -- Use `io.a2a.util.Assert.checkNotNullParam()` in the compact constructor to validate required fields +- Use `org.a2aproject.sdk.util.Assert.checkNotNullParam()` in the compact constructor to validate required fields - Use `List.copyOf()` and `Map.copyOf()` for defensive copying of collections - Apply the Builder pattern for records with many fields (see `AgentCard.java` as reference) diff --git a/CONTRIBUTING_INTEGRATIONS.md b/CONTRIBUTING_INTEGRATIONS.md index 9fc06a520..c4541471e 100644 --- a/CONTRIBUTING_INTEGRATIONS.md +++ b/CONTRIBUTING_INTEGRATIONS.md @@ -8,7 +8,7 @@ Then the project page itself needs to contain the following information as a min * How to use the integration. * Ideally there should be a sample demonstrating how to use it -* The integration should have tests, extending [AbstractA2AServerTest](tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java) +* The integration should have tests, extending [AbstractA2AServerTest](tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java) * The integration should pass the [TCK](https://github.com/a2aproject/a2a-tck), and make it obvious how to see that it has passed. * Ideally, the integration should be deployed in Maven Central. If that is not possible, provide clear instructions for how to build it. diff --git a/README.md b/README.md index 2ac7761de..f026731b9 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ mvn clean install ### Regeneration of gRPC files We copy https://github.com/a2aproject/A2A/blob/main/specification/grpc/a2a.proto to the [`spec-grpc/`](./spec-grpc) project, and adjust the `java_package` option to be as follows: ``` -option java_package = "io.a2a.grpc"; +option java_package = "org.a2aproject.sdk.grpc"; ``` -Then build the `spec-grpc` module with `mvn clean install -Dskip.protobuf.generate=false` to regenerate the gRPC classes in the `io.a2a.grpc` package. +Then build the `spec-grpc` module with `mvn clean install -Dskip.protobuf.generate=false` to regenerate the gRPC classes in the `org.a2aproject.sdk.grpc` package. ## Examples @@ -63,7 +63,7 @@ To use the reference implementation with the JSON-RPC protocol, add the followin org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} ``` @@ -74,7 +74,7 @@ To use the reference implementation with the gRPC protocol, add the following de org.a2aproject.sdk a2a-java-sdk-reference-grpc - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} ``` @@ -85,7 +85,7 @@ To use the reference implementation with the HTTP+JSON/REST protocol, add the fo org.a2aproject.sdk a2a-java-sdk-reference-rest - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} ``` @@ -95,12 +95,12 @@ you'd like to support. ### 2. Add a class that creates an A2A Agent Card ```java -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.TransportProtocol; ... @ApplicationScoped @@ -138,17 +138,17 @@ public class WeatherAgentCardProducer { ### 3. Add a class that creates an A2A Agent Executor ```java -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.JSONRPCError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.JSONRPCError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TextPart; ... @ApplicationScoped @@ -290,7 +290,7 @@ that you can use to create your A2A `Client`. org.a2aproject.sdk a2a-java-sdk-client - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} ``` @@ -306,7 +306,7 @@ If you want to use the gRPC transport, you'll need to add a relevant dependency: org.a2aproject.sdk a2a-java-sdk-client-transport-grpc - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} ``` @@ -319,7 +319,7 @@ If you want to use the HTTP+JSON/REST transport, you'll need to add a relevant d org.a2aproject.sdk a2a-java-sdk-client-transport-rest - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} ``` diff --git a/boms/README.md b/boms/README.md index dc6821d51..9c474c022 100644 --- a/boms/README.md +++ b/boms/README.md @@ -58,7 +58,7 @@ Add to your project's `pom.xml`: org.a2aproject.sdk a2a-java-sdk-bom - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} pom import @@ -88,7 +88,7 @@ Add to your project's `pom.xml`: org.a2aproject.sdk a2a-java-sdk-extras-bom - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} pom import @@ -118,7 +118,7 @@ Add to your project's `pom.xml`: org.a2aproject.sdk a2a-java-sdk-reference-bom - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} pom import diff --git a/boms/extras/src/it/extras-usage-test/pom.xml b/boms/extras/src/it/extras-usage-test/pom.xml index 1005ce7d9..67792ea5d 100644 --- a/boms/extras/src/it/extras-usage-test/pom.xml +++ b/boms/extras/src/it/extras-usage-test/pom.xml @@ -154,7 +154,7 @@ java - io.a2a.test.ExtrasBomVerifier + org.a2aproject.sdk.test.ExtrasBomVerifier diff --git a/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java b/boms/extras/src/it/extras-usage-test/src/main/java/org/a2aproject/sdk/test/ExtrasBomVerifier.java similarity index 94% rename from boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java rename to boms/extras/src/it/extras-usage-test/src/main/java/org/a2aproject/sdk/test/ExtrasBomVerifier.java index 57fa62d12..8357ce447 100644 --- a/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java +++ b/boms/extras/src/it/extras-usage-test/src/main/java/org/a2aproject/sdk/test/ExtrasBomVerifier.java @@ -1,6 +1,6 @@ -package io.a2a.test; +package org.a2aproject.sdk.test; -import io.a2a.bom.test.DynamicBomVerifier; +import org.a2aproject.sdk.bom.test.DynamicBomVerifier; import java.util.Set; diff --git a/boms/reference/src/it/reference-usage-test/pom.xml b/boms/reference/src/it/reference-usage-test/pom.xml index 7f21c2e95..a6bc0c32b 100644 --- a/boms/reference/src/it/reference-usage-test/pom.xml +++ b/boms/reference/src/it/reference-usage-test/pom.xml @@ -131,7 +131,7 @@ java - io.a2a.test.ReferenceBomVerifier + org.a2aproject.sdk.test.ReferenceBomVerifier diff --git a/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java b/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java similarity index 92% rename from boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java rename to boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java index cb74b0093..6b20bb50e 100644 --- a/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java +++ b/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java @@ -1,6 +1,6 @@ -package io.a2a.test; +package org.a2aproject.sdk.test; -import io.a2a.bom.test.DynamicBomVerifier; +import org.a2aproject.sdk.bom.test.DynamicBomVerifier; import java.util.Set; diff --git a/boms/sdk/src/it/sdk-usage-test/pom.xml b/boms/sdk/src/it/sdk-usage-test/pom.xml index 884a62b9e..5da56e93e 100644 --- a/boms/sdk/src/it/sdk-usage-test/pom.xml +++ b/boms/sdk/src/it/sdk-usage-test/pom.xml @@ -150,7 +150,7 @@ java - io.a2a.test.SdkBomVerifier + org.a2aproject.sdk.test.SdkBomVerifier diff --git a/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java b/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java similarity index 92% rename from boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java rename to boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java index cf584659c..f69d70b85 100644 --- a/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java +++ b/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java @@ -1,6 +1,6 @@ -package io.a2a.test; +package org.a2aproject.sdk.test; -import io.a2a.bom.test.DynamicBomVerifier; +import org.a2aproject.sdk.bom.test.DynamicBomVerifier; import java.util.Set; diff --git a/boms/test-utils/src/main/java/io/a2a/bom/test/DynamicBomVerifier.java b/boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/DynamicBomVerifier.java similarity index 91% rename from boms/test-utils/src/main/java/io/a2a/bom/test/DynamicBomVerifier.java rename to boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/DynamicBomVerifier.java index 71b00e28a..8fbc1fa84 100644 --- a/boms/test-utils/src/main/java/io/a2a/bom/test/DynamicBomVerifier.java +++ b/boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/DynamicBomVerifier.java @@ -1,4 +1,4 @@ -package io.a2a.bom.test; +package org.a2aproject.sdk.bom.test; import java.io.IOException; import java.nio.file.Files; @@ -109,13 +109,13 @@ public void verify() throws Exception { private void sanityCheckDiscovery(Set requiredClasses, Set forbiddenClasses) { // Do some sanity checks for some classes from both top-level and nested modules to make sure the // discovery mechanism worked properly - sanityCheckDiscovery("io.a2a.spec.AgentCard", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.server.events.EventConsumer", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.client.transport.spi.ClientTransport", requiredClasses, forbiddenClasses); + sanityCheckDiscovery("org.a2aproject.sdk.spec.AgentCard", requiredClasses, forbiddenClasses); + sanityCheckDiscovery("org.a2aproject.sdk.server.events.EventConsumer", requiredClasses, forbiddenClasses); + sanityCheckDiscovery("org.a2aproject.sdk.client.transport.spi.ClientTransport", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.server.common.quarkus.DefaultProducers", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.extras.common.events.TaskFinalizedEvent", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem", requiredClasses, forbiddenClasses); + sanityCheckDiscovery("org.a2aproject.sdk.server.common.quarkus.DefaultProducers", requiredClasses, forbiddenClasses); + sanityCheckDiscovery("org.a2aproject.sdk.extras.common.events.TaskFinalizedEvent", requiredClasses, forbiddenClasses); + sanityCheckDiscovery("org.a2aproject.sdk.extras.queuemanager.replicated.core.ReplicatedEventQueueItem", requiredClasses, forbiddenClasses); // Make sure that the required and forbidden sets don't contain the same classes Set intersection = new HashSet<>(requiredClasses); diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/package-info.java b/boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/package-info.java similarity index 61% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/package-info.java rename to boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/package-info.java index f2185d0c9..4beea380a 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/package-info.java +++ b/boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/package-info.java @@ -1,5 +1,5 @@ @NullMarked -package io.a2a.client.transport.spi; +package org.a2aproject.sdk.bom.test; import org.jspecify.annotations.NullMarked; diff --git a/client/base/src/main/java/io/a2a/A2A.java b/client/base/src/main/java/org/a2aproject/sdk/A2A.java similarity index 88% rename from client/base/src/main/java/io/a2a/A2A.java rename to client/base/src/main/java/org/a2aproject/sdk/A2A.java index 14101b678..48e40fb15 100644 --- a/client/base/src/main/java/io/a2a/A2A.java +++ b/client/base/src/main/java/org/a2aproject/sdk/A2A.java @@ -1,18 +1,18 @@ -package io.a2a; +package org.a2aproject.sdk; import java.util.Collections; import java.util.List; import java.util.Map; -import io.a2a.client.http.A2ACardResolver; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientJSONError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.client.http.A2ACardResolver; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.spec.A2AClientError; +import org.a2aproject.sdk.spec.A2AClientJSONError; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; /** @@ -47,7 +47,7 @@ * * @see Message * @see AgentCard - * @see io.a2a.client.Client + * @see org.a2aproject.sdk.client.Client */ public class A2A { @@ -58,7 +58,7 @@ public class A2A { * The message will have: *
              *
            • role: USER
            • - *
            • parts: Single {@link io.a2a.spec.TextPart} with the provided text
            • + *
            • parts: Single {@link org.a2aproject.sdk.spec.TextPart} with the provided text
            • *
            • Auto-generated message ID
            • *
            *

            @@ -103,7 +103,7 @@ public static Message toUserMessage(String text, String messageId) { * Create a simple agent message from text. *

            * This is typically used in testing or when constructing agent responses programmatically. - * Most client applications receive agent messages via {@link io.a2a.client.MessageEvent} + * Most client applications receive agent messages via {@link org.a2aproject.sdk.client.MessageEvent} * rather than creating them manually. *

            * Example: @@ -218,8 +218,8 @@ public static Message createAgentTextMessage(String text, String contextId, Stri * @param taskId the task ID to use (optional) * @return an agent message with the specified parts, context, and task IDs * @throws IllegalArgumentException if parts is null or empty - * @see io.a2a.spec.Part - * @see io.a2a.spec.TextPart + * @see org.a2aproject.sdk.spec.Part + * @see org.a2aproject.sdk.spec.TextPart */ public static Message createAgentPartsMessage(List> parts, String contextId, String taskId) { if (parts == null || parts.isEmpty()) { @@ -279,8 +279,8 @@ private static Message toMessage(List> parts, Message.Role role, String * * @param agentUrl the base URL for the agent whose agent card we want to retrieve * @return the agent card - * @throws io.a2a.spec.A2AClientError if an HTTP error occurs fetching the card - * @throws io.a2a.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema + * @throws org.a2aproject.sdk.spec.A2AClientError if an HTTP error occurs fetching the card + * @throws org.a2aproject.sdk.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema * @see #getAgentCard(A2AHttpClient, String) * @see #getAgentCard(String, String, java.util.Map) * @see AgentCard @@ -307,9 +307,9 @@ public static AgentCard getAgentCard(String agentUrl) throws A2AClientError, A2A * @param httpClient the http client to use * @param agentUrl the base URL for the agent whose agent card we want to retrieve * @return the agent card - * @throws io.a2a.spec.A2AClientError if an HTTP error occurs fetching the card - * @throws io.a2a.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema - * @see io.a2a.client.http.A2AHttpClient + * @throws org.a2aproject.sdk.spec.A2AClientError if an HTTP error occurs fetching the card + * @throws org.a2aproject.sdk.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema + * @see org.a2aproject.sdk.client.http.A2AHttpClient */ public static AgentCard getAgentCard(A2AHttpClient httpClient, String agentUrl) throws A2AClientError, A2AClientJSONError { return getAgentCard(httpClient, agentUrl, null, null); @@ -353,8 +353,8 @@ public static AgentCard getAgentCard(A2AHttpClient httpClient, String agentUrl) * agent URL, defaults to ".well-known/agent-card.json" * @param authHeaders the HTTP authentication headers to use * @return the agent card - * @throws io.a2a.spec.A2AClientError if an HTTP error occurs fetching the card - * @throws io.a2a.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema + * @throws org.a2aproject.sdk.spec.A2AClientError if an HTTP error occurs fetching the card + * @throws org.a2aproject.sdk.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema */ public static AgentCard getAgentCard(String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError, A2AClientJSONError { return getAgentCard(A2AHttpClientFactory.create(), agentUrl, relativeCardPath, authHeaders); @@ -389,8 +389,8 @@ public static AgentCard getAgentCard(String agentUrl, String relativeCardPath, M * agent URL, defaults to ".well-known/agent-card.json" * @param authHeaders the HTTP authentication headers to use * @return the agent card - * @throws io.a2a.spec.A2AClientError if an HTTP error occurs fetching the card - * @throws io.a2a.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema + * @throws org.a2aproject.sdk.spec.A2AClientError if an HTTP error occurs fetching the card + * @throws org.a2aproject.sdk.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema */ public static AgentCard getAgentCard(A2AHttpClient httpClient, String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError, A2AClientJSONError { A2ACardResolver resolver = new A2ACardResolver(httpClient, agentUrl, "", relativeCardPath, authHeaders); diff --git a/client/base/src/main/java/io/a2a/client/AbstractClient.java b/client/base/src/main/java/org/a2aproject/sdk/client/AbstractClient.java similarity index 95% rename from client/base/src/main/java/io/a2a/client/AbstractClient.java rename to client/base/src/main/java/org/a2aproject/sdk/client/AbstractClient.java index bb43fb67c..7f3171eab 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/AbstractClient.java @@ -1,28 +1,28 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; -import static io.a2a.util.Assert.checkNotNullParam; +import static org.a2aproject.sdk.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.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.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; diff --git a/client/base/src/main/java/io/a2a/client/Client.java b/client/base/src/main/java/org/a2aproject/sdk/client/Client.java similarity index 93% rename from client/base/src/main/java/io/a2a/client/Client.java rename to client/base/src/main/java/org/a2aproject/sdk/client/Client.java index 32d00d629..5abb3dae8 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/Client.java @@ -1,38 +1,38 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; -import static io.a2a.util.Assert.checkNotNullParam; +import static org.a2aproject.sdk.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.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; -import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.A2AClientError; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AClientInvalidStateError; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; @@ -103,7 +103,7 @@ *

          • Streaming: {@link #sendMessage} returns immediately, events delivered asynchronously * to consumers as the agent processes the request
          • * - * The mode is determined by {@link ClientConfig#isStreaming()} AND {@link io.a2a.spec.AgentCapabilities#streaming()}. + * The mode is determined by {@link ClientConfig#isStreaming()} AND {@link org.a2aproject.sdk.spec.AgentCapabilities#streaming()}. * Both must be {@code true} for streaming mode; otherwise blocking mode is used. *

            * Task lifecycle example: @@ -181,7 +181,7 @@ * @see MessageEvent * @see TaskEvent * @see TaskUpdateEvent - * @see io.a2a.A2A + * @see org.a2aproject.sdk.A2A */ public class Client extends AbstractClient { @@ -256,7 +256,7 @@ public void sendMessage(@NonNull Message request, *

          • Blocking mode: Blocks until the agent completes the task, then invokes consumers
          • * * Streaming mode is active when both {@link ClientConfig#isStreaming()} AND - * {@link io.a2a.spec.AgentCapabilities#streaming()} are {@code true}. + * {@link org.a2aproject.sdk.spec.AgentCapabilities#streaming()} are {@code true}. *

            * Simple example: *

            {@code
            @@ -417,7 +417,7 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo
                  * Important notes:
                  * 
              *
            • Cancellation is a request, not a guarantee - agents may decline or be unable to cancel
            • - *
            • Some agents don't support cancellation and will return {@link io.a2a.spec.UnsupportedOperationError}
            • + *
            • Some agents don't support cancellation and will return {@link org.a2aproject.sdk.spec.UnsupportedOperationError}
            • *
            • Tasks in final states (COMPLETED, FAILED, CANCELED) cannot be canceled
            • *
            • The returned task will have state CANCELED if the cancellation succeeded
            • *
            @@ -443,8 +443,8 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo * @return the task with CANCELED status if successful * @throws A2AClientException if the task cannot be canceled or if a communication error occurs * @see TaskIdParams - * @see io.a2a.spec.UnsupportedOperationError - * @see io.a2a.spec.TaskNotFoundError + * @see org.a2aproject.sdk.spec.UnsupportedOperationError + * @see org.a2aproject.sdk.spec.TaskNotFoundError */ @Override public Task cancelTask(CancelTaskParams request, @Nullable ClientCallContext context) throws A2AClientException { @@ -571,7 +571,7 @@ public void deleteTaskPushNotificationConfigurations( *

            * Requirements: *

              - *
            • Both {@link ClientConfig#isStreaming()} and {@link io.a2a.spec.AgentCapabilities#streaming()} + *
            • Both {@link ClientConfig#isStreaming()} and {@link org.a2aproject.sdk.spec.AgentCapabilities#streaming()} * must be {@code true}
            • *
            • The task must still exist and not be in a final state (or the agent must support * historical event replay)
            • diff --git a/client/base/src/main/java/io/a2a/client/ClientBuilder.java b/client/base/src/main/java/org/a2aproject/sdk/client/ClientBuilder.java similarity index 96% rename from client/base/src/main/java/io/a2a/client/ClientBuilder.java rename to client/base/src/main/java/org/a2aproject/sdk/client/ClientBuilder.java index a383c5f21..42614c262 100644 --- a/client/base/src/main/java/io/a2a/client/ClientBuilder.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/ClientBuilder.java @@ -1,4 +1,4 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; import java.util.ArrayList; import java.util.HashMap; @@ -11,16 +11,16 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.client.transport.spi.ClientTransportConfigBuilder; -import io.a2a.client.transport.spi.ClientTransportProvider; -import io.a2a.client.transport.spi.ClientTransportWrapper; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfig; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.ClientTransportProvider; +import org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.TransportProtocol; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; @@ -96,7 +96,7 @@ * @see Client * @see ClientConfig * @see ClientEvent - * @see io.a2a.client.transport.spi.ClientTransport + * @see org.a2aproject.sdk.client.transport.spi.ClientTransport */ public class ClientBuilder { diff --git a/client/base/src/main/java/io/a2a/client/ClientEvent.java b/client/base/src/main/java/org/a2aproject/sdk/client/ClientEvent.java similarity index 98% rename from client/base/src/main/java/io/a2a/client/ClientEvent.java rename to client/base/src/main/java/org/a2aproject/sdk/client/ClientEvent.java index 2275a7f2e..6d4270ff2 100644 --- a/client/base/src/main/java/io/a2a/client/ClientEvent.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/ClientEvent.java @@ -1,4 +1,4 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; /** * A sealed interface representing events received by an A2A client from an agent. diff --git a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java b/client/base/src/main/java/org/a2aproject/sdk/client/ClientTaskManager.java similarity index 89% rename from client/base/src/main/java/io/a2a/client/ClientTaskManager.java rename to client/base/src/main/java/org/a2aproject/sdk/client/ClientTaskManager.java index e8e88eec4..94c9c21a5 100644 --- a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/ClientTaskManager.java @@ -1,21 +1,21 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; -import static io.a2a.util.Utils.appendArtifactToTask; +import static org.a2aproject.sdk.util.Utils.appendArtifactToTask; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientInvalidArgsError; -import io.a2a.spec.A2AClientInvalidStateError; -import io.a2a.spec.Message; -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 org.a2aproject.sdk.spec.A2AClientError; +import org.a2aproject.sdk.spec.A2AClientInvalidArgsError; +import org.a2aproject.sdk.spec.A2AClientInvalidStateError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.jspecify.annotations.Nullable; /** diff --git a/client/base/src/main/java/io/a2a/client/MessageEvent.java b/client/base/src/main/java/org/a2aproject/sdk/client/MessageEvent.java similarity index 95% rename from client/base/src/main/java/io/a2a/client/MessageEvent.java rename to client/base/src/main/java/org/a2aproject/sdk/client/MessageEvent.java index 1db7b39fd..62669f8f9 100644 --- a/client/base/src/main/java/io/a2a/client/MessageEvent.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/MessageEvent.java @@ -1,6 +1,6 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; -import io.a2a.spec.Message; +import org.a2aproject.sdk.spec.Message; /** * A client event containing an agent's message response. @@ -50,8 +50,8 @@ * * @see ClientEvent * @see Message - * @see io.a2a.spec.Part - * @see io.a2a.spec.TextPart + * @see org.a2aproject.sdk.spec.Part + * @see org.a2aproject.sdk.spec.TextPart */ public final class MessageEvent implements ClientEvent { diff --git a/client/base/src/main/java/io/a2a/client/TaskEvent.java b/client/base/src/main/java/org/a2aproject/sdk/client/TaskEvent.java similarity index 93% rename from client/base/src/main/java/io/a2a/client/TaskEvent.java rename to client/base/src/main/java/org/a2aproject/sdk/client/TaskEvent.java index 4da4ef04f..bf103bc02 100644 --- a/client/base/src/main/java/io/a2a/client/TaskEvent.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/TaskEvent.java @@ -1,8 +1,8 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; -import static io.a2a.util.Assert.checkNotNullParam; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; -import io.a2a.spec.Task; +import org.a2aproject.sdk.spec.Task; /** * A client event containing the complete state of a task. @@ -73,8 +73,8 @@ * @see ClientEvent * @see Task * @see TaskUpdateEvent - * @see io.a2a.spec.TaskState - * @see io.a2a.spec.TaskStatus + * @see org.a2aproject.sdk.spec.TaskState + * @see org.a2aproject.sdk.spec.TaskStatus */ public final class TaskEvent implements ClientEvent { diff --git a/client/base/src/main/java/io/a2a/client/TaskUpdateEvent.java b/client/base/src/main/java/org/a2aproject/sdk/client/TaskUpdateEvent.java similarity index 85% rename from client/base/src/main/java/io/a2a/client/TaskUpdateEvent.java rename to client/base/src/main/java/org/a2aproject/sdk/client/TaskUpdateEvent.java index e9efe2404..33cf20f1e 100644 --- a/client/base/src/main/java/io/a2a/client/TaskUpdateEvent.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/TaskUpdateEvent.java @@ -1,9 +1,9 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; -import static io.a2a.util.Assert.checkNotNullParam; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; -import io.a2a.spec.Task; -import io.a2a.spec.UpdateEvent; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.UpdateEvent; /** * A client event containing an incremental update to a task. @@ -14,8 +14,8 @@ *

              * Two types of updates: *

                - *
              • {@link io.a2a.spec.TaskStatusUpdateEvent} - task state changed (e.g., SUBMITTED → WORKING → COMPLETED)
              • - *
              • {@link io.a2a.spec.TaskArtifactUpdateEvent} - new content/results available
              • + *
              • {@link org.a2aproject.sdk.spec.TaskStatusUpdateEvent} - task state changed (e.g., SUBMITTED → WORKING → COMPLETED)
              • + *
              • {@link org.a2aproject.sdk.spec.TaskArtifactUpdateEvent} - new content/results available
              • *
              *

              * Streaming task lifecycle example: @@ -77,7 +77,7 @@ * TaskUpdateEvent event4 // task has status=COMPLETED, artifact=[chunk1, chunk2, final] * }

            *

            - * Artifact updates: When {@link io.a2a.spec.TaskArtifactUpdateEvent} is received, + * Artifact updates: When {@link org.a2aproject.sdk.spec.TaskArtifactUpdateEvent} is received, * the artifact may be: *

              *
            • Incremental: New parts appended to existing artifact (common for streaming text)
            • @@ -95,10 +95,10 @@ * * @see ClientEvent * @see Task - * @see io.a2a.spec.UpdateEvent - * @see io.a2a.spec.TaskStatusUpdateEvent - * @see io.a2a.spec.TaskArtifactUpdateEvent - * @see io.a2a.spec.TaskState + * @see org.a2aproject.sdk.spec.UpdateEvent + * @see org.a2aproject.sdk.spec.TaskStatusUpdateEvent + * @see org.a2aproject.sdk.spec.TaskArtifactUpdateEvent + * @see org.a2aproject.sdk.spec.TaskState */ public final class TaskUpdateEvent implements ClientEvent { @@ -141,8 +141,8 @@ public Task getTask() { *

              * This will be either: *

                - *
              • {@link io.a2a.spec.TaskStatusUpdateEvent} - indicates a state transition
              • - *
              • {@link io.a2a.spec.TaskArtifactUpdateEvent} - indicates new content available
              • + *
              • {@link org.a2aproject.sdk.spec.TaskStatusUpdateEvent} - indicates a state transition
              • + *
              • {@link org.a2aproject.sdk.spec.TaskArtifactUpdateEvent} - indicates new content available
              • *
              * * @return the update event diff --git a/client/base/src/main/java/io/a2a/client/config/ClientConfig.java b/client/base/src/main/java/org/a2aproject/sdk/client/config/ClientConfig.java similarity index 93% rename from client/base/src/main/java/io/a2a/client/config/ClientConfig.java rename to client/base/src/main/java/org/a2aproject/sdk/client/config/ClientConfig.java index 276a17194..b6c505490 100644 --- a/client/base/src/main/java/io/a2a/client/config/ClientConfig.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/config/ClientConfig.java @@ -1,11 +1,11 @@ -package io.a2a.client.config; +package org.a2aproject.sdk.client.config; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.jspecify.annotations.Nullable; /** @@ -133,8 +133,8 @@ * Thread safety: ClientConfig is immutable and thread-safe. Multiple clients can * share the same configuration instance. * - * @see io.a2a.client.Client - * @see io.a2a.client.ClientBuilder + * @see org.a2aproject.sdk.client.Client + * @see org.a2aproject.sdk.client.ClientBuilder * @see TaskPushNotificationConfig */ public class ClientConfig { @@ -161,7 +161,7 @@ private ClientConfig(Builder builder) { * Check if streaming mode is enabled. *

              * Note: Actual streaming requires both this configuration AND agent support - * ({@link io.a2a.spec.AgentCapabilities#streaming()}). + * ({@link org.a2aproject.sdk.spec.AgentCapabilities#streaming()}). * * @return {@code true} if streaming is enabled (default) */ @@ -186,11 +186,11 @@ public boolean isPolling() { * Check if client transport preference is enabled. *

              * When {@code true}, the client iterates through its configured transports (in the order - * they were added via {@link io.a2a.client.ClientBuilder#withTransport}) and selects the first one + * they were added via {@link org.a2aproject.sdk.client.ClientBuilder#withTransport}) and selects the first one * the agent supports. *

              * When {@code false} (default), the agent's preferred transport is used (first entry - * in {@link io.a2a.spec.AgentCard#supportedInterfaces()}). + * in {@link org.a2aproject.sdk.spec.AgentCard#supportedInterfaces()}). * * @return {@code true} if using client preference, {@code false} for server preference (default) */ @@ -220,7 +220,7 @@ public List getAcceptedOutputModes() { * calls unless overridden with a different configuration. * * @return the push notification config, or {@code null} if not configured - * @see io.a2a.client.Client#sendMessage(io.a2a.spec.Message, io.a2a.spec.TaskPushNotificationConfig, java.util.Map, io.a2a.client.transport.spi.interceptors.ClientCallContext) + * @see org.a2aproject.sdk.client.Client#sendMessage(org.a2aproject.sdk.spec.Message, org.a2aproject.sdk.spec.TaskPushNotificationConfig, java.util.Map, org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext) */ public @Nullable TaskPushNotificationConfig getTaskPushNotificationConfig() { return taskPushNotificationConfig; @@ -314,9 +314,9 @@ public Builder setPolling(@Nullable Boolean polling) { /** * Set whether to use client or server transport preference. *

              - * When {@code true}, the client's transport order (from {@link io.a2a.client.ClientBuilder#withTransport} + * When {@code true}, the client's transport order (from {@link org.a2aproject.sdk.client.ClientBuilder#withTransport} * calls) takes priority. When {@code false} (default), the server's preferred transport - * (first in {@link io.a2a.spec.AgentCard#supportedInterfaces()}) is used. + * (first in {@link org.a2aproject.sdk.spec.AgentCard#supportedInterfaces()}) is used. * * @param useClientPreference {@code true} for client preference, {@code false} for server preference (default) * @return this builder for method chaining @@ -350,7 +350,7 @@ public Builder setAcceptedOutputModes(List acceptedOutputModes) { * * @param taskPushNotificationConfig the push notification configuration * @return this builder for method chaining - * @see io.a2a.client.Client#sendMessage(io.a2a.spec.Message, io.a2a.spec.TaskPushNotificationConfig, java.util.Map, io.a2a.client.transport.spi.interceptors.ClientCallContext) + * @see org.a2aproject.sdk.client.Client#sendMessage(org.a2aproject.sdk.spec.Message, org.a2aproject.sdk.spec.TaskPushNotificationConfig, java.util.Map, org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext) */ public Builder setTaskPushNotificationConfig(TaskPushNotificationConfig taskPushNotificationConfig) { this.taskPushNotificationConfig = taskPushNotificationConfig; diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/package-info.java b/client/base/src/main/java/org/a2aproject/sdk/client/config/package-info.java similarity index 58% rename from client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/package-info.java rename to client/base/src/main/java/org/a2aproject/sdk/client/config/package-info.java index 3fc8e35ec..c3054ea3f 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/package-info.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/config/package-info.java @@ -1,5 +1,5 @@ @NullMarked -package io.a2a.client.transport.jsonrpc; +package org.a2aproject.sdk.client.config; import org.jspecify.annotations.NullMarked; diff --git a/common/src/main/java/io/a2a/common/package-info.java b/client/base/src/main/java/org/a2aproject/sdk/client/package-info.java similarity index 62% rename from common/src/main/java/io/a2a/common/package-info.java rename to client/base/src/main/java/org/a2aproject/sdk/client/package-info.java index f1c6af6c4..f011fe21a 100644 --- a/common/src/main/java/io/a2a/common/package-info.java +++ b/client/base/src/main/java/org/a2aproject/sdk/client/package-info.java @@ -1,5 +1,5 @@ @NullMarked -package io.a2a.common; +package org.a2aproject.sdk.client; import org.jspecify.annotations.NullMarked; diff --git a/client/base/src/test/java/io/a2a/A2ATest.java b/client/base/src/test/java/org/a2aproject/sdk/A2ATest.java similarity index 97% rename from client/base/src/test/java/io/a2a/A2ATest.java rename to client/base/src/test/java/org/a2aproject/sdk/A2ATest.java index 1052ad76d..5445c7a7f 100644 --- a/client/base/src/test/java/io/a2a/A2ATest.java +++ b/client/base/src/test/java/org/a2aproject/sdk/A2ATest.java @@ -1,4 +1,4 @@ -package io.a2a; +package org.a2aproject.sdk; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -8,9 +8,9 @@ import java.util.Collections; import java.util.List; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; public class A2ATest { diff --git a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java b/client/base/src/test/java/org/a2aproject/sdk/client/AuthenticationAuthorizationTest.java similarity index 92% rename from client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java rename to client/base/src/test/java/org/a2aproject/sdk/client/AuthenticationAuthorizationTest.java index 5d0e9b8e9..e00b886dd 100644 --- a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java +++ b/client/base/src/test/java/org/a2aproject/sdk/client/AuthenticationAuthorizationTest.java @@ -1,4 +1,4 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -12,25 +12,25 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfigBuilder; -import io.a2a.grpc.A2AServiceGrpc; -import io.a2a.grpc.SendMessageRequest; -import io.a2a.grpc.SendMessageResponse; -import io.a2a.grpc.StreamResponse; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.Message; -import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransport; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.grpc.A2AServiceGrpc; +import org.a2aproject.sdk.grpc.SendMessageRequest; +import org.a2aproject.sdk.grpc.SendMessageResponse; +import org.a2aproject.sdk.grpc.StreamResponse; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.TransportProtocol; import io.grpc.ManagedChannel; import io.grpc.Server; import io.grpc.Status; diff --git a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java b/client/base/src/test/java/org/a2aproject/sdk/client/ClientBuilderTest.java similarity index 90% rename from client/base/src/test/java/io/a2a/client/ClientBuilderTest.java rename to client/base/src/test/java/org/a2aproject/sdk/client/ClientBuilderTest.java index bea7c5823..8df595122 100644 --- a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java +++ b/client/base/src/test/java/org/a2aproject/sdk/client/ClientBuilderTest.java @@ -1,21 +1,21 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; import java.util.Collections; import java.util.List; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransport; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.TransportProtocol; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java b/client/base/src/test/java/org/a2aproject/sdk/client/ClientTaskManagerTest.java similarity index 93% rename from client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java rename to client/base/src/test/java/org/a2aproject/sdk/client/ClientTaskManagerTest.java index 74699b97e..82ddb3aaa 100644 --- a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java +++ b/client/base/src/test/java/org/a2aproject/sdk/client/ClientTaskManagerTest.java @@ -1,4 +1,4 @@ -package io.a2a.client; +package org.a2aproject.sdk.client; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -11,16 +11,16 @@ import java.util.List; import java.util.Map; -import io.a2a.spec.A2AClientInvalidArgsError; -import io.a2a.spec.A2AClientInvalidStateError; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -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.a2aproject.sdk.spec.A2AClientInvalidArgsError; +import org.a2aproject.sdk.spec.A2AClientInvalidStateError; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/EventStreamObserver.java similarity index 90% rename from client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java rename to client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/EventStreamObserver.java index 0c928bd75..aea664fc8 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java +++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/EventStreamObserver.java @@ -1,13 +1,13 @@ -package io.a2a.client.transport.grpc; +package org.a2aproject.sdk.client.transport.grpc; -import static io.a2a.grpc.utils.ProtoUtils.FromProto; +import static org.a2aproject.sdk.grpc.utils.ProtoUtils.FromProto; import java.util.function.Consumer; import java.util.logging.Logger; -import io.a2a.grpc.StreamResponse; -import io.a2a.spec.StreamingEventKind; +import org.a2aproject.sdk.grpc.StreamResponse; +import org.a2aproject.sdk.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/GrpcErrorMapper.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapper.java similarity index 85% rename from client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java rename to client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapper.java index 781242426..cbcb05752 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java +++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapper.java @@ -1,26 +1,26 @@ -package io.a2a.client.transport.grpc; +package org.a2aproject.sdk.client.transport.grpc; import java.util.HashMap; import java.util.Map; import com.google.protobuf.InvalidProtocolBufferException; import org.jspecify.annotations.Nullable; -import io.a2a.common.A2AErrorMessages; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.A2AErrorCodes; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -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 io.a2a.spec.VersionNotSupportedError; +import org.a2aproject.sdk.common.A2AErrorMessages; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AErrorCodes; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.InvalidAgentResponseError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; import io.grpc.Status; import io.grpc.protobuf.StatusProto; @@ -76,7 +76,7 @@ public static A2AClientException mapGrpcError(Throwable e, String errorPrefix) { case NOT_FOUND -> new A2AClientException(errorPrefix + desc, new TaskNotFoundError()); case UNIMPLEMENTED -> new A2AClientException(errorPrefix + desc, new UnsupportedOperationError()); case INVALID_ARGUMENT -> new A2AClientException(errorPrefix + desc, new InvalidParamsError()); - case INTERNAL -> new A2AClientException(errorPrefix + desc, new io.a2a.spec.InternalError(null, desc, null)); + case INTERNAL -> new A2AClientException(errorPrefix + desc, new org.a2aproject.sdk.spec.InternalError(null, desc, null)); case UNAUTHENTICATED -> new A2AClientException(errorPrefix + A2AErrorMessages.AUTHENTICATION_FAILED); case PERMISSION_DENIED -> new A2AClientException(errorPrefix + A2AErrorMessages.AUTHORIZATION_FAILED); default -> new A2AClientException(errorPrefix + e.getMessage(), e); @@ -117,7 +117,7 @@ private static A2AClientException mapByErrorCode(A2AErrorCodes errorCode, String case JSON_PARSE -> new A2AClientException(fullMessage, new JSONParseError(null, errorMessage, metadata)); case METHOD_NOT_FOUND -> new A2AClientException(fullMessage, new MethodNotFoundError(null, errorMessage, metadata)); case INVALID_PARAMS -> new A2AClientException(fullMessage, new InvalidParamsError(null, errorMessage, metadata)); - case INTERNAL -> new A2AClientException(fullMessage, new io.a2a.spec.InternalError(null, errorMessage, metadata)); + case INTERNAL -> new A2AClientException(fullMessage, new org.a2aproject.sdk.spec.InternalError(null, errorMessage, metadata)); }; } } diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransport.java similarity index 78% rename from client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java rename to client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransport.java index 802b9c0e6..f7f07b0f9 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java +++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransport.java @@ -1,52 +1,52 @@ -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_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; +package org.a2aproject.sdk.client.transport.grpc; + +import static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; import java.util.List; import java.util.Map; import java.util.function.Consumer; import java.util.stream.Collectors; -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; -import io.a2a.common.A2AHeaders; -import io.a2a.grpc.A2AServiceGrpc; -import io.a2a.grpc.A2AServiceGrpc.A2AServiceBlockingV2Stub; -import io.a2a.grpc.A2AServiceGrpc.A2AServiceStub; -import io.a2a.grpc.GetExtendedAgentCardRequest; -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.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor; +import org.a2aproject.sdk.client.transport.spi.interceptors.PayloadAndHeaders; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.common.A2AHeaders; +import org.a2aproject.sdk.grpc.A2AServiceGrpc; +import org.a2aproject.sdk.grpc.A2AServiceGrpc.A2AServiceBlockingV2Stub; +import org.a2aproject.sdk.grpc.A2AServiceGrpc.A2AServiceStub; +import org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest; +import org.a2aproject.sdk.grpc.utils.ProtoUtils.FromProto; +import org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; import io.grpc.Channel; import io.grpc.Metadata; import io.grpc.StatusException; @@ -101,13 +101,13 @@ public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallCont checkNotNullParam("request", request); MessageSendParams tenantRequest = createRequestWithTenant(request); - io.a2a.grpc.SendMessageRequest sendMessageRequest = createGrpcSendMessageRequest(tenantRequest, context); + org.a2aproject.sdk.grpc.SendMessageRequest sendMessageRequest = createGrpcSendMessageRequest(tenantRequest, context); PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_MESSAGE_METHOD, sendMessageRequest, agentCard, context); try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - io.a2a.grpc.SendMessageResponse response = stubWithMetadata.sendMessage(sendMessageRequest); + org.a2aproject.sdk.grpc.SendMessageResponse response = stubWithMetadata.sendMessage(sendMessageRequest); if (response.hasMessage()) { return FromProto.message(response.getMessage()); } else if (response.hasTask()) { @@ -127,10 +127,10 @@ public void sendMessageStreaming(MessageSendParams request, Consumer streamObserver = new EventStreamObserver(eventConsumer, errorConsumer); + StreamObserver streamObserver = new EventStreamObserver(eventConsumer, errorConsumer); try { A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders); @@ -143,13 +143,13 @@ public void sendMessageStreaming(MessageSendParams request, Consumer e checkNotNullParam("request", request); checkNotNullParam("eventConsumer", eventConsumer); - io.a2a.grpc.SubscribeToTaskRequest grpcRequest = io.a2a.grpc.SubscribeToTaskRequest.newBuilder() + org.a2aproject.sdk.grpc.SubscribeToTaskRequest grpcRequest = org.a2aproject.sdk.grpc.SubscribeToTaskRequest.newBuilder() .setTenant(resolveTenant(request.tenant())) .setId(request.id()) .build(); PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, grpcRequest, agentCard, context); - StreamObserver streamObserver = new EventStreamObserver(eventConsumer, errorConsumer); + StreamObserver streamObserver = new EventStreamObserver(eventConsumer, errorConsumer); try { A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders); @@ -362,7 +362,7 @@ public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullab try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - io.a2a.grpc.AgentCard response = stubWithMetadata.getExtendedAgentCard(request); + org.a2aproject.sdk.grpc.AgentCard response = stubWithMetadata.getExtendedAgentCard(request); return FromProto.agentCard(response); } catch (StatusRuntimeException | StatusException e) { @@ -374,7 +374,7 @@ public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullab public void close() { } - private io.a2a.grpc.SendMessageRequest createGrpcSendMessageRequest(MessageSendParams messageSendParams, @Nullable ClientCallContext context) { + private org.a2aproject.sdk.grpc.SendMessageRequest createGrpcSendMessageRequest(MessageSendParams messageSendParams, @Nullable ClientCallContext context) { return ToProto.sendMessageRequest(messageSendParams); } diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportConfig.java similarity index 94% rename from client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java rename to client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportConfig.java index 605f7abb0..90d00efbe 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java +++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportConfig.java @@ -1,9 +1,9 @@ -package io.a2a.client.transport.grpc; +package org.a2aproject.sdk.client.transport.grpc; import java.util.function.Function; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.util.Assert; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfig; +import org.a2aproject.sdk.util.Assert; import io.grpc.Channel; /** @@ -81,7 +81,7 @@ * * @see GrpcTransportConfigBuilder * @see GrpcTransport - * @see io.a2a.client.transport.spi.ClientTransportConfig + * @see org.a2aproject.sdk.client.transport.spi.ClientTransportConfig * @see io.grpc.ManagedChannelBuilder */ public class GrpcTransportConfig extends ClientTransportConfig { diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportConfigBuilder.java similarity index 96% rename from client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java rename to client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportConfigBuilder.java index 9ffcc1285..1bafe78df 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java +++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportConfigBuilder.java @@ -1,9 +1,9 @@ -package io.a2a.client.transport.grpc; +package org.a2aproject.sdk.client.transport.grpc; import java.util.function.Function; -import io.a2a.client.transport.spi.ClientTransportConfigBuilder; -import io.a2a.util.Assert; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfigBuilder; +import org.a2aproject.sdk.util.Assert; import io.grpc.Channel; import org.jspecify.annotations.Nullable; @@ -141,7 +141,7 @@ * * @see GrpcTransportConfig * @see GrpcTransport - * @see io.a2a.client.transport.spi.ClientTransportConfigBuilder + * @see org.a2aproject.sdk.client.transport.spi.ClientTransportConfigBuilder * @see io.grpc.ManagedChannelBuilder * @see io.grpc.Channel */ diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportProvider.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportProvider.java similarity index 76% rename from client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportProvider.java rename to client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportProvider.java index d331d0874..c2e469554 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportProvider.java +++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransportProvider.java @@ -1,10 +1,10 @@ -package io.a2a.client.transport.grpc; +package org.a2aproject.sdk.client.transport.grpc; -import io.a2a.client.transport.spi.ClientTransportProvider; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.transport.spi.ClientTransportProvider; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.TransportProtocol; import io.grpc.Channel; /** diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/package-info.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/package-info.java similarity index 52% rename from client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/package-info.java rename to client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/package-info.java index c0c12ccb5..fe7e81954 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/package-info.java +++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/package-info.java @@ -1,4 +1,4 @@ @NullMarked -package io.a2a.client.transport.grpc; +package org.a2aproject.sdk.client.transport.grpc; import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/client/transport/grpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider b/client/transport/grpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider deleted file mode 100644 index 86d4fa7e5..000000000 --- a/client/transport/grpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.transport.grpc.GrpcTransportProvider \ No newline at end of file diff --git a/client/transport/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider b/client/transport/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider new file mode 100644 index 000000000..6ab71249f --- /dev/null +++ b/client/transport/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider @@ -0,0 +1 @@ +org.a2aproject.sdk.client.transport.grpc.GrpcTransportProvider \ No newline at end of file diff --git a/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java b/client/transport/grpc/src/test/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapperTest.java similarity index 93% rename from client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java rename to client/transport/grpc/src/test/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapperTest.java index 151ca7b91..421d92cbb 100644 --- a/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java +++ b/client/transport/grpc/src/test/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapperTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.grpc; +package org.a2aproject.sdk.client.transport.grpc; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -6,14 +6,14 @@ import com.google.protobuf.Any; import com.google.rpc.ErrorInfo; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.protobuf.StatusProto; diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/package-info.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/package-info.java deleted file mode 100644 index 956b8992a..000000000 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.jsonrpc.sse; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java similarity index 82% rename from client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java rename to client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java index 63100ee09..070f564e5 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java @@ -1,17 +1,17 @@ -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; +package org.a2aproject.sdk.client.transport.jsonrpc; + +import static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; import java.io.IOException; import java.util.List; @@ -22,48 +22,48 @@ import com.google.protobuf.MessageOrBuilder; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.client.transport.jsonrpc.sse.SSEEventListener; -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.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -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.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; -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.CreateTaskPushNotificationConfigResponse; -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.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.util.Utils; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.transport.jsonrpc.sse.SSEEventListener; +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor; +import org.a2aproject.sdk.client.transport.spi.interceptors.PayloadAndHeaders; +import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.spec.A2AClientError; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; public class JSONRPCTransport implements ClientTransport { diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportConfig.java similarity index 91% rename from client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java rename to client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportConfig.java index 909ff079e..dab1da283 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportConfig.java @@ -1,7 +1,7 @@ -package io.a2a.client.transport.jsonrpc; +package org.a2aproject.sdk.client.transport.jsonrpc; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.transport.spi.ClientTransportConfig; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfig; import org.jspecify.annotations.Nullable; /** @@ -46,7 +46,7 @@ * @see JSONRPCTransportConfigBuilder * @see JSONRPCTransport * @see A2AHttpClient - * @see io.a2a.client.http.JdkA2AHttpClient + * @see org.a2aproject.sdk.client.http.JdkA2AHttpClient */ public class JSONRPCTransportConfig extends ClientTransportConfig { diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java similarity index 92% rename from client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java rename to client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java index 7f73b4c2d..43b7126f5 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java @@ -1,8 +1,8 @@ -package io.a2a.client.transport.jsonrpc; +package org.a2aproject.sdk.client.transport.jsonrpc; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.spi.ClientTransportConfigBuilder; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfigBuilder; import org.jspecify.annotations.Nullable; /** @@ -60,7 +60,7 @@ * @see JSONRPCTransportConfig * @see JSONRPCTransport * @see A2AHttpClient - * @see io.a2a.client.http.JdkA2AHttpClient + * @see org.a2aproject.sdk.client.http.JdkA2AHttpClient */ public class JSONRPCTransportConfigBuilder extends ClientTransportConfigBuilder { diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportProvider.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportProvider.java similarity index 72% rename from client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportProvider.java rename to client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportProvider.java index 2dc1a9733..0b36fd083 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportProvider.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportProvider.java @@ -1,11 +1,11 @@ -package io.a2a.client.transport.jsonrpc; +package org.a2aproject.sdk.client.transport.jsonrpc; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.spi.ClientTransportProvider; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.transport.spi.ClientTransportProvider; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.TransportProtocol; import org.jspecify.annotations.Nullable; public class JSONRPCTransportProvider implements ClientTransportProvider { diff --git a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/package-info.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/package-info.java new file mode 100644 index 000000000..7c5ca35e2 --- /dev/null +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.client.transport.jsonrpc; + +import org.jspecify.annotations.NullMarked; + diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListener.java similarity index 84% rename from client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java rename to client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListener.java index 2c61d082e..9afb5dec3 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListener.java @@ -1,16 +1,16 @@ -package io.a2a.client.transport.jsonrpc.sse; +package org.a2aproject.sdk.client.transport.jsonrpc.sse; import java.util.concurrent.Future; import java.util.function.Consumer; import java.util.logging.Logger; -import io.a2a.client.transport.spi.sse.AbstractSSEEventListener; -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 org.a2aproject.sdk.client.transport.spi.sse.AbstractSSEEventListener; +import org.a2aproject.sdk.grpc.StreamResponse; +import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.StreamingEventKind; import org.jspecify.annotations.Nullable; /** diff --git a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/package-info.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/package-info.java new file mode 100644 index 000000000..8943e1130 --- /dev/null +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.client.transport.jsonrpc.sse; + +import org.jspecify.annotations.NullMarked; + diff --git a/client/transport/jsonrpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider b/client/transport/jsonrpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider deleted file mode 100644 index b2904cb45..000000000 --- a/client/transport/jsonrpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.transport.jsonrpc.JSONRPCTransportProvider \ No newline at end of file diff --git a/client/transport/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider b/client/transport/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider new file mode 100644 index 000000000..4aa0f4ea5 --- /dev/null +++ b/client/transport/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider @@ -0,0 +1 @@ +org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportProvider \ No newline at end of file diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java similarity index 86% rename from client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java rename to client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java index 594eac974..368647ae1 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java @@ -1,9 +1,9 @@ -package io.a2a.client.transport.jsonrpc; +package org.a2aproject.sdk.client.transport.jsonrpc; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.SEND_MESSAGE_STREAMING_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.SEND_MESSAGE_STREAMING_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.TASK_SUBSCRIPTION_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.TASK_SUBSCRIPTION_REQUEST_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonStreamingMessages.SEND_MESSAGE_STREAMING_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonStreamingMessages.SEND_MESSAGE_STREAMING_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonStreamingMessages.TASK_SUBSCRIPTION_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonStreamingMessages.TASK_SUBSCRIPTION_REQUEST_TEST_RESPONSE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -18,16 +18,16 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Part; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.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/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportTest.java similarity index 88% rename from client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java rename to client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportTest.java index 55c20bc55..93c391aa2 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -1,28 +1,28 @@ -package io.a2a.client.transport.jsonrpc; - -import static io.a2a.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_TASK_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_TASK_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_ERROR_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_ERROR_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; +package org.a2aproject.sdk.client.transport.jsonrpc; + +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.GET_TASK_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.GET_TASK_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_ERROR_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_ERROR_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.jsonrpc.JsonMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -37,35 +37,35 @@ import java.util.List; import java.util.Map; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.VersionNotSupportedError; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.Artifact; -import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.DataPart; -import io.a2a.spec.EventKind; -import io.a2a.spec.FileContent; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.Part; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.SecurityScheme; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; -import io.a2a.util.Utils; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.AuthenticationInfo; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.FileContent; +import org.a2aproject.sdk.spec.FilePart; +import org.a2aproject.sdk.spec.FileWithBytes; +import org.a2aproject.sdk.spec.FileWithUri; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.SecurityRequirement; +import org.a2aproject.sdk.spec.SecurityScheme; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.util.Utils; 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/org/a2aproject/sdk/client/transport/jsonrpc/JsonMessages.java similarity index 99% rename from client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java rename to client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonMessages.java index a0be30e0d..e71e6b3b4 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonMessages.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.jsonrpc; +package org.a2aproject.sdk.client.transport.jsonrpc; /** * Request and response messages used by the tests. These have been created following examples from diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonStreamingMessages.java similarity index 98% rename from client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java rename to client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonStreamingMessages.java index df6fee000..7b36552b9 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonStreamingMessages.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.jsonrpc; +package org.a2aproject.sdk.client.transport.jsonrpc; /** * Contains JSON strings for testing SSE streaming. diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java similarity index 95% rename from client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java rename to client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java index 389c7df8d..6b95de871 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.jsonrpc.sse; +package org.a2aproject.sdk.client.transport.jsonrpc.sse; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -13,17 +13,17 @@ import java.util.concurrent.atomic.AtomicBoolean; 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.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.a2aproject.sdk.client.transport.jsonrpc.JsonStreamingMessages; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; public class SSEEventListenerTest { diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/package-info.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/package-info.java deleted file mode 100644 index e1bb6c3b2..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.rest.sse; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestErrorMapper.java similarity index 71% rename from client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java rename to client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestErrorMapper.java index 009255f66..eee28300e 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestErrorMapper.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.rest; +package org.a2aproject.sdk.client.transport.rest; import java.util.HashMap; import java.util.Map; @@ -6,25 +6,25 @@ import java.util.logging.Logger; import com.google.gson.JsonObject; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.A2AErrorCodes; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -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 io.a2a.spec.VersionNotSupportedError; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AErrorCodes; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidAgentResponseError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; /** * Utility class to A2AHttpResponse to appropriate A2A error types @@ -143,20 +143,20 @@ private static A2AClientException mapRestErrorByReason(String reason, String err private static A2AClientException mapRestErrorByClassName(String className, String errorMessage, int code) { return switch (className) { - case "io.a2a.spec.TaskNotFoundError" -> new A2AClientException(errorMessage, new TaskNotFoundError()); - case "io.a2a.spec.ExtendedCardNotConfiguredError" -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, null)); - case "io.a2a.spec.ContentTypeNotSupportedError" -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, errorMessage, null)); - case "io.a2a.spec.InternalError" -> new A2AClientException(errorMessage, new InternalError(errorMessage)); - case "io.a2a.spec.InvalidAgentResponseError" -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, errorMessage, null)); - case "io.a2a.spec.InvalidParamsError" -> new A2AClientException(errorMessage, new InvalidParamsError()); - case "io.a2a.spec.InvalidRequestError" -> new A2AClientException(errorMessage, new InvalidRequestError()); - case "io.a2a.spec.JSONParseError" -> new A2AClientException(errorMessage, new JSONParseError()); - case "io.a2a.spec.MethodNotFoundError" -> new A2AClientException(errorMessage, new MethodNotFoundError()); - case "io.a2a.spec.PushNotificationNotSupportedError" -> new A2AClientException(errorMessage, new PushNotificationNotSupportedError()); - case "io.a2a.spec.TaskNotCancelableError" -> new A2AClientException(errorMessage, new TaskNotCancelableError()); - case "io.a2a.spec.UnsupportedOperationError" -> new A2AClientException(errorMessage, new UnsupportedOperationError()); - case "io.a2a.spec.ExtensionSupportRequiredError" -> new A2AClientException(errorMessage, new ExtensionSupportRequiredError(null, errorMessage, null)); - case "io.a2a.spec.VersionNotSupportedError" -> new A2AClientException(errorMessage, new VersionNotSupportedError(null, errorMessage, null)); + case "org.a2aproject.sdk.spec.TaskNotFoundError" -> new A2AClientException(errorMessage, new TaskNotFoundError()); + case "org.a2aproject.sdk.spec.ExtendedCardNotConfiguredError" -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, null)); + case "org.a2aproject.sdk.spec.ContentTypeNotSupportedError" -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, errorMessage, null)); + case "org.a2aproject.sdk.spec.InternalError" -> new A2AClientException(errorMessage, new InternalError(errorMessage)); + case "org.a2aproject.sdk.spec.InvalidAgentResponseError" -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, errorMessage, null)); + case "org.a2aproject.sdk.spec.InvalidParamsError" -> new A2AClientException(errorMessage, new InvalidParamsError()); + case "org.a2aproject.sdk.spec.InvalidRequestError" -> new A2AClientException(errorMessage, new InvalidRequestError()); + case "org.a2aproject.sdk.spec.JSONParseError" -> new A2AClientException(errorMessage, new JSONParseError()); + case "org.a2aproject.sdk.spec.MethodNotFoundError" -> new A2AClientException(errorMessage, new MethodNotFoundError()); + case "org.a2aproject.sdk.spec.PushNotificationNotSupportedError" -> new A2AClientException(errorMessage, new PushNotificationNotSupportedError()); + case "org.a2aproject.sdk.spec.TaskNotCancelableError" -> new A2AClientException(errorMessage, new TaskNotCancelableError()); + case "org.a2aproject.sdk.spec.UnsupportedOperationError" -> new A2AClientException(errorMessage, new UnsupportedOperationError()); + case "org.a2aproject.sdk.spec.ExtensionSupportRequiredError" -> new A2AClientException(errorMessage, new ExtensionSupportRequiredError(null, errorMessage, null)); + case "org.a2aproject.sdk.spec.VersionNotSupportedError" -> new A2AClientException(errorMessage, new VersionNotSupportedError(null, errorMessage, null)); default -> new A2AClientException(errorMessage); }; } diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java similarity index 80% rename from client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java rename to client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java index bdb26b830..0768a3bf9 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java @@ -1,17 +1,17 @@ -package io.a2a.client.transport.rest; +package org.a2aproject.sdk.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 static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; import java.io.IOException; import java.net.URLEncoder; @@ -27,37 +27,37 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.util.JsonFormat; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.client.transport.rest.sse.SSEEventListener; -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.grpc.utils.ProtoUtils; -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.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.util.Utils; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.transport.rest.sse.SSEEventListener; +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor; +import org.a2aproject.sdk.client.transport.spi.interceptors.PayloadAndHeaders; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.A2AClientError; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; public class RestTransport implements ClientTransport { @@ -83,11 +83,11 @@ public RestTransport(@Nullable A2AHttpClient httpClient, AgentCard agentCard, @Override 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)); + org.a2aproject.sdk.grpc.SendMessageRequest.Builder builder = org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder(ProtoUtils.ToProto.sendMessageRequest(messageSendParams)); 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(); + org.a2aproject.sdk.grpc.SendMessageResponse.Builder responseBuilder = org.a2aproject.sdk.grpc.SendMessageResponse.newBuilder(); JsonFormat.parser().merge(httpResponseBody, responseBuilder); if (responseBuilder.hasMessage()) { return ProtoUtils.FromProto.message(responseBuilder.getMessage()); @@ -108,7 +108,7 @@ public void sendMessageStreaming(MessageSendParams messageSendParams, Consumer> ref = new AtomicReference<>(); SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); @@ -132,7 +132,7 @@ public void sendMessageStreaming(MessageSendParams messageSendParams, Consumer eventConsumer, Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - io.a2a.grpc.SubscribeToTaskRequest.Builder builder = io.a2a.grpc.SubscribeToTaskRequest.newBuilder(); + org.a2aproject.sdk.grpc.SubscribeToTaskRequest.Builder builder = org.a2aproject.sdk.grpc.SubscribeToTaskRequest.newBuilder(); builder.setId(request.id()); PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, builder, agentCard, context); diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportConfig.java similarity index 91% rename from client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java rename to client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportConfig.java index e78c67271..69e8afe34 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportConfig.java @@ -1,7 +1,7 @@ -package io.a2a.client.transport.rest; +package org.a2aproject.sdk.client.transport.rest; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.transport.spi.ClientTransportConfig; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfig; import org.jspecify.annotations.Nullable; /** @@ -46,7 +46,7 @@ * @see RestTransportConfigBuilder * @see RestTransport * @see A2AHttpClient - * @see io.a2a.client.http.JdkA2AHttpClient + * @see org.a2aproject.sdk.client.http.JdkA2AHttpClient */ public class RestTransportConfig extends ClientTransportConfig { diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfigBuilder.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportConfigBuilder.java similarity index 92% rename from client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfigBuilder.java rename to client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportConfigBuilder.java index 257836199..dc63d11f4 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfigBuilder.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportConfigBuilder.java @@ -1,8 +1,8 @@ -package io.a2a.client.transport.rest; +package org.a2aproject.sdk.client.transport.rest; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.spi.ClientTransportConfigBuilder; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfigBuilder; import org.jspecify.annotations.Nullable; /** @@ -60,7 +60,7 @@ * @see RestTransportConfig * @see RestTransport * @see A2AHttpClient - * @see io.a2a.client.http.JdkA2AHttpClient + * @see org.a2aproject.sdk.client.http.JdkA2AHttpClient */ public class RestTransportConfigBuilder extends ClientTransportConfigBuilder { diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportProvider.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportProvider.java similarity index 69% rename from client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportProvider.java rename to client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportProvider.java index b6e6d7a47..cdc480684 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportProvider.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransportProvider.java @@ -1,11 +1,11 @@ -package io.a2a.client.transport.rest; +package org.a2aproject.sdk.client.transport.rest; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.spi.ClientTransportProvider; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.transport.spi.ClientTransportProvider; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.TransportProtocol; public class RestTransportProvider implements ClientTransportProvider { diff --git a/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/package-info.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/package-info.java new file mode 100644 index 000000000..b50c9a0a8 --- /dev/null +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.client.transport.rest; + +import org.jspecify.annotations.NullMarked; + diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListener.java similarity index 85% rename from client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java rename to client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListener.java index 2c9167b63..850a8718f 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListener.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.rest.sse; +package org.a2aproject.sdk.client.transport.rest.sse; import java.util.concurrent.Future; import java.util.function.Consumer; @@ -6,11 +6,11 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; -import io.a2a.client.transport.spi.sse.AbstractSSEEventListener; -import io.a2a.client.transport.rest.RestErrorMapper; -import io.a2a.grpc.StreamResponse; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.spec.StreamingEventKind; +import org.a2aproject.sdk.client.transport.spi.sse.AbstractSSEEventListener; +import org.a2aproject.sdk.client.transport.rest.RestErrorMapper; +import org.a2aproject.sdk.grpc.StreamResponse; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.spec.StreamingEventKind; import org.jspecify.annotations.Nullable; /** @@ -30,7 +30,7 @@ public SSEEventListener(Consumer eventHandler, public void onMessage(String message, @Nullable Future completableFuture) { try { log.fine("Streaming message received: " + message); - io.a2a.grpc.StreamResponse.Builder builder = io.a2a.grpc.StreamResponse.newBuilder(); + org.a2aproject.sdk.grpc.StreamResponse.Builder builder = org.a2aproject.sdk.grpc.StreamResponse.newBuilder(); JsonFormat.parser().merge(message, builder); parseAndHandleMessage(builder.build(), completableFuture); } catch (InvalidProtocolBufferException e) { diff --git a/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/package-info.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/package-info.java new file mode 100644 index 000000000..a308a0597 --- /dev/null +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.client.transport.rest.sse; + +import org.jspecify.annotations.NullMarked; + diff --git a/client/transport/rest/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider b/client/transport/rest/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider deleted file mode 100644 index 894866aab..000000000 --- a/client/transport/rest/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.transport.rest.RestTransportProvider \ No newline at end of file diff --git a/client/transport/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider b/client/transport/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider new file mode 100644 index 000000000..7077edc10 --- /dev/null +++ b/client/transport/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportProvider @@ -0,0 +1 @@ +org.a2aproject.sdk.client.transport.rest.RestTransportProvider \ No newline at end of file diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java b/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/JsonRestMessages.java similarity index 99% rename from client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java rename to client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/JsonRestMessages.java index b9a6527e0..4a77b0140 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java +++ b/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/JsonRestMessages.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.rest; +package org.a2aproject.sdk.client.transport.rest; /** * Request and response messages used by the tests. These have been created following examples from diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/RestTransportTest.java similarity index 87% rename from client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java rename to client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/RestTransportTest.java index a7f041237..f106e4b98 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ b/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/RestTransportTest.java @@ -1,18 +1,18 @@ -package io.a2a.client.transport.rest; - - -import static io.a2a.client.transport.rest.JsonRestMessages.CANCEL_TASK_TEST_REQUEST; -import static io.a2a.client.transport.rest.JsonRestMessages.CANCEL_TASK_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.GET_TASK_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.SEND_MESSAGE_STREAMING_TEST_REQUEST; -import static io.a2a.client.transport.rest.JsonRestMessages.SEND_MESSAGE_STREAMING_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.SEND_MESSAGE_TEST_REQUEST; -import static io.a2a.client.transport.rest.JsonRestMessages.SEND_MESSAGE_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; -import static io.a2a.client.transport.rest.JsonRestMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE; +package org.a2aproject.sdk.client.transport.rest; + + +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.CANCEL_TASK_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.CANCEL_TASK_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.GET_TASK_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.SEND_MESSAGE_STREAMING_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.SEND_MESSAGE_STREAMING_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.SEND_MESSAGE_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.SEND_MESSAGE_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.client.transport.rest.JsonRestMessages.TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -30,35 +30,35 @@ import java.util.function.Consumer; import java.util.logging.Logger; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.Artifact; -import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.VersionNotSupportedError; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Part; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.AuthenticationInfo; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; +import org.a2aproject.sdk.spec.FilePart; +import org.a2aproject.sdk.spec.FileWithBytes; +import org.a2aproject.sdk.spec.FileWithUri; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -73,7 +73,7 @@ public class RestTransportTest { private static final AgentCard CARD = AgentCard.builder() .name("Hello World Agent") .description("Just a hello world agent") - .supportedInterfaces(Collections.singletonList(new io.a2a.spec.AgentInterface("HTTP+JSON", "http://localhost:4001"))) + .supportedInterfaces(Collections.singletonList(new org.a2aproject.sdk.spec.AgentInterface("HTTP+JSON", "http://localhost:4001"))) .version("1.0.0") .documentationUrl("http://example.com/docs") .capabilities(AgentCapabilities.builder() @@ -148,7 +148,7 @@ public void testSendMessage() throws Exception { assertEquals("message-1234", history.messageId()); assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", history.taskId()); assertEquals(1, history.parts().size()); - assertTrue(history.parts().get(0) instanceof io.a2a.spec.TextPart); + assertTrue(history.parts().get(0) instanceof org.a2aproject.sdk.spec.TextPart); assertEquals("tell me a joke", ((TextPart) history.parts().get(0)).text()); assertNull(task.metadata()); assertNull(history.referenceTaskIds()); @@ -210,7 +210,7 @@ public void testGetTask() throws Exception { assertEquals("artifact-1", artifact.artifactId()); assertNull(artifact.name()); assertEquals(false, artifact.parts().isEmpty()); - assertTrue(artifact.parts().get(0) instanceof io.a2a.spec.TextPart); + assertTrue(artifact.parts().get(0) instanceof org.a2aproject.sdk.spec.TextPart); assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) artifact.parts().get(0)).text()); assertEquals(1, task.history().size()); Message history = task.history().get(0); @@ -218,7 +218,7 @@ public void testGetTask() throws Exception { assertEquals(Message.Role.ROLE_USER, history.role()); assertEquals("message-123", history.messageId()); assertEquals(3, history.parts().size()); - assertTrue(history.parts().get(0) instanceof io.a2a.spec.TextPart); + assertTrue(history.parts().get(0) instanceof org.a2aproject.sdk.spec.TextPart); assertEquals("tell me a joke", ((TextPart) history.parts().get(0)).text()); assertTrue(history.parts().get(1) instanceof FilePart); FilePart part = (FilePart) history.parts().get(1); @@ -442,7 +442,7 @@ public void testSubscribe() throws Exception { assertEquals("artifact-1", artifact.artifactId()); assertEquals("joke", artifact.name()); Part part = artifact.parts().get(0); - assertTrue(part instanceof io.a2a.spec.TextPart); + assertTrue(part instanceof org.a2aproject.sdk.spec.TextPart); assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) part).text()); } @@ -456,7 +456,7 @@ public void testExtensionSupportRequiredErrorUnmarshalling() throws Exception { // Mock server returns HTTP 400 with ExtensionSupportRequiredError String errorResponseBody = """ { - "error": "io.a2a.spec.ExtensionSupportRequiredError", + "error": "org.a2aproject.sdk.spec.ExtensionSupportRequiredError", "message": "Extension required: https://example.com/test-extension" } """; @@ -504,7 +504,7 @@ public void testVersionNotSupportedErrorUnmarshalling() throws Exception { // Mock server returns HTTP 501 with VersionNotSupportedError String errorResponseBody = """ { - "error": "io.a2a.spec.VersionNotSupportedError", + "error": "org.a2aproject.sdk.spec.VersionNotSupportedError", "message": "Protocol version 2.0 is not supported. This agent supports version 1.0" } """; @@ -552,7 +552,7 @@ public void testVersionNotSupportedErrorUnmarshallingStreaming() throws Exceptio // Mock server returns HTTP 200 with error event in SSE stream String streamResponseBody = """ - data: {"kind":"error","error":"io.a2a.spec.VersionNotSupportedError","message":"Protocol version 2.0 is not supported. This agent supports version 1.0"} + data: {"kind":"error","error":"org.a2aproject.sdk.spec.VersionNotSupportedError","message":"Protocol version 2.0 is not supported. This agent supports version 1.0"} """; diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java b/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListenerTest.java similarity index 97% rename from client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java rename to client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListenerTest.java index d208f25c3..1fc2683e8 100644 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java +++ b/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListenerTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.rest.sse; +package org.a2aproject.sdk.client.transport.rest.sse; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -9,12 +9,12 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; /** diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/package-info.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/package-info.java deleted file mode 100644 index 85b061333..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.spi.interceptors.auth; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/package-info.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/package-info.java deleted file mode 100644 index d85534d28..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.spi.interceptors; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java deleted file mode 100644 index 1083bc32e..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.spi.sse; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransport.java similarity index 86% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransport.java index cd63dadfb..0e3d9bf82 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransport.java @@ -1,25 +1,25 @@ -package io.a2a.client.transport.spi; +package org.a2aproject.sdk.client.transport.spi; 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.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; import org.jspecify.annotations.Nullable; /** diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransportConfig.java similarity index 94% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransportConfig.java index f93954b40..aa18bb656 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransportConfig.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.spi; +package org.a2aproject.sdk.client.transport.spi; import java.util.ArrayList; @@ -6,7 +6,7 @@ import java.util.List; import java.util.Map; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor; import java.util.Collections; /** @@ -34,7 +34,7 @@ * * @param the transport type this configuration is for * @see ClientTransportConfigBuilder - * @see io.a2a.client.transport.spi.interceptors.ClientCallInterceptor + * @see org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor */ public abstract class ClientTransportConfig { diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransportConfigBuilder.java similarity index 91% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransportConfigBuilder.java index fabdab765..ffcf78920 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/ClientTransportConfigBuilder.java @@ -1,9 +1,9 @@ -package io.a2a.client.transport.spi; +package org.a2aproject.sdk.client.transport.spi; import java.util.ArrayList; import java.util.List; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor; /** * Base builder class for constructing transport configuration instances. @@ -32,7 +32,7 @@ * @param the transport configuration type this builder creates * @param the concrete builder type (for method chaining) * @see ClientTransportConfig - * @see io.a2a.client.transport.spi.interceptors.ClientCallInterceptor + * @see org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor */ public abstract class ClientTransportConfigBuilder, B extends ClientTransportConfigBuilder> { @@ -64,7 +64,7 @@ public abstract class ClientTransportConfigBuilderWrappers are discovered via Java's ServiceLoader mechanism. To register a wrapper, - * create a file {@code META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper} + * create a file {@code META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper} * containing the fully qualified class name of your implementation. * *

              Wrappers are sorted by priority in descending order (highest priority first). diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallContext.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/ClientCallContext.java similarity index 90% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallContext.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/ClientCallContext.java index 288d7b54a..ef37f7975 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallContext.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/ClientCallContext.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.spi.interceptors; +package org.a2aproject.sdk.client.transport.spi.interceptors; import java.util.Map; diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallInterceptor.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/ClientCallInterceptor.java similarity index 90% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallInterceptor.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/ClientCallInterceptor.java index b8a8de797..7d9e08fb9 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallInterceptor.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/ClientCallInterceptor.java @@ -1,8 +1,8 @@ -package io.a2a.client.transport.spi.interceptors; +package org.a2aproject.sdk.client.transport.spi.interceptors; import java.util.Map; -import io.a2a.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentCard; import org.jspecify.annotations.Nullable; /** diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/PayloadAndHeaders.java similarity index 91% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/PayloadAndHeaders.java index 7f8075312..03dc61126 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/PayloadAndHeaders.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.spi.interceptors; +package org.a2aproject.sdk.client.transport.spi.interceptors; import java.util.Collections; import java.util.HashMap; diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptor.java similarity index 82% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptor.java index 2b073d413..a946ce9d0 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptor.java @@ -1,20 +1,20 @@ -package io.a2a.client.transport.spi.interceptors.auth; +package org.a2aproject.sdk.client.transport.spi.interceptors.auth; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -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.spec.APIKeySecurityScheme; -import io.a2a.spec.AgentCard; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.SecurityScheme; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor; +import org.a2aproject.sdk.client.transport.spi.interceptors.PayloadAndHeaders; +import org.a2aproject.sdk.spec.APIKeySecurityScheme; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; +import org.a2aproject.sdk.spec.OAuth2SecurityScheme; +import org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme; +import org.a2aproject.sdk.spec.SecurityRequirement; +import org.a2aproject.sdk.spec.SecurityScheme; import org.jspecify.annotations.Nullable; /** diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/CredentialService.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/CredentialService.java similarity index 79% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/CredentialService.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/CredentialService.java index 949ea8087..aff6f9b1b 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/CredentialService.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/CredentialService.java @@ -1,6 +1,6 @@ -package io.a2a.client.transport.spi.interceptors.auth; +package org.a2aproject.sdk.client.transport.spi.interceptors.auth; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; import org.jspecify.annotations.Nullable; /** diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java similarity index 92% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java index f6db9662a..f05e92288 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java @@ -1,10 +1,10 @@ -package io.a2a.client.transport.spi.interceptors.auth; +package org.a2aproject.sdk.client.transport.spi.interceptors.auth; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; import org.jspecify.annotations.Nullable; /** diff --git a/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/package-info.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/package-info.java new file mode 100644 index 000000000..d46b1482d --- /dev/null +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.client.transport.spi.interceptors.auth; + +import org.jspecify.annotations.NullMarked; + diff --git a/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/package-info.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/package-info.java new file mode 100644 index 000000000..1016099af --- /dev/null +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.client.transport.spi.interceptors; + +import org.jspecify.annotations.NullMarked; + diff --git a/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/package-info.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/package-info.java new file mode 100644 index 000000000..5519844a7 --- /dev/null +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.client.transport.spi; + +import org.jspecify.annotations.NullMarked; + diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/AbstractSSEEventListener.java similarity index 94% rename from client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java rename to client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/AbstractSSEEventListener.java index b6051bf41..994dc5874 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/AbstractSSEEventListener.java @@ -1,13 +1,13 @@ -package io.a2a.client.transport.spi.sse; +package org.a2aproject.sdk.client.transport.spi.sse; import java.util.concurrent.Future; import java.util.function.Consumer; import java.util.logging.Logger; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.jspecify.annotations.Nullable; /** diff --git a/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/package-info.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/package-info.java new file mode 100644 index 000000000..269dde525 --- /dev/null +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.client.transport.spi.sse; + +import org.jspecify.annotations.NullMarked; + 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/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptorTest.java similarity index 93% rename from client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java rename to client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptorTest.java index ed29dafab..b59f16329 100644 --- a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java +++ b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptorTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.spi.interceptors.auth; +package org.a2aproject.sdk.client.transport.spi.interceptors.auth; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -7,19 +7,19 @@ import java.util.List; import java.util.Map; -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.spec.APIKeySecurityScheme; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OAuthFlows; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.SecurityScheme; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallInterceptor; +import org.a2aproject.sdk.client.transport.spi.interceptors.PayloadAndHeaders; +import org.a2aproject.sdk.spec.APIKeySecurityScheme; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; +import org.a2aproject.sdk.spec.OAuth2SecurityScheme; +import org.a2aproject.sdk.spec.OAuthFlows; +import org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme; +import org.a2aproject.sdk.spec.SecurityRequirement; +import org.a2aproject.sdk.spec.SecurityScheme; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java similarity index 96% rename from client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java rename to client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java index 9dd643df3..fa337551a 100644 --- a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java +++ b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.transport.spi.sse; +package org.a2aproject.sdk.client.transport.spi.sse; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -11,13 +11,13 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/common/src/main/java/io/a2a/util/package-info.java b/common/src/main/java/io/a2a/util/package-info.java deleted file mode 100644 index 769e16337..000000000 --- a/common/src/main/java/io/a2a/util/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.util; - -import org.jspecify.annotations.NullMarked; - diff --git a/common/src/main/java/io/a2a/common/A2AErrorMessages.java b/common/src/main/java/org/a2aproject/sdk/common/A2AErrorMessages.java similarity index 91% rename from common/src/main/java/io/a2a/common/A2AErrorMessages.java rename to common/src/main/java/org/a2aproject/sdk/common/A2AErrorMessages.java index 2801a2b4e..d3a18eae6 100644 --- a/common/src/main/java/io/a2a/common/A2AErrorMessages.java +++ b/common/src/main/java/org/a2aproject/sdk/common/A2AErrorMessages.java @@ -1,4 +1,4 @@ -package io.a2a.common; +package org.a2aproject.sdk.common; public final class A2AErrorMessages { diff --git a/common/src/main/java/io/a2a/common/A2AHeaders.java b/common/src/main/java/org/a2aproject/sdk/common/A2AHeaders.java similarity index 95% rename from common/src/main/java/io/a2a/common/A2AHeaders.java rename to common/src/main/java/org/a2aproject/sdk/common/A2AHeaders.java index ffbbebda9..5d1c05e36 100644 --- a/common/src/main/java/io/a2a/common/A2AHeaders.java +++ b/common/src/main/java/org/a2aproject/sdk/common/A2AHeaders.java @@ -1,4 +1,4 @@ -package io.a2a.common; +package org.a2aproject.sdk.common; /** * Common A2A protocol headers and constants. diff --git a/common/src/main/java/io/a2a/common/MediaType.java b/common/src/main/java/org/a2aproject/sdk/common/MediaType.java similarity index 70% rename from common/src/main/java/io/a2a/common/MediaType.java rename to common/src/main/java/org/a2aproject/sdk/common/MediaType.java index 9cdc48211..37f74dc8e 100644 --- a/common/src/main/java/io/a2a/common/MediaType.java +++ b/common/src/main/java/org/a2aproject/sdk/common/MediaType.java @@ -1,4 +1,4 @@ -package io.a2a.common; +package org.a2aproject.sdk.common; public interface MediaType { diff --git a/client/base/src/main/java/io/a2a/client/config/package-info.java b/common/src/main/java/org/a2aproject/sdk/common/package-info.java similarity index 62% rename from client/base/src/main/java/io/a2a/client/config/package-info.java rename to common/src/main/java/org/a2aproject/sdk/common/package-info.java index ab8c28600..3416550f6 100644 --- a/client/base/src/main/java/io/a2a/client/config/package-info.java +++ b/common/src/main/java/org/a2aproject/sdk/common/package-info.java @@ -1,5 +1,5 @@ @NullMarked -package io.a2a.client.config; +package org.a2aproject.sdk.common; import org.jspecify.annotations.NullMarked; diff --git a/common/src/main/java/io/a2a/util/Assert.java b/common/src/main/java/org/a2aproject/sdk/util/Assert.java similarity index 97% rename from common/src/main/java/io/a2a/util/Assert.java rename to common/src/main/java/org/a2aproject/sdk/util/Assert.java index 0c375a36b..f7a92d63e 100644 --- a/common/src/main/java/io/a2a/util/Assert.java +++ b/common/src/main/java/org/a2aproject/sdk/util/Assert.java @@ -1,4 +1,4 @@ -package io.a2a.util; +package org.a2aproject.sdk.util; import org.jspecify.annotations.Nullable; diff --git a/common/src/main/java/io/a2a/util/NotNull.java b/common/src/main/java/org/a2aproject/sdk/util/NotNull.java similarity index 92% rename from common/src/main/java/io/a2a/util/NotNull.java rename to common/src/main/java/org/a2aproject/sdk/util/NotNull.java index 3146117f3..e32ebccdd 100644 --- a/common/src/main/java/io/a2a/util/NotNull.java +++ b/common/src/main/java/org/a2aproject/sdk/util/NotNull.java @@ -1,4 +1,4 @@ -package io.a2a.util; +package org.a2aproject.sdk.util; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/boms/test-utils/src/main/java/io/a2a/bom/test/package-info.java b/common/src/main/java/org/a2aproject/sdk/util/package-info.java similarity index 63% rename from boms/test-utils/src/main/java/io/a2a/bom/test/package-info.java rename to common/src/main/java/org/a2aproject/sdk/util/package-info.java index 98946de54..4a0de4541 100644 --- a/boms/test-utils/src/main/java/io/a2a/bom/test/package-info.java +++ b/common/src/main/java/org/a2aproject/sdk/util/package-info.java @@ -1,5 +1,5 @@ @NullMarked -package io.a2a.bom.test; +package org.a2aproject.sdk.util; import org.jspecify.annotations.NullMarked; diff --git a/examples/cloud-deployment/README.md b/examples/cloud-deployment/README.md index 8ec47925c..11ebf4979 100644 --- a/examples/cloud-deployment/README.md +++ b/examples/cloud-deployment/README.md @@ -149,7 +149,7 @@ This approach provides the same round-robin load balancing as a real LoadBalance ```bash cd ../server mvn test-compile exec:java \ - -Dexec.mainClass="io.a2a.examples.cloud.A2ACloudExampleClient" \ + -Dexec.mainClass="org.a2aproject.sdk.examples.cloud.A2ACloudExampleClient" \ -Dexec.classpathScope=test \ -Dagent.url="http://localhost:8080" ``` @@ -515,12 +515,12 @@ Then re-run `./deploy.sh` to start fresh. ``` cloud-deployment/ ├── server/ -│ ├── src/main/java/io/a2a/examples/cloud/ +│ ├── src/main/java/org/a2aproject/sdk/examples/cloud/ │ │ ├── CloudAgentCardProducer.java # Agent card configuration │ │ └── CloudAgentExecutorProducer.java # Agent business logic │ ├── src/main/resources/ │ │ └── application.properties # Application configuration -│ ├── src/test/java/io/a2a/examples/cloud/ +│ ├── src/test/java/org/a2aproject/sdk/examples/cloud/ │ │ └── A2ACloudExampleClient.java # Test client │ ├── pom.xml # Maven dependencies │ └── Dockerfile # Container image diff --git a/examples/cloud-deployment/scripts/deploy.sh b/examples/cloud-deployment/scripts/deploy.sh index 448457221..26d5b0d79 100755 --- a/examples/cloud-deployment/scripts/deploy.sh +++ b/examples/cloud-deployment/scripts/deploy.sh @@ -359,5 +359,5 @@ echo "" echo "To run the test client (demonstrating load balancing):" echo " cd ../server" echo " mvn test-compile exec:java -Dexec.classpathScope=test \\" -echo " -Dexec.mainClass=\"io.a2a.examples.cloud.A2ACloudExampleClient\" \\" +echo " -Dexec.mainClass=\"org.a2aproject.sdk.examples.cloud.A2ACloudExampleClient\" \\" echo " -Dagent.url=\"http://localhost:8080\"" diff --git a/examples/cloud-deployment/scripts/verify.sh b/examples/cloud-deployment/scripts/verify.sh index b9905b0d7..fd69715e6 100755 --- a/examples/cloud-deployment/scripts/verify.sh +++ b/examples/cloud-deployment/scripts/verify.sh @@ -81,6 +81,6 @@ echo "" echo "To run the test client (demonstrating load balancing):" echo " cd ../server" echo " mvn test-compile exec:java -Dexec.classpathScope=test \\" -echo " -Dexec.mainClass=\"io.a2a.examples.cloud.A2ACloudExampleClient\" \\" +echo " -Dexec.mainClass=\"org.a2aproject.sdk.examples.cloud.A2ACloudExampleClient\" \\" echo " -Dagent.url=\"http://localhost:8080\"" echo "==========================================" diff --git a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java b/examples/cloud-deployment/server/src/main/java/org/a2aproject/sdk/examples/cloud/CloudAgentCardProducer.java similarity index 89% rename from examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java rename to examples/cloud-deployment/server/src/main/java/org/a2aproject/sdk/examples/cloud/CloudAgentCardProducer.java index b3adbcdd8..234e112ca 100644 --- a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java +++ b/examples/cloud-deployment/server/src/main/java/org/a2aproject/sdk/examples/cloud/CloudAgentCardProducer.java @@ -1,4 +1,4 @@ -package io.a2a.examples.cloud; +package org.a2aproject.sdk.examples.cloud; import java.util.Collections; @@ -8,11 +8,11 @@ import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; import org.eclipse.microprofile.config.inject.ConfigProperty; /** diff --git a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java b/examples/cloud-deployment/server/src/main/java/org/a2aproject/sdk/examples/cloud/CloudAgentExecutorProducer.java similarity index 92% rename from examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java rename to examples/cloud-deployment/server/src/main/java/org/a2aproject/sdk/examples/cloud/CloudAgentExecutorProducer.java index 976826fb3..7e882254f 100644 --- a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java +++ b/examples/cloud-deployment/server/src/main/java/org/a2aproject/sdk/examples/cloud/CloudAgentExecutorProducer.java @@ -1,18 +1,18 @@ -package io.a2a.examples.cloud; +package org.a2aproject.sdk.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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.InternalError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/examples/cloud-deployment/server/src/main/resources/application.properties b/examples/cloud-deployment/server/src/main/resources/application.properties index 653c36398..bd84ff238 100644 --- a/examples/cloud-deployment/server/src/main/resources/application.properties +++ b/examples/cloud-deployment/server/src/main/resources/application.properties @@ -16,7 +16,7 @@ quarkus.datasource.jdbc.max-size=16 quarkus.hibernate-orm."a2a-java".datasource= quarkus.hibernate-orm."a2a-java".database.generation=update quarkus.hibernate-orm."a2a-java".log.sql=false -quarkus.hibernate-orm."a2a-java".packages=io.a2a.extras.taskstore.database.jpa,io.a2a.extras.pushnotificationconfigstore.database.jpa +quarkus.hibernate-orm."a2a-java".packages=org.a2aproject.sdk.extras.taskstore.database.jpa,org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa # Kafka Configuration for Event Replication kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092} @@ -38,12 +38,12 @@ mp.messaging.incoming.replicated-events-in.auto.offset.reset=earliest # Logging # Default to INFO level for production-like behavior # To enable DEBUG logging for troubleshooting, set these to DEBUG: -# quarkus.log.category."io.a2a.examples.cloud".level=DEBUG -# quarkus.log.category."io.a2a.server.events".level=DEBUG -# quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -# quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG +# quarkus.log.category."org.a2aproject.sdk.examples.cloud".level=DEBUG +# quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +# quarkus.log.category."org.a2aproject.sdk.extras.queuemanager.replicated".level=DEBUG +# quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG quarkus.log.level=INFO -quarkus.log.category."io.a2a".level=INFO +quarkus.log.category."org.a2aproject.sdk".level=INFO quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n # Health checks diff --git a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java b/examples/cloud-deployment/server/src/test/java/org/a2aproject/sdk/examples/cloud/A2ACloudExampleClient.java similarity index 95% rename from examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java rename to examples/cloud-deployment/server/src/test/java/org/a2aproject/sdk/examples/cloud/A2ACloudExampleClient.java index 871affb4e..80fae4df5 100644 --- a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java +++ b/examples/cloud-deployment/server/src/test/java/org/a2aproject/sdk/examples/cloud/A2ACloudExampleClient.java @@ -1,4 +1,4 @@ -package io.a2a.examples.cloud; +package org.a2aproject.sdk.examples.cloud; import java.io.IOException; import java.util.Collections; @@ -10,23 +10,23 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import io.a2a.A2A; -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.MessageEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.A2A; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.MessageEvent; +import org.a2aproject.sdk.client.TaskEvent; +import org.a2aproject.sdk.client.TaskUpdateEvent; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.TransportProtocol; /** * Test client demonstrating multi-pod A2A agent deployment with modernized message protocol. diff --git a/examples/helloworld/client/README.md b/examples/helloworld/client/README.md index cd5043f11..b186f7ec7 100644 --- a/examples/helloworld/client/README.md +++ b/examples/helloworld/client/README.md @@ -113,7 +113,7 @@ A JBang script is provided for running the client without Maven: 3. Run the client using the JBang script: ```bash - jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java + jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java ``` #### Transport Protocol Selection with JBang @@ -122,29 +122,29 @@ Select the transport protocol using the same `-Dquarkus.agentcard.protocol` prop **Using JSONRPC (default)**: ```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java ``` **Using GRPC**: ```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC +jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC ``` **Using HTTP+JSON**: ```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON +jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON ``` #### Enabling OpenTelemetry with JBang To enable OpenTelemetry with JBang: ```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true +jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true ``` You can combine protocol selection with OpenTelemetry: ```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC -Dopentelemetry=true +jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC -Dopentelemetry=true ``` ## What the Example Does @@ -194,12 +194,12 @@ Instead of the Python server, use the Java server example which has built-in Ope Or using JBang: ```bash - jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true + jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true ``` With specific protocol: ```bash - jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true + jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true ``` 3. **View traces in Grafana**: @@ -225,7 +225,7 @@ If you want to use the Python server with OpenTelemetry: Or with JBang: ```bash - jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true + jbang examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true ``` With specific protocol: diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index 8d472ebd3..c2c6d9a22 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -16,7 +16,7 @@ Examples for the Java SDK for the Agent2Agent Protocol (A2A) - src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java + src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java @@ -93,7 +93,7 @@ exec-maven-plugin 3.6.2 - io.a2a.examples.helloworld.HelloWorldClient + org.a2aproject.sdk.examples.helloworld.HelloWorldClient opentelemetry diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldClient.java similarity index 86% rename from examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java rename to examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldClient.java index 6634898c7..d948c2e7c 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java +++ b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldClient.java @@ -1,7 +1,7 @@ -package io.a2a.examples.helloworld; +package org.a2aproject.sdk.examples.helloworld; -import static io.a2a.extras.opentelemetry.client.OpenTelemetryClientTransportWrapper.OTEL_TRACER_KEY; -import static io.a2a.extras.opentelemetry.client.propagation.OpenTelemetryClientPropagatorTransportWrapper.OTEL_OPEN_TELEMETRY_KEY; +import static org.a2aproject.sdk.extras.opentelemetry.client.OpenTelemetryClientTransportWrapper.OTEL_TRACER_KEY; +import static org.a2aproject.sdk.extras.opentelemetry.client.propagation.OpenTelemetryClientPropagatorTransportWrapper.OTEL_OPEN_TELEMETRY_KEY; import java.util.ArrayList; import java.util.HashMap; @@ -11,25 +11,25 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -import io.a2a.A2A; - -import io.a2a.client.Client; -import io.a2a.client.ClientBuilder; -import io.a2a.client.ClientEvent; -import io.a2a.client.MessageEvent; -import io.a2a.client.http.A2ACardResolver; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfig; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfig; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.A2A; + +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.MessageEvent; +import org.a2aproject.sdk.client.http.A2ACardResolver; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransport; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfig; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfig; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfig; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import io.grpc.Channel; import io.grpc.ManagedChannelBuilder; import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java similarity index 95% rename from examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java rename to examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java index e4a52ffdd..57735e0f8 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java @@ -37,6 +37,6 @@ public static void main(String[] args) { } } } - io.a2a.examples.helloworld.HelloWorldClient.main(args); + org.a2aproject.sdk.examples.helloworld.HelloWorldClient.main(args); } } diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/INSTALL_JBANG.md b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/INSTALL_JBANG.md similarity index 100% rename from examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/INSTALL_JBANG.md rename to examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/INSTALL_JBANG.md diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java b/examples/helloworld/server/src/main/java/org/a2aproject/sdk/examples/helloworld/AgentCardProducer.java similarity index 86% rename from examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java rename to examples/helloworld/server/src/main/java/org/a2aproject/sdk/examples/helloworld/AgentCardProducer.java index fb66cc517..826c69db7 100644 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java +++ b/examples/helloworld/server/src/main/java/org/a2aproject/sdk/examples/helloworld/AgentCardProducer.java @@ -1,11 +1,11 @@ -package io.a2a.examples.helloworld; +package org.a2aproject.sdk.examples.helloworld; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.TransportProtocol; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; import org.eclipse.microprofile.config.inject.ConfigProperty; diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java b/examples/helloworld/server/src/main/java/org/a2aproject/sdk/examples/helloworld/AgentExecutorProducer.java similarity index 66% rename from examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java rename to examples/helloworld/server/src/main/java/org/a2aproject/sdk/examples/helloworld/AgentExecutorProducer.java index 3c3be977b..ebd18aac9 100644 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java +++ b/examples/helloworld/server/src/main/java/org/a2aproject/sdk/examples/helloworld/AgentExecutorProducer.java @@ -1,13 +1,13 @@ -package io.a2a.examples.helloworld; +package org.a2aproject.sdk.examples.helloworld; 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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.UnsupportedOperationError; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.UnsupportedOperationError; @ApplicationScoped public class AgentExecutorProducer { diff --git a/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java b/extras/common/src/main/java/org/a2aproject/sdk/extras/common/events/TaskFinalizedEvent.java similarity index 84% rename from extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java rename to extras/common/src/main/java/org/a2aproject/sdk/extras/common/events/TaskFinalizedEvent.java index 0c35bad7a..ebf1ba4a3 100644 --- a/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java +++ b/extras/common/src/main/java/org/a2aproject/sdk/extras/common/events/TaskFinalizedEvent.java @@ -1,4 +1,4 @@ -package io.a2a.extras.common.events; +package org.a2aproject.sdk.extras.common.events; /** * CDI event fired when a task reaches a final state and is successfully persisted to the database. @@ -10,7 +10,7 @@ */ public class TaskFinalizedEvent { private final String taskId; - private final Object task; // Task type from io.a2a.spec - using Object to avoid dependency + private final Object task; // Task type from org.a2aproject.sdk.spec - using Object to avoid dependency public TaskFinalizedEvent(String taskId, Object task) { this.taskId = taskId; diff --git a/extras/http-client-vertx/README.md b/extras/http-client-vertx/README.md index 9af9a1cae..b1d22a54c 100644 --- a/extras/http-client-vertx/README.md +++ b/extras/http-client-vertx/README.md @@ -129,9 +129,9 @@ client.sendMessage(message); If you need direct access to the HTTP client (rare): ```java -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.http.A2AHttpResponse; // Get the client via factory (returns VertxA2AHttpClient if available) try (A2AHttpClient client = A2AHttpClientFactory.create()) { @@ -216,7 +216,7 @@ The `VertxA2AHttpClient` constructor automatically checks for a CDI-managed `Ver If you're not using CDI but want to share a Vert.x instance: ```java -import io.a2a.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; import io.vertx.core.Vertx; // Create Vertx instance once @@ -241,8 +241,8 @@ try { For advanced use cases requiring custom Vert.x WebClient configuration, you can create your own provider: ```java -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; import io.vertx.core.Vertx; import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClientOptions; @@ -261,9 +261,9 @@ Vertx vertx = Vertx.vertx(); The module uses Java's `ServiceLoader` mechanism for automatic discovery: -1. **Provider Registration**: `META-INF/services/io.a2a.client.http.A2AHttpClientProvider` contains: +1. **Provider Registration**: `META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider` contains: ``` - io.a2a.client.http.VertxA2AHttpClientProvider + org.a2aproject.sdk.client.http.VertxA2AHttpClientProvider ``` 2. **Priority System**: Each provider has a priority: diff --git a/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClient.java b/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java similarity index 99% rename from extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClient.java rename to extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java index b6afce027..74a744b51 100644 --- a/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClient.java +++ b/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import static java.net.HttpURLConnection.HTTP_FORBIDDEN; import static java.net.HttpURLConnection.HTTP_MULT_CHOICE; @@ -17,7 +17,7 @@ import org.jspecify.annotations.Nullable; -import io.a2a.common.A2AErrorMessages; +import org.a2aproject.sdk.common.A2AErrorMessages; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.ext.web.client.HttpRequest; diff --git a/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClientProvider.java b/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientProvider.java similarity index 93% rename from extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClientProvider.java rename to extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientProvider.java index e802e1df1..3160891c7 100644 --- a/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClientProvider.java +++ b/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientProvider.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import java.util.logging.Level; import java.util.logging.Logger; @@ -40,7 +40,7 @@ public A2AHttpClient create() { } try { - Class clientClass = Class.forName("io.a2a.client.http.VertxA2AHttpClient"); + Class clientClass = Class.forName("org.a2aproject.sdk.client.http.VertxA2AHttpClient"); return (A2AHttpClient) clientClass.getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new IllegalStateException("Failed to create VertxA2AHttpClient instance", e); diff --git a/extras/http-client-vertx/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider b/extras/http-client-vertx/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider deleted file mode 100644 index 9d6a67c3b..000000000 --- a/extras/http-client-vertx/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.http.VertxA2AHttpClientProvider diff --git a/extras/http-client-vertx/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider b/extras/http-client-vertx/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider new file mode 100644 index 000000000..1cef76d4c --- /dev/null +++ b/extras/http-client-vertx/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider @@ -0,0 +1 @@ +org.a2aproject.sdk.client.http.VertxA2AHttpClientProvider diff --git a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientFactoryTest.java b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientFactoryTest.java similarity index 98% rename from extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientFactoryTest.java rename to extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientFactoryTest.java index 2ac3eac94..4bf84fafb 100644 --- a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientFactoryTest.java +++ b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientFactoryTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import static org.junit.jupiter.api.Assertions.*; diff --git a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientIntegrationTest.java b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientIntegrationTest.java similarity index 98% rename from extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientIntegrationTest.java rename to extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientIntegrationTest.java index f945aecde..0bb601beb 100644 --- a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientIntegrationTest.java +++ b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientIntegrationTest.java @@ -1,10 +1,10 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import static org.junit.jupiter.api.Assertions.*; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; -import io.a2a.common.A2AErrorMessages; +import org.a2aproject.sdk.common.A2AErrorMessages; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientSSETest.java b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientSSETest.java similarity index 99% rename from extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientSSETest.java rename to extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientSSETest.java index 64b1dec54..2daefde1e 100644 --- a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientSSETest.java +++ b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientSSETest.java @@ -1,10 +1,10 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import static org.junit.jupiter.api.Assertions.*; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; -import io.a2a.common.A2AErrorMessages; +import org.a2aproject.sdk.common.A2AErrorMessages; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientTest.java b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientTest.java similarity index 98% rename from extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientTest.java rename to extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientTest.java index 55e9afd94..d0780b20d 100644 --- a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientTest.java +++ b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import static org.junit.jupiter.api.Assertions.*; diff --git a/extras/opentelemetry/README.md b/extras/opentelemetry/README.md index 7ea5ed427..d6a14f10c 100644 --- a/extras/opentelemetry/README.md +++ b/extras/opentelemetry/README.md @@ -34,7 +34,7 @@ Add the OpenTelemetry server module to your dependencies: ```xml - io.a2a + org.a2aproject.sdk a2a-extras-opentelemetry-server ${a2a.version} diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java deleted file mode 100644 index 0ca927df9..000000000 --- a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.extras.opentelemetry.client.propagation; - -import org.jspecify.annotations.NullMarked; - diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java b/extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java similarity index 80% rename from extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java rename to extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java index 20cb377fd..898ed7b40 100644 --- a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java +++ b/extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java @@ -1,24 +1,24 @@ -package io.a2a.extras.opentelemetry.client.propagation; - -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.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; +package org.a2aproject.sdk.extras.opentelemetry.client.propagation; + +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.TextMapSetter; diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java b/extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java similarity index 76% rename from extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java rename to extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java index a8c83968c..a0c729daf 100644 --- a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java +++ b/extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java @@ -1,8 +1,8 @@ -package io.a2a.extras.opentelemetry.client.propagation; +package org.a2aproject.sdk.extras.opentelemetry.client.propagation; -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.client.transport.spi.ClientTransportWrapper; +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfig; +import org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Tracer; @@ -27,8 +27,8 @@ public class OpenTelemetryClientPropagatorTransportWrapper implements ClientTran * Configuration key for the OpenTelemetry Tracer instance. * Value must be of type {@link Tracer}. */ - public static final String OTEL_TRACER_KEY = "io.a2a.extras.opentelemetry.Tracer"; - public static final String OTEL_OPEN_TELEMETRY_KEY = "io.a2a.extras.opentelemetry.OpenTelemetry"; + public static final String OTEL_TRACER_KEY = "org.a2aproject.sdk.extras.opentelemetry.Tracer"; + public static final String OTEL_OPEN_TELEMETRY_KEY = "org.a2aproject.sdk.extras.opentelemetry.OpenTelemetry"; @Override public ClientTransport wrap(ClientTransport transport, ClientTransportConfig config) { diff --git a/extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/package-info.java b/extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/package-info.java new file mode 100644 index 000000000..62412a953 --- /dev/null +++ b/extras/opentelemetry/client-propagation/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/propagation/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.extras.opentelemetry.client.propagation; + +import org.jspecify.annotations.NullMarked; + diff --git a/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper b/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper deleted file mode 100644 index f1cccce71..000000000 --- a/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper +++ /dev/null @@ -1 +0,0 @@ -io.a2a.extras.opentelemetry.client.propagation.OpenTelemetryClientPropagatorTransportWrapper diff --git a/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper b/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper new file mode 100644 index 000000000..df935c454 --- /dev/null +++ b/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper @@ -0,0 +1 @@ +org.a2aproject.sdk.extras.opentelemetry.client.propagation.OpenTelemetryClientPropagatorTransportWrapper diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java deleted file mode 100644 index 0a7d54541..000000000 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.extras.opentelemetry.client; - -import org.jspecify.annotations.NullMarked; - diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java b/extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransport.java similarity index 89% rename from extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java rename to extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransport.java index e9b248737..574253978 100644 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java +++ b/extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransport.java @@ -1,38 +1,38 @@ -package io.a2a.extras.opentelemetry.client; +package org.a2aproject.sdk.extras.opentelemetry.client; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONFIG_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONTEXT_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_EXTENSIONS; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_MESSAGE_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_OPERATION_NAME; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_PARTS_NUMBER; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_ROLE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_TASK_ID; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_CONFIG_ID; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_CONTEXT_ID; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_EXTENSIONS; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_MESSAGE_ID; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_OPERATION_NAME; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_PARTS_NUMBER; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_ROLE; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_TASK_ID; -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.A2AClientException; -import io.a2a.spec.A2AMethods; -import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AMethods; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java b/extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java similarity index 80% rename from extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java rename to extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java index 2f61bf280..7b66a7ab6 100644 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java +++ b/extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java @@ -1,8 +1,8 @@ -package io.a2a.extras.opentelemetry.client; +package org.a2aproject.sdk.extras.opentelemetry.client; -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.client.transport.spi.ClientTransportWrapper; +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.ClientTransportConfig; +import org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper; import io.opentelemetry.api.trace.Tracer; /** @@ -26,7 +26,7 @@ public class OpenTelemetryClientTransportWrapper implements ClientTransportWrapp * Configuration key for the OpenTelemetry Tracer instance. * Value must be of type {@link Tracer}. */ - public static final String OTEL_TRACER_KEY = "io.a2a.extras.opentelemetry.Tracer"; + public static final String OTEL_TRACER_KEY = "org.a2aproject.sdk.extras.opentelemetry.Tracer"; @Override public ClientTransport wrap(ClientTransport transport, ClientTransportConfig config) { diff --git a/extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/package-info.java b/extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/package-info.java new file mode 100644 index 000000000..a78ff7fc9 --- /dev/null +++ b/extras/opentelemetry/client/src/main/java/org/a2aproject/sdk/extras/opentelemetry/client/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.extras.opentelemetry.client; + +import org.jspecify.annotations.NullMarked; + diff --git a/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper b/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper deleted file mode 100644 index 801f7dd3a..000000000 --- a/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper +++ /dev/null @@ -1 +0,0 @@ -io.a2a.extras.opentelemetry.client.OpenTelemetryClientTransportWrapper diff --git a/extras/opentelemetry/client/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper b/extras/opentelemetry/client/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper new file mode 100644 index 000000000..ab7325d47 --- /dev/null +++ b/extras/opentelemetry/client/src/main/resources/META-INF/services/org.a2aproject.sdk.client.transport.spi.ClientTransportWrapper @@ -0,0 +1 @@ +org.a2aproject.sdk.extras.opentelemetry.client.OpenTelemetryClientTransportWrapper diff --git a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java b/extras/opentelemetry/client/src/test/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java similarity index 93% rename from extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java rename to extras/opentelemetry/client/src/test/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java index 2ef582ed6..fd1e7d992 100644 --- a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java +++ b/extras/opentelemetry/client/src/test/java/org/a2aproject/sdk/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java @@ -1,30 +1,30 @@ -package io.a2a.extras.opentelemetry.client; - -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; - -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.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TextPart; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; +package org.a2aproject.sdk.extras.opentelemetry.client; + +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; + +import org.a2aproject.sdk.client.transport.spi.ClientTransport; +import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; @@ -48,8 +48,8 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import io.a2a.spec.A2AMethods; -import io.a2a.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.A2AMethods; +import org.a2aproject.sdk.spec.CancelTaskParams; @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) diff --git a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java b/extras/opentelemetry/common/src/main/java/org/a2aproject/sdk/extras/opentelemetry/A2AObservabilityNames.java similarity index 80% rename from extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java rename to extras/opentelemetry/common/src/main/java/org/a2aproject/sdk/extras/opentelemetry/A2AObservabilityNames.java index c2821d8a7..4bd74e99b 100644 --- a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java +++ b/extras/opentelemetry/common/src/main/java/org/a2aproject/sdk/extras/opentelemetry/A2AObservabilityNames.java @@ -1,9 +1,9 @@ -package io.a2a.extras.opentelemetry; +package org.a2aproject.sdk.extras.opentelemetry; public interface A2AObservabilityNames { - String EXTRACT_REQUEST_SYS_PROPERTY = "io.a2a.server.extract.request"; - String EXTRACT_RESPONSE_SYS_PROPERTY = "io.a2a.server.extract.response"; + String EXTRACT_REQUEST_SYS_PROPERTY = "org.a2aproject.sdk.server.extract.request"; + String EXTRACT_RESPONSE_SYS_PROPERTY = "org.a2aproject.sdk.server.extract.response"; String ERROR_TYPE = "error.type"; diff --git a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java b/extras/opentelemetry/common/src/main/java/org/a2aproject/sdk/extras/opentelemetry/package-info.java similarity index 84% rename from extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java rename to extras/opentelemetry/common/src/main/java/org/a2aproject/sdk/extras/opentelemetry/package-info.java index 8e7125631..eededca05 100644 --- a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java +++ b/extras/opentelemetry/common/src/main/java/org/a2aproject/sdk/extras/opentelemetry/package-info.java @@ -5,4 +5,4 @@ * used across both client and server OpenTelemetry integrations. */ @org.jspecify.annotations.NullMarked -package io.a2a.extras.opentelemetry; +package org.a2aproject.sdk.extras.opentelemetry; diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java similarity index 97% rename from extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java rename to extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java index f6f84f6e1..c2640ef8f 100644 --- a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java +++ b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java @@ -1,4 +1,4 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; @@ -9,10 +9,10 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Scope; diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/SimpleAgentExecutor.java similarity index 74% rename from extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java rename to extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/SimpleAgentExecutor.java index 6d33dd89c..c10d28a03 100644 --- a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java +++ b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/SimpleAgentExecutor.java @@ -1,11 +1,11 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; -import io.a2a.A2A; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.A2A; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.TextPart; import jakarta.enterprise.context.ApplicationScoped; /** diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/TestAgentCardProducer.java similarity index 84% rename from extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java rename to extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/TestAgentCardProducer.java index 373169fac..a34d076f0 100644 --- a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java +++ b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/TestAgentCardProducer.java @@ -1,10 +1,10 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/TestUtilsBean.java similarity index 80% rename from extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java rename to extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/TestUtilsBean.java index 594063171..52a3ee7bb 100644 --- a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java +++ b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/TestUtilsBean.java @@ -1,9 +1,9 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; -import io.a2a.server.events.QueueManager; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Event; -import io.a2a.spec.Task; +import org.a2aproject.sdk.server.events.QueueManager; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.Task; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; diff --git a/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml b/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml index 5badbc80d..1147e29fd 100644 --- a/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml +++ b/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml @@ -4,6 +4,6 @@ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd" version="4.0" bean-discovery-mode="all"> - io.a2a.extras.opentelemetry.it.InstrumentedRequestHandler + org.a2aproject.sdk.extras.opentelemetry.it.InstrumentedRequestHandler diff --git a/extras/opentelemetry/integration-tests/src/main/resources/application.properties b/extras/opentelemetry/integration-tests/src/main/resources/application.properties index ca0d2c4fd..62c720ada 100644 --- a/extras/opentelemetry/integration-tests/src/main/resources/application.properties +++ b/extras/opentelemetry/integration-tests/src/main/resources/application.properties @@ -24,5 +24,5 @@ quarkus.otel.propagators=tracecontext # Logging quarkus.log.level=INFO -quarkus.log.category."io.a2a".level=DEBUG +quarkus.log.category."org.a2aproject.sdk".level=DEBUG quarkus.log.category."io.opentelemetry".level=DEBUG diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/BaseTest.java similarity index 88% rename from extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java rename to extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/BaseTest.java index 69304e10e..b3c154f44 100644 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java +++ b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/BaseTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; import static io.restassured.RestAssured.get; diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java similarity index 95% rename from extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java rename to extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java index c0754d172..efb45eba1 100644 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java +++ b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; import static io.quarkus.vertx.web.ReactiveRoutes.APPLICATION_JSON; import static io.restassured.RestAssured.given; @@ -7,13 +7,13 @@ import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.*; -import io.a2a.A2A; -import io.a2a.client.Client; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.*; +import org.a2aproject.sdk.A2A; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.*; import io.opentelemetry.api.trace.SpanKind; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -118,7 +118,7 @@ void testListTasksCreatesSpans() throws Exception { null, null, null, null, null, null, null, "" ); - io.a2a.jsonrpc.common.wrappers.ListTasksResult result = client.listTasks(params, null); + org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult result = client.listTasks(params, null); assertNotNull(result); diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2AIT.java similarity index 83% rename from extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java rename to extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2AIT.java index 7701acd23..272acfb1d 100644 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java +++ b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2AIT.java @@ -1,4 +1,4 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; import io.quarkus.test.junit.QuarkusIntegrationTest; diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ATest.java similarity index 81% rename from extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java rename to extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ATest.java index d6c73b05c..928f91c5d 100644 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java +++ b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ATest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; import io.quarkus.test.junit.QuarkusTest; diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryTest.java similarity index 95% rename from extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java rename to extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryTest.java index 50011fa81..4aa10341e 100644 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java +++ b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.opentelemetry.it; +package org.a2aproject.sdk.extras.opentelemetry.it; import static io.restassured.RestAssured.given; import static java.net.HttpURLConnection.HTTP_OK; diff --git a/extras/opentelemetry/integration-tests/src/test/resources/application.properties b/extras/opentelemetry/integration-tests/src/test/resources/application.properties index 1e459ea8e..a2fa34671 100644 --- a/extras/opentelemetry/integration-tests/src/test/resources/application.properties +++ b/extras/opentelemetry/integration-tests/src/test/resources/application.properties @@ -22,4 +22,4 @@ quarkus.otel.propagators=tracecontext # Logging quarkus.log.level=INFO -quarkus.log.category."io.a2a".level=DEBUG +quarkus.log.category."org.a2aproject.sdk".level=DEBUG diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java deleted file mode 100644 index fdd7057d5..000000000 --- a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.extras.opentelemetry; - -import org.jspecify.annotations.NullMarked; - diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducer.java b/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducer.java similarity index 96% rename from extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducer.java rename to extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducer.java index cd30196e1..b3dccf38c 100644 --- a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducer.java +++ b/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducer.java @@ -1,6 +1,6 @@ -package io.a2a.extras.opentelemetry; +package org.a2aproject.sdk.extras.opentelemetry; -import io.a2a.server.util.async.Internal; +import org.a2aproject.sdk.server.util.async.Internal; import jakarta.annotation.PostConstruct; import jakarta.annotation.Priority; import jakarta.enterprise.context.ApplicationScoped; diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java b/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java similarity index 87% rename from extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java rename to extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java index dfad8a531..d0da323c2 100644 --- a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java +++ b/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java @@ -1,37 +1,37 @@ -package io.a2a.extras.opentelemetry; - -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.ERROR_TYPE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONFIG_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONTEXT_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_EXTENSIONS; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_MESSAGE_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_OPERATION_NAME; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_PARTS_NUMBER; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_ROLE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_TASK_ID; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.ServerCallContext; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AMethods; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; +package org.a2aproject.sdk.extras.opentelemetry; + +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.ERROR_TYPE; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_CONFIG_ID; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_CONTEXT_ID; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_EXTENSIONS; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_MESSAGE_ID; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_OPERATION_NAME; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_PARTS_NUMBER; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_ROLE; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_TASK_ID; + +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.requesthandlers.RequestHandler; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.A2AMethods; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.StatusCode; @@ -61,7 +61,7 @@ * To enable this decorator, add it to your beans.xml: *

              {@code
                * 
              - *     io.a2a.extras.opentelemetry.OpenTelemetryRequestHandlerDecorator
              + *     org.a2aproject.sdk.extras.opentelemetry.OpenTelemetryRequestHandlerDecorator
                * 
                * }
              */ diff --git a/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/package-info.java b/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/package-info.java new file mode 100644 index 000000000..b1ec777b4 --- /dev/null +++ b/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.extras.opentelemetry; + +import org.jspecify.annotations.NullMarked; + diff --git a/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml b/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml index dcc4135c8..2e7281dcc 100644 --- a/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml +++ b/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml @@ -4,6 +4,6 @@ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd" bean-discovery-mode="annotated"> - io.a2a.extras.opentelemetry.OpenTelemetryRequestHandlerDecorator + org.a2aproject.sdk.extras.opentelemetry.OpenTelemetryRequestHandlerDecorator \ No newline at end of file diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducerTest.java b/extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducerTest.java similarity index 97% rename from extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducerTest.java rename to extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducerTest.java index ff4c86a16..0921e3d03 100644 --- a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/AsyncManagedExecutorProducerTest.java +++ b/extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducerTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.opentelemetry; +package org.a2aproject.sdk.extras.opentelemetry; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -127,7 +127,7 @@ void produceMethod_hasCorrectAnnotations() throws NoSuchMethodException { // Verify method has @Internal assertTrue( - method.isAnnotationPresent(io.a2a.server.util.async.Internal.class) + method.isAnnotationPresent(org.a2aproject.sdk.server.util.async.Internal.class) ); } diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java b/extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java similarity index 96% rename from extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java rename to extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java index 290b40c37..09be558b5 100644 --- a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java +++ b/extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java @@ -1,20 +1,20 @@ -package io.a2a.extras.opentelemetry; +package org.a2aproject.sdk.extras.opentelemetry; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.ERROR_TYPE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.ERROR_TYPE; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; +import static org.a2aproject.sdk.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.ServerCallContext; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.spec.*; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.requesthandlers.RequestHandler; +import org.a2aproject.sdk.spec.*; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanKind; diff --git a/extras/push-notification-config-store-database-jpa/README.md b/extras/push-notification-config-store-database-jpa/README.md index 52becb117..6ace61d08 100644 --- a/extras/push-notification-config-store-database-jpa/README.md +++ b/extras/push-notification-config-store-database-jpa/README.md @@ -49,7 +49,7 @@ Create or update your `persistence.xml`: java:jboss/datasources/A2ADataSource - io.a2a.extras.pushnotificationconfigstore.database.jpa.JpaPushNotificationConfig + org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa.JpaPushNotificationConfig true 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java similarity index 94% rename from extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java rename to extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java index 20d88e79c..43adeac31 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java @@ -1,4 +1,4 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; +package org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa; import jakarta.persistence.TypedQuery; import java.time.Instant; @@ -11,13 +11,13 @@ import jakarta.persistence.PersistenceContext; import jakarta.transaction.Transactional; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.util.Assert; -import io.a2a.util.PageToken; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.util.PageToken; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java similarity index 90% rename from extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java rename to extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java index 6bc74a2f5..5d513c0f8 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java @@ -1,4 +1,4 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; +package org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa; import jakarta.persistence.Column; import jakarta.persistence.EmbeddedId; @@ -7,9 +7,9 @@ import jakarta.persistence.Table; import jakarta.persistence.Transient; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import java.time.Instant; @Entity diff --git a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java b/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java similarity index 94% rename from extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java rename to extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java index 9b66a8ea4..0ab0c553f 100644 --- a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java +++ b/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java @@ -1,4 +1,4 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; +package org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa; import java.io.Serializable; import java.util.Objects; 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java similarity index 93% rename from extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java rename to extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java index 59dc130f5..705dea4ed 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; +package org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -15,22 +15,22 @@ 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; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TextPart; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -84,7 +84,7 @@ public void testDirectNotificationTrigger() { Task testTask = Task.builder() .id("direct-test-task") .contextId("test-context") - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_SUBMITTED)) + .status(new org.a2aproject.sdk.spec.TaskStatus(org.a2aproject.sdk.spec.TaskState.TASK_STATE_SUBMITTED)) .build(); // Directly trigger the mock @@ -166,7 +166,7 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep // Step 6: Verify the captured notification // Check if we received events for this task (could be Task, TaskArtifactUpdateEvent, etc.) - Queue capturedEvents = mockPushNotificationSender.getCapturedEvents(); + Queue capturedEvents = mockPushNotificationSender.getCapturedEvents(); // Look for Task events with artifacts OR TaskArtifactUpdateEvent for this task boolean hasTaskWithArtifact = capturedEvents.stream() @@ -175,8 +175,8 @@ public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Excep .anyMatch(t -> taskId.equals(t.id()) && t.artifacts() != null && t.artifacts().size() > 0); boolean hasArtifactUpdateEvent = capturedEvents.stream() - .filter(e -> e instanceof io.a2a.spec.TaskArtifactUpdateEvent) - .map(e -> (io.a2a.spec.TaskArtifactUpdateEvent) e) + .filter(e -> e instanceof org.a2aproject.sdk.spec.TaskArtifactUpdateEvent) + .map(e -> (org.a2aproject.sdk.spec.TaskArtifactUpdateEvent) e) .anyMatch(e -> taskId.equals(e.taskId())); assertTrue(hasTaskWithArtifact || hasArtifactUpdateEvent, @@ -361,7 +361,7 @@ public void testPaginationWithInvalidToken() { ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams( taskId, 2, "invalid_token_that_does_not_exist", ""); - assertThrows(io.a2a.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), + assertThrows(org.a2aproject.sdk.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), "Should throw InvalidParamsError for invalid pageToken format (missing colon)"); } @@ -417,7 +417,7 @@ public void testPageTokenWithNonNumericTimestamp() { ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, 2, "not_a_number:cfg1", ""); - assertThrows(io.a2a.spec.InvalidParamsError.class, + assertThrows(org.a2aproject.sdk.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), "Should throw InvalidParamsError for non-numeric timestamp in pageToken"); } @@ -431,7 +431,7 @@ public void testPageTokenWithMissingColon() { ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, 2, "123456789cfg1", ""); - assertThrows(io.a2a.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), + assertThrows(org.a2aproject.sdk.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), "Should throw InvalidParamsError for invalid pageToken format (missing colon)"); } diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java similarity index 82% rename from extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java rename to extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java index ac5e6ffdf..3e55a2aa4 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java @@ -1,4 +1,4 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; +package org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa; import java.util.Collections; import java.util.List; @@ -6,11 +6,11 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.TransportProtocol; import io.quarkus.arc.profile.IfBuildProfile; /** 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java similarity index 80% rename from extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java rename to extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java index 4061a3619..3ecbe53c6 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java @@ -1,4 +1,4 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; +package org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa; import java.util.List; @@ -6,15 +6,15 @@ import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.A2AError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import io.quarkus.arc.profile.IfBuildProfile; /** 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java similarity index 95% rename from extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java rename to extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java index 9e0aff233..1ae2bfe9d 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/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java @@ -1,7 +1,7 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; +package org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa; -import static io.a2a.client.http.A2AHttpClient.APPLICATION_JSON; -import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; +import static org.a2aproject.sdk.client.http.A2AHttpClient.APPLICATION_JSON; +import static org.a2aproject.sdk.client.http.A2AHttpClient.CONTENT_TYPE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -16,16 +16,16 @@ import jakarta.inject.Inject; import jakarta.transaction.Transactional; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.server.tasks.BasePushNotificationSender; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.server.tasks.BasePushNotificationSender; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java similarity index 84% rename from extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java rename to extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java index 2275388a9..7e0edca46 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java @@ -1,4 +1,4 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; +package org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -7,9 +7,9 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Alternative; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; /** * Mock implementation of PushNotificationSender for integration testing. diff --git a/extras/push-notification-config-store-database-jpa/src/test/resources/META-INF/persistence.xml b/extras/push-notification-config-store-database-jpa/src/test/resources/META-INF/persistence.xml index 4ae3b38d0..b22fdfaa4 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/resources/META-INF/persistence.xml +++ b/extras/push-notification-config-store-database-jpa/src/test/resources/META-INF/persistence.xml @@ -10,7 +10,7 @@ A2A Java SDK JPA TaskStore Test Configuration - io.a2a.extras.pushnotificationconfigstore.database.jpa.JpaPushNotificationConfig + org.a2aproject.sdk.extras.pushnotificationconfigstore.database.jpa.JpaPushNotificationConfig true diff --git a/extras/queue-manager-replicated/README.md b/extras/queue-manager-replicated/README.md index de9f929c1..37f77d98a 100644 --- a/extras/queue-manager-replicated/README.md +++ b/extras/queue-manager-replicated/README.md @@ -8,10 +8,10 @@ The replication works by intercepting events as they are enqueued and sending th The main components in the replicated queue manager are: -- **[`ReplicatedQueueManager`](./core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java)**: Core queue manager that wraps the default `InMemoryQueueManager` and handles event replication. -- **[`ReplicationStrategy`](./core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java)**: Interface for different replication implementations. If `ReplicatedQueueManager` is used, a `ReplicationStrategy` **must** be provided. +- **[`ReplicatedQueueManager`](./core/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManager.java)**: Core queue manager that wraps the default `InMemoryQueueManager` and handles event replication. +- **[`ReplicationStrategy`](./core/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicationStrategy.java)**: Interface for different replication implementations. If `ReplicatedQueueManager` is used, a `ReplicationStrategy` **must** be provided. -Currently, one implementation is provided: [`ReactiveMessagingReplicationStrategy`](./replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java), which uses MicroProfile Reactive Messaging with message brokers like Apache Kafka. +Currently, one implementation is provided: [`ReactiveMessagingReplicationStrategy`](./replication-mp-reactive/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java), which uses MicroProfile Reactive Messaging with message brokers like Apache Kafka. ## Quick Start @@ -310,8 +310,8 @@ No configuration is required for the poison pill mechanism - it works automatica Enable debug logging to monitor poison pill delivery: ```properties -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -quarkus.log.category."io.a2a.extras.taskstore.database.jpa".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.queuemanager.replicated".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.taskstore.database.jpa".level=DEBUG ``` You should see log entries like: @@ -347,7 +347,7 @@ a2a.replication.grace-period-seconds=15 **Monitoring**: ```properties -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.queuemanager.replicated".level=DEBUG ``` Watch for: @@ -396,7 +396,7 @@ Enable debug logging to monitor replication activity: ```properties # For Quarkus -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.queuemanager.replicated".level=DEBUG # For other servers, configure your logging framework accordingly ``` diff --git a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java b/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java deleted file mode 100644 index fed85db64..000000000 --- a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.core; - -import io.a2a.spec.Event; - -public interface ReplicationStrategy { - void send(String taskId, Event event); -} \ No newline at end of file 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/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java similarity index 90% rename from extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java rename to extras/queue-manager-replicated/core/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java index 206e07f03..0e6eb9cc3 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/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java @@ -1,9 +1,9 @@ -package io.a2a.extras.queuemanager.replicated.core; +package org.a2aproject.sdk.extras.queuemanager.replicated.core; -import io.a2a.server.events.EventQueueItem; -import io.a2a.spec.A2AError; -import io.a2a.spec.Event; -import io.a2a.spec.StreamingEventKind; +import org.a2aproject.sdk.server.events.EventQueueItem; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.StreamingEventKind; public class ReplicatedEventQueueItem implements EventQueueItem { private String taskId; @@ -35,7 +35,7 @@ public ReplicatedEventQueueItem(String taskId, A2AError error) { // Backward compatibility constructor for generic Event objects public ReplicatedEventQueueItem(String taskId, Event event) { this.taskId = taskId; - if (event instanceof io.a2a.server.events.QueueClosedEvent) { + if (event instanceof org.a2aproject.sdk.server.events.QueueClosedEvent) { this.event = null; this.error = null; this.closedEvent = true; @@ -95,7 +95,7 @@ public void setError(A2AError error) { @Override public Event getEvent() { if (closedEvent) { - return new io.a2a.server.events.QueueClosedEvent(taskId); + return new org.a2aproject.sdk.server.events.QueueClosedEvent(taskId); } if (event != null) { return event; @@ -156,7 +156,7 @@ public void setClosedEvent(boolean closedEvent) { * @return true if this is a Task event */ public boolean isTaskEvent() { - return event instanceof io.a2a.spec.Task; + return event instanceof org.a2aproject.sdk.spec.Task; } @Override 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/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManager.java similarity index 90% rename from extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java rename to extras/queue-manager-replicated/core/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManager.java index a5e3c629c..8ab19410d 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/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManager.java @@ -1,4 +1,4 @@ -package io.a2a.extras.queuemanager.replicated.core; +package org.a2aproject.sdk.extras.queuemanager.replicated.core; import jakarta.annotation.Priority; import jakarta.enterprise.context.ApplicationScoped; @@ -7,15 +7,15 @@ import jakarta.enterprise.inject.Alternative; import jakarta.inject.Inject; -import io.a2a.extras.common.events.TaskFinalizedEvent; -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.MainEventBus; -import io.a2a.server.events.QueueManager; -import io.a2a.server.tasks.TaskStateProvider; +import org.a2aproject.sdk.extras.common.events.TaskFinalizedEvent; +import org.a2aproject.sdk.server.events.EventEnqueueHook; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.events.EventQueueFactory; +import org.a2aproject.sdk.server.events.EventQueueItem; +import org.a2aproject.sdk.server.events.InMemoryQueueManager; +import org.a2aproject.sdk.server.events.MainEventBus; +import org.a2aproject.sdk.server.events.QueueManager; +import org.a2aproject.sdk.server.tasks.TaskStateProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -159,13 +159,13 @@ public void onReplicatedEvent(@Observes ReplicatedEventQueueItem replicatedEvent */ public void onTaskFinalized(@Observes(during = TransactionPhase.AFTER_SUCCESS) TaskFinalizedEvent event) { String taskId = event.getTaskId(); - io.a2a.spec.Task finalTask = (io.a2a.spec.Task) event.getTask(); // Cast from Object + org.a2aproject.sdk.spec.Task finalTask = (org.a2aproject.sdk.spec.Task) event.getTask(); // Cast from Object LOGGER.debug("Task {} finalized - sending TaskStatusUpdateEvent then poison pill (QueueClosedEvent) after transaction commit", taskId); // Convert final Task to TaskStatusUpdateEvent to match local event distribution // This ensures remote instances receive the same event type as local instances - io.a2a.spec.TaskStatusUpdateEvent finalStatusEvent = io.a2a.spec.TaskStatusUpdateEvent.builder() + org.a2aproject.sdk.spec.TaskStatusUpdateEvent finalStatusEvent = org.a2aproject.sdk.spec.TaskStatusUpdateEvent.builder() .taskId(taskId) .contextId(finalTask.contextId()) .status(finalTask.status()) @@ -176,7 +176,7 @@ public void onTaskFinalized(@Observes(during = TransactionPhase.AFTER_SUCCESS) T // Then send poison pill // The transaction has committed, so the final state is guaranteed to be in the database - io.a2a.server.events.QueueClosedEvent closedEvent = new io.a2a.server.events.QueueClosedEvent(taskId); + org.a2aproject.sdk.server.events.QueueClosedEvent closedEvent = new org.a2aproject.sdk.server.events.QueueClosedEvent(taskId); replicationStrategy.send(taskId, closedEvent); } diff --git a/extras/queue-manager-replicated/core/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicationStrategy.java b/extras/queue-manager-replicated/core/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicationStrategy.java new file mode 100644 index 000000000..965bcaafd --- /dev/null +++ b/extras/queue-manager-replicated/core/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicationStrategy.java @@ -0,0 +1,7 @@ +package org.a2aproject.sdk.extras.queuemanager.replicated.core; + +import org.a2aproject.sdk.spec.Event; + +public interface ReplicationStrategy { + void send(String taskId, Event event); +} \ No newline at end of file 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/org/a2aproject/sdk/extras/queuemanager/replicated/core/EventSerializationTest.java similarity index 93% rename from extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/EventSerializationTest.java rename to extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/EventSerializationTest.java index 04fa5d024..84e6d068e 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/org/a2aproject/sdk/extras/queuemanager/replicated/core/EventSerializationTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.queuemanager.replicated.core; +package org.a2aproject.sdk.extras.queuemanager.replicated.core; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -9,30 +9,30 @@ import java.util.List; -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.Message; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.UnsupportedOperationError; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.events.QueueClosedEvent; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.junit.jupiter.api.Test; /** 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/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java similarity index 94% rename from extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java rename to extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java index 7c830fb64..8998c2195 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/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.queuemanager.replicated.core; +package org.a2aproject.sdk.extras.queuemanager.replicated.core; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -16,24 +16,24 @@ import java.util.concurrent.TimeUnit; 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; -import io.a2a.server.events.EventQueueTestHelper; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.server.events.QueueClosedEvent; -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.Event; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.extras.common.events.TaskFinalizedEvent; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.events.EventQueueClosedException; +import org.a2aproject.sdk.server.events.EventQueueItem; +import org.a2aproject.sdk.server.events.EventQueueTestHelper; +import org.a2aproject.sdk.server.events.EventQueueUtil; +import org.a2aproject.sdk.server.events.MainEventBus; +import org.a2aproject.sdk.server.events.MainEventBusProcessor; +import org.a2aproject.sdk.server.events.QueueClosedEvent; +import org.a2aproject.sdk.server.tasks.InMemoryTaskStore; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -103,9 +103,9 @@ void tearDown() { */ private void waitForEventProcessing(Runnable action) throws InterruptedException { CountDownLatch processingLatch = new CountDownLatch(1); - mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { + mainEventBusProcessor.setCallback(new org.a2aproject.sdk.server.events.MainEventBusProcessorCallback() { @Override - public void onEventProcessed(String taskId, io.a2a.spec.Event event) { + public void onEventProcessed(String taskId, org.a2aproject.sdk.spec.Event event) { processingLatch.countDown(); } @@ -315,16 +315,16 @@ void testParallelReplicationBehavior() throws InterruptedException { java.util.concurrent.CyclicBarrier barrier = new java.util.concurrent.CyclicBarrier(numThreads); // Track processed events for better diagnostics on failure - java.util.concurrent.CopyOnWriteArrayList processedEvents = + java.util.concurrent.CopyOnWriteArrayList processedEvents = new java.util.concurrent.CopyOnWriteArrayList<>(); // Set up callback to wait for ALL events to be processed by MainEventBusProcessor // Must wait for all 50 events (25 normal + 25 replicated) to ensure all normal events // have triggered replication before we check the count CountDownLatch processingLatch = new CountDownLatch(totalEventCount); - mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { + mainEventBusProcessor.setCallback(new org.a2aproject.sdk.server.events.MainEventBusProcessorCallback() { @Override - public void onEventProcessed(String tid, io.a2a.spec.Event event) { + public void onEventProcessed(String tid, org.a2aproject.sdk.spec.Event event) { processedEvents.add(event); processingLatch.countDown(); } @@ -645,7 +645,7 @@ public Event getLastEvent() { } - private static class MockTaskStateProvider implements io.a2a.server.tasks.TaskStateProvider { + private static class MockTaskStateProvider implements org.a2aproject.sdk.server.tasks.TaskStateProvider { private volatile boolean active; public MockTaskStateProvider(boolean active) { diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueTestHelper.java b/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/server/events/EventQueueTestHelper.java similarity index 51% rename from extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueTestHelper.java rename to extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/server/events/EventQueueTestHelper.java index 1b095889b..27017a765 100644 --- a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueTestHelper.java +++ b/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/server/events/EventQueueTestHelper.java @@ -1,7 +1,7 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; /** - * Utils to access package private methods in the io.a2a.server.events package + * Utils to access package private methods in the org.a2aproject.sdk.server.events package */ public class EventQueueTestHelper { public static EventQueue tapQueue(EventQueue queue) { diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java b/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/server/events/EventQueueUtil.java similarity index 84% rename from extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java rename to extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/server/events/EventQueueUtil.java index a91575aaa..1cc714fdd 100644 --- a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java +++ b/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/server/events/EventQueueUtil.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; public class EventQueueUtil { public static void start(MainEventBusProcessor processor) { 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/org/a2aproject/sdk/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java similarity index 86% rename from extras/queue-manager-replicated/replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java rename to extras/queue-manager-replicated/replication-mp-reactive/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java index 6f0ca9876..e0ffccb7f 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/org/a2aproject/sdk/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java @@ -1,12 +1,12 @@ -package io.a2a.extras.queuemanager.replicated.mp_reactive; +package org.a2aproject.sdk.extras.queuemanager.replicated.mp_reactive; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Event; import jakarta.inject.Inject; -import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; -import io.a2a.extras.queuemanager.replicated.core.ReplicationStrategy; -import io.a2a.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; +import org.a2aproject.sdk.extras.queuemanager.replicated.core.ReplicationStrategy; +import org.a2aproject.sdk.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; @@ -26,7 +26,7 @@ public class ReactiveMessagingReplicationStrategy implements ReplicationStrategy private Event cdiEvent; @Override - public void send(String taskId, io.a2a.spec.Event event) { + public void send(String taskId, org.a2aproject.sdk.spec.Event event) { LOGGER.debug("Sending replicated event for task: {}, event: {}", taskId, event); try { 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/org/a2aproject/sdk/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java similarity index 90% rename from extras/queue-manager-replicated/replication-mp-reactive/src/test/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java rename to extras/queue-manager-replicated/replication-mp-reactive/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java index d1f48aeb4..08d54009f 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/org/a2aproject/sdk/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.queuemanager.replicated.mp_reactive; +package org.a2aproject.sdk.extras.queuemanager.replicated.mp_reactive; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -10,12 +10,12 @@ 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.a2aproject.sdk.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.eclipse.microprofile.reactive.messaging.Emitter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java similarity index 53% rename from extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java rename to extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java index 4594f10b4..5d4dd8353 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java @@ -1,11 +1,11 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.app1; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.app1; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentCards; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCard; +import org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentCards; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCard; @ApplicationScoped public class MultiInstanceReplicationApp1AgentCardProducer { diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java similarity index 53% rename from extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java rename to extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java index f45a58095..3ab499b5c 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java @@ -1,10 +1,10 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.app1; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.app1; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentExecutor; -import io.a2a.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentExecutor; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; @ApplicationScoped public class MultiInstanceReplicationApp1AgentExecutorProducer { diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties index ea64096cb..6376d4d9c 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties @@ -8,7 +8,7 @@ quarkus.datasource."a2a-java".username=${DATABASE_USER:a2auser} quarkus.datasource."a2a-java".password=${DATABASE_PASSWORD:a2apass} quarkus.hibernate-orm."a2a-java".datasource=a2a-java quarkus.hibernate-orm."a2a-java".database.generation=drop-and-create -quarkus.hibernate-orm."a2a-java".packages=io.a2a.extras.taskstore.database.jpa +quarkus.hibernate-orm."a2a-java".packages=org.a2aproject.sdk.extras.taskstore.database.jpa # Configure the outgoing channel (QueueManager -> Kafka) mp.messaging.outgoing.replicated-events-out.connector=smallrye-kafka @@ -32,9 +32,9 @@ quarkus.kafka.devservices.enabled=false quarkus.messaging.kafka.health.timeout=5s # Enable debug logging -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.server.tasks".level=DEBUG -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -quarkus.log.category."io.a2a.extras.taskstore.database.jpa".level=DEBUG -quarkus.log.category."io.a2a.client".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.queuemanager.replicated".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.taskstore.database.jpa".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.client".level=DEBUG diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java similarity index 53% rename from extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java rename to extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java index 6874601f0..686abac33 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java @@ -1,11 +1,11 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.app2; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.app2; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentCards; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCard; +import org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentCards; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCard; @ApplicationScoped public class MultiInstanceReplicationApp2AgentCardProducer { diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java similarity index 53% rename from extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java rename to extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java index d03388179..716435a59 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java @@ -1,10 +1,10 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.app2; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.app2; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentExecutor; -import io.a2a.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentExecutor; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; @ApplicationScoped public class MultiInstanceReplicationApp2AgentExecutorProducer { diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties index d9a495e8f..9170bcb45 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties @@ -8,7 +8,7 @@ quarkus.datasource."a2a-java".username=${DATABASE_USER:a2auser} quarkus.datasource."a2a-java".password=${DATABASE_PASSWORD:a2apass} quarkus.hibernate-orm."a2a-java".datasource=a2a-java quarkus.hibernate-orm."a2a-java".database.generation=drop-and-create -quarkus.hibernate-orm."a2a-java".packages=io.a2a.extras.taskstore.database.jpa +quarkus.hibernate-orm."a2a-java".packages=org.a2aproject.sdk.extras.taskstore.database.jpa # Configure the outgoing channel (QueueManager -> Kafka) mp.messaging.outgoing.replicated-events-out.connector=smallrye-kafka @@ -32,9 +32,9 @@ quarkus.kafka.devservices.enabled=false quarkus.messaging.kafka.health.timeout=5s # Enable debug logging -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.server.tasks".level=DEBUG -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -quarkus.log.category."io.a2a.extras.taskstore.database.jpa".level=DEBUG -quarkus.log.category."io.a2a.client".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.queuemanager.replicated".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.taskstore.database.jpa".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.client".level=DEBUG diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java similarity index 84% rename from extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java rename to extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java index 4d1133ad9..d659bdff9 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java @@ -1,14 +1,14 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.common; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.common; import java.util.Collections; import java.util.List; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.TransportProtocol; /** * Shared AgentCard factory for multi-instance replication tests. 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java similarity index 77% rename from extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java rename to extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java index d51ef8f32..66e50228e 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java @@ -1,11 +1,11 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.common; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance.common; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.Task; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TextPart; /** * Shared test agent executor for multi-instance replication tests. diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java similarity index 93% rename from extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java rename to extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java index 4104bdeb7..4a42d34a4 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests.multiinstance; import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -16,22 +16,22 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -import io.a2a.A2A; -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfig; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TransportProtocol; -import io.a2a.testutils.docker.RequiresDocker; +import org.a2aproject.sdk.A2A; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfig; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.a2aproject.sdk.testutils.docker.RequiresDocker; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -319,19 +319,19 @@ public void testMultiInstanceEventReplication() throws Exception { // App1 subscriber BiConsumer app1Subscriber = (event, card) -> { String eventDetail = event.getClass().getSimpleName(); - if (event instanceof io.a2a.client.TaskUpdateEvent tue) { + if (event instanceof org.a2aproject.sdk.client.TaskUpdateEvent tue) { eventDetail += " [" + tue.getUpdateEvent().getClass().getSimpleName(); - if (tue.getUpdateEvent() instanceof io.a2a.spec.TaskStatusUpdateEvent statusEvent) { + if (tue.getUpdateEvent() instanceof org.a2aproject.sdk.spec.TaskStatusUpdateEvent statusEvent) { eventDetail += ", state=" + (statusEvent.status() != null ? statusEvent.status().state() : "null"); } eventDetail += "]"; - } else if (event instanceof io.a2a.client.TaskEvent te) { + } else if (event instanceof org.a2aproject.sdk.client.TaskEvent te) { eventDetail += " [state=" + (te.getTask().status() != null ? te.getTask().status().state() : "null") + "]"; } System.out.println("APP1 received event: " + eventDetail); // Per A2A spec 3.1.6: Handle initial TaskEvent on subscribe - if (!app1ReceivedInitialTask.get() && event instanceof io.a2a.client.TaskEvent) { + if (!app1ReceivedInitialTask.get() && event instanceof org.a2aproject.sdk.client.TaskEvent) { app1ReceivedInitialTask.set(true); System.out.println("APP1 filtered initial TaskEvent"); // Don't count initial TaskEvent toward expected artifact/status events @@ -351,19 +351,19 @@ public void testMultiInstanceEventReplication() throws Exception { // App2 subscriber BiConsumer app2Subscriber = (event, card) -> { String eventDetail = event.getClass().getSimpleName(); - if (event instanceof io.a2a.client.TaskUpdateEvent tue) { + if (event instanceof org.a2aproject.sdk.client.TaskUpdateEvent tue) { eventDetail += " [" + tue.getUpdateEvent().getClass().getSimpleName(); - if (tue.getUpdateEvent() instanceof io.a2a.spec.TaskStatusUpdateEvent statusEvent) { + if (tue.getUpdateEvent() instanceof org.a2aproject.sdk.spec.TaskStatusUpdateEvent statusEvent) { eventDetail += ", state=" + (statusEvent.status() != null ? statusEvent.status().state() : "null"); } eventDetail += "]"; - } else if (event instanceof io.a2a.client.TaskEvent te) { + } else if (event instanceof org.a2aproject.sdk.client.TaskEvent te) { eventDetail += " [state=" + (te.getTask().status() != null ? te.getTask().status().state() : "null") + "]"; } System.out.println("APP2 received event: " + eventDetail); // Per A2A spec 3.1.6: Handle initial TaskEvent on subscribe - if (!app2ReceivedInitialTask.get() && event instanceof io.a2a.client.TaskEvent) { + if (!app2ReceivedInitialTask.get() && event instanceof org.a2aproject.sdk.client.TaskEvent) { app2ReceivedInitialTask.set(true); System.out.println("APP2 filtered initial TaskEvent"); // Don't count initial TaskEvent toward expected artifact/status events 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java similarity index 94% rename from extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java rename to extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java index 4e298905b..0b6e305ee 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.queuemanager.replicated.tests; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -20,29 +20,29 @@ import jakarta.inject.Inject; -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.client.config.ClientConfig; -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.EventQueue; -import io.a2a.server.events.QueueClosedEvent; -import io.a2a.server.events.QueueManager; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.testutils.docker.RequiresDocker; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.TaskEvent; +import org.a2aproject.sdk.client.TaskUpdateEvent; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.events.QueueClosedEvent; +import org.a2aproject.sdk.server.events.QueueManager; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.testutils.docker.RequiresDocker; import io.quarkus.test.junit.QuarkusTest; import org.eclipse.microprofile.reactive.messaging.Channel; import org.eclipse.microprofile.reactive.messaging.Emitter; @@ -175,7 +175,7 @@ public void testA2AMessageReplicatedToKafka() throws Exception { // Verify the replicated event content assertEquals(taskId, replicatedEvent.getTaskId()); - io.a2a.spec.Event receivedEvent = replicatedEvent.getEvent(); + org.a2aproject.sdk.spec.Event receivedEvent = replicatedEvent.getEvent(); assertNotNull(receivedEvent); // The event should now maintain its proper type through Kafka serialization 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java similarity index 71% rename from extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java rename to extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java index 55d650991..a3d2a4f23 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java @@ -1,12 +1,12 @@ -package io.a2a.extras.queuemanager.replicated.tests; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import jakarta.inject.Inject; -import io.a2a.extras.queuemanager.replicated.core.ReplicatedQueueManager; -import io.a2a.testutils.docker.RequiresDocker; -import io.a2a.server.events.QueueManager; +import org.a2aproject.sdk.extras.queuemanager.replicated.core.ReplicatedQueueManager; +import org.a2aproject.sdk.testutils.docker.RequiresDocker; +import org.a2aproject.sdk.server.events.QueueManager; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java similarity index 79% rename from extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java rename to extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java index 3461ab7d4..14e2f3e58 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java @@ -1,4 +1,4 @@ -package io.a2a.extras.queuemanager.replicated.tests; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests; import java.util.List; @@ -6,11 +6,11 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.TransportProtocol; import io.quarkus.arc.profile.IfBuildProfile; /** 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java similarity index 83% rename from extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java rename to extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java index 8e934df7e..f65352e8d 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java @@ -1,18 +1,18 @@ -package io.a2a.extras.queuemanager.replicated.tests; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests; 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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import io.quarkus.arc.profile.IfBuildProfile; /** 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java similarity index 96% rename from extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java rename to extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java index a7edd13d3..7c9c501dc 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/org/a2aproject/sdk/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java @@ -1,4 +1,4 @@ -package io.a2a.extras.queuemanager.replicated.tests; +package org.a2aproject.sdk.extras.queuemanager.replicated.tests; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; @@ -6,8 +6,8 @@ import jakarta.enterprise.context.ApplicationScoped; -import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; -import io.a2a.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; import io.quarkus.arc.profile.IfBuildProfile; import org.eclipse.microprofile.reactive.messaging.Incoming; diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/resources/application.properties b/extras/queue-manager-replicated/tests-single-instance/src/test/resources/application.properties index 15aed5bc3..39ffe8931 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/resources/application.properties +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/resources/application.properties @@ -3,7 +3,7 @@ quarkus.datasource."a2a-java".db-kind=h2 quarkus.datasource."a2a-java".jdbc.url=jdbc:h2:mem:test quarkus.hibernate-orm."a2a-java".datasource=a2a-java quarkus.hibernate-orm."a2a-java".database.generation=drop-and-create -quarkus.hibernate-orm."a2a-java".packages=io.a2a.extras.taskstore.database.jpa +quarkus.hibernate-orm."a2a-java".packages=org.a2aproject.sdk.extras.taskstore.database.jpa # Configure the outgoing channel (QueueManager -> Kafka) mp.messaging.outgoing.replicated-events-out.connector=smallrye-kafka @@ -32,9 +32,9 @@ mp.messaging.incoming.test-replicated-events-in.group.id=test-consumer-group quarkus.messaging.kafka.health.timeout=5s # Enable debug logging for queue lifecycle and Kafka -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -quarkus.log.category."io.a2a.client".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.extras.queuemanager.replicated".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.client".level=DEBUG quarkus.log.category."io.smallrye.reactive.messaging".level=DEBUG diff --git a/extras/task-store-database-jpa/README.md b/extras/task-store-database-jpa/README.md index 117e357dd..42a5865af 100644 --- a/extras/task-store-database-jpa/README.md +++ b/extras/task-store-database-jpa/README.md @@ -49,7 +49,7 @@ Create or update your `persistence.xml`: java:jboss/datasources/A2ADataSource - io.a2a.extras.taskstore.database.jpa.JpaTask + org.a2aproject.sdk.extras.taskstore.database.jpa.JpaTask true 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/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java similarity index 95% rename from extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java rename to extras/task-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java index 3a704ee2a..b22d3fca5 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/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java @@ -1,4 +1,4 @@ -package io.a2a.extras.taskstore.database.jpa; +package org.a2aproject.sdk.extras.taskstore.database.jpa; import java.time.Duration; import java.time.Instant; @@ -17,19 +17,19 @@ import jakarta.persistence.TypedQuery; import jakarta.transaction.Transactional; -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.server.tasks.TaskSerializationException; -import io.a2a.server.tasks.TaskPersistenceException; -import io.a2a.spec.Artifact; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.util.PageToken; -import io.a2a.spec.Task; +import org.a2aproject.sdk.extras.common.events.TaskFinalizedEvent; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.server.config.A2AConfigProvider; +import org.a2aproject.sdk.server.tasks.TaskStateProvider; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.server.tasks.TaskSerializationException; +import org.a2aproject.sdk.server.tasks.TaskPersistenceException; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.util.PageToken; +import org.a2aproject.sdk.spec.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaTask.java similarity index 93% rename from extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaTask.java rename to extras/task-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaTask.java index 5a9477f2f..25091226c 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/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaTask.java @@ -1,4 +1,4 @@ -package io.a2a.extras.taskstore.database.jpa; +package org.a2aproject.sdk.extras.taskstore.database.jpa; import java.time.Instant; @@ -8,9 +8,9 @@ import jakarta.persistence.Table; import jakarta.persistence.Transient; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.Task; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.Task; @Entity @Table(name = "a2a_tasks") @@ -141,7 +141,7 @@ static JpaTask createFromTask(Task task) throws JsonProcessingException { */ private void updateDenormalizedFields(Task task) { this.contextId = task.contextId(); - io.a2a.spec.TaskState taskState = task.status().state(); + org.a2aproject.sdk.spec.TaskState taskState = task.status().state(); this.state = taskState.name(); // Extract status timestamp for efficient querying and sorting // Truncate to milliseconds for keyset pagination consistency (pageToken uses millis) diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java b/extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java similarity index 85% rename from extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java rename to extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java index 02602cdda..5f93de75e 100644 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java +++ b/extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.taskstore.database.jpa; +package org.a2aproject.sdk.extras.taskstore.database.jpa; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -14,22 +14,22 @@ import jakarta.inject.Inject; -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.TaskEvent; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TextPart; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; 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/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java similarity index 98% rename from extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java rename to extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java index 74164e39e..ababb7977 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/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java @@ -1,4 +1,4 @@ -package io.a2a.extras.taskstore.database.jpa; +package org.a2aproject.sdk.extras.taskstore.database.jpa; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -15,15 +15,15 @@ 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.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TextPart; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; @@ -727,7 +727,7 @@ public void testListTasksInvalidPageTokenFormat() { try { taskStore.list(params1); throw new AssertionError("Expected InvalidParamsError for legacy ID-only pageToken"); - } catch (io.a2a.spec.InvalidParamsError e) { + } catch (org.a2aproject.sdk.spec.InvalidParamsError e) { // Expected - legacy format not supported assertTrue(e.getMessage().contains("Invalid pageToken format"), "Error message should mention invalid format"); @@ -743,7 +743,7 @@ public void testListTasksInvalidPageTokenFormat() { try { taskStore.list(params2); throw new AssertionError("Expected InvalidParamsError for malformed timestamp"); - } catch (io.a2a.spec.InvalidParamsError e) { + } catch (org.a2aproject.sdk.spec.InvalidParamsError e) { // Expected - malformed timestamp assertTrue(e.getMessage().contains("timestamp must be numeric"), "Error message should mention numeric timestamp requirement"); diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java b/extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java similarity index 78% rename from extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java rename to extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java index 00c055801..32ce758c3 100644 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java +++ b/extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java @@ -1,4 +1,4 @@ -package io.a2a.extras.taskstore.database.jpa; +package org.a2aproject.sdk.extras.taskstore.database.jpa; import java.util.Collections; import java.util.List; @@ -6,11 +6,11 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.TransportProtocol; import io.quarkus.arc.profile.IfBuildProfile; /** 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/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java similarity index 80% rename from extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java rename to extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java index fd530a761..30bd21195 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/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java @@ -1,18 +1,18 @@ -package io.a2a.extras.taskstore.database.jpa; +package org.a2aproject.sdk.extras.taskstore.database.jpa; 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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import io.quarkus.arc.profile.IfBuildProfile; /** diff --git a/extras/task-store-database-jpa/src/test/resources/META-INF/persistence.xml b/extras/task-store-database-jpa/src/test/resources/META-INF/persistence.xml index e80e61c86..57acdb4f5 100644 --- a/extras/task-store-database-jpa/src/test/resources/META-INF/persistence.xml +++ b/extras/task-store-database-jpa/src/test/resources/META-INF/persistence.xml @@ -10,7 +10,7 @@ A2A Java SDK JPA TaskStore Test Configuration - io.a2a.extras.taskstore.database.jpa.JpaTask + org.a2aproject.sdk.extras.taskstore.database.jpa.JpaTask true diff --git a/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java similarity index 90% rename from http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java rename to http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java index 6cbcd949e..d1edf49b8 100644 --- a/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import java.io.IOException; @@ -6,18 +6,18 @@ import java.net.URISyntaxException; import java.util.Map; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -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.A2AError; +import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.spec.A2AClientError; +import org.a2aproject.sdk.spec.A2AClientJSONError; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.A2AError; import org.jspecify.annotations.Nullable; -import static io.a2a.util.Assert.checkNotNullParam; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; -import io.a2a.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentInterface; /** * Utility for fetching agent cards from A2A agents. @@ -146,7 +146,7 @@ public A2ACardResolver(A2AHttpClient httpClient, String baseUrl, @Nullable Strin this.httpClient = httpClient; String effectiveAgentCardPath = (agentCardPath == null || agentCardPath.isEmpty()) ? DEFAULT_AGENT_CARD_PATH : agentCardPath; try { - this.url = new URI(io.a2a.util.Utils.buildBaseUrl(new AgentInterface("JSONRPC", baseUrl, ""), tenant)).resolve(effectiveAgentCardPath).toString(); + this.url = new URI(org.a2aproject.sdk.util.Utils.buildBaseUrl(new AgentInterface("JSONRPC", baseUrl, ""), tenant)).resolve(effectiveAgentCardPath).toString(); } catch (URISyntaxException e) { throw new A2AClientError("Invalid agent URL", e); } @@ -183,7 +183,7 @@ public AgentCard getAgentCard() throws A2AClientError, A2AClientJSONError { } try { - io.a2a.grpc.AgentCard.Builder agentCardBuilder = io.a2a.grpc.AgentCard.newBuilder(); + org.a2aproject.sdk.grpc.AgentCard.Builder agentCardBuilder = org.a2aproject.sdk.grpc.AgentCard.newBuilder(); JSONRPCUtils.parseJsonString(body, agentCardBuilder, ""); return ProtoUtils.FromProto.agentCard(agentCardBuilder); } catch (A2AError | JsonProcessingException e) { diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClient.java similarity index 99% rename from http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java rename to http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClient.java index 1529f3e14..652bc2451 100644 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClient.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import java.io.IOException; import java.util.Map; diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpClientFactory.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java similarity index 96% rename from http-client/src/main/java/io/a2a/client/http/A2AHttpClientFactory.java rename to http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java index 05bac3112..97ace7996 100644 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpClientFactory.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import java.util.Comparator; import java.util.ServiceLoader; @@ -36,7 +36,7 @@ *

              Custom Providers

              *

              * To add a custom provider, implement {@link A2AHttpClientProvider} and register it - * in {@code META-INF/services/io.a2a.client.http.A2AHttpClientProvider}. + * in {@code META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider}. */ public final class A2AHttpClientFactory { diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpClientProvider.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientProvider.java similarity index 89% rename from http-client/src/main/java/io/a2a/client/http/A2AHttpClientProvider.java rename to http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientProvider.java index 8c33c66e6..9af62f10e 100644 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpClientProvider.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientProvider.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; /** * Service provider interface for creating {@link A2AHttpClient} instances. @@ -10,7 +10,7 @@ * *

              * To register a provider, create a file named - * {@code META-INF/services/io.a2a.client.http.A2AHttpClientProvider} containing + * {@code META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider} containing * the fully qualified class name of your provider implementation. */ public interface A2AHttpClientProvider { diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpResponse.java similarity index 96% rename from http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java rename to http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpResponse.java index 837636bcc..3084b8ddc 100644 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpResponse.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; /** * HTTP response wrapper containing status code and response body. diff --git a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java similarity index 98% rename from http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java rename to http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java index e41f36a1c..6c8f7ec53 100644 --- a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java @@ -1,6 +1,6 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; -import static io.a2a.util.Assert.checkNotNullParam; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; import static java.net.HttpURLConnection.HTTP_FORBIDDEN; import static java.net.HttpURLConnection.HTTP_MULT_CHOICE; import static java.net.HttpURLConnection.HTTP_OK; @@ -24,7 +24,7 @@ import java.util.function.Consumer; import org.jspecify.annotations.Nullable; -import io.a2a.common.A2AErrorMessages; +import org.a2aproject.sdk.common.A2AErrorMessages; /** * Default HTTP client implementation using JDK 11+ {@link HttpClient}. diff --git a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClientProvider.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClientProvider.java similarity index 93% rename from http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClientProvider.java rename to http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClientProvider.java index 1bf388286..4b53d41f6 100644 --- a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClientProvider.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClientProvider.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; /** * Service provider for {@link JdkA2AHttpClient}. diff --git a/http-client/src/main/java/io/a2a/client/http/package-info.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/package-info.java similarity index 67% rename from http-client/src/main/java/io/a2a/client/http/package-info.java rename to http-client/src/main/java/org/a2aproject/sdk/client/http/package-info.java index 667c28f5a..b4b33edc0 100644 --- a/http-client/src/main/java/io/a2a/client/http/package-info.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/package-info.java @@ -7,17 +7,17 @@ * *

              Core Components

              *
                - *
              • {@link io.a2a.client.http.A2AHttpClient} - Main HTTP client interface with builder pattern
              • - *
              • {@link io.a2a.client.http.A2AHttpClientFactory} - Factory for creating client instances via ServiceLoader
              • - *
              • {@link io.a2a.client.http.A2ACardResolver} - Utility for fetching agent cards from standard endpoints
              • - *
              • {@link io.a2a.client.http.A2AHttpResponse} - Response wrapper with status and body
              • + *
              • {@link org.a2aproject.sdk.client.http.A2AHttpClient} - Main HTTP client interface with builder pattern
              • + *
              • {@link org.a2aproject.sdk.client.http.A2AHttpClientFactory} - Factory for creating client instances via ServiceLoader
              • + *
              • {@link org.a2aproject.sdk.client.http.A2ACardResolver} - Utility for fetching agent cards from standard endpoints
              • + *
              • {@link org.a2aproject.sdk.client.http.A2AHttpResponse} - Response wrapper with status and body
              • *
              * *

              Provider System

              *

              The module uses a ServiceLoader-based provider system allowing different HTTP client * implementations to be plugged in: *

                - *
              • {@link io.a2a.client.http.JdkA2AHttpClient} - Default implementation using JDK 11+ HttpClient (priority 0)
              • + *
              • {@link org.a2aproject.sdk.client.http.JdkA2AHttpClient} - Default implementation using JDK 11+ HttpClient (priority 0)
              • *
              • VertxA2AHttpClient - Vertx-based implementation when available (priority 100)
              • *
              * @@ -49,12 +49,12 @@ *

              Agent cards are fetched from the standard {@code /.well-known/agent-card.json} endpoint * by default, with support for tenant-specific paths and custom authentication headers. * - * @see io.a2a.client.http.A2AHttpClient - * @see io.a2a.client.http.A2ACardResolver - * @see io.a2a.spec.AgentCard + * @see org.a2aproject.sdk.client.http.A2AHttpClient + * @see org.a2aproject.sdk.client.http.A2ACardResolver + * @see org.a2aproject.sdk.spec.AgentCard */ @NullMarked -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import org.jspecify.annotations.NullMarked; diff --git a/http-client/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider b/http-client/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider deleted file mode 100644 index 78dbb361e..000000000 --- a/http-client/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.http.JdkA2AHttpClientProvider diff --git a/http-client/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider b/http-client/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider new file mode 100644 index 000000000..e73f1994d --- /dev/null +++ b/http-client/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider @@ -0,0 +1 @@ +org.a2aproject.sdk.client.http.JdkA2AHttpClientProvider diff --git a/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java similarity index 92% rename from http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java rename to http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java index 3254992ef..19c91ded8 100644 --- a/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,12 +10,12 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientJSONError; -import io.a2a.spec.AgentCard; +import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.spec.A2AClientError; +import org.a2aproject.sdk.spec.A2AClientJSONError; +import org.a2aproject.sdk.spec.AgentCard; import java.util.Map; import org.junit.jupiter.api.Test; @@ -81,7 +81,7 @@ public void testGetAgentCardSuccess() throws Exception { } private AgentCard unmarshalFrom(String body) throws JsonProcessingException { - io.a2a.grpc.AgentCard.Builder agentCardBuilder = io.a2a.grpc.AgentCard.newBuilder(); + org.a2aproject.sdk.grpc.AgentCard.Builder agentCardBuilder = org.a2aproject.sdk.grpc.AgentCard.newBuilder(); JSONRPCUtils.parseJsonString(body, agentCardBuilder, ""); return ProtoUtils.FromProto.agentCard(agentCardBuilder); } diff --git a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryTest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientFactoryTest.java similarity index 98% rename from http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryTest.java rename to http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientFactoryTest.java index 72de52230..814b01c33 100644 --- a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryTest.java +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientFactoryTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import static org.junit.jupiter.api.Assertions.*; diff --git a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryUsageExample.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientFactoryUsageExample.java similarity index 99% rename from http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryUsageExample.java rename to http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientFactoryUsageExample.java index 86da8c8cf..203810ed6 100644 --- a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryUsageExample.java +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientFactoryUsageExample.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import java.io.IOException; diff --git a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientProviderTest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientProviderTest.java similarity index 95% rename from http-client/src/test/java/io/a2a/client/http/A2AHttpClientProviderTest.java rename to http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientProviderTest.java index b2e222517..525b0b505 100644 --- a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientProviderTest.java +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2AHttpClientProviderTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import static org.junit.jupiter.api.Assertions.*; diff --git a/http-client/src/test/java/io/a2a/client/http/JdkA2AHttpClientTest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/JdkA2AHttpClientTest.java similarity index 98% rename from http-client/src/test/java/io/a2a/client/http/JdkA2AHttpClientTest.java rename to http-client/src/test/java/org/a2aproject/sdk/client/http/JdkA2AHttpClientTest.java index 48e10a86c..a9c0c62d0 100644 --- a/http-client/src/test/java/io/a2a/client/http/JdkA2AHttpClientTest.java +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/JdkA2AHttpClientTest.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/http-client/src/test/java/io/a2a/client/http/JsonMessages.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/JsonMessages.java similarity index 99% rename from http-client/src/test/java/io/a2a/client/http/JsonMessages.java rename to http-client/src/test/java/org/a2aproject/sdk/client/http/JsonMessages.java index 89d146787..1f6cd24cd 100644 --- a/http-client/src/test/java/io/a2a/client/http/JsonMessages.java +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/JsonMessages.java @@ -1,4 +1,4 @@ -package io.a2a.client.http; +package org.a2aproject.sdk.client.http; /** * Request and response messages used by the tests. These have been created following examples from diff --git a/integrations/microprofile-config/README.md b/integrations/microprofile-config/README.md index 48559894d..ed9fd74ac 100644 --- a/integrations/microprofile-config/README.md +++ b/integrations/microprofile-config/README.md @@ -20,7 +20,7 @@ This module provides `MicroProfileConfigProvider`, which integrates with MicroPr org.a2aproject.sdk a2a-java-sdk-microprofile-config - ${io.a2a.sdk.version} + ${org.a2aproject.sdk.version} ``` @@ -94,8 +94,8 @@ This module works with any MicroProfile Config implementation: If you're using a different framework (Spring, Micronaut, etc.), you can implement your own `A2AConfigProvider`: ```java -import io.a2a.server.config.A2AConfigProvider; -import io.a2a.server.config.DefaultValuesConfigProvider; +import org.a2aproject.sdk.server.config.A2AConfigProvider; +import org.a2aproject.sdk.server.config.DefaultValuesConfigProvider; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Alternative; import jakarta.annotation.Priority; @@ -135,7 +135,7 @@ public class OtherEnvironmentConfigProvider implements A2AConfigProvider { ## Implementation Details -- **Package**: `io.a2a.integrations.microprofile` +- **Package**: `org.a2aproject.sdk.integrations.microprofile` - **Class**: `MicroProfileConfigProvider` - **Priority**: 50 (can be overridden) - **Scope**: `@ApplicationScoped` diff --git a/integrations/microprofile-config/src/main/java/io/a2a/integrations/microprofile/MicroProfileConfigProvider.java b/integrations/microprofile-config/src/main/java/org/a2aproject/sdk/integrations/microprofile/MicroProfileConfigProvider.java similarity index 93% rename from integrations/microprofile-config/src/main/java/io/a2a/integrations/microprofile/MicroProfileConfigProvider.java rename to integrations/microprofile-config/src/main/java/org/a2aproject/sdk/integrations/microprofile/MicroProfileConfigProvider.java index 666c2d612..9cae3962d 100644 --- a/integrations/microprofile-config/src/main/java/io/a2a/integrations/microprofile/MicroProfileConfigProvider.java +++ b/integrations/microprofile-config/src/main/java/org/a2aproject/sdk/integrations/microprofile/MicroProfileConfigProvider.java @@ -1,4 +1,4 @@ -package io.a2a.integrations.microprofile; +package org.a2aproject.sdk.integrations.microprofile; import java.util.Optional; @@ -7,8 +7,8 @@ import jakarta.annotation.Priority; import jakarta.inject.Inject; -import io.a2a.server.config.A2AConfigProvider; -import io.a2a.server.config.DefaultValuesConfigProvider; +import org.a2aproject.sdk.server.config.A2AConfigProvider; +import org.a2aproject.sdk.server.config.DefaultValuesConfigProvider; import org.eclipse.microprofile.config.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/integrations/microprofile-config/src/test/java/io/a2a/integrations/microprofile/MicroProfileConfigProviderTest.java b/integrations/microprofile-config/src/test/java/org/a2aproject/sdk/integrations/microprofile/MicroProfileConfigProviderTest.java similarity index 97% rename from integrations/microprofile-config/src/test/java/io/a2a/integrations/microprofile/MicroProfileConfigProviderTest.java rename to integrations/microprofile-config/src/test/java/org/a2aproject/sdk/integrations/microprofile/MicroProfileConfigProviderTest.java index 6ad911145..2d85911ac 100644 --- a/integrations/microprofile-config/src/test/java/io/a2a/integrations/microprofile/MicroProfileConfigProviderTest.java +++ b/integrations/microprofile-config/src/test/java/org/a2aproject/sdk/integrations/microprofile/MicroProfileConfigProviderTest.java @@ -1,4 +1,4 @@ -package io.a2a.integrations.microprofile; +package org.a2aproject.sdk.integrations.microprofile; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,7 +10,7 @@ import jakarta.inject.Inject; -import io.a2a.server.config.A2AConfigProvider; +import org.a2aproject.sdk.server.config.A2AConfigProvider; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; diff --git a/integrations/microprofile-config/src/test/resources/application.properties b/integrations/microprofile-config/src/test/resources/application.properties index a79c9b843..da7a65761 100644 --- a/integrations/microprofile-config/src/test/resources/application.properties +++ b/integrations/microprofile-config/src/test/resources/application.properties @@ -8,7 +8,7 @@ a2a.executor.core-pool-size=15 # Default value should be 50 from META-INF/a2a-defaults.properties # Exclude beans that aren't needed for config testing -quarkus.arc.exclude-types=io.a2a.server.requesthandlers.*,io.a2a.server.agentexecution.*,io.a2a.server.tasks.*,io.a2a.server.events.*,io.a2a.server.util.* +quarkus.arc.exclude-types=org.a2aproject.sdk.server.requesthandlers.*,org.a2aproject.sdk.server.agentexecution.*,org.a2aproject.sdk.server.tasks.*,org.a2aproject.sdk.server.events.*,org.a2aproject.sdk.server.util.* # Property that will be overridden by a system property a2a.test.system.property=from-application-properties \ No newline at end of file diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/IdJsonMappingException.java similarity index 95% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/IdJsonMappingException.java index de56d119c..4edce5826 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/IdJsonMappingException.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; /** * JSON mapping exception that includes request ID for error tracking. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/InvalidParamsJsonMappingException.java similarity index 93% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/InvalidParamsJsonMappingException.java index 5ac8c769c..c69ca923a 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/InvalidParamsJsonMappingException.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; /** * Exception for invalid parameters during JSON mapping. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonMappingException.java similarity index 98% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonMappingException.java index dc85d6edb..591bc2874 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonMappingException.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; import org.jspecify.annotations.Nullable; diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonProcessingException.java similarity index 97% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonProcessingException.java index cdbb7b4eb..3320c2f7a 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonProcessingException.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; import org.jspecify.annotations.Nullable; diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtil.java similarity index 95% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtil.java index 3967cbf80..8b63981a4 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtil.java @@ -1,9 +1,9 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; -import static io.a2a.jsonrpc.common.json.JsonUtil.ThrowableTypeAdapter.THROWABLE_MARKER_FIELD; -import io.a2a.spec.A2AErrorCodes; -import static io.a2a.spec.DataPart.DATA; -import static io.a2a.spec.TextPart.TEXT; +import static org.a2aproject.sdk.jsonrpc.common.json.JsonUtil.ThrowableTypeAdapter.THROWABLE_MARKER_FIELD; +import org.a2aproject.sdk.spec.A2AErrorCodes; +import static org.a2aproject.sdk.spec.DataPart.DATA; +import static org.a2aproject.sdk.spec.TextPart.TEXT; import static java.lang.String.format; import static java.util.Collections.emptyMap; @@ -29,39 +29,39 @@ import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; -import io.a2a.spec.A2AError; -import io.a2a.spec.APIKeySecurityScheme; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.DataPart; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.FileContent; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.InvalidAgentResponseError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.Message; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.MutualTLSSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.SecurityScheme; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.APIKeySecurityScheme; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.FileContent; +import org.a2aproject.sdk.spec.FilePart; +import org.a2aproject.sdk.spec.FileWithBytes; +import org.a2aproject.sdk.spec.FileWithUri; +import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; +import org.a2aproject.sdk.spec.InvalidAgentResponseError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.MutualTLSSecurityScheme; +import org.a2aproject.sdk.spec.OAuth2SecurityScheme; +import org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.SecurityRequirement; +import org.a2aproject.sdk.spec.SecurityScheme; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; import org.jspecify.annotations.Nullable; @@ -388,7 +388,7 @@ private A2AError createErrorInstance(@Nullable Integer code, @Nullable String me case INVALID_REQUEST -> new InvalidRequestError(code, message, details); case METHOD_NOT_FOUND -> new MethodNotFoundError(code, message, details); case INVALID_PARAMS -> new InvalidParamsError(code, message, details); - case INTERNAL -> new io.a2a.spec.InternalError(code, message, details); + case INTERNAL -> new org.a2aproject.sdk.spec.InternalError(code, message, details); case TASK_NOT_FOUND -> new TaskNotFoundError(message, details); case TASK_NOT_CANCELABLE -> new TaskNotCancelableError(code, message, details); case PUSH_NOTIFICATION_NOT_SUPPORTED -> new PushNotificationNotSupportedError(code, message, details); diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/MethodNotFoundJsonMappingException.java similarity index 91% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/MethodNotFoundJsonMappingException.java index 5bac1c026..773ef92c4 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/MethodNotFoundJsonMappingException.java @@ -1,6 +1,6 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; -import io.a2a.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.MethodNotFoundError; /** * Exception thrown when JSON mapping fails due to a method not found error. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/package-info.java similarity index 85% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/package-info.java index e6f547b92..52227027c 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/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.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AErrorResponse.java similarity index 94% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AErrorResponse.java index e2f91c35a..5eeaab8e3 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AErrorResponse.java @@ -1,7 +1,7 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.util.Assert; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.util.Assert; /** * Represents a JSON-RPC 2.0 error response. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AMessage.java similarity index 97% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AMessage.java index 183b8359f..6687b7d8f 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AMessage.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; /** * Base interface for all JSON-RPC 2.0 protocol messages in the A2A Protocol. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2ARequest.java similarity index 96% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2ARequest.java index e7200219a..cbafe613d 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2ARequest.java @@ -1,7 +1,7 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.util.Assert; -import io.a2a.util.Utils; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.util.Utils; /** * Base class for JSON-RPC 2.0 requests in the A2A Protocol. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AResponse.java similarity index 92% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AResponse.java index c318f2166..1c2b1c649 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AResponse.java @@ -1,9 +1,9 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; -import io.a2a.spec.A2AError; -import io.a2a.util.Assert; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.util.Assert; /** * Represents a JSONRPC response. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CancelTaskRequest.java similarity index 93% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CancelTaskRequest.java index a0c48b0df..0196d0f21 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CancelTaskRequest.java @@ -1,13 +1,13 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; -import io.a2a.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.CancelTaskParams; import java.util.UUID; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskState; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskState; /** * JSON-RPC request to cancel an in-progress task. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CancelTaskResponse.java similarity index 80% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CancelTaskResponse.java index 8a7ca6413..945f08830 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CancelTaskResponse.java @@ -1,10 +1,10 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskState; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskState; /** * JSON-RPC response for task cancellation requests. @@ -13,7 +13,7 @@ * showing {@link TaskState#TASK_STATE_CANCELED} status if the cancellation was successful. *

              * If the task cannot be canceled (e.g., already completed) or is not found, the error - * field will contain a {@link io.a2a.spec.A2AError} such as {@link TaskNotCancelableError} or + * field will contain a {@link org.a2aproject.sdk.spec.A2AError} such as {@link TaskNotCancelableError} or * {@link TaskNotFoundError}. * * @see CancelTaskRequest for the corresponding request diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java similarity index 94% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java index 13d7a8b25..ac0277f31 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java @@ -1,10 +1,10 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; import java.util.UUID; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; /** * JSON-RPC request to configure push notifications for a specific task. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java similarity index 89% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java index e46aa7d2b..6250de0a3 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java @@ -1,8 +1,8 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; /** * JSON-RPC response confirming push notification configuration for a task. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java similarity index 95% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java index 64f983520..cbbdf6925 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java @@ -1,11 +1,11 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; import java.util.UUID; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; /** * JSON-RPC request to delete a push notification configuration from a task. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java similarity index 95% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java index d25674814..9b2608b50 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java @@ -1,6 +1,6 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; +import org.a2aproject.sdk.spec.A2AError; /** * JSON-RPC response confirming deletion of a task's push notification configuration. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java similarity index 91% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java index 89e893363..18fbbd7e5 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java @@ -1,12 +1,12 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; import java.util.UUID; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; /** * JSON-RPC request to retrieve an agent's extended card with authenticated details. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java similarity index 89% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java index edf181dd6..1e628fdee 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java @@ -1,8 +1,8 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; /** * JSON-RPC response containing an agent's extended card with authenticated details. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java similarity index 92% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java index e0f11be83..9cbd4598d 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java @@ -1,11 +1,11 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; import java.util.UUID; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; /** * JSON-RPC request to retrieve push notification configuration for a task. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java similarity index 91% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java index 3aa71c8b6..33914bfdf 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java @@ -1,7 +1,7 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; /** * JSON-RPC response containing a task's push notification configuration. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskRequest.java similarity index 93% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskRequest.java index a08abe1be..a7f3f6254 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskRequest.java @@ -1,11 +1,11 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_METHOD; import java.util.UUID; -import io.a2a.spec.Task; -import io.a2a.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskQueryParams; /** * JSON-RPC request to retrieve task information by ID. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskResponse.java similarity index 89% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskResponse.java index 68ea1ed90..419f094b6 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/GetTaskResponse.java @@ -1,8 +1,8 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskNotFoundError; /** * JSON-RPC response containing requested task information. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java similarity index 92% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java index 82b7a40bc..050d10626 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsRequest.java @@ -1,12 +1,12 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; import java.util.UUID; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; /** * JSON-RPC request to list all push notification configurations for a task. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java similarity index 89% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java index eb1ef9ff7..9ae46f471 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTaskPushNotificationConfigsResponse.java @@ -1,8 +1,8 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; /** * JSON-RPC response containing all push notification configurations for a task with pagination support. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksRequest.java similarity index 93% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksRequest.java index aa8d656bc..0e238e27a 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksRequest.java @@ -1,10 +1,10 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_METHOD; import java.util.UUID; -import io.a2a.spec.ListTasksParams; +import org.a2aproject.sdk.spec.ListTasksParams; /** * A list tasks request. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksResponse.java similarity index 91% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksResponse.java index 8fa6446cb..981e59652 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksResponse.java @@ -1,6 +1,6 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; +import org.a2aproject.sdk.spec.A2AError; /** * The response for a list tasks request. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksResult.java similarity index 96% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksResult.java index 9cf2adc60..2bf65a4b7 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/ListTasksResult.java @@ -1,9 +1,9 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; import java.util.List; -import io.a2a.spec.Task; -import io.a2a.util.Assert; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java similarity index 93% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java index 60e9043dd..52caff0f2 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; /** * Represents a non-streaming JSON-RPC request. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendMessageRequest.java similarity index 95% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendMessageRequest.java index a3abf3c4c..a1d6c64b4 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendMessageRequest.java @@ -1,11 +1,11 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_MESSAGE_METHOD; import java.util.UUID; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Task; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.Task; /** * JSON-RPC request for the {@code SendMessage} method in the A2A Protocol. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendMessageResponse.java similarity index 87% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendMessageResponse.java index 4f576dd01..2a43efeae 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendMessageResponse.java @@ -1,7 +1,7 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.spec.EventKind; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.EventKind; /** * The response after receiving a send message request. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendStreamingMessageRequest.java similarity index 94% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendStreamingMessageRequest.java index 704b70435..4eaa44e0e 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendStreamingMessageRequest.java @@ -1,11 +1,11 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; import java.util.UUID; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; /** * JSON-RPC request to initiate a new task with streaming event delivery. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendStreamingMessageResponse.java similarity index 85% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageResponse.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendStreamingMessageResponse.java index 7cb428654..5a7a7dc6e 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SendStreamingMessageResponse.java @@ -1,11 +1,11 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.A2AError; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; /** * JSON-RPC response for streaming message initiation requests. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java similarity index 93% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java index c55200847..100152ce9 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java @@ -1,6 +1,6 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import io.a2a.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.StreamingEventKind; /** * Base class for JSON-RPC requests that support streaming responses in the A2A Protocol. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SubscribeToTaskRequest.java similarity index 93% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SubscribeToTaskRequest.java index 1c965d5b1..7a1a56d19 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/SubscribeToTaskRequest.java @@ -1,11 +1,11 @@ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; import java.util.UUID; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TaskIdParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.TaskIdParams; /** * JSON-RPC request to subscribe to an ongoing or completed task's event stream. diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/package-info.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/package-info.java similarity index 77% rename from jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/package-info.java rename to jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/package-info.java index 2de88b1f1..b2a3e6d40 100644 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/package-info.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/package-info.java @@ -6,9 +6,9 @@ * 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}. + * The public API is in {@code org.a2aproject.sdk.spec}. * - * @see io.a2a.spec + * @see org.a2aproject.sdk.spec * @see JSON-RPC 2.0 Specification */ -package io.a2a.jsonrpc.common.wrappers; +package org.a2aproject.sdk.jsonrpc.common.wrappers; diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/A2AErrorSerializationTest.java similarity index 75% rename from jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java rename to jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/A2AErrorSerializationTest.java index 734ff47e0..9c1935810 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java +++ b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/A2AErrorSerializationTest.java @@ -1,23 +1,23 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import java.util.List; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AErrorCodes; -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.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.A2AErrorCodes; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidAgentResponseError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.junit.jupiter.api.Test; diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/JsonUtilTest.java b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtilTest.java similarity index 97% rename from jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/JsonUtilTest.java rename to jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtilTest.java index 0584bfb7d..aff3774c7 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/JsonUtilTest.java +++ b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtilTest.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/SecurityRequirementSerializationTest.java similarity index 96% rename from jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java rename to jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/SecurityRequirementSerializationTest.java index b71809367..cf82d9935 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java +++ b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/SecurityRequirementSerializationTest.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; import static java.util.Collections.emptyMap; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test; -import io.a2a.spec.SecurityRequirement; +import org.a2aproject.sdk.spec.SecurityRequirement; /** * Tests for SecurityRequirement serialization and deserialization with JSON. diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/SecuritySchemeSerializationTest.java similarity index 93% rename from jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java rename to jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/SecuritySchemeSerializationTest.java index 5a5f3d856..9ae1bbf12 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java +++ b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/SecuritySchemeSerializationTest.java @@ -1,8 +1,8 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; -import static io.a2a.spec.APIKeySecurityScheme.Location.COOKIE; -import static io.a2a.spec.APIKeySecurityScheme.Location.HEADER; -import static io.a2a.spec.APIKeySecurityScheme.Location.QUERY; +import static org.a2aproject.sdk.spec.APIKeySecurityScheme.Location.COOKIE; +import static org.a2aproject.sdk.spec.APIKeySecurityScheme.Location.HEADER; +import static org.a2aproject.sdk.spec.APIKeySecurityScheme.Location.QUERY; import static java.lang.String.format; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -14,11 +14,11 @@ import org.junit.jupiter.api.Test; -import io.a2a.spec.APIKeySecurityScheme; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.MutualTLSSecurityScheme; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.SecurityScheme; +import org.a2aproject.sdk.spec.APIKeySecurityScheme; +import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; +import org.a2aproject.sdk.spec.MutualTLSSecurityScheme; +import org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme; +import org.a2aproject.sdk.spec.SecurityScheme; /** * Tests for SecurityScheme serialization and deserialization using Gson. diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/StreamingEventKindSerializationTest.java similarity index 95% rename from jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java rename to jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/StreamingEventKindSerializationTest.java index d0bf98090..46062671b 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java +++ b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/StreamingEventKindSerializationTest.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -8,15 +8,15 @@ import java.util.List; -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.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; /** diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/TaskSerializationTest.java similarity index 98% rename from jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java rename to jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/TaskSerializationTest.java index c5199a1e1..77fa911f3 100644 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java +++ b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/TaskSerializationTest.java @@ -1,4 +1,4 @@ -package io.a2a.jsonrpc.common.json; +package org.a2aproject.sdk.jsonrpc.common.json; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -15,18 +15,18 @@ import java.util.List; import java.util.Map; -import io.a2a.spec.Artifact; -import io.a2a.spec.DataPart; -import io.a2a.spec.FileContent; -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.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.FileContent; +import org.a2aproject.sdk.spec.FilePart; +import org.a2aproject.sdk.spec.FileWithBytes; +import org.a2aproject.sdk.spec.FileWithUri; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; diff --git a/reference/common/src/main/java/io/a2a/server/common/quarkus/DefaultProducers.java b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/DefaultProducers.java similarity index 84% rename from reference/common/src/main/java/io/a2a/server/common/quarkus/DefaultProducers.java rename to reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/DefaultProducers.java index cbc38f13f..9c1e953e9 100644 --- a/reference/common/src/main/java/io/a2a/server/common/quarkus/DefaultProducers.java +++ b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/DefaultProducers.java @@ -1,11 +1,11 @@ -package io.a2a.server.common.quarkus; +package org.a2aproject.sdk.server.common.quarkus; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.spec.AgentCard; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.spec.AgentCard; import io.quarkus.arc.DefaultBean; /** diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java b/reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/A2AExtensionsInterceptor.java similarity index 83% rename from reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java rename to reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/A2AExtensionsInterceptor.java index f985e7cd1..776e1bb97 100644 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java +++ b/reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/A2AExtensionsInterceptor.java @@ -1,9 +1,9 @@ -package io.a2a.server.grpc.quarkus; +package org.a2aproject.sdk.server.grpc.quarkus; import jakarta.enterprise.context.ApplicationScoped; -import io.a2a.common.A2AHeaders; -import io.a2a.transport.grpc.context.GrpcContextKeys; +import org.a2aproject.sdk.common.A2AHeaders; +import org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys; import io.grpc.Context; import io.grpc.Contexts; import io.grpc.Metadata; @@ -17,7 +17,7 @@ * *

              This interceptor executes before service methods are invoked, extracting A2A protocol * headers and request metadata from the gRPC call and storing them in the gRPC {@link Context} - * for access by {@link io.a2a.transport.grpc.handler.GrpcHandler} and agent implementations. + * for access by {@link org.a2aproject.sdk.transport.grpc.handler.GrpcHandler} and agent implementations. * *

              Captured Information

              *
                @@ -30,14 +30,14 @@ * *

                Context Storage

                *

                All captured information is stored in the gRPC {@link Context} using keys from - * {@link io.a2a.transport.grpc.context.GrpcContextKeys}: + * {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys}: *

                  - *
                • {@link io.a2a.transport.grpc.context.GrpcContextKeys#VERSION_HEADER_KEY VERSION_HEADER_KEY}
                • - *
                • {@link io.a2a.transport.grpc.context.GrpcContextKeys#EXTENSIONS_HEADER_KEY EXTENSIONS_HEADER_KEY}
                • - *
                • {@link io.a2a.transport.grpc.context.GrpcContextKeys#METADATA_KEY METADATA_KEY}
                • - *
                • {@link io.a2a.transport.grpc.context.GrpcContextKeys#GRPC_METHOD_NAME_KEY GRPC_METHOD_NAME_KEY}
                • - *
                • {@link io.a2a.transport.grpc.context.GrpcContextKeys#METHOD_NAME_KEY METHOD_NAME_KEY}
                • - *
                • {@link io.a2a.transport.grpc.context.GrpcContextKeys#PEER_INFO_KEY PEER_INFO_KEY}
                • + *
                • {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#VERSION_HEADER_KEY VERSION_HEADER_KEY}
                • + *
                • {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#EXTENSIONS_HEADER_KEY EXTENSIONS_HEADER_KEY}
                • + *
                • {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#METADATA_KEY METADATA_KEY}
                • + *
                • {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#GRPC_METHOD_NAME_KEY GRPC_METHOD_NAME_KEY}
                • + *
                • {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#METHOD_NAME_KEY METHOD_NAME_KEY}
                • + *
                • {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#PEER_INFO_KEY PEER_INFO_KEY}
                • *
                * *

                CDI Integration

                @@ -53,8 +53,8 @@ *
              • {@code context.peer()} → Peer info via {@code PEER_INFO_KEY}
              • *
              * - * @see io.a2a.transport.grpc.context.GrpcContextKeys - * @see io.a2a.transport.grpc.handler.GrpcHandler + * @see org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys + * @see org.a2aproject.sdk.transport.grpc.handler.GrpcHandler * @see io.grpc.ServerInterceptor */ @ApplicationScoped diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java b/reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusGrpcHandler.java similarity index 91% rename from reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java rename to reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusGrpcHandler.java index 02d441a17..e23656b8a 100644 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java +++ b/reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusGrpcHandler.java @@ -1,17 +1,17 @@ -package io.a2a.server.grpc.quarkus; +package org.a2aproject.sdk.server.grpc.quarkus; import java.util.concurrent.Executor; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; -import io.a2a.server.ExtendedAgentCard; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.AgentCard; -import io.a2a.transport.grpc.handler.CallContextFactory; -import io.a2a.transport.grpc.handler.GrpcHandler; +import org.a2aproject.sdk.server.ExtendedAgentCard; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.requesthandlers.RequestHandler; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.transport.grpc.handler.CallContextFactory; +import org.a2aproject.sdk.transport.grpc.handler.GrpcHandler; import io.quarkus.grpc.GrpcService; import io.quarkus.grpc.RegisterInterceptor; import io.quarkus.security.Authenticated; @@ -62,7 +62,7 @@ * } * } * - * @see io.a2a.transport.grpc.handler.GrpcHandler + * @see org.a2aproject.sdk.transport.grpc.handler.GrpcHandler * @see A2AExtensionsInterceptor * @see CallContextFactory */ diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java b/reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java similarity index 85% rename from reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java rename to reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java index b12635523..d0c49785e 100644 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java +++ b/reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java @@ -1,7 +1,7 @@ -package io.a2a.server.grpc.quarkus; +package org.a2aproject.sdk.server.grpc.quarkus; -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.TransportMetadata; +import org.a2aproject.sdk.spec.TransportProtocol; /** * Transport metadata provider for the Quarkus gRPC reference implementation. @@ -32,8 +32,8 @@ *
            • Protocol-specific error handling or feature detection
            • *
            * - * @see io.a2a.server.TransportMetadata - * @see io.a2a.spec.TransportProtocol + * @see org.a2aproject.sdk.server.TransportMetadata + * @see org.a2aproject.sdk.spec.TransportProtocol */ public class QuarkusGrpcTransportMetadata implements TransportMetadata { /** diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java b/reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/package-info.java similarity index 72% rename from reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java rename to reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/package-info.java index 273eb5586..03c0d7622 100644 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/package-info.java +++ b/reference/grpc/src/main/java/org/a2aproject/sdk/server/grpc/quarkus/package-info.java @@ -26,9 +26,9 @@ * *

            Core Components

            *
              - *
            • {@link io.a2a.server.grpc.quarkus.QuarkusGrpcHandler QuarkusGrpcHandler} - Main gRPC service implementation
            • - *
            • {@link io.a2a.server.grpc.quarkus.A2AExtensionsInterceptor A2AExtensionsInterceptor} - Metadata extraction interceptor
            • - *
            • {@link io.a2a.server.grpc.quarkus.QuarkusGrpcTransportMetadata QuarkusGrpcTransportMetadata} - Transport protocol identification
            • + *
            • {@link org.a2aproject.sdk.server.grpc.quarkus.QuarkusGrpcHandler QuarkusGrpcHandler} - Main gRPC service implementation
            • + *
            • {@link org.a2aproject.sdk.server.grpc.quarkus.A2AExtensionsInterceptor A2AExtensionsInterceptor} - Metadata extraction interceptor
            • + *
            • {@link org.a2aproject.sdk.server.grpc.quarkus.QuarkusGrpcTransportMetadata QuarkusGrpcTransportMetadata} - Transport protocol identification
            • *
            * *

            gRPC Methods

            @@ -56,14 +56,14 @@ * *

            Required CDI Beans: *

              - *
            • {@link io.a2a.spec.AgentCard AgentCard} with {@code @PublicAgentCard} qualifier
            • - *
            • {@link io.a2a.server.agentexecution.AgentExecutor AgentExecutor} implementation
            • + *
            • {@link org.a2aproject.sdk.spec.AgentCard AgentCard} with {@code @PublicAgentCard} qualifier
            • + *
            • {@link org.a2aproject.sdk.server.agentexecution.AgentExecutor AgentExecutor} implementation
            • *
            * *

            Optional CDI Beans: *

              - *
            • {@link io.a2a.spec.AgentCard AgentCard} with {@code @ExtendedAgentCard} qualifier
            • - *
            • {@link io.a2a.transport.grpc.handler.CallContextFactory CallContextFactory} for custom context creation
            • + *
            • {@link org.a2aproject.sdk.spec.AgentCard AgentCard} with {@code @ExtendedAgentCard} qualifier
            • + *
            • {@link org.a2aproject.sdk.transport.grpc.handler.CallContextFactory CallContextFactory} for custom context creation
            • *
            * *

            Usage

            @@ -124,7 +124,7 @@ *

            Customization

            * *

            Custom Context Creation: - *

            Provide a CDI bean implementing {@link io.a2a.transport.grpc.handler.CallContextFactory CallContextFactory}: + *

            Provide a CDI bean implementing {@link org.a2aproject.sdk.transport.grpc.handler.CallContextFactory CallContextFactory}: *

            {@code
              * @ApplicationScoped
              * public class CustomCallContextFactory implements CallContextFactory {
            @@ -155,14 +155,14 @@
              * 

            This implementation provides equivalent functionality to Python's {@code grpc.aio} server: *

              *
            • {@code grpc.aio.ServicerContext} → {@link io.grpc.Context} with {@link A2AExtensionsInterceptor}
            • - *
            • {@code context.invocation_metadata()} → {@link io.a2a.transport.grpc.context.GrpcContextKeys#METADATA_KEY}
            • - *
            • {@code context.method()} → {@link io.a2a.transport.grpc.context.GrpcContextKeys#GRPC_METHOD_NAME_KEY}
            • - *
            • {@code context.peer()} → {@link io.a2a.transport.grpc.context.GrpcContextKeys#PEER_INFO_KEY}
            • + *
            • {@code context.invocation_metadata()} → {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#METADATA_KEY}
            • + *
            • {@code context.method()} → {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#GRPC_METHOD_NAME_KEY}
            • + *
            • {@code context.peer()} → {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys#PEER_INFO_KEY}
            • *
            * - * @see io.a2a.server.grpc.quarkus.QuarkusGrpcHandler - * @see io.a2a.server.grpc.quarkus.A2AExtensionsInterceptor - * @see io.a2a.transport.grpc.handler.GrpcHandler - * @see io.a2a.transport.grpc.context.GrpcContextKeys + * @see org.a2aproject.sdk.server.grpc.quarkus.QuarkusGrpcHandler + * @see org.a2aproject.sdk.server.grpc.quarkus.A2AExtensionsInterceptor + * @see org.a2aproject.sdk.transport.grpc.handler.GrpcHandler + * @see org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys */ -package io.a2a.server.grpc.quarkus; +package org.a2aproject.sdk.server.grpc.quarkus; diff --git a/reference/grpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata b/reference/grpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index 3eb991c3c..000000000 --- a/reference/grpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1 +0,0 @@ -io.a2a.server.grpc.quarkus.QuarkusGrpcTransportMetadata \ No newline at end of file diff --git a/reference/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata b/reference/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata new file mode 100644 index 000000000..391896ed3 --- /dev/null +++ b/reference/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata @@ -0,0 +1 @@ +org.a2aproject.sdk.server.grpc.quarkus.QuarkusGrpcTransportMetadata \ No newline at end of file diff --git a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/A2ATestResource.java similarity index 93% rename from reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java rename to reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/A2ATestResource.java index 8b67aa446..b2ec9e1f0 100644 --- a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java +++ b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/A2ATestResource.java @@ -1,4 +1,4 @@ -package io.a2a.server.grpc.quarkus; +package org.a2aproject.sdk.server.grpc.quarkus; import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; @@ -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.TaskPushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.transport.grpc.handler.GrpcHandler; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.apps.common.TestUtilsBean; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.transport.grpc.handler.GrpcHandler; @Path("/test") @ApplicationScoped diff --git a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcTest.java similarity index 81% rename from reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java rename to reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcTest.java index 7423edda0..a255835e2 100644 --- a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java +++ b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcTest.java @@ -1,12 +1,12 @@ -package io.a2a.server.grpc.quarkus; +package org.a2aproject.sdk.server.grpc.quarkus; import java.util.concurrent.TimeUnit; -import io.a2a.client.ClientBuilder; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.server.apps.common.AbstractA2AServerTest; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransport; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransportConfigBuilder; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerTest; +import org.a2aproject.sdk.spec.TransportProtocol; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.quarkus.test.junit.QuarkusTest; diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java similarity index 85% rename from reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java rename to reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index 2e63d0982..a43c119a6 100644 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -1,9 +1,9 @@ -package io.a2a.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.quarkus; -import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; +import static org.a2aproject.sdk.server.ServerCallContext.TRANSPORT_KEY; +import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; +import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; +import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_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; @@ -21,51 +21,51 @@ import jakarta.inject.Singleton; import com.google.gson.JsonSyntaxException; -import io.a2a.common.A2AHeaders; -import io.a2a.server.util.sse.SseFormatter; -import io.a2a.grpc.utils.JSONRPCUtils; -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.JsonUtil; -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.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -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.ListTaskPushNotificationConfigsRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; -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.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -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.InternalError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.TransportProtocol; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.transport.jsonrpc.handler.JSONRPCHandler; +import org.a2aproject.sdk.common.A2AHeaders; +import org.a2aproject.sdk.server.util.sse.SseFormatter; +import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; +import org.a2aproject.sdk.jsonrpc.common.json.IdJsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.json.InvalidParamsJsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.jsonrpc.common.json.MethodNotFoundJsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AErrorResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2ARequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.NonStreamingJSONRPCRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SubscribeToTaskRequest; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.transport.jsonrpc.handler.JSONRPCHandler; import io.quarkus.security.Authenticated; import io.quarkus.vertx.web.Body; import io.quarkus.vertx.web.Route; @@ -140,9 +140,9 @@ *

            Errors are mapped to JSON-RPC 2.0 error responses: *

              *
            • {@link JsonSyntaxException} → {@link JSONParseError}
            • - *
            • {@link InvalidParamsJsonMappingException} → {@link io.a2a.spec.InvalidParamsError}
            • - *
            • {@link MethodNotFoundJsonMappingException} → {@link io.a2a.spec.MethodNotFoundError}
            • - *
            • {@link IdJsonMappingException} → {@link io.a2a.spec.InvalidRequestError}
            • + *
            • {@link InvalidParamsJsonMappingException} → {@link org.a2aproject.sdk.spec.InvalidParamsError}
            • + *
            • {@link MethodNotFoundJsonMappingException} → {@link org.a2aproject.sdk.spec.MethodNotFoundError}
            • + *
            • {@link IdJsonMappingException} → {@link org.a2aproject.sdk.spec.InvalidRequestError}
            • *
            • {@link Throwable} → {@link InternalError}
            • *
            * @@ -173,7 +173,7 @@ public class A2AServerRoutes { JSONRPCHandler jsonRpcHandler; @Inject - io.a2a.server.AgentCardCacheMetadata cacheMetadata; + org.a2aproject.sdk.server.AgentCardCacheMetadata cacheMetadata; // Hook so testing can wait until the MultiSseSupport is subscribed. // Without this we get intermittent failures @@ -278,14 +278,14 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { } catch (A2AError e) { error = new A2AErrorResponse(e); } catch (InvalidParamsJsonMappingException e) { - error = new A2AErrorResponse(e.getId(), new io.a2a.spec.InvalidParamsError(null, e.getMessage(), null)); + error = new A2AErrorResponse(e.getId(), new org.a2aproject.sdk.spec.InvalidParamsError(null, e.getMessage(), null)); } catch (MethodNotFoundJsonMappingException e) { - error = new A2AErrorResponse(e.getId(), new io.a2a.spec.MethodNotFoundError(null, e.getMessage(), null)); + error = new A2AErrorResponse(e.getId(), new org.a2aproject.sdk.spec.MethodNotFoundError(null, e.getMessage(), null)); } catch (IdJsonMappingException e) { - error = new A2AErrorResponse(e.getId(), new io.a2a.spec.InvalidRequestError(null, e.getMessage(), null)); + error = new A2AErrorResponse(e.getId(), new org.a2aproject.sdk.spec.InvalidRequestError(null, e.getMessage(), null)); } catch (JsonMappingException e) { // General JsonMappingException - treat as InvalidRequest - error = new A2AErrorResponse(new io.a2a.spec.InvalidRequestError(null, e.getMessage(), null)); + error = new A2AErrorResponse(new org.a2aproject.sdk.spec.InvalidRequestError(null, e.getMessage(), null)); } catch (JsonSyntaxException e) { error = new A2AErrorResponse(new JSONParseError(e.getMessage())); } catch (JsonProcessingException e) { @@ -628,7 +628,7 @@ private static String serializeResponse(A2AResponse response) { * Converts a domain response object to its protobuf representation. * *

            This method maps response types to their corresponding protobuf messages - * using {@link io.a2a.grpc.utils.ProtoUtils}, ensuring consistent serialization + * using {@link org.a2aproject.sdk.grpc.utils.ProtoUtils}, ensuring consistent serialization * across all transports (JSON-RPC, gRPC, REST). * *

            Supported Response Types: @@ -648,30 +648,30 @@ private static String serializeResponse(A2AResponse response) { * @param response the domain response object * @return the protobuf message representation * @throws IllegalArgumentException if the response type is unknown - * @see io.a2a.grpc.utils.ProtoUtils + * @see org.a2aproject.sdk.grpc.utils.ProtoUtils */ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse response) { if (response instanceof GetTaskResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); } else if (response instanceof CancelTaskResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); } else if (response instanceof SendMessageResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessage(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.taskOrMessage(r.getResult()); } else if (response instanceof ListTasksResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.listTasksResult(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.listTasksResult(r.getResult()); } else if (response instanceof CreateTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.createTaskPushNotificationConfigResponse(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.createTaskPushNotificationConfigResponse(r.getResult()); } else if (response instanceof GetTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.getTaskPushNotificationConfigResponse(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.getTaskPushNotificationConfigResponse(r.getResult()); } else if (response instanceof ListTaskPushNotificationConfigsResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.listTaskPushNotificationConfigsResponse(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.listTaskPushNotificationConfigsResponse(r.getResult()); } else if (response instanceof DeleteTaskPushNotificationConfigResponse) { // DeleteTaskPushNotificationConfig has no result body, just return empty message return com.google.protobuf.Empty.getDefaultInstance(); } else if (response instanceof GetExtendedAgentCardResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.getExtendedCardResponse(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.getExtendedCardResponse(r.getResult()); } else if (response instanceof SendStreamingMessageResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessageStream(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.taskOrMessageStream(r.getResult()); } else { throw new IllegalArgumentException("Unknown response type: " + response.getClass().getName()); } diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/CallContextFactory.java similarity index 90% rename from reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java rename to reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/CallContextFactory.java index 64b98c962..e6c48b617 100644 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/CallContextFactory.java @@ -1,6 +1,6 @@ -package io.a2a.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.quarkus; -import io.a2a.server.ServerCallContext; +import org.a2aproject.sdk.server.ServerCallContext; import io.vertx.ext.web.RoutingContext; /** @@ -62,8 +62,8 @@ public interface CallContextFactory { * Builds a {@link ServerCallContext} from a Vert.x routing context. * *

            This method is called for each incoming HTTP request to create the context - * that will be passed to the {@link io.a2a.server.requesthandlers.RequestHandler} - * and eventually to the {@link io.a2a.server.agentexecution.AgentExecutor}. + * that will be passed to the {@link org.a2aproject.sdk.server.requesthandlers.RequestHandler} + * and eventually to the {@link org.a2aproject.sdk.server.agentexecution.AgentExecutor}. * * @param rc the Vert.x routing context containing request data * @return a new ServerCallContext with extracted authentication, headers, and metadata diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java similarity index 85% rename from reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java rename to reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java index 02f2bd3f5..55899eac4 100644 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java @@ -1,7 +1,7 @@ -package io.a2a.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.quarkus; -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.TransportMetadata; +import org.a2aproject.sdk.spec.TransportProtocol; /** * Transport metadata provider for the Quarkus JSON-RPC reference implementation. @@ -32,8 +32,8 @@ *

          • Protocol-specific error handling or feature detection
          • * * - * @see io.a2a.server.TransportMetadata - * @see io.a2a.spec.TransportProtocol + * @see org.a2aproject.sdk.server.TransportMetadata + * @see org.a2aproject.sdk.spec.TransportProtocol */ public class QuarkusJSONRPCTransportMetadata implements TransportMetadata { diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/package-info.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/package-info.java similarity index 85% rename from reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/package-info.java rename to reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/package-info.java index 5d85284cc..de3d9e89c 100644 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/package-info.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/package-info.java @@ -23,9 +23,9 @@ * *

            Core Components

            *
              - *
            • {@link io.a2a.server.apps.quarkus.A2AServerRoutes A2AServerRoutes} - Vert.x Web routing and request handling
            • - *
            • {@link io.a2a.server.apps.quarkus.CallContextFactory CallContextFactory} - Extension point for custom context creation
            • - *
            • {@link io.a2a.server.apps.quarkus.QuarkusJSONRPCTransportMetadata QuarkusJSONRPCTransportMetadata} - Transport protocol identification
            • + *
            • {@link org.a2aproject.sdk.server.apps.quarkus.A2AServerRoutes A2AServerRoutes} - Vert.x Web routing and request handling
            • + *
            • {@link org.a2aproject.sdk.server.apps.quarkus.CallContextFactory CallContextFactory} - Extension point for custom context creation
            • + *
            • {@link org.a2aproject.sdk.server.apps.quarkus.QuarkusJSONRPCTransportMetadata QuarkusJSONRPCTransportMetadata} - Transport protocol identification
            • *
            * *

            JSON-RPC Endpoint

            @@ -118,7 +118,7 @@ *

            Customization

            * *

            Custom Context Creation: - *

            Provide a CDI bean implementing {@link io.a2a.server.apps.quarkus.CallContextFactory CallContextFactory}: + *

            Provide a CDI bean implementing {@link org.a2aproject.sdk.server.apps.quarkus.CallContextFactory CallContextFactory}: *

            {@code
              * @ApplicationScoped
              * public class CustomCallContextFactory implements CallContextFactory {
            @@ -163,8 +163,8 @@
              * quarkus.security.users.embedded.users.alice=password
              * 
            * - * @see io.a2a.server.apps.quarkus.A2AServerRoutes - * @see io.a2a.server.apps.quarkus.CallContextFactory - * @see io.a2a.transport.jsonrpc.handler.JSONRPCHandler + * @see org.a2aproject.sdk.server.apps.quarkus.A2AServerRoutes + * @see org.a2aproject.sdk.server.apps.quarkus.CallContextFactory + * @see org.a2aproject.sdk.transport.jsonrpc.handler.JSONRPCHandler */ -package io.a2a.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.quarkus; diff --git a/reference/jsonrpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata b/reference/jsonrpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index d9a5494b4..000000000 --- a/reference/jsonrpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1 +0,0 @@ -io.a2a.server.apps.quarkus.QuarkusJSONRPCTransportMetadata \ No newline at end of file diff --git a/reference/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata b/reference/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata new file mode 100644 index 000000000..c50d46fcf --- /dev/null +++ b/reference/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata @@ -0,0 +1 @@ +org.a2aproject.sdk.server.apps.quarkus.QuarkusJSONRPCTransportMetadata \ No newline at end of file diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutesTest.java similarity index 90% rename from reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java rename to reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutesTest.java index bc1b717e5..f2a746b2c 100644 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutesTest.java @@ -1,17 +1,17 @@ -package io.a2a.server.apps.quarkus; - -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; -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.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; +package org.a2aproject.sdk.server.apps.quarkus; + +import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; +import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; import static java.util.Collections.singletonList; import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; @@ -29,36 +29,36 @@ 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.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -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.ListTaskPushNotificationConfigsRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; -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.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -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.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.transport.jsonrpc.handler.JSONRPCHandler; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SubscribeToTaskRequest; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AuthenticationInfo; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.transport.jsonrpc.handler.JSONRPCHandler; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java similarity index 95% rename from reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java rename to reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java index b421c48d5..31af95c1d 100644 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java @@ -1,4 +1,4 @@ -package io.a2a.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.quarkus; import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; @@ -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.TaskPushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.apps.common.TestUtilsBean; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import io.quarkus.vertx.web.Body; import io.quarkus.vertx.web.Param; import io.quarkus.vertx.web.Route; diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java similarity index 52% rename from reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java rename to reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java index 4f1e76251..184f83cc4 100644 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java @@ -1,9 +1,9 @@ -package io.a2a.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.quarkus; -import io.a2a.client.ClientBuilder; -import io.a2a.client.http.JdkA2AHttpClient; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; import io.quarkus.test.junit.QuarkusTest; @QuarkusTest diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCTest.java similarity index 67% rename from reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCTest.java rename to reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCTest.java index 4123262cb..839975a0b 100644 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCTest.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCTest.java @@ -1,8 +1,8 @@ -package io.a2a.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.quarkus; -import io.a2a.client.ClientBuilder; -import io.a2a.server.apps.common.AbstractA2AServerTest; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerTest; +import org.a2aproject.sdk.spec.TransportProtocol; public abstract class QuarkusA2AJSONRPCTest extends AbstractA2AServerTest { diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java similarity index 58% rename from reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java rename to reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java index 69370566b..6eb7e7ede 100644 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java @@ -1,9 +1,9 @@ -package io.a2a.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.quarkus; -import io.a2a.client.ClientBuilder; -import io.a2a.client.http.VertxA2AHttpClient; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; import io.quarkus.test.junit.QuarkusTest; import io.vertx.core.Vertx; import jakarta.inject.Inject; diff --git a/reference/jsonrpc/src/test/resources/application.properties b/reference/jsonrpc/src/test/resources/application.properties index e612925d4..d5acb5291 100644 --- a/reference/jsonrpc/src/test/resources/application.properties +++ b/reference/jsonrpc/src/test/resources/application.properties @@ -1,6 +1,6 @@ -quarkus.arc.selected-alternatives=io.a2a.server.apps.common.TestHttpClient +quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttpClient # Debug logging for event processing and request handling -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.server.tasks".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java similarity index 94% rename from reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java rename to reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java index 94deae2b3..14e7e45f0 100644 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java @@ -1,10 +1,10 @@ -package io.a2a.server.rest.quarkus; +package org.a2aproject.sdk.server.rest.quarkus; -import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; -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 org.a2aproject.sdk.server.ServerCallContext.TRANSPORT_KEY; +import static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static org.a2aproject.sdk.transport.rest.context.RestContextKeys.HEADERS_KEY; +import static org.a2aproject.sdk.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; @@ -17,29 +17,29 @@ import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicLong; -import io.a2a.server.util.sse.SseFormatter; +import org.a2aproject.sdk.server.util.sse.SseFormatter; import jakarta.annotation.security.PermitAll; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import jakarta.inject.Singleton; -import io.a2a.common.A2AHeaders; -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.ContentTypeNotSupportedError; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.TransportProtocol; -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 org.a2aproject.sdk.common.A2AHeaders; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.a2aproject.sdk.transport.rest.handler.RestHandler; +import org.a2aproject.sdk.transport.rest.handler.RestHandler.HTTPRestResponse; +import org.a2aproject.sdk.transport.rest.handler.RestHandler.HTTPRestStreamingResponse; +import org.a2aproject.sdk.util.Utils; import io.quarkus.security.Authenticated; import io.quarkus.vertx.web.Body; import io.quarkus.vertx.web.Route; @@ -52,17 +52,17 @@ import io.vertx.ext.web.RoutingContext; import org.jspecify.annotations.Nullable; -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.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; -import static io.a2a.transport.rest.context.RestContextKeys.TENANT_KEY; +import static org.a2aproject.sdk.transport.rest.context.RestContextKeys.TENANT_KEY; /** * Quarkus reactive routes for A2A protocol REST endpoints. @@ -658,7 +658,7 @@ private boolean validateContentTypeForOptionalBody(RoutingContext rc, @Nullable * *

            Authentication: {@code @PermitAll} - Public endpoint requiring no authentication * - *

            Response: JSON containing {@link io.a2a.spec.AgentCard} with: + *

            Response: JSON containing {@link org.a2aproject.sdk.spec.AgentCard} with: *

              *
            • Agent name, description, version
            • *
            • Capabilities (streaming, push notifications)
            • @@ -697,7 +697,7 @@ public void getExtendedAgentCard(RoutingContext rc) { * Catch-all route for undefined endpoints. * *

              Handles all HTTP methods on unmatched paths with order=100 (lowest priority). - * Returns a {@link io.a2a.spec.MethodNotFoundError} with HTTP 404 status. + * Returns a {@link org.a2aproject.sdk.spec.MethodNotFoundError} with HTTP 404 status. * *

              Purpose: Provides consistent error responses for invalid API calls * instead of generic 404 HTML pages. diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/CallContextFactory.java similarity index 88% rename from reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java rename to reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/CallContextFactory.java index b6432d1b3..8e4741a6b 100644 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/CallContextFactory.java @@ -1,6 +1,6 @@ -package io.a2a.server.rest.quarkus; +package org.a2aproject.sdk.server.rest.quarkus; -import io.a2a.server.ServerCallContext; +import org.a2aproject.sdk.server.ServerCallContext; import io.vertx.ext.web.RoutingContext; /** @@ -53,8 +53,8 @@ public interface CallContextFactory { * Builds a {@link ServerCallContext} from a Vert.x routing context. * *

              This method is called for each incoming HTTP request to create the context - * that will be passed to the {@link io.a2a.server.requesthandlers.RequestHandler} - * and eventually to the {@link io.a2a.server.agentexecution.AgentExecutor}. + * that will be passed to the {@link org.a2aproject.sdk.server.requesthandlers.RequestHandler} + * and eventually to the {@link org.a2aproject.sdk.server.agentexecution.AgentExecutor}. * * @param rc the Vert.x routing context containing request data * @return a new ServerCallContext with extracted authentication, headers, and metadata diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusRestTransportMetadata.java similarity index 87% rename from reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java rename to reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusRestTransportMetadata.java index 65ab017d7..6daf65fcf 100644 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusRestTransportMetadata.java @@ -1,7 +1,7 @@ -package io.a2a.server.rest.quarkus; +package org.a2aproject.sdk.server.rest.quarkus; -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.TransportMetadata; +import org.a2aproject.sdk.spec.TransportProtocol; /** * Transport metadata implementation for Quarkus REST. diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/package-info.java similarity index 84% rename from reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java rename to reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/package-info.java index dbfa24145..e8d6e2168 100644 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/package-info.java @@ -8,7 +8,7 @@ *

              Key Components

              *
                *
              • {@link A2AServerRoutes} - Vert.x route definitions mapping HTTP paths to A2A operations
              • - *
              • {@link CallContextFactory} - Extensible factory for creating {@link io.a2a.server.ServerCallContext}
              • + *
              • {@link CallContextFactory} - Extensible factory for creating {@link org.a2aproject.sdk.server.ServerCallContext}
              • *
              • {@link QuarkusRestTransportMetadata} - Transport protocol metadata implementation
              • *
              * @@ -53,15 +53,15 @@ * * }
            * - *

            Provide CDI beans for {@link io.a2a.spec.AgentCard} and - * {@link io.a2a.server.agentexecution.AgentExecutor}, and the REST endpoints + *

            Provide CDI beans for {@link org.a2aproject.sdk.spec.AgentCard} and + * {@link org.a2aproject.sdk.server.agentexecution.AgentExecutor}, and the REST endpoints * will be automatically registered. * - * @see io.a2a.transport.rest.handler - * @see io.a2a.server.requesthandlers + * @see org.a2aproject.sdk.transport.rest.handler + * @see org.a2aproject.sdk.server.requesthandlers */ @NullMarked -package io.a2a.server.rest.quarkus; +package org.a2aproject.sdk.server.rest.quarkus; import org.jspecify.annotations.NullMarked; diff --git a/reference/rest/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata b/reference/rest/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index cb50024df..000000000 --- a/reference/rest/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1 +0,0 @@ -io.a2a.server.rest.quarkus.QuarkusRestTransportMetadata \ No newline at end of file diff --git a/reference/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata b/reference/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata new file mode 100644 index 000000000..d91fba0c9 --- /dev/null +++ b/reference/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata @@ -0,0 +1 @@ +org.a2aproject.sdk.server.rest.quarkus.QuarkusRestTransportMetadata \ No newline at end of file diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutesTest.java similarity index 95% rename from reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java rename to reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutesTest.java index 968c93ef0..6b908644b 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutesTest.java @@ -1,16 +1,16 @@ -package io.a2a.server.rest.quarkus; - -import static io.a2a.common.MediaType.APPLICATION_JSON; -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; +package org.a2aproject.sdk.server.rest.quarkus; + +import static org.a2aproject.sdk.common.MediaType.APPLICATION_JSON; +import static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; +import static org.a2aproject.sdk.transport.rest.context.RestContextKeys.METHOD_NAME_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -27,10 +27,10 @@ import jakarta.enterprise.inject.Instance; -import io.a2a.server.ServerCallContext; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.transport.rest.handler.RestHandler; -import io.a2a.transport.rest.handler.RestHandler.HTTPRestResponse; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.transport.rest.handler.RestHandler; +import org.a2aproject.sdk.transport.rest.handler.RestHandler.HTTPRestResponse; import io.vertx.core.Future; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpServerRequest; diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2ATestRoutes.java similarity index 95% rename from reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java rename to reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2ATestRoutes.java index 4099b7f73..b71e98164 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2ATestRoutes.java @@ -1,4 +1,4 @@ -package io.a2a.server.rest.quarkus; +package org.a2aproject.sdk.server.rest.quarkus; import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; @@ -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.TaskPushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.apps.common.TestUtilsBean; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import io.quarkus.vertx.web.Body; import io.quarkus.vertx.web.Param; import io.quarkus.vertx.web.Route; diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestJdkTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestJdkTest.java similarity index 52% rename from reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestJdkTest.java rename to reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestJdkTest.java index 74cdc958f..2ea4a3785 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestJdkTest.java +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestJdkTest.java @@ -1,9 +1,9 @@ -package io.a2a.server.rest.quarkus; +package org.a2aproject.sdk.server.rest.quarkus; -import io.a2a.client.ClientBuilder; -import io.a2a.client.http.JdkA2AHttpClient; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; import io.quarkus.test.junit.QuarkusTest; @QuarkusTest diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestTest.java similarity index 94% rename from reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java rename to reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestTest.java index 15f5178a3..fb8674219 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestTest.java @@ -1,13 +1,13 @@ -package io.a2a.server.rest.quarkus; +package org.a2aproject.sdk.server.rest.quarkus; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import io.a2a.client.ClientBuilder; -import io.a2a.server.apps.common.AbstractA2AServerTest; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerTest; +import org.a2aproject.sdk.spec.TransportProtocol; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestVertxTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestVertxTest.java similarity index 59% rename from reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestVertxTest.java rename to reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestVertxTest.java index 106c52fd2..c9fb9d40b 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestVertxTest.java +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestVertxTest.java @@ -1,9 +1,9 @@ -package io.a2a.server.rest.quarkus; +package org.a2aproject.sdk.server.rest.quarkus; -import io.a2a.client.ClientBuilder; -import io.a2a.client.http.VertxA2AHttpClient; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; import io.quarkus.test.junit.QuarkusTest; import io.vertx.core.Vertx; import jakarta.inject.Inject; diff --git a/reference/rest/src/test/resources/application.properties b/reference/rest/src/test/resources/application.properties index d3366bece..3700cdf7e 100644 --- a/reference/rest/src/test/resources/application.properties +++ b/reference/rest/src/test/resources/application.properties @@ -1 +1 @@ -quarkus.arc.selected-alternatives=io.a2a.server.apps.common.TestHttpClient \ No newline at end of file +quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttpClient \ No newline at end of file diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/package-info.java b/server-common/src/main/java/io/a2a/server/agentexecution/package-info.java deleted file mode 100644 index 3fc934a52..000000000 --- a/server-common/src/main/java/io/a2a/server/agentexecution/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.agentexecution; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/auth/package-info.java b/server-common/src/main/java/io/a2a/server/auth/package-info.java deleted file mode 100644 index 524d98fac..000000000 --- a/server-common/src/main/java/io/a2a/server/auth/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.auth; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/config/package-info.java b/server-common/src/main/java/io/a2a/server/config/package-info.java deleted file mode 100644 index 335bf450b..000000000 --- a/server-common/src/main/java/io/a2a/server/config/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.config; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/events/package-info.java b/server-common/src/main/java/io/a2a/server/events/package-info.java deleted file mode 100644 index 912717787..000000000 --- a/server-common/src/main/java/io/a2a/server/events/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.events; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/extensions/package-info.java b/server-common/src/main/java/io/a2a/server/extensions/package-info.java deleted file mode 100644 index aa966d4a2..000000000 --- a/server-common/src/main/java/io/a2a/server/extensions/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.extensions; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/package-info.java b/server-common/src/main/java/io/a2a/server/package-info.java deleted file mode 100644 index a2474e4c1..000000000 --- a/server-common/src/main/java/io/a2a/server/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/requesthandlers/package-info.java b/server-common/src/main/java/io/a2a/server/requesthandlers/package-info.java deleted file mode 100644 index d4f3270f4..000000000 --- a/server-common/src/main/java/io/a2a/server/requesthandlers/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.requesthandlers; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/tasks/package-info.java b/server-common/src/main/java/io/a2a/server/tasks/package-info.java deleted file mode 100644 index 1075aded6..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.tasks; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/util/async/package-info.java b/server-common/src/main/java/io/a2a/server/util/async/package-info.java deleted file mode 100644 index daf4dcf5b..000000000 --- a/server-common/src/main/java/io/a2a/server/util/async/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.util.async; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/util/package-info.java b/server-common/src/main/java/io/a2a/server/util/package-info.java deleted file mode 100644 index 897a999fb..000000000 --- a/server-common/src/main/java/io/a2a/server/util/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.util; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/AgentCardCacheMetadata.java b/server-common/src/main/java/org/a2aproject/sdk/server/AgentCardCacheMetadata.java similarity index 96% rename from server-common/src/main/java/io/a2a/server/AgentCardCacheMetadata.java rename to server-common/src/main/java/org/a2aproject/sdk/server/AgentCardCacheMetadata.java index 573ac9384..4696e3b74 100644 --- a/server-common/src/main/java/io/a2a/server/AgentCardCacheMetadata.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/AgentCardCacheMetadata.java @@ -1,4 +1,4 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -18,10 +18,10 @@ import org.jspecify.annotations.Nullable; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.server.config.A2AConfigProvider; -import io.a2a.spec.AgentCard; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.config.A2AConfigProvider; +import org.a2aproject.sdk.spec.AgentCard; /** * Provides HTTP caching metadata for Agent Card responses. diff --git a/server-common/src/main/java/io/a2a/server/AgentCardValidator.java b/server-common/src/main/java/org/a2aproject/sdk/server/AgentCardValidator.java similarity index 91% rename from server-common/src/main/java/io/a2a/server/AgentCardValidator.java rename to server-common/src/main/java/org/a2aproject/sdk/server/AgentCardValidator.java index cd499359c..e361c2735 100644 --- a/server-common/src/main/java/io/a2a/server/AgentCardValidator.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/AgentCardValidator.java @@ -1,4 +1,4 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; import java.util.ArrayList; import java.util.HashSet; @@ -8,9 +8,9 @@ import java.util.logging.Logger; import java.util.stream.Collectors; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.TransportProtocol; /** * Validates AgentCard transport configuration against available transport endpoints. @@ -20,10 +20,10 @@ public class AgentCardValidator { private static final Logger LOGGER = Logger.getLogger(AgentCardValidator.class.getName()); // Properties to turn off validation globally, or per known transport - public static final String SKIP_PROPERTY = "io.a2a.transport.skipValidation"; - public static final String SKIP_JSONRPC_PROPERTY = "io.a2a.transport.jsonrpc.skipValidation"; - public static final String SKIP_GRPC_PROPERTY = "io.a2a.transport.grpc.skipValidation"; - public static final String SKIP_REST_PROPERTY = "io.a2a.transport.rest.skipValidation"; + public static final String SKIP_PROPERTY = "org.a2aproject.sdk.transport.skipValidation"; + public static final String SKIP_JSONRPC_PROPERTY = "org.a2aproject.sdk.transport.jsonrpc.skipValidation"; + public static final String SKIP_GRPC_PROPERTY = "org.a2aproject.sdk.transport.grpc.skipValidation"; + public static final String SKIP_REST_PROPERTY = "org.a2aproject.sdk.transport.rest.skipValidation"; /** * Validates the transport configuration of an AgentCard against available transports found on the classpath. diff --git a/server-common/src/main/java/io/a2a/server/ExtendedAgentCard.java b/server-common/src/main/java/org/a2aproject/sdk/server/ExtendedAgentCard.java similarity index 93% rename from server-common/src/main/java/io/a2a/server/ExtendedAgentCard.java rename to server-common/src/main/java/org/a2aproject/sdk/server/ExtendedAgentCard.java index c9cc7eaf0..86ff36dfa 100644 --- a/server-common/src/main/java/io/a2a/server/ExtendedAgentCard.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/ExtendedAgentCard.java @@ -1,4 +1,4 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; diff --git a/server-common/src/main/java/io/a2a/server/JSONRPCException.java b/server-common/src/main/java/org/a2aproject/sdk/server/JSONRPCException.java similarity index 89% rename from server-common/src/main/java/io/a2a/server/JSONRPCException.java rename to server-common/src/main/java/org/a2aproject/sdk/server/JSONRPCException.java index 3911355d6..70798d8c8 100644 --- a/server-common/src/main/java/io/a2a/server/JSONRPCException.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/JSONRPCException.java @@ -1,6 +1,6 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; -import io.a2a.spec.A2AError; +import org.a2aproject.sdk.spec.A2AError; /** * Exception wrapper for JSON-RPC protocol errors. diff --git a/server-common/src/main/java/io/a2a/server/PublicAgentCard.java b/server-common/src/main/java/org/a2aproject/sdk/server/PublicAgentCard.java similarity index 93% rename from server-common/src/main/java/io/a2a/server/PublicAgentCard.java rename to server-common/src/main/java/org/a2aproject/sdk/server/PublicAgentCard.java index 68c670bbe..72d19b3af 100644 --- a/server-common/src/main/java/io/a2a/server/PublicAgentCard.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/PublicAgentCard.java @@ -1,4 +1,4 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; diff --git a/server-common/src/main/java/io/a2a/server/ServerCallContext.java b/server-common/src/main/java/org/a2aproject/sdk/server/ServerCallContext.java similarity index 95% rename from server-common/src/main/java/io/a2a/server/ServerCallContext.java rename to server-common/src/main/java/org/a2aproject/sdk/server/ServerCallContext.java index 21a9e790b..aed6827ed 100644 --- a/server-common/src/main/java/io/a2a/server/ServerCallContext.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/ServerCallContext.java @@ -1,17 +1,17 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import io.a2a.server.auth.User; +import org.a2aproject.sdk.server.auth.User; import org.jspecify.annotations.Nullable; public class ServerCallContext { /** * Key for transport protocol type in the state map. - * Value should be a {@link io.a2a.spec.TransportProtocol} instance. + * Value should be a {@link org.a2aproject.sdk.spec.TransportProtocol} instance. */ public static final String TRANSPORT_KEY = "transport"; @@ -123,7 +123,7 @@ public void setEventConsumerCancelCallback(@Nullable Runnable callback) { *

            * * @see #setEventConsumerCancelCallback(Runnable) - * @see io.a2a.server.events.EventConsumer#cancel() + * @see org.a2aproject.sdk.server.events.EventConsumer#cancel() */ public void invokeEventConsumerCancelCallback() { Runnable callback = this.eventConsumerCancelCallback; diff --git a/server-common/src/main/java/io/a2a/server/TransportMetadata.java b/server-common/src/main/java/org/a2aproject/sdk/server/TransportMetadata.java similarity index 95% rename from server-common/src/main/java/io/a2a/server/TransportMetadata.java rename to server-common/src/main/java/org/a2aproject/sdk/server/TransportMetadata.java index 207ebcc67..c10c2455d 100644 --- a/server-common/src/main/java/io/a2a/server/TransportMetadata.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/TransportMetadata.java @@ -1,4 +1,4 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; /** diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java b/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/AgentExecutor.java similarity index 86% rename from server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java rename to server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/AgentExecutor.java index 08d6b56d9..aba33913a 100644 --- a/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/AgentExecutor.java @@ -1,20 +1,20 @@ -package io.a2a.server.agentexecution; +package org.a2aproject.sdk.server.agentexecution; -import io.a2a.server.events.EventQueue; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.A2AError; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; /** * Core business logic interface for implementing A2A agent functionality. *

            * This is the primary extension point where agent developers implement their agent's behavior - * LLM interactions, data processing, external API calls, or any custom logic. Along with an - * {@link io.a2a.spec.AgentCard}, implementing this interface is the minimum requirement to + * {@link org.a2aproject.sdk.spec.AgentCard}, implementing this interface is the minimum requirement to * create a functioning A2A agent. *

            * *

            Lifecycle

            - * The {@link io.a2a.server.requesthandlers.DefaultRequestHandler} executes AgentExecutor methods + * The {@link org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler} executes AgentExecutor methods * asynchronously in a background thread pool when requests arrive from transport layers. * Your implementation should: *
              @@ -94,14 +94,14 @@ * * @see RequestContext * @see AgentEmitter - * @see io.a2a.server.requesthandlers.DefaultRequestHandler - * @see io.a2a.spec.AgentCard + * @see org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler + * @see org.a2aproject.sdk.spec.AgentCard */ public interface AgentExecutor { /** * Executes the agent's business logic for a message. *

              - * Called asynchronously by {@link io.a2a.server.requesthandlers.DefaultRequestHandler} + * Called asynchronously by {@link org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler} * in a background thread when a client sends a message. Enqueue events to the queue as * processing progresses. The queue remains open until you enqueue a final event * (COMPLETED, FAILED, or CANCELED state). @@ -135,7 +135,7 @@ public interface AgentExecutor { *

              * Error Handling: *

                - *
              • Throw {@link io.a2a.spec.TaskNotCancelableError} if your agent does not support + *
              • Throw {@link org.a2aproject.sdk.spec.TaskNotCancelableError} if your agent does not support * cancellation at all (e.g., fire-and-forget agents)
              • *
              • Throw {@link A2AError} if cancellation is supported but failed to execute * (e.g., unable to interrupt running operation)
              • @@ -144,7 +144,7 @@ public interface AgentExecutor { * * @param context the request context for the task being canceled * @param emitter the agent emitter for sending the cancellation event - * @throws io.a2a.spec.TaskNotCancelableError if this agent does not support cancellation + * @throws org.a2aproject.sdk.spec.TaskNotCancelableError if this agent does not support cancellation * @throws A2AError if cancellation is supported but failed to execute */ void cancel(RequestContext context, AgentEmitter emitter) throws A2AError; diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java b/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/RequestContext.java similarity index 97% rename from server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java rename to server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/RequestContext.java index b88709163..ee8253bac 100644 --- a/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/RequestContext.java @@ -1,4 +1,4 @@ -package io.a2a.server.agentexecution; +package org.a2aproject.sdk.server.agentexecution; import java.util.ArrayList; import java.util.Collections; @@ -7,14 +7,14 @@ import java.util.UUID; import java.util.stream.Collectors; -import io.a2a.server.ServerCallContext; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TextPart; import org.jspecify.annotations.Nullable; /** diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/SimpleRequestContextBuilder.java b/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/SimpleRequestContextBuilder.java similarity index 88% rename from server-common/src/main/java/io/a2a/server/agentexecution/SimpleRequestContextBuilder.java rename to server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/SimpleRequestContextBuilder.java index 573d0e879..a340ee451 100644 --- a/server-common/src/main/java/io/a2a/server/agentexecution/SimpleRequestContextBuilder.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/SimpleRequestContextBuilder.java @@ -1,10 +1,10 @@ -package io.a2a.server.agentexecution; +package org.a2aproject.sdk.server.agentexecution; import java.util.ArrayList; import java.util.List; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Task; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.Task; public class SimpleRequestContextBuilder extends RequestContext.Builder { private final TaskStore taskStore; diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/package-info.java new file mode 100644 index 000000000..0c4d88b04 --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/agentexecution/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.agentexecution; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/auth/UnauthenticatedUser.java b/server-common/src/main/java/org/a2aproject/sdk/server/auth/UnauthenticatedUser.java similarity index 89% rename from server-common/src/main/java/io/a2a/server/auth/UnauthenticatedUser.java rename to server-common/src/main/java/org/a2aproject/sdk/server/auth/UnauthenticatedUser.java index 9988ebbcf..858b77dff 100644 --- a/server-common/src/main/java/io/a2a/server/auth/UnauthenticatedUser.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/auth/UnauthenticatedUser.java @@ -1,4 +1,4 @@ -package io.a2a.server.auth; +package org.a2aproject.sdk.server.auth; public class UnauthenticatedUser implements User { diff --git a/server-common/src/main/java/io/a2a/server/auth/User.java b/server-common/src/main/java/org/a2aproject/sdk/server/auth/User.java similarity index 67% rename from server-common/src/main/java/io/a2a/server/auth/User.java rename to server-common/src/main/java/org/a2aproject/sdk/server/auth/User.java index f41e98444..4d2e56185 100644 --- a/server-common/src/main/java/io/a2a/server/auth/User.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/auth/User.java @@ -1,4 +1,4 @@ -package io.a2a.server.auth; +package org.a2aproject.sdk.server.auth; public interface User { boolean isAuthenticated(); diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/auth/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/auth/package-info.java new file mode 100644 index 000000000..3c8da57b2 --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/auth/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.auth; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/config/A2AConfigProvider.java b/server-common/src/main/java/org/a2aproject/sdk/server/config/A2AConfigProvider.java similarity index 96% rename from server-common/src/main/java/io/a2a/server/config/A2AConfigProvider.java rename to server-common/src/main/java/org/a2aproject/sdk/server/config/A2AConfigProvider.java index ccd442e1c..cc12688fb 100644 --- a/server-common/src/main/java/io/a2a/server/config/A2AConfigProvider.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/config/A2AConfigProvider.java @@ -1,4 +1,4 @@ -package io.a2a.server.config; +package org.a2aproject.sdk.server.config; import java.util.Optional; diff --git a/server-common/src/main/java/io/a2a/server/config/DefaultValuesConfigProvider.java b/server-common/src/main/java/org/a2aproject/sdk/server/config/DefaultValuesConfigProvider.java similarity index 98% rename from server-common/src/main/java/io/a2a/server/config/DefaultValuesConfigProvider.java rename to server-common/src/main/java/org/a2aproject/sdk/server/config/DefaultValuesConfigProvider.java index f2375ae57..fe5cd0367 100644 --- a/server-common/src/main/java/io/a2a/server/config/DefaultValuesConfigProvider.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/config/DefaultValuesConfigProvider.java @@ -1,4 +1,4 @@ -package io.a2a.server.config; +package org.a2aproject.sdk.server.config; import java.io.IOException; import java.io.InputStream; diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/config/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/config/package-info.java new file mode 100644 index 000000000..dd34667ea --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/config/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.config; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/EnhancedRunnable.java similarity index 97% rename from server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/EnhancedRunnable.java index 2ccf3fb60..0650e1284 100644 --- a/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/EnhancedRunnable.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; diff --git a/server-common/src/main/java/io/a2a/server/events/EventConsumer.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventConsumer.java similarity index 98% rename from server-common/src/main/java/io/a2a/server/events/EventConsumer.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/EventConsumer.java index 324d6e2d0..aa357618f 100644 --- a/server-common/src/main/java/io/a2a/server/events/EventConsumer.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventConsumer.java @@ -1,15 +1,15 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import java.util.concurrent.Executor; import java.util.concurrent.Flow; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.A2AServerException; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import mutiny.zero.BackpressureStrategy; import mutiny.zero.TubeConfiguration; import mutiny.zero.ZeroPublisher; diff --git a/server-common/src/main/java/io/a2a/server/events/EventEnqueueHook.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventEnqueueHook.java similarity index 91% rename from server-common/src/main/java/io/a2a/server/events/EventEnqueueHook.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/EventEnqueueHook.java index e61284917..198702253 100644 --- a/server-common/src/main/java/io/a2a/server/events/EventEnqueueHook.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventEnqueueHook.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; /** * Hook interface for event queue enqueue operations. diff --git a/server-common/src/main/java/io/a2a/server/events/EventQueue.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueue.java similarity index 99% rename from server-common/src/main/java/io/a2a/server/events/EventQueue.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueue.java index 6226f72e2..253a0c8ad 100644 --- a/server-common/src/main/java/io/a2a/server/events/EventQueue.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueue.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import java.util.List; import java.util.Objects; @@ -10,11 +10,11 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import io.a2a.server.tasks.TaskStateProvider; -import io.a2a.spec.Event; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.server.tasks.TaskStateProvider; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; 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/EventQueueClosedException.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueClosedException.java similarity index 84% rename from server-common/src/main/java/io/a2a/server/events/EventQueueClosedException.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueClosedException.java index 5fe80637d..5f88086a1 100644 --- a/server-common/src/main/java/io/a2a/server/events/EventQueueClosedException.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueClosedException.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; /** * Exception thrown when attempting to dequeue from a closed and empty event queue. diff --git a/server-common/src/main/java/io/a2a/server/events/EventQueueFactory.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueFactory.java similarity index 90% rename from server-common/src/main/java/io/a2a/server/events/EventQueueFactory.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueFactory.java index 3f062e660..2348c85d7 100644 --- a/server-common/src/main/java/io/a2a/server/events/EventQueueFactory.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueFactory.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; public interface EventQueueFactory { /** diff --git a/server-common/src/main/java/io/a2a/server/events/EventQueueItem.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueItem.java similarity index 92% rename from server-common/src/main/java/io/a2a/server/events/EventQueueItem.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueItem.java index e2bfc8f3c..92079cf86 100644 --- a/server-common/src/main/java/io/a2a/server/events/EventQueueItem.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventQueueItem.java @@ -1,6 +1,6 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; -import io.a2a.spec.Event; +import org.a2aproject.sdk.spec.Event; /** * Represents an item that can be enqueued/dequeued in an EventQueue. diff --git a/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/InMemoryQueueManager.java similarity index 98% rename from server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/InMemoryQueueManager.java index 53a089e4c..4ed55a0a8 100644 --- a/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/InMemoryQueueManager.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -6,7 +6,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import io.a2a.server.tasks.TaskStateProvider; +import org.a2aproject.sdk.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/events/LocalEventQueueItem.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/LocalEventQueueItem.java similarity index 83% rename from server-common/src/main/java/io/a2a/server/events/LocalEventQueueItem.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/LocalEventQueueItem.java index 88c32024d..8eb53c523 100644 --- a/server-common/src/main/java/io/a2a/server/events/LocalEventQueueItem.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/LocalEventQueueItem.java @@ -1,7 +1,7 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; -import io.a2a.spec.Event; -import io.a2a.util.Assert; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.util.Assert; /** * Represents a locally-generated event in the queue. diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBus.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBus.java similarity index 97% rename from server-common/src/main/java/io/a2a/server/events/MainEventBus.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBus.java index 90080b1e2..76d6258d1 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBus.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBus.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusContext.java similarity index 90% rename from server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusContext.java index 292a60f21..f7e672b06 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusContext.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import java.util.Objects; diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java similarity index 96% rename from server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java index d7eece30b..3b5019856 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import java.util.concurrent.CompletableFuture; @@ -8,20 +8,20 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.server.tasks.TaskManager; -import io.a2a.server.tasks.TaskPersistenceException; -import io.a2a.server.tasks.TaskSerializationException; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Event; -import io.a2a.spec.InternalError; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.server.tasks.TaskManager; +import org.a2aproject.sdk.server.tasks.TaskPersistenceException; +import org.a2aproject.sdk.server.tasks.TaskSerializationException; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.A2AServerException; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessorCallback.java similarity index 95% rename from server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessorCallback.java index b0a9adbce..2dbe827be 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessorCallback.java @@ -1,6 +1,6 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; -import io.a2a.spec.Event; +import org.a2aproject.sdk.spec.Event; /** * Callback interface for MainEventBusProcessor events. diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessorInitializer.java similarity index 97% rename from server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessorInitializer.java index ba4b300be..707b04d1f 100644 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessorInitializer.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.Initialized; diff --git a/server-common/src/main/java/io/a2a/server/events/NoTaskQueueException.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/NoTaskQueueException.java similarity index 97% rename from server-common/src/main/java/io/a2a/server/events/NoTaskQueueException.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/NoTaskQueueException.java index 5783dd214..cdb017434 100644 --- a/server-common/src/main/java/io/a2a/server/events/NoTaskQueueException.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/NoTaskQueueException.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; /** * Exception thrown when attempting to access a task queue that does not exist. diff --git a/server-common/src/main/java/io/a2a/server/events/QueueClosedEvent.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/QueueClosedEvent.java similarity index 92% rename from server-common/src/main/java/io/a2a/server/events/QueueClosedEvent.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/QueueClosedEvent.java index b18c1a47a..7f14644dc 100644 --- a/server-common/src/main/java/io/a2a/server/events/QueueClosedEvent.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/QueueClosedEvent.java @@ -1,6 +1,6 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; -import io.a2a.spec.Event; +import org.a2aproject.sdk.spec.Event; /** * Poison pill event used to signal that a queue has been closed. diff --git a/server-common/src/main/java/io/a2a/server/events/QueueManager.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/QueueManager.java similarity index 94% rename from server-common/src/main/java/io/a2a/server/events/QueueManager.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/QueueManager.java index 4ad30f0cb..b32b4041d 100644 --- a/server-common/src/main/java/io/a2a/server/events/QueueManager.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/QueueManager.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import org.jspecify.annotations.Nullable; @@ -22,7 +22,7 @@ *

                Queue Lifecycle

                *
                  *
                1. Creation: {@link #createOrTap(String)} creates MainQueue for new task or taps existing for resubscription
                2. - *
                3. Population: Agent enqueues events to MainQueue via {@link EventQueue#enqueueEvent(io.a2a.spec.Event)}
                4. + *
                5. Population: Agent enqueues events to MainQueue via {@link EventQueue#enqueueEvent(org.a2aproject.sdk.spec.Event)}
                6. *
                7. Distribution: Events automatically copied to all ChildQueues
                8. *
                9. Consumption: Consumers poll events from their queues (Main or Child)
                10. *
                11. Closure: Queue closes on final event (COMPLETED/FAILED/CANCELED) or explicit close
                12. @@ -33,7 +33,7 @@ * {@link InMemoryQueueManager} provides the standard implementation: *
                    *
                  • Stores queues in thread-safe {@link java.util.concurrent.ConcurrentHashMap}
                  • - *
                  • Integrates with {@link io.a2a.server.tasks.TaskStateProvider} for cleanup decisions
                  • + *
                  • Integrates with {@link org.a2aproject.sdk.server.tasks.TaskStateProvider} for cleanup decisions
                  • *
                  • Removes queues when tasks enter final state (COMPLETED/FAILED/CANCELED)
                  • *
                  • Supports queue tapping for resubscription scenarios
                  • *
                  @@ -78,8 +78,8 @@ * * @see EventQueue * @see InMemoryQueueManager - * @see io.a2a.server.tasks.TaskStateProvider - * @see io.a2a.server.requesthandlers.DefaultRequestHandler + * @see org.a2aproject.sdk.server.tasks.TaskStateProvider + * @see org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler */ public interface QueueManager { @@ -139,7 +139,7 @@ public interface QueueManager { /** * Creates a MainQueue if none exists, or taps the existing queue to create a ChildQueue. *

                  - * This is the primary method used by {@link io.a2a.server.requesthandlers.DefaultRequestHandler}: + * This is the primary method used by {@link org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler}: *

                    *
                  • New task: Creates and returns a MainQueue
                  • *
                  • Resubscription: Taps existing MainQueue and returns a ChildQueue
                  • diff --git a/server-common/src/main/java/io/a2a/server/events/TaskQueueExistsException.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/TaskQueueExistsException.java similarity index 93% rename from server-common/src/main/java/io/a2a/server/events/TaskQueueExistsException.java rename to server-common/src/main/java/org/a2aproject/sdk/server/events/TaskQueueExistsException.java index bfd429277..2c8d6c473 100644 --- a/server-common/src/main/java/io/a2a/server/events/TaskQueueExistsException.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/TaskQueueExistsException.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; public class TaskQueueExistsException extends RuntimeException { public TaskQueueExistsException() { diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/events/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/package-info.java new file mode 100644 index 000000000..18d7f58de --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.events; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java b/server-common/src/main/java/org/a2aproject/sdk/server/extensions/A2AExtensions.java similarity index 90% rename from server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java rename to server-common/src/main/java/org/a2aproject/sdk/server/extensions/A2AExtensions.java index 45e0e3ac2..e2103291b 100644 --- a/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/extensions/A2AExtensions.java @@ -1,13 +1,13 @@ -package io.a2a.server.extensions; +package org.a2aproject.sdk.server.extensions; import java.util.HashSet; import java.util.List; import java.util.Set; -import io.a2a.server.ServerCallContext; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentExtension; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; import org.jspecify.annotations.Nullable; public class A2AExtensions { diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/extensions/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/extensions/package-info.java new file mode 100644 index 000000000..47dd73fb5 --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/extensions/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.extensions; + +import org.jspecify.annotations.NullMarked; diff --git a/client/base/src/main/java/io/a2a/client/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/package-info.java similarity index 61% rename from client/base/src/main/java/io/a2a/client/package-info.java rename to server-common/src/main/java/org/a2aproject/sdk/server/package-info.java index 73cc3eef8..1e1d41733 100644 --- a/client/base/src/main/java/io/a2a/client/package-info.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/package-info.java @@ -1,5 +1,4 @@ @NullMarked -package io.a2a.client; +package org.a2aproject.sdk.server; import org.jspecify.annotations.NullMarked; - diff --git a/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java similarity index 93% rename from server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java rename to server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java index bd78b6159..8184d7baf 100644 --- a/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java @@ -1,10 +1,10 @@ -package io.a2a.server.requesthandlers; +package org.a2aproject.sdk.server.requesthandlers; -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.insertingProcessor; -import static io.a2a.server.util.async.AsyncUtils.processor; import static java.util.concurrent.TimeUnit.SECONDS; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.convertingProcessor; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.createTubeConfig; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.insertingProcessor; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.processor; import java.time.Instant; import java.util.HashMap; @@ -25,49 +25,49 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -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; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.server.events.QueueManager; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.server.tasks.ResultAggregator; -import io.a2a.server.tasks.TaskManager; -import io.a2a.server.tasks.TaskStore; -import io.a2a.server.util.async.EventConsumerExecutorProducer.EventConsumerExecutor; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.A2AError; -import io.a2a.spec.CancelTaskParams; -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.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.UnsupportedOperationError; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.agentexecution.SimpleRequestContextBuilder; +import org.a2aproject.sdk.server.config.A2AConfigProvider; +import org.a2aproject.sdk.server.events.EnhancedRunnable; +import org.a2aproject.sdk.server.events.EventConsumer; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.events.EventQueueItem; +import org.a2aproject.sdk.server.events.MainEventBusProcessor; +import org.a2aproject.sdk.server.events.QueueManager; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.server.tasks.ResultAggregator; +import org.a2aproject.sdk.server.tasks.TaskManager; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.server.util.async.EventConsumerExecutorProducer.EventConsumerExecutor; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; @@ -151,11 +151,11 @@ * This class is {@code @ApplicationScoped} and automatically injects: *
                      *
                    • {@link AgentExecutor} - User-provided agent business logic (required)
                    • - *
                    • {@link TaskStore} - Task persistence (default: {@link io.a2a.server.tasks.InMemoryTaskStore})
                    • - *
                    • {@link QueueManager} - Event queue management (default: {@link io.a2a.server.events.InMemoryQueueManager})
                    • - *
                    • {@link PushNotificationConfigStore} - Push config storage (default: {@link io.a2a.server.tasks.InMemoryPushNotificationConfigStore})
                    • - *
                    • {@link PushNotificationSender} - Push notification delivery (default: {@link io.a2a.server.tasks.BasePushNotificationSender})
                    • - *
                    • {@link io.a2a.server.config.A2AConfigProvider} - Configuration values
                    • + *
                    • {@link TaskStore} - Task persistence (default: {@link org.a2aproject.sdk.server.tasks.InMemoryTaskStore})
                    • + *
                    • {@link QueueManager} - Event queue management (default: {@link org.a2aproject.sdk.server.events.InMemoryQueueManager})
                    • + *
                    • {@link PushNotificationConfigStore} - Push config storage (default: {@link org.a2aproject.sdk.server.tasks.InMemoryPushNotificationConfigStore})
                    • + *
                    • {@link PushNotificationSender} - Push notification delivery (default: {@link org.a2aproject.sdk.server.tasks.BasePushNotificationSender})
                    • + *
                    • {@link org.a2aproject.sdk.server.config.A2AConfigProvider} - Configuration values
                    • *
                    • {@link java.util.concurrent.Executor} (@Internal) - Background thread pool
                    • *
                    * @@ -184,9 +184,9 @@ public class DefaultRequestHandler implements RequestHandler { /** * Separate logger for thread statistics diagnostic logging. * This allows independent control of verbose thread pool monitoring without affecting - * general request handler logging. Enable with: logging.level.io.a2a.server.diagnostics.ThreadStats=DEBUG + * general request handler logging. Enable with: logging.level.org.a2aproject.sdk.server.diagnostics.ThreadStats=DEBUG */ - private static final Logger THREAD_STATS_LOGGER = LoggerFactory.getLogger("io.a2a.server.diagnostics.ThreadStats"); + private static final Logger THREAD_STATS_LOGGER = LoggerFactory.getLogger("org.a2aproject.sdk.server.diagnostics.ThreadStats"); private static final String A2A_BLOCKING_AGENT_TIMEOUT_SECONDS = "a2a.blocking.agent.timeout.seconds"; private static final String A2A_BLOCKING_CONSUMPTION_TIMEOUT_SECONDS = "a2a.blocking.consumption.timeout.seconds"; @@ -407,7 +407,7 @@ public Task onCancelTask(CancelTaskParams params, ServerCallContext context) thr } catch (Exception e) { // Unexpected errors - log and enqueue as InternalError LOGGER.error("Agent cancellation threw unexpected exception for task {}", task.id(), e); - emitter.fail(new io.a2a.spec.InternalError("Agent cancellation failed: " + e.getMessage())); + emitter.fail(new InternalError("Agent cancellation failed: " + e.getMessage())); } // Cancel any running agent future @@ -512,7 +512,7 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte // AUTH_REQUIRED expects the client to receive it immediately and handle it out-of-band, // while the agent continues executing in the background boolean requiresImmediateReturn = kind instanceof Task task && - task.status().state() == io.a2a.spec.TaskState.TASK_STATE_AUTH_REQUIRED; + task.status().state() == org.a2aproject.sdk.spec.TaskState.TASK_STATE_AUTH_REQUIRED; if (requiresImmediateReturn) { LOGGER.debug("DefaultRequestHandler: Task {} in AUTH_REQUIRED state, skipping fire-and-forget handling", taskId.get()); @@ -934,11 +934,11 @@ public void run() { // Log unexpected runtime exceptions at ERROR level // These indicate bugs in agent implementation LOGGER.error("Agent execution threw unexpected RuntimeException for task {}", taskId, e); - emitter.fail(new io.a2a.spec.InternalError("Agent execution failed: " + e.getMessage())); + emitter.fail(new org.a2aproject.sdk.spec.InternalError("Agent execution failed: " + e.getMessage())); } catch (Exception e) { // Log other exceptions at ERROR level LOGGER.error("Agent execution threw unexpected Exception for task {}", taskId, e); - emitter.fail(new io.a2a.spec.InternalError("Agent execution failed: " + e.getMessage())); + emitter.fail(new org.a2aproject.sdk.spec.InternalError("Agent execution failed: " + e.getMessage())); } LOGGER.debug("Agent execution completed for task {}", taskId); // The consumer (running on the Vert.x worker thread) handles queue lifecycle. @@ -1120,7 +1120,7 @@ private MessageSendSetup initMessageSend(MessageSendParams params, ServerCallCon * Only logs when DEBUG level is enabled. Call this from debugger or add strategic * calls during investigation. In production with INFO logging, this is a no-op. *

                    - * Enable independently with: {@code logging.level.io.a2a.server.diagnostics.ThreadStats=DEBUG} + * Enable independently with: {@code logging.level.org.a2aproject.sdk.server.diagnostics.ThreadStats=DEBUG} *

                    */ @SuppressWarnings("unused") // Used for debugging diff --git a/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/RequestHandler.java similarity index 62% rename from server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java rename to server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/RequestHandler.java index 06bc11354..8edad37c0 100644 --- a/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/RequestHandler.java @@ -1,23 +1,23 @@ -package io.a2a.server.requesthandlers; +package org.a2aproject.sdk.server.requesthandlers; 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.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; public interface RequestHandler { Task onGetTask( diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/package-info.java new file mode 100644 index 000000000..0be56b581 --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.requesthandlers; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/AgentEmitter.java similarity index 95% rename from server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/AgentEmitter.java index d300cbca2..c062b6989 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/AgentEmitter.java @@ -1,23 +1,23 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.spec.A2AError; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -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.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.jspecify.annotations.Nullable; /** @@ -88,7 +88,7 @@ * * Events are validated by the EventQueue to ensure taskId correctness. * - * @see io.a2a.server.agentexecution.AgentExecutor + * @see org.a2aproject.sdk.server.agentexecution.AgentExecutor * @see RequestContext * @see EventQueue * @since 1.0.0 @@ -260,8 +260,8 @@ public void fail(@Nullable Message message) { * Enqueues an A2A error event which will automatically transition the task to FAILED. *

                    * Use this when you need to fail the task with a specific A2A error (such as - * {@link io.a2a.spec.UnsupportedOperationError}, {@link io.a2a.spec.InvalidRequestError}, - * {@link io.a2a.spec.TaskNotFoundError}, etc.) that should be sent to the client. + * {@link org.a2aproject.sdk.spec.UnsupportedOperationError}, {@link org.a2aproject.sdk.spec.InvalidRequestError}, + * {@link org.a2aproject.sdk.spec.TaskNotFoundError}, etc.) that should be sent to the client. *

                    *

                    * The error event is enqueued and the MainEventBusProcessor will automatically transition diff --git a/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java similarity index 86% rename from server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java index c11fb598f..6d8991f22 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java @@ -1,10 +1,10 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import static io.a2a.client.http.A2AHttpClient.APPLICATION_JSON; -import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; -import static io.a2a.common.A2AHeaders.X_A2A_NOTIFICATION_TOKEN; +import static org.a2aproject.sdk.client.http.A2AHttpClient.APPLICATION_JSON; +import static org.a2aproject.sdk.client.http.A2AHttpClient.CONTENT_TYPE; +import static org.a2aproject.sdk.common.A2AHeaders.X_A2A_NOTIFICATION_TOKEN; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import jakarta.annotation.Nullable; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -16,16 +16,16 @@ import java.util.concurrent.ExecutionException; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; 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/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStore.java similarity index 93% rename from server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStore.java index 16ab9bf9f..cd02cf5d6 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStore.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import java.util.ArrayList; import java.util.Collections; @@ -10,10 +10,10 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import io.a2a.util.Assert; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; /** * In-memory implementation of the PushNotificationConfigStore interface. diff --git a/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStore.java similarity index 97% rename from server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStore.java index 7c443b1cc..7bce70841 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStore.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import java.util.Comparator; import java.util.List; @@ -7,12 +7,12 @@ 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.Message; -import io.a2a.util.PageToken; -import io.a2a.spec.Task; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.util.PageToken; +import org.a2aproject.sdk.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/org/a2aproject/sdk/server/tasks/PushNotificationConfigStore.java similarity index 93% rename from server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationConfigStore.java index 4c5f35eda..fd1460b9a 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationConfigStore.java @@ -1,8 +1,8 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; /** * Interface for storing and retrieving push notification configurations for tasks. @@ -65,7 +65,7 @@ * * @see PushNotificationSender * @see InMemoryPushNotificationConfigStore - * @see io.a2a.spec.TaskPushNotificationConfig + * @see org.a2aproject.sdk.spec.TaskPushNotificationConfig */ public interface PushNotificationConfigStore { diff --git a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationSender.java similarity index 86% rename from server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationSender.java index d2e8bd6cf..304fed683 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationSender.java @@ -1,7 +1,7 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; /** * Interface for delivering push notifications containing task state updates to external systems. @@ -12,7 +12,7 @@ *

                    * *

                    Invocation Context

                    - * Called by {@link io.a2a.server.requesthandlers.DefaultRequestHandler} after: + * Called by {@link org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler} after: *
                      *
                    • Task events are persisted to {@link TaskStore}
                    • *
                    • Events are returned/streamed to the requesting client
                    • @@ -75,7 +75,7 @@ * * @see PushNotificationConfigStore * @see BasePushNotificationSender - * @see io.a2a.spec.TaskPushNotificationConfig + * @see org.a2aproject.sdk.spec.TaskPushNotificationConfig */ public interface PushNotificationSender { @@ -93,9 +93,9 @@ public interface PushNotificationSender { * Supported event types: *
                        *
                      • {@link Task} - wrapped in StreamResponse.task
                      • - *
                      • {@link io.a2a.spec.Message} - wrapped in StreamResponse.message
                      • - *
                      • {@link io.a2a.spec.TaskStatusUpdateEvent} - wrapped in StreamResponse.statusUpdate
                      • - *
                      • {@link io.a2a.spec.TaskArtifactUpdateEvent} - wrapped in StreamResponse.artifactUpdate
                      • + *
                      • {@link org.a2aproject.sdk.spec.Message} - wrapped in StreamResponse.message
                      • + *
                      • {@link org.a2aproject.sdk.spec.TaskStatusUpdateEvent} - wrapped in StreamResponse.statusUpdate
                      • + *
                      • {@link org.a2aproject.sdk.spec.TaskArtifactUpdateEvent} - wrapped in StreamResponse.artifactUpdate
                      • *
                      *

                      * Error Handling: Log errors but don't throw exceptions. Notifications are diff --git a/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/ResultAggregator.java similarity index 93% rename from server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/ResultAggregator.java index f1f15021e..51fc583c9 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/ResultAggregator.java @@ -1,28 +1,27 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import static io.a2a.server.util.async.AsyncUtils.consumer; -import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; -import static io.a2a.server.util.async.AsyncUtils.processor; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.consumer; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.createTubeConfig; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.processor; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.Executor; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import io.a2a.server.events.EventConsumer; -import io.a2a.server.events.EventQueueItem; -import io.a2a.spec.A2AError; -import io.a2a.spec.Event; -import io.a2a.spec.EventKind; -import io.a2a.spec.InternalError; -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.a2aproject.sdk.server.events.EventConsumer; +import org.a2aproject.sdk.server.events.EventQueueItem; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,7 +64,6 @@ public Flow.Publisher consumeAndEmit(EventConsumer consumer) { return processed; } - public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, boolean blocking) throws A2AError { Flow.Publisher allItems = consumer.consumeAll(); AtomicReference message = new AtomicReference<>(); @@ -212,7 +210,7 @@ else if (blocking) { pollingStarted.await(5, java.util.concurrent.TimeUnit.SECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new io.a2a.spec.InternalError("Interrupted waiting for EventConsumer to start"); + throw new org.a2aproject.sdk.spec.InternalError("Interrupted waiting for EventConsumer to start"); } // Wait for completion or interruption diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskManager.java similarity index 92% rename from server-common/src/main/java/io/a2a/server/tasks/TaskManager.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskManager.java index bba80bf53..53c929c26 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskManager.java @@ -1,9 +1,9 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import static io.a2a.spec.TaskState.TASK_STATE_FAILED; -import static io.a2a.spec.TaskState.TASK_STATE_SUBMITTED; -import static io.a2a.util.Assert.checkNotNullParam; -import static io.a2a.util.Utils.appendArtifactToTask; +import static org.a2aproject.sdk.spec.TaskState.TASK_STATE_FAILED; +import static org.a2aproject.sdk.spec.TaskState.TASK_STATE_SUBMITTED; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; +import static org.a2aproject.sdk.util.Utils.appendArtifactToTask; import java.util.ArrayList; import java.util.Collections; @@ -11,15 +11,15 @@ import java.util.List; import java.util.Map; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Event; -import io.a2a.spec.InternalError; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.A2AServerException; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; 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/TaskPersistenceException.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskPersistenceException.java similarity index 98% rename from server-common/src/main/java/io/a2a/server/tasks/TaskPersistenceException.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskPersistenceException.java index 97007cab9..bceea8a98 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskPersistenceException.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskPersistenceException.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import org.jspecify.annotations.Nullable; diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskSerializationException.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskSerializationException.java similarity index 98% rename from server-common/src/main/java/io/a2a/server/tasks/TaskSerializationException.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskSerializationException.java index 5916ce530..80815e686 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskSerializationException.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskSerializationException.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import org.jspecify.annotations.Nullable; diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskStateProvider.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStateProvider.java similarity index 98% rename from server-common/src/main/java/io/a2a/server/tasks/TaskStateProvider.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStateProvider.java index 837befa48..3b8c39354 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskStateProvider.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStateProvider.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; /** * Provider interface for determining the active state of a task. diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStore.java similarity index 91% rename from server-common/src/main/java/io/a2a/server/tasks/TaskStore.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStore.java index 7ae7a46bf..86a6b76cb 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStore.java @@ -1,15 +1,15 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Task; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Task; import org.jspecify.annotations.Nullable; /** * Storage interface for managing task persistence across the task lifecycle. *

                      * TaskStore is responsible for persisting task state including status updates, artifacts, - * message history, and metadata. It's called by {@link io.a2a.server.requesthandlers.DefaultRequestHandler} + * message history, and metadata. It's called by {@link org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler} * and {@link TaskManager} to save task state as agents process requests and generate events. *

                      * @@ -82,7 +82,7 @@ * conflicts appropriately (last-write-wins, optimistic locking, etc.). * *

                      List Operation Performance

                      - * The {@link #list(io.a2a.spec.ListTasksParams)} method may need to scan and filter + * The {@link #list(org.a2aproject.sdk.spec.ListTasksParams)} method may need to scan and filter * many tasks. Database implementations should: *
                        *
                      • Use indexes on contextId, status, lastUpdatedAt
                      • @@ -137,8 +137,8 @@ * } * *

                        Exception Handling

                        - * {@link io.a2a.server.events.MainEventBusProcessor} catches TaskStore exceptions and - * wraps them in {@link io.a2a.spec.InternalError} events for client distribution. + * {@link org.a2aproject.sdk.server.events.MainEventBusProcessor} catches TaskStore exceptions and + * wraps them in {@link org.a2aproject.sdk.spec.InternalError} events for client distribution. * * @see TaskManager * @see TaskStateProvider @@ -146,8 +146,8 @@ * @see TaskSerializationException * @see TaskPersistenceException * @see InMemoryTaskStore - * @see io.a2a.server.requesthandlers.DefaultRequestHandler - * @see io.a2a.server.events.MainEventBusProcessor + * @see org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler + * @see org.a2aproject.sdk.server.events.MainEventBusProcessor */ public interface TaskStore { /** diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskStoreException.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStoreException.java similarity index 92% rename from server-common/src/main/java/io/a2a/server/tasks/TaskStoreException.java rename to server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStoreException.java index 5865c5a80..b4146b91e 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskStoreException.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskStoreException.java @@ -1,6 +1,6 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import io.a2a.spec.A2AServerException; +import org.a2aproject.sdk.spec.A2AServerException; import org.jspecify.annotations.Nullable; /** @@ -23,10 +23,10 @@ *
                      * *

                      Error Handling Pattern

                      - * Caught by {@link io.a2a.server.events.MainEventBusProcessor} which: + * Caught by {@link org.a2aproject.sdk.server.events.MainEventBusProcessor} which: *
                        *
                      1. Logs the failure with full context (taskId, operation)
                      2. - *
                      3. Distributes {@link io.a2a.spec.InternalError} event to clients
                      4. + *
                      5. Distributes {@link org.a2aproject.sdk.spec.InternalError} event to clients
                      6. *
                      7. Preserves exception cause chain for diagnostics
                      8. *
                      * diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/package-info.java new file mode 100644 index 000000000..2aec780e5 --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.tasks; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java b/server-common/src/main/java/org/a2aproject/sdk/server/util/ArtifactUtils.java similarity index 94% rename from server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java rename to server-common/src/main/java/org/a2aproject/sdk/server/util/ArtifactUtils.java index 4cb1f82b5..bdb4ea041 100644 --- a/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/ArtifactUtils.java @@ -1,12 +1,12 @@ -package io.a2a.server.util; +package org.a2aproject.sdk.server.util; import java.util.List; import java.util.UUID; -import io.a2a.spec.Artifact; -import io.a2a.spec.DataPart; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import org.jspecify.annotations.Nullable; /** diff --git a/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/AsyncExecutorProducer.java similarity index 98% rename from server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java rename to server-common/src/main/java/org/a2aproject/sdk/server/util/async/AsyncExecutorProducer.java index eee254ba3..f55cb88f8 100644 --- a/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/AsyncExecutorProducer.java @@ -1,4 +1,4 @@ -package io.a2a.server.util.async; +package org.a2aproject.sdk.server.util.async; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Executor; @@ -14,7 +14,7 @@ import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; -import io.a2a.server.config.A2AConfigProvider; +import org.a2aproject.sdk.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/org/a2aproject/sdk/server/util/async/AsyncUtils.java similarity index 99% rename from server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java rename to server-common/src/main/java/org/a2aproject/sdk/server/util/async/AsyncUtils.java index 4e0a6ea5b..cb2adc49b 100644 --- a/server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/AsyncUtils.java @@ -1,4 +1,4 @@ -package io.a2a.server.util.async; +package org.a2aproject.sdk.server.util.async; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicBoolean; @@ -7,7 +7,7 @@ import java.util.function.Consumer; import java.util.function.Function; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import mutiny.zero.BackpressureStrategy; import mutiny.zero.Tube; import mutiny.zero.TubeConfiguration; diff --git a/server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/EventConsumerExecutorProducer.java similarity index 98% rename from server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java rename to server-common/src/main/java/org/a2aproject/sdk/server/util/async/EventConsumerExecutorProducer.java index 24ff7f5d1..863cd9fe4 100644 --- a/server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/EventConsumerExecutorProducer.java @@ -1,4 +1,4 @@ -package io.a2a.server.util.async; +package org.a2aproject.sdk.server.util.async; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; diff --git a/server-common/src/main/java/io/a2a/server/util/async/Internal.java b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/Internal.java similarity index 89% rename from server-common/src/main/java/io/a2a/server/util/async/Internal.java rename to server-common/src/main/java/org/a2aproject/sdk/server/util/async/Internal.java index 7774d4838..8fc9a5c8e 100644 --- a/server-common/src/main/java/io/a2a/server/util/async/Internal.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/Internal.java @@ -1,4 +1,4 @@ -package io.a2a.server.util.async; +package org.a2aproject.sdk.server.util.async; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/util/async/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/package-info.java new file mode 100644 index 000000000..ebbb183af --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/async/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.util.async; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/util/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/util/package-info.java new file mode 100644 index 000000000..d14294577 --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.server.util; + +import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java b/server-common/src/main/java/org/a2aproject/sdk/server/util/sse/SseFormatter.java similarity index 69% rename from server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java rename to server-common/src/main/java/org/a2aproject/sdk/server/util/sse/SseFormatter.java index 8777f0f80..d147fee43 100644 --- a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/sse/SseFormatter.java @@ -1,18 +1,18 @@ -package io.a2a.server.util.sse; +package org.a2aproject.sdk.server.util.sse; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.jsonrpc.common.wrappers.A2AErrorResponse; -import io.a2a.jsonrpc.common.wrappers.A2AResponse; -import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; -import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AErrorResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageResponse; /** * Framework-agnostic utility for formatting A2A responses as Server-Sent Events (SSE). @@ -109,26 +109,26 @@ private static String serializeResponse(A2AResponse 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()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); } else if (response instanceof CancelTaskResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); } else if (response instanceof SendMessageResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessage(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.taskOrMessage(r.getResult()); } else if (response instanceof ListTasksResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.listTasksResult(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.listTasksResult(r.getResult()); } else if (response instanceof CreateTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.createTaskPushNotificationConfigResponse(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.createTaskPushNotificationConfigResponse(r.getResult()); } else if (response instanceof GetTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.getTaskPushNotificationConfigResponse(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.getTaskPushNotificationConfigResponse(r.getResult()); } else if (response instanceof ListTaskPushNotificationConfigsResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.listTaskPushNotificationConfigsResponse(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.listTaskPushNotificationConfigsResponse(r.getResult()); } else if (response instanceof DeleteTaskPushNotificationConfigResponse) { // DeleteTaskPushNotificationConfig has no result body, just return empty message return com.google.protobuf.Empty.getDefaultInstance(); } else if (response instanceof GetExtendedAgentCardResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.getExtendedCardResponse(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.getExtendedCardResponse(r.getResult()); } else if (response instanceof SendStreamingMessageResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessageStream(r.getResult()); + return org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto.taskOrMessageStream(r.getResult()); } else { throw new IllegalArgumentException("Unknown response type: " + response.getClass().getName()); } diff --git a/server-common/src/main/java/io/a2a/server/util/sse/package-info.java b/server-common/src/main/java/org/a2aproject/sdk/server/util/sse/package-info.java similarity index 89% rename from server-common/src/main/java/io/a2a/server/util/sse/package-info.java rename to server-common/src/main/java/org/a2aproject/sdk/server/util/sse/package-info.java index 7e668b632..f44556a6a 100644 --- a/server-common/src/main/java/io/a2a/server/util/sse/package-info.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/util/sse/package-info.java @@ -6,6 +6,6 @@ * any HTTP server framework (Vert.x, Jakarta Servlet, etc.). */ @NullMarked -package io.a2a.server.util.sse; +package org.a2aproject.sdk.server.util.sse; import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java b/server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java similarity index 95% rename from server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java rename to server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java index da667e538..2afb2d9cf 100644 --- a/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java @@ -1,12 +1,12 @@ -package io.a2a.server.version; +package org.a2aproject.sdk.server.version; import java.util.List; import java.util.stream.Collectors; -import io.a2a.server.ServerCallContext; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.VersionNotSupportedError; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.VersionNotSupportedError; /** * Utility class for validating A2A protocol version compatibility between clients and agents. diff --git a/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/AgentCardValidatorTest.java similarity index 97% rename from server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/AgentCardValidatorTest.java index 1c913ab7f..273de7f5f 100644 --- a/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/AgentCardValidatorTest.java @@ -1,4 +1,4 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -12,10 +12,10 @@ import java.util.logging.LogRecord; import java.util.logging.Logger; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.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/org/a2aproject/sdk/server/ServerCallContextTest.java similarity index 98% rename from server-common/src/test/java/io/a2a/server/ServerCallContextTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/ServerCallContextTest.java index 911b81540..d9fb1c992 100644 --- a/server-common/src/test/java/io/a2a/server/ServerCallContextTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/ServerCallContextTest.java @@ -1,4 +1,4 @@ -package io.a2a.server; +package org.a2aproject.sdk.server; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -9,7 +9,7 @@ import java.util.Map; import java.util.Set; -import io.a2a.server.auth.User; +import org.a2aproject.sdk.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/org/a2aproject/sdk/server/agentexecution/RequestContextTest.java similarity index 97% rename from server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/agentexecution/RequestContextTest.java index 98cccbd55..9e81e5202 100644 --- a/server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/agentexecution/RequestContextTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.agentexecution; +package org.a2aproject.sdk.server.agentexecution; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -14,14 +14,14 @@ import java.util.List; import java.util.UUID; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; diff --git a/server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/EnhancedRunnableTest.java similarity index 99% rename from server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/events/EnhancedRunnableTest.java index 2b1913355..951708088 100644 --- a/server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/EnhancedRunnableTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import org.junit.jupiter.api.Test; import java.util.concurrent.CompletableFuture; diff --git a/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventConsumerTest.java similarity index 96% rename from server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/events/EventConsumerTest.java index 29c3c6ce9..eee402df5 100644 --- a/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventConsumerTest.java @@ -1,6 +1,6 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; -import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; +import static org.a2aproject.sdk.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; @@ -15,20 +15,20 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -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.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.server.tasks.InMemoryTaskStore; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.A2AServerException; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueTest.java similarity index 95% rename from server-common/src/test/java/io/a2a/server/events/EventQueueTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueTest.java index e59d66d88..11fade0a2 100644 --- a/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueTest.java @@ -1,6 +1,6 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; -import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; +import static org.a2aproject.sdk.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; @@ -14,19 +14,19 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.A2AError; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.tasks.InMemoryTaskStore; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -99,9 +99,9 @@ private EventQueue createQueueWithEventBus(String taskId) { */ private void waitForEventProcessing(Runnable action) throws InterruptedException { CountDownLatch processingLatch = new CountDownLatch(1); - mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { + mainEventBusProcessor.setCallback(new org.a2aproject.sdk.server.events.MainEventBusProcessorCallback() { @Override - public void onEventProcessed(String taskId, io.a2a.spec.Event event) { + public void onEventProcessed(String taskId, org.a2aproject.sdk.spec.Event event) { processingLatch.countDown(); } diff --git a/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueUtil.java similarity index 96% rename from server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java rename to server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueUtil.java index 6c9ed4a17..8b452a018 100644 --- a/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueUtil.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import java.util.concurrent.atomic.AtomicInteger; diff --git a/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/InMemoryQueueManagerTest.java similarity index 97% rename from server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/events/InMemoryQueueManagerTest.java index 3e09ff2af..3f2be111e 100644 --- a/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/InMemoryQueueManagerTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -14,9 +14,9 @@ import java.util.concurrent.ExecutionException; import java.util.stream.IntStream; -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.MockTaskStateProvider; -import io.a2a.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.server.tasks.InMemoryTaskStore; +import org.a2aproject.sdk.server.tasks.MockTaskStateProvider; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/server-common/src/test/java/io/a2a/server/events/MainEventBusProcessorExceptionTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java similarity index 95% rename from server-common/src/test/java/io/a2a/server/events/MainEventBusProcessorExceptionTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java index 8bb212601..986958a14 100644 --- a/server-common/src/test/java/io/a2a/server/events/MainEventBusProcessorExceptionTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.events; +package org.a2aproject.sdk.server.events; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -14,16 +14,16 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.server.tasks.TaskManager; -import io.a2a.server.tasks.TaskPersistenceException; -import io.a2a.server.tasks.TaskSerializationException; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Event; -import io.a2a.spec.InternalError; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.server.tasks.TaskManager; +import org.a2aproject.sdk.server.tasks.TaskPersistenceException; +import org.a2aproject.sdk.server.tasks.TaskSerializationException; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/extensions/A2AExtensionsTest.java similarity index 95% rename from server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/extensions/A2AExtensionsTest.java index b9dec6364..26cb32b79 100644 --- a/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/extensions/A2AExtensionsTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.extensions; +package org.a2aproject.sdk.server.extensions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -9,10 +9,10 @@ import java.util.List; import java.util.Set; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentExtension; +import org.a2aproject.sdk.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/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java similarity index 84% rename from server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java index c553de317..7ee97b094 100644 --- a/server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.requesthandlers; +package org.a2aproject.sdk.server.requesthandlers; import java.io.IOException; @@ -17,35 +17,35 @@ import jakarta.enterprise.context.Dependent; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -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.tasks.AgentEmitter; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.server.tasks.BasePushNotificationSender; -import io.a2a.server.tasks.InMemoryPushNotificationConfigStore; -import io.a2a.server.tasks.InMemoryTaskStore; -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.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.server.events.EventQueueItem; +import org.a2aproject.sdk.server.events.EventQueueUtil; +import org.a2aproject.sdk.server.events.InMemoryQueueManager; +import org.a2aproject.sdk.server.events.MainEventBus; +import org.a2aproject.sdk.server.events.MainEventBusProcessor; +import org.a2aproject.sdk.server.tasks.BasePushNotificationSender; +import org.a2aproject.sdk.server.tasks.InMemoryPushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.InMemoryTaskStore; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TextPart; import io.quarkus.arc.profile.IfBuildProfile; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; diff --git a/server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandlerTest.java similarity index 94% rename from server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandlerTest.java index c03b81dfc..6101b2602 100644 --- a/server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandlerTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.requesthandlers; +package org.a2aproject.sdk.server.requesthandlers; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -13,35 +13,35 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import io.a2a.server.ServerCallContext; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.server.tasks.InMemoryPushNotificationConfigStore; -import io.a2a.server.tasks.InMemoryTaskStore; -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.Event; -import io.a2a.spec.EventKind; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -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 io.a2a.spec.UnsupportedOperationError; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.events.EventQueueItem; +import org.a2aproject.sdk.server.events.EventQueueUtil; +import org.a2aproject.sdk.server.events.InMemoryQueueManager; +import org.a2aproject.sdk.server.events.MainEventBus; +import org.a2aproject.sdk.server.events.MainEventBusProcessor; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.server.tasks.InMemoryPushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.InMemoryTaskStore; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/server-common/src/test/java/io/a2a/server/tasks/AbstractTaskStoreExceptionTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AbstractTaskStoreExceptionTest.java similarity index 99% rename from server-common/src/test/java/io/a2a/server/tasks/AbstractTaskStoreExceptionTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/AbstractTaskStoreExceptionTest.java index 9646c24bf..caec35e40 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/AbstractTaskStoreExceptionTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AbstractTaskStoreExceptionTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterConcurrencyTest.java similarity index 97% rename from server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterConcurrencyTest.java index eafcc712a..92745c465 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterConcurrencyTest.java @@ -1,8 +1,8 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.spec.UnsupportedOperationError; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.junit.jupiter.api.Test; import java.util.concurrent.CountDownLatch; diff --git a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterTest.java similarity index 95% rename from server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterTest.java index 7c85b9004..e69863286 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterTest.java @@ -1,6 +1,6 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import static io.a2a.spec.Message.Role.ROLE_AGENT; +import static org.a2aproject.sdk.spec.Message.Role.ROLE_AGENT; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -12,20 +12,20 @@ import java.util.List; import java.util.Map; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.events.EventQueueItem; +import org.a2aproject.sdk.server.events.EventQueueUtil; +import org.a2aproject.sdk.server.events.InMemoryQueueManager; +import org.a2aproject.sdk.server.events.MainEventBus; +import org.a2aproject.sdk.server.events.MainEventBusProcessor; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStoreTest.java similarity index 97% rename from server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStoreTest.java index 02cc84ae0..b407c9f33 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStoreTest.java @@ -1,7 +1,7 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import static io.a2a.client.http.A2AHttpClient.APPLICATION_JSON; -import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; +import static org.a2aproject.sdk.client.http.A2AHttpClient.APPLICATION_JSON; +import static org.a2aproject.sdk.client.http.A2AHttpClient.CONTENT_TYPE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -13,15 +13,15 @@ import java.util.List; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.common.A2AHeaders; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.common.A2AHeaders; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; diff --git a/server-common/src/test/java/io/a2a/server/tasks/InMemoryTaskStoreTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStoreTest.java similarity index 100% rename from server-common/src/test/java/io/a2a/server/tasks/InMemoryTaskStoreTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStoreTest.java diff --git a/server-common/src/test/java/io/a2a/server/tasks/MockTaskStateProvider.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/MockTaskStateProvider.java similarity index 96% rename from server-common/src/test/java/io/a2a/server/tasks/MockTaskStateProvider.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/MockTaskStateProvider.java index c14ad1628..afdca85ce 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/MockTaskStateProvider.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/MockTaskStateProvider.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import java.util.HashSet; import java.util.Set; diff --git a/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java similarity index 95% rename from server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java index 487377255..979a95a9f 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java @@ -1,7 +1,7 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import static io.a2a.client.http.A2AHttpClient.APPLICATION_JSON; -import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; +import static org.a2aproject.sdk.client.http.A2AHttpClient.APPLICATION_JSON; +import static org.a2aproject.sdk.client.http.A2AHttpClient.CONTENT_TYPE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -16,21 +16,21 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.common.A2AHeaders; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TaskPushNotificationConfig; -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.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.common.A2AHeaders; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java similarity index 96% rename from server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java index fcd3e9381..591c5d472 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -16,20 +16,20 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import io.a2a.server.events.EventConsumer; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.spec.Event; -import io.a2a.spec.EventKind; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.server.events.EventConsumer; +import org.a2aproject.sdk.server.events.EventQueue; +import org.a2aproject.sdk.server.events.EventQueueUtil; +import org.a2aproject.sdk.server.events.InMemoryQueueManager; +import org.a2aproject.sdk.server.events.MainEventBus; +import org.a2aproject.sdk.server.events.MainEventBusProcessor; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -88,7 +88,7 @@ private Task createSampleTask(String taskId, TaskState statusState, String conte */ private void waitForEventProcessing(MainEventBusProcessor processor, Runnable action) throws InterruptedException { CountDownLatch processingLatch = new CountDownLatch(1); - processor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { + processor.setCallback(new org.a2aproject.sdk.server.events.MainEventBusProcessorCallback() { @Override public void onEventProcessed(String taskId, Event event) { processingLatch.countDown(); diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerTest.java similarity index 98% rename from server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerTest.java index 0c502fd3a..74ffcf79c 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerTest.java @@ -1,6 +1,6 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; -import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; +import static org.a2aproject.sdk.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; @@ -14,15 +14,15 @@ import java.util.List; import java.util.Map; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -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.a2aproject.sdk.spec.A2AServerException; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskPersistenceExceptionTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskPersistenceExceptionTest.java similarity index 99% rename from server-common/src/test/java/io/a2a/server/tasks/TaskPersistenceExceptionTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskPersistenceExceptionTest.java index 51ad86dc3..563e421a7 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskPersistenceExceptionTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskPersistenceExceptionTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskSerializationExceptionTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskSerializationExceptionTest.java similarity index 99% rename from server-common/src/test/java/io/a2a/server/tasks/TaskSerializationExceptionTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskSerializationExceptionTest.java index df356ef14..ed2e0b984 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskSerializationExceptionTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskSerializationExceptionTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskStoreExceptionTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskStoreExceptionTest.java similarity index 99% rename from server-common/src/test/java/io/a2a/server/tasks/TaskStoreExceptionTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskStoreExceptionTest.java index 351e4332f..00a624ead 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskStoreExceptionTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskStoreExceptionTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.tasks; +package org.a2aproject.sdk.server.tasks; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/util/ArtifactUtilsTest.java similarity index 95% rename from server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/util/ArtifactUtilsTest.java index 34912efe6..723987b1d 100644 --- a/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/util/ArtifactUtilsTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.util; +package org.a2aproject.sdk.server.util; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -11,10 +11,10 @@ import java.util.Map; import java.util.UUID; -import io.a2a.spec.Artifact; -import io.a2a.spec.DataPart; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; class ArtifactUtilsTest { diff --git a/server-common/src/test/java/io/a2a/server/util/async/AsyncUtilsTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/util/async/AsyncUtilsTest.java similarity index 98% rename from server-common/src/test/java/io/a2a/server/util/async/AsyncUtilsTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/util/async/AsyncUtilsTest.java index a1ac722b9..e4efef0e7 100644 --- a/server-common/src/test/java/io/a2a/server/util/async/AsyncUtilsTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/util/async/AsyncUtilsTest.java @@ -1,9 +1,9 @@ -package io.a2a.server.util.async; +package org.a2aproject.sdk.server.util.async; -import static io.a2a.server.util.async.AsyncUtils.consumer; -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 org.a2aproject.sdk.server.util.async.AsyncUtils.consumer; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.convertingProcessor; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.createTubeConfig; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.processor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java similarity index 95% rename from server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java rename to server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java index 8156fad4c..9079a9773 100644 --- a/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java @@ -1,4 +1,4 @@ -package io.a2a.server.version; +package org.a2aproject.sdk.server.version; import static org.junit.jupiter.api.Assertions.*; @@ -6,12 +6,12 @@ import java.util.HashSet; import java.util.List; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.VersionNotSupportedError; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.VersionNotSupportedError; import org.junit.jupiter.api.Test; public class A2AVersionValidatorTest { diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentProviderMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentProviderMapper.java deleted file mode 100644 index 80766eb72..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentProviderMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.AgentProvider} and {@link io.a2a.grpc.AgentProvider}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface AgentProviderMapper { - - AgentProviderMapper INSTANCE = A2AMappers.getMapper(AgentProviderMapper.class); - - io.a2a.grpc.AgentProvider toProto(io.a2a.spec.AgentProvider domain); - - io.a2a.spec.AgentProvider fromProto(io.a2a.grpc.AgentProvider proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java deleted file mode 100644 index d59a3e10a..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.AuthorizationCodeOAuthFlow} and {@link io.a2a.grpc.AuthorizationCodeOAuthFlow}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface AuthorizationCodeOAuthFlowMapper { - - AuthorizationCodeOAuthFlowMapper INSTANCE = A2AMappers.getMapper(AuthorizationCodeOAuthFlowMapper.class); - - io.a2a.grpc.AuthorizationCodeOAuthFlow toProto(io.a2a.spec.AuthorizationCodeOAuthFlow domain); - - io.a2a.spec.AuthorizationCodeOAuthFlow fromProto(io.a2a.grpc.AuthorizationCodeOAuthFlow proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ClientCredentialsOAuthFlowMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ClientCredentialsOAuthFlowMapper.java deleted file mode 100644 index 6dabe28b6..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ClientCredentialsOAuthFlowMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.ClientCredentialsOAuthFlow} and {@link io.a2a.grpc.ClientCredentialsOAuthFlow}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface ClientCredentialsOAuthFlowMapper { - - ClientCredentialsOAuthFlowMapper INSTANCE = A2AMappers.getMapper(ClientCredentialsOAuthFlowMapper.class); - - io.a2a.grpc.ClientCredentialsOAuthFlow toProto(io.a2a.spec.ClientCredentialsOAuthFlow domain); - - io.a2a.spec.ClientCredentialsOAuthFlow fromProto(io.a2a.grpc.ClientCredentialsOAuthFlow proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java deleted file mode 100644 index dcafce7ee..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.TaskState} and {@link io.a2a.grpc.TaskState}. - *

                      - * Handles the conversion between domain TaskState enum (with string-based wire format) - * and protobuf TaskState enum (with integer-based wire format and TASK_STATE_ prefix). - *

                      - * Note: Proto uses CANCELLED spelling while domain uses CANCELED. - *

                      - * Manual Implementation Required: Uses manual switch statements instead of @ValueMapping - * to avoid mapstruct-spi-protobuf enum strategy initialization issues. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface TaskStateMapper { - - TaskStateMapper INSTANCE = A2AMappers.getMapper(TaskStateMapper.class); - - /** - * Converts domain TaskState to proto TaskState. - * - * @param domain the domain task state - * @return the proto task state, or TASK_STATE_UNSPECIFIED if input is null - */ - default io.a2a.grpc.TaskState toProto(io.a2a.spec.TaskState domain) { - if (domain == null) { - return io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED; - } - - return switch (domain) { - case TASK_STATE_SUBMITTED -> io.a2a.grpc.TaskState.TASK_STATE_SUBMITTED; - case TASK_STATE_WORKING -> io.a2a.grpc.TaskState.TASK_STATE_WORKING; - case TASK_STATE_INPUT_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_INPUT_REQUIRED; - case TASK_STATE_AUTH_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_AUTH_REQUIRED; - case TASK_STATE_COMPLETED -> io.a2a.grpc.TaskState.TASK_STATE_COMPLETED; - case TASK_STATE_CANCELED -> io.a2a.grpc.TaskState.TASK_STATE_CANCELED; - case TASK_STATE_FAILED -> io.a2a.grpc.TaskState.TASK_STATE_FAILED; - case TASK_STATE_REJECTED -> io.a2a.grpc.TaskState.TASK_STATE_REJECTED; - case UNRECOGNIZED -> io.a2a.grpc.TaskState.UNRECOGNIZED; - }; - } - - /** - * Converts proto TaskState to domain TaskState. - * - * @param proto the proto task state - * @return the domain task state, or UNKNOWN if input is null or unrecognized - */ - default io.a2a.spec.TaskState fromProto(io.a2a.grpc.TaskState proto) { - if (proto == null) { - return io.a2a.spec.TaskState.UNRECOGNIZED; - } - - return switch (proto) { - case TASK_STATE_SUBMITTED -> io.a2a.spec.TaskState.TASK_STATE_SUBMITTED; - case TASK_STATE_WORKING -> io.a2a.spec.TaskState.TASK_STATE_WORKING; - case TASK_STATE_INPUT_REQUIRED -> io.a2a.spec.TaskState.TASK_STATE_INPUT_REQUIRED; - case TASK_STATE_AUTH_REQUIRED -> io.a2a.spec.TaskState.TASK_STATE_AUTH_REQUIRED; - case TASK_STATE_COMPLETED -> io.a2a.spec.TaskState.TASK_STATE_COMPLETED; - case TASK_STATE_CANCELED -> io.a2a.spec.TaskState.TASK_STATE_CANCELED; - case TASK_STATE_FAILED -> io.a2a.spec.TaskState.TASK_STATE_FAILED; - case TASK_STATE_REJECTED -> io.a2a.spec.TaskState.TASK_STATE_REJECTED; - case TASK_STATE_UNSPECIFIED, UNRECOGNIZED -> io.a2a.spec.TaskState.UNRECOGNIZED; - }; - } -} 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 deleted file mode 100644 index e2c98f47c..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java +++ /dev/null @@ -1,340 +0,0 @@ -package io.a2a.grpc.utils; - -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; -import io.a2a.grpc.mapper.ListTaskPushNotificationConfigsParamsMapper; -import io.a2a.grpc.mapper.ListTasksParamsMapper; -import io.a2a.grpc.mapper.ListTasksResultMapper; -import io.a2a.grpc.mapper.MessageMapper; -import io.a2a.grpc.mapper.MessageSendConfigurationMapper; -import io.a2a.grpc.mapper.MessageSendParamsMapper; -import io.a2a.grpc.mapper.StreamResponseMapper; -import io.a2a.grpc.mapper.TaskArtifactUpdateEventMapper; -import io.a2a.grpc.mapper.TaskIdParamsMapper; -import io.a2a.grpc.mapper.TaskMapper; -import io.a2a.grpc.mapper.TaskPushNotificationConfigMapper; -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.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetExtendedAgentCardParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; - -/** - * Utility class to convert between GRPC and Spec objects. - */ -public class ProtoUtils { - - public static class ToProto { - - public static io.a2a.grpc.AgentCard agentCard(AgentCard agentCard) { - return AgentCardMapper.INSTANCE.toProto(agentCard); - } - - public static io.a2a.grpc.GetExtendedAgentCardRequest extendedAgentCard(GetExtendedAgentCardParams params) { - GetExtendedAgentCardRequest.Builder builder = GetExtendedAgentCardRequest.newBuilder(); - if (params.tenant() != null) { - builder.setTenant(params.tenant()); - } - return builder.build(); - } - - public static io.a2a.grpc.GetTaskRequest getTaskRequest(TaskQueryParams params) { - return TaskQueryParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.CancelTaskRequest cancelTaskRequest(CancelTaskParams params) { - return TaskIdParamsMapper.INSTANCE.toProtoCancelTaskRequest(params); - } - - public static io.a2a.grpc.SubscribeToTaskRequest subscribeToTaskRequest(TaskIdParams params) { - return TaskIdParamsMapper.INSTANCE.toProtoSubscribeToTaskRequest(params); - } - - public static io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfigRequest(TaskPushNotificationConfig config) { - return TaskPushNotificationConfigMapper.INSTANCE.toProto(config); - } - - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest getTaskPushNotificationConfigRequest(GetTaskPushNotificationConfigParams params) { - return GetTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest deleteTaskPushNotificationConfigRequest(DeleteTaskPushNotificationConfigParams params) { - return DeleteTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest listTaskPushNotificationConfigsRequest(ListTaskPushNotificationConfigsParams params) { - return ListTaskPushNotificationConfigsParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.Task task(Task task) { - return TaskMapper.INSTANCE.toProto(task); - } - - public static io.a2a.grpc.ListTasksResponse listTasksResult(ListTasksResult result) { - return ListTasksResultMapper.INSTANCE.toProto(result); - } - - public static io.a2a.grpc.ListTasksRequest listTasksParams(ListTasksParams params) { - return ListTasksParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.Message message(Message message) { - return MessageMapper.INSTANCE.toProto(message); - } - - public static io.a2a.grpc.TaskPushNotificationConfig taskPushNotificationConfig(TaskPushNotificationConfig config) { - return TaskPushNotificationConfigMapper.INSTANCE.toProto(config); - } - - public static io.a2a.grpc.TaskArtifactUpdateEvent taskArtifactUpdateEvent(TaskArtifactUpdateEvent event) { - return TaskArtifactUpdateEventMapper.INSTANCE.toProto(event); - } - - public static io.a2a.grpc.TaskStatusUpdateEvent taskStatusUpdateEvent(TaskStatusUpdateEvent event) { - return TaskStatusUpdateEventMapper.INSTANCE.toProto(event); - } - - public static io.a2a.grpc.TaskState taskState(TaskState taskState) { - return TaskStateMapper.INSTANCE.toProto(taskState); - } - - public static io.a2a.grpc.SendMessageConfiguration messageSendConfiguration(MessageSendConfiguration messageSendConfiguration) { - return MessageSendConfigurationMapper.INSTANCE.toProto(messageSendConfiguration); - } - - public static io.a2a.grpc.SendMessageRequest sendMessageRequest(MessageSendParams request) { - return MessageSendParamsMapper.INSTANCE.toProto(request); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigsResponse(ListTaskPushNotificationConfigsResult result) { - List confs = new ArrayList<>(result.configs().size()); - for (TaskPushNotificationConfig config : result.configs()) { - confs.add(taskPushNotificationConfig(config)); - } - io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder().addAllConfigs(confs); - if (result.nextPageToken() != null) { - builder.setNextPageToken(result.nextPageToken()); - } - return builder.build(); - } - - public static StreamResponse streamResponse(StreamingEventKind streamingEventKind) { - return StreamResponseMapper.INSTANCE.toProto(streamingEventKind); - } - - public static io.a2a.grpc.SendMessageResponse taskOrMessage(EventKind eventKind) { - return switch (eventKind.kind()) { - case Task.STREAMING_EVENT_ID -> io.a2a.grpc.SendMessageResponse.newBuilder() - .setTask(task((Task) eventKind)) - .build(); - case Message.STREAMING_EVENT_ID -> io.a2a.grpc.SendMessageResponse.newBuilder() - .setMessage(message((Message) eventKind)) - .build(); - default -> throw new IllegalArgumentException("Unsupported event type: " + eventKind); - }; - } - - public static io.a2a.grpc.StreamResponse taskOrMessageStream(StreamingEventKind eventKind) { - return switch (eventKind.kind()) { - case Task.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setTask(task((Task) eventKind)) - .build(); - case Message.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setMessage(message((Message) eventKind)) - .build(); - case TaskStatusUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setStatusUpdate(taskStatusUpdateEvent((TaskStatusUpdateEvent) eventKind)) - .build(); - case TaskArtifactUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setArtifactUpdate(taskArtifactUpdateEvent((TaskArtifactUpdateEvent) eventKind)) - .build(); - default -> throw new IllegalArgumentException("Unsupported event type: " + eventKind); - }; - } - - public static io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfigResponse(TaskPushNotificationConfig config) { - return taskPushNotificationConfig(config); - } - - public static io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfigResponse(TaskPushNotificationConfig config) { - return taskPushNotificationConfig(config); - } - - public static io.a2a.grpc.AgentCard getExtendedCardResponse(AgentCard card) { - return agentCard(card); - } - } - - public static class FromProto { - - private static T convert(java.util.function.Supplier s) { - try { - return s.get(); - } catch (IllegalArgumentException ex) { - throw new InvalidParamsError(ex.getMessage()); - } - } - - public static AgentCard agentCard(io.a2a.grpc.AgentCardOrBuilder agentCard) { - io.a2a.grpc.AgentCard agentCardProto = agentCard instanceof io.a2a.grpc.AgentCard - ? (io.a2a.grpc.AgentCard) agentCard - : ((io.a2a.grpc.AgentCard.Builder) agentCard).build(); - return convert(() -> AgentCardMapper.INSTANCE.fromProto(agentCardProto)); - } - - public static TaskQueryParams taskQueryParams(io.a2a.grpc.GetTaskRequestOrBuilder request) { - io.a2a.grpc.GetTaskRequest reqProto = request instanceof io.a2a.grpc.GetTaskRequest - ? (io.a2a.grpc.GetTaskRequest) request - : ((io.a2a.grpc.GetTaskRequest.Builder) request).build(); - return convert(() -> TaskQueryParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static ListTasksParams listTasksParams(io.a2a.grpc.ListTasksRequestOrBuilder request) { - io.a2a.grpc.ListTasksRequest reqProto = request instanceof io.a2a.grpc.ListTasksRequest - ? (io.a2a.grpc.ListTasksRequest) request - : ((io.a2a.grpc.ListTasksRequest.Builder) request).build(); - return convert(() -> ListTasksParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static CancelTaskParams cancelTaskParams(io.a2a.grpc.CancelTaskRequestOrBuilder request) { - io.a2a.grpc.CancelTaskRequest reqProto = request instanceof io.a2a.grpc.CancelTaskRequest - ? (io.a2a.grpc.CancelTaskRequest) request - : ((io.a2a.grpc.CancelTaskRequest.Builder) request).build(); - return convert(() -> TaskIdParamsMapper.INSTANCE.fromProtoCancelTaskRequest(reqProto)); - } - - public static MessageSendParams messageSendParams(io.a2a.grpc.SendMessageRequestOrBuilder request) { - io.a2a.grpc.SendMessageRequest requestProto = request instanceof io.a2a.grpc.SendMessageRequest - ? (io.a2a.grpc.SendMessageRequest) request - : ((io.a2a.grpc.SendMessageRequest.Builder) request).build(); - return convert(() -> MessageSendParamsMapper.INSTANCE.fromProto(requestProto)); - } - - public static TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfigOrBuilder config) { - io.a2a.grpc.TaskPushNotificationConfig proto = config instanceof io.a2a.grpc.TaskPushNotificationConfig - ? (io.a2a.grpc.TaskPushNotificationConfig) config - : ((io.a2a.grpc.TaskPushNotificationConfig.Builder) config).build(); - return convert(() -> TaskPushNotificationConfigMapper.INSTANCE.fromProto(proto)); - } - - public static TaskPushNotificationConfig taskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfigOrBuilder config) { - io.a2a.grpc.TaskPushNotificationConfig proto = config instanceof io.a2a.grpc.TaskPushNotificationConfig - ? (io.a2a.grpc.TaskPushNotificationConfig) config - : ((io.a2a.grpc.TaskPushNotificationConfig.Builder) config).build(); - return convert(() -> TaskPushNotificationConfigMapper.INSTANCE.fromProto(proto)); - } - - public static GetTaskPushNotificationConfigParams getTaskPushNotificationConfigParams(io.a2a.grpc.GetTaskPushNotificationConfigRequestOrBuilder request) { - io.a2a.grpc.GetTaskPushNotificationConfigRequest reqProto = request instanceof io.a2a.grpc.GetTaskPushNotificationConfigRequest - ? (io.a2a.grpc.GetTaskPushNotificationConfigRequest) request - : ((io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder) request).build(); - return convert(() -> GetTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static TaskIdParams taskIdParams(io.a2a.grpc.SubscribeToTaskRequestOrBuilder request) { - io.a2a.grpc.SubscribeToTaskRequest reqProto = request instanceof io.a2a.grpc.SubscribeToTaskRequest - ? (io.a2a.grpc.SubscribeToTaskRequest) request - : ((io.a2a.grpc.SubscribeToTaskRequest.Builder) request).build(); - return convert(() -> TaskIdParamsMapper.INSTANCE.fromProtoSubscribeToTaskRequest(reqProto)); - } - - public static ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigsResult(io.a2a.grpc.ListTaskPushNotificationConfigsResponseOrBuilder response) { - List configs = response.getConfigsList(); - List result = new ArrayList<>(configs.size()); - for (io.a2a.grpc.TaskPushNotificationConfig config : configs) { - result.add(taskPushNotificationConfig(config)); - } - String nextPageToken = response.getNextPageToken(); - if (nextPageToken != null && nextPageToken.isEmpty()) { - nextPageToken = null; - } - return new ListTaskPushNotificationConfigsResult(result, nextPageToken); - } - - public static ListTaskPushNotificationConfigsParams listTaskPushNotificationConfigsParams(io.a2a.grpc.ListTaskPushNotificationConfigsRequestOrBuilder request) { - io.a2a.grpc.ListTaskPushNotificationConfigsRequest reqProto = request instanceof io.a2a.grpc.ListTaskPushNotificationConfigsRequest - ? (io.a2a.grpc.ListTaskPushNotificationConfigsRequest) request - : ((io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder) request).build(); - return convert(() -> ListTaskPushNotificationConfigsParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static DeleteTaskPushNotificationConfigParams deleteTaskPushNotificationConfigParams(io.a2a.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder request) { - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest reqProto = request instanceof io.a2a.grpc.DeleteTaskPushNotificationConfigRequest - ? (io.a2a.grpc.DeleteTaskPushNotificationConfigRequest) request - : ((io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder) request).build(); - return convert(() -> DeleteTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static Task task(io.a2a.grpc.TaskOrBuilder task) { - io.a2a.grpc.Task taskProto = task instanceof io.a2a.grpc.Task - ? (io.a2a.grpc.Task) task - : ((io.a2a.grpc.Task.Builder) task).build(); - return convert(() -> TaskMapper.INSTANCE.fromProto(taskProto)); - } - - public static Message message(io.a2a.grpc.MessageOrBuilder message) { - if (message.getMessageId().isEmpty()) { - throw new InvalidParamsError(); - } - io.a2a.grpc.Message messageProto = message instanceof io.a2a.grpc.Message - ? (io.a2a.grpc.Message) message - : ((io.a2a.grpc.Message.Builder) message).build(); - return convert(() -> MessageMapper.INSTANCE.fromProto(messageProto)); - } - - public static TaskStatusUpdateEvent taskStatusUpdateEvent(io.a2a.grpc.TaskStatusUpdateEventOrBuilder taskStatusUpdateEvent) { - io.a2a.grpc.TaskStatusUpdateEvent eventProto = taskStatusUpdateEvent instanceof io.a2a.grpc.TaskStatusUpdateEvent - ? (io.a2a.grpc.TaskStatusUpdateEvent) taskStatusUpdateEvent - : ((io.a2a.grpc.TaskStatusUpdateEvent.Builder) taskStatusUpdateEvent).build(); - return convert(() -> TaskStatusUpdateEventMapper.INSTANCE.fromProto(eventProto)); - } - - public static TaskArtifactUpdateEvent taskArtifactUpdateEvent(io.a2a.grpc.TaskArtifactUpdateEventOrBuilder taskArtifactUpdateEvent) { - io.a2a.grpc.TaskArtifactUpdateEvent eventProto = taskArtifactUpdateEvent instanceof io.a2a.grpc.TaskArtifactUpdateEvent - ? (io.a2a.grpc.TaskArtifactUpdateEvent) taskArtifactUpdateEvent - : ((io.a2a.grpc.TaskArtifactUpdateEvent.Builder) taskArtifactUpdateEvent).build(); - return convert(() -> TaskArtifactUpdateEventMapper.INSTANCE.fromProto(eventProto)); - } - - public static ListTasksResult listTasksResult(io.a2a.grpc.ListTasksResponseOrBuilder listTasksResponse) { - io.a2a.grpc.ListTasksResponse eventProto = listTasksResponse instanceof io.a2a.grpc.ListTasksResponse - ? (io.a2a.grpc.ListTasksResponse) listTasksResponse - : ((io.a2a.grpc.ListTasksResponse.Builder) listTasksResponse).build(); - return convert(() -> ListTasksResultMapper.INSTANCE.fromProto(eventProto)); - } - - public static StreamingEventKind streamingEventKind(io.a2a.grpc.StreamResponseOrBuilder streamResponse) { - io.a2a.grpc.StreamResponse streamResponseProto = streamResponse instanceof io.a2a.grpc.StreamResponse - ? (io.a2a.grpc.StreamResponse) streamResponse - : ((io.a2a.grpc.StreamResponse.Builder) streamResponse).build(); - return convert(() -> StreamResponseMapper.INSTANCE.fromProto(streamResponseProto)); - } - } - -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/utils/package-info.java b/spec-grpc/src/main/java/io/a2a/grpc/utils/package-info.java deleted file mode 100644 index 526496e36..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/utils/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.grpc.utils; - -import org.jspecify.annotations.NullMarked; - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/A2A.java similarity index 99% rename from spec-grpc/src/main/java/io/a2a/grpc/A2A.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/A2A.java index 24a14b35c..58ef82c68 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/A2A.java @@ -3,7 +3,7 @@ // source: a2a.proto // Protobuf Java Version: 4.33.1 -package io.a2a.grpc; +package org.a2aproject.sdk.grpc; @com.google.protobuf.Generated public final class A2A extends com.google.protobuf.GeneratedFile { @@ -535,8 +535,9 @@ public static void registerAllExtensions( "d\202\323\344\223\002q*1/tasks/{task_id=*}/pushNotifica" + "tionConfigs/{id=*}Z<*:/{tenant}/tasks/{t" + "ask_id=*}/pushNotificationConfigs/{id=*}" + - "B=\n\013io.a2a.grpcB\003A2AP\001Z\033google.golang.or" + - "g/lf/a2a/v1\252\002\tLf.A2a.V1b\006proto3" + "BI\n\027org.a2aproject.sdk.grpcB\003A2AP\001Z\033goog" + + "le.golang.org/lf/a2a/v1\252\002\tLf.A2a.V1b\006pro" + + "to3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/A2AServiceGrpc.java similarity index 64% rename from spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/A2AServiceGrpc.java index c4527614a..a026b749e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/A2AServiceGrpc.java @@ -1,4 +1,4 @@ -package io.a2a.grpc; +package org.a2aproject.sdk.grpc; import static io.grpc.MethodDescriptor.generateFullMethodName; @@ -15,29 +15,29 @@ private A2AServiceGrpc() {} public static final java.lang.String SERVICE_NAME = "lf.a2a.v1.A2AService"; // Static method descriptors that strictly reflect the proto. - private static volatile io.grpc.MethodDescriptor getSendMessageMethod; + private static volatile io.grpc.MethodDescriptor getSendMessageMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "SendMessage", - requestType = io.a2a.grpc.SendMessageRequest.class, - responseType = io.a2a.grpc.SendMessageResponse.class, + requestType = org.a2aproject.sdk.grpc.SendMessageRequest.class, + responseType = org.a2aproject.sdk.grpc.SendMessageResponse.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getSendMessageMethod() { - io.grpc.MethodDescriptor getSendMessageMethod; + public static io.grpc.MethodDescriptor getSendMessageMethod() { + io.grpc.MethodDescriptor getSendMessageMethod; if ((getSendMessageMethod = A2AServiceGrpc.getSendMessageMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getSendMessageMethod = A2AServiceGrpc.getSendMessageMethod) == null) { A2AServiceGrpc.getSendMessageMethod = getSendMessageMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SendMessage")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SendMessageRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.SendMessageRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SendMessageResponse.getDefaultInstance())) + org.a2aproject.sdk.grpc.SendMessageResponse.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SendMessage")) .build(); } @@ -46,29 +46,29 @@ io.a2a.grpc.SendMessageResponse> getSendMessageMethod() { return getSendMessageMethod; } - private static volatile io.grpc.MethodDescriptor getSendStreamingMessageMethod; + private static volatile io.grpc.MethodDescriptor getSendStreamingMessageMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "SendStreamingMessage", - requestType = io.a2a.grpc.SendMessageRequest.class, - responseType = io.a2a.grpc.StreamResponse.class, + requestType = org.a2aproject.sdk.grpc.SendMessageRequest.class, + responseType = org.a2aproject.sdk.grpc.StreamResponse.class, methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) - public static io.grpc.MethodDescriptor getSendStreamingMessageMethod() { - io.grpc.MethodDescriptor getSendStreamingMessageMethod; + public static io.grpc.MethodDescriptor getSendStreamingMessageMethod() { + io.grpc.MethodDescriptor getSendStreamingMessageMethod; if ((getSendStreamingMessageMethod = A2AServiceGrpc.getSendStreamingMessageMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getSendStreamingMessageMethod = A2AServiceGrpc.getSendStreamingMessageMethod) == null) { A2AServiceGrpc.getSendStreamingMessageMethod = getSendStreamingMessageMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SendStreamingMessage")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SendMessageRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.SendMessageRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.StreamResponse.getDefaultInstance())) + org.a2aproject.sdk.grpc.StreamResponse.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SendStreamingMessage")) .build(); } @@ -77,29 +77,29 @@ io.a2a.grpc.StreamResponse> getSendStreamingMessageMethod() { return getSendStreamingMessageMethod; } - private static volatile io.grpc.MethodDescriptor getGetTaskMethod; + private static volatile io.grpc.MethodDescriptor getGetTaskMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "GetTask", - requestType = io.a2a.grpc.GetTaskRequest.class, - responseType = io.a2a.grpc.Task.class, + requestType = org.a2aproject.sdk.grpc.GetTaskRequest.class, + responseType = org.a2aproject.sdk.grpc.Task.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getGetTaskMethod() { - io.grpc.MethodDescriptor getGetTaskMethod; + public static io.grpc.MethodDescriptor getGetTaskMethod() { + io.grpc.MethodDescriptor getGetTaskMethod; if ((getGetTaskMethod = A2AServiceGrpc.getGetTaskMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getGetTaskMethod = A2AServiceGrpc.getGetTaskMethod) == null) { A2AServiceGrpc.getGetTaskMethod = getGetTaskMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetTask")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.GetTaskRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.GetTaskRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.Task.getDefaultInstance())) + org.a2aproject.sdk.grpc.Task.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetTask")) .build(); } @@ -108,29 +108,29 @@ io.a2a.grpc.Task> getGetTaskMethod() { return getGetTaskMethod; } - private static volatile io.grpc.MethodDescriptor getListTasksMethod; + private static volatile io.grpc.MethodDescriptor getListTasksMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "ListTasks", - requestType = io.a2a.grpc.ListTasksRequest.class, - responseType = io.a2a.grpc.ListTasksResponse.class, + requestType = org.a2aproject.sdk.grpc.ListTasksRequest.class, + responseType = org.a2aproject.sdk.grpc.ListTasksResponse.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getListTasksMethod() { - io.grpc.MethodDescriptor getListTasksMethod; + public static io.grpc.MethodDescriptor getListTasksMethod() { + io.grpc.MethodDescriptor getListTasksMethod; if ((getListTasksMethod = A2AServiceGrpc.getListTasksMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getListTasksMethod = A2AServiceGrpc.getListTasksMethod) == null) { A2AServiceGrpc.getListTasksMethod = getListTasksMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListTasks")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTasksRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.ListTasksRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTasksResponse.getDefaultInstance())) + org.a2aproject.sdk.grpc.ListTasksResponse.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("ListTasks")) .build(); } @@ -139,29 +139,29 @@ io.a2a.grpc.ListTasksResponse> getListTasksMethod() { return getListTasksMethod; } - private static volatile io.grpc.MethodDescriptor getCancelTaskMethod; + private static volatile io.grpc.MethodDescriptor getCancelTaskMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "CancelTask", - requestType = io.a2a.grpc.CancelTaskRequest.class, - responseType = io.a2a.grpc.Task.class, + requestType = org.a2aproject.sdk.grpc.CancelTaskRequest.class, + responseType = org.a2aproject.sdk.grpc.Task.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getCancelTaskMethod() { - io.grpc.MethodDescriptor getCancelTaskMethod; + public static io.grpc.MethodDescriptor getCancelTaskMethod() { + io.grpc.MethodDescriptor getCancelTaskMethod; if ((getCancelTaskMethod = A2AServiceGrpc.getCancelTaskMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getCancelTaskMethod = A2AServiceGrpc.getCancelTaskMethod) == null) { A2AServiceGrpc.getCancelTaskMethod = getCancelTaskMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "CancelTask")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.CancelTaskRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.CancelTaskRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.Task.getDefaultInstance())) + org.a2aproject.sdk.grpc.Task.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("CancelTask")) .build(); } @@ -170,29 +170,29 @@ io.a2a.grpc.Task> getCancelTaskMethod() { return getCancelTaskMethod; } - private static volatile io.grpc.MethodDescriptor getSubscribeToTaskMethod; + private static volatile io.grpc.MethodDescriptor getSubscribeToTaskMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "SubscribeToTask", - requestType = io.a2a.grpc.SubscribeToTaskRequest.class, - responseType = io.a2a.grpc.StreamResponse.class, + requestType = org.a2aproject.sdk.grpc.SubscribeToTaskRequest.class, + responseType = org.a2aproject.sdk.grpc.StreamResponse.class, methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) - public static io.grpc.MethodDescriptor getSubscribeToTaskMethod() { - io.grpc.MethodDescriptor getSubscribeToTaskMethod; + public static io.grpc.MethodDescriptor getSubscribeToTaskMethod() { + io.grpc.MethodDescriptor getSubscribeToTaskMethod; if ((getSubscribeToTaskMethod = A2AServiceGrpc.getSubscribeToTaskMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getSubscribeToTaskMethod = A2AServiceGrpc.getSubscribeToTaskMethod) == null) { A2AServiceGrpc.getSubscribeToTaskMethod = getSubscribeToTaskMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SubscribeToTask")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SubscribeToTaskRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.SubscribeToTaskRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.StreamResponse.getDefaultInstance())) + org.a2aproject.sdk.grpc.StreamResponse.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SubscribeToTask")) .build(); } @@ -201,29 +201,29 @@ io.a2a.grpc.StreamResponse> getSubscribeToTaskMethod() { return getSubscribeToTaskMethod; } - private static volatile io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; + private static volatile io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "CreateTaskPushNotificationConfig", - requestType = io.a2a.grpc.TaskPushNotificationConfig.class, - responseType = io.a2a.grpc.TaskPushNotificationConfig.class, + requestType = org.a2aproject.sdk.grpc.TaskPushNotificationConfig.class, + responseType = org.a2aproject.sdk.grpc.TaskPushNotificationConfig.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; + public static io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod() { + io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod = getCreateTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "CreateTaskPushNotificationConfig")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance())) + org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance())) + org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("CreateTaskPushNotificationConfig")) .build(); } @@ -232,29 +232,29 @@ io.a2a.grpc.TaskPushNotificationConfig> getCreateTaskPushNotificationConfigMetho return getCreateTaskPushNotificationConfigMethod; } - private static volatile io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod; + private static volatile io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "GetTaskPushNotificationConfig", - requestType = io.a2a.grpc.GetTaskPushNotificationConfigRequest.class, - responseType = io.a2a.grpc.TaskPushNotificationConfig.class, + requestType = org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.class, + responseType = org.a2aproject.sdk.grpc.TaskPushNotificationConfig.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod; + public static io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod() { + io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod; if ((getGetTaskPushNotificationConfigMethod = A2AServiceGrpc.getGetTaskPushNotificationConfigMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getGetTaskPushNotificationConfigMethod = A2AServiceGrpc.getGetTaskPushNotificationConfigMethod) == null) { A2AServiceGrpc.getGetTaskPushNotificationConfigMethod = getGetTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetTaskPushNotificationConfig")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance())) + org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetTaskPushNotificationConfig")) .build(); } @@ -263,29 +263,29 @@ io.a2a.grpc.TaskPushNotificationConfig> getGetTaskPushNotificationConfigMethod() return getGetTaskPushNotificationConfigMethod; } - private static volatile io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod; + private static volatile io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "ListTaskPushNotificationConfigs", - requestType = io.a2a.grpc.ListTaskPushNotificationConfigsRequest.class, - responseType = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.class, + requestType = org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.class, + responseType = org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod() { - io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod; + public static io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod() { + io.grpc.MethodDescriptor getListTaskPushNotificationConfigsMethod; if ((getListTaskPushNotificationConfigsMethod = A2AServiceGrpc.getListTaskPushNotificationConfigsMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getListTaskPushNotificationConfigsMethod = A2AServiceGrpc.getListTaskPushNotificationConfigsMethod) == null) { A2AServiceGrpc.getListTaskPushNotificationConfigsMethod = getListTaskPushNotificationConfigsMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListTaskPushNotificationConfigs")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance())) + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("ListTaskPushNotificationConfigs")) .build(); } @@ -294,29 +294,29 @@ io.a2a.grpc.ListTaskPushNotificationConfigsResponse> getListTaskPushNotification return getListTaskPushNotificationConfigsMethod; } - private static volatile io.grpc.MethodDescriptor getGetExtendedAgentCardMethod; + private static volatile io.grpc.MethodDescriptor getGetExtendedAgentCardMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "GetExtendedAgentCard", - requestType = io.a2a.grpc.GetExtendedAgentCardRequest.class, - responseType = io.a2a.grpc.AgentCard.class, + requestType = org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.class, + responseType = org.a2aproject.sdk.grpc.AgentCard.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getGetExtendedAgentCardMethod() { - io.grpc.MethodDescriptor getGetExtendedAgentCardMethod; + public static io.grpc.MethodDescriptor getGetExtendedAgentCardMethod() { + io.grpc.MethodDescriptor getGetExtendedAgentCardMethod; if ((getGetExtendedAgentCardMethod = A2AServiceGrpc.getGetExtendedAgentCardMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getGetExtendedAgentCardMethod = A2AServiceGrpc.getGetExtendedAgentCardMethod) == null) { A2AServiceGrpc.getGetExtendedAgentCardMethod = getGetExtendedAgentCardMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetExtendedAgentCard")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.GetExtendedAgentCardRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.AgentCard.getDefaultInstance())) + org.a2aproject.sdk.grpc.AgentCard.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetExtendedAgentCard")) .build(); } @@ -325,27 +325,27 @@ io.a2a.grpc.AgentCard> getGetExtendedAgentCardMethod() { return getGetExtendedAgentCardMethod; } - private static volatile io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "DeleteTaskPushNotificationConfig", - requestType = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.class, + requestType = org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.class, responseType = com.google.protobuf.Empty.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod; + io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod; if ((getDeleteTaskPushNotificationConfigMethod = A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod) == null) { synchronized (A2AServiceGrpc.class) { if ((getDeleteTaskPushNotificationConfigMethod = A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod) == null) { A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod = getDeleteTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() + io.grpc.MethodDescriptor.newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName(SERVICE_NAME, "DeleteTaskPushNotificationConfig")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance())) + org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( com.google.protobuf.Empty.getDefaultInstance())) .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("DeleteTaskPushNotificationConfig")) @@ -427,8 +427,8 @@ public interface AsyncService { * Sends a message to an agent. * */ - default void sendMessage(io.a2a.grpc.SendMessageRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void sendMessage(org.a2aproject.sdk.grpc.SendMessageRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSendMessageMethod(), responseObserver); } @@ -438,8 +438,8 @@ default void sendMessage(io.a2a.grpc.SendMessageRequest request, * Streaming version of `SendMessage` * */ - default void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void sendStreamingMessage(org.a2aproject.sdk.grpc.SendMessageRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSendStreamingMessageMethod(), responseObserver); } @@ -448,8 +448,8 @@ default void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, * Gets the latest state of a task. * */ - default void getTask(io.a2a.grpc.GetTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void getTask(org.a2aproject.sdk.grpc.GetTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetTaskMethod(), responseObserver); } @@ -458,8 +458,8 @@ default void getTask(io.a2a.grpc.GetTaskRequest request, * Lists tasks that match the specified filter. * */ - default void listTasks(io.a2a.grpc.ListTasksRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void listTasks(org.a2aproject.sdk.grpc.ListTasksRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListTasksMethod(), responseObserver); } @@ -468,8 +468,8 @@ default void listTasks(io.a2a.grpc.ListTasksRequest request, * Cancels a task in progress. * */ - default void cancelTask(io.a2a.grpc.CancelTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void cancelTask(org.a2aproject.sdk.grpc.CancelTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCancelTaskMethod(), responseObserver); } @@ -479,8 +479,8 @@ default void cancelTask(io.a2a.grpc.CancelTaskRequest request, * Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected). * */ - default void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void subscribeToTask(org.a2aproject.sdk.grpc.SubscribeToTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSubscribeToTaskMethod(), responseObserver); } @@ -493,8 +493,8 @@ default void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, * Creates a push notification config for a task. * */ - default void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request, - io.grpc.stub.StreamObserver responseObserver) { + default void createTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfig request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCreateTaskPushNotificationConfigMethod(), responseObserver); } @@ -503,8 +503,8 @@ default void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationCo * Gets a push notification config for a task. * */ - default void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void getTaskPushNotificationConfig(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetTaskPushNotificationConfigMethod(), responseObserver); } @@ -513,8 +513,8 @@ default void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationCo * Get a list of push notifications configured for a task. * */ - default void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void listTaskPushNotificationConfigs(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListTaskPushNotificationConfigsMethod(), responseObserver); } @@ -523,8 +523,8 @@ default void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificatio * Gets the extended agent card for the authenticated agent. * */ - default void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, - io.grpc.stub.StreamObserver responseObserver) { + default void getExtendedAgentCard(org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetExtendedAgentCardMethod(), responseObserver); } @@ -533,7 +533,7 @@ default void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest reques * Deletes a push notification config for a task. * */ - default void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request, + default void deleteTaskPushNotificationConfig(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getDeleteTaskPushNotificationConfigMethod(), responseObserver); } @@ -577,8 +577,8 @@ protected A2AServiceStub build( * Sends a message to an agent. * */ - public void sendMessage(io.a2a.grpc.SendMessageRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void sendMessage(org.a2aproject.sdk.grpc.SendMessageRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getSendMessageMethod(), getCallOptions()), request, responseObserver); } @@ -589,8 +589,8 @@ public void sendMessage(io.a2a.grpc.SendMessageRequest request, * Streaming version of `SendMessage` * */ - public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void sendStreamingMessage(org.a2aproject.sdk.grpc.SendMessageRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncServerStreamingCall( getChannel().newCall(getSendStreamingMessageMethod(), getCallOptions()), request, responseObserver); } @@ -600,8 +600,8 @@ public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, * Gets the latest state of a task. * */ - public void getTask(io.a2a.grpc.GetTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void getTask(org.a2aproject.sdk.grpc.GetTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getGetTaskMethod(), getCallOptions()), request, responseObserver); } @@ -611,8 +611,8 @@ public void getTask(io.a2a.grpc.GetTaskRequest request, * Lists tasks that match the specified filter. * */ - public void listTasks(io.a2a.grpc.ListTasksRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void listTasks(org.a2aproject.sdk.grpc.ListTasksRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getListTasksMethod(), getCallOptions()), request, responseObserver); } @@ -622,8 +622,8 @@ public void listTasks(io.a2a.grpc.ListTasksRequest request, * Cancels a task in progress. * */ - public void cancelTask(io.a2a.grpc.CancelTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void cancelTask(org.a2aproject.sdk.grpc.CancelTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getCancelTaskMethod(), getCallOptions()), request, responseObserver); } @@ -634,8 +634,8 @@ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, * Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected). * */ - public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void subscribeToTask(org.a2aproject.sdk.grpc.SubscribeToTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncServerStreamingCall( getChannel().newCall(getSubscribeToTaskMethod(), getCallOptions()), request, responseObserver); } @@ -649,8 +649,8 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, * Creates a push notification config for a task. * */ - public void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request, - io.grpc.stub.StreamObserver responseObserver) { + public void createTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfig request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); } @@ -660,8 +660,8 @@ public void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationCon * Gets a push notification config for a task. * */ - public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void getTaskPushNotificationConfig(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getGetTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); } @@ -671,8 +671,8 @@ public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationCon * Get a list of push notifications configured for a task. * */ - public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void listTaskPushNotificationConfigs(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getListTaskPushNotificationConfigsMethod(), getCallOptions()), request, responseObserver); } @@ -682,8 +682,8 @@ public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotification * Gets the extended agent card for the authenticated agent. * */ - public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, - io.grpc.stub.StreamObserver responseObserver) { + public void getExtendedAgentCard(org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest request, + io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getGetExtendedAgentCardMethod(), getCallOptions()), request, responseObserver); } @@ -693,7 +693,7 @@ public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request * Deletes a push notification config for a task. * */ - public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request, + public void deleteTaskPushNotificationConfig(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getDeleteTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); @@ -724,7 +724,7 @@ protected A2AServiceBlockingV2Stub build( * Sends a message to an agent. * */ - public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageRequest request) throws io.grpc.StatusException { + public org.a2aproject.sdk.grpc.SendMessageResponse sendMessage(org.a2aproject.sdk.grpc.SendMessageRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getSendMessageMethod(), getCallOptions(), request); } @@ -736,8 +736,8 @@ public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageReques * */ @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") - public io.grpc.stub.BlockingClientCall - sendStreamingMessage(io.a2a.grpc.SendMessageRequest request) { + public io.grpc.stub.BlockingClientCall + sendStreamingMessage(org.a2aproject.sdk.grpc.SendMessageRequest request) { return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( getChannel(), getSendStreamingMessageMethod(), getCallOptions(), request); } @@ -747,7 +747,7 @@ public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageReques * Gets the latest state of a task. * */ - public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) throws io.grpc.StatusException { + public org.a2aproject.sdk.grpc.Task getTask(org.a2aproject.sdk.grpc.GetTaskRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getGetTaskMethod(), getCallOptions(), request); } @@ -757,7 +757,7 @@ public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) throws io.gr * Lists tasks that match the specified filter. * */ - public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest request) throws io.grpc.StatusException { + public org.a2aproject.sdk.grpc.ListTasksResponse listTasks(org.a2aproject.sdk.grpc.ListTasksRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getListTasksMethod(), getCallOptions(), request); } @@ -767,7 +767,7 @@ public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest requ * Cancels a task in progress. * */ - public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws io.grpc.StatusException { + public org.a2aproject.sdk.grpc.Task cancelTask(org.a2aproject.sdk.grpc.CancelTaskRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getCancelTaskMethod(), getCallOptions(), request); } @@ -779,8 +779,8 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws * */ @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") - public io.grpc.stub.BlockingClientCall - subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request) { + public io.grpc.stub.BlockingClientCall + subscribeToTask(org.a2aproject.sdk.grpc.SubscribeToTaskRequest request) { return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( getChannel(), getSubscribeToTaskMethod(), getCallOptions(), request); } @@ -794,7 +794,7 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws * Creates a push notification config for a task. * */ - public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request) throws io.grpc.StatusException { + public org.a2aproject.sdk.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfig request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); } @@ -804,7 +804,7 @@ public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(i * Gets a push notification config for a task. * */ - public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + public org.a2aproject.sdk.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getGetTaskPushNotificationConfigMethod(), getCallOptions(), request); } @@ -814,7 +814,7 @@ public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a * Get a list of push notifications configured for a task. * */ - public io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request) throws io.grpc.StatusException { + public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigs(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getListTaskPushNotificationConfigsMethod(), getCallOptions(), request); } @@ -824,7 +824,7 @@ public io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificat * Gets the extended agent card for the authenticated agent. * */ - public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request) throws io.grpc.StatusException { + public org.a2aproject.sdk.grpc.AgentCard getExtendedAgentCard(org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getGetExtendedAgentCardMethod(), getCallOptions(), request); } @@ -834,7 +834,7 @@ public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCa * Deletes a push notification config for a task. * */ - public com.google.protobuf.Empty deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + public com.google.protobuf.Empty deleteTaskPushNotificationConfig(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { return io.grpc.stub.ClientCalls.blockingV2UnaryCall( getChannel(), getDeleteTaskPushNotificationConfigMethod(), getCallOptions(), request); } @@ -864,7 +864,7 @@ protected A2AServiceBlockingStub build( * Sends a message to an agent. * */ - public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageRequest request) { + public org.a2aproject.sdk.grpc.SendMessageResponse sendMessage(org.a2aproject.sdk.grpc.SendMessageRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getSendMessageMethod(), getCallOptions(), request); } @@ -875,8 +875,8 @@ public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageReques * Streaming version of `SendMessage` * */ - public java.util.Iterator sendStreamingMessage( - io.a2a.grpc.SendMessageRequest request) { + public java.util.Iterator sendStreamingMessage( + org.a2aproject.sdk.grpc.SendMessageRequest request) { return io.grpc.stub.ClientCalls.blockingServerStreamingCall( getChannel(), getSendStreamingMessageMethod(), getCallOptions(), request); } @@ -886,7 +886,7 @@ public java.util.Iterator sendStreamingMessage( * Gets the latest state of a task. * */ - public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) { + public org.a2aproject.sdk.grpc.Task getTask(org.a2aproject.sdk.grpc.GetTaskRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getGetTaskMethod(), getCallOptions(), request); } @@ -896,7 +896,7 @@ public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) { * Lists tasks that match the specified filter. * */ - public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest request) { + public org.a2aproject.sdk.grpc.ListTasksResponse listTasks(org.a2aproject.sdk.grpc.ListTasksRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getListTasksMethod(), getCallOptions(), request); } @@ -906,7 +906,7 @@ public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest requ * Cancels a task in progress. * */ - public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) { + public org.a2aproject.sdk.grpc.Task cancelTask(org.a2aproject.sdk.grpc.CancelTaskRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getCancelTaskMethod(), getCallOptions(), request); } @@ -917,8 +917,8 @@ public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) { * Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected). * */ - public java.util.Iterator subscribeToTask( - io.a2a.grpc.SubscribeToTaskRequest request) { + public java.util.Iterator subscribeToTask( + org.a2aproject.sdk.grpc.SubscribeToTaskRequest request) { return io.grpc.stub.ClientCalls.blockingServerStreamingCall( getChannel(), getSubscribeToTaskMethod(), getCallOptions(), request); } @@ -932,7 +932,7 @@ public java.util.Iterator subscribeToTask( * Creates a push notification config for a task. * */ - public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request) { + public org.a2aproject.sdk.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfig request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); } @@ -942,7 +942,7 @@ public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(i * Gets a push notification config for a task. * */ - public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request) { + public org.a2aproject.sdk.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getGetTaskPushNotificationConfigMethod(), getCallOptions(), request); } @@ -952,7 +952,7 @@ public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a * Get a list of push notifications configured for a task. * */ - public io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request) { + public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigs(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getListTaskPushNotificationConfigsMethod(), getCallOptions(), request); } @@ -962,7 +962,7 @@ public io.a2a.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificat * Gets the extended agent card for the authenticated agent. * */ - public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request) { + public org.a2aproject.sdk.grpc.AgentCard getExtendedAgentCard(org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getGetExtendedAgentCardMethod(), getCallOptions(), request); } @@ -972,7 +972,7 @@ public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCa * Deletes a push notification config for a task. * */ - public com.google.protobuf.Empty deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request) { + public com.google.protobuf.Empty deleteTaskPushNotificationConfig(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest request) { return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getDeleteTaskPushNotificationConfigMethod(), getCallOptions(), request); } @@ -1002,8 +1002,8 @@ protected A2AServiceFutureStub build( * Sends a message to an agent. * */ - public com.google.common.util.concurrent.ListenableFuture sendMessage( - io.a2a.grpc.SendMessageRequest request) { + public com.google.common.util.concurrent.ListenableFuture sendMessage( + org.a2aproject.sdk.grpc.SendMessageRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getSendMessageMethod(), getCallOptions()), request); } @@ -1013,8 +1013,8 @@ public com.google.common.util.concurrent.ListenableFuture */ - public com.google.common.util.concurrent.ListenableFuture getTask( - io.a2a.grpc.GetTaskRequest request) { + public com.google.common.util.concurrent.ListenableFuture getTask( + org.a2aproject.sdk.grpc.GetTaskRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getGetTaskMethod(), getCallOptions()), request); } @@ -1024,8 +1024,8 @@ public com.google.common.util.concurrent.ListenableFuture getT * Lists tasks that match the specified filter. * */ - public com.google.common.util.concurrent.ListenableFuture listTasks( - io.a2a.grpc.ListTasksRequest request) { + public com.google.common.util.concurrent.ListenableFuture listTasks( + org.a2aproject.sdk.grpc.ListTasksRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getListTasksMethod(), getCallOptions()), request); } @@ -1035,8 +1035,8 @@ public com.google.common.util.concurrent.ListenableFuture */ - public com.google.common.util.concurrent.ListenableFuture cancelTask( - io.a2a.grpc.CancelTaskRequest request) { + public com.google.common.util.concurrent.ListenableFuture cancelTask( + org.a2aproject.sdk.grpc.CancelTaskRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getCancelTaskMethod(), getCallOptions()), request); } @@ -1050,8 +1050,8 @@ public com.google.common.util.concurrent.ListenableFuture canc * Creates a push notification config for a task. * */ - public com.google.common.util.concurrent.ListenableFuture createTaskPushNotificationConfig( - io.a2a.grpc.TaskPushNotificationConfig request) { + public com.google.common.util.concurrent.ListenableFuture createTaskPushNotificationConfig( + org.a2aproject.sdk.grpc.TaskPushNotificationConfig request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request); } @@ -1061,8 +1061,8 @@ public com.google.common.util.concurrent.ListenableFuture */ - public com.google.common.util.concurrent.ListenableFuture getTaskPushNotificationConfig( - io.a2a.grpc.GetTaskPushNotificationConfigRequest request) { + public com.google.common.util.concurrent.ListenableFuture getTaskPushNotificationConfig( + org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getGetTaskPushNotificationConfigMethod(), getCallOptions()), request); } @@ -1072,8 +1072,8 @@ public com.google.common.util.concurrent.ListenableFuture */ - public com.google.common.util.concurrent.ListenableFuture listTaskPushNotificationConfigs( - io.a2a.grpc.ListTaskPushNotificationConfigsRequest request) { + public com.google.common.util.concurrent.ListenableFuture listTaskPushNotificationConfigs( + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getListTaskPushNotificationConfigsMethod(), getCallOptions()), request); } @@ -1083,8 +1083,8 @@ public com.google.common.util.concurrent.ListenableFuture */ - public com.google.common.util.concurrent.ListenableFuture getExtendedAgentCard( - io.a2a.grpc.GetExtendedAgentCardRequest request) { + public com.google.common.util.concurrent.ListenableFuture getExtendedAgentCard( + org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getGetExtendedAgentCardMethod(), getCallOptions()), request); } @@ -1095,7 +1095,7 @@ public com.google.common.util.concurrent.ListenableFuture * */ public com.google.common.util.concurrent.ListenableFuture deleteTaskPushNotificationConfig( - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request) { + org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest request) { return io.grpc.stub.ClientCalls.futureUnaryCall( getChannel().newCall(getDeleteTaskPushNotificationConfigMethod(), getCallOptions()), request); } @@ -1131,47 +1131,47 @@ private static final class MethodHandlers implements public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { switch (methodId) { case METHODID_SEND_MESSAGE: - serviceImpl.sendMessage((io.a2a.grpc.SendMessageRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.sendMessage((org.a2aproject.sdk.grpc.SendMessageRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_SEND_STREAMING_MESSAGE: - serviceImpl.sendStreamingMessage((io.a2a.grpc.SendMessageRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.sendStreamingMessage((org.a2aproject.sdk.grpc.SendMessageRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_GET_TASK: - serviceImpl.getTask((io.a2a.grpc.GetTaskRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.getTask((org.a2aproject.sdk.grpc.GetTaskRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_LIST_TASKS: - serviceImpl.listTasks((io.a2a.grpc.ListTasksRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.listTasks((org.a2aproject.sdk.grpc.ListTasksRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_CANCEL_TASK: - serviceImpl.cancelTask((io.a2a.grpc.CancelTaskRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.cancelTask((org.a2aproject.sdk.grpc.CancelTaskRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_SUBSCRIBE_TO_TASK: - serviceImpl.subscribeToTask((io.a2a.grpc.SubscribeToTaskRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.subscribeToTask((org.a2aproject.sdk.grpc.SubscribeToTaskRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.createTaskPushNotificationConfig((io.a2a.grpc.TaskPushNotificationConfig) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.createTaskPushNotificationConfig((org.a2aproject.sdk.grpc.TaskPushNotificationConfig) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.getTaskPushNotificationConfig((io.a2a.grpc.GetTaskPushNotificationConfigRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.getTaskPushNotificationConfig((org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIGS: - serviceImpl.listTaskPushNotificationConfigs((io.a2a.grpc.ListTaskPushNotificationConfigsRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.listTaskPushNotificationConfigs((org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_GET_EXTENDED_AGENT_CARD: - serviceImpl.getExtendedAgentCard((io.a2a.grpc.GetExtendedAgentCardRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); + serviceImpl.getExtendedAgentCard((org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); break; case METHODID_DELETE_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.deleteTaskPushNotificationConfig((io.a2a.grpc.DeleteTaskPushNotificationConfigRequest) request, + serviceImpl.deleteTaskPushNotificationConfig((org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest) request, (io.grpc.stub.StreamObserver) responseObserver); break; default: @@ -1196,77 +1196,77 @@ public static final io.grpc.ServerServiceDefinition bindService(AsyncService ser getSendMessageMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.SendMessageRequest, - io.a2a.grpc.SendMessageResponse>( + org.a2aproject.sdk.grpc.SendMessageRequest, + org.a2aproject.sdk.grpc.SendMessageResponse>( service, METHODID_SEND_MESSAGE))) .addMethod( getSendStreamingMessageMethod(), io.grpc.stub.ServerCalls.asyncServerStreamingCall( new MethodHandlers< - io.a2a.grpc.SendMessageRequest, - io.a2a.grpc.StreamResponse>( + org.a2aproject.sdk.grpc.SendMessageRequest, + org.a2aproject.sdk.grpc.StreamResponse>( service, METHODID_SEND_STREAMING_MESSAGE))) .addMethod( getGetTaskMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.GetTaskRequest, - io.a2a.grpc.Task>( + org.a2aproject.sdk.grpc.GetTaskRequest, + org.a2aproject.sdk.grpc.Task>( service, METHODID_GET_TASK))) .addMethod( getListTasksMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.ListTasksRequest, - io.a2a.grpc.ListTasksResponse>( + org.a2aproject.sdk.grpc.ListTasksRequest, + org.a2aproject.sdk.grpc.ListTasksResponse>( service, METHODID_LIST_TASKS))) .addMethod( getCancelTaskMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.CancelTaskRequest, - io.a2a.grpc.Task>( + org.a2aproject.sdk.grpc.CancelTaskRequest, + org.a2aproject.sdk.grpc.Task>( service, METHODID_CANCEL_TASK))) .addMethod( getSubscribeToTaskMethod(), io.grpc.stub.ServerCalls.asyncServerStreamingCall( new MethodHandlers< - io.a2a.grpc.SubscribeToTaskRequest, - io.a2a.grpc.StreamResponse>( + org.a2aproject.sdk.grpc.SubscribeToTaskRequest, + org.a2aproject.sdk.grpc.StreamResponse>( service, METHODID_SUBSCRIBE_TO_TASK))) .addMethod( getCreateTaskPushNotificationConfigMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.TaskPushNotificationConfig, - io.a2a.grpc.TaskPushNotificationConfig>( + org.a2aproject.sdk.grpc.TaskPushNotificationConfig, + org.a2aproject.sdk.grpc.TaskPushNotificationConfig>( service, METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG))) .addMethod( getGetTaskPushNotificationConfigMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.GetTaskPushNotificationConfigRequest, - io.a2a.grpc.TaskPushNotificationConfig>( + org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest, + org.a2aproject.sdk.grpc.TaskPushNotificationConfig>( service, METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG))) .addMethod( getListTaskPushNotificationConfigsMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.ListTaskPushNotificationConfigsRequest, - io.a2a.grpc.ListTaskPushNotificationConfigsResponse>( + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest, + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse>( service, METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIGS))) .addMethod( getGetExtendedAgentCardMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.GetExtendedAgentCardRequest, - io.a2a.grpc.AgentCard>( + org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest, + org.a2aproject.sdk.grpc.AgentCard>( service, METHODID_GET_EXTENDED_AGENT_CARD))) .addMethod( getDeleteTaskPushNotificationConfigMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( new MethodHandlers< - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest, + org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest, com.google.protobuf.Empty>( service, METHODID_DELETE_TASK_PUSH_NOTIFICATION_CONFIG))) .build(); @@ -1278,7 +1278,7 @@ private static abstract class A2AServiceBaseDescriptorSupplier @java.lang.Override public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { - return io.a2a.grpc.A2A.getDescriptor(); + return org.a2aproject.sdk.grpc.A2A.getDescriptor(); } @java.lang.Override diff --git a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/APIKeySecurityScheme.java similarity index 87% rename from spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/APIKeySecurityScheme.java index d7c950934..fb8dd2747 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/APIKeySecurityScheme.java @@ -3,7 +3,7 @@ // source: a2a.proto // Protobuf Java Version: 4.33.1 -package io.a2a.grpc; +package org.a2aproject.sdk.grpc; /** *

                      @@ -39,15 +39,15 @@ private APIKeySecurityScheme() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.APIKeySecurityScheme.class, io.a2a.grpc.APIKeySecurityScheme.Builder.class);
                      +            org.a2aproject.sdk.grpc.APIKeySecurityScheme.class, org.a2aproject.sdk.grpc.APIKeySecurityScheme.Builder.class);
                         }
                       
                         public static final int DESCRIPTION_FIELD_NUMBER = 1;
                      @@ -242,10 +242,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.APIKeySecurityScheme)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.APIKeySecurityScheme)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.APIKeySecurityScheme other = (io.a2a.grpc.APIKeySecurityScheme) obj;
                      +    org.a2aproject.sdk.grpc.APIKeySecurityScheme other = (org.a2aproject.sdk.grpc.APIKeySecurityScheme) obj;
                       
                           if (!getDescription()
                               .equals(other.getDescription())) return false;
                      @@ -275,44 +275,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -320,26 +320,26 @@ public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -352,7 +352,7 @@ public static io.a2a.grpc.APIKeySecurityScheme parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.APIKeySecurityScheme prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.APIKeySecurityScheme prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -377,21 +377,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.APIKeySecurityScheme)
                      -      io.a2a.grpc.APIKeySecuritySchemeOrBuilder {
                      +      org.a2aproject.sdk.grpc.APIKeySecuritySchemeOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.APIKeySecurityScheme.class, io.a2a.grpc.APIKeySecurityScheme.Builder.class);
                      +              org.a2aproject.sdk.grpc.APIKeySecurityScheme.class, org.a2aproject.sdk.grpc.APIKeySecurityScheme.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.APIKeySecurityScheme.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.APIKeySecurityScheme.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -414,17 +414,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_APIKeySecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.APIKeySecurityScheme getDefaultInstanceForType() {
                      -      return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.APIKeySecurityScheme getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.APIKeySecurityScheme build() {
                      -      io.a2a.grpc.APIKeySecurityScheme result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.APIKeySecurityScheme build() {
                      +      org.a2aproject.sdk.grpc.APIKeySecurityScheme result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -432,14 +432,14 @@ public io.a2a.grpc.APIKeySecurityScheme build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.APIKeySecurityScheme buildPartial() {
                      -      io.a2a.grpc.APIKeySecurityScheme result = new io.a2a.grpc.APIKeySecurityScheme(this);
                      +    public org.a2aproject.sdk.grpc.APIKeySecurityScheme buildPartial() {
                      +      org.a2aproject.sdk.grpc.APIKeySecurityScheme result = new org.a2aproject.sdk.grpc.APIKeySecurityScheme(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.APIKeySecurityScheme result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.APIKeySecurityScheme result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.description_ = description_;
                      @@ -454,16 +454,16 @@ private void buildPartial0(io.a2a.grpc.APIKeySecurityScheme result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.APIKeySecurityScheme) {
                      -        return mergeFrom((io.a2a.grpc.APIKeySecurityScheme)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.APIKeySecurityScheme) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.APIKeySecurityScheme)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.APIKeySecurityScheme other) {
                      -      if (other == io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.APIKeySecurityScheme other) {
                      +      if (other == org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance()) return this;
                             if (!other.getDescription().isEmpty()) {
                               description_ = other.description_;
                               bitField0_ |= 0x00000001;
                      @@ -817,12 +817,12 @@ public Builder setNameBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.APIKeySecurityScheme)
                      -  private static final io.a2a.grpc.APIKeySecurityScheme DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.APIKeySecurityScheme DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.APIKeySecurityScheme();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.APIKeySecurityScheme();
                         }
                       
                      -  public static io.a2a.grpc.APIKeySecurityScheme getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.APIKeySecurityScheme getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -858,7 +858,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.APIKeySecurityScheme getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.APIKeySecurityScheme getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/APIKeySecuritySchemeOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/APIKeySecuritySchemeOrBuilder.java
                      index 402c95c3c..2a5068dbb 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/APIKeySecuritySchemeOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface APIKeySecuritySchemeOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCapabilities.java
                      similarity index 84%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCapabilities.java
                      index f01517fa3..119948d01 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCapabilities.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -37,15 +37,15 @@ private AgentCapabilities() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AgentCapabilities.class, io.a2a.grpc.AgentCapabilities.Builder.class);
                      +            org.a2aproject.sdk.grpc.AgentCapabilities.class, org.a2aproject.sdk.grpc.AgentCapabilities.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -105,7 +105,7 @@ public boolean getPushNotifications() {
                       
                         public static final int EXTENSIONS_FIELD_NUMBER = 3;
                         @SuppressWarnings("serial")
                      -  private java.util.List extensions_;
                      +  private java.util.List extensions_;
                         /**
                          * 
                          * A list of protocol extensions supported by the agent.
                      @@ -114,7 +114,7 @@ public boolean getPushNotifications() {
                          * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                          */
                         @java.lang.Override
                      -  public java.util.List getExtensionsList() {
                      +  public java.util.List getExtensionsList() {
                           return extensions_;
                         }
                         /**
                      @@ -125,7 +125,7 @@ public java.util.List getExtensionsList() {
                          * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getExtensionsOrBuilderList() {
                           return extensions_;
                         }
                      @@ -148,7 +148,7 @@ public int getExtensionsCount() {
                          * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentExtension getExtensions(int index) {
                      +  public org.a2aproject.sdk.grpc.AgentExtension getExtensions(int index) {
                           return extensions_.get(index);
                         }
                         /**
                      @@ -159,7 +159,7 @@ public io.a2a.grpc.AgentExtension getExtensions(int index) {
                          * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
                      +  public org.a2aproject.sdk.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
                             int index) {
                           return extensions_.get(index);
                         }
                      @@ -252,10 +252,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AgentCapabilities)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AgentCapabilities)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AgentCapabilities other = (io.a2a.grpc.AgentCapabilities) obj;
                      +    org.a2aproject.sdk.grpc.AgentCapabilities other = (org.a2aproject.sdk.grpc.AgentCapabilities) obj;
                       
                           if (hasStreaming() != other.hasStreaming()) return false;
                           if (hasStreaming()) {
                      @@ -309,44 +309,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -354,26 +354,26 @@ public static io.a2a.grpc.AgentCapabilities parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AgentCapabilities parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AgentCapabilities parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentCapabilities parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -386,7 +386,7 @@ public static io.a2a.grpc.AgentCapabilities parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AgentCapabilities prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AgentCapabilities prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -411,21 +411,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentCapabilities)
                      -      io.a2a.grpc.AgentCapabilitiesOrBuilder {
                      +      org.a2aproject.sdk.grpc.AgentCapabilitiesOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AgentCapabilities.class, io.a2a.grpc.AgentCapabilities.Builder.class);
                      +              org.a2aproject.sdk.grpc.AgentCapabilities.class, org.a2aproject.sdk.grpc.AgentCapabilities.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AgentCapabilities.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AgentCapabilities.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -455,17 +455,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCapabilities_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCapabilities getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AgentCapabilities.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AgentCapabilities getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AgentCapabilities.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCapabilities build() {
                      -      io.a2a.grpc.AgentCapabilities result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AgentCapabilities build() {
                      +      org.a2aproject.sdk.grpc.AgentCapabilities result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -473,15 +473,15 @@ public io.a2a.grpc.AgentCapabilities build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCapabilities buildPartial() {
                      -      io.a2a.grpc.AgentCapabilities result = new io.a2a.grpc.AgentCapabilities(this);
                      +    public org.a2aproject.sdk.grpc.AgentCapabilities buildPartial() {
                      +      org.a2aproject.sdk.grpc.AgentCapabilities result = new org.a2aproject.sdk.grpc.AgentCapabilities(this);
                             buildPartialRepeatedFields(result);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartialRepeatedFields(io.a2a.grpc.AgentCapabilities result) {
                      +    private void buildPartialRepeatedFields(org.a2aproject.sdk.grpc.AgentCapabilities result) {
                             if (extensionsBuilder_ == null) {
                               if (((bitField0_ & 0x00000004) != 0)) {
                                 extensions_ = java.util.Collections.unmodifiableList(extensions_);
                      @@ -493,7 +493,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.AgentCapabilities result) {
                             }
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AgentCapabilities result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AgentCapabilities result) {
                             int from_bitField0_ = bitField0_;
                             int to_bitField0_ = 0;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                      @@ -513,16 +513,16 @@ private void buildPartial0(io.a2a.grpc.AgentCapabilities result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AgentCapabilities) {
                      -        return mergeFrom((io.a2a.grpc.AgentCapabilities)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AgentCapabilities) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AgentCapabilities)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AgentCapabilities other) {
                      -      if (other == io.a2a.grpc.AgentCapabilities.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AgentCapabilities other) {
                      +      if (other == org.a2aproject.sdk.grpc.AgentCapabilities.getDefaultInstance()) return this;
                             if (other.hasStreaming()) {
                               setStreaming(other.getStreaming());
                             }
                      @@ -595,9 +595,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 16
                                   case 26: {
                      -              io.a2a.grpc.AgentExtension m =
                      +              org.a2aproject.sdk.grpc.AgentExtension m =
                                         input.readMessage(
                      -                      io.a2a.grpc.AgentExtension.parser(),
                      +                      org.a2aproject.sdk.grpc.AgentExtension.parser(),
                                             extensionRegistry);
                                     if (extensionsBuilder_ == null) {
                                       ensureExtensionsIsMutable();
                      @@ -741,17 +741,17 @@ public Builder clearPushNotifications() {
                             return this;
                           }
                       
                      -    private java.util.List extensions_ =
                      +    private java.util.List extensions_ =
                             java.util.Collections.emptyList();
                           private void ensureExtensionsIsMutable() {
                             if (!((bitField0_ & 0x00000004) != 0)) {
                      -        extensions_ = new java.util.ArrayList(extensions_);
                      +        extensions_ = new java.util.ArrayList(extensions_);
                               bitField0_ |= 0x00000004;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.AgentExtension, io.a2a.grpc.AgentExtension.Builder, io.a2a.grpc.AgentExtensionOrBuilder> extensionsBuilder_;
                      +        org.a2aproject.sdk.grpc.AgentExtension, org.a2aproject.sdk.grpc.AgentExtension.Builder, org.a2aproject.sdk.grpc.AgentExtensionOrBuilder> extensionsBuilder_;
                       
                           /**
                            * 
                      @@ -760,7 +760,7 @@ private void ensureExtensionsIsMutable() {
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public java.util.List getExtensionsList() {
                      +    public java.util.List getExtensionsList() {
                             if (extensionsBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(extensions_);
                             } else {
                      @@ -788,7 +788,7 @@ public int getExtensionsCount() {
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public io.a2a.grpc.AgentExtension getExtensions(int index) {
                      +    public org.a2aproject.sdk.grpc.AgentExtension getExtensions(int index) {
                             if (extensionsBuilder_ == null) {
                               return extensions_.get(index);
                             } else {
                      @@ -803,7 +803,7 @@ public io.a2a.grpc.AgentExtension getExtensions(int index) {
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                           public Builder setExtensions(
                      -        int index, io.a2a.grpc.AgentExtension value) {
                      +        int index, org.a2aproject.sdk.grpc.AgentExtension value) {
                             if (extensionsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -824,7 +824,7 @@ public Builder setExtensions(
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                           public Builder setExtensions(
                      -        int index, io.a2a.grpc.AgentExtension.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.AgentExtension.Builder builderForValue) {
                             if (extensionsBuilder_ == null) {
                               ensureExtensionsIsMutable();
                               extensions_.set(index, builderForValue.build());
                      @@ -841,7 +841,7 @@ public Builder setExtensions(
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public Builder addExtensions(io.a2a.grpc.AgentExtension value) {
                      +    public Builder addExtensions(org.a2aproject.sdk.grpc.AgentExtension value) {
                             if (extensionsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -862,7 +862,7 @@ public Builder addExtensions(io.a2a.grpc.AgentExtension value) {
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                           public Builder addExtensions(
                      -        int index, io.a2a.grpc.AgentExtension value) {
                      +        int index, org.a2aproject.sdk.grpc.AgentExtension value) {
                             if (extensionsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -883,7 +883,7 @@ public Builder addExtensions(
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                           public Builder addExtensions(
                      -        io.a2a.grpc.AgentExtension.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.AgentExtension.Builder builderForValue) {
                             if (extensionsBuilder_ == null) {
                               ensureExtensionsIsMutable();
                               extensions_.add(builderForValue.build());
                      @@ -901,7 +901,7 @@ public Builder addExtensions(
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                           public Builder addExtensions(
                      -        int index, io.a2a.grpc.AgentExtension.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.AgentExtension.Builder builderForValue) {
                             if (extensionsBuilder_ == null) {
                               ensureExtensionsIsMutable();
                               extensions_.add(index, builderForValue.build());
                      @@ -919,7 +919,7 @@ public Builder addExtensions(
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                           public Builder addAllExtensions(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (extensionsBuilder_ == null) {
                               ensureExtensionsIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -971,7 +971,7 @@ public Builder removeExtensions(int index) {
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public io.a2a.grpc.AgentExtension.Builder getExtensionsBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentExtension.Builder getExtensionsBuilder(
                               int index) {
                             return internalGetExtensionsFieldBuilder().getBuilder(index);
                           }
                      @@ -982,7 +982,7 @@ public io.a2a.grpc.AgentExtension.Builder getExtensionsBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
                               int index) {
                             if (extensionsBuilder_ == null) {
                               return extensions_.get(index);  } else {
                      @@ -996,7 +996,7 @@ public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getExtensionsOrBuilderList() {
                             if (extensionsBuilder_ != null) {
                               return extensionsBuilder_.getMessageOrBuilderList();
                      @@ -1011,9 +1011,9 @@ public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder() {
                      +    public org.a2aproject.sdk.grpc.AgentExtension.Builder addExtensionsBuilder() {
                             return internalGetExtensionsFieldBuilder().addBuilder(
                      -          io.a2a.grpc.AgentExtension.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.AgentExtension.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1022,10 +1022,10 @@ public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder() {
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentExtension.Builder addExtensionsBuilder(
                               int index) {
                             return internalGetExtensionsFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.AgentExtension.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.AgentExtension.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1034,16 +1034,16 @@ public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getExtensionsBuilderList() {
                             return internalGetExtensionsFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.AgentExtension, io.a2a.grpc.AgentExtension.Builder, io.a2a.grpc.AgentExtensionOrBuilder> 
                      +        org.a2aproject.sdk.grpc.AgentExtension, org.a2aproject.sdk.grpc.AgentExtension.Builder, org.a2aproject.sdk.grpc.AgentExtensionOrBuilder> 
                               internalGetExtensionsFieldBuilder() {
                             if (extensionsBuilder_ == null) {
                               extensionsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.AgentExtension, io.a2a.grpc.AgentExtension.Builder, io.a2a.grpc.AgentExtensionOrBuilder>(
                      +            org.a2aproject.sdk.grpc.AgentExtension, org.a2aproject.sdk.grpc.AgentExtension.Builder, org.a2aproject.sdk.grpc.AgentExtensionOrBuilder>(
                                       extensions_,
                                       ((bitField0_ & 0x00000004) != 0),
                                       getParentForChildren(),
                      @@ -1113,12 +1113,12 @@ public Builder clearExtendedAgentCard() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentCapabilities)
                      -  private static final io.a2a.grpc.AgentCapabilities DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AgentCapabilities DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AgentCapabilities();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AgentCapabilities();
                         }
                       
                      -  public static io.a2a.grpc.AgentCapabilities getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AgentCapabilities getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1154,7 +1154,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentCapabilities getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AgentCapabilities getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCapabilitiesOrBuilder.java
                      similarity index 90%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCapabilitiesOrBuilder.java
                      index 112329f21..1867fce31 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCapabilitiesOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AgentCapabilitiesOrBuilder extends
                      @@ -55,7 +55,7 @@ public interface AgentCapabilitiesOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getExtensionsList();
                         /**
                          * 
                      @@ -64,7 +64,7 @@ public interface AgentCapabilitiesOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                          */
                      -  io.a2a.grpc.AgentExtension getExtensions(int index);
                      +  org.a2aproject.sdk.grpc.AgentExtension getExtensions(int index);
                         /**
                          * 
                          * A list of protocol extensions supported by the agent.
                      @@ -80,7 +80,7 @@ public interface AgentCapabilitiesOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getExtensionsOrBuilderList();
                         /**
                          * 
                      @@ -89,7 +89,7 @@ public interface AgentCapabilitiesOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.AgentExtension extensions = 3;
                          */
                      -  io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
                      +  org.a2aproject.sdk.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder(
                             int index);
                       
                         /**
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCard.java
                      similarity index 86%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCard.java
                      index 7e75ae6a0..8eed8b164 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCard.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -52,7 +52,7 @@ private AgentCard() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor;
                         }
                       
                         @SuppressWarnings({"rawtypes"})
                      @@ -70,9 +70,9 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AgentCard.class, io.a2a.grpc.AgentCard.Builder.class);
                      +            org.a2aproject.sdk.grpc.AgentCard.class, org.a2aproject.sdk.grpc.AgentCard.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -178,7 +178,7 @@ public java.lang.String getDescription() {
                       
                         public static final int SUPPORTED_INTERFACES_FIELD_NUMBER = 3;
                         @SuppressWarnings("serial")
                      -  private java.util.List supportedInterfaces_;
                      +  private java.util.List supportedInterfaces_;
                         /**
                          * 
                          * Ordered list of supported interfaces. The first entry is preferred.
                      @@ -187,7 +187,7 @@ public java.lang.String getDescription() {
                          * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List getSupportedInterfacesList() {
                      +  public java.util.List getSupportedInterfacesList() {
                           return supportedInterfaces_;
                         }
                         /**
                      @@ -198,7 +198,7 @@ public java.util.List getSupportedInterfacesList() {
                          * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getSupportedInterfacesOrBuilderList() {
                           return supportedInterfaces_;
                         }
                      @@ -221,7 +221,7 @@ public int getSupportedInterfacesCount() {
                          * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) {
                      +  public org.a2aproject.sdk.grpc.AgentInterface getSupportedInterfaces(int index) {
                           return supportedInterfaces_.get(index);
                         }
                         /**
                      @@ -232,13 +232,13 @@ public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) {
                          * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                      +  public org.a2aproject.sdk.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                             int index) {
                           return supportedInterfaces_.get(index);
                         }
                       
                         public static final int PROVIDER_FIELD_NUMBER = 4;
                      -  private io.a2a.grpc.AgentProvider provider_;
                      +  private org.a2aproject.sdk.grpc.AgentProvider provider_;
                         /**
                          * 
                          * The service provider of the agent.
                      @@ -260,8 +260,8 @@ public boolean hasProvider() {
                          * @return The provider.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentProvider getProvider() {
                      -    return provider_ == null ? io.a2a.grpc.AgentProvider.getDefaultInstance() : provider_;
                      +  public org.a2aproject.sdk.grpc.AgentProvider getProvider() {
                      +    return provider_ == null ? org.a2aproject.sdk.grpc.AgentProvider.getDefaultInstance() : provider_;
                         }
                         /**
                          * 
                      @@ -271,8 +271,8 @@ public io.a2a.grpc.AgentProvider getProvider() {
                          * .lf.a2a.v1.AgentProvider provider = 4;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder() {
                      -    return provider_ == null ? io.a2a.grpc.AgentProvider.getDefaultInstance() : provider_;
                      +  public org.a2aproject.sdk.grpc.AgentProviderOrBuilder getProviderOrBuilder() {
                      +    return provider_ == null ? org.a2aproject.sdk.grpc.AgentProvider.getDefaultInstance() : provider_;
                         }
                       
                         public static final int VERSION_FIELD_NUMBER = 5;
                      @@ -384,7 +384,7 @@ public java.lang.String getDocumentationUrl() {
                         }
                       
                         public static final int CAPABILITIES_FIELD_NUMBER = 7;
                      -  private io.a2a.grpc.AgentCapabilities capabilities_;
                      +  private org.a2aproject.sdk.grpc.AgentCapabilities capabilities_;
                         /**
                          * 
                          * A2A Capability set supported by the agent.
                      @@ -406,8 +406,8 @@ public boolean hasCapabilities() {
                          * @return The capabilities.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentCapabilities getCapabilities() {
                      -    return capabilities_ == null ? io.a2a.grpc.AgentCapabilities.getDefaultInstance() : capabilities_;
                      +  public org.a2aproject.sdk.grpc.AgentCapabilities getCapabilities() {
                      +    return capabilities_ == null ? org.a2aproject.sdk.grpc.AgentCapabilities.getDefaultInstance() : capabilities_;
                         }
                         /**
                          * 
                      @@ -417,26 +417,26 @@ public io.a2a.grpc.AgentCapabilities getCapabilities() {
                          * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() {
                      -    return capabilities_ == null ? io.a2a.grpc.AgentCapabilities.getDefaultInstance() : capabilities_;
                      +  public org.a2aproject.sdk.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() {
                      +    return capabilities_ == null ? org.a2aproject.sdk.grpc.AgentCapabilities.getDefaultInstance() : capabilities_;
                         }
                       
                         public static final int SECURITY_SCHEMES_FIELD_NUMBER = 8;
                         private static final class SecuritySchemesDefaultEntryHolder {
                           static final com.google.protobuf.MapEntry<
                      -        java.lang.String, io.a2a.grpc.SecurityScheme> defaultEntry =
                      +        java.lang.String, org.a2aproject.sdk.grpc.SecurityScheme> defaultEntry =
                                   com.google.protobuf.MapEntry
                      -            .newDefaultInstance(
                      -                io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, 
                      +            .newDefaultInstance(
                      +                org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, 
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                                       "",
                                       com.google.protobuf.WireFormat.FieldType.MESSAGE,
                      -                io.a2a.grpc.SecurityScheme.getDefaultInstance());
                      +                org.a2aproject.sdk.grpc.SecurityScheme.getDefaultInstance());
                         }
                         @SuppressWarnings("serial")
                         private com.google.protobuf.MapField<
                      -      java.lang.String, io.a2a.grpc.SecurityScheme> securitySchemes_;
                      -  private com.google.protobuf.MapField
                      +      java.lang.String, org.a2aproject.sdk.grpc.SecurityScheme> securitySchemes_;
                      +  private com.google.protobuf.MapField
                         internalGetSecuritySchemes() {
                           if (securitySchemes_ == null) {
                             return com.google.protobuf.MapField.emptyMapField(
                      @@ -465,7 +465,7 @@ public boolean containsSecuritySchemes(
                          */
                         @java.lang.Override
                         @java.lang.Deprecated
                      -  public java.util.Map getSecuritySchemes() {
                      +  public java.util.Map getSecuritySchemes() {
                           return getSecuritySchemesMap();
                         }
                         /**
                      @@ -476,7 +476,7 @@ public java.util.Map getSecuritySc
                          * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                          */
                         @java.lang.Override
                      -  public java.util.Map getSecuritySchemesMap() {
                      +  public java.util.Map getSecuritySchemesMap() {
                           return internalGetSecuritySchemes().getMap();
                         }
                         /**
                      @@ -488,12 +488,12 @@ public java.util.Map getSecuritySc
                          */
                         @java.lang.Override
                         public /* nullable */
                      -io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault(
                      +org.a2aproject.sdk.grpc.SecurityScheme getSecuritySchemesOrDefault(
                             java.lang.String key,
                             /* nullable */
                      -io.a2a.grpc.SecurityScheme defaultValue) {
                      +org.a2aproject.sdk.grpc.SecurityScheme defaultValue) {
                           if (key == null) { throw new NullPointerException("map key"); }
                      -    java.util.Map map =
                      +    java.util.Map map =
                               internalGetSecuritySchemes().getMap();
                           return map.containsKey(key) ? map.get(key) : defaultValue;
                         }
                      @@ -505,10 +505,10 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault(
                          * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                      +  public org.a2aproject.sdk.grpc.SecurityScheme getSecuritySchemesOrThrow(
                             java.lang.String key) {
                           if (key == null) { throw new NullPointerException("map key"); }
                      -    java.util.Map map =
                      +    java.util.Map map =
                               internalGetSecuritySchemes().getMap();
                           if (!map.containsKey(key)) {
                             throw new java.lang.IllegalArgumentException();
                      @@ -518,7 +518,7 @@ public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                       
                         public static final int SECURITY_REQUIREMENTS_FIELD_NUMBER = 9;
                         @SuppressWarnings("serial")
                      -  private java.util.List securityRequirements_;
                      +  private java.util.List securityRequirements_;
                         /**
                          * 
                          * Security requirements for contacting the agent.
                      @@ -527,7 +527,7 @@ public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                          */
                         @java.lang.Override
                      -  public java.util.List getSecurityRequirementsList() {
                      +  public java.util.List getSecurityRequirementsList() {
                           return securityRequirements_;
                         }
                         /**
                      @@ -538,7 +538,7 @@ public java.util.List getSecurityRequirementsLi
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getSecurityRequirementsOrBuilderList() {
                           return securityRequirements_;
                         }
                      @@ -561,7 +561,7 @@ public int getSecurityRequirementsCount() {
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) {
                      +  public org.a2aproject.sdk.grpc.SecurityRequirement getSecurityRequirements(int index) {
                           return securityRequirements_.get(index);
                         }
                         /**
                      @@ -572,7 +572,7 @@ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) {
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                      +  public org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                             int index) {
                           return securityRequirements_.get(index);
                         }
                      @@ -693,7 +693,7 @@ public java.lang.String getDefaultOutputModes(int index) {
                       
                         public static final int SKILLS_FIELD_NUMBER = 12;
                         @SuppressWarnings("serial")
                      -  private java.util.List skills_;
                      +  private java.util.List skills_;
                         /**
                          * 
                          * Skills represent the abilities of an agent.
                      @@ -704,7 +704,7 @@ public java.lang.String getDefaultOutputModes(int index) {
                          * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List getSkillsList() {
                      +  public java.util.List getSkillsList() {
                           return skills_;
                         }
                         /**
                      @@ -717,7 +717,7 @@ public java.util.List getSkillsList() {
                          * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getSkillsOrBuilderList() {
                           return skills_;
                         }
                      @@ -744,7 +744,7 @@ public int getSkillsCount() {
                          * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentSkill getSkills(int index) {
                      +  public org.a2aproject.sdk.grpc.AgentSkill getSkills(int index) {
                           return skills_.get(index);
                         }
                         /**
                      @@ -757,14 +757,14 @@ public io.a2a.grpc.AgentSkill getSkills(int index) {
                          * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                      +  public org.a2aproject.sdk.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                             int index) {
                           return skills_.get(index);
                         }
                       
                         public static final int SIGNATURES_FIELD_NUMBER = 13;
                         @SuppressWarnings("serial")
                      -  private java.util.List signatures_;
                      +  private java.util.List signatures_;
                         /**
                          * 
                          * JSON Web Signatures computed for this `AgentCard`.
                      @@ -773,7 +773,7 @@ public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                          * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                          */
                         @java.lang.Override
                      -  public java.util.List getSignaturesList() {
                      +  public java.util.List getSignaturesList() {
                           return signatures_;
                         }
                         /**
                      @@ -784,7 +784,7 @@ public java.util.List getSignaturesList() {
                          * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getSignaturesOrBuilderList() {
                           return signatures_;
                         }
                      @@ -807,7 +807,7 @@ public int getSignaturesCount() {
                          * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentCardSignature getSignatures(int index) {
                      +  public org.a2aproject.sdk.grpc.AgentCardSignature getSignatures(int index) {
                           return signatures_.get(index);
                         }
                         /**
                      @@ -818,7 +818,7 @@ public io.a2a.grpc.AgentCardSignature getSignatures(int index) {
                          * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder(
                      +  public org.a2aproject.sdk.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder(
                             int index) {
                           return signatures_.get(index);
                         }
                      @@ -974,9 +974,9 @@ public int getSerializedSize() {
                             size += com.google.protobuf.CodedOutputStream
                               .computeMessageSize(7, getCapabilities());
                           }
                      -    for (java.util.Map.Entry entry
                      +    for (java.util.Map.Entry entry
                                : internalGetSecuritySchemes().getMap().entrySet()) {
                      -      com.google.protobuf.MapEntry
                      +      com.google.protobuf.MapEntry
                             securitySchemes__ = SecuritySchemesDefaultEntryHolder.defaultEntry.newBuilderForType()
                                 .setKey(entry.getKey())
                                 .setValue(entry.getValue())
                      @@ -1025,10 +1025,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AgentCard)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AgentCard)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AgentCard other = (io.a2a.grpc.AgentCard) obj;
                      +    org.a2aproject.sdk.grpc.AgentCard other = (org.a2aproject.sdk.grpc.AgentCard) obj;
                       
                           if (!getName()
                               .equals(other.getName())) return false;
                      @@ -1136,44 +1136,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AgentCard parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -1181,26 +1181,26 @@ public static io.a2a.grpc.AgentCard parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AgentCard parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AgentCard parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentCard parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCard parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -1213,7 +1213,7 @@ public static io.a2a.grpc.AgentCard parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AgentCard prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AgentCard prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -1241,10 +1241,10 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentCard)
                      -      io.a2a.grpc.AgentCardOrBuilder {
                      +      org.a2aproject.sdk.grpc.AgentCardOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor;
                           }
                       
                           @SuppressWarnings({"rawtypes"})
                      @@ -1272,12 +1272,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AgentCard.class, io.a2a.grpc.AgentCard.Builder.class);
                      +              org.a2aproject.sdk.grpc.AgentCard.class, org.a2aproject.sdk.grpc.AgentCard.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AgentCard.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AgentCard.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -1356,17 +1356,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCard_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCard getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AgentCard.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AgentCard getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AgentCard.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCard build() {
                      -      io.a2a.grpc.AgentCard result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AgentCard build() {
                      +      org.a2aproject.sdk.grpc.AgentCard result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -1374,15 +1374,15 @@ public io.a2a.grpc.AgentCard build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCard buildPartial() {
                      -      io.a2a.grpc.AgentCard result = new io.a2a.grpc.AgentCard(this);
                      +    public org.a2aproject.sdk.grpc.AgentCard buildPartial() {
                      +      org.a2aproject.sdk.grpc.AgentCard result = new org.a2aproject.sdk.grpc.AgentCard(this);
                             buildPartialRepeatedFields(result);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartialRepeatedFields(io.a2a.grpc.AgentCard result) {
                      +    private void buildPartialRepeatedFields(org.a2aproject.sdk.grpc.AgentCard result) {
                             if (supportedInterfacesBuilder_ == null) {
                               if (((bitField0_ & 0x00000004) != 0)) {
                                 supportedInterfaces_ = java.util.Collections.unmodifiableList(supportedInterfaces_);
                      @@ -1421,7 +1421,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.AgentCard result) {
                             }
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AgentCard result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AgentCard result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.name_ = name_;
                      @@ -1469,16 +1469,16 @@ private void buildPartial0(io.a2a.grpc.AgentCard result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AgentCard) {
                      -        return mergeFrom((io.a2a.grpc.AgentCard)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AgentCard) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AgentCard)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AgentCard other) {
                      -      if (other == io.a2a.grpc.AgentCard.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AgentCard other) {
                      +      if (other == org.a2aproject.sdk.grpc.AgentCard.getDefaultInstance()) return this;
                             if (!other.getName().isEmpty()) {
                               name_ = other.name_;
                               bitField0_ |= 0x00000001;
                      @@ -1674,9 +1674,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 18
                                   case 26: {
                      -              io.a2a.grpc.AgentInterface m =
                      +              org.a2aproject.sdk.grpc.AgentInterface m =
                                         input.readMessage(
                      -                      io.a2a.grpc.AgentInterface.parser(),
                      +                      org.a2aproject.sdk.grpc.AgentInterface.parser(),
                                             extensionRegistry);
                                     if (supportedInterfacesBuilder_ == null) {
                                       ensureSupportedInterfacesIsMutable();
                      @@ -1711,7 +1711,7 @@ public Builder mergeFrom(
                                     break;
                                   } // case 58
                                   case 66: {
                      -              com.google.protobuf.MapEntry
                      +              com.google.protobuf.MapEntry
                                     securitySchemes__ = input.readMessage(
                                         SecuritySchemesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
                                     internalGetMutableSecuritySchemes().ensureBuilderMap().put(
                      @@ -1720,9 +1720,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 66
                                   case 74: {
                      -              io.a2a.grpc.SecurityRequirement m =
                      +              org.a2aproject.sdk.grpc.SecurityRequirement m =
                                         input.readMessage(
                      -                      io.a2a.grpc.SecurityRequirement.parser(),
                      +                      org.a2aproject.sdk.grpc.SecurityRequirement.parser(),
                                             extensionRegistry);
                                     if (securityRequirementsBuilder_ == null) {
                                       ensureSecurityRequirementsIsMutable();
                      @@ -1745,9 +1745,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 90
                                   case 98: {
                      -              io.a2a.grpc.AgentSkill m =
                      +              org.a2aproject.sdk.grpc.AgentSkill m =
                                         input.readMessage(
                      -                      io.a2a.grpc.AgentSkill.parser(),
                      +                      org.a2aproject.sdk.grpc.AgentSkill.parser(),
                                             extensionRegistry);
                                     if (skillsBuilder_ == null) {
                                       ensureSkillsIsMutable();
                      @@ -1758,9 +1758,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 98
                                   case 106: {
                      -              io.a2a.grpc.AgentCardSignature m =
                      +              org.a2aproject.sdk.grpc.AgentCardSignature m =
                                         input.readMessage(
                      -                      io.a2a.grpc.AgentCardSignature.parser(),
                      +                      org.a2aproject.sdk.grpc.AgentCardSignature.parser(),
                                             extensionRegistry);
                                     if (signaturesBuilder_ == null) {
                                       ensureSignaturesIsMutable();
                      @@ -1991,17 +1991,17 @@ public Builder setDescriptionBytes(
                             return this;
                           }
                       
                      -    private java.util.List supportedInterfaces_ =
                      +    private java.util.List supportedInterfaces_ =
                             java.util.Collections.emptyList();
                           private void ensureSupportedInterfacesIsMutable() {
                             if (!((bitField0_ & 0x00000004) != 0)) {
                      -        supportedInterfaces_ = new java.util.ArrayList(supportedInterfaces_);
                      +        supportedInterfaces_ = new java.util.ArrayList(supportedInterfaces_);
                               bitField0_ |= 0x00000004;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> supportedInterfacesBuilder_;
                      +        org.a2aproject.sdk.grpc.AgentInterface, org.a2aproject.sdk.grpc.AgentInterface.Builder, org.a2aproject.sdk.grpc.AgentInterfaceOrBuilder> supportedInterfacesBuilder_;
                       
                           /**
                            * 
                      @@ -2010,7 +2010,7 @@ private void ensureSupportedInterfacesIsMutable() {
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List getSupportedInterfacesList() {
                      +    public java.util.List getSupportedInterfacesList() {
                             if (supportedInterfacesBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(supportedInterfaces_);
                             } else {
                      @@ -2038,7 +2038,7 @@ public int getSupportedInterfacesCount() {
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) {
                      +    public org.a2aproject.sdk.grpc.AgentInterface getSupportedInterfaces(int index) {
                             if (supportedInterfacesBuilder_ == null) {
                               return supportedInterfaces_.get(index);
                             } else {
                      @@ -2053,7 +2053,7 @@ public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) {
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setSupportedInterfaces(
                      -        int index, io.a2a.grpc.AgentInterface value) {
                      +        int index, org.a2aproject.sdk.grpc.AgentInterface value) {
                             if (supportedInterfacesBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -2074,7 +2074,7 @@ public Builder setSupportedInterfaces(
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setSupportedInterfaces(
                      -        int index, io.a2a.grpc.AgentInterface.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.AgentInterface.Builder builderForValue) {
                             if (supportedInterfacesBuilder_ == null) {
                               ensureSupportedInterfacesIsMutable();
                               supportedInterfaces_.set(index, builderForValue.build());
                      @@ -2091,7 +2091,7 @@ public Builder setSupportedInterfaces(
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder addSupportedInterfaces(io.a2a.grpc.AgentInterface value) {
                      +    public Builder addSupportedInterfaces(org.a2aproject.sdk.grpc.AgentInterface value) {
                             if (supportedInterfacesBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -2112,7 +2112,7 @@ public Builder addSupportedInterfaces(io.a2a.grpc.AgentInterface value) {
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addSupportedInterfaces(
                      -        int index, io.a2a.grpc.AgentInterface value) {
                      +        int index, org.a2aproject.sdk.grpc.AgentInterface value) {
                             if (supportedInterfacesBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -2133,7 +2133,7 @@ public Builder addSupportedInterfaces(
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addSupportedInterfaces(
                      -        io.a2a.grpc.AgentInterface.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.AgentInterface.Builder builderForValue) {
                             if (supportedInterfacesBuilder_ == null) {
                               ensureSupportedInterfacesIsMutable();
                               supportedInterfaces_.add(builderForValue.build());
                      @@ -2151,7 +2151,7 @@ public Builder addSupportedInterfaces(
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addSupportedInterfaces(
                      -        int index, io.a2a.grpc.AgentInterface.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.AgentInterface.Builder builderForValue) {
                             if (supportedInterfacesBuilder_ == null) {
                               ensureSupportedInterfacesIsMutable();
                               supportedInterfaces_.add(index, builderForValue.build());
                      @@ -2169,7 +2169,7 @@ public Builder addSupportedInterfaces(
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addAllSupportedInterfaces(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (supportedInterfacesBuilder_ == null) {
                               ensureSupportedInterfacesIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -2221,7 +2221,7 @@ public Builder removeSupportedInterfaces(int index) {
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentInterface.Builder getSupportedInterfacesBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentInterface.Builder getSupportedInterfacesBuilder(
                               int index) {
                             return internalGetSupportedInterfacesFieldBuilder().getBuilder(index);
                           }
                      @@ -2232,7 +2232,7 @@ public io.a2a.grpc.AgentInterface.Builder getSupportedInterfacesBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                               int index) {
                             if (supportedInterfacesBuilder_ == null) {
                               return supportedInterfaces_.get(index);  } else {
                      @@ -2246,7 +2246,7 @@ public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSupportedInterfacesOrBuilderList() {
                             if (supportedInterfacesBuilder_ != null) {
                               return supportedInterfacesBuilder_.getMessageOrBuilderList();
                      @@ -2261,9 +2261,9 @@ public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder() {
                      +    public org.a2aproject.sdk.grpc.AgentInterface.Builder addSupportedInterfacesBuilder() {
                             return internalGetSupportedInterfacesFieldBuilder().addBuilder(
                      -          io.a2a.grpc.AgentInterface.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.AgentInterface.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -2272,10 +2272,10 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder() {
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentInterface.Builder addSupportedInterfacesBuilder(
                               int index) {
                             return internalGetSupportedInterfacesFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.AgentInterface.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.AgentInterface.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -2284,16 +2284,16 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSupportedInterfacesBuilderList() {
                             return internalGetSupportedInterfacesFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> 
                      +        org.a2aproject.sdk.grpc.AgentInterface, org.a2aproject.sdk.grpc.AgentInterface.Builder, org.a2aproject.sdk.grpc.AgentInterfaceOrBuilder> 
                               internalGetSupportedInterfacesFieldBuilder() {
                             if (supportedInterfacesBuilder_ == null) {
                               supportedInterfacesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder>(
                      +            org.a2aproject.sdk.grpc.AgentInterface, org.a2aproject.sdk.grpc.AgentInterface.Builder, org.a2aproject.sdk.grpc.AgentInterfaceOrBuilder>(
                                       supportedInterfaces_,
                                       ((bitField0_ & 0x00000004) != 0),
                                       getParentForChildren(),
                      @@ -2303,9 +2303,9 @@ public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder(
                             return supportedInterfacesBuilder_;
                           }
                       
                      -    private io.a2a.grpc.AgentProvider provider_;
                      +    private org.a2aproject.sdk.grpc.AgentProvider provider_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.AgentProvider, io.a2a.grpc.AgentProvider.Builder, io.a2a.grpc.AgentProviderOrBuilder> providerBuilder_;
                      +        org.a2aproject.sdk.grpc.AgentProvider, org.a2aproject.sdk.grpc.AgentProvider.Builder, org.a2aproject.sdk.grpc.AgentProviderOrBuilder> providerBuilder_;
                           /**
                            * 
                            * The service provider of the agent.
                      @@ -2325,9 +2325,9 @@ public boolean hasProvider() {
                            * .lf.a2a.v1.AgentProvider provider = 4;
                            * @return The provider.
                            */
                      -    public io.a2a.grpc.AgentProvider getProvider() {
                      +    public org.a2aproject.sdk.grpc.AgentProvider getProvider() {
                             if (providerBuilder_ == null) {
                      -        return provider_ == null ? io.a2a.grpc.AgentProvider.getDefaultInstance() : provider_;
                      +        return provider_ == null ? org.a2aproject.sdk.grpc.AgentProvider.getDefaultInstance() : provider_;
                             } else {
                               return providerBuilder_.getMessage();
                             }
                      @@ -2339,7 +2339,7 @@ public io.a2a.grpc.AgentProvider getProvider() {
                            *
                            * .lf.a2a.v1.AgentProvider provider = 4;
                            */
                      -    public Builder setProvider(io.a2a.grpc.AgentProvider value) {
                      +    public Builder setProvider(org.a2aproject.sdk.grpc.AgentProvider value) {
                             if (providerBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -2360,7 +2360,7 @@ public Builder setProvider(io.a2a.grpc.AgentProvider value) {
                            * .lf.a2a.v1.AgentProvider provider = 4;
                            */
                           public Builder setProvider(
                      -        io.a2a.grpc.AgentProvider.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.AgentProvider.Builder builderForValue) {
                             if (providerBuilder_ == null) {
                               provider_ = builderForValue.build();
                             } else {
                      @@ -2377,11 +2377,11 @@ public Builder setProvider(
                            *
                            * .lf.a2a.v1.AgentProvider provider = 4;
                            */
                      -    public Builder mergeProvider(io.a2a.grpc.AgentProvider value) {
                      +    public Builder mergeProvider(org.a2aproject.sdk.grpc.AgentProvider value) {
                             if (providerBuilder_ == null) {
                               if (((bitField0_ & 0x00000008) != 0) &&
                                 provider_ != null &&
                      -          provider_ != io.a2a.grpc.AgentProvider.getDefaultInstance()) {
                      +          provider_ != org.a2aproject.sdk.grpc.AgentProvider.getDefaultInstance()) {
                                 getProviderBuilder().mergeFrom(value);
                               } else {
                                 provider_ = value;
                      @@ -2419,7 +2419,7 @@ public Builder clearProvider() {
                            *
                            * .lf.a2a.v1.AgentProvider provider = 4;
                            */
                      -    public io.a2a.grpc.AgentProvider.Builder getProviderBuilder() {
                      +    public org.a2aproject.sdk.grpc.AgentProvider.Builder getProviderBuilder() {
                             bitField0_ |= 0x00000008;
                             onChanged();
                             return internalGetProviderFieldBuilder().getBuilder();
                      @@ -2431,12 +2431,12 @@ public io.a2a.grpc.AgentProvider.Builder getProviderBuilder() {
                            *
                            * .lf.a2a.v1.AgentProvider provider = 4;
                            */
                      -    public io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.AgentProviderOrBuilder getProviderOrBuilder() {
                             if (providerBuilder_ != null) {
                               return providerBuilder_.getMessageOrBuilder();
                             } else {
                               return provider_ == null ?
                      -            io.a2a.grpc.AgentProvider.getDefaultInstance() : provider_;
                      +            org.a2aproject.sdk.grpc.AgentProvider.getDefaultInstance() : provider_;
                             }
                           }
                           /**
                      @@ -2447,11 +2447,11 @@ public io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder() {
                            * .lf.a2a.v1.AgentProvider provider = 4;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.AgentProvider, io.a2a.grpc.AgentProvider.Builder, io.a2a.grpc.AgentProviderOrBuilder> 
                      +        org.a2aproject.sdk.grpc.AgentProvider, org.a2aproject.sdk.grpc.AgentProvider.Builder, org.a2aproject.sdk.grpc.AgentProviderOrBuilder> 
                               internalGetProviderFieldBuilder() {
                             if (providerBuilder_ == null) {
                               providerBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.AgentProvider, io.a2a.grpc.AgentProvider.Builder, io.a2a.grpc.AgentProviderOrBuilder>(
                      +            org.a2aproject.sdk.grpc.AgentProvider, org.a2aproject.sdk.grpc.AgentProvider.Builder, org.a2aproject.sdk.grpc.AgentProviderOrBuilder>(
                                       getProvider(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -2660,9 +2660,9 @@ public Builder setDocumentationUrlBytes(
                             return this;
                           }
                       
                      -    private io.a2a.grpc.AgentCapabilities capabilities_;
                      +    private org.a2aproject.sdk.grpc.AgentCapabilities capabilities_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.AgentCapabilities, io.a2a.grpc.AgentCapabilities.Builder, io.a2a.grpc.AgentCapabilitiesOrBuilder> capabilitiesBuilder_;
                      +        org.a2aproject.sdk.grpc.AgentCapabilities, org.a2aproject.sdk.grpc.AgentCapabilities.Builder, org.a2aproject.sdk.grpc.AgentCapabilitiesOrBuilder> capabilitiesBuilder_;
                           /**
                            * 
                            * A2A Capability set supported by the agent.
                      @@ -2682,9 +2682,9 @@ public boolean hasCapabilities() {
                            * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                            * @return The capabilities.
                            */
                      -    public io.a2a.grpc.AgentCapabilities getCapabilities() {
                      +    public org.a2aproject.sdk.grpc.AgentCapabilities getCapabilities() {
                             if (capabilitiesBuilder_ == null) {
                      -        return capabilities_ == null ? io.a2a.grpc.AgentCapabilities.getDefaultInstance() : capabilities_;
                      +        return capabilities_ == null ? org.a2aproject.sdk.grpc.AgentCapabilities.getDefaultInstance() : capabilities_;
                             } else {
                               return capabilitiesBuilder_.getMessage();
                             }
                      @@ -2696,7 +2696,7 @@ public io.a2a.grpc.AgentCapabilities getCapabilities() {
                            *
                            * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder setCapabilities(io.a2a.grpc.AgentCapabilities value) {
                      +    public Builder setCapabilities(org.a2aproject.sdk.grpc.AgentCapabilities value) {
                             if (capabilitiesBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -2717,7 +2717,7 @@ public Builder setCapabilities(io.a2a.grpc.AgentCapabilities value) {
                            * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setCapabilities(
                      -        io.a2a.grpc.AgentCapabilities.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.AgentCapabilities.Builder builderForValue) {
                             if (capabilitiesBuilder_ == null) {
                               capabilities_ = builderForValue.build();
                             } else {
                      @@ -2734,11 +2734,11 @@ public Builder setCapabilities(
                            *
                            * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) {
                      +    public Builder mergeCapabilities(org.a2aproject.sdk.grpc.AgentCapabilities value) {
                             if (capabilitiesBuilder_ == null) {
                               if (((bitField0_ & 0x00000040) != 0) &&
                                 capabilities_ != null &&
                      -          capabilities_ != io.a2a.grpc.AgentCapabilities.getDefaultInstance()) {
                      +          capabilities_ != org.a2aproject.sdk.grpc.AgentCapabilities.getDefaultInstance()) {
                                 getCapabilitiesBuilder().mergeFrom(value);
                               } else {
                                 capabilities_ = value;
                      @@ -2776,7 +2776,7 @@ public Builder clearCapabilities() {
                            *
                            * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() {
                      +    public org.a2aproject.sdk.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() {
                             bitField0_ |= 0x00000040;
                             onChanged();
                             return internalGetCapabilitiesFieldBuilder().getBuilder();
                      @@ -2788,12 +2788,12 @@ public io.a2a.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() {
                            *
                            * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() {
                             if (capabilitiesBuilder_ != null) {
                               return capabilitiesBuilder_.getMessageOrBuilder();
                             } else {
                               return capabilities_ == null ?
                      -            io.a2a.grpc.AgentCapabilities.getDefaultInstance() : capabilities_;
                      +            org.a2aproject.sdk.grpc.AgentCapabilities.getDefaultInstance() : capabilities_;
                             }
                           }
                           /**
                      @@ -2804,11 +2804,11 @@ public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() {
                            * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.AgentCapabilities, io.a2a.grpc.AgentCapabilities.Builder, io.a2a.grpc.AgentCapabilitiesOrBuilder> 
                      +        org.a2aproject.sdk.grpc.AgentCapabilities, org.a2aproject.sdk.grpc.AgentCapabilities.Builder, org.a2aproject.sdk.grpc.AgentCapabilitiesOrBuilder> 
                               internalGetCapabilitiesFieldBuilder() {
                             if (capabilitiesBuilder_ == null) {
                               capabilitiesBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.AgentCapabilities, io.a2a.grpc.AgentCapabilities.Builder, io.a2a.grpc.AgentCapabilitiesOrBuilder>(
                      +            org.a2aproject.sdk.grpc.AgentCapabilities, org.a2aproject.sdk.grpc.AgentCapabilities.Builder, org.a2aproject.sdk.grpc.AgentCapabilitiesOrBuilder>(
                                       getCapabilities(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -2817,30 +2817,30 @@ public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() {
                             return capabilitiesBuilder_;
                           }
                       
                      -    private static final class SecuritySchemesConverter implements com.google.protobuf.MapFieldBuilder.Converter {
                      +    private static final class SecuritySchemesConverter implements com.google.protobuf.MapFieldBuilder.Converter {
                             @java.lang.Override
                      -      public io.a2a.grpc.SecurityScheme build(io.a2a.grpc.SecuritySchemeOrBuilder val) {
                      -        if (val instanceof io.a2a.grpc.SecurityScheme) { return (io.a2a.grpc.SecurityScheme) val; }
                      -        return ((io.a2a.grpc.SecurityScheme.Builder) val).build();
                      +      public org.a2aproject.sdk.grpc.SecurityScheme build(org.a2aproject.sdk.grpc.SecuritySchemeOrBuilder val) {
                      +        if (val instanceof org.a2aproject.sdk.grpc.SecurityScheme) { return (org.a2aproject.sdk.grpc.SecurityScheme) val; }
                      +        return ((org.a2aproject.sdk.grpc.SecurityScheme.Builder) val).build();
                             }
                       
                             @java.lang.Override
                      -      public com.google.protobuf.MapEntry defaultEntry() {
                      +      public com.google.protobuf.MapEntry defaultEntry() {
                               return SecuritySchemesDefaultEntryHolder.defaultEntry;
                             }
                           };
                           private static final SecuritySchemesConverter securitySchemesConverter = new SecuritySchemesConverter();
                       
                           private com.google.protobuf.MapFieldBuilder<
                      -        java.lang.String, io.a2a.grpc.SecuritySchemeOrBuilder, io.a2a.grpc.SecurityScheme, io.a2a.grpc.SecurityScheme.Builder> securitySchemes_;
                      -    private com.google.protobuf.MapFieldBuilder
                      +        java.lang.String, org.a2aproject.sdk.grpc.SecuritySchemeOrBuilder, org.a2aproject.sdk.grpc.SecurityScheme, org.a2aproject.sdk.grpc.SecurityScheme.Builder> securitySchemes_;
                      +    private com.google.protobuf.MapFieldBuilder
                               internalGetSecuritySchemes() {
                             if (securitySchemes_ == null) {
                               return new com.google.protobuf.MapFieldBuilder<>(securitySchemesConverter);
                             }
                             return securitySchemes_;
                           }
                      -    private com.google.protobuf.MapFieldBuilder
                      +    private com.google.protobuf.MapFieldBuilder
                               internalGetMutableSecuritySchemes() {
                             if (securitySchemes_ == null) {
                               securitySchemes_ = new com.google.protobuf.MapFieldBuilder<>(securitySchemesConverter);
                      @@ -2870,7 +2870,7 @@ public boolean containsSecuritySchemes(
                            */
                           @java.lang.Override
                           @java.lang.Deprecated
                      -    public java.util.Map getSecuritySchemes() {
                      +    public java.util.Map getSecuritySchemes() {
                             return getSecuritySchemesMap();
                           }
                           /**
                      @@ -2881,7 +2881,7 @@ public java.util.Map getSecuritySc
                            * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                            */
                           @java.lang.Override
                      -    public java.util.Map getSecuritySchemesMap() {
                      +    public java.util.Map getSecuritySchemesMap() {
                             return internalGetSecuritySchemes().getImmutableMap();
                           }
                           /**
                      @@ -2893,12 +2893,12 @@ public java.util.Map getSecuritySc
                            */
                           @java.lang.Override
                           public /* nullable */
                      -io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault(
                      +org.a2aproject.sdk.grpc.SecurityScheme getSecuritySchemesOrDefault(
                               java.lang.String key,
                               /* nullable */
                      -io.a2a.grpc.SecurityScheme defaultValue) {
                      +org.a2aproject.sdk.grpc.SecurityScheme defaultValue) {
                             if (key == null) { throw new NullPointerException("map key"); }
                      -      java.util.Map map = internalGetMutableSecuritySchemes().ensureBuilderMap();
                      +      java.util.Map map = internalGetMutableSecuritySchemes().ensureBuilderMap();
                             return map.containsKey(key) ? securitySchemesConverter.build(map.get(key)) : defaultValue;
                           }
                           /**
                      @@ -2909,10 +2909,10 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault(
                            * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                      +    public org.a2aproject.sdk.grpc.SecurityScheme getSecuritySchemesOrThrow(
                               java.lang.String key) {
                             if (key == null) { throw new NullPointerException("map key"); }
                      -      java.util.Map map = internalGetMutableSecuritySchemes().ensureBuilderMap();
                      +      java.util.Map map = internalGetMutableSecuritySchemes().ensureBuilderMap();
                             if (!map.containsKey(key)) {
                               throw new java.lang.IllegalArgumentException();
                             }
                      @@ -2941,7 +2941,7 @@ public Builder removeSecuritySchemes(
                            * Use alternate mutation accessors instead.
                            */
                           @java.lang.Deprecated
                      -    public java.util.Map
                      +    public java.util.Map
                               getMutableSecuritySchemes() {
                             bitField0_ |= 0x00000080;
                             return internalGetMutableSecuritySchemes().ensureMessageMap();
                      @@ -2955,7 +2955,7 @@ public Builder removeSecuritySchemes(
                            */
                           public Builder putSecuritySchemes(
                               java.lang.String key,
                      -        io.a2a.grpc.SecurityScheme value) {
                      +        org.a2aproject.sdk.grpc.SecurityScheme value) {
                             if (key == null) { throw new NullPointerException("map key"); }
                             if (value == null) { throw new NullPointerException("map value"); }
                             internalGetMutableSecuritySchemes().ensureBuilderMap()
                      @@ -2971,8 +2971,8 @@ public Builder putSecuritySchemes(
                            * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                            */
                           public Builder putAllSecuritySchemes(
                      -        java.util.Map values) {
                      -      for (java.util.Map.Entry e : values.entrySet()) {
                      +        java.util.Map values) {
                      +      for (java.util.Map.Entry e : values.entrySet()) {
                               if (e.getKey() == null || e.getValue() == null) {
                                 throw new NullPointerException();
                               }
                      @@ -2989,32 +2989,32 @@ public Builder putAllSecuritySchemes(
                            *
                            * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                            */
                      -    public io.a2a.grpc.SecurityScheme.Builder putSecuritySchemesBuilderIfAbsent(
                      +    public org.a2aproject.sdk.grpc.SecurityScheme.Builder putSecuritySchemesBuilderIfAbsent(
                               java.lang.String key) {
                      -      java.util.Map builderMap = internalGetMutableSecuritySchemes().ensureBuilderMap();
                      -      io.a2a.grpc.SecuritySchemeOrBuilder entry = builderMap.get(key);
                      +      java.util.Map builderMap = internalGetMutableSecuritySchemes().ensureBuilderMap();
                      +      org.a2aproject.sdk.grpc.SecuritySchemeOrBuilder entry = builderMap.get(key);
                             if (entry == null) {
                      -        entry = io.a2a.grpc.SecurityScheme.newBuilder();
                      +        entry = org.a2aproject.sdk.grpc.SecurityScheme.newBuilder();
                               builderMap.put(key, entry);
                             }
                      -      if (entry instanceof io.a2a.grpc.SecurityScheme) {
                      -        entry = ((io.a2a.grpc.SecurityScheme) entry).toBuilder();
                      +      if (entry instanceof org.a2aproject.sdk.grpc.SecurityScheme) {
                      +        entry = ((org.a2aproject.sdk.grpc.SecurityScheme) entry).toBuilder();
                               builderMap.put(key, entry);
                             }
                      -      return (io.a2a.grpc.SecurityScheme.Builder) entry;
                      +      return (org.a2aproject.sdk.grpc.SecurityScheme.Builder) entry;
                           }
                       
                      -    private java.util.List securityRequirements_ =
                      +    private java.util.List securityRequirements_ =
                             java.util.Collections.emptyList();
                           private void ensureSecurityRequirementsIsMutable() {
                             if (!((bitField0_ & 0x00000100) != 0)) {
                      -        securityRequirements_ = new java.util.ArrayList(securityRequirements_);
                      +        securityRequirements_ = new java.util.ArrayList(securityRequirements_);
                               bitField0_ |= 0x00000100;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> securityRequirementsBuilder_;
                      +        org.a2aproject.sdk.grpc.SecurityRequirement, org.a2aproject.sdk.grpc.SecurityRequirement.Builder, org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder> securityRequirementsBuilder_;
                       
                           /**
                            * 
                      @@ -3023,7 +3023,7 @@ private void ensureSecurityRequirementsIsMutable() {
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public java.util.List getSecurityRequirementsList() {
                      +    public java.util.List getSecurityRequirementsList() {
                             if (securityRequirementsBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(securityRequirements_);
                             } else {
                      @@ -3051,7 +3051,7 @@ public int getSecurityRequirementsCount() {
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) {
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement getSecurityRequirements(int index) {
                             if (securityRequirementsBuilder_ == null) {
                               return securityRequirements_.get(index);
                             } else {
                      @@ -3066,7 +3066,7 @@ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) {
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                           public Builder setSecurityRequirements(
                      -        int index, io.a2a.grpc.SecurityRequirement value) {
                      +        int index, org.a2aproject.sdk.grpc.SecurityRequirement value) {
                             if (securityRequirementsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -3087,7 +3087,7 @@ public Builder setSecurityRequirements(
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                           public Builder setSecurityRequirements(
                      -        int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.SecurityRequirement.Builder builderForValue) {
                             if (securityRequirementsBuilder_ == null) {
                               ensureSecurityRequirementsIsMutable();
                               securityRequirements_.set(index, builderForValue.build());
                      @@ -3104,7 +3104,7 @@ public Builder setSecurityRequirements(
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) {
                      +    public Builder addSecurityRequirements(org.a2aproject.sdk.grpc.SecurityRequirement value) {
                             if (securityRequirementsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -3125,7 +3125,7 @@ public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) {
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                           public Builder addSecurityRequirements(
                      -        int index, io.a2a.grpc.SecurityRequirement value) {
                      +        int index, org.a2aproject.sdk.grpc.SecurityRequirement value) {
                             if (securityRequirementsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -3146,7 +3146,7 @@ public Builder addSecurityRequirements(
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                           public Builder addSecurityRequirements(
                      -        io.a2a.grpc.SecurityRequirement.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.SecurityRequirement.Builder builderForValue) {
                             if (securityRequirementsBuilder_ == null) {
                               ensureSecurityRequirementsIsMutable();
                               securityRequirements_.add(builderForValue.build());
                      @@ -3164,7 +3164,7 @@ public Builder addSecurityRequirements(
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                           public Builder addSecurityRequirements(
                      -        int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.SecurityRequirement.Builder builderForValue) {
                             if (securityRequirementsBuilder_ == null) {
                               ensureSecurityRequirementsIsMutable();
                               securityRequirements_.add(index, builderForValue.build());
                      @@ -3182,7 +3182,7 @@ public Builder addSecurityRequirements(
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                           public Builder addAllSecurityRequirements(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (securityRequirementsBuilder_ == null) {
                               ensureSecurityRequirementsIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -3234,7 +3234,7 @@ public Builder removeSecurityRequirements(int index) {
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder(
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder(
                               int index) {
                             return internalGetSecurityRequirementsFieldBuilder().getBuilder(index);
                           }
                      @@ -3245,7 +3245,7 @@ public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder(
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                      +    public org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                               int index) {
                             if (securityRequirementsBuilder_ == null) {
                               return securityRequirements_.get(index);  } else {
                      @@ -3259,7 +3259,7 @@ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSecurityRequirementsOrBuilderList() {
                             if (securityRequirementsBuilder_ != null) {
                               return securityRequirementsBuilder_.getMessageOrBuilderList();
                      @@ -3274,9 +3274,9 @@ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() {
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() {
                             return internalGetSecurityRequirementsFieldBuilder().addBuilder(
                      -          io.a2a.grpc.SecurityRequirement.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.SecurityRequirement.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -3285,10 +3285,10 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder()
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder(
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder(
                               int index) {
                             return internalGetSecurityRequirementsFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.SecurityRequirement.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.SecurityRequirement.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -3297,16 +3297,16 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder(
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSecurityRequirementsBuilderList() {
                             return internalGetSecurityRequirementsFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> 
                      +        org.a2aproject.sdk.grpc.SecurityRequirement, org.a2aproject.sdk.grpc.SecurityRequirement.Builder, org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder> 
                               internalGetSecurityRequirementsFieldBuilder() {
                             if (securityRequirementsBuilder_ == null) {
                               securityRequirementsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder>(
                      +            org.a2aproject.sdk.grpc.SecurityRequirement, org.a2aproject.sdk.grpc.SecurityRequirement.Builder, org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder>(
                                       securityRequirements_,
                                       ((bitField0_ & 0x00000100) != 0),
                                       getParentForChildren(),
                      @@ -3628,17 +3628,17 @@ public Builder addDefaultOutputModesBytes(
                             return this;
                           }
                       
                      -    private java.util.List skills_ =
                      +    private java.util.List skills_ =
                             java.util.Collections.emptyList();
                           private void ensureSkillsIsMutable() {
                             if (!((bitField0_ & 0x00000800) != 0)) {
                      -        skills_ = new java.util.ArrayList(skills_);
                      +        skills_ = new java.util.ArrayList(skills_);
                               bitField0_ |= 0x00000800;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.AgentSkill, io.a2a.grpc.AgentSkill.Builder, io.a2a.grpc.AgentSkillOrBuilder> skillsBuilder_;
                      +        org.a2aproject.sdk.grpc.AgentSkill, org.a2aproject.sdk.grpc.AgentSkill.Builder, org.a2aproject.sdk.grpc.AgentSkillOrBuilder> skillsBuilder_;
                       
                           /**
                            * 
                      @@ -3649,7 +3649,7 @@ private void ensureSkillsIsMutable() {
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List getSkillsList() {
                      +    public java.util.List getSkillsList() {
                             if (skillsBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(skills_);
                             } else {
                      @@ -3681,7 +3681,7 @@ public int getSkillsCount() {
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentSkill getSkills(int index) {
                      +    public org.a2aproject.sdk.grpc.AgentSkill getSkills(int index) {
                             if (skillsBuilder_ == null) {
                               return skills_.get(index);
                             } else {
                      @@ -3698,7 +3698,7 @@ public io.a2a.grpc.AgentSkill getSkills(int index) {
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setSkills(
                      -        int index, io.a2a.grpc.AgentSkill value) {
                      +        int index, org.a2aproject.sdk.grpc.AgentSkill value) {
                             if (skillsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -3721,7 +3721,7 @@ public Builder setSkills(
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setSkills(
                      -        int index, io.a2a.grpc.AgentSkill.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.AgentSkill.Builder builderForValue) {
                             if (skillsBuilder_ == null) {
                               ensureSkillsIsMutable();
                               skills_.set(index, builderForValue.build());
                      @@ -3740,7 +3740,7 @@ public Builder setSkills(
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder addSkills(io.a2a.grpc.AgentSkill value) {
                      +    public Builder addSkills(org.a2aproject.sdk.grpc.AgentSkill value) {
                             if (skillsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -3763,7 +3763,7 @@ public Builder addSkills(io.a2a.grpc.AgentSkill value) {
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addSkills(
                      -        int index, io.a2a.grpc.AgentSkill value) {
                      +        int index, org.a2aproject.sdk.grpc.AgentSkill value) {
                             if (skillsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -3786,7 +3786,7 @@ public Builder addSkills(
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addSkills(
                      -        io.a2a.grpc.AgentSkill.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.AgentSkill.Builder builderForValue) {
                             if (skillsBuilder_ == null) {
                               ensureSkillsIsMutable();
                               skills_.add(builderForValue.build());
                      @@ -3806,7 +3806,7 @@ public Builder addSkills(
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addSkills(
                      -        int index, io.a2a.grpc.AgentSkill.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.AgentSkill.Builder builderForValue) {
                             if (skillsBuilder_ == null) {
                               ensureSkillsIsMutable();
                               skills_.add(index, builderForValue.build());
                      @@ -3826,7 +3826,7 @@ public Builder addSkills(
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addAllSkills(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (skillsBuilder_ == null) {
                               ensureSkillsIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -3884,7 +3884,7 @@ public Builder removeSkills(int index) {
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentSkill.Builder getSkillsBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentSkill.Builder getSkillsBuilder(
                               int index) {
                             return internalGetSkillsFieldBuilder().getBuilder(index);
                           }
                      @@ -3897,7 +3897,7 @@ public io.a2a.grpc.AgentSkill.Builder getSkillsBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                               int index) {
                             if (skillsBuilder_ == null) {
                               return skills_.get(index);  } else {
                      @@ -3913,7 +3913,7 @@ public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSkillsOrBuilderList() {
                             if (skillsBuilder_ != null) {
                               return skillsBuilder_.getMessageOrBuilderList();
                      @@ -3930,9 +3930,9 @@ public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder() {
                      +    public org.a2aproject.sdk.grpc.AgentSkill.Builder addSkillsBuilder() {
                             return internalGetSkillsFieldBuilder().addBuilder(
                      -          io.a2a.grpc.AgentSkill.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.AgentSkill.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -3943,10 +3943,10 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder() {
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentSkill.Builder addSkillsBuilder(
                               int index) {
                             return internalGetSkillsFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.AgentSkill.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.AgentSkill.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -3957,16 +3957,16 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSkillsBuilderList() {
                             return internalGetSkillsFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.AgentSkill, io.a2a.grpc.AgentSkill.Builder, io.a2a.grpc.AgentSkillOrBuilder> 
                      +        org.a2aproject.sdk.grpc.AgentSkill, org.a2aproject.sdk.grpc.AgentSkill.Builder, org.a2aproject.sdk.grpc.AgentSkillOrBuilder> 
                               internalGetSkillsFieldBuilder() {
                             if (skillsBuilder_ == null) {
                               skillsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.AgentSkill, io.a2a.grpc.AgentSkill.Builder, io.a2a.grpc.AgentSkillOrBuilder>(
                      +            org.a2aproject.sdk.grpc.AgentSkill, org.a2aproject.sdk.grpc.AgentSkill.Builder, org.a2aproject.sdk.grpc.AgentSkillOrBuilder>(
                                       skills_,
                                       ((bitField0_ & 0x00000800) != 0),
                                       getParentForChildren(),
                      @@ -3976,17 +3976,17 @@ public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder(
                             return skillsBuilder_;
                           }
                       
                      -    private java.util.List signatures_ =
                      +    private java.util.List signatures_ =
                             java.util.Collections.emptyList();
                           private void ensureSignaturesIsMutable() {
                             if (!((bitField0_ & 0x00001000) != 0)) {
                      -        signatures_ = new java.util.ArrayList(signatures_);
                      +        signatures_ = new java.util.ArrayList(signatures_);
                               bitField0_ |= 0x00001000;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.AgentCardSignature, io.a2a.grpc.AgentCardSignature.Builder, io.a2a.grpc.AgentCardSignatureOrBuilder> signaturesBuilder_;
                      +        org.a2aproject.sdk.grpc.AgentCardSignature, org.a2aproject.sdk.grpc.AgentCardSignature.Builder, org.a2aproject.sdk.grpc.AgentCardSignatureOrBuilder> signaturesBuilder_;
                       
                           /**
                            * 
                      @@ -3995,7 +3995,7 @@ private void ensureSignaturesIsMutable() {
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public java.util.List getSignaturesList() {
                      +    public java.util.List getSignaturesList() {
                             if (signaturesBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(signatures_);
                             } else {
                      @@ -4023,7 +4023,7 @@ public int getSignaturesCount() {
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public io.a2a.grpc.AgentCardSignature getSignatures(int index) {
                      +    public org.a2aproject.sdk.grpc.AgentCardSignature getSignatures(int index) {
                             if (signaturesBuilder_ == null) {
                               return signatures_.get(index);
                             } else {
                      @@ -4038,7 +4038,7 @@ public io.a2a.grpc.AgentCardSignature getSignatures(int index) {
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                           public Builder setSignatures(
                      -        int index, io.a2a.grpc.AgentCardSignature value) {
                      +        int index, org.a2aproject.sdk.grpc.AgentCardSignature value) {
                             if (signaturesBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -4059,7 +4059,7 @@ public Builder setSignatures(
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                           public Builder setSignatures(
                      -        int index, io.a2a.grpc.AgentCardSignature.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.AgentCardSignature.Builder builderForValue) {
                             if (signaturesBuilder_ == null) {
                               ensureSignaturesIsMutable();
                               signatures_.set(index, builderForValue.build());
                      @@ -4076,7 +4076,7 @@ public Builder setSignatures(
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public Builder addSignatures(io.a2a.grpc.AgentCardSignature value) {
                      +    public Builder addSignatures(org.a2aproject.sdk.grpc.AgentCardSignature value) {
                             if (signaturesBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -4097,7 +4097,7 @@ public Builder addSignatures(io.a2a.grpc.AgentCardSignature value) {
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                           public Builder addSignatures(
                      -        int index, io.a2a.grpc.AgentCardSignature value) {
                      +        int index, org.a2aproject.sdk.grpc.AgentCardSignature value) {
                             if (signaturesBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -4118,7 +4118,7 @@ public Builder addSignatures(
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                           public Builder addSignatures(
                      -        io.a2a.grpc.AgentCardSignature.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.AgentCardSignature.Builder builderForValue) {
                             if (signaturesBuilder_ == null) {
                               ensureSignaturesIsMutable();
                               signatures_.add(builderForValue.build());
                      @@ -4136,7 +4136,7 @@ public Builder addSignatures(
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                           public Builder addSignatures(
                      -        int index, io.a2a.grpc.AgentCardSignature.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.AgentCardSignature.Builder builderForValue) {
                             if (signaturesBuilder_ == null) {
                               ensureSignaturesIsMutable();
                               signatures_.add(index, builderForValue.build());
                      @@ -4154,7 +4154,7 @@ public Builder addSignatures(
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                           public Builder addAllSignatures(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (signaturesBuilder_ == null) {
                               ensureSignaturesIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -4206,7 +4206,7 @@ public Builder removeSignatures(int index) {
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public io.a2a.grpc.AgentCardSignature.Builder getSignaturesBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentCardSignature.Builder getSignaturesBuilder(
                               int index) {
                             return internalGetSignaturesFieldBuilder().getBuilder(index);
                           }
                      @@ -4217,7 +4217,7 @@ public io.a2a.grpc.AgentCardSignature.Builder getSignaturesBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder(
                               int index) {
                             if (signaturesBuilder_ == null) {
                               return signatures_.get(index);  } else {
                      @@ -4231,7 +4231,7 @@ public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSignaturesOrBuilderList() {
                             if (signaturesBuilder_ != null) {
                               return signaturesBuilder_.getMessageOrBuilderList();
                      @@ -4246,9 +4246,9 @@ public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder() {
                      +    public org.a2aproject.sdk.grpc.AgentCardSignature.Builder addSignaturesBuilder() {
                             return internalGetSignaturesFieldBuilder().addBuilder(
                      -          io.a2a.grpc.AgentCardSignature.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.AgentCardSignature.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -4257,10 +4257,10 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder() {
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder(
                      +    public org.a2aproject.sdk.grpc.AgentCardSignature.Builder addSignaturesBuilder(
                               int index) {
                             return internalGetSignaturesFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.AgentCardSignature.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.AgentCardSignature.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -4269,16 +4269,16 @@ public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder(
                            *
                            * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSignaturesBuilderList() {
                             return internalGetSignaturesFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.AgentCardSignature, io.a2a.grpc.AgentCardSignature.Builder, io.a2a.grpc.AgentCardSignatureOrBuilder> 
                      +        org.a2aproject.sdk.grpc.AgentCardSignature, org.a2aproject.sdk.grpc.AgentCardSignature.Builder, org.a2aproject.sdk.grpc.AgentCardSignatureOrBuilder> 
                               internalGetSignaturesFieldBuilder() {
                             if (signaturesBuilder_ == null) {
                               signaturesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.AgentCardSignature, io.a2a.grpc.AgentCardSignature.Builder, io.a2a.grpc.AgentCardSignatureOrBuilder>(
                      +            org.a2aproject.sdk.grpc.AgentCardSignature, org.a2aproject.sdk.grpc.AgentCardSignature.Builder, org.a2aproject.sdk.grpc.AgentCardSignatureOrBuilder>(
                                       signatures_,
                                       ((bitField0_ & 0x00001000) != 0),
                                       getParentForChildren(),
                      @@ -4395,12 +4395,12 @@ public Builder setIconUrlBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentCard)
                      -  private static final io.a2a.grpc.AgentCard DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AgentCard DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AgentCard();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AgentCard();
                         }
                       
                      -  public static io.a2a.grpc.AgentCard getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AgentCard getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -4436,7 +4436,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentCard getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AgentCard getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardOrBuilder.java
                      similarity index 88%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardOrBuilder.java
                      index 8e19c6bd8..bfb01cfc9 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AgentCardOrBuilder extends
                      @@ -63,7 +63,7 @@ public interface AgentCardOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSupportedInterfacesList();
                         /**
                          * 
                      @@ -72,7 +72,7 @@ public interface AgentCardOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.AgentInterface getSupportedInterfaces(int index);
                      +  org.a2aproject.sdk.grpc.AgentInterface getSupportedInterfaces(int index);
                         /**
                          * 
                          * Ordered list of supported interfaces. The first entry is preferred.
                      @@ -88,7 +88,7 @@ public interface AgentCardOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSupportedInterfacesOrBuilderList();
                         /**
                          * 
                      @@ -97,7 +97,7 @@ public interface AgentCardOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.AgentInterface supported_interfaces = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                      +  org.a2aproject.sdk.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                             int index);
                       
                         /**
                      @@ -117,7 +117,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                          * .lf.a2a.v1.AgentProvider provider = 4;
                          * @return The provider.
                          */
                      -  io.a2a.grpc.AgentProvider getProvider();
                      +  org.a2aproject.sdk.grpc.AgentProvider getProvider();
                         /**
                          * 
                          * The service provider of the agent.
                      @@ -125,7 +125,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                          *
                          * .lf.a2a.v1.AgentProvider provider = 4;
                          */
                      -  io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder();
                      +  org.a2aproject.sdk.grpc.AgentProviderOrBuilder getProviderOrBuilder();
                       
                         /**
                          * 
                      @@ -195,7 +195,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                          * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                          * @return The capabilities.
                          */
                      -  io.a2a.grpc.AgentCapabilities getCapabilities();
                      +  org.a2aproject.sdk.grpc.AgentCapabilities getCapabilities();
                         /**
                          * 
                          * A2A Capability set supported by the agent.
                      @@ -203,7 +203,7 @@ io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder(
                          *
                          * .lf.a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder();
                      +  org.a2aproject.sdk.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder();
                       
                         /**
                          * 
                      @@ -226,7 +226,7 @@ boolean containsSecuritySchemes(
                          * Use {@link #getSecuritySchemesMap()} instead.
                          */
                         @java.lang.Deprecated
                      -  java.util.Map
                      +  java.util.Map
                         getSecuritySchemes();
                         /**
                          * 
                      @@ -235,7 +235,7 @@ boolean containsSecuritySchemes(
                          *
                          * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                          */
                      -  java.util.Map
                      +  java.util.Map
                         getSecuritySchemesMap();
                         /**
                          * 
                      @@ -245,10 +245,10 @@ boolean containsSecuritySchemes(
                          * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                          */
                         /* nullable */
                      -io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault(
                      +org.a2aproject.sdk.grpc.SecurityScheme getSecuritySchemesOrDefault(
                             java.lang.String key,
                             /* nullable */
                      -io.a2a.grpc.SecurityScheme defaultValue);
                      +org.a2aproject.sdk.grpc.SecurityScheme defaultValue);
                         /**
                          * 
                          * The security scheme details used for authenticating with this agent.
                      @@ -256,7 +256,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault(
                          *
                          * map<string, .lf.a2a.v1.SecurityScheme> security_schemes = 8;
                          */
                      -  io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                      +  org.a2aproject.sdk.grpc.SecurityScheme getSecuritySchemesOrThrow(
                             java.lang.String key);
                       
                         /**
                      @@ -266,7 +266,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                          *
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSecurityRequirementsList();
                         /**
                          * 
                      @@ -275,7 +275,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                          *
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                          */
                      -  io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index);
                      +  org.a2aproject.sdk.grpc.SecurityRequirement getSecurityRequirements(int index);
                         /**
                          * 
                          * Security requirements for contacting the agent.
                      @@ -291,7 +291,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                          *
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSecurityRequirementsOrBuilderList();
                         /**
                          * 
                      @@ -300,7 +300,7 @@ io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow(
                          *
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 9;
                          */
                      -  io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                      +  org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                             int index);
                       
                         /**
                      @@ -402,7 +402,7 @@ io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSkillsList();
                         /**
                          * 
                      @@ -413,7 +413,7 @@ io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.AgentSkill getSkills(int index);
                      +  org.a2aproject.sdk.grpc.AgentSkill getSkills(int index);
                         /**
                          * 
                          * Skills represent the abilities of an agent.
                      @@ -433,7 +433,7 @@ io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSkillsOrBuilderList();
                         /**
                          * 
                      @@ -444,7 +444,7 @@ io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                      +  org.a2aproject.sdk.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                             int index);
                       
                         /**
                      @@ -454,7 +454,7 @@ io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSignaturesList();
                         /**
                          * 
                      @@ -463,7 +463,7 @@ io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                          */
                      -  io.a2a.grpc.AgentCardSignature getSignatures(int index);
                      +  org.a2aproject.sdk.grpc.AgentCardSignature getSignatures(int index);
                         /**
                          * 
                          * JSON Web Signatures computed for this `AgentCard`.
                      @@ -479,7 +479,7 @@ io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSignaturesOrBuilderList();
                         /**
                          * 
                      @@ -488,7 +488,7 @@ io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.AgentCardSignature signatures = 13;
                          */
                      -  io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder(
                      +  org.a2aproject.sdk.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder(
                             int index);
                       
                         /**
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardSignature.java
                      similarity index 89%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardSignature.java
                      index 567d94c50..99dd0b33b 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardSignature.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -39,15 +39,15 @@ private AgentCardSignature() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AgentCardSignature.class, io.a2a.grpc.AgentCardSignature.Builder.class);
                      +            org.a2aproject.sdk.grpc.AgentCardSignature.class, org.a2aproject.sdk.grpc.AgentCardSignature.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -241,10 +241,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AgentCardSignature)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AgentCardSignature)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AgentCardSignature other = (io.a2a.grpc.AgentCardSignature) obj;
                      +    org.a2aproject.sdk.grpc.AgentCardSignature other = (org.a2aproject.sdk.grpc.AgentCardSignature) obj;
                       
                           if (!getProtected()
                               .equals(other.getProtected())) return false;
                      @@ -279,44 +279,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -324,26 +324,26 @@ public static io.a2a.grpc.AgentCardSignature parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AgentCardSignature parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AgentCardSignature parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentCardSignature parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -356,7 +356,7 @@ public static io.a2a.grpc.AgentCardSignature parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AgentCardSignature prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AgentCardSignature prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -382,21 +382,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentCardSignature)
                      -      io.a2a.grpc.AgentCardSignatureOrBuilder {
                      +      org.a2aproject.sdk.grpc.AgentCardSignatureOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AgentCardSignature.class, io.a2a.grpc.AgentCardSignature.Builder.class);
                      +              org.a2aproject.sdk.grpc.AgentCardSignature.class, org.a2aproject.sdk.grpc.AgentCardSignature.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AgentCardSignature.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AgentCardSignature.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -429,17 +429,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentCardSignature_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCardSignature getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AgentCardSignature.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AgentCardSignature getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AgentCardSignature.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCardSignature build() {
                      -      io.a2a.grpc.AgentCardSignature result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AgentCardSignature build() {
                      +      org.a2aproject.sdk.grpc.AgentCardSignature result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -447,14 +447,14 @@ public io.a2a.grpc.AgentCardSignature build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentCardSignature buildPartial() {
                      -      io.a2a.grpc.AgentCardSignature result = new io.a2a.grpc.AgentCardSignature(this);
                      +    public org.a2aproject.sdk.grpc.AgentCardSignature buildPartial() {
                      +      org.a2aproject.sdk.grpc.AgentCardSignature result = new org.a2aproject.sdk.grpc.AgentCardSignature(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AgentCardSignature result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AgentCardSignature result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.protected_ = protected_;
                      @@ -474,16 +474,16 @@ private void buildPartial0(io.a2a.grpc.AgentCardSignature result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AgentCardSignature) {
                      -        return mergeFrom((io.a2a.grpc.AgentCardSignature)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AgentCardSignature) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AgentCardSignature)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AgentCardSignature other) {
                      -      if (other == io.a2a.grpc.AgentCardSignature.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AgentCardSignature other) {
                      +      if (other == org.a2aproject.sdk.grpc.AgentCardSignature.getDefaultInstance()) return this;
                             if (!other.getProtected().isEmpty()) {
                               protected_ = other.protected_;
                               bitField0_ |= 0x00000001;
                      @@ -917,12 +917,12 @@ public com.google.protobuf.StructOrBuilder getHeaderOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentCardSignature)
                      -  private static final io.a2a.grpc.AgentCardSignature DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AgentCardSignature DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AgentCardSignature();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AgentCardSignature();
                         }
                       
                      -  public static io.a2a.grpc.AgentCardSignature getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AgentCardSignature getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -958,7 +958,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentCardSignature getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AgentCardSignature getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardSignatureOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardSignatureOrBuilder.java
                      index ecd7ff95d..cf7c6ae73 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentCardSignatureOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AgentCardSignatureOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentExtension.java
                      similarity index 90%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentExtension.java
                      index e623157f3..1c2b6cb87 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentExtension.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private AgentExtension() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AgentExtension.class, io.a2a.grpc.AgentExtension.Builder.class);
                      +            org.a2aproject.sdk.grpc.AgentExtension.class, org.a2aproject.sdk.grpc.AgentExtension.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -256,10 +256,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AgentExtension)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AgentExtension)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AgentExtension other = (io.a2a.grpc.AgentExtension) obj;
                      +    org.a2aproject.sdk.grpc.AgentExtension other = (org.a2aproject.sdk.grpc.AgentExtension) obj;
                       
                           if (!getUri()
                               .equals(other.getUri())) return false;
                      @@ -299,44 +299,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AgentExtension parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -344,26 +344,26 @@ public static io.a2a.grpc.AgentExtension parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AgentExtension parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AgentExtension parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentExtension parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentExtension parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -376,7 +376,7 @@ public static io.a2a.grpc.AgentExtension parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AgentExtension prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AgentExtension prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -401,21 +401,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentExtension)
                      -      io.a2a.grpc.AgentExtensionOrBuilder {
                      +      org.a2aproject.sdk.grpc.AgentExtensionOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AgentExtension.class, io.a2a.grpc.AgentExtension.Builder.class);
                      +              org.a2aproject.sdk.grpc.AgentExtension.class, org.a2aproject.sdk.grpc.AgentExtension.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AgentExtension.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AgentExtension.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -449,17 +449,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentExtension_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentExtension getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AgentExtension.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AgentExtension getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AgentExtension.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentExtension build() {
                      -      io.a2a.grpc.AgentExtension result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AgentExtension build() {
                      +      org.a2aproject.sdk.grpc.AgentExtension result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -467,14 +467,14 @@ public io.a2a.grpc.AgentExtension build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentExtension buildPartial() {
                      -      io.a2a.grpc.AgentExtension result = new io.a2a.grpc.AgentExtension(this);
                      +    public org.a2aproject.sdk.grpc.AgentExtension buildPartial() {
                      +      org.a2aproject.sdk.grpc.AgentExtension result = new org.a2aproject.sdk.grpc.AgentExtension(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AgentExtension result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AgentExtension result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.uri_ = uri_;
                      @@ -497,16 +497,16 @@ private void buildPartial0(io.a2a.grpc.AgentExtension result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AgentExtension) {
                      -        return mergeFrom((io.a2a.grpc.AgentExtension)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AgentExtension) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AgentExtension)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AgentExtension other) {
                      -      if (other == io.a2a.grpc.AgentExtension.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AgentExtension other) {
                      +      if (other == org.a2aproject.sdk.grpc.AgentExtension.getDefaultInstance()) return this;
                             if (!other.getUri().isEmpty()) {
                               uri_ = other.uri_;
                               bitField0_ |= 0x00000001;
                      @@ -977,12 +977,12 @@ public com.google.protobuf.StructOrBuilder getParamsOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentExtension)
                      -  private static final io.a2a.grpc.AgentExtension DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AgentExtension DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AgentExtension();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AgentExtension();
                         }
                       
                      -  public static io.a2a.grpc.AgentExtension getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AgentExtension getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1018,7 +1018,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentExtension getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AgentExtension getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentExtensionOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentExtensionOrBuilder.java
                      index 42cb9594b..079b6e587 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentExtensionOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AgentExtensionOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentInterface.java
                      similarity index 91%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentInterface.java
                      index 4d6fb828e..0e6cf31bd 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentInterface.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -41,15 +41,15 @@ private AgentInterface() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AgentInterface.class, io.a2a.grpc.AgentInterface.Builder.class);
                      +            org.a2aproject.sdk.grpc.AgentInterface.class, org.a2aproject.sdk.grpc.AgentInterface.Builder.class);
                         }
                       
                         public static final int URL_FIELD_NUMBER = 1;
                      @@ -307,10 +307,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AgentInterface)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AgentInterface)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AgentInterface other = (io.a2a.grpc.AgentInterface) obj;
                      +    org.a2aproject.sdk.grpc.AgentInterface other = (org.a2aproject.sdk.grpc.AgentInterface) obj;
                       
                           if (!getUrl()
                               .equals(other.getUrl())) return false;
                      @@ -344,44 +344,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AgentInterface parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -389,26 +389,26 @@ public static io.a2a.grpc.AgentInterface parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AgentInterface parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AgentInterface parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentInterface parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentInterface parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -421,7 +421,7 @@ public static io.a2a.grpc.AgentInterface parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AgentInterface prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AgentInterface prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -447,21 +447,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentInterface)
                      -      io.a2a.grpc.AgentInterfaceOrBuilder {
                      +      org.a2aproject.sdk.grpc.AgentInterfaceOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AgentInterface.class, io.a2a.grpc.AgentInterface.Builder.class);
                      +              org.a2aproject.sdk.grpc.AgentInterface.class, org.a2aproject.sdk.grpc.AgentInterface.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AgentInterface.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AgentInterface.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -485,17 +485,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentInterface_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentInterface getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AgentInterface.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AgentInterface getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AgentInterface.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentInterface build() {
                      -      io.a2a.grpc.AgentInterface result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AgentInterface build() {
                      +      org.a2aproject.sdk.grpc.AgentInterface result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -503,14 +503,14 @@ public io.a2a.grpc.AgentInterface build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentInterface buildPartial() {
                      -      io.a2a.grpc.AgentInterface result = new io.a2a.grpc.AgentInterface(this);
                      +    public org.a2aproject.sdk.grpc.AgentInterface buildPartial() {
                      +      org.a2aproject.sdk.grpc.AgentInterface result = new org.a2aproject.sdk.grpc.AgentInterface(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AgentInterface result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AgentInterface result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.url_ = url_;
                      @@ -528,16 +528,16 @@ private void buildPartial0(io.a2a.grpc.AgentInterface result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AgentInterface) {
                      -        return mergeFrom((io.a2a.grpc.AgentInterface)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AgentInterface) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AgentInterface)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AgentInterface other) {
                      -      if (other == io.a2a.grpc.AgentInterface.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AgentInterface other) {
                      +      if (other == org.a2aproject.sdk.grpc.AgentInterface.getDefaultInstance()) return this;
                             if (!other.getUrl().isEmpty()) {
                               url_ = other.url_;
                               bitField0_ |= 0x00000001;
                      @@ -1018,12 +1018,12 @@ public Builder setProtocolVersionBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentInterface)
                      -  private static final io.a2a.grpc.AgentInterface DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AgentInterface DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AgentInterface();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AgentInterface();
                         }
                       
                      -  public static io.a2a.grpc.AgentInterface getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AgentInterface getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1059,7 +1059,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentInterface getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AgentInterface getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentInterfaceOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentInterfaceOrBuilder.java
                      index 3f31901c7..f53b83917 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentInterfaceOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AgentInterfaceOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentProvider.java
                      similarity index 86%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentProvider.java
                      index dc484c549..17c348a6d 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentProvider.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private AgentProvider() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AgentProvider.class, io.a2a.grpc.AgentProvider.Builder.class);
                      +            org.a2aproject.sdk.grpc.AgentProvider.class, org.a2aproject.sdk.grpc.AgentProvider.Builder.class);
                         }
                       
                         public static final int URL_FIELD_NUMBER = 1;
                      @@ -192,10 +192,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AgentProvider)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AgentProvider)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AgentProvider other = (io.a2a.grpc.AgentProvider) obj;
                      +    org.a2aproject.sdk.grpc.AgentProvider other = (org.a2aproject.sdk.grpc.AgentProvider) obj;
                       
                           if (!getUrl()
                               .equals(other.getUrl())) return false;
                      @@ -221,44 +221,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AgentProvider parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -266,26 +266,26 @@ public static io.a2a.grpc.AgentProvider parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AgentProvider parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AgentProvider parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentProvider parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentProvider parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -298,7 +298,7 @@ public static io.a2a.grpc.AgentProvider parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AgentProvider prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AgentProvider prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -323,21 +323,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentProvider)
                      -      io.a2a.grpc.AgentProviderOrBuilder {
                      +      org.a2aproject.sdk.grpc.AgentProviderOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AgentProvider.class, io.a2a.grpc.AgentProvider.Builder.class);
                      +              org.a2aproject.sdk.grpc.AgentProvider.class, org.a2aproject.sdk.grpc.AgentProvider.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AgentProvider.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AgentProvider.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -359,17 +359,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentProvider_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentProvider getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AgentProvider.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AgentProvider getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AgentProvider.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentProvider build() {
                      -      io.a2a.grpc.AgentProvider result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AgentProvider build() {
                      +      org.a2aproject.sdk.grpc.AgentProvider result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -377,14 +377,14 @@ public io.a2a.grpc.AgentProvider build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentProvider buildPartial() {
                      -      io.a2a.grpc.AgentProvider result = new io.a2a.grpc.AgentProvider(this);
                      +    public org.a2aproject.sdk.grpc.AgentProvider buildPartial() {
                      +      org.a2aproject.sdk.grpc.AgentProvider result = new org.a2aproject.sdk.grpc.AgentProvider(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AgentProvider result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AgentProvider result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.url_ = url_;
                      @@ -396,16 +396,16 @@ private void buildPartial0(io.a2a.grpc.AgentProvider result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AgentProvider) {
                      -        return mergeFrom((io.a2a.grpc.AgentProvider)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AgentProvider) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AgentProvider)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AgentProvider other) {
                      -      if (other == io.a2a.grpc.AgentProvider.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AgentProvider other) {
                      +      if (other == org.a2aproject.sdk.grpc.AgentProvider.getDefaultInstance()) return this;
                             if (!other.getUrl().isEmpty()) {
                               url_ = other.url_;
                               bitField0_ |= 0x00000001;
                      @@ -667,12 +667,12 @@ public Builder setOrganizationBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentProvider)
                      -  private static final io.a2a.grpc.AgentProvider DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AgentProvider DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AgentProvider();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AgentProvider();
                         }
                       
                      -  public static io.a2a.grpc.AgentProvider getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AgentProvider getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -708,7 +708,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentProvider getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AgentProvider getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentProviderOrBuilder.java
                      similarity index 97%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentProviderOrBuilder.java
                      index cfff51140..412440a76 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentProviderOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AgentProviderOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentSkill.java
                      similarity index 91%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentSkill.java
                      index 304775e4c..8f31cfa7e 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentSkill.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -48,15 +48,15 @@ private AgentSkill() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AgentSkill.class, io.a2a.grpc.AgentSkill.Builder.class);
                      +            org.a2aproject.sdk.grpc.AgentSkill.class, org.a2aproject.sdk.grpc.AgentSkill.Builder.class);
                         }
                       
                         public static final int ID_FIELD_NUMBER = 1;
                      @@ -414,7 +414,7 @@ public java.lang.String getOutputModes(int index) {
                       
                         public static final int SECURITY_REQUIREMENTS_FIELD_NUMBER = 8;
                         @SuppressWarnings("serial")
                      -  private java.util.List securityRequirements_;
                      +  private java.util.List securityRequirements_;
                         /**
                          * 
                          * Security schemes necessary for this skill.
                      @@ -423,7 +423,7 @@ public java.lang.String getOutputModes(int index) {
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                          */
                         @java.lang.Override
                      -  public java.util.List getSecurityRequirementsList() {
                      +  public java.util.List getSecurityRequirementsList() {
                           return securityRequirements_;
                         }
                         /**
                      @@ -434,7 +434,7 @@ public java.util.List getSecurityRequirementsLi
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getSecurityRequirementsOrBuilderList() {
                           return securityRequirements_;
                         }
                      @@ -457,7 +457,7 @@ public int getSecurityRequirementsCount() {
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) {
                      +  public org.a2aproject.sdk.grpc.SecurityRequirement getSecurityRequirements(int index) {
                           return securityRequirements_.get(index);
                         }
                         /**
                      @@ -468,7 +468,7 @@ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) {
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                      +  public org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                             int index) {
                           return securityRequirements_.get(index);
                         }
                      @@ -575,10 +575,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AgentSkill)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AgentSkill)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AgentSkill other = (io.a2a.grpc.AgentSkill) obj;
                      +    org.a2aproject.sdk.grpc.AgentSkill other = (org.a2aproject.sdk.grpc.AgentSkill) obj;
                       
                           if (!getId()
                               .equals(other.getId())) return false;
                      @@ -638,44 +638,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AgentSkill parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -683,26 +683,26 @@ public static io.a2a.grpc.AgentSkill parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AgentSkill parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AgentSkill parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AgentSkill parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AgentSkill parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -715,7 +715,7 @@ public static io.a2a.grpc.AgentSkill parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AgentSkill prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AgentSkill prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -740,21 +740,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AgentSkill)
                      -      io.a2a.grpc.AgentSkillOrBuilder {
                      +      org.a2aproject.sdk.grpc.AgentSkillOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AgentSkill.class, io.a2a.grpc.AgentSkill.Builder.class);
                      +              org.a2aproject.sdk.grpc.AgentSkill.class, org.a2aproject.sdk.grpc.AgentSkill.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AgentSkill.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AgentSkill.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -792,17 +792,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AgentSkill_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentSkill getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AgentSkill.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AgentSkill getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AgentSkill.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentSkill build() {
                      -      io.a2a.grpc.AgentSkill result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AgentSkill build() {
                      +      org.a2aproject.sdk.grpc.AgentSkill result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -810,15 +810,15 @@ public io.a2a.grpc.AgentSkill build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AgentSkill buildPartial() {
                      -      io.a2a.grpc.AgentSkill result = new io.a2a.grpc.AgentSkill(this);
                      +    public org.a2aproject.sdk.grpc.AgentSkill buildPartial() {
                      +      org.a2aproject.sdk.grpc.AgentSkill result = new org.a2aproject.sdk.grpc.AgentSkill(this);
                             buildPartialRepeatedFields(result);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartialRepeatedFields(io.a2a.grpc.AgentSkill result) {
                      +    private void buildPartialRepeatedFields(org.a2aproject.sdk.grpc.AgentSkill result) {
                             if (securityRequirementsBuilder_ == null) {
                               if (((bitField0_ & 0x00000080) != 0)) {
                                 securityRequirements_ = java.util.Collections.unmodifiableList(securityRequirements_);
                      @@ -830,7 +830,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.AgentSkill result) {
                             }
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AgentSkill result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AgentSkill result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.id_ = id_;
                      @@ -861,16 +861,16 @@ private void buildPartial0(io.a2a.grpc.AgentSkill result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AgentSkill) {
                      -        return mergeFrom((io.a2a.grpc.AgentSkill)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AgentSkill) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AgentSkill)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AgentSkill other) {
                      -      if (other == io.a2a.grpc.AgentSkill.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AgentSkill other) {
                      +      if (other == org.a2aproject.sdk.grpc.AgentSkill.getDefaultInstance()) return this;
                             if (!other.getId().isEmpty()) {
                               id_ = other.id_;
                               bitField0_ |= 0x00000001;
                      @@ -1018,9 +1018,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 58
                                   case 66: {
                      -              io.a2a.grpc.SecurityRequirement m =
                      +              org.a2aproject.sdk.grpc.SecurityRequirement m =
                                         input.readMessage(
                      -                      io.a2a.grpc.SecurityRequirement.parser(),
                      +                      org.a2aproject.sdk.grpc.SecurityRequirement.parser(),
                                             extensionRegistry);
                                     if (securityRequirementsBuilder_ == null) {
                                       ensureSecurityRequirementsIsMutable();
                      @@ -1911,17 +1911,17 @@ public Builder addOutputModesBytes(
                             return this;
                           }
                       
                      -    private java.util.List securityRequirements_ =
                      +    private java.util.List securityRequirements_ =
                             java.util.Collections.emptyList();
                           private void ensureSecurityRequirementsIsMutable() {
                             if (!((bitField0_ & 0x00000080) != 0)) {
                      -        securityRequirements_ = new java.util.ArrayList(securityRequirements_);
                      +        securityRequirements_ = new java.util.ArrayList(securityRequirements_);
                               bitField0_ |= 0x00000080;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> securityRequirementsBuilder_;
                      +        org.a2aproject.sdk.grpc.SecurityRequirement, org.a2aproject.sdk.grpc.SecurityRequirement.Builder, org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder> securityRequirementsBuilder_;
                       
                           /**
                            * 
                      @@ -1930,7 +1930,7 @@ private void ensureSecurityRequirementsIsMutable() {
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public java.util.List getSecurityRequirementsList() {
                      +    public java.util.List getSecurityRequirementsList() {
                             if (securityRequirementsBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(securityRequirements_);
                             } else {
                      @@ -1958,7 +1958,7 @@ public int getSecurityRequirementsCount() {
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) {
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement getSecurityRequirements(int index) {
                             if (securityRequirementsBuilder_ == null) {
                               return securityRequirements_.get(index);
                             } else {
                      @@ -1973,7 +1973,7 @@ public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) {
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                           public Builder setSecurityRequirements(
                      -        int index, io.a2a.grpc.SecurityRequirement value) {
                      +        int index, org.a2aproject.sdk.grpc.SecurityRequirement value) {
                             if (securityRequirementsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1994,7 +1994,7 @@ public Builder setSecurityRequirements(
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                           public Builder setSecurityRequirements(
                      -        int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.SecurityRequirement.Builder builderForValue) {
                             if (securityRequirementsBuilder_ == null) {
                               ensureSecurityRequirementsIsMutable();
                               securityRequirements_.set(index, builderForValue.build());
                      @@ -2011,7 +2011,7 @@ public Builder setSecurityRequirements(
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) {
                      +    public Builder addSecurityRequirements(org.a2aproject.sdk.grpc.SecurityRequirement value) {
                             if (securityRequirementsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -2032,7 +2032,7 @@ public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) {
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                           public Builder addSecurityRequirements(
                      -        int index, io.a2a.grpc.SecurityRequirement value) {
                      +        int index, org.a2aproject.sdk.grpc.SecurityRequirement value) {
                             if (securityRequirementsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -2053,7 +2053,7 @@ public Builder addSecurityRequirements(
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                           public Builder addSecurityRequirements(
                      -        io.a2a.grpc.SecurityRequirement.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.SecurityRequirement.Builder builderForValue) {
                             if (securityRequirementsBuilder_ == null) {
                               ensureSecurityRequirementsIsMutable();
                               securityRequirements_.add(builderForValue.build());
                      @@ -2071,7 +2071,7 @@ public Builder addSecurityRequirements(
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                           public Builder addSecurityRequirements(
                      -        int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.SecurityRequirement.Builder builderForValue) {
                             if (securityRequirementsBuilder_ == null) {
                               ensureSecurityRequirementsIsMutable();
                               securityRequirements_.add(index, builderForValue.build());
                      @@ -2089,7 +2089,7 @@ public Builder addSecurityRequirements(
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                           public Builder addAllSecurityRequirements(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (securityRequirementsBuilder_ == null) {
                               ensureSecurityRequirementsIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -2141,7 +2141,7 @@ public Builder removeSecurityRequirements(int index) {
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder(
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder(
                               int index) {
                             return internalGetSecurityRequirementsFieldBuilder().getBuilder(index);
                           }
                      @@ -2152,7 +2152,7 @@ public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder(
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                      +    public org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                               int index) {
                             if (securityRequirementsBuilder_ == null) {
                               return securityRequirements_.get(index);  } else {
                      @@ -2166,7 +2166,7 @@ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSecurityRequirementsOrBuilderList() {
                             if (securityRequirementsBuilder_ != null) {
                               return securityRequirementsBuilder_.getMessageOrBuilderList();
                      @@ -2181,9 +2181,9 @@ public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() {
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() {
                             return internalGetSecurityRequirementsFieldBuilder().addBuilder(
                      -          io.a2a.grpc.SecurityRequirement.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.SecurityRequirement.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -2192,10 +2192,10 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder()
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder(
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder(
                               int index) {
                             return internalGetSecurityRequirementsFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.SecurityRequirement.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.SecurityRequirement.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -2204,16 +2204,16 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder(
                            *
                            * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getSecurityRequirementsBuilderList() {
                             return internalGetSecurityRequirementsFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> 
                      +        org.a2aproject.sdk.grpc.SecurityRequirement, org.a2aproject.sdk.grpc.SecurityRequirement.Builder, org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder> 
                               internalGetSecurityRequirementsFieldBuilder() {
                             if (securityRequirementsBuilder_ == null) {
                               securityRequirementsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder>(
                      +            org.a2aproject.sdk.grpc.SecurityRequirement, org.a2aproject.sdk.grpc.SecurityRequirement.Builder, org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder>(
                                       securityRequirements_,
                                       ((bitField0_ & 0x00000080) != 0),
                                       getParentForChildren(),
                      @@ -2227,12 +2227,12 @@ public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AgentSkill)
                      -  private static final io.a2a.grpc.AgentSkill DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AgentSkill DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AgentSkill();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AgentSkill();
                         }
                       
                      -  public static io.a2a.grpc.AgentSkill getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AgentSkill getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -2268,7 +2268,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AgentSkill getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AgentSkill getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentSkillOrBuilder.java
                      similarity index 95%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentSkillOrBuilder.java
                      index c982233c5..7893b1bf9 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AgentSkillOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AgentSkillOrBuilder extends
                      @@ -241,7 +241,7 @@ public interface AgentSkillOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSecurityRequirementsList();
                         /**
                          * 
                      @@ -250,7 +250,7 @@ public interface AgentSkillOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                          */
                      -  io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index);
                      +  org.a2aproject.sdk.grpc.SecurityRequirement getSecurityRequirements(int index);
                         /**
                          * 
                          * Security schemes necessary for this skill.
                      @@ -266,7 +266,7 @@ public interface AgentSkillOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getSecurityRequirementsOrBuilderList();
                         /**
                          * 
                      @@ -275,6 +275,6 @@ public interface AgentSkillOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.SecurityRequirement security_requirements = 8;
                          */
                      -  io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                      +  org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder(
                             int index);
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Artifact.java
                      similarity index 91%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/Artifact.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Artifact.java
                      index d49d2184f..ad1affc3d 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Artifact.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -42,15 +42,15 @@ private Artifact() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Artifact_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.Artifact.class, io.a2a.grpc.Artifact.Builder.class);
                      +            org.a2aproject.sdk.grpc.Artifact.class, org.a2aproject.sdk.grpc.Artifact.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -197,7 +197,7 @@ public java.lang.String getDescription() {
                       
                         public static final int PARTS_FIELD_NUMBER = 4;
                         @SuppressWarnings("serial")
                      -  private java.util.List parts_;
                      +  private java.util.List parts_;
                         /**
                          * 
                          * The content of the artifact. Must contain at least one part.
                      @@ -206,7 +206,7 @@ public java.lang.String getDescription() {
                          * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List getPartsList() {
                      +  public java.util.List getPartsList() {
                           return parts_;
                         }
                         /**
                      @@ -217,7 +217,7 @@ public java.util.List getPartsList() {
                          * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getPartsOrBuilderList() {
                           return parts_;
                         }
                      @@ -240,7 +240,7 @@ public int getPartsCount() {
                          * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Part getParts(int index) {
                      +  public org.a2aproject.sdk.grpc.Part getParts(int index) {
                           return parts_.get(index);
                         }
                         /**
                      @@ -251,7 +251,7 @@ public io.a2a.grpc.Part getParts(int index) {
                          * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                      +  public org.a2aproject.sdk.grpc.PartOrBuilder getPartsOrBuilder(
                             int index) {
                           return parts_.get(index);
                         }
                      @@ -423,10 +423,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.Artifact)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.Artifact)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.Artifact other = (io.a2a.grpc.Artifact) obj;
                      +    org.a2aproject.sdk.grpc.Artifact other = (org.a2aproject.sdk.grpc.Artifact) obj;
                       
                           if (!getArtifactId()
                               .equals(other.getArtifactId())) return false;
                      @@ -477,44 +477,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.Artifact parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -522,26 +522,26 @@ public static io.a2a.grpc.Artifact parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.Artifact parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.Artifact parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.Artifact parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.Artifact parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Artifact parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -554,7 +554,7 @@ public static io.a2a.grpc.Artifact parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.Artifact prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.Artifact prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -579,21 +579,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.Artifact)
                      -      io.a2a.grpc.ArtifactOrBuilder {
                      +      org.a2aproject.sdk.grpc.ArtifactOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Artifact_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.Artifact.class, io.a2a.grpc.Artifact.Builder.class);
                      +              org.a2aproject.sdk.grpc.Artifact.class, org.a2aproject.sdk.grpc.Artifact.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.Artifact.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.Artifact.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -637,17 +637,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Artifact_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Artifact getDefaultInstanceForType() {
                      -      return io.a2a.grpc.Artifact.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.Artifact getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.Artifact.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Artifact build() {
                      -      io.a2a.grpc.Artifact result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.Artifact build() {
                      +      org.a2aproject.sdk.grpc.Artifact result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -655,15 +655,15 @@ public io.a2a.grpc.Artifact build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Artifact buildPartial() {
                      -      io.a2a.grpc.Artifact result = new io.a2a.grpc.Artifact(this);
                      +    public org.a2aproject.sdk.grpc.Artifact buildPartial() {
                      +      org.a2aproject.sdk.grpc.Artifact result = new org.a2aproject.sdk.grpc.Artifact(this);
                             buildPartialRepeatedFields(result);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartialRepeatedFields(io.a2a.grpc.Artifact result) {
                      +    private void buildPartialRepeatedFields(org.a2aproject.sdk.grpc.Artifact result) {
                             if (partsBuilder_ == null) {
                               if (((bitField0_ & 0x00000008) != 0)) {
                                 parts_ = java.util.Collections.unmodifiableList(parts_);
                      @@ -675,7 +675,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.Artifact result) {
                             }
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.Artifact result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.Artifact result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.artifactId_ = artifactId_;
                      @@ -702,16 +702,16 @@ private void buildPartial0(io.a2a.grpc.Artifact result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.Artifact) {
                      -        return mergeFrom((io.a2a.grpc.Artifact)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.Artifact) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.Artifact)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.Artifact other) {
                      -      if (other == io.a2a.grpc.Artifact.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.Artifact other) {
                      +      if (other == org.a2aproject.sdk.grpc.Artifact.getDefaultInstance()) return this;
                             if (!other.getArtifactId().isEmpty()) {
                               artifactId_ = other.artifactId_;
                               bitField0_ |= 0x00000001;
                      @@ -808,9 +808,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 26
                                   case 34: {
                      -              io.a2a.grpc.Part m =
                      +              org.a2aproject.sdk.grpc.Part m =
                                         input.readMessage(
                      -                      io.a2a.grpc.Part.parser(),
                      +                      org.a2aproject.sdk.grpc.Part.parser(),
                                             extensionRegistry);
                                     if (partsBuilder_ == null) {
                                       ensurePartsIsMutable();
                      @@ -1126,17 +1126,17 @@ public Builder setDescriptionBytes(
                             return this;
                           }
                       
                      -    private java.util.List parts_ =
                      +    private java.util.List parts_ =
                             java.util.Collections.emptyList();
                           private void ensurePartsIsMutable() {
                             if (!((bitField0_ & 0x00000008) != 0)) {
                      -        parts_ = new java.util.ArrayList(parts_);
                      +        parts_ = new java.util.ArrayList(parts_);
                               bitField0_ |= 0x00000008;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder> partsBuilder_;
                      +        org.a2aproject.sdk.grpc.Part, org.a2aproject.sdk.grpc.Part.Builder, org.a2aproject.sdk.grpc.PartOrBuilder> partsBuilder_;
                       
                           /**
                            * 
                      @@ -1145,7 +1145,7 @@ private void ensurePartsIsMutable() {
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List getPartsList() {
                      +    public java.util.List getPartsList() {
                             if (partsBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(parts_);
                             } else {
                      @@ -1173,7 +1173,7 @@ public int getPartsCount() {
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Part getParts(int index) {
                      +    public org.a2aproject.sdk.grpc.Part getParts(int index) {
                             if (partsBuilder_ == null) {
                               return parts_.get(index);
                             } else {
                      @@ -1188,7 +1188,7 @@ public io.a2a.grpc.Part getParts(int index) {
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setParts(
                      -        int index, io.a2a.grpc.Part value) {
                      +        int index, org.a2aproject.sdk.grpc.Part value) {
                             if (partsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1209,7 +1209,7 @@ public Builder setParts(
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setParts(
                      -        int index, io.a2a.grpc.Part.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Part.Builder builderForValue) {
                             if (partsBuilder_ == null) {
                               ensurePartsIsMutable();
                               parts_.set(index, builderForValue.build());
                      @@ -1226,7 +1226,7 @@ public Builder setParts(
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder addParts(io.a2a.grpc.Part value) {
                      +    public Builder addParts(org.a2aproject.sdk.grpc.Part value) {
                             if (partsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1247,7 +1247,7 @@ public Builder addParts(io.a2a.grpc.Part value) {
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addParts(
                      -        int index, io.a2a.grpc.Part value) {
                      +        int index, org.a2aproject.sdk.grpc.Part value) {
                             if (partsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1268,7 +1268,7 @@ public Builder addParts(
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addParts(
                      -        io.a2a.grpc.Part.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Part.Builder builderForValue) {
                             if (partsBuilder_ == null) {
                               ensurePartsIsMutable();
                               parts_.add(builderForValue.build());
                      @@ -1286,7 +1286,7 @@ public Builder addParts(
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addParts(
                      -        int index, io.a2a.grpc.Part.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Part.Builder builderForValue) {
                             if (partsBuilder_ == null) {
                               ensurePartsIsMutable();
                               parts_.add(index, builderForValue.build());
                      @@ -1304,7 +1304,7 @@ public Builder addParts(
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addAllParts(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (partsBuilder_ == null) {
                               ensurePartsIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -1356,7 +1356,7 @@ public Builder removeParts(int index) {
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Part.Builder getPartsBuilder(
                      +    public org.a2aproject.sdk.grpc.Part.Builder getPartsBuilder(
                               int index) {
                             return internalGetPartsFieldBuilder().getBuilder(index);
                           }
                      @@ -1367,7 +1367,7 @@ public io.a2a.grpc.Part.Builder getPartsBuilder(
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                      +    public org.a2aproject.sdk.grpc.PartOrBuilder getPartsOrBuilder(
                               int index) {
                             if (partsBuilder_ == null) {
                               return parts_.get(index);  } else {
                      @@ -1381,7 +1381,7 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getPartsOrBuilderList() {
                             if (partsBuilder_ != null) {
                               return partsBuilder_.getMessageOrBuilderList();
                      @@ -1396,9 +1396,9 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Part.Builder addPartsBuilder() {
                      +    public org.a2aproject.sdk.grpc.Part.Builder addPartsBuilder() {
                             return internalGetPartsFieldBuilder().addBuilder(
                      -          io.a2a.grpc.Part.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.Part.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1407,10 +1407,10 @@ public io.a2a.grpc.Part.Builder addPartsBuilder() {
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Part.Builder addPartsBuilder(
                      +    public org.a2aproject.sdk.grpc.Part.Builder addPartsBuilder(
                               int index) {
                             return internalGetPartsFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.Part.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.Part.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1419,16 +1419,16 @@ public io.a2a.grpc.Part.Builder addPartsBuilder(
                            *
                            * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getPartsBuilderList() {
                             return internalGetPartsFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Part, org.a2aproject.sdk.grpc.Part.Builder, org.a2aproject.sdk.grpc.PartOrBuilder> 
                               internalGetPartsFieldBuilder() {
                             if (partsBuilder_ == null) {
                               partsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder>(
                      +            org.a2aproject.sdk.grpc.Part, org.a2aproject.sdk.grpc.Part.Builder, org.a2aproject.sdk.grpc.PartOrBuilder>(
                                       parts_,
                                       ((bitField0_ & 0x00000008) != 0),
                                       getParentForChildren(),
                      @@ -1746,12 +1746,12 @@ public Builder addExtensionsBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.Artifact)
                      -  private static final io.a2a.grpc.Artifact DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.Artifact DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.Artifact();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.Artifact();
                         }
                       
                      -  public static io.a2a.grpc.Artifact getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.Artifact getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1787,7 +1787,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.Artifact getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.Artifact getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ArtifactOrBuilder.java
                      similarity index 94%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ArtifactOrBuilder.java
                      index 4ba0ed83d..641fcd1d8 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ArtifactOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface ArtifactOrBuilder extends
                      @@ -77,7 +77,7 @@ public interface ArtifactOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getPartsList();
                         /**
                          * 
                      @@ -86,7 +86,7 @@ public interface ArtifactOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.Part getParts(int index);
                      +  org.a2aproject.sdk.grpc.Part getParts(int index);
                         /**
                          * 
                          * The content of the artifact. Must contain at least one part.
                      @@ -102,7 +102,7 @@ public interface ArtifactOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getPartsOrBuilderList();
                         /**
                          * 
                      @@ -111,7 +111,7 @@ public interface ArtifactOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Part parts = 4 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                      +  org.a2aproject.sdk.grpc.PartOrBuilder getPartsOrBuilder(
                             int index);
                       
                         /**
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthenticationInfo.java
                      similarity index 86%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthenticationInfo.java
                      index fc4750715..86ec9805f 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthenticationInfo.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private AuthenticationInfo() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AuthenticationInfo.class, io.a2a.grpc.AuthenticationInfo.Builder.class);
                      +            org.a2aproject.sdk.grpc.AuthenticationInfo.class, org.a2aproject.sdk.grpc.AuthenticationInfo.Builder.class);
                         }
                       
                         public static final int SCHEME_FIELD_NUMBER = 1;
                      @@ -192,10 +192,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AuthenticationInfo)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AuthenticationInfo)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AuthenticationInfo other = (io.a2a.grpc.AuthenticationInfo) obj;
                      +    org.a2aproject.sdk.grpc.AuthenticationInfo other = (org.a2aproject.sdk.grpc.AuthenticationInfo) obj;
                       
                           if (!getScheme()
                               .equals(other.getScheme())) return false;
                      @@ -221,44 +221,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -266,26 +266,26 @@ public static io.a2a.grpc.AuthenticationInfo parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AuthenticationInfo parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AuthenticationInfo parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AuthenticationInfo parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -298,7 +298,7 @@ public static io.a2a.grpc.AuthenticationInfo parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AuthenticationInfo prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AuthenticationInfo prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -323,21 +323,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AuthenticationInfo)
                      -      io.a2a.grpc.AuthenticationInfoOrBuilder {
                      +      org.a2aproject.sdk.grpc.AuthenticationInfoOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AuthenticationInfo.class, io.a2a.grpc.AuthenticationInfo.Builder.class);
                      +              org.a2aproject.sdk.grpc.AuthenticationInfo.class, org.a2aproject.sdk.grpc.AuthenticationInfo.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AuthenticationInfo.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AuthenticationInfo.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -359,17 +359,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthenticationInfo_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AuthenticationInfo getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AuthenticationInfo.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AuthenticationInfo getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AuthenticationInfo.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AuthenticationInfo build() {
                      -      io.a2a.grpc.AuthenticationInfo result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AuthenticationInfo build() {
                      +      org.a2aproject.sdk.grpc.AuthenticationInfo result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -377,14 +377,14 @@ public io.a2a.grpc.AuthenticationInfo build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AuthenticationInfo buildPartial() {
                      -      io.a2a.grpc.AuthenticationInfo result = new io.a2a.grpc.AuthenticationInfo(this);
                      +    public org.a2aproject.sdk.grpc.AuthenticationInfo buildPartial() {
                      +      org.a2aproject.sdk.grpc.AuthenticationInfo result = new org.a2aproject.sdk.grpc.AuthenticationInfo(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AuthenticationInfo result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AuthenticationInfo result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.scheme_ = scheme_;
                      @@ -396,16 +396,16 @@ private void buildPartial0(io.a2a.grpc.AuthenticationInfo result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AuthenticationInfo) {
                      -        return mergeFrom((io.a2a.grpc.AuthenticationInfo)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AuthenticationInfo) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AuthenticationInfo)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AuthenticationInfo other) {
                      -      if (other == io.a2a.grpc.AuthenticationInfo.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AuthenticationInfo other) {
                      +      if (other == org.a2aproject.sdk.grpc.AuthenticationInfo.getDefaultInstance()) return this;
                             if (!other.getScheme().isEmpty()) {
                               scheme_ = other.scheme_;
                               bitField0_ |= 0x00000001;
                      @@ -667,12 +667,12 @@ public Builder setCredentialsBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AuthenticationInfo)
                      -  private static final io.a2a.grpc.AuthenticationInfo DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AuthenticationInfo DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AuthenticationInfo();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AuthenticationInfo();
                         }
                       
                      -  public static io.a2a.grpc.AuthenticationInfo getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AuthenticationInfo getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -708,7 +708,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AuthenticationInfo getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AuthenticationInfo getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthenticationInfoOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthenticationInfoOrBuilder.java
                      index 7d5860fe1..11f6abd85 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthenticationInfoOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AuthenticationInfoOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthorizationCodeOAuthFlow.java
                      similarity index 91%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthorizationCodeOAuthFlow.java
                      index 13b09915a..2055479da 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthorizationCodeOAuthFlow.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -39,7 +39,7 @@ private AuthorizationCodeOAuthFlow() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor;
                         }
                       
                         @SuppressWarnings({"rawtypes"})
                      @@ -57,9 +57,9 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.AuthorizationCodeOAuthFlow.class, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder.class);
                      +            org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.class, org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.Builder.class);
                         }
                       
                         public static final int AUTHORIZATION_URL_FIELD_NUMBER = 1;
                      @@ -209,7 +209,7 @@ private static final class ScopesDefaultEntryHolder {
                               java.lang.String, java.lang.String> defaultEntry =
                                   com.google.protobuf.MapEntry
                                   .newDefaultInstance(
                      -                io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, 
                      +                org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, 
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                                       "",
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                      @@ -388,10 +388,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.AuthorizationCodeOAuthFlow)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.AuthorizationCodeOAuthFlow other = (io.a2a.grpc.AuthorizationCodeOAuthFlow) obj;
                      +    org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow other = (org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) obj;
                       
                           if (!getAuthorizationUrl()
                               .equals(other.getAuthorizationUrl())) return false;
                      @@ -432,44 +432,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -477,26 +477,26 @@ public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -509,7 +509,7 @@ public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.AuthorizationCodeOAuthFlow prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -534,10 +534,10 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.AuthorizationCodeOAuthFlow)
                      -      io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder {
                      +      org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlowOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor;
                           }
                       
                           @SuppressWarnings({"rawtypes"})
                      @@ -565,12 +565,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.AuthorizationCodeOAuthFlow.class, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder.class);
                      +              org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.class, org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.AuthorizationCodeOAuthFlow.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -595,17 +595,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_AuthorizationCodeOAuthFlow_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AuthorizationCodeOAuthFlow getDefaultInstanceForType() {
                      -      return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AuthorizationCodeOAuthFlow build() {
                      -      io.a2a.grpc.AuthorizationCodeOAuthFlow result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow build() {
                      +      org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -613,14 +613,14 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlow build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.AuthorizationCodeOAuthFlow buildPartial() {
                      -      io.a2a.grpc.AuthorizationCodeOAuthFlow result = new io.a2a.grpc.AuthorizationCodeOAuthFlow(this);
                      +    public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow buildPartial() {
                      +      org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow result = new org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.AuthorizationCodeOAuthFlow result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.authorizationUrl_ = authorizationUrl_;
                      @@ -642,16 +642,16 @@ private void buildPartial0(io.a2a.grpc.AuthorizationCodeOAuthFlow result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.AuthorizationCodeOAuthFlow) {
                      -        return mergeFrom((io.a2a.grpc.AuthorizationCodeOAuthFlow)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.AuthorizationCodeOAuthFlow other) {
                      -      if (other == io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow other) {
                      +      if (other == org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance()) return this;
                             if (!other.getAuthorizationUrl().isEmpty()) {
                               authorizationUrl_ = other.authorizationUrl_;
                               bitField0_ |= 0x00000001;
                      @@ -1227,12 +1227,12 @@ public Builder clearPkceRequired() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.AuthorizationCodeOAuthFlow)
                      -  private static final io.a2a.grpc.AuthorizationCodeOAuthFlow DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.AuthorizationCodeOAuthFlow();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow();
                         }
                       
                      -  public static io.a2a.grpc.AuthorizationCodeOAuthFlow getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1268,7 +1268,7 @@ public com.google.protobuf.Parser getParserForType()
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.AuthorizationCodeOAuthFlow getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthorizationCodeOAuthFlowOrBuilder.java
                      similarity index 99%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthorizationCodeOAuthFlowOrBuilder.java
                      index 55c17dc7b..d9f007235 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/AuthorizationCodeOAuthFlowOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface AuthorizationCodeOAuthFlowOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/CancelTaskRequest.java
                      similarity index 89%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/CancelTaskRequest.java
                      index d1ca30eca..40265d798 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/CancelTaskRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private CancelTaskRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.CancelTaskRequest.class, io.a2a.grpc.CancelTaskRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.CancelTaskRequest.class, org.a2aproject.sdk.grpc.CancelTaskRequest.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -234,10 +234,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.CancelTaskRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.CancelTaskRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.CancelTaskRequest other = (io.a2a.grpc.CancelTaskRequest) obj;
                      +    org.a2aproject.sdk.grpc.CancelTaskRequest other = (org.a2aproject.sdk.grpc.CancelTaskRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -272,44 +272,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -317,26 +317,26 @@ public static io.a2a.grpc.CancelTaskRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.CancelTaskRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.CancelTaskRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.CancelTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -349,7 +349,7 @@ public static io.a2a.grpc.CancelTaskRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.CancelTaskRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.CancelTaskRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -374,21 +374,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.CancelTaskRequest)
                      -      io.a2a.grpc.CancelTaskRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.CancelTaskRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.CancelTaskRequest.class, io.a2a.grpc.CancelTaskRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.CancelTaskRequest.class, org.a2aproject.sdk.grpc.CancelTaskRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.CancelTaskRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.CancelTaskRequest.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -421,17 +421,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_CancelTaskRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.CancelTaskRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.CancelTaskRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.CancelTaskRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.CancelTaskRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.CancelTaskRequest build() {
                      -      io.a2a.grpc.CancelTaskRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.CancelTaskRequest build() {
                      +      org.a2aproject.sdk.grpc.CancelTaskRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -439,14 +439,14 @@ public io.a2a.grpc.CancelTaskRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.CancelTaskRequest buildPartial() {
                      -      io.a2a.grpc.CancelTaskRequest result = new io.a2a.grpc.CancelTaskRequest(this);
                      +    public org.a2aproject.sdk.grpc.CancelTaskRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.CancelTaskRequest result = new org.a2aproject.sdk.grpc.CancelTaskRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.CancelTaskRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.CancelTaskRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -466,16 +466,16 @@ private void buildPartial0(io.a2a.grpc.CancelTaskRequest result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.CancelTaskRequest) {
                      -        return mergeFrom((io.a2a.grpc.CancelTaskRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.CancelTaskRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.CancelTaskRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.CancelTaskRequest other) {
                      -      if (other == io.a2a.grpc.CancelTaskRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.CancelTaskRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.CancelTaskRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -894,12 +894,12 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.CancelTaskRequest)
                      -  private static final io.a2a.grpc.CancelTaskRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.CancelTaskRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.CancelTaskRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.CancelTaskRequest();
                         }
                       
                      -  public static io.a2a.grpc.CancelTaskRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.CancelTaskRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -935,7 +935,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.CancelTaskRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.CancelTaskRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/CancelTaskRequestOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/CancelTaskRequestOrBuilder.java
                      index 6dc8b9243..3513fb99f 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/CancelTaskRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface CancelTaskRequestOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ClientCredentialsOAuthFlow.java
                      similarity index 89%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ClientCredentialsOAuthFlow.java
                      index c91bda94f..24f62e447 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ClientCredentialsOAuthFlow.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,7 +38,7 @@ private ClientCredentialsOAuthFlow() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor;
                         }
                       
                         @SuppressWarnings({"rawtypes"})
                      @@ -56,9 +56,9 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.ClientCredentialsOAuthFlow.class, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder.class);
                      +            org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.class, org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.Builder.class);
                         }
                       
                         public static final int TOKEN_URL_FIELD_NUMBER = 1;
                      @@ -161,7 +161,7 @@ private static final class ScopesDefaultEntryHolder {
                               java.lang.String, java.lang.String> defaultEntry =
                                   com.google.protobuf.MapEntry
                                   .newDefaultInstance(
                      -                io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, 
                      +                org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, 
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                                       "",
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                      @@ -311,10 +311,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.ClientCredentialsOAuthFlow)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.ClientCredentialsOAuthFlow other = (io.a2a.grpc.ClientCredentialsOAuthFlow) obj;
                      +    org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow other = (org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) obj;
                       
                           if (!getTokenUrl()
                               .equals(other.getTokenUrl())) return false;
                      @@ -346,44 +346,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -391,26 +391,26 @@ public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -423,7 +423,7 @@ public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.ClientCredentialsOAuthFlow prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -448,10 +448,10 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ClientCredentialsOAuthFlow)
                      -      io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder {
                      +      org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlowOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor;
                           }
                       
                           @SuppressWarnings({"rawtypes"})
                      @@ -479,12 +479,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.ClientCredentialsOAuthFlow.class, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder.class);
                      +              org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.class, org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.ClientCredentialsOAuthFlow.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -507,17 +507,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ClientCredentialsOAuthFlow_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ClientCredentialsOAuthFlow getDefaultInstanceForType() {
                      -      return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ClientCredentialsOAuthFlow build() {
                      -      io.a2a.grpc.ClientCredentialsOAuthFlow result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow build() {
                      +      org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -525,14 +525,14 @@ public io.a2a.grpc.ClientCredentialsOAuthFlow build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ClientCredentialsOAuthFlow buildPartial() {
                      -      io.a2a.grpc.ClientCredentialsOAuthFlow result = new io.a2a.grpc.ClientCredentialsOAuthFlow(this);
                      +    public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow buildPartial() {
                      +      org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow result = new org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.ClientCredentialsOAuthFlow result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tokenUrl_ = tokenUrl_;
                      @@ -548,16 +548,16 @@ private void buildPartial0(io.a2a.grpc.ClientCredentialsOAuthFlow result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.ClientCredentialsOAuthFlow) {
                      -        return mergeFrom((io.a2a.grpc.ClientCredentialsOAuthFlow)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.ClientCredentialsOAuthFlow other) {
                      -      if (other == io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow other) {
                      +      if (other == org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance()) return this;
                             if (!other.getTokenUrl().isEmpty()) {
                               tokenUrl_ = other.tokenUrl_;
                               bitField0_ |= 0x00000001;
                      @@ -976,12 +976,12 @@ public Builder putAllScopes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.ClientCredentialsOAuthFlow)
                      -  private static final io.a2a.grpc.ClientCredentialsOAuthFlow DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.ClientCredentialsOAuthFlow();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow();
                         }
                       
                      -  public static io.a2a.grpc.ClientCredentialsOAuthFlow getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1017,7 +1017,7 @@ public com.google.protobuf.Parser getParserForType()
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.ClientCredentialsOAuthFlow getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ClientCredentialsOAuthFlowOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ClientCredentialsOAuthFlowOrBuilder.java
                      index 0c60b6a5a..a3a8c9520 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ClientCredentialsOAuthFlowOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface ClientCredentialsOAuthFlowOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeleteTaskPushNotificationConfigRequest.java
                      similarity index 85%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeleteTaskPushNotificationConfigRequest.java
                      index 7375f7b5d..c15d15852 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeleteTaskPushNotificationConfigRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -39,15 +39,15 @@ private DeleteTaskPushNotificationConfigRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.class, io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class);
                         }
                       
                         public static final int TENANT_FIELD_NUMBER = 1;
                      @@ -242,10 +242,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.DeleteTaskPushNotificationConfigRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.DeleteTaskPushNotificationConfigRequest other = (io.a2a.grpc.DeleteTaskPushNotificationConfigRequest) obj;
                      +    org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest other = (org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -275,44 +275,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -320,26 +320,26 @@ public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -352,7 +352,7 @@ public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -377,21 +377,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.DeleteTaskPushNotificationConfigRequest)
                      -      io.a2a.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.class, io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -414,17 +414,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest build() {
                      -      io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest build() {
                      +      org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -432,14 +432,14 @@ public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest buildPartial() {
                      -      io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result = new io.a2a.grpc.DeleteTaskPushNotificationConfigRequest(this);
                      +    public org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest result = new org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -454,16 +454,16 @@ private void buildPartial0(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest r
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.DeleteTaskPushNotificationConfigRequest) {
                      -        return mergeFrom((io.a2a.grpc.DeleteTaskPushNotificationConfigRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest other) {
                      -      if (other == io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -817,12 +817,12 @@ public Builder setIdBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.DeleteTaskPushNotificationConfigRequest)
                      -  private static final io.a2a.grpc.DeleteTaskPushNotificationConfigRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.DeleteTaskPushNotificationConfigRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest();
                         }
                       
                      -  public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -858,7 +858,7 @@ public com.google.protobuf.Parser getPa
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java
                      index f0f9c4b0d..906d43632 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface DeleteTaskPushNotificationConfigRequestOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeviceCodeOAuthFlow.java
                      similarity index 91%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeviceCodeOAuthFlow.java
                      index 15c0404ca..d0067625c 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeviceCodeOAuthFlow.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -41,7 +41,7 @@ private DeviceCodeOAuthFlow() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor;
                         }
                       
                         @SuppressWarnings({"rawtypes"})
                      @@ -59,9 +59,9 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.DeviceCodeOAuthFlow.class, io.a2a.grpc.DeviceCodeOAuthFlow.Builder.class);
                      +            org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.class, org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.Builder.class);
                         }
                       
                         public static final int DEVICE_AUTHORIZATION_URL_FIELD_NUMBER = 1;
                      @@ -211,7 +211,7 @@ private static final class ScopesDefaultEntryHolder {
                               java.lang.String, java.lang.String> defaultEntry =
                                   com.google.protobuf.MapEntry
                                   .newDefaultInstance(
                      -                io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, 
                      +                org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, 
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                                       "",
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                      @@ -367,10 +367,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.DeviceCodeOAuthFlow)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.DeviceCodeOAuthFlow other = (io.a2a.grpc.DeviceCodeOAuthFlow) obj;
                      +    org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow other = (org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) obj;
                       
                           if (!getDeviceAuthorizationUrl()
                               .equals(other.getDeviceAuthorizationUrl())) return false;
                      @@ -406,44 +406,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -451,26 +451,26 @@ public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -483,7 +483,7 @@ public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.DeviceCodeOAuthFlow prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -510,10 +510,10 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.DeviceCodeOAuthFlow)
                      -      io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder {
                      +      org.a2aproject.sdk.grpc.DeviceCodeOAuthFlowOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor;
                           }
                       
                           @SuppressWarnings({"rawtypes"})
                      @@ -541,12 +541,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.DeviceCodeOAuthFlow.class, io.a2a.grpc.DeviceCodeOAuthFlow.Builder.class);
                      +              org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.class, org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.DeviceCodeOAuthFlow.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -570,17 +570,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_DeviceCodeOAuthFlow_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstanceForType() {
                      -      return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.DeviceCodeOAuthFlow build() {
                      -      io.a2a.grpc.DeviceCodeOAuthFlow result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow build() {
                      +      org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -588,14 +588,14 @@ public io.a2a.grpc.DeviceCodeOAuthFlow build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.DeviceCodeOAuthFlow buildPartial() {
                      -      io.a2a.grpc.DeviceCodeOAuthFlow result = new io.a2a.grpc.DeviceCodeOAuthFlow(this);
                      +    public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow buildPartial() {
                      +      org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow result = new org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.DeviceCodeOAuthFlow result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.deviceAuthorizationUrl_ = deviceAuthorizationUrl_;
                      @@ -614,16 +614,16 @@ private void buildPartial0(io.a2a.grpc.DeviceCodeOAuthFlow result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.DeviceCodeOAuthFlow) {
                      -        return mergeFrom((io.a2a.grpc.DeviceCodeOAuthFlow)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.DeviceCodeOAuthFlow other) {
                      -      if (other == io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow other) {
                      +      if (other == org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance()) return this;
                             if (!other.getDeviceAuthorizationUrl().isEmpty()) {
                               deviceAuthorizationUrl_ = other.deviceAuthorizationUrl_;
                               bitField0_ |= 0x00000001;
                      @@ -1144,12 +1144,12 @@ public Builder putAllScopes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.DeviceCodeOAuthFlow)
                      -  private static final io.a2a.grpc.DeviceCodeOAuthFlow DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.DeviceCodeOAuthFlow();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow();
                         }
                       
                      -  public static io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1185,7 +1185,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeviceCodeOAuthFlowOrBuilder.java
                      similarity index 99%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeviceCodeOAuthFlowOrBuilder.java
                      index d7b8add51..b8a563eb8 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/DeviceCodeOAuthFlowOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface DeviceCodeOAuthFlowOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetExtendedAgentCardRequest.java
                      similarity index 79%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetExtendedAgentCardRequest.java
                      index 452f7481e..2df0aa5d5 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetExtendedAgentCardRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -37,15 +37,15 @@ private GetExtendedAgentCardRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.GetExtendedAgentCardRequest.class, io.a2a.grpc.GetExtendedAgentCardRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.class, org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.Builder.class);
                         }
                       
                         public static final int TENANT_FIELD_NUMBER = 1;
                      @@ -134,10 +134,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.GetExtendedAgentCardRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.GetExtendedAgentCardRequest other = (io.a2a.grpc.GetExtendedAgentCardRequest) obj;
                      +    org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest other = (org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -159,44 +159,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -204,26 +204,26 @@ public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -236,7 +236,7 @@ public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.GetExtendedAgentCardRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -261,21 +261,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.GetExtendedAgentCardRequest)
                      -      io.a2a.grpc.GetExtendedAgentCardRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.GetExtendedAgentCardRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.GetExtendedAgentCardRequest.class, io.a2a.grpc.GetExtendedAgentCardRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.class, org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.GetExtendedAgentCardRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -296,17 +296,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetExtendedAgentCardRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetExtendedAgentCardRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.GetExtendedAgentCardRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetExtendedAgentCardRequest build() {
                      -      io.a2a.grpc.GetExtendedAgentCardRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest build() {
                      +      org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -314,14 +314,14 @@ public io.a2a.grpc.GetExtendedAgentCardRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetExtendedAgentCardRequest buildPartial() {
                      -      io.a2a.grpc.GetExtendedAgentCardRequest result = new io.a2a.grpc.GetExtendedAgentCardRequest(this);
                      +    public org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest result = new org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.GetExtendedAgentCardRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -330,16 +330,16 @@ private void buildPartial0(io.a2a.grpc.GetExtendedAgentCardRequest result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.GetExtendedAgentCardRequest) {
                      -        return mergeFrom((io.a2a.grpc.GetExtendedAgentCardRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.GetExtendedAgentCardRequest other) {
                      -      if (other == io.a2a.grpc.GetExtendedAgentCardRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -489,12 +489,12 @@ public Builder setTenantBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.GetExtendedAgentCardRequest)
                      -  private static final io.a2a.grpc.GetExtendedAgentCardRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.GetExtendedAgentCardRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest();
                         }
                       
                      -  public static io.a2a.grpc.GetExtendedAgentCardRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -530,7 +530,7 @@ public com.google.protobuf.Parser getParserForType(
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.GetExtendedAgentCardRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetExtendedAgentCardRequestOrBuilder.java
                      similarity index 96%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetExtendedAgentCardRequestOrBuilder.java
                      index e7f6a6615..277f8f9f4 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetExtendedAgentCardRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface GetExtendedAgentCardRequestOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskPushNotificationConfigRequest.java
                      similarity index 85%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskPushNotificationConfigRequest.java
                      index 5fc7aa7fc..5d75f7126 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskPushNotificationConfigRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -39,15 +39,15 @@ private GetTaskPushNotificationConfigRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.GetTaskPushNotificationConfigRequest.class, io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.Builder.class);
                         }
                       
                         public static final int TENANT_FIELD_NUMBER = 1;
                      @@ -242,10 +242,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.GetTaskPushNotificationConfigRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.GetTaskPushNotificationConfigRequest other = (io.a2a.grpc.GetTaskPushNotificationConfigRequest) obj;
                      +    org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest other = (org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -275,44 +275,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -320,26 +320,26 @@ public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -352,7 +352,7 @@ public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.GetTaskPushNotificationConfigRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -377,21 +377,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.GetTaskPushNotificationConfigRequest)
                      -      io.a2a.grpc.GetTaskPushNotificationConfigRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.GetTaskPushNotificationConfigRequest.class, io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -414,17 +414,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetTaskPushNotificationConfigRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetTaskPushNotificationConfigRequest build() {
                      -      io.a2a.grpc.GetTaskPushNotificationConfigRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest build() {
                      +      org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -432,14 +432,14 @@ public io.a2a.grpc.GetTaskPushNotificationConfigRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetTaskPushNotificationConfigRequest buildPartial() {
                      -      io.a2a.grpc.GetTaskPushNotificationConfigRequest result = new io.a2a.grpc.GetTaskPushNotificationConfigRequest(this);
                      +    public org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest result = new org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.GetTaskPushNotificationConfigRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -454,16 +454,16 @@ private void buildPartial0(io.a2a.grpc.GetTaskPushNotificationConfigRequest resu
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.GetTaskPushNotificationConfigRequest) {
                      -        return mergeFrom((io.a2a.grpc.GetTaskPushNotificationConfigRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.GetTaskPushNotificationConfigRequest other) {
                      -      if (other == io.a2a.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -817,12 +817,12 @@ public Builder setIdBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.GetTaskPushNotificationConfigRequest)
                      -  private static final io.a2a.grpc.GetTaskPushNotificationConfigRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.GetTaskPushNotificationConfigRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest();
                         }
                       
                      -  public static io.a2a.grpc.GetTaskPushNotificationConfigRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -858,7 +858,7 @@ public com.google.protobuf.Parser getParse
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.GetTaskPushNotificationConfigRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java
                      index 9c6ab84e3..38143466a 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface GetTaskPushNotificationConfigRequestOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskRequest.java
                      similarity index 88%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskRequest.java
                      index 2d6ff2246..6506c36e3 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private GetTaskRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.GetTaskRequest.class, io.a2a.grpc.GetTaskRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.GetTaskRequest.class, org.a2aproject.sdk.grpc.GetTaskRequest.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -229,10 +229,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.GetTaskRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.GetTaskRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.GetTaskRequest other = (io.a2a.grpc.GetTaskRequest) obj;
                      +    org.a2aproject.sdk.grpc.GetTaskRequest other = (org.a2aproject.sdk.grpc.GetTaskRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -267,44 +267,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -312,26 +312,26 @@ public static io.a2a.grpc.GetTaskRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.GetTaskRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.GetTaskRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.GetTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -344,7 +344,7 @@ public static io.a2a.grpc.GetTaskRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.GetTaskRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.GetTaskRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -369,21 +369,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.GetTaskRequest)
                      -      io.a2a.grpc.GetTaskRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.GetTaskRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.GetTaskRequest.class, io.a2a.grpc.GetTaskRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.GetTaskRequest.class, org.a2aproject.sdk.grpc.GetTaskRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.GetTaskRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.GetTaskRequest.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -406,17 +406,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_GetTaskRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetTaskRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.GetTaskRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.GetTaskRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.GetTaskRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetTaskRequest build() {
                      -      io.a2a.grpc.GetTaskRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.GetTaskRequest build() {
                      +      org.a2aproject.sdk.grpc.GetTaskRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -424,14 +424,14 @@ public io.a2a.grpc.GetTaskRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.GetTaskRequest buildPartial() {
                      -      io.a2a.grpc.GetTaskRequest result = new io.a2a.grpc.GetTaskRequest(this);
                      +    public org.a2aproject.sdk.grpc.GetTaskRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.GetTaskRequest result = new org.a2aproject.sdk.grpc.GetTaskRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.GetTaskRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.GetTaskRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -449,16 +449,16 @@ private void buildPartial0(io.a2a.grpc.GetTaskRequest result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.GetTaskRequest) {
                      -        return mergeFrom((io.a2a.grpc.GetTaskRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.GetTaskRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.GetTaskRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.GetTaskRequest other) {
                      -      if (other == io.a2a.grpc.GetTaskRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.GetTaskRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.GetTaskRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -786,12 +786,12 @@ public Builder clearHistoryLength() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.GetTaskRequest)
                      -  private static final io.a2a.grpc.GetTaskRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.GetTaskRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.GetTaskRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.GetTaskRequest();
                         }
                       
                      -  public static io.a2a.grpc.GetTaskRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.GetTaskRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -827,7 +827,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.GetTaskRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.GetTaskRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskRequestOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskRequestOrBuilder.java
                      index e844a918c..e4096d8fe 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/GetTaskRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface GetTaskRequestOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/HTTPAuthSecurityScheme.java
                      similarity index 88%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/HTTPAuthSecurityScheme.java
                      index 9e1132a20..9d705e786 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/HTTPAuthSecurityScheme.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -39,15 +39,15 @@ private HTTPAuthSecurityScheme() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.HTTPAuthSecurityScheme.class, io.a2a.grpc.HTTPAuthSecurityScheme.Builder.class);
                      +            org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.class, org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.Builder.class);
                         }
                       
                         public static final int DESCRIPTION_FIELD_NUMBER = 1;
                      @@ -248,10 +248,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.HTTPAuthSecurityScheme)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.HTTPAuthSecurityScheme other = (io.a2a.grpc.HTTPAuthSecurityScheme) obj;
                      +    org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme other = (org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) obj;
                       
                           if (!getDescription()
                               .equals(other.getDescription())) return false;
                      @@ -281,44 +281,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -326,26 +326,26 @@ public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -358,7 +358,7 @@ public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.HTTPAuthSecurityScheme prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -383,21 +383,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.HTTPAuthSecurityScheme)
                      -      io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder {
                      +      org.a2aproject.sdk.grpc.HTTPAuthSecuritySchemeOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.HTTPAuthSecurityScheme.class, io.a2a.grpc.HTTPAuthSecurityScheme.Builder.class);
                      +              org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.class, org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.HTTPAuthSecurityScheme.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -420,17 +420,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_HTTPAuthSecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.HTTPAuthSecurityScheme getDefaultInstanceForType() {
                      -      return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.HTTPAuthSecurityScheme build() {
                      -      io.a2a.grpc.HTTPAuthSecurityScheme result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme build() {
                      +      org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -438,14 +438,14 @@ public io.a2a.grpc.HTTPAuthSecurityScheme build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.HTTPAuthSecurityScheme buildPartial() {
                      -      io.a2a.grpc.HTTPAuthSecurityScheme result = new io.a2a.grpc.HTTPAuthSecurityScheme(this);
                      +    public org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme buildPartial() {
                      +      org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme result = new org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.HTTPAuthSecurityScheme result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.description_ = description_;
                      @@ -460,16 +460,16 @@ private void buildPartial0(io.a2a.grpc.HTTPAuthSecurityScheme result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.HTTPAuthSecurityScheme) {
                      -        return mergeFrom((io.a2a.grpc.HTTPAuthSecurityScheme)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.HTTPAuthSecurityScheme other) {
                      -      if (other == io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme other) {
                      +      if (other == org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance()) return this;
                             if (!other.getDescription().isEmpty()) {
                               description_ = other.description_;
                               bitField0_ |= 0x00000001;
                      @@ -838,12 +838,12 @@ public Builder setBearerFormatBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.HTTPAuthSecurityScheme)
                      -  private static final io.a2a.grpc.HTTPAuthSecurityScheme DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.HTTPAuthSecurityScheme();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme();
                         }
                       
                      -  public static io.a2a.grpc.HTTPAuthSecurityScheme getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -879,7 +879,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.HTTPAuthSecurityScheme getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/HTTPAuthSecuritySchemeOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/HTTPAuthSecuritySchemeOrBuilder.java
                      index ee79f8014..1c1fa8be8 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/HTTPAuthSecuritySchemeOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface HTTPAuthSecuritySchemeOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ImplicitOAuthFlow.java
                      similarity index 90%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ImplicitOAuthFlow.java
                      index e11473d4f..f001bea96 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ImplicitOAuthFlow.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,7 +38,7 @@ private ImplicitOAuthFlow() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor;
                         }
                       
                         @SuppressWarnings({"rawtypes"})
                      @@ -56,9 +56,9 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class);
                      +            org.a2aproject.sdk.grpc.ImplicitOAuthFlow.class, org.a2aproject.sdk.grpc.ImplicitOAuthFlow.Builder.class);
                         }
                       
                         public static final int AUTHORIZATION_URL_FIELD_NUMBER = 1;
                      @@ -165,7 +165,7 @@ private static final class ScopesDefaultEntryHolder {
                               java.lang.String, java.lang.String> defaultEntry =
                                   com.google.protobuf.MapEntry
                                   .newDefaultInstance(
                      -                io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, 
                      +                org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, 
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                                       "",
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                      @@ -319,10 +319,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.ImplicitOAuthFlow)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.ImplicitOAuthFlow)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.ImplicitOAuthFlow other = (io.a2a.grpc.ImplicitOAuthFlow) obj;
                      +    org.a2aproject.sdk.grpc.ImplicitOAuthFlow other = (org.a2aproject.sdk.grpc.ImplicitOAuthFlow) obj;
                       
                           if (!getAuthorizationUrl()
                               .equals(other.getAuthorizationUrl())) return false;
                      @@ -354,44 +354,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -399,26 +399,26 @@ public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -431,7 +431,7 @@ public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.ImplicitOAuthFlow prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.ImplicitOAuthFlow prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -456,10 +456,10 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ImplicitOAuthFlow)
                      -      io.a2a.grpc.ImplicitOAuthFlowOrBuilder {
                      +      org.a2aproject.sdk.grpc.ImplicitOAuthFlowOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor;
                           }
                       
                           @SuppressWarnings({"rawtypes"})
                      @@ -487,12 +487,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class);
                      +              org.a2aproject.sdk.grpc.ImplicitOAuthFlow.class, org.a2aproject.sdk.grpc.ImplicitOAuthFlow.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.ImplicitOAuthFlow.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.ImplicitOAuthFlow.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -515,17 +515,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ImplicitOAuthFlow_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ImplicitOAuthFlow getDefaultInstanceForType() {
                      -      return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.ImplicitOAuthFlow getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ImplicitOAuthFlow build() {
                      -      io.a2a.grpc.ImplicitOAuthFlow result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.ImplicitOAuthFlow build() {
                      +      org.a2aproject.sdk.grpc.ImplicitOAuthFlow result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -533,14 +533,14 @@ public io.a2a.grpc.ImplicitOAuthFlow build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ImplicitOAuthFlow buildPartial() {
                      -      io.a2a.grpc.ImplicitOAuthFlow result = new io.a2a.grpc.ImplicitOAuthFlow(this);
                      +    public org.a2aproject.sdk.grpc.ImplicitOAuthFlow buildPartial() {
                      +      org.a2aproject.sdk.grpc.ImplicitOAuthFlow result = new org.a2aproject.sdk.grpc.ImplicitOAuthFlow(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.ImplicitOAuthFlow result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.ImplicitOAuthFlow result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.authorizationUrl_ = authorizationUrl_;
                      @@ -556,16 +556,16 @@ private void buildPartial0(io.a2a.grpc.ImplicitOAuthFlow result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.ImplicitOAuthFlow) {
                      -        return mergeFrom((io.a2a.grpc.ImplicitOAuthFlow)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.ImplicitOAuthFlow) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.ImplicitOAuthFlow)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.ImplicitOAuthFlow other) {
                      -      if (other == io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.ImplicitOAuthFlow other) {
                      +      if (other == org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance()) return this;
                             if (!other.getAuthorizationUrl().isEmpty()) {
                               authorizationUrl_ = other.authorizationUrl_;
                               bitField0_ |= 0x00000001;
                      @@ -1001,12 +1001,12 @@ public Builder putAllScopes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.ImplicitOAuthFlow)
                      -  private static final io.a2a.grpc.ImplicitOAuthFlow DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.ImplicitOAuthFlow DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.ImplicitOAuthFlow();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.ImplicitOAuthFlow();
                         }
                       
                      -  public static io.a2a.grpc.ImplicitOAuthFlow getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.ImplicitOAuthFlow getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1042,7 +1042,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.ImplicitOAuthFlow getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.ImplicitOAuthFlow getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ImplicitOAuthFlowOrBuilder.java
                      similarity index 99%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ImplicitOAuthFlowOrBuilder.java
                      index 90d959a61..2779e408d 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ImplicitOAuthFlowOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface ImplicitOAuthFlowOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsRequest.java
                      similarity index 86%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsRequest.java
                      index a95d7ea53..7fc0a8b0a 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -39,15 +39,15 @@ private ListTaskPushNotificationConfigsRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.ListTaskPushNotificationConfigsRequest.class, io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.class, org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.Builder.class);
                         }
                       
                         public static final int TENANT_FIELD_NUMBER = 4;
                      @@ -264,10 +264,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.ListTaskPushNotificationConfigsRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.ListTaskPushNotificationConfigsRequest other = (io.a2a.grpc.ListTaskPushNotificationConfigsRequest) obj;
                      +    org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest other = (org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -301,44 +301,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -346,26 +346,26 @@ public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -378,7 +378,7 @@ public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.ListTaskPushNotificationConfigsRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -403,21 +403,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ListTaskPushNotificationConfigsRequest)
                      -      io.a2a.grpc.ListTaskPushNotificationConfigsRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.ListTaskPushNotificationConfigsRequest.class, io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.class, org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.ListTaskPushNotificationConfigsRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -441,17 +441,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTaskPushNotificationConfigsRequest build() {
                      -      io.a2a.grpc.ListTaskPushNotificationConfigsRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest build() {
                      +      org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -459,14 +459,14 @@ public io.a2a.grpc.ListTaskPushNotificationConfigsRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTaskPushNotificationConfigsRequest buildPartial() {
                      -      io.a2a.grpc.ListTaskPushNotificationConfigsRequest result = new io.a2a.grpc.ListTaskPushNotificationConfigsRequest(this);
                      +    public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest result = new org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigsRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -484,16 +484,16 @@ private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigsRequest re
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.ListTaskPushNotificationConfigsRequest) {
                      -        return mergeFrom((io.a2a.grpc.ListTaskPushNotificationConfigsRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigsRequest other) {
                      -      if (other == io.a2a.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -899,12 +899,12 @@ public Builder setPageTokenBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.ListTaskPushNotificationConfigsRequest)
                      -  private static final io.a2a.grpc.ListTaskPushNotificationConfigsRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.ListTaskPushNotificationConfigsRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest();
                         }
                       
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -940,7 +940,7 @@ public com.google.protobuf.Parser getPar
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java
                      index adaf35d45..9d1eaad77 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface ListTaskPushNotificationConfigsRequestOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponse.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsResponse.java
                      similarity index 78%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponse.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsResponse.java
                      index 231e22f89..fbeabf775 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponse.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsResponse.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -39,20 +39,20 @@ private ListTaskPushNotificationConfigsResponse() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.ListTaskPushNotificationConfigsResponse.class, io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder.class);
                      +            org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.class, org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.Builder.class);
                         }
                       
                         public static final int CONFIGS_FIELD_NUMBER = 1;
                         @SuppressWarnings("serial")
                      -  private java.util.List configs_;
                      +  private java.util.List configs_;
                         /**
                          * 
                          * The list of push notification configurations.
                      @@ -61,7 +61,7 @@ private ListTaskPushNotificationConfigsResponse() {
                          * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                          */
                         @java.lang.Override
                      -  public java.util.List getConfigsList() {
                      +  public java.util.List getConfigsList() {
                           return configs_;
                         }
                         /**
                      @@ -72,7 +72,7 @@ public java.util.List getConfigsList() {
                          * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getConfigsOrBuilderList() {
                           return configs_;
                         }
                      @@ -95,7 +95,7 @@ public int getConfigsCount() {
                          * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) {
                      +  public org.a2aproject.sdk.grpc.TaskPushNotificationConfig getConfigs(int index) {
                           return configs_.get(index);
                         }
                         /**
                      @@ -106,7 +106,7 @@ public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) {
                          * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder(
                      +  public org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder(
                             int index) {
                           return configs_.get(index);
                         }
                      @@ -204,10 +204,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.ListTaskPushNotificationConfigsResponse)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.ListTaskPushNotificationConfigsResponse other = (io.a2a.grpc.ListTaskPushNotificationConfigsResponse) obj;
                      +    org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse other = (org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse) obj;
                       
                           if (!getConfigsList()
                               .equals(other.getConfigsList())) return false;
                      @@ -235,44 +235,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -280,26 +280,26 @@ public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -312,7 +312,7 @@ public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.ListTaskPushNotificationConfigsResponse prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -338,21 +338,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ListTaskPushNotificationConfigsResponse)
                      -      io.a2a.grpc.ListTaskPushNotificationConfigsResponseOrBuilder {
                      +      org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponseOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.ListTaskPushNotificationConfigsResponse.class, io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder.class);
                      +              org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.class, org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -380,17 +380,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTaskPushNotificationConfigsResponse_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstanceForType() {
                      -      return io.a2a.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTaskPushNotificationConfigsResponse build() {
                      -      io.a2a.grpc.ListTaskPushNotificationConfigsResponse result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse build() {
                      +      org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -398,15 +398,15 @@ public io.a2a.grpc.ListTaskPushNotificationConfigsResponse build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTaskPushNotificationConfigsResponse buildPartial() {
                      -      io.a2a.grpc.ListTaskPushNotificationConfigsResponse result = new io.a2a.grpc.ListTaskPushNotificationConfigsResponse(this);
                      +    public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse buildPartial() {
                      +      org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse result = new org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse(this);
                             buildPartialRepeatedFields(result);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartialRepeatedFields(io.a2a.grpc.ListTaskPushNotificationConfigsResponse result) {
                      +    private void buildPartialRepeatedFields(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse result) {
                             if (configsBuilder_ == null) {
                               if (((bitField0_ & 0x00000001) != 0)) {
                                 configs_ = java.util.Collections.unmodifiableList(configs_);
                      @@ -418,7 +418,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.ListTaskPushNotificationConf
                             }
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigsResponse result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000002) != 0)) {
                               result.nextPageToken_ = nextPageToken_;
                      @@ -427,16 +427,16 @@ private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigsResponse r
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.ListTaskPushNotificationConfigsResponse) {
                      -        return mergeFrom((io.a2a.grpc.ListTaskPushNotificationConfigsResponse)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigsResponse other) {
                      -      if (other == io.a2a.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse other) {
                      +      if (other == org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.getDefaultInstance()) return this;
                             if (configsBuilder_ == null) {
                               if (!other.configs_.isEmpty()) {
                                 if (configs_.isEmpty()) {
                      @@ -495,9 +495,9 @@ public Builder mergeFrom(
                                     done = true;
                                     break;
                                   case 10: {
                      -              io.a2a.grpc.TaskPushNotificationConfig m =
                      +              org.a2aproject.sdk.grpc.TaskPushNotificationConfig m =
                                         input.readMessage(
                      -                      io.a2a.grpc.TaskPushNotificationConfig.parser(),
                      +                      org.a2aproject.sdk.grpc.TaskPushNotificationConfig.parser(),
                                             extensionRegistry);
                                     if (configsBuilder_ == null) {
                                       ensureConfigsIsMutable();
                      @@ -529,17 +529,17 @@ public Builder mergeFrom(
                           }
                           private int bitField0_;
                       
                      -    private java.util.List configs_ =
                      +    private java.util.List configs_ =
                             java.util.Collections.emptyList();
                           private void ensureConfigsIsMutable() {
                             if (!((bitField0_ & 0x00000001) != 0)) {
                      -        configs_ = new java.util.ArrayList(configs_);
                      +        configs_ = new java.util.ArrayList(configs_);
                               bitField0_ |= 0x00000001;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> configsBuilder_;
                      +        org.a2aproject.sdk.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder> configsBuilder_;
                       
                           /**
                            * 
                      @@ -548,7 +548,7 @@ private void ensureConfigsIsMutable() {
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public java.util.List getConfigsList() {
                      +    public java.util.List getConfigsList() {
                             if (configsBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(configs_);
                             } else {
                      @@ -576,7 +576,7 @@ public int getConfigsCount() {
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) {
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig getConfigs(int index) {
                             if (configsBuilder_ == null) {
                               return configs_.get(index);
                             } else {
                      @@ -591,7 +591,7 @@ public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) {
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                           public Builder setConfigs(
                      -        int index, io.a2a.grpc.TaskPushNotificationConfig value) {
                      +        int index, org.a2aproject.sdk.grpc.TaskPushNotificationConfig value) {
                             if (configsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -612,7 +612,7 @@ public Builder setConfigs(
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                           public Builder setConfigs(
                      -        int index, io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder builderForValue) {
                             if (configsBuilder_ == null) {
                               ensureConfigsIsMutable();
                               configs_.set(index, builderForValue.build());
                      @@ -629,7 +629,7 @@ public Builder setConfigs(
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public Builder addConfigs(io.a2a.grpc.TaskPushNotificationConfig value) {
                      +    public Builder addConfigs(org.a2aproject.sdk.grpc.TaskPushNotificationConfig value) {
                             if (configsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -650,7 +650,7 @@ public Builder addConfigs(io.a2a.grpc.TaskPushNotificationConfig value) {
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                           public Builder addConfigs(
                      -        int index, io.a2a.grpc.TaskPushNotificationConfig value) {
                      +        int index, org.a2aproject.sdk.grpc.TaskPushNotificationConfig value) {
                             if (configsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -671,7 +671,7 @@ public Builder addConfigs(
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                           public Builder addConfigs(
                      -        io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder builderForValue) {
                             if (configsBuilder_ == null) {
                               ensureConfigsIsMutable();
                               configs_.add(builderForValue.build());
                      @@ -689,7 +689,7 @@ public Builder addConfigs(
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                           public Builder addConfigs(
                      -        int index, io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder builderForValue) {
                             if (configsBuilder_ == null) {
                               ensureConfigsIsMutable();
                               configs_.add(index, builderForValue.build());
                      @@ -707,7 +707,7 @@ public Builder addConfigs(
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                           public Builder addAllConfigs(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (configsBuilder_ == null) {
                               ensureConfigsIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -759,7 +759,7 @@ public Builder removeConfigs(int index) {
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public io.a2a.grpc.TaskPushNotificationConfig.Builder getConfigsBuilder(
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder getConfigsBuilder(
                               int index) {
                             return internalGetConfigsFieldBuilder().getBuilder(index);
                           }
                      @@ -770,7 +770,7 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder getConfigsBuilder(
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder(
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder(
                               int index) {
                             if (configsBuilder_ == null) {
                               return configs_.get(index);  } else {
                      @@ -784,7 +784,7 @@ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getConfigsOrBuilderList() {
                             if (configsBuilder_ != null) {
                               return configsBuilder_.getMessageOrBuilderList();
                      @@ -799,9 +799,9 @@ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder() {
                             return internalGetConfigsFieldBuilder().addBuilder(
                      -          io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -810,10 +810,10 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder() {
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder(
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder(
                               int index) {
                             return internalGetConfigsFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -822,16 +822,16 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder(
                            *
                            * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getConfigsBuilderList() {
                             return internalGetConfigsFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> 
                      +        org.a2aproject.sdk.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder> 
                               internalGetConfigsFieldBuilder() {
                             if (configsBuilder_ == null) {
                               configsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder>(
                      +            org.a2aproject.sdk.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder>(
                                       configs_,
                                       ((bitField0_ & 0x00000001) != 0),
                                       getParentForChildren(),
                      @@ -937,12 +937,12 @@ public Builder setNextPageTokenBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.ListTaskPushNotificationConfigsResponse)
                      -  private static final io.a2a.grpc.ListTaskPushNotificationConfigsResponse DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.ListTaskPushNotificationConfigsResponse();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse();
                         }
                       
                      -  public static io.a2a.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -978,7 +978,7 @@ public com.google.protobuf.Parser getPa
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java
                      similarity index 84%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java
                      index 1aa552f31..ea8b090df 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTaskPushNotificationConfigsResponseOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface ListTaskPushNotificationConfigsResponseOrBuilder extends
                      @@ -17,7 +17,7 @@ public interface ListTaskPushNotificationConfigsResponseOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getConfigsList();
                         /**
                          * 
                      @@ -26,7 +26,7 @@ public interface ListTaskPushNotificationConfigsResponseOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                          */
                      -  io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index);
                      +  org.a2aproject.sdk.grpc.TaskPushNotificationConfig getConfigs(int index);
                         /**
                          * 
                          * The list of push notification configurations.
                      @@ -42,7 +42,7 @@ public interface ListTaskPushNotificationConfigsResponseOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getConfigsOrBuilderList();
                         /**
                          * 
                      @@ -51,7 +51,7 @@ public interface ListTaskPushNotificationConfigsResponseOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.TaskPushNotificationConfig configs = 1;
                          */
                      -  io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder(
                      +  org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder(
                             int index);
                       
                         /**
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksRequest.java
                      similarity index 92%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksRequest.java
                      index 414660319..9d183147b 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -40,15 +40,15 @@ private ListTasksRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.ListTasksRequest.class, io.a2a.grpc.ListTasksRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.ListTasksRequest.class, org.a2aproject.sdk.grpc.ListTasksRequest.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -167,9 +167,9 @@ public java.lang.String getContextId() {
                          * .lf.a2a.v1.TaskState status = 3;
                          * @return The status.
                          */
                      -  @java.lang.Override public io.a2a.grpc.TaskState getStatus() {
                      -    io.a2a.grpc.TaskState result = io.a2a.grpc.TaskState.forNumber(status_);
                      -    return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result;
                      +  @java.lang.Override public org.a2aproject.sdk.grpc.TaskState getStatus() {
                      +    org.a2aproject.sdk.grpc.TaskState result = org.a2aproject.sdk.grpc.TaskState.forNumber(status_);
                      +    return result == null ? org.a2aproject.sdk.grpc.TaskState.UNRECOGNIZED : result;
                         }
                       
                         public static final int PAGE_SIZE_FIELD_NUMBER = 4;
                      @@ -373,7 +373,7 @@ public void writeTo(com.google.protobuf.CodedOutputStream output)
                           if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) {
                             com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_);
                           }
                      -    if (status_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) {
                      +    if (status_ != org.a2aproject.sdk.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) {
                             output.writeEnum(3, status_);
                           }
                           if (((bitField0_ & 0x00000001) != 0)) {
                      @@ -406,7 +406,7 @@ public int getSerializedSize() {
                           if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) {
                             size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_);
                           }
                      -    if (status_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) {
                      +    if (status_ != org.a2aproject.sdk.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) {
                             size += com.google.protobuf.CodedOutputStream
                               .computeEnumSize(3, status_);
                           }
                      @@ -439,10 +439,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.ListTasksRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.ListTasksRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.ListTasksRequest other = (io.a2a.grpc.ListTasksRequest) obj;
                      +    org.a2aproject.sdk.grpc.ListTasksRequest other = (org.a2aproject.sdk.grpc.ListTasksRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -512,44 +512,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -557,26 +557,26 @@ public static io.a2a.grpc.ListTasksRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.ListTasksRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.ListTasksRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ListTasksRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -589,7 +589,7 @@ public static io.a2a.grpc.ListTasksRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.ListTasksRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.ListTasksRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -614,21 +614,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ListTasksRequest)
                      -      io.a2a.grpc.ListTasksRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.ListTasksRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.ListTasksRequest.class, io.a2a.grpc.ListTasksRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.ListTasksRequest.class, org.a2aproject.sdk.grpc.ListTasksRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.ListTasksRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.ListTasksRequest.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -666,17 +666,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTasksRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.ListTasksRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.ListTasksRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.ListTasksRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTasksRequest build() {
                      -      io.a2a.grpc.ListTasksRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.ListTasksRequest build() {
                      +      org.a2aproject.sdk.grpc.ListTasksRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -684,14 +684,14 @@ public io.a2a.grpc.ListTasksRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTasksRequest buildPartial() {
                      -      io.a2a.grpc.ListTasksRequest result = new io.a2a.grpc.ListTasksRequest(this);
                      +    public org.a2aproject.sdk.grpc.ListTasksRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.ListTasksRequest result = new org.a2aproject.sdk.grpc.ListTasksRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.ListTasksRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.ListTasksRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -729,16 +729,16 @@ private void buildPartial0(io.a2a.grpc.ListTasksRequest result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.ListTasksRequest) {
                      -        return mergeFrom((io.a2a.grpc.ListTasksRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.ListTasksRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.ListTasksRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.ListTasksRequest other) {
                      -      if (other == io.a2a.grpc.ListTasksRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.ListTasksRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.ListTasksRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -1074,9 +1074,9 @@ public Builder setStatusValue(int value) {
                            * @return The status.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskState getStatus() {
                      -      io.a2a.grpc.TaskState result = io.a2a.grpc.TaskState.forNumber(status_);
                      -      return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result;
                      +    public org.a2aproject.sdk.grpc.TaskState getStatus() {
                      +      org.a2aproject.sdk.grpc.TaskState result = org.a2aproject.sdk.grpc.TaskState.forNumber(status_);
                      +      return result == null ? org.a2aproject.sdk.grpc.TaskState.UNRECOGNIZED : result;
                           }
                           /**
                            * 
                      @@ -1087,7 +1087,7 @@ public io.a2a.grpc.TaskState getStatus() {
                            * @param value The status to set.
                            * @return This builder for chaining.
                            */
                      -    public Builder setStatus(io.a2a.grpc.TaskState value) {
                      +    public Builder setStatus(org.a2aproject.sdk.grpc.TaskState value) {
                             if (value == null) { throw new NullPointerException(); }
                             bitField0_ |= 0x00000004;
                             status_ = value.getNumber();
                      @@ -1565,12 +1565,12 @@ public Builder clearIncludeArtifacts() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.ListTasksRequest)
                      -  private static final io.a2a.grpc.ListTasksRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.ListTasksRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.ListTasksRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.ListTasksRequest();
                         }
                       
                      -  public static io.a2a.grpc.ListTasksRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.ListTasksRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1606,7 +1606,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.ListTasksRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.ListTasksRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksRequestOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksRequestOrBuilder.java
                      index d577c8507..b6ab50f5d 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface ListTasksRequestOrBuilder extends
                      @@ -67,7 +67,7 @@ public interface ListTasksRequestOrBuilder extends
                          * .lf.a2a.v1.TaskState status = 3;
                          * @return The status.
                          */
                      -  io.a2a.grpc.TaskState getStatus();
                      +  org.a2aproject.sdk.grpc.TaskState getStatus();
                       
                         /**
                          * 
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksResponse.java
                      similarity index 85%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksResponse.java
                      index 4eaf740db..24d06f6bf 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksResponse.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,20 +38,20 @@ private ListTasksResponse() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.ListTasksResponse.class, io.a2a.grpc.ListTasksResponse.Builder.class);
                      +            org.a2aproject.sdk.grpc.ListTasksResponse.class, org.a2aproject.sdk.grpc.ListTasksResponse.Builder.class);
                         }
                       
                         public static final int TASKS_FIELD_NUMBER = 1;
                         @SuppressWarnings("serial")
                      -  private java.util.List tasks_;
                      +  private java.util.List tasks_;
                         /**
                          * 
                          * Array of tasks matching the specified criteria.
                      @@ -60,7 +60,7 @@ private ListTasksResponse() {
                          * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List getTasksList() {
                      +  public java.util.List getTasksList() {
                           return tasks_;
                         }
                         /**
                      @@ -71,7 +71,7 @@ public java.util.List getTasksList() {
                          * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getTasksOrBuilderList() {
                           return tasks_;
                         }
                      @@ -94,7 +94,7 @@ public int getTasksCount() {
                          * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Task getTasks(int index) {
                      +  public org.a2aproject.sdk.grpc.Task getTasks(int index) {
                           return tasks_.get(index);
                         }
                         /**
                      @@ -105,7 +105,7 @@ public io.a2a.grpc.Task getTasks(int index) {
                          * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder(
                      +  public org.a2aproject.sdk.grpc.TaskOrBuilder getTasksOrBuilder(
                             int index) {
                           return tasks_.get(index);
                         }
                      @@ -247,10 +247,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.ListTasksResponse)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.ListTasksResponse)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.ListTasksResponse other = (io.a2a.grpc.ListTasksResponse) obj;
                      +    org.a2aproject.sdk.grpc.ListTasksResponse other = (org.a2aproject.sdk.grpc.ListTasksResponse) obj;
                       
                           if (!getTasksList()
                               .equals(other.getTasksList())) return false;
                      @@ -286,44 +286,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -331,26 +331,26 @@ public static io.a2a.grpc.ListTasksResponse parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.ListTasksResponse parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.ListTasksResponse parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.ListTasksResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -363,7 +363,7 @@ public static io.a2a.grpc.ListTasksResponse parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.ListTasksResponse prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.ListTasksResponse prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -388,21 +388,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.ListTasksResponse)
                      -      io.a2a.grpc.ListTasksResponseOrBuilder {
                      +      org.a2aproject.sdk.grpc.ListTasksResponseOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.ListTasksResponse.class, io.a2a.grpc.ListTasksResponse.Builder.class);
                      +              org.a2aproject.sdk.grpc.ListTasksResponse.class, org.a2aproject.sdk.grpc.ListTasksResponse.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.ListTasksResponse.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.ListTasksResponse.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -432,17 +432,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_ListTasksResponse_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTasksResponse getDefaultInstanceForType() {
                      -      return io.a2a.grpc.ListTasksResponse.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.ListTasksResponse getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.ListTasksResponse.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTasksResponse build() {
                      -      io.a2a.grpc.ListTasksResponse result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.ListTasksResponse build() {
                      +      org.a2aproject.sdk.grpc.ListTasksResponse result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -450,15 +450,15 @@ public io.a2a.grpc.ListTasksResponse build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.ListTasksResponse buildPartial() {
                      -      io.a2a.grpc.ListTasksResponse result = new io.a2a.grpc.ListTasksResponse(this);
                      +    public org.a2aproject.sdk.grpc.ListTasksResponse buildPartial() {
                      +      org.a2aproject.sdk.grpc.ListTasksResponse result = new org.a2aproject.sdk.grpc.ListTasksResponse(this);
                             buildPartialRepeatedFields(result);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartialRepeatedFields(io.a2a.grpc.ListTasksResponse result) {
                      +    private void buildPartialRepeatedFields(org.a2aproject.sdk.grpc.ListTasksResponse result) {
                             if (tasksBuilder_ == null) {
                               if (((bitField0_ & 0x00000001) != 0)) {
                                 tasks_ = java.util.Collections.unmodifiableList(tasks_);
                      @@ -470,7 +470,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.ListTasksResponse result) {
                             }
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.ListTasksResponse result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.ListTasksResponse result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000002) != 0)) {
                               result.nextPageToken_ = nextPageToken_;
                      @@ -485,16 +485,16 @@ private void buildPartial0(io.a2a.grpc.ListTasksResponse result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.ListTasksResponse) {
                      -        return mergeFrom((io.a2a.grpc.ListTasksResponse)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.ListTasksResponse) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.ListTasksResponse)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.ListTasksResponse other) {
                      -      if (other == io.a2a.grpc.ListTasksResponse.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.ListTasksResponse other) {
                      +      if (other == org.a2aproject.sdk.grpc.ListTasksResponse.getDefaultInstance()) return this;
                             if (tasksBuilder_ == null) {
                               if (!other.tasks_.isEmpty()) {
                                 if (tasks_.isEmpty()) {
                      @@ -559,9 +559,9 @@ public Builder mergeFrom(
                                     done = true;
                                     break;
                                   case 10: {
                      -              io.a2a.grpc.Task m =
                      +              org.a2aproject.sdk.grpc.Task m =
                                         input.readMessage(
                      -                      io.a2a.grpc.Task.parser(),
                      +                      org.a2aproject.sdk.grpc.Task.parser(),
                                             extensionRegistry);
                                     if (tasksBuilder_ == null) {
                                       ensureTasksIsMutable();
                      @@ -603,17 +603,17 @@ public Builder mergeFrom(
                           }
                           private int bitField0_;
                       
                      -    private java.util.List tasks_ =
                      +    private java.util.List tasks_ =
                             java.util.Collections.emptyList();
                           private void ensureTasksIsMutable() {
                             if (!((bitField0_ & 0x00000001) != 0)) {
                      -        tasks_ = new java.util.ArrayList(tasks_);
                      +        tasks_ = new java.util.ArrayList(tasks_);
                               bitField0_ |= 0x00000001;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> tasksBuilder_;
                      +        org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder> tasksBuilder_;
                       
                           /**
                            * 
                      @@ -622,7 +622,7 @@ private void ensureTasksIsMutable() {
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List getTasksList() {
                      +    public java.util.List getTasksList() {
                             if (tasksBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(tasks_);
                             } else {
                      @@ -650,7 +650,7 @@ public int getTasksCount() {
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Task getTasks(int index) {
                      +    public org.a2aproject.sdk.grpc.Task getTasks(int index) {
                             if (tasksBuilder_ == null) {
                               return tasks_.get(index);
                             } else {
                      @@ -665,7 +665,7 @@ public io.a2a.grpc.Task getTasks(int index) {
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setTasks(
                      -        int index, io.a2a.grpc.Task value) {
                      +        int index, org.a2aproject.sdk.grpc.Task value) {
                             if (tasksBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -686,7 +686,7 @@ public Builder setTasks(
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setTasks(
                      -        int index, io.a2a.grpc.Task.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Task.Builder builderForValue) {
                             if (tasksBuilder_ == null) {
                               ensureTasksIsMutable();
                               tasks_.set(index, builderForValue.build());
                      @@ -703,7 +703,7 @@ public Builder setTasks(
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder addTasks(io.a2a.grpc.Task value) {
                      +    public Builder addTasks(org.a2aproject.sdk.grpc.Task value) {
                             if (tasksBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -724,7 +724,7 @@ public Builder addTasks(io.a2a.grpc.Task value) {
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addTasks(
                      -        int index, io.a2a.grpc.Task value) {
                      +        int index, org.a2aproject.sdk.grpc.Task value) {
                             if (tasksBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -745,7 +745,7 @@ public Builder addTasks(
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addTasks(
                      -        io.a2a.grpc.Task.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Task.Builder builderForValue) {
                             if (tasksBuilder_ == null) {
                               ensureTasksIsMutable();
                               tasks_.add(builderForValue.build());
                      @@ -763,7 +763,7 @@ public Builder addTasks(
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addTasks(
                      -        int index, io.a2a.grpc.Task.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Task.Builder builderForValue) {
                             if (tasksBuilder_ == null) {
                               ensureTasksIsMutable();
                               tasks_.add(index, builderForValue.build());
                      @@ -781,7 +781,7 @@ public Builder addTasks(
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addAllTasks(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (tasksBuilder_ == null) {
                               ensureTasksIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -833,7 +833,7 @@ public Builder removeTasks(int index) {
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Task.Builder getTasksBuilder(
                      +    public org.a2aproject.sdk.grpc.Task.Builder getTasksBuilder(
                               int index) {
                             return internalGetTasksFieldBuilder().getBuilder(index);
                           }
                      @@ -844,7 +844,7 @@ public io.a2a.grpc.Task.Builder getTasksBuilder(
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder(
                      +    public org.a2aproject.sdk.grpc.TaskOrBuilder getTasksOrBuilder(
                               int index) {
                             if (tasksBuilder_ == null) {
                               return tasks_.get(index);  } else {
                      @@ -858,7 +858,7 @@ public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getTasksOrBuilderList() {
                             if (tasksBuilder_ != null) {
                               return tasksBuilder_.getMessageOrBuilderList();
                      @@ -873,9 +873,9 @@ public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Task.Builder addTasksBuilder() {
                      +    public org.a2aproject.sdk.grpc.Task.Builder addTasksBuilder() {
                             return internalGetTasksFieldBuilder().addBuilder(
                      -          io.a2a.grpc.Task.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.Task.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -884,10 +884,10 @@ public io.a2a.grpc.Task.Builder addTasksBuilder() {
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Task.Builder addTasksBuilder(
                      +    public org.a2aproject.sdk.grpc.Task.Builder addTasksBuilder(
                               int index) {
                             return internalGetTasksFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.Task.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.Task.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -896,16 +896,16 @@ public io.a2a.grpc.Task.Builder addTasksBuilder(
                            *
                            * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getTasksBuilderList() {
                             return internalGetTasksFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder> 
                               internalGetTasksFieldBuilder() {
                             if (tasksBuilder_ == null) {
                               tasksBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder>(
                      +            org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder>(
                                       tasks_,
                                       ((bitField0_ & 0x00000001) != 0),
                                       getParentForChildren(),
                      @@ -1099,12 +1099,12 @@ public Builder clearTotalSize() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.ListTasksResponse)
                      -  private static final io.a2a.grpc.ListTasksResponse DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.ListTasksResponse DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.ListTasksResponse();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.ListTasksResponse();
                         }
                       
                      -  public static io.a2a.grpc.ListTasksResponse getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.ListTasksResponse getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1140,7 +1140,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.ListTasksResponse getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.ListTasksResponse getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksResponseOrBuilder.java
                      similarity index 90%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksResponseOrBuilder.java
                      index cbaddefbf..b8a39881a 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/ListTasksResponseOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface ListTasksResponseOrBuilder extends
                      @@ -17,7 +17,7 @@ public interface ListTasksResponseOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getTasksList();
                         /**
                          * 
                      @@ -26,7 +26,7 @@ public interface ListTasksResponseOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.Task getTasks(int index);
                      +  org.a2aproject.sdk.grpc.Task getTasks(int index);
                         /**
                          * 
                          * Array of tasks matching the specified criteria.
                      @@ -42,7 +42,7 @@ public interface ListTasksResponseOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getTasksOrBuilderList();
                         /**
                          * 
                      @@ -51,7 +51,7 @@ public interface ListTasksResponseOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.TaskOrBuilder getTasksOrBuilder(
                      +  org.a2aproject.sdk.grpc.TaskOrBuilder getTasksOrBuilder(
                             int index);
                       
                         /**
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Message.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Message.java
                      similarity index 91%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/Message.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Message.java
                      index ac9dbdc6f..d5145ad74 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/Message.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Message.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -50,15 +50,15 @@ private Message() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Message_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.Message.class, io.a2a.grpc.Message.Builder.class);
                      +            org.a2aproject.sdk.grpc.Message.class, org.a2aproject.sdk.grpc.Message.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -224,14 +224,14 @@ public java.lang.String getTaskId() {
                          * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED];
                          * @return The role.
                          */
                      -  @java.lang.Override public io.a2a.grpc.Role getRole() {
                      -    io.a2a.grpc.Role result = io.a2a.grpc.Role.forNumber(role_);
                      -    return result == null ? io.a2a.grpc.Role.UNRECOGNIZED : result;
                      +  @java.lang.Override public org.a2aproject.sdk.grpc.Role getRole() {
                      +    org.a2aproject.sdk.grpc.Role result = org.a2aproject.sdk.grpc.Role.forNumber(role_);
                      +    return result == null ? org.a2aproject.sdk.grpc.Role.UNRECOGNIZED : result;
                         }
                       
                         public static final int PARTS_FIELD_NUMBER = 5;
                         @SuppressWarnings("serial")
                      -  private java.util.List parts_;
                      +  private java.util.List parts_;
                         /**
                          * 
                          * Parts is the container of the message content.
                      @@ -240,7 +240,7 @@ public java.lang.String getTaskId() {
                          * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List getPartsList() {
                      +  public java.util.List getPartsList() {
                           return parts_;
                         }
                         /**
                      @@ -251,7 +251,7 @@ public java.util.List getPartsList() {
                          * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getPartsOrBuilderList() {
                           return parts_;
                         }
                      @@ -274,7 +274,7 @@ public int getPartsCount() {
                          * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Part getParts(int index) {
                      +  public org.a2aproject.sdk.grpc.Part getParts(int index) {
                           return parts_.get(index);
                         }
                         /**
                      @@ -285,7 +285,7 @@ public io.a2a.grpc.Part getParts(int index) {
                          * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                      +  public org.a2aproject.sdk.grpc.PartOrBuilder getPartsOrBuilder(
                             int index) {
                           return parts_.get(index);
                         }
                      @@ -457,7 +457,7 @@ public void writeTo(com.google.protobuf.CodedOutputStream output)
                           if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) {
                             com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_);
                           }
                      -    if (role_ != io.a2a.grpc.Role.ROLE_UNSPECIFIED.getNumber()) {
                      +    if (role_ != org.a2aproject.sdk.grpc.Role.ROLE_UNSPECIFIED.getNumber()) {
                             output.writeEnum(4, role_);
                           }
                           for (int i = 0; i < parts_.size(); i++) {
                      @@ -490,7 +490,7 @@ public int getSerializedSize() {
                           if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) {
                             size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_);
                           }
                      -    if (role_ != io.a2a.grpc.Role.ROLE_UNSPECIFIED.getNumber()) {
                      +    if (role_ != org.a2aproject.sdk.grpc.Role.ROLE_UNSPECIFIED.getNumber()) {
                             size += com.google.protobuf.CodedOutputStream
                               .computeEnumSize(4, role_);
                           }
                      @@ -528,10 +528,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.Message)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.Message)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.Message other = (io.a2a.grpc.Message) obj;
                      +    org.a2aproject.sdk.grpc.Message other = (org.a2aproject.sdk.grpc.Message) obj;
                       
                           if (!getMessageId()
                               .equals(other.getMessageId())) return false;
                      @@ -591,44 +591,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.Message parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -636,26 +636,26 @@ public static io.a2a.grpc.Message parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.Message parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.Message parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.Message parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.Message parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Message parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -668,7 +668,7 @@ public static io.a2a.grpc.Message parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.Message prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.Message prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -698,21 +698,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.Message)
                      -      io.a2a.grpc.MessageOrBuilder {
                      +      org.a2aproject.sdk.grpc.MessageOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Message_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.Message.class, io.a2a.grpc.Message.Builder.class);
                      +              org.a2aproject.sdk.grpc.Message.class, org.a2aproject.sdk.grpc.Message.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.Message.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.Message.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -759,17 +759,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Message_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Message getDefaultInstanceForType() {
                      -      return io.a2a.grpc.Message.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.Message getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Message build() {
                      -      io.a2a.grpc.Message result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.Message build() {
                      +      org.a2aproject.sdk.grpc.Message result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -777,15 +777,15 @@ public io.a2a.grpc.Message build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Message buildPartial() {
                      -      io.a2a.grpc.Message result = new io.a2a.grpc.Message(this);
                      +    public org.a2aproject.sdk.grpc.Message buildPartial() {
                      +      org.a2aproject.sdk.grpc.Message result = new org.a2aproject.sdk.grpc.Message(this);
                             buildPartialRepeatedFields(result);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartialRepeatedFields(io.a2a.grpc.Message result) {
                      +    private void buildPartialRepeatedFields(org.a2aproject.sdk.grpc.Message result) {
                             if (partsBuilder_ == null) {
                               if (((bitField0_ & 0x00000010) != 0)) {
                                 parts_ = java.util.Collections.unmodifiableList(parts_);
                      @@ -797,7 +797,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.Message result) {
                             }
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.Message result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.Message result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.messageId_ = messageId_;
                      @@ -831,16 +831,16 @@ private void buildPartial0(io.a2a.grpc.Message result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.Message) {
                      -        return mergeFrom((io.a2a.grpc.Message)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.Message) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.Message)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.Message other) {
                      -      if (other == io.a2a.grpc.Message.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.Message other) {
                      +      if (other == org.a2aproject.sdk.grpc.Message.getDefaultInstance()) return this;
                             if (!other.getMessageId().isEmpty()) {
                               messageId_ = other.messageId_;
                               bitField0_ |= 0x00000001;
                      @@ -955,9 +955,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 32
                                   case 42: {
                      -              io.a2a.grpc.Part m =
                      +              org.a2aproject.sdk.grpc.Part m =
                                         input.readMessage(
                      -                      io.a2a.grpc.Part.parser(),
                      +                      org.a2aproject.sdk.grpc.Part.parser(),
                                             extensionRegistry);
                                     if (partsBuilder_ == null) {
                                       ensurePartsIsMutable();
                      @@ -1315,9 +1315,9 @@ public Builder setRoleValue(int value) {
                            * @return The role.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.Role getRole() {
                      -      io.a2a.grpc.Role result = io.a2a.grpc.Role.forNumber(role_);
                      -      return result == null ? io.a2a.grpc.Role.UNRECOGNIZED : result;
                      +    public org.a2aproject.sdk.grpc.Role getRole() {
                      +      org.a2aproject.sdk.grpc.Role result = org.a2aproject.sdk.grpc.Role.forNumber(role_);
                      +      return result == null ? org.a2aproject.sdk.grpc.Role.UNRECOGNIZED : result;
                           }
                           /**
                            * 
                      @@ -1328,7 +1328,7 @@ public io.a2a.grpc.Role getRole() {
                            * @param value The role to set.
                            * @return This builder for chaining.
                            */
                      -    public Builder setRole(io.a2a.grpc.Role value) {
                      +    public Builder setRole(org.a2aproject.sdk.grpc.Role value) {
                             if (value == null) { throw new NullPointerException(); }
                             bitField0_ |= 0x00000008;
                             role_ = value.getNumber();
                      @@ -1350,17 +1350,17 @@ public Builder clearRole() {
                             return this;
                           }
                       
                      -    private java.util.List parts_ =
                      +    private java.util.List parts_ =
                             java.util.Collections.emptyList();
                           private void ensurePartsIsMutable() {
                             if (!((bitField0_ & 0x00000010) != 0)) {
                      -        parts_ = new java.util.ArrayList(parts_);
                      +        parts_ = new java.util.ArrayList(parts_);
                               bitField0_ |= 0x00000010;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder> partsBuilder_;
                      +        org.a2aproject.sdk.grpc.Part, org.a2aproject.sdk.grpc.Part.Builder, org.a2aproject.sdk.grpc.PartOrBuilder> partsBuilder_;
                       
                           /**
                            * 
                      @@ -1369,7 +1369,7 @@ private void ensurePartsIsMutable() {
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List getPartsList() {
                      +    public java.util.List getPartsList() {
                             if (partsBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(parts_);
                             } else {
                      @@ -1397,7 +1397,7 @@ public int getPartsCount() {
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Part getParts(int index) {
                      +    public org.a2aproject.sdk.grpc.Part getParts(int index) {
                             if (partsBuilder_ == null) {
                               return parts_.get(index);
                             } else {
                      @@ -1412,7 +1412,7 @@ public io.a2a.grpc.Part getParts(int index) {
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setParts(
                      -        int index, io.a2a.grpc.Part value) {
                      +        int index, org.a2aproject.sdk.grpc.Part value) {
                             if (partsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1433,7 +1433,7 @@ public Builder setParts(
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setParts(
                      -        int index, io.a2a.grpc.Part.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Part.Builder builderForValue) {
                             if (partsBuilder_ == null) {
                               ensurePartsIsMutable();
                               parts_.set(index, builderForValue.build());
                      @@ -1450,7 +1450,7 @@ public Builder setParts(
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder addParts(io.a2a.grpc.Part value) {
                      +    public Builder addParts(org.a2aproject.sdk.grpc.Part value) {
                             if (partsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1471,7 +1471,7 @@ public Builder addParts(io.a2a.grpc.Part value) {
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addParts(
                      -        int index, io.a2a.grpc.Part value) {
                      +        int index, org.a2aproject.sdk.grpc.Part value) {
                             if (partsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1492,7 +1492,7 @@ public Builder addParts(
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addParts(
                      -        io.a2a.grpc.Part.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Part.Builder builderForValue) {
                             if (partsBuilder_ == null) {
                               ensurePartsIsMutable();
                               parts_.add(builderForValue.build());
                      @@ -1510,7 +1510,7 @@ public Builder addParts(
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addParts(
                      -        int index, io.a2a.grpc.Part.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Part.Builder builderForValue) {
                             if (partsBuilder_ == null) {
                               ensurePartsIsMutable();
                               parts_.add(index, builderForValue.build());
                      @@ -1528,7 +1528,7 @@ public Builder addParts(
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder addAllParts(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (partsBuilder_ == null) {
                               ensurePartsIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -1580,7 +1580,7 @@ public Builder removeParts(int index) {
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Part.Builder getPartsBuilder(
                      +    public org.a2aproject.sdk.grpc.Part.Builder getPartsBuilder(
                               int index) {
                             return internalGetPartsFieldBuilder().getBuilder(index);
                           }
                      @@ -1591,7 +1591,7 @@ public io.a2a.grpc.Part.Builder getPartsBuilder(
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                      +    public org.a2aproject.sdk.grpc.PartOrBuilder getPartsOrBuilder(
                               int index) {
                             if (partsBuilder_ == null) {
                               return parts_.get(index);  } else {
                      @@ -1605,7 +1605,7 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getPartsOrBuilderList() {
                             if (partsBuilder_ != null) {
                               return partsBuilder_.getMessageOrBuilderList();
                      @@ -1620,9 +1620,9 @@ public io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Part.Builder addPartsBuilder() {
                      +    public org.a2aproject.sdk.grpc.Part.Builder addPartsBuilder() {
                             return internalGetPartsFieldBuilder().addBuilder(
                      -          io.a2a.grpc.Part.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.Part.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1631,10 +1631,10 @@ public io.a2a.grpc.Part.Builder addPartsBuilder() {
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Part.Builder addPartsBuilder(
                      +    public org.a2aproject.sdk.grpc.Part.Builder addPartsBuilder(
                               int index) {
                             return internalGetPartsFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.Part.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.Part.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1643,16 +1643,16 @@ public io.a2a.grpc.Part.Builder addPartsBuilder(
                            *
                            * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getPartsBuilderList() {
                             return internalGetPartsFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Part, org.a2aproject.sdk.grpc.Part.Builder, org.a2aproject.sdk.grpc.PartOrBuilder> 
                               internalGetPartsFieldBuilder() {
                             if (partsBuilder_ == null) {
                               partsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder>(
                      +            org.a2aproject.sdk.grpc.Part, org.a2aproject.sdk.grpc.Part.Builder, org.a2aproject.sdk.grpc.PartOrBuilder>(
                                       parts_,
                                       ((bitField0_ & 0x00000010) != 0),
                                       getParentForChildren(),
                      @@ -2117,12 +2117,12 @@ public Builder addReferenceTaskIdsBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.Message)
                      -  private static final io.a2a.grpc.Message DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.Message DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.Message();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.Message();
                         }
                       
                      -  public static io.a2a.grpc.Message getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.Message getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -2158,7 +2158,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.Message getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.Message getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MessageOrBuilder.java
                      similarity index 95%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MessageOrBuilder.java
                      index 256f38fe4..6493c0a71 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MessageOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface MessageOrBuilder extends
                      @@ -87,7 +87,7 @@ public interface MessageOrBuilder extends
                          * .lf.a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED];
                          * @return The role.
                          */
                      -  io.a2a.grpc.Role getRole();
                      +  org.a2aproject.sdk.grpc.Role getRole();
                       
                         /**
                          * 
                      @@ -96,7 +96,7 @@ public interface MessageOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getPartsList();
                         /**
                          * 
                      @@ -105,7 +105,7 @@ public interface MessageOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.Part getParts(int index);
                      +  org.a2aproject.sdk.grpc.Part getParts(int index);
                         /**
                          * 
                          * Parts is the container of the message content.
                      @@ -121,7 +121,7 @@ public interface MessageOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getPartsOrBuilderList();
                         /**
                          * 
                      @@ -130,7 +130,7 @@ public interface MessageOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.PartOrBuilder getPartsOrBuilder(
                      +  org.a2aproject.sdk.grpc.PartOrBuilder getPartsOrBuilder(
                             int index);
                       
                         /**
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MutualTlsSecurityScheme.java
                      similarity index 80%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MutualTlsSecurityScheme.java
                      index 66490ee33..282830c3e 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MutualTlsSecurityScheme.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -37,15 +37,15 @@ private MutualTlsSecurityScheme() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.MutualTlsSecurityScheme.class, io.a2a.grpc.MutualTlsSecurityScheme.Builder.class);
                      +            org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.class, org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.Builder.class);
                         }
                       
                         public static final int DESCRIPTION_FIELD_NUMBER = 1;
                      @@ -134,10 +134,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.MutualTlsSecurityScheme)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.MutualTlsSecurityScheme)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.MutualTlsSecurityScheme other = (io.a2a.grpc.MutualTlsSecurityScheme) obj;
                      +    org.a2aproject.sdk.grpc.MutualTlsSecurityScheme other = (org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) obj;
                       
                           if (!getDescription()
                               .equals(other.getDescription())) return false;
                      @@ -159,44 +159,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -204,26 +204,26 @@ public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -236,7 +236,7 @@ public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.MutualTlsSecurityScheme prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.MutualTlsSecurityScheme prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -261,21 +261,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.MutualTlsSecurityScheme)
                      -      io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder {
                      +      org.a2aproject.sdk.grpc.MutualTlsSecuritySchemeOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.MutualTlsSecurityScheme.class, io.a2a.grpc.MutualTlsSecurityScheme.Builder.class);
                      +              org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.class, org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.MutualTlsSecurityScheme.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -296,17 +296,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_MutualTlsSecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.MutualTlsSecurityScheme getDefaultInstanceForType() {
                      -      return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.MutualTlsSecurityScheme getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.MutualTlsSecurityScheme build() {
                      -      io.a2a.grpc.MutualTlsSecurityScheme result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.MutualTlsSecurityScheme build() {
                      +      org.a2aproject.sdk.grpc.MutualTlsSecurityScheme result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -314,14 +314,14 @@ public io.a2a.grpc.MutualTlsSecurityScheme build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.MutualTlsSecurityScheme buildPartial() {
                      -      io.a2a.grpc.MutualTlsSecurityScheme result = new io.a2a.grpc.MutualTlsSecurityScheme(this);
                      +    public org.a2aproject.sdk.grpc.MutualTlsSecurityScheme buildPartial() {
                      +      org.a2aproject.sdk.grpc.MutualTlsSecurityScheme result = new org.a2aproject.sdk.grpc.MutualTlsSecurityScheme(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.MutualTlsSecurityScheme result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.MutualTlsSecurityScheme result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.description_ = description_;
                      @@ -330,16 +330,16 @@ private void buildPartial0(io.a2a.grpc.MutualTlsSecurityScheme result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.MutualTlsSecurityScheme) {
                      -        return mergeFrom((io.a2a.grpc.MutualTlsSecurityScheme)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.MutualTlsSecurityScheme)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.MutualTlsSecurityScheme other) {
                      -      if (other == io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.MutualTlsSecurityScheme other) {
                      +      if (other == org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance()) return this;
                             if (!other.getDescription().isEmpty()) {
                               description_ = other.description_;
                               bitField0_ |= 0x00000001;
                      @@ -489,12 +489,12 @@ public Builder setDescriptionBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.MutualTlsSecurityScheme)
                      -  private static final io.a2a.grpc.MutualTlsSecurityScheme DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.MutualTlsSecurityScheme DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.MutualTlsSecurityScheme();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.MutualTlsSecurityScheme();
                         }
                       
                      -  public static io.a2a.grpc.MutualTlsSecurityScheme getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.MutualTlsSecurityScheme getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -530,7 +530,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.MutualTlsSecurityScheme getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.MutualTlsSecurityScheme getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MutualTlsSecuritySchemeOrBuilder.java
                      similarity index 96%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MutualTlsSecuritySchemeOrBuilder.java
                      index b16aa1add..62495af9e 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/MutualTlsSecuritySchemeOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface MutualTlsSecuritySchemeOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuth2SecurityScheme.java
                      similarity index 84%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuth2SecurityScheme.java
                      index 144a99864..4b3c1a169 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuth2SecurityScheme.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private OAuth2SecurityScheme() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.OAuth2SecurityScheme.class, io.a2a.grpc.OAuth2SecurityScheme.Builder.class);
                      +            org.a2aproject.sdk.grpc.OAuth2SecurityScheme.class, org.a2aproject.sdk.grpc.OAuth2SecurityScheme.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -98,7 +98,7 @@ public java.lang.String getDescription() {
                         }
                       
                         public static final int FLOWS_FIELD_NUMBER = 2;
                      -  private io.a2a.grpc.OAuthFlows flows_;
                      +  private org.a2aproject.sdk.grpc.OAuthFlows flows_;
                         /**
                          * 
                          * An object containing configuration information for the supported OAuth 2.0 flows.
                      @@ -120,8 +120,8 @@ public boolean hasFlows() {
                          * @return The flows.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.OAuthFlows getFlows() {
                      -    return flows_ == null ? io.a2a.grpc.OAuthFlows.getDefaultInstance() : flows_;
                      +  public org.a2aproject.sdk.grpc.OAuthFlows getFlows() {
                      +    return flows_ == null ? org.a2aproject.sdk.grpc.OAuthFlows.getDefaultInstance() : flows_;
                         }
                         /**
                          * 
                      @@ -131,8 +131,8 @@ public io.a2a.grpc.OAuthFlows getFlows() {
                          * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() {
                      -    return flows_ == null ? io.a2a.grpc.OAuthFlows.getDefaultInstance() : flows_;
                      +  public org.a2aproject.sdk.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() {
                      +    return flows_ == null ? org.a2aproject.sdk.grpc.OAuthFlows.getDefaultInstance() : flows_;
                         }
                       
                         public static final int OAUTH2_METADATA_URL_FIELD_NUMBER = 3;
                      @@ -236,10 +236,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.OAuth2SecurityScheme)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.OAuth2SecurityScheme)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.OAuth2SecurityScheme other = (io.a2a.grpc.OAuth2SecurityScheme) obj;
                      +    org.a2aproject.sdk.grpc.OAuth2SecurityScheme other = (org.a2aproject.sdk.grpc.OAuth2SecurityScheme) obj;
                       
                           if (!getDescription()
                               .equals(other.getDescription())) return false;
                      @@ -274,44 +274,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -319,26 +319,26 @@ public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -351,7 +351,7 @@ public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.OAuth2SecurityScheme prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.OAuth2SecurityScheme prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -376,21 +376,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.OAuth2SecurityScheme)
                      -      io.a2a.grpc.OAuth2SecuritySchemeOrBuilder {
                      +      org.a2aproject.sdk.grpc.OAuth2SecuritySchemeOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.OAuth2SecurityScheme.class, io.a2a.grpc.OAuth2SecurityScheme.Builder.class);
                      +              org.a2aproject.sdk.grpc.OAuth2SecurityScheme.class, org.a2aproject.sdk.grpc.OAuth2SecurityScheme.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.OAuth2SecurityScheme.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.OAuth2SecurityScheme.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -423,17 +423,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuth2SecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OAuth2SecurityScheme getDefaultInstanceForType() {
                      -      return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.OAuth2SecurityScheme getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OAuth2SecurityScheme build() {
                      -      io.a2a.grpc.OAuth2SecurityScheme result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.OAuth2SecurityScheme build() {
                      +      org.a2aproject.sdk.grpc.OAuth2SecurityScheme result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -441,14 +441,14 @@ public io.a2a.grpc.OAuth2SecurityScheme build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OAuth2SecurityScheme buildPartial() {
                      -      io.a2a.grpc.OAuth2SecurityScheme result = new io.a2a.grpc.OAuth2SecurityScheme(this);
                      +    public org.a2aproject.sdk.grpc.OAuth2SecurityScheme buildPartial() {
                      +      org.a2aproject.sdk.grpc.OAuth2SecurityScheme result = new org.a2aproject.sdk.grpc.OAuth2SecurityScheme(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.OAuth2SecurityScheme result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.OAuth2SecurityScheme result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.description_ = description_;
                      @@ -468,16 +468,16 @@ private void buildPartial0(io.a2a.grpc.OAuth2SecurityScheme result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.OAuth2SecurityScheme) {
                      -        return mergeFrom((io.a2a.grpc.OAuth2SecurityScheme)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.OAuth2SecurityScheme) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.OAuth2SecurityScheme)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.OAuth2SecurityScheme other) {
                      -      if (other == io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.OAuth2SecurityScheme other) {
                      +      if (other == org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance()) return this;
                             if (!other.getDescription().isEmpty()) {
                               description_ = other.description_;
                               bitField0_ |= 0x00000001;
                      @@ -643,9 +643,9 @@ public Builder setDescriptionBytes(
                             return this;
                           }
                       
                      -    private io.a2a.grpc.OAuthFlows flows_;
                      +    private org.a2aproject.sdk.grpc.OAuthFlows flows_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.OAuthFlows, io.a2a.grpc.OAuthFlows.Builder, io.a2a.grpc.OAuthFlowsOrBuilder> flowsBuilder_;
                      +        org.a2aproject.sdk.grpc.OAuthFlows, org.a2aproject.sdk.grpc.OAuthFlows.Builder, org.a2aproject.sdk.grpc.OAuthFlowsOrBuilder> flowsBuilder_;
                           /**
                            * 
                            * An object containing configuration information for the supported OAuth 2.0 flows.
                      @@ -665,9 +665,9 @@ public boolean hasFlows() {
                            * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                            * @return The flows.
                            */
                      -    public io.a2a.grpc.OAuthFlows getFlows() {
                      +    public org.a2aproject.sdk.grpc.OAuthFlows getFlows() {
                             if (flowsBuilder_ == null) {
                      -        return flows_ == null ? io.a2a.grpc.OAuthFlows.getDefaultInstance() : flows_;
                      +        return flows_ == null ? org.a2aproject.sdk.grpc.OAuthFlows.getDefaultInstance() : flows_;
                             } else {
                               return flowsBuilder_.getMessage();
                             }
                      @@ -679,7 +679,7 @@ public io.a2a.grpc.OAuthFlows getFlows() {
                            *
                            * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder setFlows(io.a2a.grpc.OAuthFlows value) {
                      +    public Builder setFlows(org.a2aproject.sdk.grpc.OAuthFlows value) {
                             if (flowsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -700,7 +700,7 @@ public Builder setFlows(io.a2a.grpc.OAuthFlows value) {
                            * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setFlows(
                      -        io.a2a.grpc.OAuthFlows.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.OAuthFlows.Builder builderForValue) {
                             if (flowsBuilder_ == null) {
                               flows_ = builderForValue.build();
                             } else {
                      @@ -717,11 +717,11 @@ public Builder setFlows(
                            *
                            * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder mergeFlows(io.a2a.grpc.OAuthFlows value) {
                      +    public Builder mergeFlows(org.a2aproject.sdk.grpc.OAuthFlows value) {
                             if (flowsBuilder_ == null) {
                               if (((bitField0_ & 0x00000002) != 0) &&
                                 flows_ != null &&
                      -          flows_ != io.a2a.grpc.OAuthFlows.getDefaultInstance()) {
                      +          flows_ != org.a2aproject.sdk.grpc.OAuthFlows.getDefaultInstance()) {
                                 getFlowsBuilder().mergeFrom(value);
                               } else {
                                 flows_ = value;
                      @@ -759,7 +759,7 @@ public Builder clearFlows() {
                            *
                            * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.OAuthFlows.Builder getFlowsBuilder() {
                      +    public org.a2aproject.sdk.grpc.OAuthFlows.Builder getFlowsBuilder() {
                             bitField0_ |= 0x00000002;
                             onChanged();
                             return internalGetFlowsFieldBuilder().getBuilder();
                      @@ -771,12 +771,12 @@ public io.a2a.grpc.OAuthFlows.Builder getFlowsBuilder() {
                            *
                            * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() {
                             if (flowsBuilder_ != null) {
                               return flowsBuilder_.getMessageOrBuilder();
                             } else {
                               return flows_ == null ?
                      -            io.a2a.grpc.OAuthFlows.getDefaultInstance() : flows_;
                      +            org.a2aproject.sdk.grpc.OAuthFlows.getDefaultInstance() : flows_;
                             }
                           }
                           /**
                      @@ -787,11 +787,11 @@ public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() {
                            * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.OAuthFlows, io.a2a.grpc.OAuthFlows.Builder, io.a2a.grpc.OAuthFlowsOrBuilder> 
                      +        org.a2aproject.sdk.grpc.OAuthFlows, org.a2aproject.sdk.grpc.OAuthFlows.Builder, org.a2aproject.sdk.grpc.OAuthFlowsOrBuilder> 
                               internalGetFlowsFieldBuilder() {
                             if (flowsBuilder_ == null) {
                               flowsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.OAuthFlows, io.a2a.grpc.OAuthFlows.Builder, io.a2a.grpc.OAuthFlowsOrBuilder>(
                      +            org.a2aproject.sdk.grpc.OAuthFlows, org.a2aproject.sdk.grpc.OAuthFlows.Builder, org.a2aproject.sdk.grpc.OAuthFlowsOrBuilder>(
                                       getFlows(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -901,12 +901,12 @@ public Builder setOauth2MetadataUrlBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.OAuth2SecurityScheme)
                      -  private static final io.a2a.grpc.OAuth2SecurityScheme DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.OAuth2SecurityScheme DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.OAuth2SecurityScheme();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.OAuth2SecurityScheme();
                         }
                       
                      -  public static io.a2a.grpc.OAuth2SecurityScheme getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.OAuth2SecurityScheme getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -942,7 +942,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.OAuth2SecurityScheme getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.OAuth2SecurityScheme getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuth2SecuritySchemeOrBuilder.java
                      similarity index 93%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuth2SecuritySchemeOrBuilder.java
                      index 1eb612bb1..c528595de 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuth2SecuritySchemeOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface OAuth2SecuritySchemeOrBuilder extends
                      @@ -47,7 +47,7 @@ public interface OAuth2SecuritySchemeOrBuilder extends
                          * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                          * @return The flows.
                          */
                      -  io.a2a.grpc.OAuthFlows getFlows();
                      +  org.a2aproject.sdk.grpc.OAuthFlows getFlows();
                         /**
                          * 
                          * An object containing configuration information for the supported OAuth 2.0 flows.
                      @@ -55,7 +55,7 @@ public interface OAuth2SecuritySchemeOrBuilder extends
                          *
                          * .lf.a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder();
                      +  org.a2aproject.sdk.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder();
                       
                         /**
                          * 
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuthFlows.java
                      similarity index 73%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuthFlows.java
                      index 15c96acec..a1c821f62 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuthFlows.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -36,15 +36,15 @@ private OAuthFlows() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.OAuthFlows.class, io.a2a.grpc.OAuthFlows.Builder.class);
                      +            org.a2aproject.sdk.grpc.OAuthFlows.class, org.a2aproject.sdk.grpc.OAuthFlows.Builder.class);
                         }
                       
                         private int flowCase_ = 0;
                      @@ -117,11 +117,11 @@ public boolean hasAuthorizationCode() {
                          * @return The authorizationCode.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() {
                      +  public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() {
                           if (flowCase_ == 1) {
                      -       return (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -131,11 +131,11 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() {
                          * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() {
                           if (flowCase_ == 1) {
                      -       return (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                         }
                       
                         public static final int CLIENT_CREDENTIALS_FIELD_NUMBER = 2;
                      @@ -160,11 +160,11 @@ public boolean hasClientCredentials() {
                          * @return The clientCredentials.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials() {
                      +  public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow getClientCredentials() {
                           if (flowCase_ == 2) {
                      -       return (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -174,11 +174,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials() {
                          * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() {
                           if (flowCase_ == 2) {
                      -       return (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                         }
                       
                         public static final int IMPLICIT_FIELD_NUMBER = 3;
                      @@ -207,11 +207,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                          * @return The implicit.
                          */
                         @java.lang.Override
                      -  @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow getImplicit() {
                      +  @java.lang.Deprecated public org.a2aproject.sdk.grpc.ImplicitOAuthFlow getImplicit() {
                           if (flowCase_ == 3) {
                      -       return (io.a2a.grpc.ImplicitOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.ImplicitOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -221,11 +221,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                          * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
                          */
                         @java.lang.Override
                      -  @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() {
                      +  @java.lang.Deprecated public org.a2aproject.sdk.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() {
                           if (flowCase_ == 3) {
                      -       return (io.a2a.grpc.ImplicitOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.ImplicitOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance();
                         }
                       
                         public static final int PASSWORD_FIELD_NUMBER = 4;
                      @@ -254,11 +254,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                          * @return The password.
                          */
                         @java.lang.Override
                      -  @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow getPassword() {
                      +  @java.lang.Deprecated public org.a2aproject.sdk.grpc.PasswordOAuthFlow getPassword() {
                           if (flowCase_ == 4) {
                      -       return (io.a2a.grpc.PasswordOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.PasswordOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -268,11 +268,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                          * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
                          */
                         @java.lang.Override
                      -  @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() {
                      +  @java.lang.Deprecated public org.a2aproject.sdk.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() {
                           if (flowCase_ == 4) {
                      -       return (io.a2a.grpc.PasswordOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.PasswordOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance();
                         }
                       
                         public static final int DEVICE_CODE_FIELD_NUMBER = 5;
                      @@ -297,11 +297,11 @@ public boolean hasDeviceCode() {
                          * @return The deviceCode.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() {
                      +  public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow getDeviceCode() {
                           if (flowCase_ == 5) {
                      -       return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -311,11 +311,11 @@ public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() {
                          * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() {
                           if (flowCase_ == 5) {
                      -       return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_;
                      +       return (org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) flow_;
                           }
                      -    return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                         }
                       
                         private byte memoizedIsInitialized = -1;
                      @@ -333,19 +333,19 @@ public final boolean isInitialized() {
                         public void writeTo(com.google.protobuf.CodedOutputStream output)
                                             throws java.io.IOException {
                           if (flowCase_ == 1) {
                      -      output.writeMessage(1, (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_);
                      +      output.writeMessage(1, (org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) flow_);
                           }
                           if (flowCase_ == 2) {
                      -      output.writeMessage(2, (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_);
                      +      output.writeMessage(2, (org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) flow_);
                           }
                           if (flowCase_ == 3) {
                      -      output.writeMessage(3, (io.a2a.grpc.ImplicitOAuthFlow) flow_);
                      +      output.writeMessage(3, (org.a2aproject.sdk.grpc.ImplicitOAuthFlow) flow_);
                           }
                           if (flowCase_ == 4) {
                      -      output.writeMessage(4, (io.a2a.grpc.PasswordOAuthFlow) flow_);
                      +      output.writeMessage(4, (org.a2aproject.sdk.grpc.PasswordOAuthFlow) flow_);
                           }
                           if (flowCase_ == 5) {
                      -      output.writeMessage(5, (io.a2a.grpc.DeviceCodeOAuthFlow) flow_);
                      +      output.writeMessage(5, (org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) flow_);
                           }
                           getUnknownFields().writeTo(output);
                         }
                      @@ -358,23 +358,23 @@ public int getSerializedSize() {
                           size = 0;
                           if (flowCase_ == 1) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(1, (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_);
                      +        .computeMessageSize(1, (org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) flow_);
                           }
                           if (flowCase_ == 2) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(2, (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_);
                      +        .computeMessageSize(2, (org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) flow_);
                           }
                           if (flowCase_ == 3) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(3, (io.a2a.grpc.ImplicitOAuthFlow) flow_);
                      +        .computeMessageSize(3, (org.a2aproject.sdk.grpc.ImplicitOAuthFlow) flow_);
                           }
                           if (flowCase_ == 4) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(4, (io.a2a.grpc.PasswordOAuthFlow) flow_);
                      +        .computeMessageSize(4, (org.a2aproject.sdk.grpc.PasswordOAuthFlow) flow_);
                           }
                           if (flowCase_ == 5) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(5, (io.a2a.grpc.DeviceCodeOAuthFlow) flow_);
                      +        .computeMessageSize(5, (org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) flow_);
                           }
                           size += getUnknownFields().getSerializedSize();
                           memoizedSize = size;
                      @@ -386,10 +386,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.OAuthFlows)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.OAuthFlows)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.OAuthFlows other = (io.a2a.grpc.OAuthFlows) obj;
                      +    org.a2aproject.sdk.grpc.OAuthFlows other = (org.a2aproject.sdk.grpc.OAuthFlows) obj;
                       
                           if (!getFlowCase().equals(other.getFlowCase())) return false;
                           switch (flowCase_) {
                      @@ -456,44 +456,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -501,26 +501,26 @@ public static io.a2a.grpc.OAuthFlows parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.OAuthFlows parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.OAuthFlows parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.OAuthFlows parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -533,7 +533,7 @@ public static io.a2a.grpc.OAuthFlows parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.OAuthFlows prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.OAuthFlows prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -558,21 +558,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.OAuthFlows)
                      -      io.a2a.grpc.OAuthFlowsOrBuilder {
                      +      org.a2aproject.sdk.grpc.OAuthFlowsOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.OAuthFlows.class, io.a2a.grpc.OAuthFlows.Builder.class);
                      +              org.a2aproject.sdk.grpc.OAuthFlows.class, org.a2aproject.sdk.grpc.OAuthFlows.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.OAuthFlows.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.OAuthFlows.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -609,17 +609,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OAuthFlows_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OAuthFlows getDefaultInstanceForType() {
                      -      return io.a2a.grpc.OAuthFlows.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.OAuthFlows getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.OAuthFlows.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OAuthFlows build() {
                      -      io.a2a.grpc.OAuthFlows result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.OAuthFlows build() {
                      +      org.a2aproject.sdk.grpc.OAuthFlows result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -627,19 +627,19 @@ public io.a2a.grpc.OAuthFlows build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OAuthFlows buildPartial() {
                      -      io.a2a.grpc.OAuthFlows result = new io.a2a.grpc.OAuthFlows(this);
                      +    public org.a2aproject.sdk.grpc.OAuthFlows buildPartial() {
                      +      org.a2aproject.sdk.grpc.OAuthFlows result = new org.a2aproject.sdk.grpc.OAuthFlows(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             buildPartialOneofs(result);
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.OAuthFlows result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.OAuthFlows result) {
                             int from_bitField0_ = bitField0_;
                           }
                       
                      -    private void buildPartialOneofs(io.a2a.grpc.OAuthFlows result) {
                      +    private void buildPartialOneofs(org.a2aproject.sdk.grpc.OAuthFlows result) {
                             result.flowCase_ = flowCase_;
                             result.flow_ = this.flow_;
                             if (flowCase_ == 1 &&
                      @@ -666,16 +666,16 @@ private void buildPartialOneofs(io.a2a.grpc.OAuthFlows result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.OAuthFlows) {
                      -        return mergeFrom((io.a2a.grpc.OAuthFlows)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.OAuthFlows) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.OAuthFlows)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.OAuthFlows other) {
                      -      if (other == io.a2a.grpc.OAuthFlows.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.OAuthFlows other) {
                      +      if (other == org.a2aproject.sdk.grpc.OAuthFlows.getDefaultInstance()) return this;
                             switch (other.getFlowCase()) {
                               case AUTHORIZATION_CODE: {
                                 mergeAuthorizationCode(other.getAuthorizationCode());
                      @@ -795,7 +795,7 @@ public Builder clearFlow() {
                           private int bitField0_;
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.AuthorizationCodeOAuthFlow, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder, io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder> authorizationCodeBuilder_;
                      +        org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow, org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.Builder, org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlowOrBuilder> authorizationCodeBuilder_;
                           /**
                            * 
                            * Configuration for the OAuth Authorization Code flow.
                      @@ -817,17 +817,17 @@ public boolean hasAuthorizationCode() {
                            * @return The authorizationCode.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() {
                      +    public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() {
                             if (authorizationCodeBuilder_ == null) {
                               if (flowCase_ == 1) {
                      -          return (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                             } else {
                               if (flowCase_ == 1) {
                                 return authorizationCodeBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -837,7 +837,7 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() {
                            *
                            * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                            */
                      -    public Builder setAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow value) {
                      +    public Builder setAuthorizationCode(org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow value) {
                             if (authorizationCodeBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -858,7 +858,7 @@ public Builder setAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow value
                            * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                            */
                           public Builder setAuthorizationCode(
                      -        io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.Builder builderForValue) {
                             if (authorizationCodeBuilder_ == null) {
                               flow_ = builderForValue.build();
                               onChanged();
                      @@ -875,11 +875,11 @@ public Builder setAuthorizationCode(
                            *
                            * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                            */
                      -    public Builder mergeAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow value) {
                      +    public Builder mergeAuthorizationCode(org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow value) {
                             if (authorizationCodeBuilder_ == null) {
                               if (flowCase_ == 1 &&
                      -            flow_ != io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance()) {
                      -          flow_ = io.a2a.grpc.AuthorizationCodeOAuthFlow.newBuilder((io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_)
                      +            flow_ != org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance()) {
                      +          flow_ = org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.newBuilder((org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) flow_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 flow_ = value;
                      @@ -925,7 +925,7 @@ public Builder clearAuthorizationCode() {
                            *
                            * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                            */
                      -    public io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder getAuthorizationCodeBuilder() {
                      +    public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.Builder getAuthorizationCodeBuilder() {
                             return internalGetAuthorizationCodeFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -936,14 +936,14 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder getAuthorizationCodeBuilde
                            * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() {
                             if ((flowCase_ == 1) && (authorizationCodeBuilder_ != null)) {
                               return authorizationCodeBuilder_.getMessageOrBuilder();
                             } else {
                               if (flowCase_ == 1) {
                      -          return (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -954,15 +954,15 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBui
                            * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.AuthorizationCodeOAuthFlow, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder, io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder> 
                      +        org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow, org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.Builder, org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlowOrBuilder> 
                               internalGetAuthorizationCodeFieldBuilder() {
                             if (authorizationCodeBuilder_ == null) {
                               if (!(flowCase_ == 1)) {
                      -          flow_ = io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                      +          flow_ = org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance();
                               }
                               authorizationCodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.AuthorizationCodeOAuthFlow, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder, io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder>(
                      -                (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_,
                      +            org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow, org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow.Builder, org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlowOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow) flow_,
                                       getParentForChildren(),
                                       isClean());
                               flow_ = null;
                      @@ -973,7 +973,7 @@ public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBui
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.ClientCredentialsOAuthFlow, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder, io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder> clientCredentialsBuilder_;
                      +        org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow, org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.Builder, org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlowOrBuilder> clientCredentialsBuilder_;
                           /**
                            * 
                            * Configuration for the OAuth Client Credentials flow.
                      @@ -995,17 +995,17 @@ public boolean hasClientCredentials() {
                            * @return The clientCredentials.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials() {
                      +    public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow getClientCredentials() {
                             if (clientCredentialsBuilder_ == null) {
                               if (flowCase_ == 2) {
                      -          return (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                             } else {
                               if (flowCase_ == 2) {
                                 return clientCredentialsBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1015,7 +1015,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials() {
                            *
                            * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                            */
                      -    public Builder setClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow value) {
                      +    public Builder setClientCredentials(org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow value) {
                             if (clientCredentialsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1036,7 +1036,7 @@ public Builder setClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow value
                            * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                            */
                           public Builder setClientCredentials(
                      -        io.a2a.grpc.ClientCredentialsOAuthFlow.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.Builder builderForValue) {
                             if (clientCredentialsBuilder_ == null) {
                               flow_ = builderForValue.build();
                               onChanged();
                      @@ -1053,11 +1053,11 @@ public Builder setClientCredentials(
                            *
                            * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                            */
                      -    public Builder mergeClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow value) {
                      +    public Builder mergeClientCredentials(org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow value) {
                             if (clientCredentialsBuilder_ == null) {
                               if (flowCase_ == 2 &&
                      -            flow_ != io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance()) {
                      -          flow_ = io.a2a.grpc.ClientCredentialsOAuthFlow.newBuilder((io.a2a.grpc.ClientCredentialsOAuthFlow) flow_)
                      +            flow_ != org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance()) {
                      +          flow_ = org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.newBuilder((org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) flow_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 flow_ = value;
                      @@ -1103,7 +1103,7 @@ public Builder clearClientCredentials() {
                            *
                            * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                            */
                      -    public io.a2a.grpc.ClientCredentialsOAuthFlow.Builder getClientCredentialsBuilder() {
                      +    public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.Builder getClientCredentialsBuilder() {
                             return internalGetClientCredentialsFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1114,14 +1114,14 @@ public io.a2a.grpc.ClientCredentialsOAuthFlow.Builder getClientCredentialsBuilde
                            * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() {
                             if ((flowCase_ == 2) && (clientCredentialsBuilder_ != null)) {
                               return clientCredentialsBuilder_.getMessageOrBuilder();
                             } else {
                               if (flowCase_ == 2) {
                      -          return (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1132,15 +1132,15 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.ClientCredentialsOAuthFlow, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder, io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder> 
                      +        org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow, org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.Builder, org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlowOrBuilder> 
                               internalGetClientCredentialsFieldBuilder() {
                             if (clientCredentialsBuilder_ == null) {
                               if (!(flowCase_ == 2)) {
                      -          flow_ = io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                      +          flow_ = org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.getDefaultInstance();
                               }
                               clientCredentialsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.ClientCredentialsOAuthFlow, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder, io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder>(
                      -                (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_,
                      +            org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow, org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow.Builder, org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlowOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow) flow_,
                                       getParentForChildren(),
                                       isClean());
                               flow_ = null;
                      @@ -1151,7 +1151,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> implicitBuilder_;
                      +        org.a2aproject.sdk.grpc.ImplicitOAuthFlow, org.a2aproject.sdk.grpc.ImplicitOAuthFlow.Builder, org.a2aproject.sdk.grpc.ImplicitOAuthFlowOrBuilder> implicitBuilder_;
                           /**
                            * 
                            * Deprecated: Use Authorization Code + PKCE instead.
                      @@ -1177,17 +1177,17 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * @return The implicit.
                            */
                           @java.lang.Override
                      -    @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow getImplicit() {
                      +    @java.lang.Deprecated public org.a2aproject.sdk.grpc.ImplicitOAuthFlow getImplicit() {
                             if (implicitBuilder_ == null) {
                               if (flowCase_ == 3) {
                      -          return (io.a2a.grpc.ImplicitOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.ImplicitOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance();
                             } else {
                               if (flowCase_ == 3) {
                                 return implicitBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1197,7 +1197,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            *
                            * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
                            */
                      -    @java.lang.Deprecated public Builder setImplicit(io.a2a.grpc.ImplicitOAuthFlow value) {
                      +    @java.lang.Deprecated public Builder setImplicit(org.a2aproject.sdk.grpc.ImplicitOAuthFlow value) {
                             if (implicitBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1218,7 +1218,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
                            */
                           @java.lang.Deprecated public Builder setImplicit(
                      -        io.a2a.grpc.ImplicitOAuthFlow.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.ImplicitOAuthFlow.Builder builderForValue) {
                             if (implicitBuilder_ == null) {
                               flow_ = builderForValue.build();
                               onChanged();
                      @@ -1235,11 +1235,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            *
                            * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
                            */
                      -    @java.lang.Deprecated public Builder mergeImplicit(io.a2a.grpc.ImplicitOAuthFlow value) {
                      +    @java.lang.Deprecated public Builder mergeImplicit(org.a2aproject.sdk.grpc.ImplicitOAuthFlow value) {
                             if (implicitBuilder_ == null) {
                               if (flowCase_ == 3 &&
                      -            flow_ != io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance()) {
                      -          flow_ = io.a2a.grpc.ImplicitOAuthFlow.newBuilder((io.a2a.grpc.ImplicitOAuthFlow) flow_)
                      +            flow_ != org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance()) {
                      +          flow_ = org.a2aproject.sdk.grpc.ImplicitOAuthFlow.newBuilder((org.a2aproject.sdk.grpc.ImplicitOAuthFlow) flow_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 flow_ = value;
                      @@ -1285,7 +1285,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            *
                            * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
                            */
                      -    @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow.Builder getImplicitBuilder() {
                      +    @java.lang.Deprecated public org.a2aproject.sdk.grpc.ImplicitOAuthFlow.Builder getImplicitBuilder() {
                             return internalGetImplicitFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1296,14 +1296,14 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
                            */
                           @java.lang.Override
                      -    @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() {
                      +    @java.lang.Deprecated public org.a2aproject.sdk.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() {
                             if ((flowCase_ == 3) && (implicitBuilder_ != null)) {
                               return implicitBuilder_.getMessageOrBuilder();
                             } else {
                               if (flowCase_ == 3) {
                      -          return (io.a2a.grpc.ImplicitOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.ImplicitOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1314,15 +1314,15 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> 
                      +        org.a2aproject.sdk.grpc.ImplicitOAuthFlow, org.a2aproject.sdk.grpc.ImplicitOAuthFlow.Builder, org.a2aproject.sdk.grpc.ImplicitOAuthFlowOrBuilder> 
                               internalGetImplicitFieldBuilder() {
                             if (implicitBuilder_ == null) {
                               if (!(flowCase_ == 3)) {
                      -          flow_ = io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance();
                      +          flow_ = org.a2aproject.sdk.grpc.ImplicitOAuthFlow.getDefaultInstance();
                               }
                               implicitBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder>(
                      -                (io.a2a.grpc.ImplicitOAuthFlow) flow_,
                      +            org.a2aproject.sdk.grpc.ImplicitOAuthFlow, org.a2aproject.sdk.grpc.ImplicitOAuthFlow.Builder, org.a2aproject.sdk.grpc.ImplicitOAuthFlowOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.ImplicitOAuthFlow) flow_,
                                       getParentForChildren(),
                                       isClean());
                               flow_ = null;
                      @@ -1333,7 +1333,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> passwordBuilder_;
                      +        org.a2aproject.sdk.grpc.PasswordOAuthFlow, org.a2aproject.sdk.grpc.PasswordOAuthFlow.Builder, org.a2aproject.sdk.grpc.PasswordOAuthFlowOrBuilder> passwordBuilder_;
                           /**
                            * 
                            * Deprecated: Use Authorization Code + PKCE or Device Code.
                      @@ -1359,17 +1359,17 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * @return The password.
                            */
                           @java.lang.Override
                      -    @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow getPassword() {
                      +    @java.lang.Deprecated public org.a2aproject.sdk.grpc.PasswordOAuthFlow getPassword() {
                             if (passwordBuilder_ == null) {
                               if (flowCase_ == 4) {
                      -          return (io.a2a.grpc.PasswordOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.PasswordOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance();
                             } else {
                               if (flowCase_ == 4) {
                                 return passwordBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1379,7 +1379,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            *
                            * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
                            */
                      -    @java.lang.Deprecated public Builder setPassword(io.a2a.grpc.PasswordOAuthFlow value) {
                      +    @java.lang.Deprecated public Builder setPassword(org.a2aproject.sdk.grpc.PasswordOAuthFlow value) {
                             if (passwordBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1400,7 +1400,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
                            */
                           @java.lang.Deprecated public Builder setPassword(
                      -        io.a2a.grpc.PasswordOAuthFlow.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.PasswordOAuthFlow.Builder builderForValue) {
                             if (passwordBuilder_ == null) {
                               flow_ = builderForValue.build();
                               onChanged();
                      @@ -1417,11 +1417,11 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            *
                            * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
                            */
                      -    @java.lang.Deprecated public Builder mergePassword(io.a2a.grpc.PasswordOAuthFlow value) {
                      +    @java.lang.Deprecated public Builder mergePassword(org.a2aproject.sdk.grpc.PasswordOAuthFlow value) {
                             if (passwordBuilder_ == null) {
                               if (flowCase_ == 4 &&
                      -            flow_ != io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance()) {
                      -          flow_ = io.a2a.grpc.PasswordOAuthFlow.newBuilder((io.a2a.grpc.PasswordOAuthFlow) flow_)
                      +            flow_ != org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance()) {
                      +          flow_ = org.a2aproject.sdk.grpc.PasswordOAuthFlow.newBuilder((org.a2aproject.sdk.grpc.PasswordOAuthFlow) flow_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 flow_ = value;
                      @@ -1467,7 +1467,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            *
                            * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
                            */
                      -    @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow.Builder getPasswordBuilder() {
                      +    @java.lang.Deprecated public org.a2aproject.sdk.grpc.PasswordOAuthFlow.Builder getPasswordBuilder() {
                             return internalGetPasswordFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1478,14 +1478,14 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
                            */
                           @java.lang.Override
                      -    @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() {
                      +    @java.lang.Deprecated public org.a2aproject.sdk.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() {
                             if ((flowCase_ == 4) && (passwordBuilder_ != null)) {
                               return passwordBuilder_.getMessageOrBuilder();
                             } else {
                               if (flowCase_ == 4) {
                      -          return (io.a2a.grpc.PasswordOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.PasswordOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1496,15 +1496,15 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                            * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> 
                      +        org.a2aproject.sdk.grpc.PasswordOAuthFlow, org.a2aproject.sdk.grpc.PasswordOAuthFlow.Builder, org.a2aproject.sdk.grpc.PasswordOAuthFlowOrBuilder> 
                               internalGetPasswordFieldBuilder() {
                             if (passwordBuilder_ == null) {
                               if (!(flowCase_ == 4)) {
                      -          flow_ = io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
                      +          flow_ = org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance();
                               }
                               passwordBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder>(
                      -                (io.a2a.grpc.PasswordOAuthFlow) flow_,
                      +            org.a2aproject.sdk.grpc.PasswordOAuthFlow, org.a2aproject.sdk.grpc.PasswordOAuthFlow.Builder, org.a2aproject.sdk.grpc.PasswordOAuthFlowOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.PasswordOAuthFlow) flow_,
                                       getParentForChildren(),
                                       isClean());
                               flow_ = null;
                      @@ -1515,7 +1515,7 @@ public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBui
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder> deviceCodeBuilder_;
                      +        org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow, org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.Builder, org.a2aproject.sdk.grpc.DeviceCodeOAuthFlowOrBuilder> deviceCodeBuilder_;
                           /**
                            * 
                            * Configuration for the OAuth Device Code flow.
                      @@ -1537,17 +1537,17 @@ public boolean hasDeviceCode() {
                            * @return The deviceCode.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() {
                      +    public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow getDeviceCode() {
                             if (deviceCodeBuilder_ == null) {
                               if (flowCase_ == 5) {
                      -          return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                             } else {
                               if (flowCase_ == 5) {
                                 return deviceCodeBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1557,7 +1557,7 @@ public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() {
                            *
                            * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                            */
                      -    public Builder setDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) {
                      +    public Builder setDeviceCode(org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow value) {
                             if (deviceCodeBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1578,7 +1578,7 @@ public Builder setDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) {
                            * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                            */
                           public Builder setDeviceCode(
                      -        io.a2a.grpc.DeviceCodeOAuthFlow.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.Builder builderForValue) {
                             if (deviceCodeBuilder_ == null) {
                               flow_ = builderForValue.build();
                               onChanged();
                      @@ -1595,11 +1595,11 @@ public Builder setDeviceCode(
                            *
                            * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                            */
                      -    public Builder mergeDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) {
                      +    public Builder mergeDeviceCode(org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow value) {
                             if (deviceCodeBuilder_ == null) {
                               if (flowCase_ == 5 &&
                      -            flow_ != io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance()) {
                      -          flow_ = io.a2a.grpc.DeviceCodeOAuthFlow.newBuilder((io.a2a.grpc.DeviceCodeOAuthFlow) flow_)
                      +            flow_ != org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance()) {
                      +          flow_ = org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.newBuilder((org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) flow_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 flow_ = value;
                      @@ -1645,7 +1645,7 @@ public Builder clearDeviceCode() {
                            *
                            * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                            */
                      -    public io.a2a.grpc.DeviceCodeOAuthFlow.Builder getDeviceCodeBuilder() {
                      +    public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.Builder getDeviceCodeBuilder() {
                             return internalGetDeviceCodeFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1656,14 +1656,14 @@ public io.a2a.grpc.DeviceCodeOAuthFlow.Builder getDeviceCodeBuilder() {
                            * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() {
                             if ((flowCase_ == 5) && (deviceCodeBuilder_ != null)) {
                               return deviceCodeBuilder_.getMessageOrBuilder();
                             } else {
                               if (flowCase_ == 5) {
                      -          return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_;
                      +          return (org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) flow_;
                               }
                      -        return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1674,15 +1674,15 @@ public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() {
                            * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder> 
                      +        org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow, org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.Builder, org.a2aproject.sdk.grpc.DeviceCodeOAuthFlowOrBuilder> 
                               internalGetDeviceCodeFieldBuilder() {
                             if (deviceCodeBuilder_ == null) {
                               if (!(flowCase_ == 5)) {
                      -          flow_ = io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                      +          flow_ = org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.getDefaultInstance();
                               }
                               deviceCodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder>(
                      -                (io.a2a.grpc.DeviceCodeOAuthFlow) flow_,
                      +            org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow, org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow.Builder, org.a2aproject.sdk.grpc.DeviceCodeOAuthFlowOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow) flow_,
                                       getParentForChildren(),
                                       isClean());
                               flow_ = null;
                      @@ -1696,12 +1696,12 @@ public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.OAuthFlows)
                      -  private static final io.a2a.grpc.OAuthFlows DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.OAuthFlows DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.OAuthFlows();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.OAuthFlows();
                         }
                       
                      -  public static io.a2a.grpc.OAuthFlows getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.OAuthFlows getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1737,7 +1737,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.OAuthFlows getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.OAuthFlows getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuthFlowsOrBuilder.java
                      similarity index 80%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuthFlowsOrBuilder.java
                      index fbb2e96d9..f8d7fa6a8 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OAuthFlowsOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface OAuthFlowsOrBuilder extends
                      @@ -27,7 +27,7 @@ public interface OAuthFlowsOrBuilder extends
                          * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                          * @return The authorizationCode.
                          */
                      -  io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode();
                      +  org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode();
                         /**
                          * 
                          * Configuration for the OAuth Authorization Code flow.
                      @@ -35,7 +35,7 @@ public interface OAuthFlowsOrBuilder extends
                          *
                          * .lf.a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1;
                          */
                      -  io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder();
                      +  org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder();
                       
                         /**
                          * 
                      @@ -54,7 +54,7 @@ public interface OAuthFlowsOrBuilder extends
                          * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                          * @return The clientCredentials.
                          */
                      -  io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials();
                      +  org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow getClientCredentials();
                         /**
                          * 
                          * Configuration for the OAuth Client Credentials flow.
                      @@ -62,7 +62,7 @@ public interface OAuthFlowsOrBuilder extends
                          *
                          * .lf.a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2;
                          */
                      -  io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder();
                      +  org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder();
                       
                         /**
                          * 
                      @@ -85,7 +85,7 @@ public interface OAuthFlowsOrBuilder extends
                          *     See a2a.proto;l=569
                          * @return The implicit.
                          */
                      -  @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlow getImplicit();
                      +  @java.lang.Deprecated org.a2aproject.sdk.grpc.ImplicitOAuthFlow getImplicit();
                         /**
                          * 
                          * Deprecated: Use Authorization Code + PKCE instead.
                      @@ -93,7 +93,7 @@ public interface OAuthFlowsOrBuilder extends
                          *
                          * .lf.a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true];
                          */
                      -  @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder();
                      +  @java.lang.Deprecated org.a2aproject.sdk.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder();
                       
                         /**
                          * 
                      @@ -116,7 +116,7 @@ public interface OAuthFlowsOrBuilder extends
                          *     See a2a.proto;l=571
                          * @return The password.
                          */
                      -  @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlow getPassword();
                      +  @java.lang.Deprecated org.a2aproject.sdk.grpc.PasswordOAuthFlow getPassword();
                         /**
                          * 
                          * Deprecated: Use Authorization Code + PKCE or Device Code.
                      @@ -124,7 +124,7 @@ public interface OAuthFlowsOrBuilder extends
                          *
                          * .lf.a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true];
                          */
                      -  @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder();
                      +  @java.lang.Deprecated org.a2aproject.sdk.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder();
                       
                         /**
                          * 
                      @@ -143,7 +143,7 @@ public interface OAuthFlowsOrBuilder extends
                          * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                          * @return The deviceCode.
                          */
                      -  io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode();
                      +  org.a2aproject.sdk.grpc.DeviceCodeOAuthFlow getDeviceCode();
                         /**
                          * 
                          * Configuration for the OAuth Device Code flow.
                      @@ -151,7 +151,7 @@ public interface OAuthFlowsOrBuilder extends
                          *
                          * .lf.a2a.v1.DeviceCodeOAuthFlow device_code = 5;
                          */
                      -  io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder();
                      +  org.a2aproject.sdk.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder();
                       
                      -  io.a2a.grpc.OAuthFlows.FlowCase getFlowCase();
                      +  org.a2aproject.sdk.grpc.OAuthFlows.FlowCase getFlowCase();
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OpenIdConnectSecurityScheme.java
                      similarity index 84%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OpenIdConnectSecurityScheme.java
                      index d0b2eb580..9008fb411 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OpenIdConnectSecurityScheme.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private OpenIdConnectSecurityScheme() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.OpenIdConnectSecurityScheme.class, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder.class);
                      +            org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.class, org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.Builder.class);
                         }
                       
                         public static final int DESCRIPTION_FIELD_NUMBER = 1;
                      @@ -188,10 +188,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.OpenIdConnectSecurityScheme)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.OpenIdConnectSecurityScheme other = (io.a2a.grpc.OpenIdConnectSecurityScheme) obj;
                      +    org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme other = (org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) obj;
                       
                           if (!getDescription()
                               .equals(other.getDescription())) return false;
                      @@ -217,44 +217,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -262,26 +262,26 @@ public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -294,7 +294,7 @@ public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.OpenIdConnectSecurityScheme prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -319,21 +319,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.OpenIdConnectSecurityScheme)
                      -      io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder {
                      +      org.a2aproject.sdk.grpc.OpenIdConnectSecuritySchemeOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.OpenIdConnectSecurityScheme.class, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder.class);
                      +              org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.class, org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.OpenIdConnectSecurityScheme.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -355,17 +355,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_OpenIdConnectSecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OpenIdConnectSecurityScheme getDefaultInstanceForType() {
                      -      return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OpenIdConnectSecurityScheme build() {
                      -      io.a2a.grpc.OpenIdConnectSecurityScheme result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme build() {
                      +      org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -373,14 +373,14 @@ public io.a2a.grpc.OpenIdConnectSecurityScheme build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.OpenIdConnectSecurityScheme buildPartial() {
                      -      io.a2a.grpc.OpenIdConnectSecurityScheme result = new io.a2a.grpc.OpenIdConnectSecurityScheme(this);
                      +    public org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme buildPartial() {
                      +      org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme result = new org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.OpenIdConnectSecurityScheme result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.description_ = description_;
                      @@ -392,16 +392,16 @@ private void buildPartial0(io.a2a.grpc.OpenIdConnectSecurityScheme result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.OpenIdConnectSecurityScheme) {
                      -        return mergeFrom((io.a2a.grpc.OpenIdConnectSecurityScheme)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.OpenIdConnectSecurityScheme other) {
                      -      if (other == io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme other) {
                      +      if (other == org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance()) return this;
                             if (!other.getDescription().isEmpty()) {
                               description_ = other.description_;
                               bitField0_ |= 0x00000001;
                      @@ -653,12 +653,12 @@ public Builder setOpenIdConnectUrlBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.OpenIdConnectSecurityScheme)
                      -  private static final io.a2a.grpc.OpenIdConnectSecurityScheme DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.OpenIdConnectSecurityScheme();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme();
                         }
                       
                      -  public static io.a2a.grpc.OpenIdConnectSecurityScheme getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -694,7 +694,7 @@ public com.google.protobuf.Parser getParserForType(
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.OpenIdConnectSecurityScheme getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OpenIdConnectSecuritySchemeOrBuilder.java
                      similarity index 97%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OpenIdConnectSecuritySchemeOrBuilder.java
                      index 3887a6d38..70d619efe 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/OpenIdConnectSecuritySchemeOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface OpenIdConnectSecuritySchemeOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Part.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Part.java
                      similarity index 94%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/Part.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Part.java
                      index 46f10d95c..0bb9149a4 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/Part.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Part.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -40,15 +40,15 @@ private Part() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Part_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.Part.class, io.a2a.grpc.Part.Builder.class);
                      +            org.a2aproject.sdk.grpc.Part.class, org.a2aproject.sdk.grpc.Part.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -512,10 +512,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.Part)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.Part)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.Part other = (io.a2a.grpc.Part) obj;
                      +    org.a2aproject.sdk.grpc.Part other = (org.a2aproject.sdk.grpc.Part) obj;
                       
                           if (hasMetadata() != other.hasMetadata()) return false;
                           if (hasMetadata()) {
                      @@ -591,44 +591,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.Part parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -636,26 +636,26 @@ public static io.a2a.grpc.Part parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.Part parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.Part parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.Part parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.Part parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Part parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -668,7 +668,7 @@ public static io.a2a.grpc.Part parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.Part prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.Part prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -695,21 +695,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.Part)
                      -      io.a2a.grpc.PartOrBuilder {
                      +      org.a2aproject.sdk.grpc.PartOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Part_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.Part.class, io.a2a.grpc.Part.Builder.class);
                      +              org.a2aproject.sdk.grpc.Part.class, org.a2aproject.sdk.grpc.Part.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.Part.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.Part.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -747,17 +747,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Part_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Part getDefaultInstanceForType() {
                      -      return io.a2a.grpc.Part.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.Part getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.Part.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Part build() {
                      -      io.a2a.grpc.Part result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.Part build() {
                      +      org.a2aproject.sdk.grpc.Part result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -765,15 +765,15 @@ public io.a2a.grpc.Part build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Part buildPartial() {
                      -      io.a2a.grpc.Part result = new io.a2a.grpc.Part(this);
                      +    public org.a2aproject.sdk.grpc.Part buildPartial() {
                      +      org.a2aproject.sdk.grpc.Part result = new org.a2aproject.sdk.grpc.Part(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             buildPartialOneofs(result);
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.Part result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.Part result) {
                             int from_bitField0_ = bitField0_;
                             int to_bitField0_ = 0;
                             if (((from_bitField0_ & 0x00000010) != 0)) {
                      @@ -791,7 +791,7 @@ private void buildPartial0(io.a2a.grpc.Part result) {
                             result.bitField0_ |= to_bitField0_;
                           }
                       
                      -    private void buildPartialOneofs(io.a2a.grpc.Part result) {
                      +    private void buildPartialOneofs(org.a2aproject.sdk.grpc.Part result) {
                             result.contentCase_ = contentCase_;
                             result.content_ = this.content_;
                             if (contentCase_ == 4 &&
                      @@ -802,16 +802,16 @@ private void buildPartialOneofs(io.a2a.grpc.Part result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.Part) {
                      -        return mergeFrom((io.a2a.grpc.Part)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.Part) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.Part)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.Part other) {
                      -      if (other == io.a2a.grpc.Part.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.Part other) {
                      +      if (other == org.a2aproject.sdk.grpc.Part.getDefaultInstance()) return this;
                             if (other.hasMetadata()) {
                               mergeMetadata(other.getMetadata());
                             }
                      @@ -1769,12 +1769,12 @@ public Builder setMediaTypeBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.Part)
                      -  private static final io.a2a.grpc.Part DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.Part DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.Part();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.Part();
                         }
                       
                      -  public static io.a2a.grpc.Part getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.Part getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1810,7 +1810,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.Part getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.Part getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PartOrBuilder.java
                      similarity index 97%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PartOrBuilder.java
                      index 1ac1a1c9b..2cf552689 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PartOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface PartOrBuilder extends
                      @@ -183,5 +183,5 @@ public interface PartOrBuilder extends
                         com.google.protobuf.ByteString
                             getMediaTypeBytes();
                       
                      -  io.a2a.grpc.Part.ContentCase getContentCase();
                      +  org.a2aproject.sdk.grpc.Part.ContentCase getContentCase();
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PasswordOAuthFlow.java
                      similarity index 90%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PasswordOAuthFlow.java
                      index df4abb7a3..c0e43154a 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PasswordOAuthFlow.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,7 +38,7 @@ private PasswordOAuthFlow() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor;
                         }
                       
                         @SuppressWarnings({"rawtypes"})
                      @@ -56,9 +56,9 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class);
                      +            org.a2aproject.sdk.grpc.PasswordOAuthFlow.class, org.a2aproject.sdk.grpc.PasswordOAuthFlow.Builder.class);
                         }
                       
                         public static final int TOKEN_URL_FIELD_NUMBER = 1;
                      @@ -165,7 +165,7 @@ private static final class ScopesDefaultEntryHolder {
                               java.lang.String, java.lang.String> defaultEntry =
                                   com.google.protobuf.MapEntry
                                   .newDefaultInstance(
                      -                io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, 
                      +                org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, 
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                                       "",
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                      @@ -319,10 +319,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.PasswordOAuthFlow)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.PasswordOAuthFlow)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.PasswordOAuthFlow other = (io.a2a.grpc.PasswordOAuthFlow) obj;
                      +    org.a2aproject.sdk.grpc.PasswordOAuthFlow other = (org.a2aproject.sdk.grpc.PasswordOAuthFlow) obj;
                       
                           if (!getTokenUrl()
                               .equals(other.getTokenUrl())) return false;
                      @@ -354,44 +354,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -399,26 +399,26 @@ public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -431,7 +431,7 @@ public static io.a2a.grpc.PasswordOAuthFlow parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.PasswordOAuthFlow prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.PasswordOAuthFlow prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -456,10 +456,10 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.PasswordOAuthFlow)
                      -      io.a2a.grpc.PasswordOAuthFlowOrBuilder {
                      +      org.a2aproject.sdk.grpc.PasswordOAuthFlowOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor;
                           }
                       
                           @SuppressWarnings({"rawtypes"})
                      @@ -487,12 +487,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class);
                      +              org.a2aproject.sdk.grpc.PasswordOAuthFlow.class, org.a2aproject.sdk.grpc.PasswordOAuthFlow.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.PasswordOAuthFlow.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.PasswordOAuthFlow.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -515,17 +515,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_PasswordOAuthFlow_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.PasswordOAuthFlow getDefaultInstanceForType() {
                      -      return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.PasswordOAuthFlow getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.PasswordOAuthFlow build() {
                      -      io.a2a.grpc.PasswordOAuthFlow result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.PasswordOAuthFlow build() {
                      +      org.a2aproject.sdk.grpc.PasswordOAuthFlow result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -533,14 +533,14 @@ public io.a2a.grpc.PasswordOAuthFlow build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.PasswordOAuthFlow buildPartial() {
                      -      io.a2a.grpc.PasswordOAuthFlow result = new io.a2a.grpc.PasswordOAuthFlow(this);
                      +    public org.a2aproject.sdk.grpc.PasswordOAuthFlow buildPartial() {
                      +      org.a2aproject.sdk.grpc.PasswordOAuthFlow result = new org.a2aproject.sdk.grpc.PasswordOAuthFlow(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.PasswordOAuthFlow result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.PasswordOAuthFlow result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tokenUrl_ = tokenUrl_;
                      @@ -556,16 +556,16 @@ private void buildPartial0(io.a2a.grpc.PasswordOAuthFlow result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.PasswordOAuthFlow) {
                      -        return mergeFrom((io.a2a.grpc.PasswordOAuthFlow)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.PasswordOAuthFlow) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.PasswordOAuthFlow)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.PasswordOAuthFlow other) {
                      -      if (other == io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.PasswordOAuthFlow other) {
                      +      if (other == org.a2aproject.sdk.grpc.PasswordOAuthFlow.getDefaultInstance()) return this;
                             if (!other.getTokenUrl().isEmpty()) {
                               tokenUrl_ = other.tokenUrl_;
                               bitField0_ |= 0x00000001;
                      @@ -1001,12 +1001,12 @@ public Builder putAllScopes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.PasswordOAuthFlow)
                      -  private static final io.a2a.grpc.PasswordOAuthFlow DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.PasswordOAuthFlow DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.PasswordOAuthFlow();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.PasswordOAuthFlow();
                         }
                       
                      -  public static io.a2a.grpc.PasswordOAuthFlow getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.PasswordOAuthFlow getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1042,7 +1042,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.PasswordOAuthFlow getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.PasswordOAuthFlow getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PasswordOAuthFlowOrBuilder.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PasswordOAuthFlowOrBuilder.java
                      index 0eab9e995..e86de6e0c 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/PasswordOAuthFlowOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface PasswordOAuthFlowOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Role.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Role.java
                      similarity index 97%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/Role.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Role.java
                      index b33496ba1..5384d4216 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/Role.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Role.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -134,7 +134,7 @@ public Role findValueByNumber(int number) {
                         }
                         public static com.google.protobuf.Descriptors.EnumDescriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.getDescriptor().getEnumTypes().get(1);
                      +    return org.a2aproject.sdk.grpc.A2A.getDescriptor().getEnumTypes().get(1);
                         }
                       
                         private static final Role[] VALUES = values();
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityRequirement.java
                      similarity index 73%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityRequirement.java
                      index 3208d39a0..002fe52bf 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityRequirement.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -36,7 +36,7 @@ private SecurityRequirement() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor;
                         }
                       
                         @SuppressWarnings({"rawtypes"})
                      @@ -54,27 +54,27 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldRefl
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.SecurityRequirement.class, io.a2a.grpc.SecurityRequirement.Builder.class);
                      +            org.a2aproject.sdk.grpc.SecurityRequirement.class, org.a2aproject.sdk.grpc.SecurityRequirement.Builder.class);
                         }
                       
                         public static final int SCHEMES_FIELD_NUMBER = 1;
                         private static final class SchemesDefaultEntryHolder {
                           static final com.google.protobuf.MapEntry<
                      -        java.lang.String, io.a2a.grpc.StringList> defaultEntry =
                      +        java.lang.String, org.a2aproject.sdk.grpc.StringList> defaultEntry =
                                   com.google.protobuf.MapEntry
                      -            .newDefaultInstance(
                      -                io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, 
                      +            .newDefaultInstance(
                      +                org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, 
                                       com.google.protobuf.WireFormat.FieldType.STRING,
                                       "",
                                       com.google.protobuf.WireFormat.FieldType.MESSAGE,
                      -                io.a2a.grpc.StringList.getDefaultInstance());
                      +                org.a2aproject.sdk.grpc.StringList.getDefaultInstance());
                         }
                         @SuppressWarnings("serial")
                         private com.google.protobuf.MapField<
                      -      java.lang.String, io.a2a.grpc.StringList> schemes_;
                      -  private com.google.protobuf.MapField
                      +      java.lang.String, org.a2aproject.sdk.grpc.StringList> schemes_;
                      +  private com.google.protobuf.MapField
                         internalGetSchemes() {
                           if (schemes_ == null) {
                             return com.google.protobuf.MapField.emptyMapField(
                      @@ -103,7 +103,7 @@ public boolean containsSchemes(
                          */
                         @java.lang.Override
                         @java.lang.Deprecated
                      -  public java.util.Map getSchemes() {
                      +  public java.util.Map getSchemes() {
                           return getSchemesMap();
                         }
                         /**
                      @@ -114,7 +114,7 @@ public java.util.Map getSchemes() {
                          * map<string, .lf.a2a.v1.StringList> schemes = 1;
                          */
                         @java.lang.Override
                      -  public java.util.Map getSchemesMap() {
                      +  public java.util.Map getSchemesMap() {
                           return internalGetSchemes().getMap();
                         }
                         /**
                      @@ -126,12 +126,12 @@ public java.util.Map getSchemesMap() {
                          */
                         @java.lang.Override
                         public /* nullable */
                      -io.a2a.grpc.StringList getSchemesOrDefault(
                      +org.a2aproject.sdk.grpc.StringList getSchemesOrDefault(
                             java.lang.String key,
                             /* nullable */
                      -io.a2a.grpc.StringList defaultValue) {
                      +org.a2aproject.sdk.grpc.StringList defaultValue) {
                           if (key == null) { throw new NullPointerException("map key"); }
                      -    java.util.Map map =
                      +    java.util.Map map =
                               internalGetSchemes().getMap();
                           return map.containsKey(key) ? map.get(key) : defaultValue;
                         }
                      @@ -143,10 +143,10 @@ io.a2a.grpc.StringList getSchemesOrDefault(
                          * map<string, .lf.a2a.v1.StringList> schemes = 1;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.StringList getSchemesOrThrow(
                      +  public org.a2aproject.sdk.grpc.StringList getSchemesOrThrow(
                             java.lang.String key) {
                           if (key == null) { throw new NullPointerException("map key"); }
                      -    java.util.Map map =
                      +    java.util.Map map =
                               internalGetSchemes().getMap();
                           if (!map.containsKey(key)) {
                             throw new java.lang.IllegalArgumentException();
                      @@ -183,9 +183,9 @@ public int getSerializedSize() {
                           if (size != -1) return size;
                       
                           size = 0;
                      -    for (java.util.Map.Entry entry
                      +    for (java.util.Map.Entry entry
                                : internalGetSchemes().getMap().entrySet()) {
                      -      com.google.protobuf.MapEntry
                      +      com.google.protobuf.MapEntry
                             schemes__ = SchemesDefaultEntryHolder.defaultEntry.newBuilderForType()
                                 .setKey(entry.getKey())
                                 .setValue(entry.getValue())
                      @@ -203,10 +203,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.SecurityRequirement)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.SecurityRequirement)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.SecurityRequirement other = (io.a2a.grpc.SecurityRequirement) obj;
                      +    org.a2aproject.sdk.grpc.SecurityRequirement other = (org.a2aproject.sdk.grpc.SecurityRequirement) obj;
                       
                           if (!internalGetSchemes().equals(
                               other.internalGetSchemes())) return false;
                      @@ -230,44 +230,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -275,26 +275,26 @@ public static io.a2a.grpc.SecurityRequirement parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.SecurityRequirement parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.SecurityRequirement parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SecurityRequirement parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -307,7 +307,7 @@ public static io.a2a.grpc.SecurityRequirement parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.SecurityRequirement prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.SecurityRequirement prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -332,10 +332,10 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SecurityRequirement)
                      -      io.a2a.grpc.SecurityRequirementOrBuilder {
                      +      org.a2aproject.sdk.grpc.SecurityRequirementOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor;
                           }
                       
                           @SuppressWarnings({"rawtypes"})
                      @@ -363,12 +363,12 @@ protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFi
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.SecurityRequirement.class, io.a2a.grpc.SecurityRequirement.Builder.class);
                      +              org.a2aproject.sdk.grpc.SecurityRequirement.class, org.a2aproject.sdk.grpc.SecurityRequirement.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.SecurityRequirement.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.SecurityRequirement.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -389,17 +389,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityRequirement_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SecurityRequirement getDefaultInstanceForType() {
                      -      return io.a2a.grpc.SecurityRequirement.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.SecurityRequirement.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SecurityRequirement build() {
                      -      io.a2a.grpc.SecurityRequirement result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement build() {
                      +      org.a2aproject.sdk.grpc.SecurityRequirement result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -407,14 +407,14 @@ public io.a2a.grpc.SecurityRequirement build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SecurityRequirement buildPartial() {
                      -      io.a2a.grpc.SecurityRequirement result = new io.a2a.grpc.SecurityRequirement(this);
                      +    public org.a2aproject.sdk.grpc.SecurityRequirement buildPartial() {
                      +      org.a2aproject.sdk.grpc.SecurityRequirement result = new org.a2aproject.sdk.grpc.SecurityRequirement(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.SecurityRequirement result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.SecurityRequirement result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.schemes_ = internalGetSchemes().build(SchemesDefaultEntryHolder.defaultEntry);
                      @@ -423,16 +423,16 @@ private void buildPartial0(io.a2a.grpc.SecurityRequirement result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.SecurityRequirement) {
                      -        return mergeFrom((io.a2a.grpc.SecurityRequirement)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.SecurityRequirement) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.SecurityRequirement)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.SecurityRequirement other) {
                      -      if (other == io.a2a.grpc.SecurityRequirement.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.SecurityRequirement other) {
                      +      if (other == org.a2aproject.sdk.grpc.SecurityRequirement.getDefaultInstance()) return this;
                             internalGetMutableSchemes().mergeFrom(
                                 other.internalGetSchemes());
                             bitField0_ |= 0x00000001;
                      @@ -463,7 +463,7 @@ public Builder mergeFrom(
                                     done = true;
                                     break;
                                   case 10: {
                      -              com.google.protobuf.MapEntry
                      +              com.google.protobuf.MapEntry
                                     schemes__ = input.readMessage(
                                         SchemesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
                                     internalGetMutableSchemes().ensureBuilderMap().put(
                      @@ -488,30 +488,30 @@ public Builder mergeFrom(
                           }
                           private int bitField0_;
                       
                      -    private static final class SchemesConverter implements com.google.protobuf.MapFieldBuilder.Converter {
                      +    private static final class SchemesConverter implements com.google.protobuf.MapFieldBuilder.Converter {
                             @java.lang.Override
                      -      public io.a2a.grpc.StringList build(io.a2a.grpc.StringListOrBuilder val) {
                      -        if (val instanceof io.a2a.grpc.StringList) { return (io.a2a.grpc.StringList) val; }
                      -        return ((io.a2a.grpc.StringList.Builder) val).build();
                      +      public org.a2aproject.sdk.grpc.StringList build(org.a2aproject.sdk.grpc.StringListOrBuilder val) {
                      +        if (val instanceof org.a2aproject.sdk.grpc.StringList) { return (org.a2aproject.sdk.grpc.StringList) val; }
                      +        return ((org.a2aproject.sdk.grpc.StringList.Builder) val).build();
                             }
                       
                             @java.lang.Override
                      -      public com.google.protobuf.MapEntry defaultEntry() {
                      +      public com.google.protobuf.MapEntry defaultEntry() {
                               return SchemesDefaultEntryHolder.defaultEntry;
                             }
                           };
                           private static final SchemesConverter schemesConverter = new SchemesConverter();
                       
                           private com.google.protobuf.MapFieldBuilder<
                      -        java.lang.String, io.a2a.grpc.StringListOrBuilder, io.a2a.grpc.StringList, io.a2a.grpc.StringList.Builder> schemes_;
                      -    private com.google.protobuf.MapFieldBuilder
                      +        java.lang.String, org.a2aproject.sdk.grpc.StringListOrBuilder, org.a2aproject.sdk.grpc.StringList, org.a2aproject.sdk.grpc.StringList.Builder> schemes_;
                      +    private com.google.protobuf.MapFieldBuilder
                               internalGetSchemes() {
                             if (schemes_ == null) {
                               return new com.google.protobuf.MapFieldBuilder<>(schemesConverter);
                             }
                             return schemes_;
                           }
                      -    private com.google.protobuf.MapFieldBuilder
                      +    private com.google.protobuf.MapFieldBuilder
                               internalGetMutableSchemes() {
                             if (schemes_ == null) {
                               schemes_ = new com.google.protobuf.MapFieldBuilder<>(schemesConverter);
                      @@ -541,7 +541,7 @@ public boolean containsSchemes(
                            */
                           @java.lang.Override
                           @java.lang.Deprecated
                      -    public java.util.Map getSchemes() {
                      +    public java.util.Map getSchemes() {
                             return getSchemesMap();
                           }
                           /**
                      @@ -552,7 +552,7 @@ public java.util.Map getSchemes() {
                            * map<string, .lf.a2a.v1.StringList> schemes = 1;
                            */
                           @java.lang.Override
                      -    public java.util.Map getSchemesMap() {
                      +    public java.util.Map getSchemesMap() {
                             return internalGetSchemes().getImmutableMap();
                           }
                           /**
                      @@ -564,12 +564,12 @@ public java.util.Map getSchemesMap() {
                            */
                           @java.lang.Override
                           public /* nullable */
                      -io.a2a.grpc.StringList getSchemesOrDefault(
                      +org.a2aproject.sdk.grpc.StringList getSchemesOrDefault(
                               java.lang.String key,
                               /* nullable */
                      -io.a2a.grpc.StringList defaultValue) {
                      +org.a2aproject.sdk.grpc.StringList defaultValue) {
                             if (key == null) { throw new NullPointerException("map key"); }
                      -      java.util.Map map = internalGetMutableSchemes().ensureBuilderMap();
                      +      java.util.Map map = internalGetMutableSchemes().ensureBuilderMap();
                             return map.containsKey(key) ? schemesConverter.build(map.get(key)) : defaultValue;
                           }
                           /**
                      @@ -580,10 +580,10 @@ io.a2a.grpc.StringList getSchemesOrDefault(
                            * map<string, .lf.a2a.v1.StringList> schemes = 1;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.StringList getSchemesOrThrow(
                      +    public org.a2aproject.sdk.grpc.StringList getSchemesOrThrow(
                               java.lang.String key) {
                             if (key == null) { throw new NullPointerException("map key"); }
                      -      java.util.Map map = internalGetMutableSchemes().ensureBuilderMap();
                      +      java.util.Map map = internalGetMutableSchemes().ensureBuilderMap();
                             if (!map.containsKey(key)) {
                               throw new java.lang.IllegalArgumentException();
                             }
                      @@ -612,7 +612,7 @@ public Builder removeSchemes(
                            * Use alternate mutation accessors instead.
                            */
                           @java.lang.Deprecated
                      -    public java.util.Map
                      +    public java.util.Map
                               getMutableSchemes() {
                             bitField0_ |= 0x00000001;
                             return internalGetMutableSchemes().ensureMessageMap();
                      @@ -626,7 +626,7 @@ public Builder removeSchemes(
                            */
                           public Builder putSchemes(
                               java.lang.String key,
                      -        io.a2a.grpc.StringList value) {
                      +        org.a2aproject.sdk.grpc.StringList value) {
                             if (key == null) { throw new NullPointerException("map key"); }
                             if (value == null) { throw new NullPointerException("map value"); }
                             internalGetMutableSchemes().ensureBuilderMap()
                      @@ -642,8 +642,8 @@ public Builder putSchemes(
                            * map<string, .lf.a2a.v1.StringList> schemes = 1;
                            */
                           public Builder putAllSchemes(
                      -        java.util.Map values) {
                      -      for (java.util.Map.Entry e : values.entrySet()) {
                      +        java.util.Map values) {
                      +      for (java.util.Map.Entry e : values.entrySet()) {
                               if (e.getKey() == null || e.getValue() == null) {
                                 throw new NullPointerException();
                               }
                      @@ -660,31 +660,31 @@ public Builder putAllSchemes(
                            *
                            * map<string, .lf.a2a.v1.StringList> schemes = 1;
                            */
                      -    public io.a2a.grpc.StringList.Builder putSchemesBuilderIfAbsent(
                      +    public org.a2aproject.sdk.grpc.StringList.Builder putSchemesBuilderIfAbsent(
                               java.lang.String key) {
                      -      java.util.Map builderMap = internalGetMutableSchemes().ensureBuilderMap();
                      -      io.a2a.grpc.StringListOrBuilder entry = builderMap.get(key);
                      +      java.util.Map builderMap = internalGetMutableSchemes().ensureBuilderMap();
                      +      org.a2aproject.sdk.grpc.StringListOrBuilder entry = builderMap.get(key);
                             if (entry == null) {
                      -        entry = io.a2a.grpc.StringList.newBuilder();
                      +        entry = org.a2aproject.sdk.grpc.StringList.newBuilder();
                               builderMap.put(key, entry);
                             }
                      -      if (entry instanceof io.a2a.grpc.StringList) {
                      -        entry = ((io.a2a.grpc.StringList) entry).toBuilder();
                      +      if (entry instanceof org.a2aproject.sdk.grpc.StringList) {
                      +        entry = ((org.a2aproject.sdk.grpc.StringList) entry).toBuilder();
                               builderMap.put(key, entry);
                             }
                      -      return (io.a2a.grpc.StringList.Builder) entry;
                      +      return (org.a2aproject.sdk.grpc.StringList.Builder) entry;
                           }
                       
                           // @@protoc_insertion_point(builder_scope:lf.a2a.v1.SecurityRequirement)
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.SecurityRequirement)
                      -  private static final io.a2a.grpc.SecurityRequirement DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.SecurityRequirement DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.SecurityRequirement();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.SecurityRequirement();
                         }
                       
                      -  public static io.a2a.grpc.SecurityRequirement getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.SecurityRequirement getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -720,7 +720,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.SecurityRequirement getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.SecurityRequirement getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityRequirementOrBuilder.java
                      similarity index 81%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityRequirementOrBuilder.java
                      index 6fe317ba1..396bd5110 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityRequirementOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface SecurityRequirementOrBuilder extends
                      @@ -31,7 +31,7 @@ boolean containsSchemes(
                          * Use {@link #getSchemesMap()} instead.
                          */
                         @java.lang.Deprecated
                      -  java.util.Map
                      +  java.util.Map
                         getSchemes();
                         /**
                          * 
                      @@ -40,7 +40,7 @@ boolean containsSchemes(
                          *
                          * map<string, .lf.a2a.v1.StringList> schemes = 1;
                          */
                      -  java.util.Map
                      +  java.util.Map
                         getSchemesMap();
                         /**
                          * 
                      @@ -50,10 +50,10 @@ boolean containsSchemes(
                          * map<string, .lf.a2a.v1.StringList> schemes = 1;
                          */
                         /* nullable */
                      -io.a2a.grpc.StringList getSchemesOrDefault(
                      +org.a2aproject.sdk.grpc.StringList getSchemesOrDefault(
                             java.lang.String key,
                             /* nullable */
                      -io.a2a.grpc.StringList defaultValue);
                      +org.a2aproject.sdk.grpc.StringList defaultValue);
                         /**
                          * 
                          * A map of security schemes to the required scopes.
                      @@ -61,6 +61,6 @@ io.a2a.grpc.StringList getSchemesOrDefault(
                          *
                          * map<string, .lf.a2a.v1.StringList> schemes = 1;
                          */
                      -  io.a2a.grpc.StringList getSchemesOrThrow(
                      +  org.a2aproject.sdk.grpc.StringList getSchemesOrThrow(
                             java.lang.String key);
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityScheme.java
                      similarity index 72%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityScheme.java
                      index db9617df3..4680b002b 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecurityScheme.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private SecurityScheme() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.SecurityScheme.class, io.a2a.grpc.SecurityScheme.Builder.class);
                      +            org.a2aproject.sdk.grpc.SecurityScheme.class, org.a2aproject.sdk.grpc.SecurityScheme.Builder.class);
                         }
                       
                         private int schemeCase_ = 0;
                      @@ -119,11 +119,11 @@ public boolean hasApiKeySecurityScheme() {
                          * @return The apiKeySecurityScheme.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme() {
                      +  public org.a2aproject.sdk.grpc.APIKeySecurityScheme getApiKeySecurityScheme() {
                           if (schemeCase_ == 1) {
                      -       return (io.a2a.grpc.APIKeySecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.APIKeySecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -133,11 +133,11 @@ public io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme() {
                          * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() {
                           if (schemeCase_ == 1) {
                      -       return (io.a2a.grpc.APIKeySecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.APIKeySecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance();
                         }
                       
                         public static final int HTTP_AUTH_SECURITY_SCHEME_FIELD_NUMBER = 2;
                      @@ -162,11 +162,11 @@ public boolean hasHttpAuthSecurityScheme() {
                          * @return The httpAuthSecurityScheme.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() {
                      +  public org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() {
                           if (schemeCase_ == 2) {
                      -       return (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -176,11 +176,11 @@ public io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() {
                          * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() {
                           if (schemeCase_ == 2) {
                      -       return (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                         }
                       
                         public static final int OAUTH2_SECURITY_SCHEME_FIELD_NUMBER = 3;
                      @@ -205,11 +205,11 @@ public boolean hasOauth2SecurityScheme() {
                          * @return The oauth2SecurityScheme.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() {
                      +  public org.a2aproject.sdk.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() {
                           if (schemeCase_ == 3) {
                      -       return (io.a2a.grpc.OAuth2SecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.OAuth2SecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -219,11 +219,11 @@ public io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() {
                          * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() {
                           if (schemeCase_ == 3) {
                      -       return (io.a2a.grpc.OAuth2SecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.OAuth2SecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance();
                         }
                       
                         public static final int OPEN_ID_CONNECT_SECURITY_SCHEME_FIELD_NUMBER = 4;
                      @@ -248,11 +248,11 @@ public boolean hasOpenIdConnectSecurityScheme() {
                          * @return The openIdConnectSecurityScheme.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() {
                      +  public org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() {
                           if (schemeCase_ == 4) {
                      -       return (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -262,11 +262,11 @@ public io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme()
                          * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() {
                           if (schemeCase_ == 4) {
                      -       return (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                         }
                       
                         public static final int MTLS_SECURITY_SCHEME_FIELD_NUMBER = 5;
                      @@ -291,11 +291,11 @@ public boolean hasMtlsSecurityScheme() {
                          * @return The mtlsSecurityScheme.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() {
                      +  public org.a2aproject.sdk.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() {
                           if (schemeCase_ == 5) {
                      -       return (io.a2a.grpc.MutualTlsSecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -305,11 +305,11 @@ public io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() {
                          * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() {
                           if (schemeCase_ == 5) {
                      -       return (io.a2a.grpc.MutualTlsSecurityScheme) scheme_;
                      +       return (org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) scheme_;
                           }
                      -    return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                         }
                       
                         private byte memoizedIsInitialized = -1;
                      @@ -327,19 +327,19 @@ public final boolean isInitialized() {
                         public void writeTo(com.google.protobuf.CodedOutputStream output)
                                             throws java.io.IOException {
                           if (schemeCase_ == 1) {
                      -      output.writeMessage(1, (io.a2a.grpc.APIKeySecurityScheme) scheme_);
                      +      output.writeMessage(1, (org.a2aproject.sdk.grpc.APIKeySecurityScheme) scheme_);
                           }
                           if (schemeCase_ == 2) {
                      -      output.writeMessage(2, (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_);
                      +      output.writeMessage(2, (org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) scheme_);
                           }
                           if (schemeCase_ == 3) {
                      -      output.writeMessage(3, (io.a2a.grpc.OAuth2SecurityScheme) scheme_);
                      +      output.writeMessage(3, (org.a2aproject.sdk.grpc.OAuth2SecurityScheme) scheme_);
                           }
                           if (schemeCase_ == 4) {
                      -      output.writeMessage(4, (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_);
                      +      output.writeMessage(4, (org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) scheme_);
                           }
                           if (schemeCase_ == 5) {
                      -      output.writeMessage(5, (io.a2a.grpc.MutualTlsSecurityScheme) scheme_);
                      +      output.writeMessage(5, (org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) scheme_);
                           }
                           getUnknownFields().writeTo(output);
                         }
                      @@ -352,23 +352,23 @@ public int getSerializedSize() {
                           size = 0;
                           if (schemeCase_ == 1) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(1, (io.a2a.grpc.APIKeySecurityScheme) scheme_);
                      +        .computeMessageSize(1, (org.a2aproject.sdk.grpc.APIKeySecurityScheme) scheme_);
                           }
                           if (schemeCase_ == 2) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(2, (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_);
                      +        .computeMessageSize(2, (org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) scheme_);
                           }
                           if (schemeCase_ == 3) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(3, (io.a2a.grpc.OAuth2SecurityScheme) scheme_);
                      +        .computeMessageSize(3, (org.a2aproject.sdk.grpc.OAuth2SecurityScheme) scheme_);
                           }
                           if (schemeCase_ == 4) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(4, (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_);
                      +        .computeMessageSize(4, (org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) scheme_);
                           }
                           if (schemeCase_ == 5) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(5, (io.a2a.grpc.MutualTlsSecurityScheme) scheme_);
                      +        .computeMessageSize(5, (org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) scheme_);
                           }
                           size += getUnknownFields().getSerializedSize();
                           memoizedSize = size;
                      @@ -380,10 +380,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.SecurityScheme)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.SecurityScheme)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.SecurityScheme other = (io.a2a.grpc.SecurityScheme) obj;
                      +    org.a2aproject.sdk.grpc.SecurityScheme other = (org.a2aproject.sdk.grpc.SecurityScheme) obj;
                       
                           if (!getSchemeCase().equals(other.getSchemeCase())) return false;
                           switch (schemeCase_) {
                      @@ -450,44 +450,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -495,26 +495,26 @@ public static io.a2a.grpc.SecurityScheme parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.SecurityScheme parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.SecurityScheme parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SecurityScheme parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -527,7 +527,7 @@ public static io.a2a.grpc.SecurityScheme parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.SecurityScheme prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.SecurityScheme prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -554,21 +554,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SecurityScheme)
                      -      io.a2a.grpc.SecuritySchemeOrBuilder {
                      +      org.a2aproject.sdk.grpc.SecuritySchemeOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.SecurityScheme.class, io.a2a.grpc.SecurityScheme.Builder.class);
                      +              org.a2aproject.sdk.grpc.SecurityScheme.class, org.a2aproject.sdk.grpc.SecurityScheme.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.SecurityScheme.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.SecurityScheme.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -605,17 +605,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SecurityScheme_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SecurityScheme getDefaultInstanceForType() {
                      -      return io.a2a.grpc.SecurityScheme.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.SecurityScheme getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.SecurityScheme.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SecurityScheme build() {
                      -      io.a2a.grpc.SecurityScheme result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.SecurityScheme build() {
                      +      org.a2aproject.sdk.grpc.SecurityScheme result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -623,19 +623,19 @@ public io.a2a.grpc.SecurityScheme build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SecurityScheme buildPartial() {
                      -      io.a2a.grpc.SecurityScheme result = new io.a2a.grpc.SecurityScheme(this);
                      +    public org.a2aproject.sdk.grpc.SecurityScheme buildPartial() {
                      +      org.a2aproject.sdk.grpc.SecurityScheme result = new org.a2aproject.sdk.grpc.SecurityScheme(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             buildPartialOneofs(result);
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.SecurityScheme result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.SecurityScheme result) {
                             int from_bitField0_ = bitField0_;
                           }
                       
                      -    private void buildPartialOneofs(io.a2a.grpc.SecurityScheme result) {
                      +    private void buildPartialOneofs(org.a2aproject.sdk.grpc.SecurityScheme result) {
                             result.schemeCase_ = schemeCase_;
                             result.scheme_ = this.scheme_;
                             if (schemeCase_ == 1 &&
                      @@ -662,16 +662,16 @@ private void buildPartialOneofs(io.a2a.grpc.SecurityScheme result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.SecurityScheme) {
                      -        return mergeFrom((io.a2a.grpc.SecurityScheme)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.SecurityScheme) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.SecurityScheme)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.SecurityScheme other) {
                      -      if (other == io.a2a.grpc.SecurityScheme.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.SecurityScheme other) {
                      +      if (other == org.a2aproject.sdk.grpc.SecurityScheme.getDefaultInstance()) return this;
                             switch (other.getSchemeCase()) {
                               case API_KEY_SECURITY_SCHEME: {
                                 mergeApiKeySecurityScheme(other.getApiKeySecurityScheme());
                      @@ -791,7 +791,7 @@ public Builder clearScheme() {
                           private int bitField0_;
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.APIKeySecurityScheme, io.a2a.grpc.APIKeySecurityScheme.Builder, io.a2a.grpc.APIKeySecuritySchemeOrBuilder> apiKeySecuritySchemeBuilder_;
                      +        org.a2aproject.sdk.grpc.APIKeySecurityScheme, org.a2aproject.sdk.grpc.APIKeySecurityScheme.Builder, org.a2aproject.sdk.grpc.APIKeySecuritySchemeOrBuilder> apiKeySecuritySchemeBuilder_;
                           /**
                            * 
                            * API key-based authentication.
                      @@ -813,17 +813,17 @@ public boolean hasApiKeySecurityScheme() {
                            * @return The apiKeySecurityScheme.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme() {
                      +    public org.a2aproject.sdk.grpc.APIKeySecurityScheme getApiKeySecurityScheme() {
                             if (apiKeySecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 1) {
                      -          return (io.a2a.grpc.APIKeySecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.APIKeySecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance();
                             } else {
                               if (schemeCase_ == 1) {
                                 return apiKeySecuritySchemeBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -833,7 +833,7 @@ public io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme() {
                            *
                            * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                            */
                      -    public Builder setApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) {
                      +    public Builder setApiKeySecurityScheme(org.a2aproject.sdk.grpc.APIKeySecurityScheme value) {
                             if (apiKeySecuritySchemeBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -854,7 +854,7 @@ public Builder setApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) {
                            * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                            */
                           public Builder setApiKeySecurityScheme(
                      -        io.a2a.grpc.APIKeySecurityScheme.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.APIKeySecurityScheme.Builder builderForValue) {
                             if (apiKeySecuritySchemeBuilder_ == null) {
                               scheme_ = builderForValue.build();
                               onChanged();
                      @@ -871,11 +871,11 @@ public Builder setApiKeySecurityScheme(
                            *
                            * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                            */
                      -    public Builder mergeApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) {
                      +    public Builder mergeApiKeySecurityScheme(org.a2aproject.sdk.grpc.APIKeySecurityScheme value) {
                             if (apiKeySecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 1 &&
                      -            scheme_ != io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance()) {
                      -          scheme_ = io.a2a.grpc.APIKeySecurityScheme.newBuilder((io.a2a.grpc.APIKeySecurityScheme) scheme_)
                      +            scheme_ != org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance()) {
                      +          scheme_ = org.a2aproject.sdk.grpc.APIKeySecurityScheme.newBuilder((org.a2aproject.sdk.grpc.APIKeySecurityScheme) scheme_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 scheme_ = value;
                      @@ -921,7 +921,7 @@ public Builder clearApiKeySecurityScheme() {
                            *
                            * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                            */
                      -    public io.a2a.grpc.APIKeySecurityScheme.Builder getApiKeySecuritySchemeBuilder() {
                      +    public org.a2aproject.sdk.grpc.APIKeySecurityScheme.Builder getApiKeySecuritySchemeBuilder() {
                             return internalGetApiKeySecuritySchemeFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -932,14 +932,14 @@ public io.a2a.grpc.APIKeySecurityScheme.Builder getApiKeySecuritySchemeBuilder()
                            * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() {
                             if ((schemeCase_ == 1) && (apiKeySecuritySchemeBuilder_ != null)) {
                               return apiKeySecuritySchemeBuilder_.getMessageOrBuilder();
                             } else {
                               if (schemeCase_ == 1) {
                      -          return (io.a2a.grpc.APIKeySecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.APIKeySecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -950,15 +950,15 @@ public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilde
                            * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.APIKeySecurityScheme, io.a2a.grpc.APIKeySecurityScheme.Builder, io.a2a.grpc.APIKeySecuritySchemeOrBuilder> 
                      +        org.a2aproject.sdk.grpc.APIKeySecurityScheme, org.a2aproject.sdk.grpc.APIKeySecurityScheme.Builder, org.a2aproject.sdk.grpc.APIKeySecuritySchemeOrBuilder> 
                               internalGetApiKeySecuritySchemeFieldBuilder() {
                             if (apiKeySecuritySchemeBuilder_ == null) {
                               if (!(schemeCase_ == 1)) {
                      -          scheme_ = io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance();
                      +          scheme_ = org.a2aproject.sdk.grpc.APIKeySecurityScheme.getDefaultInstance();
                               }
                               apiKeySecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.APIKeySecurityScheme, io.a2a.grpc.APIKeySecurityScheme.Builder, io.a2a.grpc.APIKeySecuritySchemeOrBuilder>(
                      -                (io.a2a.grpc.APIKeySecurityScheme) scheme_,
                      +            org.a2aproject.sdk.grpc.APIKeySecurityScheme, org.a2aproject.sdk.grpc.APIKeySecurityScheme.Builder, org.a2aproject.sdk.grpc.APIKeySecuritySchemeOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.APIKeySecurityScheme) scheme_,
                                       getParentForChildren(),
                                       isClean());
                               scheme_ = null;
                      @@ -969,7 +969,7 @@ public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilde
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.HTTPAuthSecurityScheme, io.a2a.grpc.HTTPAuthSecurityScheme.Builder, io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder> httpAuthSecuritySchemeBuilder_;
                      +        org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme, org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.Builder, org.a2aproject.sdk.grpc.HTTPAuthSecuritySchemeOrBuilder> httpAuthSecuritySchemeBuilder_;
                           /**
                            * 
                            * HTTP authentication (Basic, Bearer, etc.).
                      @@ -991,17 +991,17 @@ public boolean hasHttpAuthSecurityScheme() {
                            * @return The httpAuthSecurityScheme.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() {
                      +    public org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() {
                             if (httpAuthSecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 2) {
                      -          return (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                             } else {
                               if (schemeCase_ == 2) {
                                 return httpAuthSecuritySchemeBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1011,7 +1011,7 @@ public io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() {
                            *
                            * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                            */
                      -    public Builder setHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme value) {
                      +    public Builder setHttpAuthSecurityScheme(org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme value) {
                             if (httpAuthSecuritySchemeBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1032,7 +1032,7 @@ public Builder setHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme valu
                            * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                            */
                           public Builder setHttpAuthSecurityScheme(
                      -        io.a2a.grpc.HTTPAuthSecurityScheme.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.Builder builderForValue) {
                             if (httpAuthSecuritySchemeBuilder_ == null) {
                               scheme_ = builderForValue.build();
                               onChanged();
                      @@ -1049,11 +1049,11 @@ public Builder setHttpAuthSecurityScheme(
                            *
                            * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                            */
                      -    public Builder mergeHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme value) {
                      +    public Builder mergeHttpAuthSecurityScheme(org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme value) {
                             if (httpAuthSecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 2 &&
                      -            scheme_ != io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance()) {
                      -          scheme_ = io.a2a.grpc.HTTPAuthSecurityScheme.newBuilder((io.a2a.grpc.HTTPAuthSecurityScheme) scheme_)
                      +            scheme_ != org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance()) {
                      +          scheme_ = org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.newBuilder((org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) scheme_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 scheme_ = value;
                      @@ -1099,7 +1099,7 @@ public Builder clearHttpAuthSecurityScheme() {
                            *
                            * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                            */
                      -    public io.a2a.grpc.HTTPAuthSecurityScheme.Builder getHttpAuthSecuritySchemeBuilder() {
                      +    public org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.Builder getHttpAuthSecuritySchemeBuilder() {
                             return internalGetHttpAuthSecuritySchemeFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1110,14 +1110,14 @@ public io.a2a.grpc.HTTPAuthSecurityScheme.Builder getHttpAuthSecuritySchemeBuild
                            * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() {
                             if ((schemeCase_ == 2) && (httpAuthSecuritySchemeBuilder_ != null)) {
                               return httpAuthSecuritySchemeBuilder_.getMessageOrBuilder();
                             } else {
                               if (schemeCase_ == 2) {
                      -          return (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1128,15 +1128,15 @@ public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBu
                            * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.HTTPAuthSecurityScheme, io.a2a.grpc.HTTPAuthSecurityScheme.Builder, io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder> 
                      +        org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme, org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.Builder, org.a2aproject.sdk.grpc.HTTPAuthSecuritySchemeOrBuilder> 
                               internalGetHttpAuthSecuritySchemeFieldBuilder() {
                             if (httpAuthSecuritySchemeBuilder_ == null) {
                               if (!(schemeCase_ == 2)) {
                      -          scheme_ = io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                      +          scheme_ = org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.getDefaultInstance();
                               }
                               httpAuthSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.HTTPAuthSecurityScheme, io.a2a.grpc.HTTPAuthSecurityScheme.Builder, io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder>(
                      -                (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_,
                      +            org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme, org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme.Builder, org.a2aproject.sdk.grpc.HTTPAuthSecuritySchemeOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme) scheme_,
                                       getParentForChildren(),
                                       isClean());
                               scheme_ = null;
                      @@ -1147,7 +1147,7 @@ public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBu
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.OAuth2SecurityScheme, io.a2a.grpc.OAuth2SecurityScheme.Builder, io.a2a.grpc.OAuth2SecuritySchemeOrBuilder> oauth2SecuritySchemeBuilder_;
                      +        org.a2aproject.sdk.grpc.OAuth2SecurityScheme, org.a2aproject.sdk.grpc.OAuth2SecurityScheme.Builder, org.a2aproject.sdk.grpc.OAuth2SecuritySchemeOrBuilder> oauth2SecuritySchemeBuilder_;
                           /**
                            * 
                            * OAuth 2.0 authentication.
                      @@ -1169,17 +1169,17 @@ public boolean hasOauth2SecurityScheme() {
                            * @return The oauth2SecurityScheme.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() {
                      +    public org.a2aproject.sdk.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() {
                             if (oauth2SecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 3) {
                      -          return (io.a2a.grpc.OAuth2SecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.OAuth2SecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance();
                             } else {
                               if (schemeCase_ == 3) {
                                 return oauth2SecuritySchemeBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1189,7 +1189,7 @@ public io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() {
                            *
                            * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                            */
                      -    public Builder setOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) {
                      +    public Builder setOauth2SecurityScheme(org.a2aproject.sdk.grpc.OAuth2SecurityScheme value) {
                             if (oauth2SecuritySchemeBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1210,7 +1210,7 @@ public Builder setOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) {
                            * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                            */
                           public Builder setOauth2SecurityScheme(
                      -        io.a2a.grpc.OAuth2SecurityScheme.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.OAuth2SecurityScheme.Builder builderForValue) {
                             if (oauth2SecuritySchemeBuilder_ == null) {
                               scheme_ = builderForValue.build();
                               onChanged();
                      @@ -1227,11 +1227,11 @@ public Builder setOauth2SecurityScheme(
                            *
                            * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                            */
                      -    public Builder mergeOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) {
                      +    public Builder mergeOauth2SecurityScheme(org.a2aproject.sdk.grpc.OAuth2SecurityScheme value) {
                             if (oauth2SecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 3 &&
                      -            scheme_ != io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance()) {
                      -          scheme_ = io.a2a.grpc.OAuth2SecurityScheme.newBuilder((io.a2a.grpc.OAuth2SecurityScheme) scheme_)
                      +            scheme_ != org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance()) {
                      +          scheme_ = org.a2aproject.sdk.grpc.OAuth2SecurityScheme.newBuilder((org.a2aproject.sdk.grpc.OAuth2SecurityScheme) scheme_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 scheme_ = value;
                      @@ -1277,7 +1277,7 @@ public Builder clearOauth2SecurityScheme() {
                            *
                            * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                            */
                      -    public io.a2a.grpc.OAuth2SecurityScheme.Builder getOauth2SecuritySchemeBuilder() {
                      +    public org.a2aproject.sdk.grpc.OAuth2SecurityScheme.Builder getOauth2SecuritySchemeBuilder() {
                             return internalGetOauth2SecuritySchemeFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1288,14 +1288,14 @@ public io.a2a.grpc.OAuth2SecurityScheme.Builder getOauth2SecuritySchemeBuilder()
                            * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() {
                             if ((schemeCase_ == 3) && (oauth2SecuritySchemeBuilder_ != null)) {
                               return oauth2SecuritySchemeBuilder_.getMessageOrBuilder();
                             } else {
                               if (schemeCase_ == 3) {
                      -          return (io.a2a.grpc.OAuth2SecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.OAuth2SecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1306,15 +1306,15 @@ public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilde
                            * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.OAuth2SecurityScheme, io.a2a.grpc.OAuth2SecurityScheme.Builder, io.a2a.grpc.OAuth2SecuritySchemeOrBuilder> 
                      +        org.a2aproject.sdk.grpc.OAuth2SecurityScheme, org.a2aproject.sdk.grpc.OAuth2SecurityScheme.Builder, org.a2aproject.sdk.grpc.OAuth2SecuritySchemeOrBuilder> 
                               internalGetOauth2SecuritySchemeFieldBuilder() {
                             if (oauth2SecuritySchemeBuilder_ == null) {
                               if (!(schemeCase_ == 3)) {
                      -          scheme_ = io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance();
                      +          scheme_ = org.a2aproject.sdk.grpc.OAuth2SecurityScheme.getDefaultInstance();
                               }
                               oauth2SecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.OAuth2SecurityScheme, io.a2a.grpc.OAuth2SecurityScheme.Builder, io.a2a.grpc.OAuth2SecuritySchemeOrBuilder>(
                      -                (io.a2a.grpc.OAuth2SecurityScheme) scheme_,
                      +            org.a2aproject.sdk.grpc.OAuth2SecurityScheme, org.a2aproject.sdk.grpc.OAuth2SecurityScheme.Builder, org.a2aproject.sdk.grpc.OAuth2SecuritySchemeOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.OAuth2SecurityScheme) scheme_,
                                       getParentForChildren(),
                                       isClean());
                               scheme_ = null;
                      @@ -1325,7 +1325,7 @@ public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilde
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.OpenIdConnectSecurityScheme, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder, io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder> openIdConnectSecuritySchemeBuilder_;
                      +        org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme, org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.Builder, org.a2aproject.sdk.grpc.OpenIdConnectSecuritySchemeOrBuilder> openIdConnectSecuritySchemeBuilder_;
                           /**
                            * 
                            * OpenID Connect authentication.
                      @@ -1347,17 +1347,17 @@ public boolean hasOpenIdConnectSecurityScheme() {
                            * @return The openIdConnectSecurityScheme.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() {
                      +    public org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() {
                             if (openIdConnectSecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 4) {
                      -          return (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                             } else {
                               if (schemeCase_ == 4) {
                                 return openIdConnectSecuritySchemeBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1367,7 +1367,7 @@ public io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme()
                            *
                            * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                            */
                      -    public Builder setOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurityScheme value) {
                      +    public Builder setOpenIdConnectSecurityScheme(org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme value) {
                             if (openIdConnectSecuritySchemeBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1388,7 +1388,7 @@ public Builder setOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurityS
                            * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                            */
                           public Builder setOpenIdConnectSecurityScheme(
                      -        io.a2a.grpc.OpenIdConnectSecurityScheme.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.Builder builderForValue) {
                             if (openIdConnectSecuritySchemeBuilder_ == null) {
                               scheme_ = builderForValue.build();
                               onChanged();
                      @@ -1405,11 +1405,11 @@ public Builder setOpenIdConnectSecurityScheme(
                            *
                            * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                            */
                      -    public Builder mergeOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurityScheme value) {
                      +    public Builder mergeOpenIdConnectSecurityScheme(org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme value) {
                             if (openIdConnectSecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 4 &&
                      -            scheme_ != io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance()) {
                      -          scheme_ = io.a2a.grpc.OpenIdConnectSecurityScheme.newBuilder((io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_)
                      +            scheme_ != org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance()) {
                      +          scheme_ = org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.newBuilder((org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) scheme_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 scheme_ = value;
                      @@ -1455,7 +1455,7 @@ public Builder clearOpenIdConnectSecurityScheme() {
                            *
                            * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                            */
                      -    public io.a2a.grpc.OpenIdConnectSecurityScheme.Builder getOpenIdConnectSecuritySchemeBuilder() {
                      +    public org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.Builder getOpenIdConnectSecuritySchemeBuilder() {
                             return internalGetOpenIdConnectSecuritySchemeFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1466,14 +1466,14 @@ public io.a2a.grpc.OpenIdConnectSecurityScheme.Builder getOpenIdConnectSecurityS
                            * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() {
                             if ((schemeCase_ == 4) && (openIdConnectSecuritySchemeBuilder_ != null)) {
                               return openIdConnectSecuritySchemeBuilder_.getMessageOrBuilder();
                             } else {
                               if (schemeCase_ == 4) {
                      -          return (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1484,15 +1484,15 @@ public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecurity
                            * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.OpenIdConnectSecurityScheme, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder, io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder> 
                      +        org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme, org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.Builder, org.a2aproject.sdk.grpc.OpenIdConnectSecuritySchemeOrBuilder> 
                               internalGetOpenIdConnectSecuritySchemeFieldBuilder() {
                             if (openIdConnectSecuritySchemeBuilder_ == null) {
                               if (!(schemeCase_ == 4)) {
                      -          scheme_ = io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                      +          scheme_ = org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.getDefaultInstance();
                               }
                               openIdConnectSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.OpenIdConnectSecurityScheme, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder, io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder>(
                      -                (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_,
                      +            org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme, org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme.Builder, org.a2aproject.sdk.grpc.OpenIdConnectSecuritySchemeOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme) scheme_,
                                       getParentForChildren(),
                                       isClean());
                               scheme_ = null;
                      @@ -1503,7 +1503,7 @@ public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecurity
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.MutualTlsSecurityScheme, io.a2a.grpc.MutualTlsSecurityScheme.Builder, io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder> mtlsSecuritySchemeBuilder_;
                      +        org.a2aproject.sdk.grpc.MutualTlsSecurityScheme, org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.Builder, org.a2aproject.sdk.grpc.MutualTlsSecuritySchemeOrBuilder> mtlsSecuritySchemeBuilder_;
                           /**
                            * 
                            * Mutual TLS authentication.
                      @@ -1525,17 +1525,17 @@ public boolean hasMtlsSecurityScheme() {
                            * @return The mtlsSecurityScheme.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() {
                      +    public org.a2aproject.sdk.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() {
                             if (mtlsSecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 5) {
                      -          return (io.a2a.grpc.MutualTlsSecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                             } else {
                               if (schemeCase_ == 5) {
                                 return mtlsSecuritySchemeBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1545,7 +1545,7 @@ public io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() {
                            *
                            * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                            */
                      -    public Builder setMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value) {
                      +    public Builder setMtlsSecurityScheme(org.a2aproject.sdk.grpc.MutualTlsSecurityScheme value) {
                             if (mtlsSecuritySchemeBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1566,7 +1566,7 @@ public Builder setMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value)
                            * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                            */
                           public Builder setMtlsSecurityScheme(
                      -        io.a2a.grpc.MutualTlsSecurityScheme.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.Builder builderForValue) {
                             if (mtlsSecuritySchemeBuilder_ == null) {
                               scheme_ = builderForValue.build();
                               onChanged();
                      @@ -1583,11 +1583,11 @@ public Builder setMtlsSecurityScheme(
                            *
                            * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                            */
                      -    public Builder mergeMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value) {
                      +    public Builder mergeMtlsSecurityScheme(org.a2aproject.sdk.grpc.MutualTlsSecurityScheme value) {
                             if (mtlsSecuritySchemeBuilder_ == null) {
                               if (schemeCase_ == 5 &&
                      -            scheme_ != io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance()) {
                      -          scheme_ = io.a2a.grpc.MutualTlsSecurityScheme.newBuilder((io.a2a.grpc.MutualTlsSecurityScheme) scheme_)
                      +            scheme_ != org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance()) {
                      +          scheme_ = org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.newBuilder((org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) scheme_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 scheme_ = value;
                      @@ -1633,7 +1633,7 @@ public Builder clearMtlsSecurityScheme() {
                            *
                            * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                            */
                      -    public io.a2a.grpc.MutualTlsSecurityScheme.Builder getMtlsSecuritySchemeBuilder() {
                      +    public org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.Builder getMtlsSecuritySchemeBuilder() {
                             return internalGetMtlsSecuritySchemeFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1644,14 +1644,14 @@ public io.a2a.grpc.MutualTlsSecurityScheme.Builder getMtlsSecuritySchemeBuilder(
                            * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() {
                             if ((schemeCase_ == 5) && (mtlsSecuritySchemeBuilder_ != null)) {
                               return mtlsSecuritySchemeBuilder_.getMessageOrBuilder();
                             } else {
                               if (schemeCase_ == 5) {
                      -          return (io.a2a.grpc.MutualTlsSecurityScheme) scheme_;
                      +          return (org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) scheme_;
                               }
                      -        return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1662,15 +1662,15 @@ public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuild
                            * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.MutualTlsSecurityScheme, io.a2a.grpc.MutualTlsSecurityScheme.Builder, io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder> 
                      +        org.a2aproject.sdk.grpc.MutualTlsSecurityScheme, org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.Builder, org.a2aproject.sdk.grpc.MutualTlsSecuritySchemeOrBuilder> 
                               internalGetMtlsSecuritySchemeFieldBuilder() {
                             if (mtlsSecuritySchemeBuilder_ == null) {
                               if (!(schemeCase_ == 5)) {
                      -          scheme_ = io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                      +          scheme_ = org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.getDefaultInstance();
                               }
                               mtlsSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.MutualTlsSecurityScheme, io.a2a.grpc.MutualTlsSecurityScheme.Builder, io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder>(
                      -                (io.a2a.grpc.MutualTlsSecurityScheme) scheme_,
                      +            org.a2aproject.sdk.grpc.MutualTlsSecurityScheme, org.a2aproject.sdk.grpc.MutualTlsSecurityScheme.Builder, org.a2aproject.sdk.grpc.MutualTlsSecuritySchemeOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.MutualTlsSecurityScheme) scheme_,
                                       getParentForChildren(),
                                       isClean());
                               scheme_ = null;
                      @@ -1684,12 +1684,12 @@ public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuild
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.SecurityScheme)
                      -  private static final io.a2a.grpc.SecurityScheme DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.SecurityScheme DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.SecurityScheme();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.SecurityScheme();
                         }
                       
                      -  public static io.a2a.grpc.SecurityScheme getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.SecurityScheme getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1725,7 +1725,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.SecurityScheme getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.SecurityScheme getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecuritySchemeOrBuilder.java
                      similarity index 78%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecuritySchemeOrBuilder.java
                      index c76a1b560..ff5dd654e 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SecuritySchemeOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface SecuritySchemeOrBuilder extends
                      @@ -27,7 +27,7 @@ public interface SecuritySchemeOrBuilder extends
                          * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                          * @return The apiKeySecurityScheme.
                          */
                      -  io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme();
                      +  org.a2aproject.sdk.grpc.APIKeySecurityScheme getApiKeySecurityScheme();
                         /**
                          * 
                          * API key-based authentication.
                      @@ -35,7 +35,7 @@ public interface SecuritySchemeOrBuilder extends
                          *
                          * .lf.a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1;
                          */
                      -  io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder();
                      +  org.a2aproject.sdk.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder();
                       
                         /**
                          * 
                      @@ -54,7 +54,7 @@ public interface SecuritySchemeOrBuilder extends
                          * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                          * @return The httpAuthSecurityScheme.
                          */
                      -  io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme();
                      +  org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme();
                         /**
                          * 
                          * HTTP authentication (Basic, Bearer, etc.).
                      @@ -62,7 +62,7 @@ public interface SecuritySchemeOrBuilder extends
                          *
                          * .lf.a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2;
                          */
                      -  io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder();
                      +  org.a2aproject.sdk.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder();
                       
                         /**
                          * 
                      @@ -81,7 +81,7 @@ public interface SecuritySchemeOrBuilder extends
                          * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                          * @return The oauth2SecurityScheme.
                          */
                      -  io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme();
                      +  org.a2aproject.sdk.grpc.OAuth2SecurityScheme getOauth2SecurityScheme();
                         /**
                          * 
                          * OAuth 2.0 authentication.
                      @@ -89,7 +89,7 @@ public interface SecuritySchemeOrBuilder extends
                          *
                          * .lf.a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3;
                          */
                      -  io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder();
                      +  org.a2aproject.sdk.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder();
                       
                         /**
                          * 
                      @@ -108,7 +108,7 @@ public interface SecuritySchemeOrBuilder extends
                          * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                          * @return The openIdConnectSecurityScheme.
                          */
                      -  io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme();
                      +  org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme();
                         /**
                          * 
                          * OpenID Connect authentication.
                      @@ -116,7 +116,7 @@ public interface SecuritySchemeOrBuilder extends
                          *
                          * .lf.a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
                          */
                      -  io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder();
                      +  org.a2aproject.sdk.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder();
                       
                         /**
                          * 
                      @@ -135,7 +135,7 @@ public interface SecuritySchemeOrBuilder extends
                          * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                          * @return The mtlsSecurityScheme.
                          */
                      -  io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme();
                      +  org.a2aproject.sdk.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme();
                         /**
                          * 
                          * Mutual TLS authentication.
                      @@ -143,7 +143,7 @@ public interface SecuritySchemeOrBuilder extends
                          *
                          * .lf.a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5;
                          */
                      -  io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder();
                      +  org.a2aproject.sdk.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder();
                       
                      -  io.a2a.grpc.SecurityScheme.SchemeCase getSchemeCase();
                      +  org.a2aproject.sdk.grpc.SecurityScheme.SchemeCase getSchemeCase();
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageConfiguration.java
                      similarity index 86%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageConfiguration.java
                      index bedda4ab3..a37272b47 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageConfiguration.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private SendMessageConfiguration() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.SendMessageConfiguration.class, io.a2a.grpc.SendMessageConfiguration.Builder.class);
                      +            org.a2aproject.sdk.grpc.SendMessageConfiguration.class, org.a2aproject.sdk.grpc.SendMessageConfiguration.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -108,7 +108,7 @@ public java.lang.String getAcceptedOutputModes(int index) {
                         }
                       
                         public static final int TASK_PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 2;
                      -  private io.a2a.grpc.TaskPushNotificationConfig taskPushNotificationConfig_;
                      +  private org.a2aproject.sdk.grpc.TaskPushNotificationConfig taskPushNotificationConfig_;
                         /**
                          * 
                          * Configuration for the agent to send push notifications for task updates.
                      @@ -132,8 +132,8 @@ public boolean hasTaskPushNotificationConfig() {
                          * @return The taskPushNotificationConfig.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig() {
                      -    return taskPushNotificationConfig_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_;
                      +  public org.a2aproject.sdk.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig() {
                      +    return taskPushNotificationConfig_ == null ? org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_;
                         }
                         /**
                          * 
                      @@ -144,8 +144,8 @@ public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig() {
                          * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder() {
                      -    return taskPushNotificationConfig_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_;
                      +  public org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder() {
                      +    return taskPushNotificationConfig_ == null ? org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_;
                         }
                       
                         public static final int HISTORY_LENGTH_FIELD_NUMBER = 3;
                      @@ -265,10 +265,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.SendMessageConfiguration)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.SendMessageConfiguration)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.SendMessageConfiguration other = (io.a2a.grpc.SendMessageConfiguration) obj;
                      +    org.a2aproject.sdk.grpc.SendMessageConfiguration other = (org.a2aproject.sdk.grpc.SendMessageConfiguration) obj;
                       
                           if (!getAcceptedOutputModesList()
                               .equals(other.getAcceptedOutputModesList())) return false;
                      @@ -315,44 +315,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -360,26 +360,26 @@ public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.SendMessageConfiguration parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.SendMessageConfiguration parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -392,7 +392,7 @@ public static io.a2a.grpc.SendMessageConfiguration parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.SendMessageConfiguration prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.SendMessageConfiguration prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -417,21 +417,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SendMessageConfiguration)
                      -      io.a2a.grpc.SendMessageConfigurationOrBuilder {
                      +      org.a2aproject.sdk.grpc.SendMessageConfigurationOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.SendMessageConfiguration.class, io.a2a.grpc.SendMessageConfiguration.Builder.class);
                      +              org.a2aproject.sdk.grpc.SendMessageConfiguration.class, org.a2aproject.sdk.grpc.SendMessageConfiguration.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.SendMessageConfiguration.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.SendMessageConfiguration.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -466,17 +466,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageConfiguration_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageConfiguration getDefaultInstanceForType() {
                      -      return io.a2a.grpc.SendMessageConfiguration.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.SendMessageConfiguration getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.SendMessageConfiguration.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageConfiguration build() {
                      -      io.a2a.grpc.SendMessageConfiguration result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.SendMessageConfiguration build() {
                      +      org.a2aproject.sdk.grpc.SendMessageConfiguration result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -484,14 +484,14 @@ public io.a2a.grpc.SendMessageConfiguration build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageConfiguration buildPartial() {
                      -      io.a2a.grpc.SendMessageConfiguration result = new io.a2a.grpc.SendMessageConfiguration(this);
                      +    public org.a2aproject.sdk.grpc.SendMessageConfiguration buildPartial() {
                      +      org.a2aproject.sdk.grpc.SendMessageConfiguration result = new org.a2aproject.sdk.grpc.SendMessageConfiguration(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.SendMessageConfiguration result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.SendMessageConfiguration result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               acceptedOutputModes_.makeImmutable();
                      @@ -516,16 +516,16 @@ private void buildPartial0(io.a2a.grpc.SendMessageConfiguration result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.SendMessageConfiguration) {
                      -        return mergeFrom((io.a2a.grpc.SendMessageConfiguration)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.SendMessageConfiguration) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.SendMessageConfiguration)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.SendMessageConfiguration other) {
                      -      if (other == io.a2a.grpc.SendMessageConfiguration.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.SendMessageConfiguration other) {
                      +      if (other == org.a2aproject.sdk.grpc.SendMessageConfiguration.getDefaultInstance()) return this;
                             if (!other.acceptedOutputModes_.isEmpty()) {
                               if (acceptedOutputModes_.isEmpty()) {
                                 acceptedOutputModes_ = other.acceptedOutputModes_;
                      @@ -767,9 +767,9 @@ public Builder addAcceptedOutputModesBytes(
                             return this;
                           }
                       
                      -    private io.a2a.grpc.TaskPushNotificationConfig taskPushNotificationConfig_;
                      +    private org.a2aproject.sdk.grpc.TaskPushNotificationConfig taskPushNotificationConfig_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> taskPushNotificationConfigBuilder_;
                      +        org.a2aproject.sdk.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder> taskPushNotificationConfigBuilder_;
                           /**
                            * 
                            * Configuration for the agent to send push notifications for task updates.
                      @@ -791,9 +791,9 @@ public boolean hasTaskPushNotificationConfig() {
                            * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                            * @return The taskPushNotificationConfig.
                            */
                      -    public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig() {
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig() {
                             if (taskPushNotificationConfigBuilder_ == null) {
                      -        return taskPushNotificationConfig_ == null ? io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_;
                      +        return taskPushNotificationConfig_ == null ? org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_;
                             } else {
                               return taskPushNotificationConfigBuilder_.getMessage();
                             }
                      @@ -806,7 +806,7 @@ public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig() {
                            *
                            * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                            */
                      -    public Builder setTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig value) {
                      +    public Builder setTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfig value) {
                             if (taskPushNotificationConfigBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -828,7 +828,7 @@ public Builder setTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationCon
                            * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                            */
                           public Builder setTaskPushNotificationConfig(
                      -        io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder builderForValue) {
                             if (taskPushNotificationConfigBuilder_ == null) {
                               taskPushNotificationConfig_ = builderForValue.build();
                             } else {
                      @@ -846,11 +846,11 @@ public Builder setTaskPushNotificationConfig(
                            *
                            * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                            */
                      -    public Builder mergeTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig value) {
                      +    public Builder mergeTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfig value) {
                             if (taskPushNotificationConfigBuilder_ == null) {
                               if (((bitField0_ & 0x00000002) != 0) &&
                                 taskPushNotificationConfig_ != null &&
                      -          taskPushNotificationConfig_ != io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance()) {
                      +          taskPushNotificationConfig_ != org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance()) {
                                 getTaskPushNotificationConfigBuilder().mergeFrom(value);
                               } else {
                                 taskPushNotificationConfig_ = value;
                      @@ -890,7 +890,7 @@ public Builder clearTaskPushNotificationConfig() {
                            *
                            * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                            */
                      -    public io.a2a.grpc.TaskPushNotificationConfig.Builder getTaskPushNotificationConfigBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder getTaskPushNotificationConfigBuilder() {
                             bitField0_ |= 0x00000002;
                             onChanged();
                             return internalGetTaskPushNotificationConfigFieldBuilder().getBuilder();
                      @@ -903,12 +903,12 @@ public io.a2a.grpc.TaskPushNotificationConfig.Builder getTaskPushNotificationCon
                            *
                            * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                            */
                      -    public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder() {
                             if (taskPushNotificationConfigBuilder_ != null) {
                               return taskPushNotificationConfigBuilder_.getMessageOrBuilder();
                             } else {
                               return taskPushNotificationConfig_ == null ?
                      -            io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_;
                      +            org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance() : taskPushNotificationConfig_;
                             }
                           }
                           /**
                      @@ -920,11 +920,11 @@ public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationCo
                            * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> 
                      +        org.a2aproject.sdk.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder> 
                               internalGetTaskPushNotificationConfigFieldBuilder() {
                             if (taskPushNotificationConfigBuilder_ == null) {
                               taskPushNotificationConfigBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder>(
                      +            org.a2aproject.sdk.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder>(
                                       getTaskPushNotificationConfig(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -1061,12 +1061,12 @@ public Builder clearReturnImmediately() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.SendMessageConfiguration)
                      -  private static final io.a2a.grpc.SendMessageConfiguration DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.SendMessageConfiguration DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageConfiguration();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.SendMessageConfiguration();
                         }
                       
                      -  public static io.a2a.grpc.SendMessageConfiguration getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.SendMessageConfiguration getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1102,7 +1102,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.SendMessageConfiguration getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.SendMessageConfiguration getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageConfigurationOrBuilder.java
                      similarity index 95%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageConfigurationOrBuilder.java
                      index affb9b361..7b2bbcca2 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageConfigurationOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface SendMessageConfigurationOrBuilder extends
                      @@ -74,7 +74,7 @@ public interface SendMessageConfigurationOrBuilder extends
                          * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                          * @return The taskPushNotificationConfig.
                          */
                      -  io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig();
                      +  org.a2aproject.sdk.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig();
                         /**
                          * 
                          * Configuration for the agent to send push notifications for task updates.
                      @@ -83,7 +83,7 @@ public interface SendMessageConfigurationOrBuilder extends
                          *
                          * .lf.a2a.v1.TaskPushNotificationConfig task_push_notification_config = 2;
                          */
                      -  io.a2a.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder();
                      +  org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder getTaskPushNotificationConfigOrBuilder();
                       
                         /**
                          * 
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageRequest.java
                      similarity index 83%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageRequest.java
                      index c629f23d5..e3a35f139 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -37,15 +37,15 @@ private SendMessageRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.SendMessageRequest.class, io.a2a.grpc.SendMessageRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.SendMessageRequest.class, org.a2aproject.sdk.grpc.SendMessageRequest.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -97,7 +97,7 @@ public java.lang.String getTenant() {
                         }
                       
                         public static final int MESSAGE_FIELD_NUMBER = 2;
                      -  private io.a2a.grpc.Message message_;
                      +  private org.a2aproject.sdk.grpc.Message message_;
                         /**
                          * 
                          * The message to send to the agent.
                      @@ -119,8 +119,8 @@ public boolean hasMessage() {
                          * @return The message.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Message getMessage() {
                      -    return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_;
                      +  public org.a2aproject.sdk.grpc.Message getMessage() {
                      +    return message_ == null ? org.a2aproject.sdk.grpc.Message.getDefaultInstance() : message_;
                         }
                         /**
                          * 
                      @@ -130,12 +130,12 @@ public io.a2a.grpc.Message getMessage() {
                          * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                      -    return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_;
                      +  public org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder() {
                      +    return message_ == null ? org.a2aproject.sdk.grpc.Message.getDefaultInstance() : message_;
                         }
                       
                         public static final int CONFIGURATION_FIELD_NUMBER = 3;
                      -  private io.a2a.grpc.SendMessageConfiguration configuration_;
                      +  private org.a2aproject.sdk.grpc.SendMessageConfiguration configuration_;
                         /**
                          * 
                          * Configuration for the send request.
                      @@ -157,8 +157,8 @@ public boolean hasConfiguration() {
                          * @return The configuration.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.SendMessageConfiguration getConfiguration() {
                      -    return configuration_ == null ? io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_;
                      +  public org.a2aproject.sdk.grpc.SendMessageConfiguration getConfiguration() {
                      +    return configuration_ == null ? org.a2aproject.sdk.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_;
                         }
                         /**
                          * 
                      @@ -168,8 +168,8 @@ public io.a2a.grpc.SendMessageConfiguration getConfiguration() {
                          * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() {
                      -    return configuration_ == null ? io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_;
                      +  public org.a2aproject.sdk.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() {
                      +    return configuration_ == null ? org.a2aproject.sdk.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_;
                         }
                       
                         public static final int METADATA_FIELD_NUMBER = 4;
                      @@ -270,10 +270,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.SendMessageRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.SendMessageRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.SendMessageRequest other = (io.a2a.grpc.SendMessageRequest) obj;
                      +    org.a2aproject.sdk.grpc.SendMessageRequest other = (org.a2aproject.sdk.grpc.SendMessageRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -322,44 +322,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -367,26 +367,26 @@ public static io.a2a.grpc.SendMessageRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.SendMessageRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.SendMessageRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SendMessageRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -399,7 +399,7 @@ public static io.a2a.grpc.SendMessageRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.SendMessageRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.SendMessageRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -424,21 +424,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SendMessageRequest)
                      -      io.a2a.grpc.SendMessageRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.SendMessageRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.SendMessageRequest.class, io.a2a.grpc.SendMessageRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.SendMessageRequest.class, org.a2aproject.sdk.grpc.SendMessageRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.SendMessageRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -482,17 +482,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.SendMessageRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.SendMessageRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.SendMessageRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageRequest build() {
                      -      io.a2a.grpc.SendMessageRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.SendMessageRequest build() {
                      +      org.a2aproject.sdk.grpc.SendMessageRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -500,14 +500,14 @@ public io.a2a.grpc.SendMessageRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageRequest buildPartial() {
                      -      io.a2a.grpc.SendMessageRequest result = new io.a2a.grpc.SendMessageRequest(this);
                      +    public org.a2aproject.sdk.grpc.SendMessageRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.SendMessageRequest result = new org.a2aproject.sdk.grpc.SendMessageRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.SendMessageRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.SendMessageRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -536,16 +536,16 @@ private void buildPartial0(io.a2a.grpc.SendMessageRequest result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.SendMessageRequest) {
                      -        return mergeFrom((io.a2a.grpc.SendMessageRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.SendMessageRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.SendMessageRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.SendMessageRequest other) {
                      -      if (other == io.a2a.grpc.SendMessageRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.SendMessageRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.SendMessageRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -721,9 +721,9 @@ public Builder setTenantBytes(
                             return this;
                           }
                       
                      -    private io.a2a.grpc.Message message_;
                      +    private org.a2aproject.sdk.grpc.Message message_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_;
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> messageBuilder_;
                           /**
                            * 
                            * The message to send to the agent.
                      @@ -743,9 +743,9 @@ public boolean hasMessage() {
                            * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                            * @return The message.
                            */
                      -    public io.a2a.grpc.Message getMessage() {
                      +    public org.a2aproject.sdk.grpc.Message getMessage() {
                             if (messageBuilder_ == null) {
                      -        return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_;
                      +        return message_ == null ? org.a2aproject.sdk.grpc.Message.getDefaultInstance() : message_;
                             } else {
                               return messageBuilder_.getMessage();
                             }
                      @@ -757,7 +757,7 @@ public io.a2a.grpc.Message getMessage() {
                            *
                            * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder setMessage(io.a2a.grpc.Message value) {
                      +    public Builder setMessage(org.a2aproject.sdk.grpc.Message value) {
                             if (messageBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -778,7 +778,7 @@ public Builder setMessage(io.a2a.grpc.Message value) {
                            * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setMessage(
                      -        io.a2a.grpc.Message.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Message.Builder builderForValue) {
                             if (messageBuilder_ == null) {
                               message_ = builderForValue.build();
                             } else {
                      @@ -795,11 +795,11 @@ public Builder setMessage(
                            *
                            * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder mergeMessage(io.a2a.grpc.Message value) {
                      +    public Builder mergeMessage(org.a2aproject.sdk.grpc.Message value) {
                             if (messageBuilder_ == null) {
                               if (((bitField0_ & 0x00000002) != 0) &&
                                 message_ != null &&
                      -          message_ != io.a2a.grpc.Message.getDefaultInstance()) {
                      +          message_ != org.a2aproject.sdk.grpc.Message.getDefaultInstance()) {
                                 getMessageBuilder().mergeFrom(value);
                               } else {
                                 message_ = value;
                      @@ -837,7 +837,7 @@ public Builder clearMessage() {
                            *
                            * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Message.Builder getMessageBuilder() {
                      +    public org.a2aproject.sdk.grpc.Message.Builder getMessageBuilder() {
                             bitField0_ |= 0x00000002;
                             onChanged();
                             return internalGetMessageFieldBuilder().getBuilder();
                      @@ -849,12 +849,12 @@ public io.a2a.grpc.Message.Builder getMessageBuilder() {
                            *
                            * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder() {
                             if (messageBuilder_ != null) {
                               return messageBuilder_.getMessageOrBuilder();
                             } else {
                               return message_ == null ?
                      -            io.a2a.grpc.Message.getDefaultInstance() : message_;
                      +            org.a2aproject.sdk.grpc.Message.getDefaultInstance() : message_;
                             }
                           }
                           /**
                      @@ -865,11 +865,11 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                            * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> 
                               internalGetMessageFieldBuilder() {
                             if (messageBuilder_ == null) {
                               messageBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>(
                      +            org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder>(
                                       getMessage(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -878,9 +878,9 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                             return messageBuilder_;
                           }
                       
                      -    private io.a2a.grpc.SendMessageConfiguration configuration_;
                      +    private org.a2aproject.sdk.grpc.SendMessageConfiguration configuration_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.SendMessageConfiguration, io.a2a.grpc.SendMessageConfiguration.Builder, io.a2a.grpc.SendMessageConfigurationOrBuilder> configurationBuilder_;
                      +        org.a2aproject.sdk.grpc.SendMessageConfiguration, org.a2aproject.sdk.grpc.SendMessageConfiguration.Builder, org.a2aproject.sdk.grpc.SendMessageConfigurationOrBuilder> configurationBuilder_;
                           /**
                            * 
                            * Configuration for the send request.
                      @@ -900,9 +900,9 @@ public boolean hasConfiguration() {
                            * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                            * @return The configuration.
                            */
                      -    public io.a2a.grpc.SendMessageConfiguration getConfiguration() {
                      +    public org.a2aproject.sdk.grpc.SendMessageConfiguration getConfiguration() {
                             if (configurationBuilder_ == null) {
                      -        return configuration_ == null ? io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_;
                      +        return configuration_ == null ? org.a2aproject.sdk.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_;
                             } else {
                               return configurationBuilder_.getMessage();
                             }
                      @@ -914,7 +914,7 @@ public io.a2a.grpc.SendMessageConfiguration getConfiguration() {
                            *
                            * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                            */
                      -    public Builder setConfiguration(io.a2a.grpc.SendMessageConfiguration value) {
                      +    public Builder setConfiguration(org.a2aproject.sdk.grpc.SendMessageConfiguration value) {
                             if (configurationBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -935,7 +935,7 @@ public Builder setConfiguration(io.a2a.grpc.SendMessageConfiguration value) {
                            * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                            */
                           public Builder setConfiguration(
                      -        io.a2a.grpc.SendMessageConfiguration.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.SendMessageConfiguration.Builder builderForValue) {
                             if (configurationBuilder_ == null) {
                               configuration_ = builderForValue.build();
                             } else {
                      @@ -952,11 +952,11 @@ public Builder setConfiguration(
                            *
                            * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                            */
                      -    public Builder mergeConfiguration(io.a2a.grpc.SendMessageConfiguration value) {
                      +    public Builder mergeConfiguration(org.a2aproject.sdk.grpc.SendMessageConfiguration value) {
                             if (configurationBuilder_ == null) {
                               if (((bitField0_ & 0x00000004) != 0) &&
                                 configuration_ != null &&
                      -          configuration_ != io.a2a.grpc.SendMessageConfiguration.getDefaultInstance()) {
                      +          configuration_ != org.a2aproject.sdk.grpc.SendMessageConfiguration.getDefaultInstance()) {
                                 getConfigurationBuilder().mergeFrom(value);
                               } else {
                                 configuration_ = value;
                      @@ -994,7 +994,7 @@ public Builder clearConfiguration() {
                            *
                            * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                            */
                      -    public io.a2a.grpc.SendMessageConfiguration.Builder getConfigurationBuilder() {
                      +    public org.a2aproject.sdk.grpc.SendMessageConfiguration.Builder getConfigurationBuilder() {
                             bitField0_ |= 0x00000004;
                             onChanged();
                             return internalGetConfigurationFieldBuilder().getBuilder();
                      @@ -1006,12 +1006,12 @@ public io.a2a.grpc.SendMessageConfiguration.Builder getConfigurationBuilder() {
                            *
                            * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                            */
                      -    public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() {
                             if (configurationBuilder_ != null) {
                               return configurationBuilder_.getMessageOrBuilder();
                             } else {
                               return configuration_ == null ?
                      -            io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_;
                      +            org.a2aproject.sdk.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_;
                             }
                           }
                           /**
                      @@ -1022,11 +1022,11 @@ public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder()
                            * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.SendMessageConfiguration, io.a2a.grpc.SendMessageConfiguration.Builder, io.a2a.grpc.SendMessageConfigurationOrBuilder> 
                      +        org.a2aproject.sdk.grpc.SendMessageConfiguration, org.a2aproject.sdk.grpc.SendMessageConfiguration.Builder, org.a2aproject.sdk.grpc.SendMessageConfigurationOrBuilder> 
                               internalGetConfigurationFieldBuilder() {
                             if (configurationBuilder_ == null) {
                               configurationBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.SendMessageConfiguration, io.a2a.grpc.SendMessageConfiguration.Builder, io.a2a.grpc.SendMessageConfigurationOrBuilder>(
                      +            org.a2aproject.sdk.grpc.SendMessageConfiguration, org.a2aproject.sdk.grpc.SendMessageConfiguration.Builder, org.a2aproject.sdk.grpc.SendMessageConfigurationOrBuilder>(
                                       getConfiguration(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -1196,12 +1196,12 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.SendMessageRequest)
                      -  private static final io.a2a.grpc.SendMessageRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.SendMessageRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.SendMessageRequest();
                         }
                       
                      -  public static io.a2a.grpc.SendMessageRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.SendMessageRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1237,7 +1237,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.SendMessageRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.SendMessageRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageRequestOrBuilder.java
                      similarity index 89%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageRequestOrBuilder.java
                      index 5adba7a8a..7c111188e 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface SendMessageRequestOrBuilder extends
                      @@ -47,7 +47,7 @@ public interface SendMessageRequestOrBuilder extends
                          * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                          * @return The message.
                          */
                      -  io.a2a.grpc.Message getMessage();
                      +  org.a2aproject.sdk.grpc.Message getMessage();
                         /**
                          * 
                          * The message to send to the agent.
                      @@ -55,7 +55,7 @@ public interface SendMessageRequestOrBuilder extends
                          *
                          * .lf.a2a.v1.Message message = 2 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.MessageOrBuilder getMessageOrBuilder();
                      +  org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder();
                       
                         /**
                          * 
                      @@ -74,7 +74,7 @@ public interface SendMessageRequestOrBuilder extends
                          * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                          * @return The configuration.
                          */
                      -  io.a2a.grpc.SendMessageConfiguration getConfiguration();
                      +  org.a2aproject.sdk.grpc.SendMessageConfiguration getConfiguration();
                         /**
                          * 
                          * Configuration for the send request.
                      @@ -82,7 +82,7 @@ public interface SendMessageRequestOrBuilder extends
                          *
                          * .lf.a2a.v1.SendMessageConfiguration configuration = 3;
                          */
                      -  io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder();
                      +  org.a2aproject.sdk.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder();
                       
                         /**
                          * 
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageResponse.java
                      similarity index 75%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageResponse.java
                      index b848b65e1..640052cc3 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageResponse.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -36,15 +36,15 @@ private SendMessageResponse() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.SendMessageResponse.class, io.a2a.grpc.SendMessageResponse.Builder.class);
                      +            org.a2aproject.sdk.grpc.SendMessageResponse.class, org.a2aproject.sdk.grpc.SendMessageResponse.Builder.class);
                         }
                       
                         private int payloadCase_ = 0;
                      @@ -111,11 +111,11 @@ public boolean hasTask() {
                          * @return The task.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Task getTask() {
                      +  public org.a2aproject.sdk.grpc.Task getTask() {
                           if (payloadCase_ == 1) {
                      -       return (io.a2a.grpc.Task) payload_;
                      +       return (org.a2aproject.sdk.grpc.Task) payload_;
                           }
                      -    return io.a2a.grpc.Task.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -125,11 +125,11 @@ public io.a2a.grpc.Task getTask() {
                          * .lf.a2a.v1.Task task = 1;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.TaskOrBuilder getTaskOrBuilder() {
                           if (payloadCase_ == 1) {
                      -       return (io.a2a.grpc.Task) payload_;
                      +       return (org.a2aproject.sdk.grpc.Task) payload_;
                           }
                      -    return io.a2a.grpc.Task.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                         }
                       
                         public static final int MESSAGE_FIELD_NUMBER = 2;
                      @@ -154,11 +154,11 @@ public boolean hasMessage() {
                          * @return The message.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Message getMessage() {
                      +  public org.a2aproject.sdk.grpc.Message getMessage() {
                           if (payloadCase_ == 2) {
                      -       return (io.a2a.grpc.Message) payload_;
                      +       return (org.a2aproject.sdk.grpc.Message) payload_;
                           }
                      -    return io.a2a.grpc.Message.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -168,11 +168,11 @@ public io.a2a.grpc.Message getMessage() {
                          * .lf.a2a.v1.Message message = 2;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder() {
                           if (payloadCase_ == 2) {
                      -       return (io.a2a.grpc.Message) payload_;
                      +       return (org.a2aproject.sdk.grpc.Message) payload_;
                           }
                      -    return io.a2a.grpc.Message.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                         }
                       
                         private byte memoizedIsInitialized = -1;
                      @@ -190,10 +190,10 @@ public final boolean isInitialized() {
                         public void writeTo(com.google.protobuf.CodedOutputStream output)
                                             throws java.io.IOException {
                           if (payloadCase_ == 1) {
                      -      output.writeMessage(1, (io.a2a.grpc.Task) payload_);
                      +      output.writeMessage(1, (org.a2aproject.sdk.grpc.Task) payload_);
                           }
                           if (payloadCase_ == 2) {
                      -      output.writeMessage(2, (io.a2a.grpc.Message) payload_);
                      +      output.writeMessage(2, (org.a2aproject.sdk.grpc.Message) payload_);
                           }
                           getUnknownFields().writeTo(output);
                         }
                      @@ -206,11 +206,11 @@ public int getSerializedSize() {
                           size = 0;
                           if (payloadCase_ == 1) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(1, (io.a2a.grpc.Task) payload_);
                      +        .computeMessageSize(1, (org.a2aproject.sdk.grpc.Task) payload_);
                           }
                           if (payloadCase_ == 2) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(2, (io.a2a.grpc.Message) payload_);
                      +        .computeMessageSize(2, (org.a2aproject.sdk.grpc.Message) payload_);
                           }
                           size += getUnknownFields().getSerializedSize();
                           memoizedSize = size;
                      @@ -222,10 +222,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.SendMessageResponse)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.SendMessageResponse)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.SendMessageResponse other = (io.a2a.grpc.SendMessageResponse) obj;
                      +    org.a2aproject.sdk.grpc.SendMessageResponse other = (org.a2aproject.sdk.grpc.SendMessageResponse) obj;
                       
                           if (!getPayloadCase().equals(other.getPayloadCase())) return false;
                           switch (payloadCase_) {
                      @@ -268,44 +268,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -313,26 +313,26 @@ public static io.a2a.grpc.SendMessageResponse parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.SendMessageResponse parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.SendMessageResponse parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SendMessageResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -345,7 +345,7 @@ public static io.a2a.grpc.SendMessageResponse parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.SendMessageResponse prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.SendMessageResponse prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -370,21 +370,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SendMessageResponse)
                      -      io.a2a.grpc.SendMessageResponseOrBuilder {
                      +      org.a2aproject.sdk.grpc.SendMessageResponseOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.SendMessageResponse.class, io.a2a.grpc.SendMessageResponse.Builder.class);
                      +              org.a2aproject.sdk.grpc.SendMessageResponse.class, org.a2aproject.sdk.grpc.SendMessageResponse.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.SendMessageResponse.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.SendMessageResponse.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -412,17 +412,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SendMessageResponse_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageResponse getDefaultInstanceForType() {
                      -      return io.a2a.grpc.SendMessageResponse.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.SendMessageResponse getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.SendMessageResponse.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageResponse build() {
                      -      io.a2a.grpc.SendMessageResponse result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.SendMessageResponse build() {
                      +      org.a2aproject.sdk.grpc.SendMessageResponse result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -430,19 +430,19 @@ public io.a2a.grpc.SendMessageResponse build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SendMessageResponse buildPartial() {
                      -      io.a2a.grpc.SendMessageResponse result = new io.a2a.grpc.SendMessageResponse(this);
                      +    public org.a2aproject.sdk.grpc.SendMessageResponse buildPartial() {
                      +      org.a2aproject.sdk.grpc.SendMessageResponse result = new org.a2aproject.sdk.grpc.SendMessageResponse(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             buildPartialOneofs(result);
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.SendMessageResponse result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.SendMessageResponse result) {
                             int from_bitField0_ = bitField0_;
                           }
                       
                      -    private void buildPartialOneofs(io.a2a.grpc.SendMessageResponse result) {
                      +    private void buildPartialOneofs(org.a2aproject.sdk.grpc.SendMessageResponse result) {
                             result.payloadCase_ = payloadCase_;
                             result.payload_ = this.payload_;
                             if (payloadCase_ == 1 &&
                      @@ -457,16 +457,16 @@ private void buildPartialOneofs(io.a2a.grpc.SendMessageResponse result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.SendMessageResponse) {
                      -        return mergeFrom((io.a2a.grpc.SendMessageResponse)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.SendMessageResponse) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.SendMessageResponse)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.SendMessageResponse other) {
                      -      if (other == io.a2a.grpc.SendMessageResponse.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.SendMessageResponse other) {
                      +      if (other == org.a2aproject.sdk.grpc.SendMessageResponse.getDefaultInstance()) return this;
                             switch (other.getPayloadCase()) {
                               case TASK: {
                                 mergeTask(other.getTask());
                      @@ -553,7 +553,7 @@ public Builder clearPayload() {
                           private int bitField0_;
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> taskBuilder_;
                      +        org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder> taskBuilder_;
                           /**
                            * 
                            * The task created or updated by the message.
                      @@ -575,17 +575,17 @@ public boolean hasTask() {
                            * @return The task.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.Task getTask() {
                      +    public org.a2aproject.sdk.grpc.Task getTask() {
                             if (taskBuilder_ == null) {
                               if (payloadCase_ == 1) {
                      -          return (io.a2a.grpc.Task) payload_;
                      +          return (org.a2aproject.sdk.grpc.Task) payload_;
                               }
                      -        return io.a2a.grpc.Task.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                             } else {
                               if (payloadCase_ == 1) {
                                 return taskBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.Task.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -595,7 +595,7 @@ public io.a2a.grpc.Task getTask() {
                            *
                            * .lf.a2a.v1.Task task = 1;
                            */
                      -    public Builder setTask(io.a2a.grpc.Task value) {
                      +    public Builder setTask(org.a2aproject.sdk.grpc.Task value) {
                             if (taskBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -616,7 +616,7 @@ public Builder setTask(io.a2a.grpc.Task value) {
                            * .lf.a2a.v1.Task task = 1;
                            */
                           public Builder setTask(
                      -        io.a2a.grpc.Task.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Task.Builder builderForValue) {
                             if (taskBuilder_ == null) {
                               payload_ = builderForValue.build();
                               onChanged();
                      @@ -633,11 +633,11 @@ public Builder setTask(
                            *
                            * .lf.a2a.v1.Task task = 1;
                            */
                      -    public Builder mergeTask(io.a2a.grpc.Task value) {
                      +    public Builder mergeTask(org.a2aproject.sdk.grpc.Task value) {
                             if (taskBuilder_ == null) {
                               if (payloadCase_ == 1 &&
                      -            payload_ != io.a2a.grpc.Task.getDefaultInstance()) {
                      -          payload_ = io.a2a.grpc.Task.newBuilder((io.a2a.grpc.Task) payload_)
                      +            payload_ != org.a2aproject.sdk.grpc.Task.getDefaultInstance()) {
                      +          payload_ = org.a2aproject.sdk.grpc.Task.newBuilder((org.a2aproject.sdk.grpc.Task) payload_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 payload_ = value;
                      @@ -683,7 +683,7 @@ public Builder clearTask() {
                            *
                            * .lf.a2a.v1.Task task = 1;
                            */
                      -    public io.a2a.grpc.Task.Builder getTaskBuilder() {
                      +    public org.a2aproject.sdk.grpc.Task.Builder getTaskBuilder() {
                             return internalGetTaskFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -694,14 +694,14 @@ public io.a2a.grpc.Task.Builder getTaskBuilder() {
                            * .lf.a2a.v1.Task task = 1;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskOrBuilder getTaskOrBuilder() {
                             if ((payloadCase_ == 1) && (taskBuilder_ != null)) {
                               return taskBuilder_.getMessageOrBuilder();
                             } else {
                               if (payloadCase_ == 1) {
                      -          return (io.a2a.grpc.Task) payload_;
                      +          return (org.a2aproject.sdk.grpc.Task) payload_;
                               }
                      -        return io.a2a.grpc.Task.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -712,15 +712,15 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
                            * .lf.a2a.v1.Task task = 1;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder> 
                               internalGetTaskFieldBuilder() {
                             if (taskBuilder_ == null) {
                               if (!(payloadCase_ == 1)) {
                      -          payload_ = io.a2a.grpc.Task.getDefaultInstance();
                      +          payload_ = org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                               }
                               taskBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder>(
                      -                (io.a2a.grpc.Task) payload_,
                      +            org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.Task) payload_,
                                       getParentForChildren(),
                                       isClean());
                               payload_ = null;
                      @@ -731,7 +731,7 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_;
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> messageBuilder_;
                           /**
                            * 
                            * A message from the agent.
                      @@ -753,17 +753,17 @@ public boolean hasMessage() {
                            * @return The message.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.Message getMessage() {
                      +    public org.a2aproject.sdk.grpc.Message getMessage() {
                             if (messageBuilder_ == null) {
                               if (payloadCase_ == 2) {
                      -          return (io.a2a.grpc.Message) payload_;
                      +          return (org.a2aproject.sdk.grpc.Message) payload_;
                               }
                      -        return io.a2a.grpc.Message.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                             } else {
                               if (payloadCase_ == 2) {
                                 return messageBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.Message.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -773,7 +773,7 @@ public io.a2a.grpc.Message getMessage() {
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public Builder setMessage(io.a2a.grpc.Message value) {
                      +    public Builder setMessage(org.a2aproject.sdk.grpc.Message value) {
                             if (messageBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -794,7 +794,7 @@ public Builder setMessage(io.a2a.grpc.Message value) {
                            * .lf.a2a.v1.Message message = 2;
                            */
                           public Builder setMessage(
                      -        io.a2a.grpc.Message.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Message.Builder builderForValue) {
                             if (messageBuilder_ == null) {
                               payload_ = builderForValue.build();
                               onChanged();
                      @@ -811,11 +811,11 @@ public Builder setMessage(
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public Builder mergeMessage(io.a2a.grpc.Message value) {
                      +    public Builder mergeMessage(org.a2aproject.sdk.grpc.Message value) {
                             if (messageBuilder_ == null) {
                               if (payloadCase_ == 2 &&
                      -            payload_ != io.a2a.grpc.Message.getDefaultInstance()) {
                      -          payload_ = io.a2a.grpc.Message.newBuilder((io.a2a.grpc.Message) payload_)
                      +            payload_ != org.a2aproject.sdk.grpc.Message.getDefaultInstance()) {
                      +          payload_ = org.a2aproject.sdk.grpc.Message.newBuilder((org.a2aproject.sdk.grpc.Message) payload_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 payload_ = value;
                      @@ -861,7 +861,7 @@ public Builder clearMessage() {
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public io.a2a.grpc.Message.Builder getMessageBuilder() {
                      +    public org.a2aproject.sdk.grpc.Message.Builder getMessageBuilder() {
                             return internalGetMessageFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -872,14 +872,14 @@ public io.a2a.grpc.Message.Builder getMessageBuilder() {
                            * .lf.a2a.v1.Message message = 2;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder() {
                             if ((payloadCase_ == 2) && (messageBuilder_ != null)) {
                               return messageBuilder_.getMessageOrBuilder();
                             } else {
                               if (payloadCase_ == 2) {
                      -          return (io.a2a.grpc.Message) payload_;
                      +          return (org.a2aproject.sdk.grpc.Message) payload_;
                               }
                      -        return io.a2a.grpc.Message.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -890,15 +890,15 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                            * .lf.a2a.v1.Message message = 2;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> 
                               internalGetMessageFieldBuilder() {
                             if (messageBuilder_ == null) {
                               if (!(payloadCase_ == 2)) {
                      -          payload_ = io.a2a.grpc.Message.getDefaultInstance();
                      +          payload_ = org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                               }
                               messageBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>(
                      -                (io.a2a.grpc.Message) payload_,
                      +            org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.Message) payload_,
                                       getParentForChildren(),
                                       isClean());
                               payload_ = null;
                      @@ -912,12 +912,12 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.SendMessageResponse)
                      -  private static final io.a2a.grpc.SendMessageResponse DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.SendMessageResponse DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageResponse();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.SendMessageResponse();
                         }
                       
                      -  public static io.a2a.grpc.SendMessageResponse getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.SendMessageResponse getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -953,7 +953,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.SendMessageResponse getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.SendMessageResponse getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageResponseOrBuilder.java
                      similarity index 80%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageResponseOrBuilder.java
                      index 9e56a7c36..658c19386 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SendMessageResponseOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface SendMessageResponseOrBuilder extends
                      @@ -27,7 +27,7 @@ public interface SendMessageResponseOrBuilder extends
                          * .lf.a2a.v1.Task task = 1;
                          * @return The task.
                          */
                      -  io.a2a.grpc.Task getTask();
                      +  org.a2aproject.sdk.grpc.Task getTask();
                         /**
                          * 
                          * The task created or updated by the message.
                      @@ -35,7 +35,7 @@ public interface SendMessageResponseOrBuilder extends
                          *
                          * .lf.a2a.v1.Task task = 1;
                          */
                      -  io.a2a.grpc.TaskOrBuilder getTaskOrBuilder();
                      +  org.a2aproject.sdk.grpc.TaskOrBuilder getTaskOrBuilder();
                       
                         /**
                          * 
                      @@ -54,7 +54,7 @@ public interface SendMessageResponseOrBuilder extends
                          * .lf.a2a.v1.Message message = 2;
                          * @return The message.
                          */
                      -  io.a2a.grpc.Message getMessage();
                      +  org.a2aproject.sdk.grpc.Message getMessage();
                         /**
                          * 
                          * A message from the agent.
                      @@ -62,7 +62,7 @@ public interface SendMessageResponseOrBuilder extends
                          *
                          * .lf.a2a.v1.Message message = 2;
                          */
                      -  io.a2a.grpc.MessageOrBuilder getMessageOrBuilder();
                      +  org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder();
                       
                      -  io.a2a.grpc.SendMessageResponse.PayloadCase getPayloadCase();
                      +  org.a2aproject.sdk.grpc.SendMessageResponse.PayloadCase getPayloadCase();
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StreamResponse.java
                      similarity index 74%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StreamResponse.java
                      index 7ed30be81..b500ee7d6 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StreamResponse.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -36,15 +36,15 @@ private StreamResponse() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.StreamResponse.class, io.a2a.grpc.StreamResponse.Builder.class);
                      +            org.a2aproject.sdk.grpc.StreamResponse.class, org.a2aproject.sdk.grpc.StreamResponse.Builder.class);
                         }
                       
                         private int payloadCase_ = 0;
                      @@ -115,11 +115,11 @@ public boolean hasTask() {
                          * @return The task.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Task getTask() {
                      +  public org.a2aproject.sdk.grpc.Task getTask() {
                           if (payloadCase_ == 1) {
                      -       return (io.a2a.grpc.Task) payload_;
                      +       return (org.a2aproject.sdk.grpc.Task) payload_;
                           }
                      -    return io.a2a.grpc.Task.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -129,11 +129,11 @@ public io.a2a.grpc.Task getTask() {
                          * .lf.a2a.v1.Task task = 1;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.TaskOrBuilder getTaskOrBuilder() {
                           if (payloadCase_ == 1) {
                      -       return (io.a2a.grpc.Task) payload_;
                      +       return (org.a2aproject.sdk.grpc.Task) payload_;
                           }
                      -    return io.a2a.grpc.Task.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                         }
                       
                         public static final int MESSAGE_FIELD_NUMBER = 2;
                      @@ -158,11 +158,11 @@ public boolean hasMessage() {
                          * @return The message.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Message getMessage() {
                      +  public org.a2aproject.sdk.grpc.Message getMessage() {
                           if (payloadCase_ == 2) {
                      -       return (io.a2a.grpc.Message) payload_;
                      +       return (org.a2aproject.sdk.grpc.Message) payload_;
                           }
                      -    return io.a2a.grpc.Message.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -172,11 +172,11 @@ public io.a2a.grpc.Message getMessage() {
                          * .lf.a2a.v1.Message message = 2;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder() {
                           if (payloadCase_ == 2) {
                      -       return (io.a2a.grpc.Message) payload_;
                      +       return (org.a2aproject.sdk.grpc.Message) payload_;
                           }
                      -    return io.a2a.grpc.Message.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                         }
                       
                         public static final int STATUS_UPDATE_FIELD_NUMBER = 3;
                      @@ -201,11 +201,11 @@ public boolean hasStatusUpdate() {
                          * @return The statusUpdate.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate() {
                      +  public org.a2aproject.sdk.grpc.TaskStatusUpdateEvent getStatusUpdate() {
                           if (payloadCase_ == 3) {
                      -       return (io.a2a.grpc.TaskStatusUpdateEvent) payload_;
                      +       return (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) payload_;
                           }
                      -    return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -215,11 +215,11 @@ public io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate() {
                          * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() {
                           if (payloadCase_ == 3) {
                      -       return (io.a2a.grpc.TaskStatusUpdateEvent) payload_;
                      +       return (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) payload_;
                           }
                      -    return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                         }
                       
                         public static final int ARTIFACT_UPDATE_FIELD_NUMBER = 4;
                      @@ -244,11 +244,11 @@ public boolean hasArtifactUpdate() {
                          * @return The artifactUpdate.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate() {
                      +  public org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent getArtifactUpdate() {
                           if (payloadCase_ == 4) {
                      -       return (io.a2a.grpc.TaskArtifactUpdateEvent) payload_;
                      +       return (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) payload_;
                           }
                      -    return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                         }
                         /**
                          * 
                      @@ -258,11 +258,11 @@ public io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate() {
                          * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() {
                      +  public org.a2aproject.sdk.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() {
                           if (payloadCase_ == 4) {
                      -       return (io.a2a.grpc.TaskArtifactUpdateEvent) payload_;
                      +       return (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) payload_;
                           }
                      -    return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                      +    return org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                         }
                       
                         private byte memoizedIsInitialized = -1;
                      @@ -280,16 +280,16 @@ public final boolean isInitialized() {
                         public void writeTo(com.google.protobuf.CodedOutputStream output)
                                             throws java.io.IOException {
                           if (payloadCase_ == 1) {
                      -      output.writeMessage(1, (io.a2a.grpc.Task) payload_);
                      +      output.writeMessage(1, (org.a2aproject.sdk.grpc.Task) payload_);
                           }
                           if (payloadCase_ == 2) {
                      -      output.writeMessage(2, (io.a2a.grpc.Message) payload_);
                      +      output.writeMessage(2, (org.a2aproject.sdk.grpc.Message) payload_);
                           }
                           if (payloadCase_ == 3) {
                      -      output.writeMessage(3, (io.a2a.grpc.TaskStatusUpdateEvent) payload_);
                      +      output.writeMessage(3, (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) payload_);
                           }
                           if (payloadCase_ == 4) {
                      -      output.writeMessage(4, (io.a2a.grpc.TaskArtifactUpdateEvent) payload_);
                      +      output.writeMessage(4, (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) payload_);
                           }
                           getUnknownFields().writeTo(output);
                         }
                      @@ -302,19 +302,19 @@ public int getSerializedSize() {
                           size = 0;
                           if (payloadCase_ == 1) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(1, (io.a2a.grpc.Task) payload_);
                      +        .computeMessageSize(1, (org.a2aproject.sdk.grpc.Task) payload_);
                           }
                           if (payloadCase_ == 2) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(2, (io.a2a.grpc.Message) payload_);
                      +        .computeMessageSize(2, (org.a2aproject.sdk.grpc.Message) payload_);
                           }
                           if (payloadCase_ == 3) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(3, (io.a2a.grpc.TaskStatusUpdateEvent) payload_);
                      +        .computeMessageSize(3, (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) payload_);
                           }
                           if (payloadCase_ == 4) {
                             size += com.google.protobuf.CodedOutputStream
                      -        .computeMessageSize(4, (io.a2a.grpc.TaskArtifactUpdateEvent) payload_);
                      +        .computeMessageSize(4, (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) payload_);
                           }
                           size += getUnknownFields().getSerializedSize();
                           memoizedSize = size;
                      @@ -326,10 +326,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.StreamResponse)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.StreamResponse)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.StreamResponse other = (io.a2a.grpc.StreamResponse) obj;
                      +    org.a2aproject.sdk.grpc.StreamResponse other = (org.a2aproject.sdk.grpc.StreamResponse) obj;
                       
                           if (!getPayloadCase().equals(other.getPayloadCase())) return false;
                           switch (payloadCase_) {
                      @@ -388,44 +388,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.StreamResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -433,26 +433,26 @@ public static io.a2a.grpc.StreamResponse parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.StreamResponse parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.StreamResponse parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.StreamResponse parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StreamResponse parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -465,7 +465,7 @@ public static io.a2a.grpc.StreamResponse parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.StreamResponse prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.StreamResponse prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -490,21 +490,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.StreamResponse)
                      -      io.a2a.grpc.StreamResponseOrBuilder {
                      +      org.a2aproject.sdk.grpc.StreamResponseOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.StreamResponse.class, io.a2a.grpc.StreamResponse.Builder.class);
                      +              org.a2aproject.sdk.grpc.StreamResponse.class, org.a2aproject.sdk.grpc.StreamResponse.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.StreamResponse.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.StreamResponse.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -538,17 +538,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StreamResponse_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.StreamResponse getDefaultInstanceForType() {
                      -      return io.a2a.grpc.StreamResponse.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.StreamResponse getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.StreamResponse.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.StreamResponse build() {
                      -      io.a2a.grpc.StreamResponse result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.StreamResponse build() {
                      +      org.a2aproject.sdk.grpc.StreamResponse result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -556,19 +556,19 @@ public io.a2a.grpc.StreamResponse build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.StreamResponse buildPartial() {
                      -      io.a2a.grpc.StreamResponse result = new io.a2a.grpc.StreamResponse(this);
                      +    public org.a2aproject.sdk.grpc.StreamResponse buildPartial() {
                      +      org.a2aproject.sdk.grpc.StreamResponse result = new org.a2aproject.sdk.grpc.StreamResponse(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             buildPartialOneofs(result);
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.StreamResponse result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.StreamResponse result) {
                             int from_bitField0_ = bitField0_;
                           }
                       
                      -    private void buildPartialOneofs(io.a2a.grpc.StreamResponse result) {
                      +    private void buildPartialOneofs(org.a2aproject.sdk.grpc.StreamResponse result) {
                             result.payloadCase_ = payloadCase_;
                             result.payload_ = this.payload_;
                             if (payloadCase_ == 1 &&
                      @@ -591,16 +591,16 @@ private void buildPartialOneofs(io.a2a.grpc.StreamResponse result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.StreamResponse) {
                      -        return mergeFrom((io.a2a.grpc.StreamResponse)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.StreamResponse) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.StreamResponse)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.StreamResponse other) {
                      -      if (other == io.a2a.grpc.StreamResponse.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.StreamResponse other) {
                      +      if (other == org.a2aproject.sdk.grpc.StreamResponse.getDefaultInstance()) return this;
                             switch (other.getPayloadCase()) {
                               case TASK: {
                                 mergeTask(other.getTask());
                      @@ -709,7 +709,7 @@ public Builder clearPayload() {
                           private int bitField0_;
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> taskBuilder_;
                      +        org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder> taskBuilder_;
                           /**
                            * 
                            * A Task object containing the current state of the task.
                      @@ -731,17 +731,17 @@ public boolean hasTask() {
                            * @return The task.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.Task getTask() {
                      +    public org.a2aproject.sdk.grpc.Task getTask() {
                             if (taskBuilder_ == null) {
                               if (payloadCase_ == 1) {
                      -          return (io.a2a.grpc.Task) payload_;
                      +          return (org.a2aproject.sdk.grpc.Task) payload_;
                               }
                      -        return io.a2a.grpc.Task.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                             } else {
                               if (payloadCase_ == 1) {
                                 return taskBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.Task.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -751,7 +751,7 @@ public io.a2a.grpc.Task getTask() {
                            *
                            * .lf.a2a.v1.Task task = 1;
                            */
                      -    public Builder setTask(io.a2a.grpc.Task value) {
                      +    public Builder setTask(org.a2aproject.sdk.grpc.Task value) {
                             if (taskBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -772,7 +772,7 @@ public Builder setTask(io.a2a.grpc.Task value) {
                            * .lf.a2a.v1.Task task = 1;
                            */
                           public Builder setTask(
                      -        io.a2a.grpc.Task.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Task.Builder builderForValue) {
                             if (taskBuilder_ == null) {
                               payload_ = builderForValue.build();
                               onChanged();
                      @@ -789,11 +789,11 @@ public Builder setTask(
                            *
                            * .lf.a2a.v1.Task task = 1;
                            */
                      -    public Builder mergeTask(io.a2a.grpc.Task value) {
                      +    public Builder mergeTask(org.a2aproject.sdk.grpc.Task value) {
                             if (taskBuilder_ == null) {
                               if (payloadCase_ == 1 &&
                      -            payload_ != io.a2a.grpc.Task.getDefaultInstance()) {
                      -          payload_ = io.a2a.grpc.Task.newBuilder((io.a2a.grpc.Task) payload_)
                      +            payload_ != org.a2aproject.sdk.grpc.Task.getDefaultInstance()) {
                      +          payload_ = org.a2aproject.sdk.grpc.Task.newBuilder((org.a2aproject.sdk.grpc.Task) payload_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 payload_ = value;
                      @@ -839,7 +839,7 @@ public Builder clearTask() {
                            *
                            * .lf.a2a.v1.Task task = 1;
                            */
                      -    public io.a2a.grpc.Task.Builder getTaskBuilder() {
                      +    public org.a2aproject.sdk.grpc.Task.Builder getTaskBuilder() {
                             return internalGetTaskFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -850,14 +850,14 @@ public io.a2a.grpc.Task.Builder getTaskBuilder() {
                            * .lf.a2a.v1.Task task = 1;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskOrBuilder getTaskOrBuilder() {
                             if ((payloadCase_ == 1) && (taskBuilder_ != null)) {
                               return taskBuilder_.getMessageOrBuilder();
                             } else {
                               if (payloadCase_ == 1) {
                      -          return (io.a2a.grpc.Task) payload_;
                      +          return (org.a2aproject.sdk.grpc.Task) payload_;
                               }
                      -        return io.a2a.grpc.Task.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -868,15 +868,15 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
                            * .lf.a2a.v1.Task task = 1;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder> 
                               internalGetTaskFieldBuilder() {
                             if (taskBuilder_ == null) {
                               if (!(payloadCase_ == 1)) {
                      -          payload_ = io.a2a.grpc.Task.getDefaultInstance();
                      +          payload_ = org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                               }
                               taskBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder>(
                      -                (io.a2a.grpc.Task) payload_,
                      +            org.a2aproject.sdk.grpc.Task, org.a2aproject.sdk.grpc.Task.Builder, org.a2aproject.sdk.grpc.TaskOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.Task) payload_,
                                       getParentForChildren(),
                                       isClean());
                               payload_ = null;
                      @@ -887,7 +887,7 @@ public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() {
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_;
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> messageBuilder_;
                           /**
                            * 
                            * A Message object containing a message from the agent.
                      @@ -909,17 +909,17 @@ public boolean hasMessage() {
                            * @return The message.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.Message getMessage() {
                      +    public org.a2aproject.sdk.grpc.Message getMessage() {
                             if (messageBuilder_ == null) {
                               if (payloadCase_ == 2) {
                      -          return (io.a2a.grpc.Message) payload_;
                      +          return (org.a2aproject.sdk.grpc.Message) payload_;
                               }
                      -        return io.a2a.grpc.Message.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                             } else {
                               if (payloadCase_ == 2) {
                                 return messageBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.Message.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -929,7 +929,7 @@ public io.a2a.grpc.Message getMessage() {
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public Builder setMessage(io.a2a.grpc.Message value) {
                      +    public Builder setMessage(org.a2aproject.sdk.grpc.Message value) {
                             if (messageBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -950,7 +950,7 @@ public Builder setMessage(io.a2a.grpc.Message value) {
                            * .lf.a2a.v1.Message message = 2;
                            */
                           public Builder setMessage(
                      -        io.a2a.grpc.Message.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Message.Builder builderForValue) {
                             if (messageBuilder_ == null) {
                               payload_ = builderForValue.build();
                               onChanged();
                      @@ -967,11 +967,11 @@ public Builder setMessage(
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public Builder mergeMessage(io.a2a.grpc.Message value) {
                      +    public Builder mergeMessage(org.a2aproject.sdk.grpc.Message value) {
                             if (messageBuilder_ == null) {
                               if (payloadCase_ == 2 &&
                      -            payload_ != io.a2a.grpc.Message.getDefaultInstance()) {
                      -          payload_ = io.a2a.grpc.Message.newBuilder((io.a2a.grpc.Message) payload_)
                      +            payload_ != org.a2aproject.sdk.grpc.Message.getDefaultInstance()) {
                      +          payload_ = org.a2aproject.sdk.grpc.Message.newBuilder((org.a2aproject.sdk.grpc.Message) payload_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 payload_ = value;
                      @@ -1017,7 +1017,7 @@ public Builder clearMessage() {
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public io.a2a.grpc.Message.Builder getMessageBuilder() {
                      +    public org.a2aproject.sdk.grpc.Message.Builder getMessageBuilder() {
                             return internalGetMessageFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1028,14 +1028,14 @@ public io.a2a.grpc.Message.Builder getMessageBuilder() {
                            * .lf.a2a.v1.Message message = 2;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder() {
                             if ((payloadCase_ == 2) && (messageBuilder_ != null)) {
                               return messageBuilder_.getMessageOrBuilder();
                             } else {
                               if (payloadCase_ == 2) {
                      -          return (io.a2a.grpc.Message) payload_;
                      +          return (org.a2aproject.sdk.grpc.Message) payload_;
                               }
                      -        return io.a2a.grpc.Message.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1046,15 +1046,15 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                            * .lf.a2a.v1.Message message = 2;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> 
                               internalGetMessageFieldBuilder() {
                             if (messageBuilder_ == null) {
                               if (!(payloadCase_ == 2)) {
                      -          payload_ = io.a2a.grpc.Message.getDefaultInstance();
                      +          payload_ = org.a2aproject.sdk.grpc.Message.getDefaultInstance();
                               }
                               messageBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>(
                      -                (io.a2a.grpc.Message) payload_,
                      +            org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.Message) payload_,
                                       getParentForChildren(),
                                       isClean());
                               payload_ = null;
                      @@ -1065,7 +1065,7 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskStatusUpdateEvent, io.a2a.grpc.TaskStatusUpdateEvent.Builder, io.a2a.grpc.TaskStatusUpdateEventOrBuilder> statusUpdateBuilder_;
                      +        org.a2aproject.sdk.grpc.TaskStatusUpdateEvent, org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.Builder, org.a2aproject.sdk.grpc.TaskStatusUpdateEventOrBuilder> statusUpdateBuilder_;
                           /**
                            * 
                            * An event indicating a task status update.
                      @@ -1087,17 +1087,17 @@ public boolean hasStatusUpdate() {
                            * @return The statusUpdate.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate() {
                      +    public org.a2aproject.sdk.grpc.TaskStatusUpdateEvent getStatusUpdate() {
                             if (statusUpdateBuilder_ == null) {
                               if (payloadCase_ == 3) {
                      -          return (io.a2a.grpc.TaskStatusUpdateEvent) payload_;
                      +          return (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) payload_;
                               }
                      -        return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                             } else {
                               if (payloadCase_ == 3) {
                                 return statusUpdateBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1107,7 +1107,7 @@ public io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate() {
                            *
                            * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                            */
                      -    public Builder setStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) {
                      +    public Builder setStatusUpdate(org.a2aproject.sdk.grpc.TaskStatusUpdateEvent value) {
                             if (statusUpdateBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1128,7 +1128,7 @@ public Builder setStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) {
                            * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                            */
                           public Builder setStatusUpdate(
                      -        io.a2a.grpc.TaskStatusUpdateEvent.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.Builder builderForValue) {
                             if (statusUpdateBuilder_ == null) {
                               payload_ = builderForValue.build();
                               onChanged();
                      @@ -1145,11 +1145,11 @@ public Builder setStatusUpdate(
                            *
                            * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                            */
                      -    public Builder mergeStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) {
                      +    public Builder mergeStatusUpdate(org.a2aproject.sdk.grpc.TaskStatusUpdateEvent value) {
                             if (statusUpdateBuilder_ == null) {
                               if (payloadCase_ == 3 &&
                      -            payload_ != io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance()) {
                      -          payload_ = io.a2a.grpc.TaskStatusUpdateEvent.newBuilder((io.a2a.grpc.TaskStatusUpdateEvent) payload_)
                      +            payload_ != org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance()) {
                      +          payload_ = org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.newBuilder((org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) payload_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 payload_ = value;
                      @@ -1195,7 +1195,7 @@ public Builder clearStatusUpdate() {
                            *
                            * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                            */
                      -    public io.a2a.grpc.TaskStatusUpdateEvent.Builder getStatusUpdateBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.Builder getStatusUpdateBuilder() {
                             return internalGetStatusUpdateFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1206,14 +1206,14 @@ public io.a2a.grpc.TaskStatusUpdateEvent.Builder getStatusUpdateBuilder() {
                            * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() {
                             if ((payloadCase_ == 3) && (statusUpdateBuilder_ != null)) {
                               return statusUpdateBuilder_.getMessageOrBuilder();
                             } else {
                               if (payloadCase_ == 3) {
                      -          return (io.a2a.grpc.TaskStatusUpdateEvent) payload_;
                      +          return (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) payload_;
                               }
                      -        return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1224,15 +1224,15 @@ public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() {
                            * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskStatusUpdateEvent, io.a2a.grpc.TaskStatusUpdateEvent.Builder, io.a2a.grpc.TaskStatusUpdateEventOrBuilder> 
                      +        org.a2aproject.sdk.grpc.TaskStatusUpdateEvent, org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.Builder, org.a2aproject.sdk.grpc.TaskStatusUpdateEventOrBuilder> 
                               internalGetStatusUpdateFieldBuilder() {
                             if (statusUpdateBuilder_ == null) {
                               if (!(payloadCase_ == 3)) {
                      -          payload_ = io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                      +          payload_ = org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                               }
                               statusUpdateBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.TaskStatusUpdateEvent, io.a2a.grpc.TaskStatusUpdateEvent.Builder, io.a2a.grpc.TaskStatusUpdateEventOrBuilder>(
                      -                (io.a2a.grpc.TaskStatusUpdateEvent) payload_,
                      +            org.a2aproject.sdk.grpc.TaskStatusUpdateEvent, org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.Builder, org.a2aproject.sdk.grpc.TaskStatusUpdateEventOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) payload_,
                                       getParentForChildren(),
                                       isClean());
                               payload_ = null;
                      @@ -1243,7 +1243,7 @@ public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() {
                           }
                       
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskArtifactUpdateEvent, io.a2a.grpc.TaskArtifactUpdateEvent.Builder, io.a2a.grpc.TaskArtifactUpdateEventOrBuilder> artifactUpdateBuilder_;
                      +        org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent, org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.Builder, org.a2aproject.sdk.grpc.TaskArtifactUpdateEventOrBuilder> artifactUpdateBuilder_;
                           /**
                            * 
                            * An event indicating a task artifact update.
                      @@ -1265,17 +1265,17 @@ public boolean hasArtifactUpdate() {
                            * @return The artifactUpdate.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate() {
                      +    public org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent getArtifactUpdate() {
                             if (artifactUpdateBuilder_ == null) {
                               if (payloadCase_ == 4) {
                      -          return (io.a2a.grpc.TaskArtifactUpdateEvent) payload_;
                      +          return (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) payload_;
                               }
                      -        return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                             } else {
                               if (payloadCase_ == 4) {
                                 return artifactUpdateBuilder_.getMessage();
                               }
                      -        return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1285,7 +1285,7 @@ public io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate() {
                            *
                            * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                            */
                      -    public Builder setArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) {
                      +    public Builder setArtifactUpdate(org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent value) {
                             if (artifactUpdateBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1306,7 +1306,7 @@ public Builder setArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) {
                            * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                            */
                           public Builder setArtifactUpdate(
                      -        io.a2a.grpc.TaskArtifactUpdateEvent.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.Builder builderForValue) {
                             if (artifactUpdateBuilder_ == null) {
                               payload_ = builderForValue.build();
                               onChanged();
                      @@ -1323,11 +1323,11 @@ public Builder setArtifactUpdate(
                            *
                            * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                            */
                      -    public Builder mergeArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) {
                      +    public Builder mergeArtifactUpdate(org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent value) {
                             if (artifactUpdateBuilder_ == null) {
                               if (payloadCase_ == 4 &&
                      -            payload_ != io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance()) {
                      -          payload_ = io.a2a.grpc.TaskArtifactUpdateEvent.newBuilder((io.a2a.grpc.TaskArtifactUpdateEvent) payload_)
                      +            payload_ != org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance()) {
                      +          payload_ = org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.newBuilder((org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) payload_)
                                     .mergeFrom(value).buildPartial();
                               } else {
                                 payload_ = value;
                      @@ -1373,7 +1373,7 @@ public Builder clearArtifactUpdate() {
                            *
                            * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                            */
                      -    public io.a2a.grpc.TaskArtifactUpdateEvent.Builder getArtifactUpdateBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.Builder getArtifactUpdateBuilder() {
                             return internalGetArtifactUpdateFieldBuilder().getBuilder();
                           }
                           /**
                      @@ -1384,14 +1384,14 @@ public io.a2a.grpc.TaskArtifactUpdateEvent.Builder getArtifactUpdateBuilder() {
                            * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() {
                             if ((payloadCase_ == 4) && (artifactUpdateBuilder_ != null)) {
                               return artifactUpdateBuilder_.getMessageOrBuilder();
                             } else {
                               if (payloadCase_ == 4) {
                      -          return (io.a2a.grpc.TaskArtifactUpdateEvent) payload_;
                      +          return (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) payload_;
                               }
                      -        return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                      +        return org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                             }
                           }
                           /**
                      @@ -1402,15 +1402,15 @@ public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder()
                            * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskArtifactUpdateEvent, io.a2a.grpc.TaskArtifactUpdateEvent.Builder, io.a2a.grpc.TaskArtifactUpdateEventOrBuilder> 
                      +        org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent, org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.Builder, org.a2aproject.sdk.grpc.TaskArtifactUpdateEventOrBuilder> 
                               internalGetArtifactUpdateFieldBuilder() {
                             if (artifactUpdateBuilder_ == null) {
                               if (!(payloadCase_ == 4)) {
                      -          payload_ = io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                      +          payload_ = org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                               }
                               artifactUpdateBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.TaskArtifactUpdateEvent, io.a2a.grpc.TaskArtifactUpdateEvent.Builder, io.a2a.grpc.TaskArtifactUpdateEventOrBuilder>(
                      -                (io.a2a.grpc.TaskArtifactUpdateEvent) payload_,
                      +            org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent, org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.Builder, org.a2aproject.sdk.grpc.TaskArtifactUpdateEventOrBuilder>(
                      +                (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) payload_,
                                       getParentForChildren(),
                                       isClean());
                               payload_ = null;
                      @@ -1424,12 +1424,12 @@ public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder()
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.StreamResponse)
                      -  private static final io.a2a.grpc.StreamResponse DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.StreamResponse DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.StreamResponse();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.StreamResponse();
                         }
                       
                      -  public static io.a2a.grpc.StreamResponse getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.StreamResponse getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1465,7 +1465,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.StreamResponse getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.StreamResponse getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StreamResponseOrBuilder.java
                      similarity index 80%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StreamResponseOrBuilder.java
                      index 228e5fa0f..ea577ed02 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StreamResponseOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface StreamResponseOrBuilder extends
                      @@ -27,7 +27,7 @@ public interface StreamResponseOrBuilder extends
                          * .lf.a2a.v1.Task task = 1;
                          * @return The task.
                          */
                      -  io.a2a.grpc.Task getTask();
                      +  org.a2aproject.sdk.grpc.Task getTask();
                         /**
                          * 
                          * A Task object containing the current state of the task.
                      @@ -35,7 +35,7 @@ public interface StreamResponseOrBuilder extends
                          *
                          * .lf.a2a.v1.Task task = 1;
                          */
                      -  io.a2a.grpc.TaskOrBuilder getTaskOrBuilder();
                      +  org.a2aproject.sdk.grpc.TaskOrBuilder getTaskOrBuilder();
                       
                         /**
                          * 
                      @@ -54,7 +54,7 @@ public interface StreamResponseOrBuilder extends
                          * .lf.a2a.v1.Message message = 2;
                          * @return The message.
                          */
                      -  io.a2a.grpc.Message getMessage();
                      +  org.a2aproject.sdk.grpc.Message getMessage();
                         /**
                          * 
                          * A Message object containing a message from the agent.
                      @@ -62,7 +62,7 @@ public interface StreamResponseOrBuilder extends
                          *
                          * .lf.a2a.v1.Message message = 2;
                          */
                      -  io.a2a.grpc.MessageOrBuilder getMessageOrBuilder();
                      +  org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder();
                       
                         /**
                          * 
                      @@ -81,7 +81,7 @@ public interface StreamResponseOrBuilder extends
                          * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                          * @return The statusUpdate.
                          */
                      -  io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate();
                      +  org.a2aproject.sdk.grpc.TaskStatusUpdateEvent getStatusUpdate();
                         /**
                          * 
                          * An event indicating a task status update.
                      @@ -89,7 +89,7 @@ public interface StreamResponseOrBuilder extends
                          *
                          * .lf.a2a.v1.TaskStatusUpdateEvent status_update = 3;
                          */
                      -  io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder();
                      +  org.a2aproject.sdk.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder();
                       
                         /**
                          * 
                      @@ -108,7 +108,7 @@ public interface StreamResponseOrBuilder extends
                          * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                          * @return The artifactUpdate.
                          */
                      -  io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate();
                      +  org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent getArtifactUpdate();
                         /**
                          * 
                          * An event indicating a task artifact update.
                      @@ -116,7 +116,7 @@ public interface StreamResponseOrBuilder extends
                          *
                          * .lf.a2a.v1.TaskArtifactUpdateEvent artifact_update = 4;
                          */
                      -  io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder();
                      +  org.a2aproject.sdk.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder();
                       
                      -  io.a2a.grpc.StreamResponse.PayloadCase getPayloadCase();
                      +  org.a2aproject.sdk.grpc.StreamResponse.PayloadCase getPayloadCase();
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StringList.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StringList.java
                      similarity index 84%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/StringList.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StringList.java
                      index 258bd0cba..fd93c8ab2 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/StringList.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StringList.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -39,15 +39,15 @@ private StringList() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StringList_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.StringList.class, io.a2a.grpc.StringList.Builder.class);
                      +            org.a2aproject.sdk.grpc.StringList.class, org.a2aproject.sdk.grpc.StringList.Builder.class);
                         }
                       
                         public static final int LIST_FIELD_NUMBER = 1;
                      @@ -147,10 +147,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.StringList)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.StringList)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.StringList other = (io.a2a.grpc.StringList) obj;
                      +    org.a2aproject.sdk.grpc.StringList other = (org.a2aproject.sdk.grpc.StringList) obj;
                       
                           if (!getListList()
                               .equals(other.getListList())) return false;
                      @@ -174,44 +174,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.StringList parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -219,26 +219,26 @@ public static io.a2a.grpc.StringList parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.StringList parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.StringList parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.StringList parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.StringList parseFrom(
                      +  public static org.a2aproject.sdk.grpc.StringList parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -251,7 +251,7 @@ public static io.a2a.grpc.StringList parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.StringList prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.StringList prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -277,21 +277,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.StringList)
                      -      io.a2a.grpc.StringListOrBuilder {
                      +      org.a2aproject.sdk.grpc.StringListOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StringList_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.StringList.class, io.a2a.grpc.StringList.Builder.class);
                      +              org.a2aproject.sdk.grpc.StringList.class, org.a2aproject.sdk.grpc.StringList.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.StringList.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.StringList.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -313,17 +313,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_StringList_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.StringList getDefaultInstanceForType() {
                      -      return io.a2a.grpc.StringList.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.StringList getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.StringList.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.StringList build() {
                      -      io.a2a.grpc.StringList result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.StringList build() {
                      +      org.a2aproject.sdk.grpc.StringList result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -331,14 +331,14 @@ public io.a2a.grpc.StringList build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.StringList buildPartial() {
                      -      io.a2a.grpc.StringList result = new io.a2a.grpc.StringList(this);
                      +    public org.a2aproject.sdk.grpc.StringList buildPartial() {
                      +      org.a2aproject.sdk.grpc.StringList result = new org.a2aproject.sdk.grpc.StringList(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.StringList result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.StringList result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               list_.makeImmutable();
                      @@ -348,16 +348,16 @@ private void buildPartial0(io.a2a.grpc.StringList result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.StringList) {
                      -        return mergeFrom((io.a2a.grpc.StringList)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.StringList) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.StringList)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.StringList other) {
                      -      if (other == io.a2a.grpc.StringList.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.StringList other) {
                      +      if (other == org.a2aproject.sdk.grpc.StringList.getDefaultInstance()) return this;
                             if (!other.list_.isEmpty()) {
                               if (list_.isEmpty()) {
                                 list_ = other.list_;
                      @@ -568,12 +568,12 @@ public Builder addListBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.StringList)
                      -  private static final io.a2a.grpc.StringList DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.StringList DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.StringList();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.StringList();
                         }
                       
                      -  public static io.a2a.grpc.StringList getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.StringList getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -609,7 +609,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.StringList getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.StringList getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StringListOrBuilder.java
                      similarity index 97%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StringListOrBuilder.java
                      index a6b31a667..a6eca1a32 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/StringListOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface StringListOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SubscribeToTaskRequest.java
                      similarity index 84%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SubscribeToTaskRequest.java
                      index a3f0eceb7..5a2f3f6c0 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SubscribeToTaskRequest.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private SubscribeToTaskRequest() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.SubscribeToTaskRequest.class, io.a2a.grpc.SubscribeToTaskRequest.Builder.class);
                      +            org.a2aproject.sdk.grpc.SubscribeToTaskRequest.class, org.a2aproject.sdk.grpc.SubscribeToTaskRequest.Builder.class);
                         }
                       
                         public static final int TENANT_FIELD_NUMBER = 1;
                      @@ -188,10 +188,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.SubscribeToTaskRequest)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.SubscribeToTaskRequest)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.SubscribeToTaskRequest other = (io.a2a.grpc.SubscribeToTaskRequest) obj;
                      +    org.a2aproject.sdk.grpc.SubscribeToTaskRequest other = (org.a2aproject.sdk.grpc.SubscribeToTaskRequest) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -217,44 +217,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -262,26 +262,26 @@ public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -294,7 +294,7 @@ public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.SubscribeToTaskRequest prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.SubscribeToTaskRequest prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -319,21 +319,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.SubscribeToTaskRequest)
                      -      io.a2a.grpc.SubscribeToTaskRequestOrBuilder {
                      +      org.a2aproject.sdk.grpc.SubscribeToTaskRequestOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.SubscribeToTaskRequest.class, io.a2a.grpc.SubscribeToTaskRequest.Builder.class);
                      +              org.a2aproject.sdk.grpc.SubscribeToTaskRequest.class, org.a2aproject.sdk.grpc.SubscribeToTaskRequest.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.SubscribeToTaskRequest.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.SubscribeToTaskRequest.newBuilder()
                           private Builder() {
                       
                           }
                      @@ -355,17 +355,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_SubscribeToTaskRequest_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SubscribeToTaskRequest getDefaultInstanceForType() {
                      -      return io.a2a.grpc.SubscribeToTaskRequest.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.SubscribeToTaskRequest getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.SubscribeToTaskRequest.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SubscribeToTaskRequest build() {
                      -      io.a2a.grpc.SubscribeToTaskRequest result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.SubscribeToTaskRequest build() {
                      +      org.a2aproject.sdk.grpc.SubscribeToTaskRequest result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -373,14 +373,14 @@ public io.a2a.grpc.SubscribeToTaskRequest build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.SubscribeToTaskRequest buildPartial() {
                      -      io.a2a.grpc.SubscribeToTaskRequest result = new io.a2a.grpc.SubscribeToTaskRequest(this);
                      +    public org.a2aproject.sdk.grpc.SubscribeToTaskRequest buildPartial() {
                      +      org.a2aproject.sdk.grpc.SubscribeToTaskRequest result = new org.a2aproject.sdk.grpc.SubscribeToTaskRequest(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.SubscribeToTaskRequest result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.SubscribeToTaskRequest result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -392,16 +392,16 @@ private void buildPartial0(io.a2a.grpc.SubscribeToTaskRequest result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.SubscribeToTaskRequest) {
                      -        return mergeFrom((io.a2a.grpc.SubscribeToTaskRequest)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.SubscribeToTaskRequest) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.SubscribeToTaskRequest)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.SubscribeToTaskRequest other) {
                      -      if (other == io.a2a.grpc.SubscribeToTaskRequest.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.SubscribeToTaskRequest other) {
                      +      if (other == org.a2aproject.sdk.grpc.SubscribeToTaskRequest.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -653,12 +653,12 @@ public Builder setIdBytes(
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.SubscribeToTaskRequest)
                      -  private static final io.a2a.grpc.SubscribeToTaskRequest DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.SubscribeToTaskRequest DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.SubscribeToTaskRequest();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.SubscribeToTaskRequest();
                         }
                       
                      -  public static io.a2a.grpc.SubscribeToTaskRequest getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -694,7 +694,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.SubscribeToTaskRequest getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.SubscribeToTaskRequest getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SubscribeToTaskRequestOrBuilder.java
                      similarity index 97%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SubscribeToTaskRequestOrBuilder.java
                      index fccd932ad..f3ff99a05 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/SubscribeToTaskRequestOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface SubscribeToTaskRequestOrBuilder extends
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Task.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Task.java
                      similarity index 86%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/Task.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Task.java
                      index 7b0d12ca4..fe433c755 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/Task.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/Task.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -43,15 +43,15 @@ private Task() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Task_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.Task.class, io.a2a.grpc.Task.Builder.class);
                      +            org.a2aproject.sdk.grpc.Task.class, org.a2aproject.sdk.grpc.Task.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -154,7 +154,7 @@ public java.lang.String getContextId() {
                         }
                       
                         public static final int STATUS_FIELD_NUMBER = 3;
                      -  private io.a2a.grpc.TaskStatus status_;
                      +  private org.a2aproject.sdk.grpc.TaskStatus status_;
                         /**
                          * 
                          * The current status of a `Task`, including `state` and a `message`.
                      @@ -176,8 +176,8 @@ public boolean hasStatus() {
                          * @return The status.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskStatus getStatus() {
                      -    return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_;
                      +  public org.a2aproject.sdk.grpc.TaskStatus getStatus() {
                      +    return status_ == null ? org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance() : status_;
                         }
                         /**
                          * 
                      @@ -187,13 +187,13 @@ public io.a2a.grpc.TaskStatus getStatus() {
                          * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                      -    return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_;
                      +  public org.a2aproject.sdk.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                      +    return status_ == null ? org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance() : status_;
                         }
                       
                         public static final int ARTIFACTS_FIELD_NUMBER = 4;
                         @SuppressWarnings("serial")
                      -  private java.util.List artifacts_;
                      +  private java.util.List artifacts_;
                         /**
                          * 
                          * A set of output artifacts for a `Task`.
                      @@ -202,7 +202,7 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                          * repeated .lf.a2a.v1.Artifact artifacts = 4;
                          */
                         @java.lang.Override
                      -  public java.util.List getArtifactsList() {
                      +  public java.util.List getArtifactsList() {
                           return artifacts_;
                         }
                         /**
                      @@ -213,7 +213,7 @@ public java.util.List getArtifactsList() {
                          * repeated .lf.a2a.v1.Artifact artifacts = 4;
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getArtifactsOrBuilderList() {
                           return artifacts_;
                         }
                      @@ -236,7 +236,7 @@ public int getArtifactsCount() {
                          * repeated .lf.a2a.v1.Artifact artifacts = 4;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Artifact getArtifacts(int index) {
                      +  public org.a2aproject.sdk.grpc.Artifact getArtifacts(int index) {
                           return artifacts_.get(index);
                         }
                         /**
                      @@ -247,14 +247,14 @@ public io.a2a.grpc.Artifact getArtifacts(int index) {
                          * repeated .lf.a2a.v1.Artifact artifacts = 4;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                      +  public org.a2aproject.sdk.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                             int index) {
                           return artifacts_.get(index);
                         }
                       
                         public static final int HISTORY_FIELD_NUMBER = 5;
                         @SuppressWarnings("serial")
                      -  private java.util.List history_;
                      +  private java.util.List history_;
                         /**
                          * 
                          * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
                      @@ -264,7 +264,7 @@ public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                          * repeated .lf.a2a.v1.Message history = 5;
                          */
                         @java.lang.Override
                      -  public java.util.List getHistoryList() {
                      +  public java.util.List getHistoryList() {
                           return history_;
                         }
                         /**
                      @@ -276,7 +276,7 @@ public java.util.List getHistoryList() {
                          * repeated .lf.a2a.v1.Message history = 5;
                          */
                         @java.lang.Override
                      -  public java.util.List 
                      +  public java.util.List 
                             getHistoryOrBuilderList() {
                           return history_;
                         }
                      @@ -301,7 +301,7 @@ public int getHistoryCount() {
                          * repeated .lf.a2a.v1.Message history = 5;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Message getHistory(int index) {
                      +  public org.a2aproject.sdk.grpc.Message getHistory(int index) {
                           return history_.get(index);
                         }
                         /**
                      @@ -313,7 +313,7 @@ public io.a2a.grpc.Message getHistory(int index) {
                          * repeated .lf.a2a.v1.Message history = 5;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder(
                      +  public org.a2aproject.sdk.grpc.MessageOrBuilder getHistoryOrBuilder(
                             int index) {
                           return history_.get(index);
                         }
                      @@ -432,10 +432,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.Task)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.Task)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.Task other = (io.a2a.grpc.Task) obj;
                      +    org.a2aproject.sdk.grpc.Task other = (org.a2aproject.sdk.grpc.Task) obj;
                       
                           if (!getId()
                               .equals(other.getId())) return false;
                      @@ -491,44 +491,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.Task parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -536,26 +536,26 @@ public static io.a2a.grpc.Task parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.Task parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.Task parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.Task parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.Task parseFrom(
                      +  public static org.a2aproject.sdk.grpc.Task parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -568,7 +568,7 @@ public static io.a2a.grpc.Task parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.Task prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.Task prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -596,21 +596,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.Task)
                      -      io.a2a.grpc.TaskOrBuilder {
                      +      org.a2aproject.sdk.grpc.TaskOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Task_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.Task.class, io.a2a.grpc.Task.Builder.class);
                      +              org.a2aproject.sdk.grpc.Task.class, org.a2aproject.sdk.grpc.Task.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.Task.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.Task.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -665,17 +665,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_Task_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Task getDefaultInstanceForType() {
                      -      return io.a2a.grpc.Task.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.Task getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.Task.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Task build() {
                      -      io.a2a.grpc.Task result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.Task build() {
                      +      org.a2aproject.sdk.grpc.Task result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -683,15 +683,15 @@ public io.a2a.grpc.Task build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.Task buildPartial() {
                      -      io.a2a.grpc.Task result = new io.a2a.grpc.Task(this);
                      +    public org.a2aproject.sdk.grpc.Task buildPartial() {
                      +      org.a2aproject.sdk.grpc.Task result = new org.a2aproject.sdk.grpc.Task(this);
                             buildPartialRepeatedFields(result);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartialRepeatedFields(io.a2a.grpc.Task result) {
                      +    private void buildPartialRepeatedFields(org.a2aproject.sdk.grpc.Task result) {
                             if (artifactsBuilder_ == null) {
                               if (((bitField0_ & 0x00000008) != 0)) {
                                 artifacts_ = java.util.Collections.unmodifiableList(artifacts_);
                      @@ -712,7 +712,7 @@ private void buildPartialRepeatedFields(io.a2a.grpc.Task result) {
                             }
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.Task result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.Task result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.id_ = id_;
                      @@ -738,16 +738,16 @@ private void buildPartial0(io.a2a.grpc.Task result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.Task) {
                      -        return mergeFrom((io.a2a.grpc.Task)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.Task) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.Task)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.Task other) {
                      -      if (other == io.a2a.grpc.Task.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.Task other) {
                      +      if (other == org.a2aproject.sdk.grpc.Task.getDefaultInstance()) return this;
                             if (!other.getId().isEmpty()) {
                               id_ = other.id_;
                               bitField0_ |= 0x00000001;
                      @@ -860,9 +860,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 26
                                   case 34: {
                      -              io.a2a.grpc.Artifact m =
                      +              org.a2aproject.sdk.grpc.Artifact m =
                                         input.readMessage(
                      -                      io.a2a.grpc.Artifact.parser(),
                      +                      org.a2aproject.sdk.grpc.Artifact.parser(),
                                             extensionRegistry);
                                     if (artifactsBuilder_ == null) {
                                       ensureArtifactsIsMutable();
                      @@ -873,9 +873,9 @@ public Builder mergeFrom(
                                     break;
                                   } // case 34
                                   case 42: {
                      -              io.a2a.grpc.Message m =
                      +              org.a2aproject.sdk.grpc.Message m =
                                         input.readMessage(
                      -                      io.a2a.grpc.Message.parser(),
                      +                      org.a2aproject.sdk.grpc.Message.parser(),
                                             extensionRegistry);
                                     if (historyBuilder_ == null) {
                                       ensureHistoryIsMutable();
                      @@ -1103,9 +1103,9 @@ public Builder setContextIdBytes(
                             return this;
                           }
                       
                      -    private io.a2a.grpc.TaskStatus status_;
                      +    private org.a2aproject.sdk.grpc.TaskStatus status_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> statusBuilder_;
                      +        org.a2aproject.sdk.grpc.TaskStatus, org.a2aproject.sdk.grpc.TaskStatus.Builder, org.a2aproject.sdk.grpc.TaskStatusOrBuilder> statusBuilder_;
                           /**
                            * 
                            * The current status of a `Task`, including `state` and a `message`.
                      @@ -1125,9 +1125,9 @@ public boolean hasStatus() {
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            * @return The status.
                            */
                      -    public io.a2a.grpc.TaskStatus getStatus() {
                      +    public org.a2aproject.sdk.grpc.TaskStatus getStatus() {
                             if (statusBuilder_ == null) {
                      -        return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_;
                      +        return status_ == null ? org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance() : status_;
                             } else {
                               return statusBuilder_.getMessage();
                             }
                      @@ -1139,7 +1139,7 @@ public io.a2a.grpc.TaskStatus getStatus() {
                            *
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder setStatus(io.a2a.grpc.TaskStatus value) {
                      +    public Builder setStatus(org.a2aproject.sdk.grpc.TaskStatus value) {
                             if (statusBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1160,7 +1160,7 @@ public Builder setStatus(io.a2a.grpc.TaskStatus value) {
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setStatus(
                      -        io.a2a.grpc.TaskStatus.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.TaskStatus.Builder builderForValue) {
                             if (statusBuilder_ == null) {
                               status_ = builderForValue.build();
                             } else {
                      @@ -1177,11 +1177,11 @@ public Builder setStatus(
                            *
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder mergeStatus(io.a2a.grpc.TaskStatus value) {
                      +    public Builder mergeStatus(org.a2aproject.sdk.grpc.TaskStatus value) {
                             if (statusBuilder_ == null) {
                               if (((bitField0_ & 0x00000004) != 0) &&
                                 status_ != null &&
                      -          status_ != io.a2a.grpc.TaskStatus.getDefaultInstance()) {
                      +          status_ != org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance()) {
                                 getStatusBuilder().mergeFrom(value);
                               } else {
                                 status_ = value;
                      @@ -1219,7 +1219,7 @@ public Builder clearStatus() {
                            *
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskStatus.Builder getStatusBuilder() {
                             bitField0_ |= 0x00000004;
                             onChanged();
                             return internalGetStatusFieldBuilder().getBuilder();
                      @@ -1231,12 +1231,12 @@ public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() {
                            *
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                             if (statusBuilder_ != null) {
                               return statusBuilder_.getMessageOrBuilder();
                             } else {
                               return status_ == null ?
                      -            io.a2a.grpc.TaskStatus.getDefaultInstance() : status_;
                      +            org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance() : status_;
                             }
                           }
                           /**
                      @@ -1247,11 +1247,11 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> 
                      +        org.a2aproject.sdk.grpc.TaskStatus, org.a2aproject.sdk.grpc.TaskStatus.Builder, org.a2aproject.sdk.grpc.TaskStatusOrBuilder> 
                               internalGetStatusFieldBuilder() {
                             if (statusBuilder_ == null) {
                               statusBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder>(
                      +            org.a2aproject.sdk.grpc.TaskStatus, org.a2aproject.sdk.grpc.TaskStatus.Builder, org.a2aproject.sdk.grpc.TaskStatusOrBuilder>(
                                       getStatus(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -1260,17 +1260,17 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                             return statusBuilder_;
                           }
                       
                      -    private java.util.List artifacts_ =
                      +    private java.util.List artifacts_ =
                             java.util.Collections.emptyList();
                           private void ensureArtifactsIsMutable() {
                             if (!((bitField0_ & 0x00000008) != 0)) {
                      -        artifacts_ = new java.util.ArrayList(artifacts_);
                      +        artifacts_ = new java.util.ArrayList(artifacts_);
                               bitField0_ |= 0x00000008;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> artifactsBuilder_;
                      +        org.a2aproject.sdk.grpc.Artifact, org.a2aproject.sdk.grpc.Artifact.Builder, org.a2aproject.sdk.grpc.ArtifactOrBuilder> artifactsBuilder_;
                       
                           /**
                            * 
                      @@ -1279,7 +1279,7 @@ private void ensureArtifactsIsMutable() {
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public java.util.List getArtifactsList() {
                      +    public java.util.List getArtifactsList() {
                             if (artifactsBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(artifacts_);
                             } else {
                      @@ -1307,7 +1307,7 @@ public int getArtifactsCount() {
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public io.a2a.grpc.Artifact getArtifacts(int index) {
                      +    public org.a2aproject.sdk.grpc.Artifact getArtifacts(int index) {
                             if (artifactsBuilder_ == null) {
                               return artifacts_.get(index);
                             } else {
                      @@ -1322,7 +1322,7 @@ public io.a2a.grpc.Artifact getArtifacts(int index) {
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                           public Builder setArtifacts(
                      -        int index, io.a2a.grpc.Artifact value) {
                      +        int index, org.a2aproject.sdk.grpc.Artifact value) {
                             if (artifactsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1343,7 +1343,7 @@ public Builder setArtifacts(
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                           public Builder setArtifacts(
                      -        int index, io.a2a.grpc.Artifact.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Artifact.Builder builderForValue) {
                             if (artifactsBuilder_ == null) {
                               ensureArtifactsIsMutable();
                               artifacts_.set(index, builderForValue.build());
                      @@ -1360,7 +1360,7 @@ public Builder setArtifacts(
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public Builder addArtifacts(io.a2a.grpc.Artifact value) {
                      +    public Builder addArtifacts(org.a2aproject.sdk.grpc.Artifact value) {
                             if (artifactsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1381,7 +1381,7 @@ public Builder addArtifacts(io.a2a.grpc.Artifact value) {
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                           public Builder addArtifacts(
                      -        int index, io.a2a.grpc.Artifact value) {
                      +        int index, org.a2aproject.sdk.grpc.Artifact value) {
                             if (artifactsBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1402,7 +1402,7 @@ public Builder addArtifacts(
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                           public Builder addArtifacts(
                      -        io.a2a.grpc.Artifact.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Artifact.Builder builderForValue) {
                             if (artifactsBuilder_ == null) {
                               ensureArtifactsIsMutable();
                               artifacts_.add(builderForValue.build());
                      @@ -1420,7 +1420,7 @@ public Builder addArtifacts(
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                           public Builder addArtifacts(
                      -        int index, io.a2a.grpc.Artifact.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Artifact.Builder builderForValue) {
                             if (artifactsBuilder_ == null) {
                               ensureArtifactsIsMutable();
                               artifacts_.add(index, builderForValue.build());
                      @@ -1438,7 +1438,7 @@ public Builder addArtifacts(
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                           public Builder addAllArtifacts(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (artifactsBuilder_ == null) {
                               ensureArtifactsIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -1490,7 +1490,7 @@ public Builder removeArtifacts(int index) {
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public io.a2a.grpc.Artifact.Builder getArtifactsBuilder(
                      +    public org.a2aproject.sdk.grpc.Artifact.Builder getArtifactsBuilder(
                               int index) {
                             return internalGetArtifactsFieldBuilder().getBuilder(index);
                           }
                      @@ -1501,7 +1501,7 @@ public io.a2a.grpc.Artifact.Builder getArtifactsBuilder(
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                      +    public org.a2aproject.sdk.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                               int index) {
                             if (artifactsBuilder_ == null) {
                               return artifacts_.get(index);  } else {
                      @@ -1515,7 +1515,7 @@ public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getArtifactsOrBuilderList() {
                             if (artifactsBuilder_ != null) {
                               return artifactsBuilder_.getMessageOrBuilderList();
                      @@ -1530,9 +1530,9 @@ public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public io.a2a.grpc.Artifact.Builder addArtifactsBuilder() {
                      +    public org.a2aproject.sdk.grpc.Artifact.Builder addArtifactsBuilder() {
                             return internalGetArtifactsFieldBuilder().addBuilder(
                      -          io.a2a.grpc.Artifact.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.Artifact.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1541,10 +1541,10 @@ public io.a2a.grpc.Artifact.Builder addArtifactsBuilder() {
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public io.a2a.grpc.Artifact.Builder addArtifactsBuilder(
                      +    public org.a2aproject.sdk.grpc.Artifact.Builder addArtifactsBuilder(
                               int index) {
                             return internalGetArtifactsFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.Artifact.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.Artifact.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1553,16 +1553,16 @@ public io.a2a.grpc.Artifact.Builder addArtifactsBuilder(
                            *
                            * repeated .lf.a2a.v1.Artifact artifacts = 4;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getArtifactsBuilderList() {
                             return internalGetArtifactsFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Artifact, org.a2aproject.sdk.grpc.Artifact.Builder, org.a2aproject.sdk.grpc.ArtifactOrBuilder> 
                               internalGetArtifactsFieldBuilder() {
                             if (artifactsBuilder_ == null) {
                               artifactsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder>(
                      +            org.a2aproject.sdk.grpc.Artifact, org.a2aproject.sdk.grpc.Artifact.Builder, org.a2aproject.sdk.grpc.ArtifactOrBuilder>(
                                       artifacts_,
                                       ((bitField0_ & 0x00000008) != 0),
                                       getParentForChildren(),
                      @@ -1572,17 +1572,17 @@ public io.a2a.grpc.Artifact.Builder addArtifactsBuilder(
                             return artifactsBuilder_;
                           }
                       
                      -    private java.util.List history_ =
                      +    private java.util.List history_ =
                             java.util.Collections.emptyList();
                           private void ensureHistoryIsMutable() {
                             if (!((bitField0_ & 0x00000010) != 0)) {
                      -        history_ = new java.util.ArrayList(history_);
                      +        history_ = new java.util.ArrayList(history_);
                               bitField0_ |= 0x00000010;
                              }
                           }
                       
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> historyBuilder_;
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> historyBuilder_;
                       
                           /**
                            * 
                      @@ -1592,7 +1592,7 @@ private void ensureHistoryIsMutable() {
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public java.util.List getHistoryList() {
                      +    public java.util.List getHistoryList() {
                             if (historyBuilder_ == null) {
                               return java.util.Collections.unmodifiableList(history_);
                             } else {
                      @@ -1622,7 +1622,7 @@ public int getHistoryCount() {
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public io.a2a.grpc.Message getHistory(int index) {
                      +    public org.a2aproject.sdk.grpc.Message getHistory(int index) {
                             if (historyBuilder_ == null) {
                               return history_.get(index);
                             } else {
                      @@ -1638,7 +1638,7 @@ public io.a2a.grpc.Message getHistory(int index) {
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                           public Builder setHistory(
                      -        int index, io.a2a.grpc.Message value) {
                      +        int index, org.a2aproject.sdk.grpc.Message value) {
                             if (historyBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1660,7 +1660,7 @@ public Builder setHistory(
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                           public Builder setHistory(
                      -        int index, io.a2a.grpc.Message.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Message.Builder builderForValue) {
                             if (historyBuilder_ == null) {
                               ensureHistoryIsMutable();
                               history_.set(index, builderForValue.build());
                      @@ -1678,7 +1678,7 @@ public Builder setHistory(
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public Builder addHistory(io.a2a.grpc.Message value) {
                      +    public Builder addHistory(org.a2aproject.sdk.grpc.Message value) {
                             if (historyBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1700,7 +1700,7 @@ public Builder addHistory(io.a2a.grpc.Message value) {
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                           public Builder addHistory(
                      -        int index, io.a2a.grpc.Message value) {
                      +        int index, org.a2aproject.sdk.grpc.Message value) {
                             if (historyBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1722,7 +1722,7 @@ public Builder addHistory(
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                           public Builder addHistory(
                      -        io.a2a.grpc.Message.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Message.Builder builderForValue) {
                             if (historyBuilder_ == null) {
                               ensureHistoryIsMutable();
                               history_.add(builderForValue.build());
                      @@ -1741,7 +1741,7 @@ public Builder addHistory(
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                           public Builder addHistory(
                      -        int index, io.a2a.grpc.Message.Builder builderForValue) {
                      +        int index, org.a2aproject.sdk.grpc.Message.Builder builderForValue) {
                             if (historyBuilder_ == null) {
                               ensureHistoryIsMutable();
                               history_.add(index, builderForValue.build());
                      @@ -1760,7 +1760,7 @@ public Builder addHistory(
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                           public Builder addAllHistory(
                      -        java.lang.Iterable values) {
                      +        java.lang.Iterable values) {
                             if (historyBuilder_ == null) {
                               ensureHistoryIsMutable();
                               com.google.protobuf.AbstractMessageLite.Builder.addAll(
                      @@ -1815,7 +1815,7 @@ public Builder removeHistory(int index) {
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public io.a2a.grpc.Message.Builder getHistoryBuilder(
                      +    public org.a2aproject.sdk.grpc.Message.Builder getHistoryBuilder(
                               int index) {
                             return internalGetHistoryFieldBuilder().getBuilder(index);
                           }
                      @@ -1827,7 +1827,7 @@ public io.a2a.grpc.Message.Builder getHistoryBuilder(
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder(
                      +    public org.a2aproject.sdk.grpc.MessageOrBuilder getHistoryOrBuilder(
                               int index) {
                             if (historyBuilder_ == null) {
                               return history_.get(index);  } else {
                      @@ -1842,7 +1842,7 @@ public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getHistoryOrBuilderList() {
                             if (historyBuilder_ != null) {
                               return historyBuilder_.getMessageOrBuilderList();
                      @@ -1858,9 +1858,9 @@ public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder(
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public io.a2a.grpc.Message.Builder addHistoryBuilder() {
                      +    public org.a2aproject.sdk.grpc.Message.Builder addHistoryBuilder() {
                             return internalGetHistoryFieldBuilder().addBuilder(
                      -          io.a2a.grpc.Message.getDefaultInstance());
                      +          org.a2aproject.sdk.grpc.Message.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1870,10 +1870,10 @@ public io.a2a.grpc.Message.Builder addHistoryBuilder() {
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public io.a2a.grpc.Message.Builder addHistoryBuilder(
                      +    public org.a2aproject.sdk.grpc.Message.Builder addHistoryBuilder(
                               int index) {
                             return internalGetHistoryFieldBuilder().addBuilder(
                      -          index, io.a2a.grpc.Message.getDefaultInstance());
                      +          index, org.a2aproject.sdk.grpc.Message.getDefaultInstance());
                           }
                           /**
                            * 
                      @@ -1883,16 +1883,16 @@ public io.a2a.grpc.Message.Builder addHistoryBuilder(
                            *
                            * repeated .lf.a2a.v1.Message history = 5;
                            */
                      -    public java.util.List 
                      +    public java.util.List 
                                getHistoryBuilderList() {
                             return internalGetHistoryFieldBuilder().getBuilderList();
                           }
                           private com.google.protobuf.RepeatedFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> 
                               internalGetHistoryFieldBuilder() {
                             if (historyBuilder_ == null) {
                               historyBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
                      -            io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>(
                      +            org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder>(
                                       history_,
                                       ((bitField0_ & 0x00000010) != 0),
                                       getParentForChildren(),
                      @@ -2072,12 +2072,12 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.Task)
                      -  private static final io.a2a.grpc.Task DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.Task DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.Task();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.Task();
                         }
                       
                      -  public static io.a2a.grpc.Task getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.Task getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -2113,7 +2113,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.Task getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.Task getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskArtifactUpdateEvent.java
                      similarity index 88%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskArtifactUpdateEvent.java
                      index b89e56e3f..8a51e76b3 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskArtifactUpdateEvent.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private TaskArtifactUpdateEvent() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.TaskArtifactUpdateEvent.class, io.a2a.grpc.TaskArtifactUpdateEvent.Builder.class);
                      +            org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.class, org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -145,7 +145,7 @@ public java.lang.String getContextId() {
                         }
                       
                         public static final int ARTIFACT_FIELD_NUMBER = 3;
                      -  private io.a2a.grpc.Artifact artifact_;
                      +  private org.a2aproject.sdk.grpc.Artifact artifact_;
                         /**
                          * 
                          * The artifact that was generated or updated.
                      @@ -167,8 +167,8 @@ public boolean hasArtifact() {
                          * @return The artifact.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Artifact getArtifact() {
                      -    return artifact_ == null ? io.a2a.grpc.Artifact.getDefaultInstance() : artifact_;
                      +  public org.a2aproject.sdk.grpc.Artifact getArtifact() {
                      +    return artifact_ == null ? org.a2aproject.sdk.grpc.Artifact.getDefaultInstance() : artifact_;
                         }
                         /**
                          * 
                      @@ -178,8 +178,8 @@ public io.a2a.grpc.Artifact getArtifact() {
                          * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder() {
                      -    return artifact_ == null ? io.a2a.grpc.Artifact.getDefaultInstance() : artifact_;
                      +  public org.a2aproject.sdk.grpc.ArtifactOrBuilder getArtifactOrBuilder() {
                      +    return artifact_ == null ? org.a2aproject.sdk.grpc.Artifact.getDefaultInstance() : artifact_;
                         }
                       
                         public static final int APPEND_FIELD_NUMBER = 4;
                      @@ -324,10 +324,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.TaskArtifactUpdateEvent)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.TaskArtifactUpdateEvent other = (io.a2a.grpc.TaskArtifactUpdateEvent) obj;
                      +    org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent other = (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) obj;
                       
                           if (!getTaskId()
                               .equals(other.getTaskId())) return false;
                      @@ -381,44 +381,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -426,26 +426,26 @@ public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -458,7 +458,7 @@ public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.TaskArtifactUpdateEvent prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -483,21 +483,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.TaskArtifactUpdateEvent)
                      -      io.a2a.grpc.TaskArtifactUpdateEventOrBuilder {
                      +      org.a2aproject.sdk.grpc.TaskArtifactUpdateEventOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.TaskArtifactUpdateEvent.class, io.a2a.grpc.TaskArtifactUpdateEvent.Builder.class);
                      +              org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.class, org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.TaskArtifactUpdateEvent.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -538,17 +538,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskArtifactUpdateEvent_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskArtifactUpdateEvent getDefaultInstanceForType() {
                      -      return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskArtifactUpdateEvent build() {
                      -      io.a2a.grpc.TaskArtifactUpdateEvent result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent build() {
                      +      org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -556,14 +556,14 @@ public io.a2a.grpc.TaskArtifactUpdateEvent build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskArtifactUpdateEvent buildPartial() {
                      -      io.a2a.grpc.TaskArtifactUpdateEvent result = new io.a2a.grpc.TaskArtifactUpdateEvent(this);
                      +    public org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent buildPartial() {
                      +      org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent result = new org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.TaskArtifactUpdateEvent result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.taskId_ = taskId_;
                      @@ -595,16 +595,16 @@ private void buildPartial0(io.a2a.grpc.TaskArtifactUpdateEvent result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.TaskArtifactUpdateEvent) {
                      -        return mergeFrom((io.a2a.grpc.TaskArtifactUpdateEvent)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.TaskArtifactUpdateEvent other) {
                      -      if (other == io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent other) {
                      +      if (other == org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.getDefaultInstance()) return this;
                             if (!other.getTaskId().isEmpty()) {
                               taskId_ = other.taskId_;
                               bitField0_ |= 0x00000001;
                      @@ -888,9 +888,9 @@ public Builder setContextIdBytes(
                             return this;
                           }
                       
                      -    private io.a2a.grpc.Artifact artifact_;
                      +    private org.a2aproject.sdk.grpc.Artifact artifact_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> artifactBuilder_;
                      +        org.a2aproject.sdk.grpc.Artifact, org.a2aproject.sdk.grpc.Artifact.Builder, org.a2aproject.sdk.grpc.ArtifactOrBuilder> artifactBuilder_;
                           /**
                            * 
                            * The artifact that was generated or updated.
                      @@ -910,9 +910,9 @@ public boolean hasArtifact() {
                            * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                            * @return The artifact.
                            */
                      -    public io.a2a.grpc.Artifact getArtifact() {
                      +    public org.a2aproject.sdk.grpc.Artifact getArtifact() {
                             if (artifactBuilder_ == null) {
                      -        return artifact_ == null ? io.a2a.grpc.Artifact.getDefaultInstance() : artifact_;
                      +        return artifact_ == null ? org.a2aproject.sdk.grpc.Artifact.getDefaultInstance() : artifact_;
                             } else {
                               return artifactBuilder_.getMessage();
                             }
                      @@ -924,7 +924,7 @@ public io.a2a.grpc.Artifact getArtifact() {
                            *
                            * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder setArtifact(io.a2a.grpc.Artifact value) {
                      +    public Builder setArtifact(org.a2aproject.sdk.grpc.Artifact value) {
                             if (artifactBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -945,7 +945,7 @@ public Builder setArtifact(io.a2a.grpc.Artifact value) {
                            * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setArtifact(
                      -        io.a2a.grpc.Artifact.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Artifact.Builder builderForValue) {
                             if (artifactBuilder_ == null) {
                               artifact_ = builderForValue.build();
                             } else {
                      @@ -962,11 +962,11 @@ public Builder setArtifact(
                            *
                            * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder mergeArtifact(io.a2a.grpc.Artifact value) {
                      +    public Builder mergeArtifact(org.a2aproject.sdk.grpc.Artifact value) {
                             if (artifactBuilder_ == null) {
                               if (((bitField0_ & 0x00000004) != 0) &&
                                 artifact_ != null &&
                      -          artifact_ != io.a2a.grpc.Artifact.getDefaultInstance()) {
                      +          artifact_ != org.a2aproject.sdk.grpc.Artifact.getDefaultInstance()) {
                                 getArtifactBuilder().mergeFrom(value);
                               } else {
                                 artifact_ = value;
                      @@ -1004,7 +1004,7 @@ public Builder clearArtifact() {
                            *
                            * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.Artifact.Builder getArtifactBuilder() {
                      +    public org.a2aproject.sdk.grpc.Artifact.Builder getArtifactBuilder() {
                             bitField0_ |= 0x00000004;
                             onChanged();
                             return internalGetArtifactFieldBuilder().getBuilder();
                      @@ -1016,12 +1016,12 @@ public io.a2a.grpc.Artifact.Builder getArtifactBuilder() {
                            *
                            * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.ArtifactOrBuilder getArtifactOrBuilder() {
                             if (artifactBuilder_ != null) {
                               return artifactBuilder_.getMessageOrBuilder();
                             } else {
                               return artifact_ == null ?
                      -            io.a2a.grpc.Artifact.getDefaultInstance() : artifact_;
                      +            org.a2aproject.sdk.grpc.Artifact.getDefaultInstance() : artifact_;
                             }
                           }
                           /**
                      @@ -1032,11 +1032,11 @@ public io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder() {
                            * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Artifact, org.a2aproject.sdk.grpc.Artifact.Builder, org.a2aproject.sdk.grpc.ArtifactOrBuilder> 
                               internalGetArtifactFieldBuilder() {
                             if (artifactBuilder_ == null) {
                               artifactBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder>(
                      +            org.a2aproject.sdk.grpc.Artifact, org.a2aproject.sdk.grpc.Artifact.Builder, org.a2aproject.sdk.grpc.ArtifactOrBuilder>(
                                       getArtifact(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -1297,12 +1297,12 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.TaskArtifactUpdateEvent)
                      -  private static final io.a2a.grpc.TaskArtifactUpdateEvent DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.TaskArtifactUpdateEvent();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent();
                         }
                       
                      -  public static io.a2a.grpc.TaskArtifactUpdateEvent getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1338,7 +1338,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskArtifactUpdateEvent getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskArtifactUpdateEventOrBuilder.java
                      similarity index 95%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskArtifactUpdateEventOrBuilder.java
                      index b543856f4..88409c4a8 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskArtifactUpdateEventOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface TaskArtifactUpdateEventOrBuilder extends
                      @@ -67,7 +67,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends
                          * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                          * @return The artifact.
                          */
                      -  io.a2a.grpc.Artifact getArtifact();
                      +  org.a2aproject.sdk.grpc.Artifact getArtifact();
                         /**
                          * 
                          * The artifact that was generated or updated.
                      @@ -75,7 +75,7 @@ public interface TaskArtifactUpdateEventOrBuilder extends
                          *
                          * .lf.a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder();
                      +  org.a2aproject.sdk.grpc.ArtifactOrBuilder getArtifactOrBuilder();
                       
                         /**
                          * 
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskOrBuilder.java
                      similarity index 88%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskOrBuilder.java
                      index 09bdfc0ab..a276cc652 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface TaskOrBuilder extends
                      @@ -71,7 +71,7 @@ public interface TaskOrBuilder extends
                          * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                          * @return The status.
                          */
                      -  io.a2a.grpc.TaskStatus getStatus();
                      +  org.a2aproject.sdk.grpc.TaskStatus getStatus();
                         /**
                          * 
                          * The current status of a `Task`, including `state` and a `message`.
                      @@ -79,7 +79,7 @@ public interface TaskOrBuilder extends
                          *
                          * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder();
                      +  org.a2aproject.sdk.grpc.TaskStatusOrBuilder getStatusOrBuilder();
                       
                         /**
                          * 
                      @@ -88,7 +88,7 @@ public interface TaskOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Artifact artifacts = 4;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getArtifactsList();
                         /**
                          * 
                      @@ -97,7 +97,7 @@ public interface TaskOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Artifact artifacts = 4;
                          */
                      -  io.a2a.grpc.Artifact getArtifacts(int index);
                      +  org.a2aproject.sdk.grpc.Artifact getArtifacts(int index);
                         /**
                          * 
                          * A set of output artifacts for a `Task`.
                      @@ -113,7 +113,7 @@ public interface TaskOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Artifact artifacts = 4;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getArtifactsOrBuilderList();
                         /**
                          * 
                      @@ -122,7 +122,7 @@ public interface TaskOrBuilder extends
                          *
                          * repeated .lf.a2a.v1.Artifact artifacts = 4;
                          */
                      -  io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                      +  org.a2aproject.sdk.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                             int index);
                       
                         /**
                      @@ -133,7 +133,7 @@ io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.Message history = 5;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getHistoryList();
                         /**
                          * 
                      @@ -143,7 +143,7 @@ io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.Message history = 5;
                          */
                      -  io.a2a.grpc.Message getHistory(int index);
                      +  org.a2aproject.sdk.grpc.Message getHistory(int index);
                         /**
                          * 
                          * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
                      @@ -161,7 +161,7 @@ io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.Message history = 5;
                          */
                      -  java.util.List 
                      +  java.util.List 
                             getHistoryOrBuilderList();
                         /**
                          * 
                      @@ -171,7 +171,7 @@ io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder(
                          *
                          * repeated .lf.a2a.v1.Message history = 5;
                          */
                      -  io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder(
                      +  org.a2aproject.sdk.grpc.MessageOrBuilder getHistoryOrBuilder(
                             int index);
                       
                         /**
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskPushNotificationConfig.java
                      similarity index 87%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskPushNotificationConfig.java
                      index a523424f3..c0ee382e0 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskPushNotificationConfig.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -41,15 +41,15 @@ private TaskPushNotificationConfig() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.TaskPushNotificationConfig.class, io.a2a.grpc.TaskPushNotificationConfig.Builder.class);
                      +            org.a2aproject.sdk.grpc.TaskPushNotificationConfig.class, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -291,7 +291,7 @@ public java.lang.String getToken() {
                         }
                       
                         public static final int AUTHENTICATION_FIELD_NUMBER = 6;
                      -  private io.a2a.grpc.AuthenticationInfo authentication_;
                      +  private org.a2aproject.sdk.grpc.AuthenticationInfo authentication_;
                         /**
                          * 
                          * Authentication information required to send the notification.
                      @@ -313,8 +313,8 @@ public boolean hasAuthentication() {
                          * @return The authentication.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AuthenticationInfo getAuthentication() {
                      -    return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_;
                      +  public org.a2aproject.sdk.grpc.AuthenticationInfo getAuthentication() {
                      +    return authentication_ == null ? org.a2aproject.sdk.grpc.AuthenticationInfo.getDefaultInstance() : authentication_;
                         }
                         /**
                          * 
                      @@ -324,8 +324,8 @@ public io.a2a.grpc.AuthenticationInfo getAuthentication() {
                          * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() {
                      -    return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_;
                      +  public org.a2aproject.sdk.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() {
                      +    return authentication_ == null ? org.a2aproject.sdk.grpc.AuthenticationInfo.getDefaultInstance() : authentication_;
                         }
                       
                         private byte memoizedIsInitialized = -1;
                      @@ -398,10 +398,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.TaskPushNotificationConfig)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.TaskPushNotificationConfig)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.TaskPushNotificationConfig other = (io.a2a.grpc.TaskPushNotificationConfig) obj;
                      +    org.a2aproject.sdk.grpc.TaskPushNotificationConfig other = (org.a2aproject.sdk.grpc.TaskPushNotificationConfig) obj;
                       
                           if (!getTenant()
                               .equals(other.getTenant())) return false;
                      @@ -448,44 +448,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -493,26 +493,26 @@ public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -525,7 +525,7 @@ public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.TaskPushNotificationConfig prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.TaskPushNotificationConfig prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -550,21 +550,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.TaskPushNotificationConfig)
                      -      io.a2a.grpc.TaskPushNotificationConfigOrBuilder {
                      +      org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.TaskPushNotificationConfig.class, io.a2a.grpc.TaskPushNotificationConfig.Builder.class);
                      +              org.a2aproject.sdk.grpc.TaskPushNotificationConfig.class, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.TaskPushNotificationConfig.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.TaskPushNotificationConfig.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -600,17 +600,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskPushNotificationConfig_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskPushNotificationConfig getDefaultInstanceForType() {
                      -      return io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskPushNotificationConfig build() {
                      -      io.a2a.grpc.TaskPushNotificationConfig result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig build() {
                      +      org.a2aproject.sdk.grpc.TaskPushNotificationConfig result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -618,14 +618,14 @@ public io.a2a.grpc.TaskPushNotificationConfig build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskPushNotificationConfig buildPartial() {
                      -      io.a2a.grpc.TaskPushNotificationConfig result = new io.a2a.grpc.TaskPushNotificationConfig(this);
                      +    public org.a2aproject.sdk.grpc.TaskPushNotificationConfig buildPartial() {
                      +      org.a2aproject.sdk.grpc.TaskPushNotificationConfig result = new org.a2aproject.sdk.grpc.TaskPushNotificationConfig(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.TaskPushNotificationConfig result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.TaskPushNotificationConfig result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.tenant_ = tenant_;
                      @@ -654,16 +654,16 @@ private void buildPartial0(io.a2a.grpc.TaskPushNotificationConfig result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.TaskPushNotificationConfig) {
                      -        return mergeFrom((io.a2a.grpc.TaskPushNotificationConfig)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.TaskPushNotificationConfig) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.TaskPushNotificationConfig)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.TaskPushNotificationConfig other) {
                      -      if (other == io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.TaskPushNotificationConfig other) {
                      +      if (other == org.a2aproject.sdk.grpc.TaskPushNotificationConfig.getDefaultInstance()) return this;
                             if (!other.getTenant().isEmpty()) {
                               tenant_ = other.tenant_;
                               bitField0_ |= 0x00000001;
                      @@ -1232,9 +1232,9 @@ public Builder setTokenBytes(
                             return this;
                           }
                       
                      -    private io.a2a.grpc.AuthenticationInfo authentication_;
                      +    private org.a2aproject.sdk.grpc.AuthenticationInfo authentication_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> authenticationBuilder_;
                      +        org.a2aproject.sdk.grpc.AuthenticationInfo, org.a2aproject.sdk.grpc.AuthenticationInfo.Builder, org.a2aproject.sdk.grpc.AuthenticationInfoOrBuilder> authenticationBuilder_;
                           /**
                            * 
                            * Authentication information required to send the notification.
                      @@ -1254,9 +1254,9 @@ public boolean hasAuthentication() {
                            * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                            * @return The authentication.
                            */
                      -    public io.a2a.grpc.AuthenticationInfo getAuthentication() {
                      +    public org.a2aproject.sdk.grpc.AuthenticationInfo getAuthentication() {
                             if (authenticationBuilder_ == null) {
                      -        return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_;
                      +        return authentication_ == null ? org.a2aproject.sdk.grpc.AuthenticationInfo.getDefaultInstance() : authentication_;
                             } else {
                               return authenticationBuilder_.getMessage();
                             }
                      @@ -1268,7 +1268,7 @@ public io.a2a.grpc.AuthenticationInfo getAuthentication() {
                            *
                            * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                            */
                      -    public Builder setAuthentication(io.a2a.grpc.AuthenticationInfo value) {
                      +    public Builder setAuthentication(org.a2aproject.sdk.grpc.AuthenticationInfo value) {
                             if (authenticationBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -1289,7 +1289,7 @@ public Builder setAuthentication(io.a2a.grpc.AuthenticationInfo value) {
                            * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                            */
                           public Builder setAuthentication(
                      -        io.a2a.grpc.AuthenticationInfo.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.AuthenticationInfo.Builder builderForValue) {
                             if (authenticationBuilder_ == null) {
                               authentication_ = builderForValue.build();
                             } else {
                      @@ -1306,11 +1306,11 @@ public Builder setAuthentication(
                            *
                            * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                            */
                      -    public Builder mergeAuthentication(io.a2a.grpc.AuthenticationInfo value) {
                      +    public Builder mergeAuthentication(org.a2aproject.sdk.grpc.AuthenticationInfo value) {
                             if (authenticationBuilder_ == null) {
                               if (((bitField0_ & 0x00000020) != 0) &&
                                 authentication_ != null &&
                      -          authentication_ != io.a2a.grpc.AuthenticationInfo.getDefaultInstance()) {
                      +          authentication_ != org.a2aproject.sdk.grpc.AuthenticationInfo.getDefaultInstance()) {
                                 getAuthenticationBuilder().mergeFrom(value);
                               } else {
                                 authentication_ = value;
                      @@ -1348,7 +1348,7 @@ public Builder clearAuthentication() {
                            *
                            * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                            */
                      -    public io.a2a.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() {
                      +    public org.a2aproject.sdk.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() {
                             bitField0_ |= 0x00000020;
                             onChanged();
                             return internalGetAuthenticationFieldBuilder().getBuilder();
                      @@ -1360,12 +1360,12 @@ public io.a2a.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() {
                            *
                            * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                            */
                      -    public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() {
                             if (authenticationBuilder_ != null) {
                               return authenticationBuilder_.getMessageOrBuilder();
                             } else {
                               return authentication_ == null ?
                      -            io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_;
                      +            org.a2aproject.sdk.grpc.AuthenticationInfo.getDefaultInstance() : authentication_;
                             }
                           }
                           /**
                      @@ -1376,11 +1376,11 @@ public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() {
                            * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> 
                      +        org.a2aproject.sdk.grpc.AuthenticationInfo, org.a2aproject.sdk.grpc.AuthenticationInfo.Builder, org.a2aproject.sdk.grpc.AuthenticationInfoOrBuilder> 
                               internalGetAuthenticationFieldBuilder() {
                             if (authenticationBuilder_ == null) {
                               authenticationBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder>(
                      +            org.a2aproject.sdk.grpc.AuthenticationInfo, org.a2aproject.sdk.grpc.AuthenticationInfo.Builder, org.a2aproject.sdk.grpc.AuthenticationInfoOrBuilder>(
                                       getAuthentication(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -1393,12 +1393,12 @@ public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.TaskPushNotificationConfig)
                      -  private static final io.a2a.grpc.TaskPushNotificationConfig DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.TaskPushNotificationConfig DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.TaskPushNotificationConfig();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.TaskPushNotificationConfig();
                         }
                       
                      -  public static io.a2a.grpc.TaskPushNotificationConfig getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1434,7 +1434,7 @@ public com.google.protobuf.Parser getParserForType()
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskPushNotificationConfig getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.TaskPushNotificationConfig getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskPushNotificationConfigOrBuilder.java
                      similarity index 94%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskPushNotificationConfigOrBuilder.java
                      index 771d13522..280be4b16 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskPushNotificationConfigOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface TaskPushNotificationConfigOrBuilder extends
                      @@ -129,7 +129,7 @@ public interface TaskPushNotificationConfigOrBuilder extends
                          * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                          * @return The authentication.
                          */
                      -  io.a2a.grpc.AuthenticationInfo getAuthentication();
                      +  org.a2aproject.sdk.grpc.AuthenticationInfo getAuthentication();
                         /**
                          * 
                          * Authentication information required to send the notification.
                      @@ -137,5 +137,5 @@ public interface TaskPushNotificationConfigOrBuilder extends
                          *
                          * .lf.a2a.v1.AuthenticationInfo authentication = 6;
                          */
                      -  io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder();
                      +  org.a2aproject.sdk.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder();
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskState.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskState.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskState.java
                      index b5632db75..f79daf4f2 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskState.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -240,7 +240,7 @@ public TaskState findValueByNumber(int number) {
                         }
                         public static com.google.protobuf.Descriptors.EnumDescriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.getDescriptor().getEnumTypes().get(0);
                      +    return org.a2aproject.sdk.grpc.A2A.getDescriptor().getEnumTypes().get(0);
                         }
                       
                         private static final TaskState[] VALUES = values();
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatus.java
                      similarity index 83%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatus.java
                      index f31bffb15..2aea1e13c 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatus.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -37,15 +37,15 @@ private TaskStatus() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.TaskStatus.class, io.a2a.grpc.TaskStatus.Builder.class);
                      +            org.a2aproject.sdk.grpc.TaskStatus.class, org.a2aproject.sdk.grpc.TaskStatus.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -70,13 +70,13 @@ private TaskStatus() {
                          * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED];
                          * @return The state.
                          */
                      -  @java.lang.Override public io.a2a.grpc.TaskState getState() {
                      -    io.a2a.grpc.TaskState result = io.a2a.grpc.TaskState.forNumber(state_);
                      -    return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result;
                      +  @java.lang.Override public org.a2aproject.sdk.grpc.TaskState getState() {
                      +    org.a2aproject.sdk.grpc.TaskState result = org.a2aproject.sdk.grpc.TaskState.forNumber(state_);
                      +    return result == null ? org.a2aproject.sdk.grpc.TaskState.UNRECOGNIZED : result;
                         }
                       
                         public static final int MESSAGE_FIELD_NUMBER = 2;
                      -  private io.a2a.grpc.Message message_;
                      +  private org.a2aproject.sdk.grpc.Message message_;
                         /**
                          * 
                          * A message associated with the status.
                      @@ -98,8 +98,8 @@ public boolean hasMessage() {
                          * @return The message.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.Message getMessage() {
                      -    return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_;
                      +  public org.a2aproject.sdk.grpc.Message getMessage() {
                      +    return message_ == null ? org.a2aproject.sdk.grpc.Message.getDefaultInstance() : message_;
                         }
                         /**
                          * 
                      @@ -109,8 +109,8 @@ public io.a2a.grpc.Message getMessage() {
                          * .lf.a2a.v1.Message message = 2;
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                      -    return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_;
                      +  public org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder() {
                      +    return message_ == null ? org.a2aproject.sdk.grpc.Message.getDefaultInstance() : message_;
                         }
                       
                         public static final int TIMESTAMP_FIELD_NUMBER = 3;
                      @@ -168,7 +168,7 @@ public final boolean isInitialized() {
                         @java.lang.Override
                         public void writeTo(com.google.protobuf.CodedOutputStream output)
                                             throws java.io.IOException {
                      -    if (state_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) {
                      +    if (state_ != org.a2aproject.sdk.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) {
                             output.writeEnum(1, state_);
                           }
                           if (((bitField0_ & 0x00000001) != 0)) {
                      @@ -186,7 +186,7 @@ public int getSerializedSize() {
                           if (size != -1) return size;
                       
                           size = 0;
                      -    if (state_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) {
                      +    if (state_ != org.a2aproject.sdk.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) {
                             size += com.google.protobuf.CodedOutputStream
                               .computeEnumSize(1, state_);
                           }
                      @@ -208,10 +208,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.TaskStatus)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.TaskStatus)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.TaskStatus other = (io.a2a.grpc.TaskStatus) obj;
                      +    org.a2aproject.sdk.grpc.TaskStatus other = (org.a2aproject.sdk.grpc.TaskStatus) obj;
                       
                           if (state_ != other.state_) return false;
                           if (hasMessage() != other.hasMessage()) return false;
                      @@ -250,44 +250,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.TaskStatus parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -295,26 +295,26 @@ public static io.a2a.grpc.TaskStatus parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.TaskStatus parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.TaskStatus parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.TaskStatus parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatus parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -327,7 +327,7 @@ public static io.a2a.grpc.TaskStatus parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.TaskStatus prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.TaskStatus prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -352,21 +352,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.TaskStatus)
                      -      io.a2a.grpc.TaskStatusOrBuilder {
                      +      org.a2aproject.sdk.grpc.TaskStatusOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.TaskStatus.class, io.a2a.grpc.TaskStatus.Builder.class);
                      +              org.a2aproject.sdk.grpc.TaskStatus.class, org.a2aproject.sdk.grpc.TaskStatus.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.TaskStatus.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.TaskStatus.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -404,17 +404,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatus_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskStatus getDefaultInstanceForType() {
                      -      return io.a2a.grpc.TaskStatus.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.TaskStatus getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskStatus build() {
                      -      io.a2a.grpc.TaskStatus result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.TaskStatus build() {
                      +      org.a2aproject.sdk.grpc.TaskStatus result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -422,14 +422,14 @@ public io.a2a.grpc.TaskStatus build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskStatus buildPartial() {
                      -      io.a2a.grpc.TaskStatus result = new io.a2a.grpc.TaskStatus(this);
                      +    public org.a2aproject.sdk.grpc.TaskStatus buildPartial() {
                      +      org.a2aproject.sdk.grpc.TaskStatus result = new org.a2aproject.sdk.grpc.TaskStatus(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.TaskStatus result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.TaskStatus result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.state_ = state_;
                      @@ -452,16 +452,16 @@ private void buildPartial0(io.a2a.grpc.TaskStatus result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.TaskStatus) {
                      -        return mergeFrom((io.a2a.grpc.TaskStatus)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.TaskStatus) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.TaskStatus)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.TaskStatus other) {
                      -      if (other == io.a2a.grpc.TaskStatus.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.TaskStatus other) {
                      +      if (other == org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance()) return this;
                             if (other.state_ != 0) {
                               setStateValue(other.getStateValue());
                             }
                      @@ -569,9 +569,9 @@ public Builder setStateValue(int value) {
                            * @return The state.
                            */
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskState getState() {
                      -      io.a2a.grpc.TaskState result = io.a2a.grpc.TaskState.forNumber(state_);
                      -      return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result;
                      +    public org.a2aproject.sdk.grpc.TaskState getState() {
                      +      org.a2aproject.sdk.grpc.TaskState result = org.a2aproject.sdk.grpc.TaskState.forNumber(state_);
                      +      return result == null ? org.a2aproject.sdk.grpc.TaskState.UNRECOGNIZED : result;
                           }
                           /**
                            * 
                      @@ -582,7 +582,7 @@ public io.a2a.grpc.TaskState getState() {
                            * @param value The state to set.
                            * @return This builder for chaining.
                            */
                      -    public Builder setState(io.a2a.grpc.TaskState value) {
                      +    public Builder setState(org.a2aproject.sdk.grpc.TaskState value) {
                             if (value == null) { throw new NullPointerException(); }
                             bitField0_ |= 0x00000001;
                             state_ = value.getNumber();
                      @@ -604,9 +604,9 @@ public Builder clearState() {
                             return this;
                           }
                       
                      -    private io.a2a.grpc.Message message_;
                      +    private org.a2aproject.sdk.grpc.Message message_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_;
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> messageBuilder_;
                           /**
                            * 
                            * A message associated with the status.
                      @@ -626,9 +626,9 @@ public boolean hasMessage() {
                            * .lf.a2a.v1.Message message = 2;
                            * @return The message.
                            */
                      -    public io.a2a.grpc.Message getMessage() {
                      +    public org.a2aproject.sdk.grpc.Message getMessage() {
                             if (messageBuilder_ == null) {
                      -        return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_;
                      +        return message_ == null ? org.a2aproject.sdk.grpc.Message.getDefaultInstance() : message_;
                             } else {
                               return messageBuilder_.getMessage();
                             }
                      @@ -640,7 +640,7 @@ public io.a2a.grpc.Message getMessage() {
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public Builder setMessage(io.a2a.grpc.Message value) {
                      +    public Builder setMessage(org.a2aproject.sdk.grpc.Message value) {
                             if (messageBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -661,7 +661,7 @@ public Builder setMessage(io.a2a.grpc.Message value) {
                            * .lf.a2a.v1.Message message = 2;
                            */
                           public Builder setMessage(
                      -        io.a2a.grpc.Message.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.Message.Builder builderForValue) {
                             if (messageBuilder_ == null) {
                               message_ = builderForValue.build();
                             } else {
                      @@ -678,11 +678,11 @@ public Builder setMessage(
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public Builder mergeMessage(io.a2a.grpc.Message value) {
                      +    public Builder mergeMessage(org.a2aproject.sdk.grpc.Message value) {
                             if (messageBuilder_ == null) {
                               if (((bitField0_ & 0x00000002) != 0) &&
                                 message_ != null &&
                      -          message_ != io.a2a.grpc.Message.getDefaultInstance()) {
                      +          message_ != org.a2aproject.sdk.grpc.Message.getDefaultInstance()) {
                                 getMessageBuilder().mergeFrom(value);
                               } else {
                                 message_ = value;
                      @@ -720,7 +720,7 @@ public Builder clearMessage() {
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public io.a2a.grpc.Message.Builder getMessageBuilder() {
                      +    public org.a2aproject.sdk.grpc.Message.Builder getMessageBuilder() {
                             bitField0_ |= 0x00000002;
                             onChanged();
                             return internalGetMessageFieldBuilder().getBuilder();
                      @@ -732,12 +732,12 @@ public io.a2a.grpc.Message.Builder getMessageBuilder() {
                            *
                            * .lf.a2a.v1.Message message = 2;
                            */
                      -    public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder() {
                             if (messageBuilder_ != null) {
                               return messageBuilder_.getMessageOrBuilder();
                             } else {
                               return message_ == null ?
                      -            io.a2a.grpc.Message.getDefaultInstance() : message_;
                      +            org.a2aproject.sdk.grpc.Message.getDefaultInstance() : message_;
                             }
                           }
                           /**
                      @@ -748,11 +748,11 @@ public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() {
                            * .lf.a2a.v1.Message message = 2;
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> 
                      +        org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder> 
                               internalGetMessageFieldBuilder() {
                             if (messageBuilder_ == null) {
                               messageBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>(
                      +            org.a2aproject.sdk.grpc.Message, org.a2aproject.sdk.grpc.Message.Builder, org.a2aproject.sdk.grpc.MessageOrBuilder>(
                                       getMessage(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -931,12 +931,12 @@ public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.TaskStatus)
                      -  private static final io.a2a.grpc.TaskStatus DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.TaskStatus DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.TaskStatus();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.TaskStatus();
                         }
                       
                      -  public static io.a2a.grpc.TaskStatus getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.TaskStatus getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -972,7 +972,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskStatus getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.TaskStatus getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusOrBuilder.java
                      similarity index 91%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusOrBuilder.java
                      index f2e5c1270..71bed07df 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface TaskStatusOrBuilder extends
                      @@ -27,7 +27,7 @@ public interface TaskStatusOrBuilder extends
                          * .lf.a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED];
                          * @return The state.
                          */
                      -  io.a2a.grpc.TaskState getState();
                      +  org.a2aproject.sdk.grpc.TaskState getState();
                       
                         /**
                          * 
                      @@ -46,7 +46,7 @@ public interface TaskStatusOrBuilder extends
                          * .lf.a2a.v1.Message message = 2;
                          * @return The message.
                          */
                      -  io.a2a.grpc.Message getMessage();
                      +  org.a2aproject.sdk.grpc.Message getMessage();
                         /**
                          * 
                          * A message associated with the status.
                      @@ -54,7 +54,7 @@ public interface TaskStatusOrBuilder extends
                          *
                          * .lf.a2a.v1.Message message = 2;
                          */
                      -  io.a2a.grpc.MessageOrBuilder getMessageOrBuilder();
                      +  org.a2aproject.sdk.grpc.MessageOrBuilder getMessageOrBuilder();
                       
                         /**
                          * 
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusUpdateEvent.java
                      similarity index 86%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusUpdateEvent.java
                      index 43eac7f2d..cd50149ae 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusUpdateEvent.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       /**
                        * 
                      @@ -38,15 +38,15 @@ private TaskStatusUpdateEvent() {
                       
                         public static final com.google.protobuf.Descriptors.Descriptor
                             getDescriptor() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor;
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor;
                         }
                       
                         @java.lang.Override
                         protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                             internalGetFieldAccessorTable() {
                      -    return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable
                      +    return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable
                               .ensureFieldAccessorsInitialized(
                      -            io.a2a.grpc.TaskStatusUpdateEvent.class, io.a2a.grpc.TaskStatusUpdateEvent.Builder.class);
                      +            org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.class, org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.Builder.class);
                         }
                       
                         private int bitField0_;
                      @@ -145,7 +145,7 @@ public java.lang.String getContextId() {
                         }
                       
                         public static final int STATUS_FIELD_NUMBER = 3;
                      -  private io.a2a.grpc.TaskStatus status_;
                      +  private org.a2aproject.sdk.grpc.TaskStatus status_;
                         /**
                          * 
                          * The new status of the task.
                      @@ -167,8 +167,8 @@ public boolean hasStatus() {
                          * @return The status.
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskStatus getStatus() {
                      -    return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_;
                      +  public org.a2aproject.sdk.grpc.TaskStatus getStatus() {
                      +    return status_ == null ? org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance() : status_;
                         }
                         /**
                          * 
                      @@ -178,8 +178,8 @@ public io.a2a.grpc.TaskStatus getStatus() {
                          * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                      -    return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_;
                      +  public org.a2aproject.sdk.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                      +    return status_ == null ? org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance() : status_;
                         }
                       
                         public static final int METADATA_FIELD_NUMBER = 4;
                      @@ -279,10 +279,10 @@ public boolean equals(final java.lang.Object obj) {
                           if (obj == this) {
                            return true;
                           }
                      -    if (!(obj instanceof io.a2a.grpc.TaskStatusUpdateEvent)) {
                      +    if (!(obj instanceof org.a2aproject.sdk.grpc.TaskStatusUpdateEvent)) {
                             return super.equals(obj);
                           }
                      -    io.a2a.grpc.TaskStatusUpdateEvent other = (io.a2a.grpc.TaskStatusUpdateEvent) obj;
                      +    org.a2aproject.sdk.grpc.TaskStatusUpdateEvent other = (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) obj;
                       
                           if (!getTaskId()
                               .equals(other.getTaskId())) return false;
                      @@ -326,44 +326,44 @@ public int hashCode() {
                           return hash;
                         }
                       
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(
                             java.nio.ByteBuffer data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(
                             java.nio.ByteBuffer data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(
                             com.google.protobuf.ByteString data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(
                             com.google.protobuf.ByteString data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(byte[] data)
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(byte[] data)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(
                             byte[] data,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws com.google.protobuf.InvalidProtocolBufferException {
                           return PARSER.parseFrom(data, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -371,26 +371,26 @@ public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                               .parseWithIOException(PARSER, input, extensionRegistry);
                         }
                       
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseDelimitedFrom(java.io.InputStream input)
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseDelimitedFrom(java.io.InputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input);
                         }
                       
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseDelimitedFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseDelimitedFrom(
                             java.io.InputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(
                             com.google.protobuf.CodedInputStream input)
                             throws java.io.IOException {
                           return com.google.protobuf.GeneratedMessage
                               .parseWithIOException(PARSER, input);
                         }
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent parseFrom(
                             com.google.protobuf.CodedInputStream input,
                             com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                             throws java.io.IOException {
                      @@ -403,7 +403,7 @@ public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(
                         public static Builder newBuilder() {
                           return DEFAULT_INSTANCE.toBuilder();
                         }
                      -  public static Builder newBuilder(io.a2a.grpc.TaskStatusUpdateEvent prototype) {
                      +  public static Builder newBuilder(org.a2aproject.sdk.grpc.TaskStatusUpdateEvent prototype) {
                           return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
                         }
                         @java.lang.Override
                      @@ -428,21 +428,21 @@ protected Builder newBuilderForType(
                         public static final class Builder extends
                             com.google.protobuf.GeneratedMessage.Builder implements
                             // @@protoc_insertion_point(builder_implements:lf.a2a.v1.TaskStatusUpdateEvent)
                      -      io.a2a.grpc.TaskStatusUpdateEventOrBuilder {
                      +      org.a2aproject.sdk.grpc.TaskStatusUpdateEventOrBuilder {
                           public static final com.google.protobuf.Descriptors.Descriptor
                               getDescriptor() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor;
                           }
                       
                           @java.lang.Override
                           protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
                               internalGetFieldAccessorTable() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable
                                 .ensureFieldAccessorsInitialized(
                      -              io.a2a.grpc.TaskStatusUpdateEvent.class, io.a2a.grpc.TaskStatusUpdateEvent.Builder.class);
                      +              org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.class, org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.Builder.class);
                           }
                       
                      -    // Construct using io.a2a.grpc.TaskStatusUpdateEvent.newBuilder()
                      +    // Construct using org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.newBuilder()
                           private Builder() {
                             maybeForceBuilderInitialization();
                           }
                      @@ -481,17 +481,17 @@ public Builder clear() {
                           @java.lang.Override
                           public com.google.protobuf.Descriptors.Descriptor
                               getDescriptorForType() {
                      -      return io.a2a.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor;
                      +      return org.a2aproject.sdk.grpc.A2A.internal_static_lf_a2a_v1_TaskStatusUpdateEvent_descriptor;
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskStatusUpdateEvent getDefaultInstanceForType() {
                      -      return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                      +    public org.a2aproject.sdk.grpc.TaskStatusUpdateEvent getDefaultInstanceForType() {
                      +      return org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance();
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskStatusUpdateEvent build() {
                      -      io.a2a.grpc.TaskStatusUpdateEvent result = buildPartial();
                      +    public org.a2aproject.sdk.grpc.TaskStatusUpdateEvent build() {
                      +      org.a2aproject.sdk.grpc.TaskStatusUpdateEvent result = buildPartial();
                             if (!result.isInitialized()) {
                               throw newUninitializedMessageException(result);
                             }
                      @@ -499,14 +499,14 @@ public io.a2a.grpc.TaskStatusUpdateEvent build() {
                           }
                       
                           @java.lang.Override
                      -    public io.a2a.grpc.TaskStatusUpdateEvent buildPartial() {
                      -      io.a2a.grpc.TaskStatusUpdateEvent result = new io.a2a.grpc.TaskStatusUpdateEvent(this);
                      +    public org.a2aproject.sdk.grpc.TaskStatusUpdateEvent buildPartial() {
                      +      org.a2aproject.sdk.grpc.TaskStatusUpdateEvent result = new org.a2aproject.sdk.grpc.TaskStatusUpdateEvent(this);
                             if (bitField0_ != 0) { buildPartial0(result); }
                             onBuilt();
                             return result;
                           }
                       
                      -    private void buildPartial0(io.a2a.grpc.TaskStatusUpdateEvent result) {
                      +    private void buildPartial0(org.a2aproject.sdk.grpc.TaskStatusUpdateEvent result) {
                             int from_bitField0_ = bitField0_;
                             if (((from_bitField0_ & 0x00000001) != 0)) {
                               result.taskId_ = taskId_;
                      @@ -532,16 +532,16 @@ private void buildPartial0(io.a2a.grpc.TaskStatusUpdateEvent result) {
                       
                           @java.lang.Override
                           public Builder mergeFrom(com.google.protobuf.Message other) {
                      -      if (other instanceof io.a2a.grpc.TaskStatusUpdateEvent) {
                      -        return mergeFrom((io.a2a.grpc.TaskStatusUpdateEvent)other);
                      +      if (other instanceof org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) {
                      +        return mergeFrom((org.a2aproject.sdk.grpc.TaskStatusUpdateEvent)other);
                             } else {
                               super.mergeFrom(other);
                               return this;
                             }
                           }
                       
                      -    public Builder mergeFrom(io.a2a.grpc.TaskStatusUpdateEvent other) {
                      -      if (other == io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance()) return this;
                      +    public Builder mergeFrom(org.a2aproject.sdk.grpc.TaskStatusUpdateEvent other) {
                      +      if (other == org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.getDefaultInstance()) return this;
                             if (!other.getTaskId().isEmpty()) {
                               taskId_ = other.taskId_;
                               bitField0_ |= 0x00000001;
                      @@ -809,9 +809,9 @@ public Builder setContextIdBytes(
                             return this;
                           }
                       
                      -    private io.a2a.grpc.TaskStatus status_;
                      +    private org.a2aproject.sdk.grpc.TaskStatus status_;
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> statusBuilder_;
                      +        org.a2aproject.sdk.grpc.TaskStatus, org.a2aproject.sdk.grpc.TaskStatus.Builder, org.a2aproject.sdk.grpc.TaskStatusOrBuilder> statusBuilder_;
                           /**
                            * 
                            * The new status of the task.
                      @@ -831,9 +831,9 @@ public boolean hasStatus() {
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            * @return The status.
                            */
                      -    public io.a2a.grpc.TaskStatus getStatus() {
                      +    public org.a2aproject.sdk.grpc.TaskStatus getStatus() {
                             if (statusBuilder_ == null) {
                      -        return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_;
                      +        return status_ == null ? org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance() : status_;
                             } else {
                               return statusBuilder_.getMessage();
                             }
                      @@ -845,7 +845,7 @@ public io.a2a.grpc.TaskStatus getStatus() {
                            *
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder setStatus(io.a2a.grpc.TaskStatus value) {
                      +    public Builder setStatus(org.a2aproject.sdk.grpc.TaskStatus value) {
                             if (statusBuilder_ == null) {
                               if (value == null) {
                                 throw new NullPointerException();
                      @@ -866,7 +866,7 @@ public Builder setStatus(io.a2a.grpc.TaskStatus value) {
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           public Builder setStatus(
                      -        io.a2a.grpc.TaskStatus.Builder builderForValue) {
                      +        org.a2aproject.sdk.grpc.TaskStatus.Builder builderForValue) {
                             if (statusBuilder_ == null) {
                               status_ = builderForValue.build();
                             } else {
                      @@ -883,11 +883,11 @@ public Builder setStatus(
                            *
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public Builder mergeStatus(io.a2a.grpc.TaskStatus value) {
                      +    public Builder mergeStatus(org.a2aproject.sdk.grpc.TaskStatus value) {
                             if (statusBuilder_ == null) {
                               if (((bitField0_ & 0x00000004) != 0) &&
                                 status_ != null &&
                      -          status_ != io.a2a.grpc.TaskStatus.getDefaultInstance()) {
                      +          status_ != org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance()) {
                                 getStatusBuilder().mergeFrom(value);
                               } else {
                                 status_ = value;
                      @@ -925,7 +925,7 @@ public Builder clearStatus() {
                            *
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskStatus.Builder getStatusBuilder() {
                             bitField0_ |= 0x00000004;
                             onChanged();
                             return internalGetStatusFieldBuilder().getBuilder();
                      @@ -937,12 +937,12 @@ public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() {
                            *
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                      -    public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                      +    public org.a2aproject.sdk.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                             if (statusBuilder_ != null) {
                               return statusBuilder_.getMessageOrBuilder();
                             } else {
                               return status_ == null ?
                      -            io.a2a.grpc.TaskStatus.getDefaultInstance() : status_;
                      +            org.a2aproject.sdk.grpc.TaskStatus.getDefaultInstance() : status_;
                             }
                           }
                           /**
                      @@ -953,11 +953,11 @@ public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() {
                            * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                            */
                           private com.google.protobuf.SingleFieldBuilder<
                      -        io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> 
                      +        org.a2aproject.sdk.grpc.TaskStatus, org.a2aproject.sdk.grpc.TaskStatus.Builder, org.a2aproject.sdk.grpc.TaskStatusOrBuilder> 
                               internalGetStatusFieldBuilder() {
                             if (statusBuilder_ == null) {
                               statusBuilder_ = new com.google.protobuf.SingleFieldBuilder<
                      -            io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder>(
                      +            org.a2aproject.sdk.grpc.TaskStatus, org.a2aproject.sdk.grpc.TaskStatus.Builder, org.a2aproject.sdk.grpc.TaskStatusOrBuilder>(
                                       getStatus(),
                                       getParentForChildren(),
                                       isClean());
                      @@ -1127,12 +1127,12 @@ public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() {
                         }
                       
                         // @@protoc_insertion_point(class_scope:lf.a2a.v1.TaskStatusUpdateEvent)
                      -  private static final io.a2a.grpc.TaskStatusUpdateEvent DEFAULT_INSTANCE;
                      +  private static final org.a2aproject.sdk.grpc.TaskStatusUpdateEvent DEFAULT_INSTANCE;
                         static {
                      -    DEFAULT_INSTANCE = new io.a2a.grpc.TaskStatusUpdateEvent();
                      +    DEFAULT_INSTANCE = new org.a2aproject.sdk.grpc.TaskStatusUpdateEvent();
                         }
                       
                      -  public static io.a2a.grpc.TaskStatusUpdateEvent getDefaultInstance() {
                      +  public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent getDefaultInstance() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      @@ -1168,7 +1168,7 @@ public com.google.protobuf.Parser getParserForType() {
                         }
                       
                         @java.lang.Override
                      -  public io.a2a.grpc.TaskStatusUpdateEvent getDefaultInstanceForType() {
                      +  public org.a2aproject.sdk.grpc.TaskStatusUpdateEvent getDefaultInstanceForType() {
                           return DEFAULT_INSTANCE;
                         }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusUpdateEventOrBuilder.java
                      similarity index 94%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusUpdateEventOrBuilder.java
                      index 155fee71a..06d729dff 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/TaskStatusUpdateEventOrBuilder.java
                      @@ -3,7 +3,7 @@
                       // source: a2a.proto
                       // Protobuf Java Version: 4.33.1
                       
                      -package io.a2a.grpc;
                      +package org.a2aproject.sdk.grpc;
                       
                       @com.google.protobuf.Generated
                       public interface TaskStatusUpdateEventOrBuilder extends
                      @@ -67,7 +67,7 @@ public interface TaskStatusUpdateEventOrBuilder extends
                          * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                          * @return The status.
                          */
                      -  io.a2a.grpc.TaskStatus getStatus();
                      +  org.a2aproject.sdk.grpc.TaskStatus getStatus();
                         /**
                          * 
                          * The new status of the task.
                      @@ -75,7 +75,7 @@ public interface TaskStatusUpdateEventOrBuilder extends
                          *
                          * .lf.a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED];
                          */
                      -  io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder();
                      +  org.a2aproject.sdk.grpc.TaskStatusOrBuilder getStatusOrBuilder();
                       
                         /**
                          * 
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2ACommonFieldMapper.java
                      similarity index 96%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2ACommonFieldMapper.java
                      index 15ba5f48f..7a5c277da 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2ACommonFieldMapper.java
                      @@ -1,4 +1,4 @@
                      -package io.a2a.grpc.mapper;
                      +package org.a2aproject.sdk.grpc.mapper;
                       
                       import java.time.Instant;
                       import java.time.OffsetDateTime;
                      @@ -14,7 +14,7 @@
                       import org.mapstruct.Mapper;
                       import org.mapstruct.Named;
                       
                      -import io.a2a.spec.InvalidParamsError;
                      +import org.a2aproject.sdk.spec.InvalidParamsError;
                       
                       /**
                        * Common field mapping utilities shared across all mappers.
                      @@ -438,21 +438,21 @@ default Instant protoTimestampToInstant(Timestamp timestamp) {
                            * @throws InvalidParamsError if state is UNRECOGNIZED (invalid enum value)
                            */
                           @Named("taskStateOrNull")
                      -    default io.a2a.spec.TaskState taskStateOrNull(io.a2a.grpc.TaskState state) {
                      -        if (state == null || state == io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED) {
                      +    default org.a2aproject.sdk.spec.TaskState taskStateOrNull(org.a2aproject.sdk.grpc.TaskState state) {
                      +        if (state == null || state == org.a2aproject.sdk.grpc.TaskState.TASK_STATE_UNSPECIFIED) {
                                   return null;
                               }
                               // Reject invalid enum values (e.g., "INVALID_STATUS" from JSON)
                      -        if (state == io.a2a.grpc.TaskState.UNRECOGNIZED) {
                      -            String validStates = java.util.Arrays.stream(io.a2a.spec.TaskState.values())
                      -                    .filter(s -> s != io.a2a.spec.TaskState.UNRECOGNIZED)
                      +        if (state == org.a2aproject.sdk.grpc.TaskState.UNRECOGNIZED) {
                      +            String validStates = java.util.Arrays.stream(org.a2aproject.sdk.spec.TaskState.values())
                      +                    .filter(s -> s != org.a2aproject.sdk.spec.TaskState.UNRECOGNIZED)
                                           .map(Enum::name)
                                           .collect(java.util.stream.Collectors.joining(", "));
                                   throw new InvalidParamsError(null,
                                       "Invalid task state value. Must be one of: " + validStates,
                                       null);
                               }
                      -        io.a2a.spec.TaskState result = TaskStateMapper.INSTANCE.fromProto(state);
                      +        org.a2aproject.sdk.spec.TaskState result = TaskStateMapper.INSTANCE.fromProto(state);
                               return result;
                           }
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AMappers.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2AMappers.java
                      similarity index 95%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AMappers.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2AMappers.java
                      index 25535b158..eab580898 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AMappers.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2AMappers.java
                      @@ -1,4 +1,4 @@
                      -package io.a2a.grpc.mapper;
                      +package org.a2aproject.sdk.grpc.mapper;
                       
                       import java.lang.reflect.Constructor;
                       import java.lang.reflect.InvocationTargetException;
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AProtoMapperConfig.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2AProtoMapperConfig.java
                      similarity index 98%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AProtoMapperConfig.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2AProtoMapperConfig.java
                      index dd7e77084..d2122924a 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AProtoMapperConfig.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/A2AProtoMapperConfig.java
                      @@ -1,4 +1,4 @@
                      -package io.a2a.grpc.mapper;
                      +package org.a2aproject.sdk.grpc.mapper;
                       
                       import java.nio.ByteBuffer;
                       import java.time.Instant;
                      @@ -36,7 +36,7 @@ public interface A2AProtoMapperConfig {
                           // 1. Enum Conversions
                           // ========================================================================
                       
                      -    default String map(io.a2a.spec.APIKeySecurityScheme.Location location) {
                      +    default String map(org.a2aproject.sdk.spec.APIKeySecurityScheme.Location location) {
                               return location == null ? null : location.asString();
                           }
                       
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/APIKeySecuritySchemeMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/APIKeySecuritySchemeMapper.java
                      similarity index 52%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/APIKeySecuritySchemeMapper.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/APIKeySecuritySchemeMapper.java
                      index 2b1a068f8..f6934dcc6 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/APIKeySecuritySchemeMapper.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/APIKeySecuritySchemeMapper.java
                      @@ -1,11 +1,11 @@
                      -package io.a2a.grpc.mapper;
                      +package org.a2aproject.sdk.grpc.mapper;
                       
                       import org.mapstruct.CollectionMappingStrategy;
                       import org.mapstruct.Mapper;
                       import org.mapstruct.Mapping;
                       
                       /**
                      - * Mapper between {@link io.a2a.spec.APIKeySecurityScheme} and {@link io.a2a.grpc.APIKeySecurityScheme}.
                      + * Mapper between {@link org.a2aproject.sdk.spec.APIKeySecurityScheme} and {@link org.a2aproject.sdk.grpc.APIKeySecurityScheme}.
                        */
                       @Mapper(config = A2AProtoMapperConfig.class,
                               collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
                      @@ -15,17 +15,17 @@ public interface APIKeySecuritySchemeMapper {
                       
                           // location enum is converted to string via ProtoMapperConfig.map(Location)
                           @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)")
                      -    io.a2a.grpc.APIKeySecurityScheme toProto(io.a2a.spec.APIKeySecurityScheme domain);
                      +    org.a2aproject.sdk.grpc.APIKeySecurityScheme toProto(org.a2aproject.sdk.spec.APIKeySecurityScheme domain);
                       
                      -    default io.a2a.spec.APIKeySecurityScheme fromProto(io.a2a.grpc.APIKeySecurityScheme proto) {
                      +    default org.a2aproject.sdk.spec.APIKeySecurityScheme fromProto(org.a2aproject.sdk.grpc.APIKeySecurityScheme proto) {
                               if (proto == null) {
                                   return null;
                               }
                       
                      -        io.a2a.spec.APIKeySecurityScheme.Location location =
                      -            io.a2a.spec.APIKeySecurityScheme.Location.fromString(proto.getLocation());
                      +        org.a2aproject.sdk.spec.APIKeySecurityScheme.Location location =
                      +            org.a2aproject.sdk.spec.APIKeySecurityScheme.Location.fromString(proto.getLocation());
                               String description = proto.getDescription().isEmpty() ? null : proto.getDescription();
                       
                      -        return new io.a2a.spec.APIKeySecurityScheme(location, proto.getName(), description);
                      +        return new org.a2aproject.sdk.spec.APIKeySecurityScheme(location, proto.getName(), description);
                           }
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCapabilitiesMapper.java
                      similarity index 51%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCapabilitiesMapper.java
                      index a8216fec8..d91db5256 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCapabilitiesMapper.java
                      @@ -1,10 +1,10 @@
                      -package io.a2a.grpc.mapper;
                      +package org.a2aproject.sdk.grpc.mapper;
                       
                       import org.mapstruct.CollectionMappingStrategy;
                       import org.mapstruct.Mapper;
                       
                       /**
                      - * Mapper between {@link io.a2a.spec.AgentCapabilities} and {@link io.a2a.grpc.AgentCapabilities}.
                      + * Mapper between {@link org.a2aproject.sdk.spec.AgentCapabilities} and {@link org.a2aproject.sdk.grpc.AgentCapabilities}.
                        */
                       @Mapper(config = A2AProtoMapperConfig.class,
                               collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
                      @@ -13,7 +13,7 @@ public interface AgentCapabilitiesMapper {
                       
                           AgentCapabilitiesMapper INSTANCE = A2AMappers.getMapper(AgentCapabilitiesMapper.class);
                       
                      -    io.a2a.grpc.AgentCapabilities toProto(io.a2a.spec.AgentCapabilities domain);
                      +    org.a2aproject.sdk.grpc.AgentCapabilities toProto(org.a2aproject.sdk.spec.AgentCapabilities domain);
                       
                      -    io.a2a.spec.AgentCapabilities fromProto(io.a2a.grpc.AgentCapabilities proto);
                      +    org.a2aproject.sdk.spec.AgentCapabilities fromProto(org.a2aproject.sdk.grpc.AgentCapabilities proto);
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java
                      similarity index 80%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java
                      index 268d54714..df9be2b6d 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java
                      @@ -1,11 +1,11 @@
                      -package io.a2a.grpc.mapper;
                      +package org.a2aproject.sdk.grpc.mapper;
                       
                       import org.mapstruct.CollectionMappingStrategy;
                       import org.mapstruct.Mapper;
                       import org.mapstruct.Mapping;
                       
                       /**
                      - * Mapper between {@link io.a2a.spec.AgentCard} and {@link io.a2a.grpc.AgentCard}.
                      + * Mapper between {@link org.a2aproject.sdk.spec.AgentCard} and {@link org.a2aproject.sdk.grpc.AgentCard}.
                        */
                       @Mapper(config = A2AProtoMapperConfig.class,
                               collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
                      @@ -25,10 +25,10 @@ public interface AgentCardMapper {
                           @Mapping(target = "provider", source = "provider", conditionExpression = "java(domain.provider() != null)")
                           @Mapping(target = "documentationUrl", source = "documentationUrl", conditionExpression = "java(domain.documentationUrl() != null)")
                           @Mapping(target = "iconUrl", source = "iconUrl", conditionExpression = "java(domain.iconUrl() != null)")
                      -    io.a2a.grpc.AgentCard toProto(io.a2a.spec.AgentCard domain);
                      +    org.a2aproject.sdk.grpc.AgentCard toProto(org.a2aproject.sdk.spec.AgentCard domain);
                       
                           @Mapping(target = "provider", source = "provider", conditionExpression = "java(proto.hasProvider())")
                           @Mapping(target = "documentationUrl", source = "documentationUrl", conditionExpression = "java(!proto.getDocumentationUrl().isEmpty())")
                           @Mapping(target = "iconUrl", source = "iconUrl", conditionExpression = "java(!proto.getIconUrl().isEmpty())")
                      -    io.a2a.spec.AgentCard fromProto(io.a2a.grpc.AgentCard proto);
                      +    org.a2aproject.sdk.spec.AgentCard fromProto(org.a2aproject.sdk.grpc.AgentCard proto);
                       }
                      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardSignatureMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardSignatureMapper.java
                      similarity index 76%
                      rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardSignatureMapper.java
                      rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardSignatureMapper.java
                      index b8b83d35b..e83a23d27 100644
                      --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardSignatureMapper.java
                      +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardSignatureMapper.java
                      @@ -1,11 +1,11 @@
                      -package io.a2a.grpc.mapper;
                      +package org.a2aproject.sdk.grpc.mapper;
                       
                       import org.mapstruct.CollectionMappingStrategy;
                       import org.mapstruct.Mapper;
                       import org.mapstruct.Mapping;
                       
                       /**
                      - * Mapper between {@link io.a2a.spec.AgentCardSignature} and {@link io.a2a.grpc.AgentCardSignature}.
                      + * Mapper between {@link org.a2aproject.sdk.spec.AgentCardSignature} and {@link org.a2aproject.sdk.grpc.AgentCardSignature}.
                        * 

                      * Uses CommonFieldMapper for struct conversion (header field). */ @@ -23,7 +23,7 @@ public interface AgentCardSignatureMapper { */ @Mapping(source = "protectedHeader", target = "protected") @Mapping(target = "header", source = "header", conditionExpression = "java(domain.header() != null)", qualifiedByName = "mapToStruct") - io.a2a.grpc.AgentCardSignature toProto(io.a2a.spec.AgentCardSignature domain); + org.a2aproject.sdk.grpc.AgentCardSignature toProto(org.a2aproject.sdk.spec.AgentCardSignature domain); /** * Converts proto AgentCardSignature to domain AgentCardSignature. @@ -32,5 +32,5 @@ public interface AgentCardSignatureMapper { */ @Mapping(source = "protected", target = "protectedHeader") @Mapping(target = "header", source = "header", qualifiedByName = "structToMap") - io.a2a.spec.AgentCardSignature fromProto(io.a2a.grpc.AgentCardSignature proto); + org.a2aproject.sdk.spec.AgentCardSignature fromProto(org.a2aproject.sdk.grpc.AgentCardSignature proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentExtensionMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentExtensionMapper.java similarity index 73% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentExtensionMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentExtensionMapper.java index c99c947c6..ff95b83b7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentExtensionMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentExtensionMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.AgentExtension} and {@link io.a2a.grpc.AgentExtension}. + * Mapper between {@link org.a2aproject.sdk.spec.AgentExtension} and {@link org.a2aproject.sdk.grpc.AgentExtension}. *

                      * Uses CommonFieldMapper for struct conversion (params field). */ @@ -22,7 +22,7 @@ public interface AgentExtensionMapper { * Maps params field via struct conversion. */ @Mapping(target = "params", source = "params", conditionExpression = "java(domain.params() != null)", qualifiedByName = "mapToStruct") - io.a2a.grpc.AgentExtension toProto(io.a2a.spec.AgentExtension domain); + org.a2aproject.sdk.grpc.AgentExtension toProto(org.a2aproject.sdk.spec.AgentExtension domain); /** * Converts proto AgentExtension to domain AgentExtension. @@ -30,5 +30,5 @@ public interface AgentExtensionMapper { * Maps params field from struct to map. */ @Mapping(target = "params", source = "params", qualifiedByName = "structToMap") - io.a2a.spec.AgentExtension fromProto(io.a2a.grpc.AgentExtension proto); + org.a2aproject.sdk.spec.AgentExtension fromProto(org.a2aproject.sdk.grpc.AgentExtension proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentInterfaceMapper.java similarity index 51% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentInterfaceMapper.java index 184a8c346..81b476088 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentInterfaceMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.AgentInterface} and {@link io.a2a.grpc.AgentInterface}. + * Mapper between {@link org.a2aproject.sdk.spec.AgentInterface} and {@link org.a2aproject.sdk.grpc.AgentInterface}. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) @@ -13,7 +13,7 @@ public interface AgentInterfaceMapper { AgentInterfaceMapper INSTANCE = A2AMappers.getMapper(AgentInterfaceMapper.class); - io.a2a.grpc.AgentInterface toProto(io.a2a.spec.AgentInterface domain); + org.a2aproject.sdk.grpc.AgentInterface toProto(org.a2aproject.sdk.spec.AgentInterface domain); - io.a2a.spec.AgentInterface fromProto(io.a2a.grpc.AgentInterface proto); + org.a2aproject.sdk.spec.AgentInterface fromProto(org.a2aproject.sdk.grpc.AgentInterface proto); } diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentProviderMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentProviderMapper.java new file mode 100644 index 000000000..4a0e7293c --- /dev/null +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentProviderMapper.java @@ -0,0 +1,18 @@ +package org.a2aproject.sdk.grpc.mapper; + +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapper; + +/** + * Mapper between {@link org.a2aproject.sdk.spec.AgentProvider} and {@link org.a2aproject.sdk.grpc.AgentProvider}. + */ +@Mapper(config = A2AProtoMapperConfig.class, + collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) +public interface AgentProviderMapper { + + AgentProviderMapper INSTANCE = A2AMappers.getMapper(AgentProviderMapper.class); + + org.a2aproject.sdk.grpc.AgentProvider toProto(org.a2aproject.sdk.spec.AgentProvider domain); + + org.a2aproject.sdk.spec.AgentProvider fromProto(org.a2aproject.sdk.grpc.AgentProvider proto); +} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentSkillMapper.java similarity index 53% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentSkillMapper.java index d56c572b8..ce091fe01 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentSkillMapper.java @@ -1,10 +1,10 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; /** - * Mapper between {@link io.a2a.spec.AgentSkill} and {@link io.a2a.grpc.AgentSkill}. + * Mapper between {@link org.a2aproject.sdk.spec.AgentSkill} and {@link org.a2aproject.sdk.grpc.AgentSkill}. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, @@ -13,7 +13,7 @@ public interface AgentSkillMapper { AgentSkillMapper INSTANCE = A2AMappers.getMapper(AgentSkillMapper.class); - io.a2a.grpc.AgentSkill toProto(io.a2a.spec.AgentSkill domain); + org.a2aproject.sdk.grpc.AgentSkill toProto(org.a2aproject.sdk.spec.AgentSkill domain); - io.a2a.spec.AgentSkill fromProto(io.a2a.grpc.AgentSkill proto); + org.a2aproject.sdk.spec.AgentSkill fromProto(org.a2aproject.sdk.grpc.AgentSkill proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ArtifactMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ArtifactMapper.java similarity index 84% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/ArtifactMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ArtifactMapper.java index b5efe8739..e6734883a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ArtifactMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ArtifactMapper.java @@ -1,12 +1,12 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.Artifact; +import org.a2aproject.sdk.spec.Artifact; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.Artifact} and {@link io.a2a.grpc.Artifact}. + * Mapper between {@link org.a2aproject.sdk.spec.Artifact} and {@link org.a2aproject.sdk.grpc.Artifact}. *

                      * Uses ADDER_PREFERRED strategy to use addAllExtensions() method instead of * trying to instantiate ProtocolStringList. Enables full compile-time validation! @@ -26,7 +26,7 @@ public interface ArtifactMapper { @Mapping(target = "name", source = "name", conditionExpression = "java(domain.name() != null)") @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.Artifact toProto(Artifact domain); + org.a2aproject.sdk.grpc.Artifact toProto(Artifact domain); /** * Converts proto Artifact to domain Artifact. @@ -37,5 +37,5 @@ public interface ArtifactMapper { @Mapping(target = "description", source = "description", qualifiedByName = "emptyToNull") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") @Mapping(target = "extensions", source = "extensions", qualifiedByName = "emptyListToNull") - Artifact fromProto(io.a2a.grpc.Artifact proto); + Artifact fromProto(org.a2aproject.sdk.grpc.Artifact proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AuthenticationInfoMapper.java similarity index 72% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AuthenticationInfoMapper.java index 1e50f6d3d..2a230bc8e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AuthenticationInfoMapper.java @@ -1,4 +1,4 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; @@ -6,7 +6,7 @@ import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.AuthenticationInfo} and {@link io.a2a.grpc.AuthenticationInfo}. + * Mapper between {@link org.a2aproject.sdk.spec.AuthenticationInfo} and {@link org.a2aproject.sdk.grpc.AuthenticationInfo}. *

                      * Maps between domain AuthenticationInfo (schemes as List of String) and proto AuthenticationInfo (scheme as String). * The proto scheme field is mapped to/from the first element of the domain schemes list. @@ -22,13 +22,13 @@ public interface AuthenticationInfoMapper { * Takes the first scheme from the schemes list. */ @Mapping(target = "credentials", source = "credentials", conditionExpression = "java(domain.credentials() != null)") - io.a2a.grpc.AuthenticationInfo toProto(io.a2a.spec.AuthenticationInfo domain); + org.a2aproject.sdk.grpc.AuthenticationInfo toProto(org.a2aproject.sdk.spec.AuthenticationInfo domain); /** * Converts proto AuthenticationInfo to domain AuthenticationInfo. * Wraps the single scheme in a list. */ - io.a2a.spec.AuthenticationInfo fromProto(io.a2a.grpc.AuthenticationInfo proto); + org.a2aproject.sdk.spec.AuthenticationInfo fromProto(org.a2aproject.sdk.grpc.AuthenticationInfo proto); } diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java new file mode 100644 index 000000000..2ab04ba8e --- /dev/null +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.grpc.mapper; + +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +/** + * Mapper between {@link org.a2aproject.sdk.spec.AuthorizationCodeOAuthFlow} and {@link org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow}. + */ +@Mapper(config = A2AProtoMapperConfig.class, + collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) +public interface AuthorizationCodeOAuthFlowMapper { + + AuthorizationCodeOAuthFlowMapper INSTANCE = A2AMappers.getMapper(AuthorizationCodeOAuthFlowMapper.class); + + org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow toProto(org.a2aproject.sdk.spec.AuthorizationCodeOAuthFlow domain); + + org.a2aproject.sdk.spec.AuthorizationCodeOAuthFlow fromProto(org.a2aproject.sdk.grpc.AuthorizationCodeOAuthFlow proto); +} diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ClientCredentialsOAuthFlowMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ClientCredentialsOAuthFlowMapper.java new file mode 100644 index 000000000..26aabf6ac --- /dev/null +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ClientCredentialsOAuthFlowMapper.java @@ -0,0 +1,18 @@ +package org.a2aproject.sdk.grpc.mapper; + +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapper; + +/** + * Mapper between {@link org.a2aproject.sdk.spec.ClientCredentialsOAuthFlow} and {@link org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow}. + */ +@Mapper(config = A2AProtoMapperConfig.class, + collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) +public interface ClientCredentialsOAuthFlowMapper { + + ClientCredentialsOAuthFlowMapper INSTANCE = A2AMappers.getMapper(ClientCredentialsOAuthFlowMapper.class); + + org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow toProto(org.a2aproject.sdk.spec.ClientCredentialsOAuthFlow domain); + + org.a2aproject.sdk.spec.ClientCredentialsOAuthFlow fromProto(org.a2aproject.sdk.grpc.ClientCredentialsOAuthFlow proto); +} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java similarity index 65% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java index 6e30f6eb9..18fc3ae9d 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java @@ -1,13 +1,13 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.grpc.DeleteTaskPushNotificationConfigRequest} and {@link io.a2a.spec.DeleteTaskPushNotificationConfigParams}. + * Mapper between {@link org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest} and {@link org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams}. */ @Mapper(config = A2AProtoMapperConfig.class) public interface DeleteTaskPushNotificationConfigParamsMapper { @@ -21,7 +21,7 @@ public interface DeleteTaskPushNotificationConfigParamsMapper { @Mapping(target = "taskId", source = "taskId") @Mapping(target = "id", source = "id") @Mapping(target = "tenant", source = "tenant") - DeleteTaskPushNotificationConfigParams fromProto(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest proto); + DeleteTaskPushNotificationConfigParams fromProto(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest proto); /** * Converts domain DeleteTaskPushNotificationConfigParams to proto DeleteTaskPushNotificationConfigRequest. @@ -29,5 +29,5 @@ public interface DeleteTaskPushNotificationConfigParamsMapper { @Mapping(target = "taskId", source = "taskId") @Mapping(target = "id", source = "id") @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest toProto(DeleteTaskPushNotificationConfigParams domain); + org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest toProto(DeleteTaskPushNotificationConfigParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java similarity index 66% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java index b9a8cad1b..9febadf56 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java @@ -1,13 +1,13 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.grpc.GetTaskPushNotificationConfigRequest} and {@link io.a2a.spec.GetTaskPushNotificationConfigParams}. + * Mapper between {@link org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest} and {@link org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams}. */ @Mapper(config = A2AProtoMapperConfig.class) public interface GetTaskPushNotificationConfigParamsMapper { @@ -21,7 +21,7 @@ public interface GetTaskPushNotificationConfigParamsMapper { @Mapping(target = "taskId", source = "taskId") @Mapping(target = "id", source = "id") @Mapping(target = "tenant", source = "tenant") - GetTaskPushNotificationConfigParams fromProto(io.a2a.grpc.GetTaskPushNotificationConfigRequest proto); + GetTaskPushNotificationConfigParams fromProto(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest proto); /** * Converts domain GetTaskPushNotificationConfigParams to proto GetTaskPushNotificationConfigRequest. @@ -29,5 +29,5 @@ public interface GetTaskPushNotificationConfigParamsMapper { @Mapping(target = "taskId", source = "taskId") @Mapping(target = "id", source = "id", conditionExpression = "java(domain.id() != null)") @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.GetTaskPushNotificationConfigRequest toProto(GetTaskPushNotificationConfigParams domain); + org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest toProto(GetTaskPushNotificationConfigParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/HTTPAuthSecuritySchemeMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/HTTPAuthSecuritySchemeMapper.java similarity index 63% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/HTTPAuthSecuritySchemeMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/HTTPAuthSecuritySchemeMapper.java index 4953635a1..261c32ce7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/HTTPAuthSecuritySchemeMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/HTTPAuthSecuritySchemeMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.HTTPAuthSecurityScheme} and {@link io.a2a.grpc.HTTPAuthSecurityScheme}. + * Mapper between {@link org.a2aproject.sdk.spec.HTTPAuthSecurityScheme} and {@link org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme}. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) @@ -15,9 +15,9 @@ public interface HTTPAuthSecuritySchemeMapper { @Mapping(target = "bearerFormat", source = "bearerFormat", conditionExpression = "java(domain.bearerFormat() != null)") @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - io.a2a.grpc.HTTPAuthSecurityScheme toProto(io.a2a.spec.HTTPAuthSecurityScheme domain); + org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme toProto(org.a2aproject.sdk.spec.HTTPAuthSecurityScheme domain); - default io.a2a.spec.HTTPAuthSecurityScheme fromProto(io.a2a.grpc.HTTPAuthSecurityScheme proto) { + default org.a2aproject.sdk.spec.HTTPAuthSecurityScheme fromProto(org.a2aproject.sdk.grpc.HTTPAuthSecurityScheme proto) { if (proto == null) { return null; } @@ -25,6 +25,6 @@ default io.a2a.spec.HTTPAuthSecurityScheme fromProto(io.a2a.grpc.HTTPAuthSecurit String bearerFormat = proto.getBearerFormat().isEmpty() ? null : proto.getBearerFormat(); String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); - return new io.a2a.spec.HTTPAuthSecurityScheme(bearerFormat, proto.getScheme(), description); + return new org.a2aproject.sdk.spec.HTTPAuthSecurityScheme(bearerFormat, proto.getScheme(), description); } } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigsParamsMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTaskPushNotificationConfigsParamsMapper.java similarity index 63% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigsParamsMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTaskPushNotificationConfigsParamsMapper.java index bf6e3cf79..635600bf2 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigsParamsMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTaskPushNotificationConfigsParamsMapper.java @@ -1,13 +1,13 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.grpc.ListTaskPushNotificationConfigsRequest} and {@link io.a2a.spec.ListTaskPushNotificationConfigsParams}. + * Mapper between {@link org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest} and {@link org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams}. */ @Mapper(config = A2AProtoMapperConfig.class) public interface ListTaskPushNotificationConfigsParamsMapper { @@ -20,12 +20,12 @@ public interface ListTaskPushNotificationConfigsParamsMapper { @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "taskId") @Mapping(target = "tenant", source = "tenant") - ListTaskPushNotificationConfigsParams fromProto(io.a2a.grpc.ListTaskPushNotificationConfigsRequest proto); + ListTaskPushNotificationConfigsParams fromProto(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest proto); /** * Converts domain ListTaskPushNotificationConfigsParams to proto ListTaskPushNotificationConfigsRequest. */ @Mapping(target = "taskId", source = "id") @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.ListTaskPushNotificationConfigsRequest toProto(ListTaskPushNotificationConfigsParams domain); + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest toProto(ListTaskPushNotificationConfigsParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTasksParamsMapper.java similarity index 91% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTasksParamsMapper.java index 06d4c2dd4..f9ffb8557 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTasksParamsMapper.java @@ -1,6 +1,6 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.grpc.ListTasksRequest; +import org.a2aproject.sdk.grpc.ListTasksRequest; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -28,7 +28,7 @@ public interface ListTasksParamsMapper { @Mapping(target = "historyLength", source = "historyLength", conditionExpression = "java(params.historyLength() != null)") @Mapping(target = "statusTimestampAfter", source = "statusTimestampAfter", qualifiedByName = "instantToProtoTimestamp") @Mapping(target = "includeArtifacts", source = "includeArtifacts", conditionExpression = "java(params.includeArtifacts() != null)") - ListTasksRequest toProto(io.a2a.spec.ListTasksParams params); + ListTasksRequest toProto(org.a2aproject.sdk.spec.ListTasksParams params); /** * Converts protobuf ListTasksRequest to domain ListTasksParams. @@ -45,5 +45,5 @@ public interface ListTasksParamsMapper { @Mapping(target = "historyLength", expression = "java(request.hasHistoryLength() ? request.getHistoryLength() : null)") @Mapping(target = "statusTimestampAfter", source = "statusTimestampAfter", qualifiedByName = "protoTimestampToInstant") @Mapping(target = "includeArtifacts", source = "includeArtifacts", qualifiedByName = "falseToNull") - io.a2a.spec.ListTasksParams fromProto(ListTasksRequest request); + org.a2aproject.sdk.spec.ListTasksParams fromProto(ListTasksRequest request); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTasksResultMapper.java similarity index 72% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTasksResultMapper.java index 599877002..637800991 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ListTasksResultMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link ListTasksResult} and {@link io.a2a.grpc.ListTasksResponse}. + * Mapper between {@link ListTasksResult} and {@link org.a2aproject.sdk.grpc.ListTasksResponse}. *

                      * Handles conversion with null handling for nextPageToken field. * Uses ADDER_PREFERRED strategy to avoid ProtocolMessageList instantiation issues. @@ -22,8 +22,8 @@ public interface ListTasksResultMapper { * Protobuf builders don't accept null, so nextPageToken is conditionally mapped. */ @Mapping(target = "nextPageToken", source = "nextPageToken", conditionExpression = "java(domain.nextPageToken() != null)") - io.a2a.grpc.ListTasksResponse toProto(ListTasksResult domain); + org.a2aproject.sdk.grpc.ListTasksResponse toProto(ListTasksResult domain); @Mapping(source = "nextPageToken", target = "nextPageToken", conditionExpression = "java(proto.getNextPageToken() != null)") - ListTasksResult fromProto(io.a2a.grpc.ListTasksResponse proto); + ListTasksResult fromProto(org.a2aproject.sdk.grpc.ListTasksResponse proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageMapper.java similarity index 74% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageMapper.java index 47cf84f03..05b2bfccf 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageMapper.java @@ -1,6 +1,6 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.Message; +import org.a2aproject.sdk.spec.Message; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.CollectionMappingStrategy; @@ -8,7 +8,7 @@ import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.Message} and {@link io.a2a.grpc.Message}. + * Mapper between {@link org.a2aproject.sdk.spec.Message} and {@link org.a2aproject.sdk.grpc.Message}. *

                      * Uses ADDER_PREFERRED strategy for List fields (parts, extensions, referenceTaskIds) * to avoid ProtocolStringList instantiation issues. @@ -28,7 +28,7 @@ public interface MessageMapper { @Mapping(target = "contextId", source = "contextId", conditionExpression = "java(domain.contextId() != null)") @Mapping(target = "taskId", source = "taskId", conditionExpression = "java(domain.taskId() != null)") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.Message toProto(Message domain); + org.a2aproject.sdk.grpc.Message toProto(Message domain); /** * Converts proto Message to domain Message. @@ -40,7 +40,7 @@ public interface MessageMapper { @Mapping(target = "contextId", source = "contextId", qualifiedByName = "emptyToNull") @Mapping(target = "taskId", source = "taskId", qualifiedByName = "emptyToNull") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - @Mapping(target = "extensions", expression = "java(io.a2a.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getExtensionsList()))") - @Mapping(target = "referenceTaskIds", expression = "java(io.a2a.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getReferenceTaskIdsList()))") - Message fromProto(io.a2a.grpc.Message proto); + @Mapping(target = "extensions", expression = "java(org.a2aproject.sdk.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getExtensionsList()))") + @Mapping(target = "referenceTaskIds", expression = "java(org.a2aproject.sdk.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getReferenceTaskIdsList()))") + Message fromProto(org.a2aproject.sdk.grpc.Message proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageSendConfigurationMapper.java similarity index 70% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageSendConfigurationMapper.java index 138ad346a..8e291caf6 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageSendConfigurationMapper.java @@ -1,6 +1,6 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendConfiguration; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.CollectionMappingStrategy; @@ -8,7 +8,7 @@ import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.MessageSendConfiguration} and {@link io.a2a.grpc.SendMessageConfiguration}. + * Mapper between {@link org.a2aproject.sdk.spec.MessageSendConfiguration} and {@link org.a2aproject.sdk.grpc.SendMessageConfiguration}. *

                      * Handles bidirectional mapping with null/empty list conversions and task push notification config delegation. * Uses ADDER_PREFERRED strategy to avoid ProtocolStringList instantiation issues. @@ -24,13 +24,13 @@ public interface MessageSendConfigurationMapper { * Converts domain MessageSendConfiguration to proto SendMessageConfiguration. */ @Mapping(target = "taskPushNotificationConfig", source = "taskPushNotificationConfig", conditionExpression = "java(domain.taskPushNotificationConfig() != null)") - io.a2a.grpc.SendMessageConfiguration toProto(MessageSendConfiguration domain); + org.a2aproject.sdk.grpc.SendMessageConfiguration toProto(MessageSendConfiguration domain); /** * Converts proto SendMessageConfiguration to domain MessageSendConfiguration. * Uses Builder pattern for record construction. */ @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "acceptedOutputModes", expression = "java(io.a2a.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getAcceptedOutputModesList()))") - MessageSendConfiguration fromProto(io.a2a.grpc.SendMessageConfiguration proto); + @Mapping(target = "acceptedOutputModes", expression = "java(org.a2aproject.sdk.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getAcceptedOutputModesList()))") + MessageSendConfiguration fromProto(org.a2aproject.sdk.grpc.SendMessageConfiguration proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageSendParamsMapper.java similarity index 76% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageSendParamsMapper.java index 11885ac11..78bec7580 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MessageSendParamsMapper.java @@ -1,13 +1,13 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.MessageSendParams; +import org.a2aproject.sdk.spec.MessageSendParams; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.MessageSendParams} and {@link io.a2a.grpc.SendMessageRequest}. + * Mapper between {@link org.a2aproject.sdk.spec.MessageSendParams} and {@link org.a2aproject.sdk.grpc.SendMessageRequest}. *

                      * Handles bidirectional mapping with message/request field name difference and Struct conversions. */ @@ -22,7 +22,7 @@ public interface MessageSendParamsMapper { */ @Mapping(target = "configuration", source = "configuration", conditionExpression = "java(domain.configuration() != null)") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.SendMessageRequest toProto(MessageSendParams domain); + org.a2aproject.sdk.grpc.SendMessageRequest toProto(MessageSendParams domain); /** * Converts proto SendMessageRequest to domain MessageSendParams. @@ -31,5 +31,5 @@ public interface MessageSendParamsMapper { */ @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - MessageSendParams fromProto(io.a2a.grpc.SendMessageRequest proto); + MessageSendParams fromProto(org.a2aproject.sdk.grpc.SendMessageRequest proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MutualTLSSecuritySchemeMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MutualTLSSecuritySchemeMapper.java similarity index 57% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/MutualTLSSecuritySchemeMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MutualTLSSecuritySchemeMapper.java index c6155d580..4a56fc926 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MutualTLSSecuritySchemeMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/MutualTLSSecuritySchemeMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.MutualTLSSecurityScheme} and {@link io.a2a.grpc.MutualTlsSecurityScheme}. + * Mapper between {@link org.a2aproject.sdk.spec.MutualTLSSecurityScheme} and {@link org.a2aproject.sdk.grpc.MutualTlsSecurityScheme}. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) @@ -14,15 +14,15 @@ public interface MutualTLSSecuritySchemeMapper { MutualTLSSecuritySchemeMapper INSTANCE = A2AMappers.getMapper(MutualTLSSecuritySchemeMapper.class); @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - io.a2a.grpc.MutualTlsSecurityScheme toProto(io.a2a.spec.MutualTLSSecurityScheme domain); + org.a2aproject.sdk.grpc.MutualTlsSecurityScheme toProto(org.a2aproject.sdk.spec.MutualTLSSecurityScheme domain); - default io.a2a.spec.MutualTLSSecurityScheme fromProto(io.a2a.grpc.MutualTlsSecurityScheme proto) { + default org.a2aproject.sdk.spec.MutualTLSSecurityScheme fromProto(org.a2aproject.sdk.grpc.MutualTlsSecurityScheme proto) { if (proto == null) { return null; } String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); - return new io.a2a.spec.MutualTLSSecurityScheme(description); + return new org.a2aproject.sdk.spec.MutualTLSSecurityScheme(description); } } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuth2SecuritySchemeMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OAuth2SecuritySchemeMapper.java similarity index 61% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuth2SecuritySchemeMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OAuth2SecuritySchemeMapper.java index 088cb509d..cae76a12b 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuth2SecuritySchemeMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OAuth2SecuritySchemeMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.OAuth2SecurityScheme} and {@link io.a2a.grpc.OAuth2SecurityScheme}. + * Mapper between {@link org.a2aproject.sdk.spec.OAuth2SecurityScheme} and {@link org.a2aproject.sdk.grpc.OAuth2SecurityScheme}. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, @@ -16,17 +16,17 @@ public interface OAuth2SecuritySchemeMapper { @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") @Mapping(target = "oauth2MetadataUrl", source = "oauth2MetadataUrl", conditionExpression = "java(domain.oauth2MetadataUrl() != null)") - io.a2a.grpc.OAuth2SecurityScheme toProto(io.a2a.spec.OAuth2SecurityScheme domain); + org.a2aproject.sdk.grpc.OAuth2SecurityScheme toProto(org.a2aproject.sdk.spec.OAuth2SecurityScheme domain); - default io.a2a.spec.OAuth2SecurityScheme fromProto(io.a2a.grpc.OAuth2SecurityScheme proto) { + default org.a2aproject.sdk.spec.OAuth2SecurityScheme fromProto(org.a2aproject.sdk.grpc.OAuth2SecurityScheme proto) { if (proto == null) { return null; } - io.a2a.spec.OAuthFlows flows = OAuthFlowsMapper.INSTANCE.fromProto(proto.getFlows()); + org.a2aproject.sdk.spec.OAuthFlows flows = OAuthFlowsMapper.INSTANCE.fromProto(proto.getFlows()); String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); String oauth2MetadataUrl = proto.getOauth2MetadataUrl().isEmpty() ? null : proto.getOauth2MetadataUrl(); - return new io.a2a.spec.OAuth2SecurityScheme(flows, description, oauth2MetadataUrl); + return new org.a2aproject.sdk.spec.OAuth2SecurityScheme(flows, description, oauth2MetadataUrl); } } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OAuthFlowsMapper.java similarity index 63% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OAuthFlowsMapper.java index 66894d49a..ecea584a4 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OAuthFlowsMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.OAuthFlows} and {@link io.a2a.grpc.OAuthFlows}. + * Mapper between {@link org.a2aproject.sdk.spec.OAuthFlows} and {@link org.a2aproject.sdk.grpc.OAuthFlows}. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, @@ -19,7 +19,7 @@ public interface OAuthFlowsMapper { @Mapping(target = "implicit", ignore = true) @Mapping(target = "password", ignore = true) - io.a2a.grpc.OAuthFlows toProto(io.a2a.spec.OAuthFlows domain); + org.a2aproject.sdk.grpc.OAuthFlows toProto(org.a2aproject.sdk.spec.OAuthFlows domain); - io.a2a.spec.OAuthFlows fromProto(io.a2a.grpc.OAuthFlows proto); + org.a2aproject.sdk.spec.OAuthFlows fromProto(org.a2aproject.sdk.grpc.OAuthFlows proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java similarity index 55% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java index da1dd2d6b..a526a9308 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.OpenIdConnectSecurityScheme} and {@link io.a2a.grpc.OpenIdConnectSecurityScheme}. + * Mapper between {@link org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme} and {@link org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme}. */ @Mapper(config = A2AProtoMapperConfig.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) @@ -14,15 +14,15 @@ public interface OpenIdConnectSecuritySchemeMapper { OpenIdConnectSecuritySchemeMapper INSTANCE = A2AMappers.getMapper(OpenIdConnectSecuritySchemeMapper.class); @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - io.a2a.grpc.OpenIdConnectSecurityScheme toProto(io.a2a.spec.OpenIdConnectSecurityScheme domain); + org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme toProto(org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme domain); - default io.a2a.spec.OpenIdConnectSecurityScheme fromProto(io.a2a.grpc.OpenIdConnectSecurityScheme proto) { + default org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme fromProto(org.a2aproject.sdk.grpc.OpenIdConnectSecurityScheme proto) { if (proto == null) { return null; } String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); - return new io.a2a.spec.OpenIdConnectSecurityScheme(proto.getOpenIdConnectUrl(), description); + return new org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme(proto.getOpenIdConnectUrl(), description); } } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/PartMapper.java similarity index 86% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/PartMapper.java index 79748f3c2..cd8fb8600 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/PartMapper.java @@ -1,22 +1,22 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import java.util.Base64; import com.google.protobuf.ByteString; import com.google.protobuf.Value; -import io.a2a.spec.DataPart; -import io.a2a.spec.FileContent; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.FileContent; +import org.a2aproject.sdk.spec.FilePart; +import org.a2aproject.sdk.spec.FileWithBytes; +import org.a2aproject.sdk.spec.FileWithUri; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import java.util.Map; import org.mapstruct.Mapper; /** - * Mapper between {@link io.a2a.spec.Part} and {@link io.a2a.grpc.Part}. + * Mapper between {@link org.a2aproject.sdk.spec.Part} and {@link org.a2aproject.sdk.grpc.Part}. *

                      * Handles polymorphic Part conversion using the proto's oneof content field: *

                        @@ -38,12 +38,12 @@ public interface PartMapper { * Converts domain Part to proto Part. * Handles TextPart, FilePart (FileWithBytes and FileWithUri), and DataPart polymorphism. */ - default io.a2a.grpc.Part toProto(Part domain) { + default org.a2aproject.sdk.grpc.Part toProto(Part domain) { if (domain == null) { return null; } - io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + org.a2aproject.sdk.grpc.Part.Builder builder = org.a2aproject.sdk.grpc.Part.newBuilder(); if (domain instanceof TextPart textPart) { builder.setText(textPart.text()); @@ -85,7 +85,7 @@ default io.a2a.grpc.Part toProto(Part domain) { * Converts proto Part to domain Part. * Reconstructs TextPart, FilePart, or DataPart based on oneof content field. */ - default Part fromProto(io.a2a.grpc.Part proto) { + default Part fromProto(org.a2aproject.sdk.grpc.Part proto) { if (proto == null) { return null; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ResourceNameParser.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ResourceNameParser.java similarity index 98% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/ResourceNameParser.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ResourceNameParser.java index ba7303a74..653fe79de 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ResourceNameParser.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/ResourceNameParser.java @@ -1,4 +1,4 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; /** * Utility class for parsing gRPC resource names. diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/RoleMapper.java similarity index 63% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/RoleMapper.java index 8ff59552c..e327c6be3 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/RoleMapper.java @@ -1,11 +1,11 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.grpc.Role; -import io.a2a.spec.Message; +import org.a2aproject.sdk.grpc.Role; +import org.a2aproject.sdk.spec.Message; import org.mapstruct.Mapper; /** - * Mapper between {@link io.a2a.spec.Message.Role} and {@link io.a2a.grpc.Role}. + * Mapper between {@link org.a2aproject.sdk.spec.Message.Role} and {@link org.a2aproject.sdk.grpc.Role}. *

                        * Handles enum conversion between domain and protobuf role representations: *

                          @@ -25,13 +25,13 @@ public interface RoleMapper { /** * Converts domain Role to proto Role. */ - default io.a2a.grpc.Role toProto(Message.Role domain) { + default org.a2aproject.sdk.grpc.Role toProto(Message.Role domain) { if (domain == null) { - return io.a2a.grpc.Role.ROLE_UNSPECIFIED; + return org.a2aproject.sdk.grpc.Role.ROLE_UNSPECIFIED; } return switch (domain) { - case ROLE_USER -> io.a2a.grpc.Role.ROLE_USER; - case ROLE_AGENT -> io.a2a.grpc.Role.ROLE_AGENT; + case ROLE_USER -> org.a2aproject.sdk.grpc.Role.ROLE_USER; + case ROLE_AGENT -> org.a2aproject.sdk.grpc.Role.ROLE_AGENT; case ROLE_UNSPECIFIED -> Role.ROLE_UNSPECIFIED; }; } @@ -39,8 +39,8 @@ default io.a2a.grpc.Role toProto(Message.Role domain) { /** * Converts proto Role to domain Role. */ - default Message.Role fromProto(io.a2a.grpc.Role proto) { - if (proto == null || proto == io.a2a.grpc.Role.ROLE_UNSPECIFIED) { + default Message.Role fromProto(org.a2aproject.sdk.grpc.Role proto) { + if (proto == null || proto == org.a2aproject.sdk.grpc.Role.ROLE_UNSPECIFIED) { return null; } return switch (proto) { diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SecurityRequirementMapper.java similarity index 77% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SecurityRequirementMapper.java index 8f9f98fe6..18bc645f9 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SecurityRequirementMapper.java @@ -1,4 +1,4 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -6,7 +6,7 @@ import java.util.Map; import com.google.protobuf.ProtocolStringList; -import io.a2a.grpc.StringList; +import org.a2aproject.sdk.grpc.StringList; import org.mapstruct.Mapper; /** @@ -46,12 +46,12 @@ public interface SecurityRequirementMapper { * @param domainRequirement domain SecurityRequirement with schemes map * @return SecurityRequirement proto message, or null if input is null */ - default io.a2a.grpc.SecurityRequirement mapSecurityRequirement(io.a2a.spec.SecurityRequirement domainRequirement) { + default org.a2aproject.sdk.grpc.SecurityRequirement mapSecurityRequirement(org.a2aproject.sdk.spec.SecurityRequirement domainRequirement) { if (domainRequirement == null) { return null; } - io.a2a.grpc.SecurityRequirement.Builder securityBuilder = io.a2a.grpc.SecurityRequirement.newBuilder(); + org.a2aproject.sdk.grpc.SecurityRequirement.Builder securityBuilder = org.a2aproject.sdk.grpc.SecurityRequirement.newBuilder(); Map> schemes = domainRequirement.schemes(); if (schemes != null) { for (Map.Entry> entry : schemes.entrySet()) { @@ -74,13 +74,13 @@ default io.a2a.grpc.SecurityRequirement mapSecurityRequirement(io.a2a.spec.Secur * @param domainSecurity list of SecurityRequirement domain objects * @return list of SecurityRequirement proto messages, or null if input is null */ - default List toProto(List domainSecurity) { + default List toProto(List domainSecurity) { if (domainSecurity == null) { return null; } - List protoList = new ArrayList<>(domainSecurity.size()); - for (io.a2a.spec.SecurityRequirement requirement : domainSecurity) { + List protoList = new ArrayList<>(domainSecurity.size()); + for (org.a2aproject.sdk.spec.SecurityRequirement requirement : domainSecurity) { protoList.add(mapSecurityRequirement(requirement)); } return protoList; @@ -92,20 +92,20 @@ default List toProto(List fromProto(List protoSecurity) { + default List fromProto(List protoSecurity) { if (protoSecurity == null) { return null; } - List domainList = new ArrayList<>(protoSecurity.size()); - for (io.a2a.grpc.SecurityRequirement security : protoSecurity) { + List domainList = new ArrayList<>(protoSecurity.size()); + for (org.a2aproject.sdk.grpc.SecurityRequirement security : protoSecurity) { Map> schemeMap = new LinkedHashMap<>(); for (Map.Entry entry : security.getSchemesMap().entrySet()) { ProtocolStringList listList = entry.getValue().getListList(); List values = new ArrayList<>(listList); schemeMap.put(entry.getKey(), values); } - domainList.add(new io.a2a.spec.SecurityRequirement(schemeMap)); + domainList.add(new org.a2aproject.sdk.spec.SecurityRequirement(schemeMap)); } return domainList; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecuritySchemeMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SecuritySchemeMapper.java similarity index 80% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/SecuritySchemeMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SecuritySchemeMapper.java index 723762785..5c15e944f 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecuritySchemeMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SecuritySchemeMapper.java @@ -1,15 +1,15 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.APIKeySecurityScheme; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.MutualTLSSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OpenIdConnectSecurityScheme; +import org.a2aproject.sdk.spec.APIKeySecurityScheme; +import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; +import org.a2aproject.sdk.spec.MutualTLSSecurityScheme; +import org.a2aproject.sdk.spec.OAuth2SecurityScheme; +import org.a2aproject.sdk.spec.OpenIdConnectSecurityScheme; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; /** - * Mapper between {@link io.a2a.spec.SecurityScheme} and {@link io.a2a.grpc.SecurityScheme}. + * Mapper between {@link org.a2aproject.sdk.spec.SecurityScheme} and {@link org.a2aproject.sdk.grpc.SecurityScheme}. *

                          * This mapper handles the polymorphic sealed interface SecurityScheme by using a custom * default method with switch expression. MapStruct doesn't natively support sealed interfaces @@ -41,29 +41,29 @@ public interface SecuritySchemeMapper { * @param domain the domain security scheme (sealed interface) * @return the protobuf SecurityScheme with the appropriate oneof field set */ - default io.a2a.grpc.SecurityScheme toProto(io.a2a.spec.SecurityScheme domain) { + default org.a2aproject.sdk.grpc.SecurityScheme toProto(org.a2aproject.sdk.spec.SecurityScheme domain) { if (domain == null) { return null; } if (domain instanceof APIKeySecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() + return org.a2aproject.sdk.grpc.SecurityScheme.newBuilder() .setApiKeySecurityScheme(APIKeySecuritySchemeMapper.INSTANCE.toProto(s)) .build(); } else if (domain instanceof HTTPAuthSecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() + return org.a2aproject.sdk.grpc.SecurityScheme.newBuilder() .setHttpAuthSecurityScheme(HTTPAuthSecuritySchemeMapper.INSTANCE.toProto(s)) .build(); } else if (domain instanceof OAuth2SecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() + return org.a2aproject.sdk.grpc.SecurityScheme.newBuilder() .setOauth2SecurityScheme(OAuth2SecuritySchemeMapper.INSTANCE.toProto(s)) .build(); } else if (domain instanceof OpenIdConnectSecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() + return org.a2aproject.sdk.grpc.SecurityScheme.newBuilder() .setOpenIdConnectSecurityScheme(OpenIdConnectSecuritySchemeMapper.INSTANCE.toProto(s)) .build(); } else if (domain instanceof MutualTLSSecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() + return org.a2aproject.sdk.grpc.SecurityScheme.newBuilder() .setMtlsSecurityScheme(MutualTLSSecuritySchemeMapper.INSTANCE.toProto(s)) .build(); } @@ -81,7 +81,7 @@ default io.a2a.grpc.SecurityScheme toProto(io.a2a.spec.SecurityScheme domain) { * @param proto the protobuf SecurityScheme with a oneof field set * @return the domain security scheme (sealed interface implementation) */ - default io.a2a.spec.SecurityScheme fromProto(io.a2a.grpc.SecurityScheme proto) { + default org.a2aproject.sdk.spec.SecurityScheme fromProto(org.a2aproject.sdk.grpc.SecurityScheme proto) { if (proto == null) { return null; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/StreamResponseMapper.java similarity index 75% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/StreamResponseMapper.java index 07eacb148..9028ad0d6 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/StreamResponseMapper.java @@ -1,14 +1,14 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.mapstruct.Mapper; /** - * Mapper between {@link io.a2a.spec.StreamingEventKind} and {@link io.a2a.grpc.StreamResponse}. + * Mapper between {@link org.a2aproject.sdk.spec.StreamingEventKind} and {@link org.a2aproject.sdk.grpc.StreamResponse}. *

                          * StreamResponse uses a protobuf oneof field to represent polymorphic streaming events. * StreamingEventKind is a sealed interface with four permitted implementations: @@ -35,22 +35,22 @@ public interface StreamResponseMapper { * @param domain the streaming event kind (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent) * @return the proto StreamResponse with the appropriate oneof field set */ - default io.a2a.grpc.StreamResponse toProto(StreamingEventKind domain) { + default org.a2aproject.sdk.grpc.StreamResponse toProto(StreamingEventKind domain) { if (domain == null) { return null; } return switch (domain.kind()) { - case Task.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() + case Task.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.StreamResponse.newBuilder() .setTask(TaskMapper.INSTANCE.toProto((Task) domain)) .build(); - case Message.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() + case Message.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.StreamResponse.newBuilder() .setMessage(MessageMapper.INSTANCE.toProto((Message) domain)) .build(); - case TaskStatusUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() + case TaskStatusUpdateEvent.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.StreamResponse.newBuilder() .setStatusUpdate(TaskStatusUpdateEventMapper.INSTANCE.toProto((TaskStatusUpdateEvent) domain)) .build(); - case TaskArtifactUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() + case TaskArtifactUpdateEvent.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.StreamResponse.newBuilder() .setArtifactUpdate(TaskArtifactUpdateEventMapper.INSTANCE.toProto((TaskArtifactUpdateEvent) domain)) .build(); default -> @@ -66,7 +66,7 @@ default io.a2a.grpc.StreamResponse toProto(StreamingEventKind domain) { * @return the corresponding domain streaming event kind * @throws IllegalArgumentException if the oneof field is not set */ - default StreamingEventKind fromProto(io.a2a.grpc.StreamResponse proto) { + default StreamingEventKind fromProto(org.a2aproject.sdk.grpc.StreamResponse proto) { if (proto == null) { return null; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SubscribeToTaskRequestMapper.java similarity index 74% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SubscribeToTaskRequestMapper.java index c21d1d8a7..90fe97ade 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/SubscribeToTaskRequestMapper.java @@ -1,10 +1,10 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SubscribeToTaskRequest; import org.mapstruct.Mapper; /** - * Mapper between {@link SubscribeToTaskRequest} and {@link io.a2a.grpc.SubscribeToTaskRequest}. + * Mapper between {@link SubscribeToTaskRequest} and {@link org.a2aproject.sdk.grpc.SubscribeToTaskRequest}. *

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

                            @@ -28,11 +28,11 @@ public interface SubscribeToTaskRequestMapper { * @param domain the domain SubscribeToTaskRequest * @return the proto SubscribeToTaskRequest */ - default io.a2a.grpc.SubscribeToTaskRequest toProto(SubscribeToTaskRequest domain) { + default org.a2aproject.sdk.grpc.SubscribeToTaskRequest toProto(SubscribeToTaskRequest domain) { if (domain == null || domain.getParams() == null || domain.getParams().id() == null) { return null; } - return io.a2a.grpc.SubscribeToTaskRequest.newBuilder() + return org.a2aproject.sdk.grpc.SubscribeToTaskRequest.newBuilder() .setId(domain.getParams().id()) .build(); } @@ -44,12 +44,12 @@ default io.a2a.grpc.SubscribeToTaskRequest toProto(SubscribeToTaskRequest domain * @param proto the proto SubscribeToTaskRequest * @return the domain SubscribeToTaskRequest */ - default SubscribeToTaskRequest fromProto(io.a2a.grpc.SubscribeToTaskRequest proto) { + default SubscribeToTaskRequest fromProto(org.a2aproject.sdk.grpc.SubscribeToTaskRequest proto) { if (proto == null || proto.getId()== null) { return null; } return SubscribeToTaskRequest.builder() - .params(new io.a2a.spec.TaskIdParams(proto.getId())) + .params(new org.a2aproject.sdk.spec.TaskIdParams(proto.getId())) .build(); } } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskArtifactUpdateEventMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskArtifactUpdateEventMapper.java similarity index 74% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskArtifactUpdateEventMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskArtifactUpdateEventMapper.java index 2c52d80d2..4e262a27e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskArtifactUpdateEventMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskArtifactUpdateEventMapper.java @@ -1,13 +1,13 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.TaskArtifactUpdateEvent} and {@link io.a2a.grpc.TaskArtifactUpdateEvent}. + * Mapper between {@link org.a2aproject.sdk.spec.TaskArtifactUpdateEvent} and {@link org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent}. *

                            * Now fully declarative using Builder pattern with @BeanMapping. */ @@ -23,7 +23,7 @@ public interface TaskArtifactUpdateEventMapper { @Mapping(target = "append", source = "append", conditionExpression = "java(domain.append() != null)") @Mapping(target = "lastChunk", source = "lastChunk", conditionExpression = "java(domain.lastChunk() != null)") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.TaskArtifactUpdateEvent toProto(TaskArtifactUpdateEvent domain); + org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent toProto(TaskArtifactUpdateEvent domain); /** * Converts proto TaskArtifactUpdateEvent to domain. @@ -31,5 +31,5 @@ public interface TaskArtifactUpdateEventMapper { */ @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - TaskArtifactUpdateEvent fromProto(io.a2a.grpc.TaskArtifactUpdateEvent proto); + TaskArtifactUpdateEvent fromProto(org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskIdParamsMapper.java similarity index 71% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskIdParamsMapper.java index 15522ce72..b42d9379a 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskIdParamsMapper.java @@ -1,14 +1,14 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.TaskIdParams; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.TaskIdParams; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper for {@link io.a2a.spec.TaskIdParams} from various gRPC request types. + * Mapper for {@link org.a2aproject.sdk.spec.TaskIdParams} from various gRPC request types. *

                            * Extracts task ID from resource name format "tasks/{id}" using {@link ResourceNameParser}. */ @@ -24,7 +24,7 @@ public interface TaskIdParamsMapper { @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "id") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - CancelTaskParams fromProtoCancelTaskRequest(io.a2a.grpc.CancelTaskRequest proto); + CancelTaskParams fromProtoCancelTaskRequest(org.a2aproject.sdk.grpc.CancelTaskRequest proto); /** * Converts proto CancelTaskRequest to domain TaskIdParams. @@ -33,7 +33,7 @@ public interface TaskIdParamsMapper { @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "id") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.CancelTaskRequest toProtoCancelTaskRequest(CancelTaskParams domain); + org.a2aproject.sdk.grpc.CancelTaskRequest toProtoCancelTaskRequest(CancelTaskParams domain); /** @@ -43,7 +43,7 @@ public interface TaskIdParamsMapper { @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "id") @Mapping(target = "tenant", source = "tenant") - TaskIdParams fromProtoSubscribeToTaskRequest(io.a2a.grpc.SubscribeToTaskRequest proto); + TaskIdParams fromProtoSubscribeToTaskRequest(org.a2aproject.sdk.grpc.SubscribeToTaskRequest proto); /** * Converts domain TaskIdParams to proto SubscribeToTaskRequest. @@ -51,5 +51,5 @@ public interface TaskIdParamsMapper { */ @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "id") - io.a2a.grpc.SubscribeToTaskRequest toProtoSubscribeToTaskRequest(TaskIdParams domain); + org.a2aproject.sdk.grpc.SubscribeToTaskRequest toProtoSubscribeToTaskRequest(TaskIdParams domain); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskMapper.java similarity index 85% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskMapper.java index 20ece6064..d83c31bc7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskMapper.java @@ -1,6 +1,6 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.Task; +import org.a2aproject.sdk.spec.Task; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.CollectionMappingStrategy; @@ -8,7 +8,7 @@ import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.Task} and {@link io.a2a.grpc.Task}. + * Mapper between {@link org.a2aproject.sdk.spec.Task} and {@link org.a2aproject.sdk.grpc.Task}. *

                            * Uses ADDER_PREFERRED strategy for List fields (artifacts, history) * to use addAllArtifacts() and addAllHistory() methods. @@ -27,7 +27,7 @@ public interface TaskMapper { @Mapping(target = "id", source = "id", conditionExpression = "java(domain.id() != null)") @Mapping(target = "contextId", source = "contextId", conditionExpression = "java(domain.contextId() != null)") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.Task toProto(Task domain); + org.a2aproject.sdk.grpc.Task toProto(Task domain); /** * Converts proto Task to domain Task. @@ -38,5 +38,5 @@ public interface TaskMapper { @Mapping(target = "id", source = "id", qualifiedByName = "emptyToNull") @Mapping(target = "contextId", source = "contextId", qualifiedByName = "emptyToNull") @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - Task fromProto(io.a2a.grpc.Task proto); + Task fromProto(org.a2aproject.sdk.grpc.Task proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskPushNotificationConfigMapper.java similarity index 87% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskPushNotificationConfigMapper.java index 07b498ad0..2d815954e 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskPushNotificationConfigMapper.java @@ -1,6 +1,6 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -30,7 +30,7 @@ public interface TaskPushNotificationConfigMapper { @Mapping(target = "token", source = "token", conditionExpression = "java(domain.token() != null)") @Mapping(target = "tenant", source = "tenant", conditionExpression = "java(domain.tenant() != null)") @Mapping(target = "authentication", source = "authentication", conditionExpression = "java(domain.authentication() != null)") - io.a2a.grpc.TaskPushNotificationConfig toProto(TaskPushNotificationConfig domain); + org.a2aproject.sdk.grpc.TaskPushNotificationConfig toProto(TaskPushNotificationConfig domain); /** * Converts protobuf TaskPushNotificationConfig to domain TaskPushNotificationConfig. @@ -42,5 +42,5 @@ public interface TaskPushNotificationConfigMapper { @Mapping(target = "tenant", source = "tenant", qualifiedByName = "emptyToNull") @Mapping(target = "taskId", source = "taskId", qualifiedByName = "emptyToNull") @Mapping(target = "authentication", source = "authentication", conditionExpression = "java(proto.hasAuthentication())") - TaskPushNotificationConfig fromProto(io.a2a.grpc.TaskPushNotificationConfig proto); + TaskPushNotificationConfig fromProto(org.a2aproject.sdk.grpc.TaskPushNotificationConfig proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskQueryParamsMapper.java similarity index 72% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskQueryParamsMapper.java index 4d13ff514..fe5916a47 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskQueryParamsMapper.java @@ -1,13 +1,13 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskQueryParams; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.grpc.GetTaskRequest} and {@link io.a2a.spec.TaskQueryParams}. + * Mapper between {@link org.a2aproject.sdk.grpc.GetTaskRequest} and {@link org.a2aproject.sdk.spec.TaskQueryParams}. *

                            * Extracts task ID from resource name format "tasks/{id}" using {@link ResourceNameParser}. */ @@ -23,11 +23,11 @@ public interface TaskQueryParamsMapper { @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "id") @Mapping(target = "historyLength", source = "historyLength") - TaskQueryParams fromProto(io.a2a.grpc.GetTaskRequest proto); + TaskQueryParams fromProto(org.a2aproject.sdk.grpc.GetTaskRequest proto); @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "id", source = "id") @Mapping(target = "historyLength", source = "historyLength") @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.GetTaskRequest toProto(TaskQueryParams domain); + org.a2aproject.sdk.grpc.GetTaskRequest toProto(TaskQueryParams domain); } diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStateMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStateMapper.java new file mode 100644 index 000000000..a8507afb5 --- /dev/null +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStateMapper.java @@ -0,0 +1,68 @@ +package org.a2aproject.sdk.grpc.mapper; + +import org.mapstruct.Mapper; + +/** + * Mapper between {@link org.a2aproject.sdk.spec.TaskState} and {@link org.a2aproject.sdk.grpc.TaskState}. + *

                            + * Handles the conversion between domain TaskState enum (with string-based wire format) + * and protobuf TaskState enum (with integer-based wire format and TASK_STATE_ prefix). + *

                            + * Note: Proto uses CANCELLED spelling while domain uses CANCELED. + *

                            + * Manual Implementation Required: Uses manual switch statements instead of @ValueMapping + * to avoid mapstruct-spi-protobuf enum strategy initialization issues. + */ +@Mapper(config = A2AProtoMapperConfig.class) +public interface TaskStateMapper { + + TaskStateMapper INSTANCE = A2AMappers.getMapper(TaskStateMapper.class); + + /** + * Converts domain TaskState to proto TaskState. + * + * @param domain the domain task state + * @return the proto task state, or TASK_STATE_UNSPECIFIED if input is null + */ + default org.a2aproject.sdk.grpc.TaskState toProto(org.a2aproject.sdk.spec.TaskState domain) { + if (domain == null) { + return org.a2aproject.sdk.grpc.TaskState.TASK_STATE_UNSPECIFIED; + } + + return switch (domain) { + case TASK_STATE_SUBMITTED -> org.a2aproject.sdk.grpc.TaskState.TASK_STATE_SUBMITTED; + case TASK_STATE_WORKING -> org.a2aproject.sdk.grpc.TaskState.TASK_STATE_WORKING; + case TASK_STATE_INPUT_REQUIRED -> org.a2aproject.sdk.grpc.TaskState.TASK_STATE_INPUT_REQUIRED; + case TASK_STATE_AUTH_REQUIRED -> org.a2aproject.sdk.grpc.TaskState.TASK_STATE_AUTH_REQUIRED; + case TASK_STATE_COMPLETED -> org.a2aproject.sdk.grpc.TaskState.TASK_STATE_COMPLETED; + case TASK_STATE_CANCELED -> org.a2aproject.sdk.grpc.TaskState.TASK_STATE_CANCELED; + case TASK_STATE_FAILED -> org.a2aproject.sdk.grpc.TaskState.TASK_STATE_FAILED; + case TASK_STATE_REJECTED -> org.a2aproject.sdk.grpc.TaskState.TASK_STATE_REJECTED; + case UNRECOGNIZED -> org.a2aproject.sdk.grpc.TaskState.UNRECOGNIZED; + }; + } + + /** + * Converts proto TaskState to domain TaskState. + * + * @param proto the proto task state + * @return the domain task state, or UNKNOWN if input is null or unrecognized + */ + default org.a2aproject.sdk.spec.TaskState fromProto(org.a2aproject.sdk.grpc.TaskState proto) { + if (proto == null) { + return org.a2aproject.sdk.spec.TaskState.UNRECOGNIZED; + } + + return switch (proto) { + case TASK_STATE_SUBMITTED -> org.a2aproject.sdk.spec.TaskState.TASK_STATE_SUBMITTED; + case TASK_STATE_WORKING -> org.a2aproject.sdk.spec.TaskState.TASK_STATE_WORKING; + case TASK_STATE_INPUT_REQUIRED -> org.a2aproject.sdk.spec.TaskState.TASK_STATE_INPUT_REQUIRED; + case TASK_STATE_AUTH_REQUIRED -> org.a2aproject.sdk.spec.TaskState.TASK_STATE_AUTH_REQUIRED; + case TASK_STATE_COMPLETED -> org.a2aproject.sdk.spec.TaskState.TASK_STATE_COMPLETED; + case TASK_STATE_CANCELED -> org.a2aproject.sdk.spec.TaskState.TASK_STATE_CANCELED; + case TASK_STATE_FAILED -> org.a2aproject.sdk.spec.TaskState.TASK_STATE_FAILED; + case TASK_STATE_REJECTED -> org.a2aproject.sdk.spec.TaskState.TASK_STATE_REJECTED; + case TASK_STATE_UNSPECIFIED, UNRECOGNIZED -> org.a2aproject.sdk.spec.TaskState.UNRECOGNIZED; + }; + } +} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusMapper.java similarity index 81% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusMapper.java index f6c32c81c..24fecb285 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusMapper.java @@ -1,13 +1,13 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatus; import org.mapstruct.BeanMapping; import org.mapstruct.Builder; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.TaskStatus} and {@link io.a2a.grpc.TaskStatus}. + * Mapper between {@link org.a2aproject.sdk.spec.TaskStatus} and {@link org.a2aproject.sdk.grpc.TaskStatus}. *

                            * Handles conversion of task status including state, optional message, and timestamp. * Uses TaskStateMapper for state conversion, MessageMapper for message conversion, @@ -25,7 +25,7 @@ public interface TaskStatusMapper { @Mapping(target = "state", source = "state", conditionExpression = "java(domain.state() != null)") @Mapping(target = "message", source = "message", conditionExpression = "java(domain.message() != null)") @Mapping(target = "timestamp", source = "timestamp", qualifiedByName = "offsetDateTimeToProtoTimestamp") - io.a2a.grpc.TaskStatus toProto(TaskStatus domain); + org.a2aproject.sdk.grpc.TaskStatus toProto(TaskStatus domain); /** * Converts proto TaskStatus to domain TaskStatus. @@ -33,5 +33,5 @@ public interface TaskStatusMapper { */ @BeanMapping(builder = @Builder(buildMethod = "build")) @Mapping(target = "timestamp", source = "timestamp", qualifiedByName = "protoTimestampToOffsetDateTime") - TaskStatus fromProto(io.a2a.grpc.TaskStatus proto); + TaskStatus fromProto(org.a2aproject.sdk.grpc.TaskStatus proto); } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusUpdateEventMapper.java similarity index 76% rename from spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusUpdateEventMapper.java index f8ced3ecf..a06a5a4bb 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusUpdateEventMapper.java @@ -1,12 +1,12 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.TaskStatusUpdateEvent} and {@link io.a2a.grpc.TaskStatusUpdateEvent}. + * Mapper between {@link org.a2aproject.sdk.spec.TaskStatusUpdateEvent} and {@link org.a2aproject.sdk.grpc.TaskStatusUpdateEvent}. *

                            * Now fully declarative using Builder pattern with @BeanMapping. * Builder's isFinal() method handles the Java "final" keyword mapping. @@ -22,13 +22,13 @@ public interface TaskStatusUpdateEventMapper { * Note: isFinal field is ignored as it has been removed from the proto (field 4 is reserved). */ @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.TaskStatusUpdateEvent toProto(TaskStatusUpdateEvent domain); + org.a2aproject.sdk.grpc.TaskStatusUpdateEvent toProto(TaskStatusUpdateEvent domain); /** * Converts proto TaskStatusUpdateEvent to domain. * Note: isFinal is derived from status.state().isFinal() since the field has been removed from the proto (field 4 is reserved). */ - default TaskStatusUpdateEvent fromProto(io.a2a.grpc.TaskStatusUpdateEvent proto) { + default TaskStatusUpdateEvent fromProto(org.a2aproject.sdk.grpc.TaskStatusUpdateEvent proto) { if (proto == null) { return null; } diff --git a/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java similarity index 80% rename from spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java index a21008bda..270fde3a7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java @@ -1,9 +1,9 @@ -package io.a2a.grpc.utils; +package org.a2aproject.sdk.grpc.utils; -import io.a2a.spec.A2AErrorCodes; -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 org.a2aproject.sdk.spec.A2AErrorCodes; +import static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; import java.io.IOException; import java.io.StringWriter; @@ -23,60 +23,60 @@ import com.google.gson.stream.JsonWriter; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; -import io.a2a.grpc.StreamResponse; -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.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -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.ListTaskPushNotificationConfigsRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; -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.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; -import io.a2a.spec.A2AError; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -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 io.a2a.spec.VersionNotSupportedError; -import io.a2a.util.Utils; +import org.a2aproject.sdk.grpc.StreamResponse; +import org.a2aproject.sdk.jsonrpc.common.json.IdJsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.json.InvalidParamsJsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.MethodNotFoundJsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AMessage; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2ARequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SubscribeToTaskRequest; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.InvalidAgentResponseError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; +import org.a2aproject.sdk.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; +import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; /** * Utilities for converting between JSON-RPC 2.0 messages and Protocol Buffer objects. @@ -148,11 +148,11 @@ * JSONRPCRequest request = JSONRPCUtils.parseRequestBody(jsonRequest); * * // Create JSON-RPC request from proto - * io.a2a.grpc.GetTaskRequest protoRequest = ...; + * org.a2aproject.sdk.grpc.GetTaskRequest protoRequest = ...; * String json = JSONRPCUtils.toJsonRPCRequest("req-1", "tasks.get", protoRequest); * * // Create JSON-RPC response from proto - * io.a2a.grpc.Task protoTask = ...; + * org.a2aproject.sdk.grpc.Task protoTask = ...; * String response = JSONRPCUtils.toJsonRPCResultResponse("req-1", protoTask); * }

                      * @@ -193,7 +193,7 @@ public static A2ARequest parseRequestBody(String body, @Nullable String tenan private static A2ARequest parseMethodRequest(String version, Object id, String method, JsonElement paramsNode, @Nullable String tenant) throws InvalidParamsError, MethodNotFoundJsonMappingException, JsonProcessingException { switch (method) { case GET_TASK_METHOD -> { - io.a2a.grpc.GetTaskRequest.Builder builder = io.a2a.grpc.GetTaskRequest.newBuilder(); + org.a2aproject.sdk.grpc.GetTaskRequest.Builder builder = org.a2aproject.sdk.grpc.GetTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -201,7 +201,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new GetTaskRequest(version, id, ProtoUtils.FromProto.taskQueryParams(builder)); } case CANCEL_TASK_METHOD -> { - io.a2a.grpc.CancelTaskRequest.Builder builder = io.a2a.grpc.CancelTaskRequest.newBuilder(); + org.a2aproject.sdk.grpc.CancelTaskRequest.Builder builder = org.a2aproject.sdk.grpc.CancelTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -209,7 +209,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new CancelTaskRequest(version, id, ProtoUtils.FromProto.cancelTaskParams(builder)); } case LIST_TASK_METHOD -> { - io.a2a.grpc.ListTasksRequest.Builder builder = io.a2a.grpc.ListTasksRequest.newBuilder(); + org.a2aproject.sdk.grpc.ListTasksRequest.Builder builder = org.a2aproject.sdk.grpc.ListTasksRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -217,7 +217,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new ListTasksRequest(version, id, ProtoUtils.FromProto.listTasksParams(builder)); } case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); + org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder builder = org.a2aproject.sdk.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -225,7 +225,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new CreateTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.createTaskPushNotificationConfig(builder)); } case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); + org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.Builder builder = org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -233,7 +233,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new GetTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.getTaskPushNotificationConfigParams(builder)); } case SEND_MESSAGE_METHOD -> { - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); + org.a2aproject.sdk.grpc.SendMessageRequest.Builder builder = org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -241,7 +241,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new SendMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); } case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.ListTaskPushNotificationConfigsRequest.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigsRequest.newBuilder(); + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.Builder builder = org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -249,7 +249,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new ListTaskPushNotificationConfigsRequest(version, id, ProtoUtils.FromProto.listTaskPushNotificationConfigsParams(builder)); } case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); + org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.Builder builder = org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -260,7 +260,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new GetExtendedAgentCardRequest(version, id); } case SEND_STREAMING_MESSAGE_METHOD -> { - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); + org.a2aproject.sdk.grpc.SendMessageRequest.Builder builder = org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -268,7 +268,7 @@ private static A2ARequest parseMethodRequest(String version, Object id, Strin return new SendStreamingMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); } case SUBSCRIBE_TO_TASK_METHOD -> { - io.a2a.grpc.SubscribeToTaskRequest.Builder builder = io.a2a.grpc.SubscribeToTaskRequest.newBuilder(); + org.a2aproject.sdk.grpc.SubscribeToTaskRequest.Builder builder = org.a2aproject.sdk.grpc.SubscribeToTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { builder.setTenant(tenant); @@ -305,32 +305,32 @@ public static A2AResponse parseResponseBody(String body, String method) throw } switch (method) { case GET_TASK_METHOD -> { - io.a2a.grpc.Task.Builder builder = io.a2a.grpc.Task.newBuilder(); + org.a2aproject.sdk.grpc.Task.Builder builder = org.a2aproject.sdk.grpc.Task.newBuilder(); parseRequestBody(paramsNode, builder, id); return new GetTaskResponse(id, ProtoUtils.FromProto.task(builder)); } case CANCEL_TASK_METHOD -> { - io.a2a.grpc.Task.Builder builder = io.a2a.grpc.Task.newBuilder(); + org.a2aproject.sdk.grpc.Task.Builder builder = org.a2aproject.sdk.grpc.Task.newBuilder(); parseRequestBody(paramsNode, builder, id); return new CancelTaskResponse(id, ProtoUtils.FromProto.task(builder)); } case LIST_TASK_METHOD -> { - io.a2a.grpc.ListTasksResponse.Builder builder = io.a2a.grpc.ListTasksResponse.newBuilder(); + org.a2aproject.sdk.grpc.ListTasksResponse.Builder builder = org.a2aproject.sdk.grpc.ListTasksResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); return new ListTasksResponse(id, ProtoUtils.FromProto.listTasksResult(builder)); } case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); + org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder builder = org.a2aproject.sdk.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(paramsNode, builder, id); return new CreateTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.taskPushNotificationConfig(builder)); } case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); + org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder builder = org.a2aproject.sdk.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(paramsNode, builder, id); return new GetTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.taskPushNotificationConfig(builder)); } case SEND_MESSAGE_METHOD -> { - io.a2a.grpc.SendMessageResponse.Builder builder = io.a2a.grpc.SendMessageResponse.newBuilder(); + org.a2aproject.sdk.grpc.SendMessageResponse.Builder builder = org.a2aproject.sdk.grpc.SendMessageResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); if (builder.hasMessage()) { return new SendMessageResponse(id, ProtoUtils.FromProto.message(builder.getMessage())); @@ -338,7 +338,7 @@ public static A2AResponse parseResponseBody(String body, String method) throw return new SendMessageResponse(id, ProtoUtils.FromProto.task(builder.getTask())); } case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.ListTaskPushNotificationConfigsResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(); + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.Builder builder = org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); return new ListTaskPushNotificationConfigsResponse(id, ProtoUtils.FromProto.listTaskPushNotificationConfigsResult(builder)); } @@ -346,7 +346,7 @@ public static A2AResponse parseResponseBody(String body, String method) throw return new DeleteTaskPushNotificationConfigResponse(id); } case GET_EXTENDED_AGENT_CARD_METHOD -> { - io.a2a.grpc.AgentCard.Builder builder = io.a2a.grpc.AgentCard.newBuilder(); + org.a2aproject.sdk.grpc.AgentCard.Builder builder = org.a2aproject.sdk.grpc.AgentCard.newBuilder(); parseRequestBody(paramsNode, builder, id); return new GetExtendedAgentCardResponse(id, ProtoUtils.FromProto.agentCard(builder)); } @@ -403,7 +403,7 @@ private static A2AError processError(JsonObject error) { case INVALID_REQUEST -> new InvalidRequestError(code, message, details); case METHOD_NOT_FOUND -> new MethodNotFoundError(code, message, details); case INVALID_PARAMS -> new InvalidParamsError(code, message, details); - case INTERNAL -> new io.a2a.spec.InternalError(code, message, details); + case INTERNAL -> new org.a2aproject.sdk.spec.InternalError(code, message, details); case PUSH_NOTIFICATION_NOT_SUPPORTED -> new PushNotificationNotSupportedError(code, message, details); case UNSUPPORTED_OPERATION -> new UnsupportedOperationError(code, message, details); case CONTENT_TYPE_NOT_SUPPORTED -> new ContentTypeNotSupportedError(code, message, details); diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/ProtoUtils.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/ProtoUtils.java new file mode 100644 index 000000000..a7e93533a --- /dev/null +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/ProtoUtils.java @@ -0,0 +1,340 @@ +package org.a2aproject.sdk.grpc.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest; +import org.a2aproject.sdk.grpc.StreamResponse; +import org.a2aproject.sdk.grpc.mapper.AgentCardMapper; +import org.a2aproject.sdk.grpc.mapper.DeleteTaskPushNotificationConfigParamsMapper; +import org.a2aproject.sdk.grpc.mapper.GetTaskPushNotificationConfigParamsMapper; +import org.a2aproject.sdk.grpc.mapper.ListTaskPushNotificationConfigsParamsMapper; +import org.a2aproject.sdk.grpc.mapper.ListTasksParamsMapper; +import org.a2aproject.sdk.grpc.mapper.ListTasksResultMapper; +import org.a2aproject.sdk.grpc.mapper.MessageMapper; +import org.a2aproject.sdk.grpc.mapper.MessageSendConfigurationMapper; +import org.a2aproject.sdk.grpc.mapper.MessageSendParamsMapper; +import org.a2aproject.sdk.grpc.mapper.StreamResponseMapper; +import org.a2aproject.sdk.grpc.mapper.TaskArtifactUpdateEventMapper; +import org.a2aproject.sdk.grpc.mapper.TaskIdParamsMapper; +import org.a2aproject.sdk.grpc.mapper.TaskMapper; +import org.a2aproject.sdk.grpc.mapper.TaskPushNotificationConfigMapper; +import org.a2aproject.sdk.grpc.mapper.TaskQueryParamsMapper; +import org.a2aproject.sdk.grpc.mapper.TaskStateMapper; +import org.a2aproject.sdk.grpc.mapper.TaskStatusUpdateEventMapper; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetExtendedAgentCardParams; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; + +/** + * Utility class to convert between GRPC and Spec objects. + */ +public class ProtoUtils { + + public static class ToProto { + + public static org.a2aproject.sdk.grpc.AgentCard agentCard(AgentCard agentCard) { + return AgentCardMapper.INSTANCE.toProto(agentCard); + } + + public static org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest extendedAgentCard(GetExtendedAgentCardParams params) { + GetExtendedAgentCardRequest.Builder builder = GetExtendedAgentCardRequest.newBuilder(); + if (params.tenant() != null) { + builder.setTenant(params.tenant()); + } + return builder.build(); + } + + public static org.a2aproject.sdk.grpc.GetTaskRequest getTaskRequest(TaskQueryParams params) { + return TaskQueryParamsMapper.INSTANCE.toProto(params); + } + + public static org.a2aproject.sdk.grpc.CancelTaskRequest cancelTaskRequest(CancelTaskParams params) { + return TaskIdParamsMapper.INSTANCE.toProtoCancelTaskRequest(params); + } + + public static org.a2aproject.sdk.grpc.SubscribeToTaskRequest subscribeToTaskRequest(TaskIdParams params) { + return TaskIdParamsMapper.INSTANCE.toProtoSubscribeToTaskRequest(params); + } + + public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig createTaskPushNotificationConfigRequest(TaskPushNotificationConfig config) { + return TaskPushNotificationConfigMapper.INSTANCE.toProto(config); + } + + public static org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest getTaskPushNotificationConfigRequest(GetTaskPushNotificationConfigParams params) { + return GetTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); + } + + public static org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest deleteTaskPushNotificationConfigRequest(DeleteTaskPushNotificationConfigParams params) { + return DeleteTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); + } + + public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest listTaskPushNotificationConfigsRequest(ListTaskPushNotificationConfigsParams params) { + return ListTaskPushNotificationConfigsParamsMapper.INSTANCE.toProto(params); + } + + public static org.a2aproject.sdk.grpc.Task task(Task task) { + return TaskMapper.INSTANCE.toProto(task); + } + + public static org.a2aproject.sdk.grpc.ListTasksResponse listTasksResult(ListTasksResult result) { + return ListTasksResultMapper.INSTANCE.toProto(result); + } + + public static org.a2aproject.sdk.grpc.ListTasksRequest listTasksParams(ListTasksParams params) { + return ListTasksParamsMapper.INSTANCE.toProto(params); + } + + public static org.a2aproject.sdk.grpc.Message message(Message message) { + return MessageMapper.INSTANCE.toProto(message); + } + + public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig taskPushNotificationConfig(TaskPushNotificationConfig config) { + return TaskPushNotificationConfigMapper.INSTANCE.toProto(config); + } + + public static org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent taskArtifactUpdateEvent(TaskArtifactUpdateEvent event) { + return TaskArtifactUpdateEventMapper.INSTANCE.toProto(event); + } + + public static org.a2aproject.sdk.grpc.TaskStatusUpdateEvent taskStatusUpdateEvent(TaskStatusUpdateEvent event) { + return TaskStatusUpdateEventMapper.INSTANCE.toProto(event); + } + + public static org.a2aproject.sdk.grpc.TaskState taskState(TaskState taskState) { + return TaskStateMapper.INSTANCE.toProto(taskState); + } + + public static org.a2aproject.sdk.grpc.SendMessageConfiguration messageSendConfiguration(MessageSendConfiguration messageSendConfiguration) { + return MessageSendConfigurationMapper.INSTANCE.toProto(messageSendConfiguration); + } + + public static org.a2aproject.sdk.grpc.SendMessageRequest sendMessageRequest(MessageSendParams request) { + return MessageSendParamsMapper.INSTANCE.toProto(request); + } + + public static org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse listTaskPushNotificationConfigsResponse(ListTaskPushNotificationConfigsResult result) { + List confs = new ArrayList<>(result.configs().size()); + for (TaskPushNotificationConfig config : result.configs()) { + confs.add(taskPushNotificationConfig(config)); + } + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.Builder builder = org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.newBuilder().addAllConfigs(confs); + if (result.nextPageToken() != null) { + builder.setNextPageToken(result.nextPageToken()); + } + return builder.build(); + } + + public static StreamResponse streamResponse(StreamingEventKind streamingEventKind) { + return StreamResponseMapper.INSTANCE.toProto(streamingEventKind); + } + + public static org.a2aproject.sdk.grpc.SendMessageResponse taskOrMessage(EventKind eventKind) { + return switch (eventKind.kind()) { + case Task.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.SendMessageResponse.newBuilder() + .setTask(task((Task) eventKind)) + .build(); + case Message.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.SendMessageResponse.newBuilder() + .setMessage(message((Message) eventKind)) + .build(); + default -> throw new IllegalArgumentException("Unsupported event type: " + eventKind); + }; + } + + public static org.a2aproject.sdk.grpc.StreamResponse taskOrMessageStream(StreamingEventKind eventKind) { + return switch (eventKind.kind()) { + case Task.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.StreamResponse.newBuilder() + .setTask(task((Task) eventKind)) + .build(); + case Message.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.StreamResponse.newBuilder() + .setMessage(message((Message) eventKind)) + .build(); + case TaskStatusUpdateEvent.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.StreamResponse.newBuilder() + .setStatusUpdate(taskStatusUpdateEvent((TaskStatusUpdateEvent) eventKind)) + .build(); + case TaskArtifactUpdateEvent.STREAMING_EVENT_ID -> org.a2aproject.sdk.grpc.StreamResponse.newBuilder() + .setArtifactUpdate(taskArtifactUpdateEvent((TaskArtifactUpdateEvent) eventKind)) + .build(); + default -> throw new IllegalArgumentException("Unsupported event type: " + eventKind); + }; + } + + public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig createTaskPushNotificationConfigResponse(TaskPushNotificationConfig config) { + return taskPushNotificationConfig(config); + } + + public static org.a2aproject.sdk.grpc.TaskPushNotificationConfig getTaskPushNotificationConfigResponse(TaskPushNotificationConfig config) { + return taskPushNotificationConfig(config); + } + + public static org.a2aproject.sdk.grpc.AgentCard getExtendedCardResponse(AgentCard card) { + return agentCard(card); + } + } + + public static class FromProto { + + private static T convert(java.util.function.Supplier s) { + try { + return s.get(); + } catch (IllegalArgumentException ex) { + throw new InvalidParamsError(ex.getMessage()); + } + } + + public static AgentCard agentCard(org.a2aproject.sdk.grpc.AgentCardOrBuilder agentCard) { + org.a2aproject.sdk.grpc.AgentCard agentCardProto = agentCard instanceof org.a2aproject.sdk.grpc.AgentCard + ? (org.a2aproject.sdk.grpc.AgentCard) agentCard + : ((org.a2aproject.sdk.grpc.AgentCard.Builder) agentCard).build(); + return convert(() -> AgentCardMapper.INSTANCE.fromProto(agentCardProto)); + } + + public static TaskQueryParams taskQueryParams(org.a2aproject.sdk.grpc.GetTaskRequestOrBuilder request) { + org.a2aproject.sdk.grpc.GetTaskRequest reqProto = request instanceof org.a2aproject.sdk.grpc.GetTaskRequest + ? (org.a2aproject.sdk.grpc.GetTaskRequest) request + : ((org.a2aproject.sdk.grpc.GetTaskRequest.Builder) request).build(); + return convert(() -> TaskQueryParamsMapper.INSTANCE.fromProto(reqProto)); + } + + public static ListTasksParams listTasksParams(org.a2aproject.sdk.grpc.ListTasksRequestOrBuilder request) { + org.a2aproject.sdk.grpc.ListTasksRequest reqProto = request instanceof org.a2aproject.sdk.grpc.ListTasksRequest + ? (org.a2aproject.sdk.grpc.ListTasksRequest) request + : ((org.a2aproject.sdk.grpc.ListTasksRequest.Builder) request).build(); + return convert(() -> ListTasksParamsMapper.INSTANCE.fromProto(reqProto)); + } + + public static CancelTaskParams cancelTaskParams(org.a2aproject.sdk.grpc.CancelTaskRequestOrBuilder request) { + org.a2aproject.sdk.grpc.CancelTaskRequest reqProto = request instanceof org.a2aproject.sdk.grpc.CancelTaskRequest + ? (org.a2aproject.sdk.grpc.CancelTaskRequest) request + : ((org.a2aproject.sdk.grpc.CancelTaskRequest.Builder) request).build(); + return convert(() -> TaskIdParamsMapper.INSTANCE.fromProtoCancelTaskRequest(reqProto)); + } + + public static MessageSendParams messageSendParams(org.a2aproject.sdk.grpc.SendMessageRequestOrBuilder request) { + org.a2aproject.sdk.grpc.SendMessageRequest requestProto = request instanceof org.a2aproject.sdk.grpc.SendMessageRequest + ? (org.a2aproject.sdk.grpc.SendMessageRequest) request + : ((org.a2aproject.sdk.grpc.SendMessageRequest.Builder) request).build(); + return convert(() -> MessageSendParamsMapper.INSTANCE.fromProto(requestProto)); + } + + public static TaskPushNotificationConfig createTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder config) { + org.a2aproject.sdk.grpc.TaskPushNotificationConfig proto = config instanceof org.a2aproject.sdk.grpc.TaskPushNotificationConfig + ? (org.a2aproject.sdk.grpc.TaskPushNotificationConfig) config + : ((org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder) config).build(); + return convert(() -> TaskPushNotificationConfigMapper.INSTANCE.fromProto(proto)); + } + + public static TaskPushNotificationConfig taskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfigOrBuilder config) { + org.a2aproject.sdk.grpc.TaskPushNotificationConfig proto = config instanceof org.a2aproject.sdk.grpc.TaskPushNotificationConfig + ? (org.a2aproject.sdk.grpc.TaskPushNotificationConfig) config + : ((org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder) config).build(); + return convert(() -> TaskPushNotificationConfigMapper.INSTANCE.fromProto(proto)); + } + + public static GetTaskPushNotificationConfigParams getTaskPushNotificationConfigParams(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequestOrBuilder request) { + org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest reqProto = request instanceof org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest + ? (org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest) request + : ((org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest.Builder) request).build(); + return convert(() -> GetTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto)); + } + + public static TaskIdParams taskIdParams(org.a2aproject.sdk.grpc.SubscribeToTaskRequestOrBuilder request) { + org.a2aproject.sdk.grpc.SubscribeToTaskRequest reqProto = request instanceof org.a2aproject.sdk.grpc.SubscribeToTaskRequest + ? (org.a2aproject.sdk.grpc.SubscribeToTaskRequest) request + : ((org.a2aproject.sdk.grpc.SubscribeToTaskRequest.Builder) request).build(); + return convert(() -> TaskIdParamsMapper.INSTANCE.fromProtoSubscribeToTaskRequest(reqProto)); + } + + public static ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigsResult(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponseOrBuilder response) { + List configs = response.getConfigsList(); + List result = new ArrayList<>(configs.size()); + for (org.a2aproject.sdk.grpc.TaskPushNotificationConfig config : configs) { + result.add(taskPushNotificationConfig(config)); + } + String nextPageToken = response.getNextPageToken(); + if (nextPageToken != null && nextPageToken.isEmpty()) { + nextPageToken = null; + } + return new ListTaskPushNotificationConfigsResult(result, nextPageToken); + } + + public static ListTaskPushNotificationConfigsParams listTaskPushNotificationConfigsParams(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequestOrBuilder request) { + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest reqProto = request instanceof org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest + ? (org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest) request + : ((org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest.Builder) request).build(); + return convert(() -> ListTaskPushNotificationConfigsParamsMapper.INSTANCE.fromProto(reqProto)); + } + + public static DeleteTaskPushNotificationConfigParams deleteTaskPushNotificationConfigParams(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder request) { + org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest reqProto = request instanceof org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest + ? (org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest) request + : ((org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest.Builder) request).build(); + return convert(() -> DeleteTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto)); + } + + public static Task task(org.a2aproject.sdk.grpc.TaskOrBuilder task) { + org.a2aproject.sdk.grpc.Task taskProto = task instanceof org.a2aproject.sdk.grpc.Task + ? (org.a2aproject.sdk.grpc.Task) task + : ((org.a2aproject.sdk.grpc.Task.Builder) task).build(); + return convert(() -> TaskMapper.INSTANCE.fromProto(taskProto)); + } + + public static Message message(org.a2aproject.sdk.grpc.MessageOrBuilder message) { + if (message.getMessageId().isEmpty()) { + throw new InvalidParamsError(); + } + org.a2aproject.sdk.grpc.Message messageProto = message instanceof org.a2aproject.sdk.grpc.Message + ? (org.a2aproject.sdk.grpc.Message) message + : ((org.a2aproject.sdk.grpc.Message.Builder) message).build(); + return convert(() -> MessageMapper.INSTANCE.fromProto(messageProto)); + } + + public static TaskStatusUpdateEvent taskStatusUpdateEvent(org.a2aproject.sdk.grpc.TaskStatusUpdateEventOrBuilder taskStatusUpdateEvent) { + org.a2aproject.sdk.grpc.TaskStatusUpdateEvent eventProto = taskStatusUpdateEvent instanceof org.a2aproject.sdk.grpc.TaskStatusUpdateEvent + ? (org.a2aproject.sdk.grpc.TaskStatusUpdateEvent) taskStatusUpdateEvent + : ((org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.Builder) taskStatusUpdateEvent).build(); + return convert(() -> TaskStatusUpdateEventMapper.INSTANCE.fromProto(eventProto)); + } + + public static TaskArtifactUpdateEvent taskArtifactUpdateEvent(org.a2aproject.sdk.grpc.TaskArtifactUpdateEventOrBuilder taskArtifactUpdateEvent) { + org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent eventProto = taskArtifactUpdateEvent instanceof org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent + ? (org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent) taskArtifactUpdateEvent + : ((org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.Builder) taskArtifactUpdateEvent).build(); + return convert(() -> TaskArtifactUpdateEventMapper.INSTANCE.fromProto(eventProto)); + } + + public static ListTasksResult listTasksResult(org.a2aproject.sdk.grpc.ListTasksResponseOrBuilder listTasksResponse) { + org.a2aproject.sdk.grpc.ListTasksResponse eventProto = listTasksResponse instanceof org.a2aproject.sdk.grpc.ListTasksResponse + ? (org.a2aproject.sdk.grpc.ListTasksResponse) listTasksResponse + : ((org.a2aproject.sdk.grpc.ListTasksResponse.Builder) listTasksResponse).build(); + return convert(() -> ListTasksResultMapper.INSTANCE.fromProto(eventProto)); + } + + public static StreamingEventKind streamingEventKind(org.a2aproject.sdk.grpc.StreamResponseOrBuilder streamResponse) { + org.a2aproject.sdk.grpc.StreamResponse streamResponseProto = streamResponse instanceof org.a2aproject.sdk.grpc.StreamResponse + ? (org.a2aproject.sdk.grpc.StreamResponse) streamResponse + : ((org.a2aproject.sdk.grpc.StreamResponse.Builder) streamResponse).build(); + return convert(() -> StreamResponseMapper.INSTANCE.fromProto(streamResponseProto)); + } + } + +} diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/package-info.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/package-info.java similarity index 59% rename from client/transport/rest/src/main/java/io/a2a/client/transport/rest/package-info.java rename to spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/package-info.java index b7892c239..b3d56fb8a 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/package-info.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/package-info.java @@ -1,5 +1,5 @@ @NullMarked -package io.a2a.client.transport.rest; +package org.a2aproject.sdk.grpc.utils; import org.jspecify.annotations.NullMarked; diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto index 4f12d54fb..47aa03aab 100644 --- a/spec-grpc/src/main/proto/a2a.proto +++ b/spec-grpc/src/main/proto/a2a.proto @@ -15,7 +15,7 @@ option csharp_namespace = "Lf.A2a.V1"; option go_package = "google.golang.org/lf/a2a/v1"; option java_multiple_files = true; option java_outer_classname = "A2A"; -option java_package = "io.a2a.grpc"; +option java_package = "org.a2aproject.sdk.grpc"; // Provides operations for interacting with agents using the A2A protocol. service A2AService { diff --git a/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/mapper/A2ACommonFieldMapperTest.java similarity index 90% rename from spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java rename to spec-grpc/src/test/java/org/a2aproject/sdk/grpc/mapper/A2ACommonFieldMapperTest.java index 206123103..d77c649a8 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java +++ b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/mapper/A2ACommonFieldMapperTest.java @@ -1,4 +1,4 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -9,8 +9,8 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.spec.MessageSendParams; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.spec.MessageSendParams; import org.junit.jupiter.api.Test; public class A2ACommonFieldMapperTest { @@ -63,7 +63,7 @@ void testValueToObject_WithEmptyStruct_ReturnsEmptyMap() throws InvalidProtocolB " }\n" + "}"; - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); + org.a2aproject.sdk.grpc.SendMessageRequest.Builder builder = org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder(); JsonFormat.parser().merge(json, builder); // This should not throw NullPointerException @@ -96,7 +96,7 @@ void testValueToObject_WithNestedEmptyStruct_ReturnsEmptyMap() throws InvalidPro " }\n" + "}"; - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); + org.a2aproject.sdk.grpc.SendMessageRequest.Builder builder = org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder(); JsonFormat.parser().merge(json, builder); // This should not throw NullPointerException diff --git a/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/mapper/StreamResponseMapperTest.java similarity index 70% rename from spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java rename to spec-grpc/src/test/java/org/a2aproject/sdk/grpc/mapper/StreamResponseMapperTest.java index 99ff1ad39..a53527009 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java +++ b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/mapper/StreamResponseMapperTest.java @@ -1,4 +1,4 @@ -package io.a2a.grpc.mapper; +package org.a2aproject.sdk.grpc.mapper; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -7,15 +7,15 @@ import java.util.Collections; -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.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; public class StreamResponseMapperTest { @@ -30,25 +30,25 @@ void testConvertTask_ToProto() { .build(); // Act - io.a2a.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(task); + org.a2aproject.sdk.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(task); // Assert assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.TASK, result.getPayloadCase()); + assertEquals(org.a2aproject.sdk.grpc.StreamResponse.PayloadCase.TASK, result.getPayloadCase()); assertEquals("task-123", result.getTask().getId()); assertEquals("context-456", result.getTask().getContextId()); - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_COMPLETED, result.getTask().getStatus().getState()); + assertEquals(org.a2aproject.sdk.grpc.TaskState.TASK_STATE_COMPLETED, result.getTask().getStatus().getState()); } @Test void testConvertTask_FromProto() { // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setTask(io.a2a.grpc.Task.newBuilder() + org.a2aproject.sdk.grpc.StreamResponse proto = org.a2aproject.sdk.grpc.StreamResponse.newBuilder() + .setTask(org.a2aproject.sdk.grpc.Task.newBuilder() .setId("task-123") .setContextId("context-456") - .setStatus(io.a2a.grpc.TaskStatus.newBuilder() - .setState(io.a2a.grpc.TaskState.TASK_STATE_COMPLETED) + .setStatus(org.a2aproject.sdk.grpc.TaskStatus.newBuilder() + .setState(org.a2aproject.sdk.grpc.TaskState.TASK_STATE_COMPLETED) .build()) .build()) .build(); @@ -76,25 +76,25 @@ void testConvertMessage_ToProto() { .build(); // Act - io.a2a.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(message); + org.a2aproject.sdk.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(message); // Assert assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.MESSAGE, result.getPayloadCase()); + assertEquals(org.a2aproject.sdk.grpc.StreamResponse.PayloadCase.MESSAGE, result.getPayloadCase()); assertEquals("msg-123", result.getMessage().getMessageId()); assertEquals("context-456", result.getMessage().getContextId()); - assertEquals(io.a2a.grpc.Role.ROLE_USER, result.getMessage().getRole()); + assertEquals(org.a2aproject.sdk.grpc.Role.ROLE_USER, result.getMessage().getRole()); } @Test void testConvertMessage_FromProto() { // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setMessage(io.a2a.grpc.Message.newBuilder() + org.a2aproject.sdk.grpc.StreamResponse proto = org.a2aproject.sdk.grpc.StreamResponse.newBuilder() + .setMessage(org.a2aproject.sdk.grpc.Message.newBuilder() .setMessageId("msg-123") .setContextId("context-456") - .setRole(io.a2a.grpc.Role.ROLE_USER) - .addParts(io.a2a.grpc.Part.newBuilder() + .setRole(org.a2aproject.sdk.grpc.Role.ROLE_USER) + .addParts(org.a2aproject.sdk.grpc.Part.newBuilder() .setText("Hello") .build()) .build()) @@ -122,25 +122,25 @@ void testConvertTaskStatusUpdateEvent_ToProto() { .build(); // Act - io.a2a.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(event); + org.a2aproject.sdk.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(event); // Assert assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.STATUS_UPDATE, result.getPayloadCase()); + assertEquals(org.a2aproject.sdk.grpc.StreamResponse.PayloadCase.STATUS_UPDATE, result.getPayloadCase()); assertEquals("task-123", result.getStatusUpdate().getTaskId()); assertEquals("context-456", result.getStatusUpdate().getContextId()); - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_WORKING, result.getStatusUpdate().getStatus().getState()); + assertEquals(org.a2aproject.sdk.grpc.TaskState.TASK_STATE_WORKING, result.getStatusUpdate().getStatus().getState()); } @Test void testConvertTaskStatusUpdateEvent_FromProto() { // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent.newBuilder() + org.a2aproject.sdk.grpc.StreamResponse proto = org.a2aproject.sdk.grpc.StreamResponse.newBuilder() + .setStatusUpdate(org.a2aproject.sdk.grpc.TaskStatusUpdateEvent.newBuilder() .setTaskId("task-123") .setContextId("context-456") - .setStatus(io.a2a.grpc.TaskStatus.newBuilder() - .setState(io.a2a.grpc.TaskState.TASK_STATE_WORKING) + .setStatus(org.a2aproject.sdk.grpc.TaskStatus.newBuilder() + .setState(org.a2aproject.sdk.grpc.TaskState.TASK_STATE_WORKING) .build()) .build()) .build(); @@ -172,11 +172,11 @@ void testConvertTaskArtifactUpdateEvent_ToProto() { .build(); // Act - io.a2a.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(event); + org.a2aproject.sdk.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(event); // Assert assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.ARTIFACT_UPDATE, result.getPayloadCase()); + assertEquals(org.a2aproject.sdk.grpc.StreamResponse.PayloadCase.ARTIFACT_UPDATE, result.getPayloadCase()); assertEquals("task-123", result.getArtifactUpdate().getTaskId()); assertEquals("context-456", result.getArtifactUpdate().getContextId()); assertEquals("artifact-1", result.getArtifactUpdate().getArtifact().getArtifactId()); @@ -186,14 +186,14 @@ void testConvertTaskArtifactUpdateEvent_ToProto() { @Test void testConvertTaskArtifactUpdateEvent_FromProto() { // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent.newBuilder() + org.a2aproject.sdk.grpc.StreamResponse proto = org.a2aproject.sdk.grpc.StreamResponse.newBuilder() + .setArtifactUpdate(org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent.newBuilder() .setTaskId("task-123") .setContextId("context-456") - .setArtifact(io.a2a.grpc.Artifact.newBuilder() + .setArtifact(org.a2aproject.sdk.grpc.Artifact.newBuilder() .setArtifactId("artifact-1") .setName("result") - .addParts(io.a2a.grpc.Part.newBuilder() + .addParts(org.a2aproject.sdk.grpc.Part.newBuilder() .setText("Result text") .build()) .build()) @@ -216,7 +216,7 @@ void testConvertTaskArtifactUpdateEvent_FromProto() { @Test void testConvertStreamResponse_FromProto_PayloadNotSet_ThrowsException() { // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder().build(); + org.a2aproject.sdk.grpc.StreamResponse proto = org.a2aproject.sdk.grpc.StreamResponse.newBuilder().build(); // Act & Assert IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { @@ -235,7 +235,7 @@ void testConvertStreamResponse_Roundtrip_Task() { .build(); // Act - io.a2a.grpc.StreamResponse proto = StreamResponseMapper.INSTANCE.toProto(originalTask); + org.a2aproject.sdk.grpc.StreamResponse proto = StreamResponseMapper.INSTANCE.toProto(originalTask); StreamingEventKind result = StreamResponseMapper.INSTANCE.fromProto(proto); // Assert @@ -258,7 +258,7 @@ void testConvertStreamResponse_Roundtrip_Message() { .build(); // Act - io.a2a.grpc.StreamResponse proto = StreamResponseMapper.INSTANCE.toProto(originalMessage); + org.a2aproject.sdk.grpc.StreamResponse proto = StreamResponseMapper.INSTANCE.toProto(originalMessage); StreamingEventKind result = StreamResponseMapper.INSTANCE.fromProto(proto); // Assert diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java similarity index 92% rename from spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java rename to spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java index 7428f693e..d692be94e 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java +++ b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java @@ -1,8 +1,8 @@ -package io.a2a.grpc.utils; +package org.a2aproject.sdk.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.a2aproject.sdk.grpc.utils.JSONRPCUtils.ERROR_MESSAGE; +import static org.a2aproject.sdk.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static org.a2aproject.sdk.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; @@ -11,17 +11,17 @@ import com.google.gson.JsonSyntaxException; -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.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.jsonrpc.common.json.InvalidParamsJsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonMappingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2ARequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.junit.jupiter.api.Test; public class JSONRPCUtilsTest { diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/PartTypeAdapterTest.java similarity index 93% rename from spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java rename to spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/PartTypeAdapterTest.java index 3daea3a4a..26a1463da 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/PartTypeAdapterTest.java +++ b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/PartTypeAdapterTest.java @@ -1,7 +1,7 @@ -package io.a2a.grpc.utils; +package org.a2aproject.sdk.grpc.utils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -12,16 +12,16 @@ import com.google.protobuf.Value; import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.Structs; -import io.a2a.grpc.mapper.A2ACommonFieldMapper; +import org.a2aproject.sdk.grpc.mapper.A2ACommonFieldMapper; import java.util.List; import java.util.Map; -import io.a2a.spec.DataPart; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.FilePart; +import org.a2aproject.sdk.spec.FileWithBytes; +import org.a2aproject.sdk.spec.FileWithUri; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -60,7 +60,7 @@ public void shouldSerializeTextPartWithMetadata() throws JsonProcessingException @Test public void shouldDeserializeTextPart() throws JsonProcessingException, InvalidProtocolBufferException { - io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + org.a2aproject.sdk.grpc.Part.Builder builder = org.a2aproject.sdk.grpc.Part.newBuilder(); builder.setText("Hello, world!"); String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); Partpart = JsonUtil.fromJson(json, Part.class); @@ -73,7 +73,7 @@ public void shouldDeserializeTextPart() throws JsonProcessingException, InvalidP @Test public void shouldDeserializeTextPartWithMetadata() throws JsonProcessingException, InvalidProtocolBufferException { - io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + org.a2aproject.sdk.grpc.Part.Builder builder = org.a2aproject.sdk.grpc.Part.newBuilder(); builder.setText("Hi"); builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(Map.of("key", "value"))); String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); @@ -111,7 +111,7 @@ public void shouldSerializeFilePartWithBytes() throws JsonProcessingException { @Test public void shouldDeserializeFilePartWithBytes() throws JsonProcessingException, InvalidProtocolBufferException { - io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + org.a2aproject.sdk.grpc.Part.Builder builder = org.a2aproject.sdk.grpc.Part.newBuilder(); builder.setFilename("diagram.png").setMediaType("image/png").setRaw(ByteString.copyFrom(Base64.getDecoder().decode("abc12w=="))); builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(Map.of("key", "value"))); String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); @@ -190,7 +190,7 @@ public void shouldSerializeFilePartWithUri() throws JsonProcessingException { @Test public void shouldDeserializeFilePartWithUri() throws JsonProcessingException, InvalidProtocolBufferException { - io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + org.a2aproject.sdk.grpc.Part.Builder builder = org.a2aproject.sdk.grpc.Part.newBuilder(); builder.setFilename("photo.png").setMediaType("image/png").setUrl("https://example.com/photo.png"); builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(Map.of("key", "value"))); String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); @@ -249,7 +249,7 @@ public void shouldSerializeDataPartWithObject() throws JsonProcessingException { @Test public void shouldDeserializeDataPartWithObject() throws JsonProcessingException, InvalidProtocolBufferException { - io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); + org.a2aproject.sdk.grpc.Part.Builder builder = org.a2aproject.sdk.grpc.Part.newBuilder(); builder.setData(Value.newBuilder().setStructValue(Structs.of("count", Value.newBuilder().setNumberValue(42).build(), "label", Value.newBuilder().setStringValue("items").build()))); builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(Map.of("key", "value"))); String json = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/ToProtoTest.java similarity index 86% rename from spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java rename to spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/ToProtoTest.java index 06759af55..d27b2ce63 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/ToProtoTest.java @@ -1,8 +1,8 @@ -package io.a2a.grpc.utils; +package org.a2aproject.sdk.grpc.utils; -import static io.a2a.grpc.Role.ROLE_AGENT; -import static io.a2a.grpc.Role.ROLE_USER; -import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; +import static org.a2aproject.sdk.grpc.Role.ROLE_AGENT; +import static org.a2aproject.sdk.grpc.Role.ROLE_USER; +import static org.a2aproject.sdk.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -12,26 +12,26 @@ import java.util.List; import java.util.Map; -import io.a2a.grpc.SendMessageConfiguration; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.Artifact; -import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; +import org.a2aproject.sdk.grpc.SendMessageConfiguration; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.SecurityRequirement; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.AuthenticationInfo; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; import org.junit.jupiter.api.Test; public class ToProtoTest { @@ -65,7 +65,7 @@ public void convertAgentCard() { .examples(List.of("hi", "hello world")) .build())) .build(); - io.a2a.grpc.AgentCard result = ProtoUtils.ToProto.agentCard(agentCard); + org.a2aproject.sdk.grpc.AgentCard result = ProtoUtils.ToProto.agentCard(agentCard); assertEquals("Hello World Agent", result.getName()); assertEquals("Just a hello world agent", result.getDescription()); assertEquals(1, result.getSupportedInterfacesList().size()); @@ -138,10 +138,10 @@ public void convertTask() { .contextId("session-xyz") .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) .build(); - io.a2a.grpc.Task result = ProtoUtils.ToProto.task(task); + org.a2aproject.sdk.grpc.Task result = ProtoUtils.ToProto.task(task); assertEquals("session-xyz", result.getContextId()); assertEquals("cancel-task-123", result.getId()); - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_SUBMITTED, result.getStatus().getState()); + assertEquals(org.a2aproject.sdk.grpc.TaskState.TASK_STATE_SUBMITTED, result.getStatus().getState()); assertEquals(0, result.getArtifactsCount()); assertEquals(0, result.getHistoryCount()); task = Task.builder().id("cancel-task-123") @@ -158,7 +158,7 @@ public void convertTask() { result = ProtoUtils.ToProto.task(task); assertEquals("session-xyz", result.getContextId()); assertEquals("cancel-task-123", result.getId()); - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_SUBMITTED, result.getStatus().getState()); + assertEquals(org.a2aproject.sdk.grpc.TaskState.TASK_STATE_SUBMITTED, result.getStatus().getState()); assertEquals(1, result.getArtifactsCount()); assertEquals("11", result.getArtifacts(0).getArtifactId()); assertEquals("artefact", result.getArtifacts(0).getName()); @@ -181,7 +181,7 @@ public void convertTask() { @Test public void convertMessage() { - io.a2a.grpc.Message result = ProtoUtils.ToProto.message(SIMPLE_MESSAGE); + org.a2aproject.sdk.grpc.Message result = ProtoUtils.ToProto.message(SIMPLE_MESSAGE); assertEquals("context-1234", result.getContextId()); assertEquals("message-1234", result.getMessageId()); assertEquals(ROLE_USER, result.getRole()); @@ -213,7 +213,7 @@ public void convertTaskPushNotificationConfig() { .taskId("push-task-123") .url("http://example.com") .build(); - io.a2a.grpc.TaskPushNotificationConfig result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); + org.a2aproject.sdk.grpc.TaskPushNotificationConfig result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); assertEquals("push-task-123", result.getTaskId()); assertEquals("xyz", result.getId()); assertEquals("http://example.com", result.getUrl()); @@ -244,7 +244,7 @@ public void convertTaskArtifactUpdateEvent() { .artifactId("11") .parts(new TextPart("text")) .build()).build(); - io.a2a.grpc.TaskArtifactUpdateEvent result = ProtoUtils.ToProto.taskArtifactUpdateEvent(task); + org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent result = ProtoUtils.ToProto.taskArtifactUpdateEvent(task); assertEquals("task-123", result.getTaskId()); assertEquals("session-123", result.getContextId()); assertNotNull(result.getArtifact()); @@ -264,12 +264,12 @@ public void convertTaskStatusUpdateEvent() { completedStatus.state().isFinal(), // Derive from state null ); - io.a2a.grpc.TaskStatusUpdateEvent result = ProtoUtils.ToProto.taskStatusUpdateEvent(tsue); + org.a2aproject.sdk.grpc.TaskStatusUpdateEvent result = ProtoUtils.ToProto.taskStatusUpdateEvent(tsue); assertEquals("1234", result.getTaskId()); assertEquals("xyz", result.getContextId()); // Note: isFinal field has been removed from the proto (field 4 is reserved) // It is now derived from status.state().isFinal() - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_COMPLETED, result.getStatus().getState()); + assertEquals(org.a2aproject.sdk.grpc.TaskState.TASK_STATE_COMPLETED, result.getStatus().getState()); } @Test @@ -293,7 +293,7 @@ public void convertTaskTimestampStatus() { .status(testStatus) .build(); - io.a2a.grpc.Task grpcTask = ProtoUtils.ToProto.task(task); + org.a2aproject.sdk.grpc.Task grpcTask = ProtoUtils.ToProto.task(task); task = ProtoUtils.FromProto.task(grpcTask); TaskStatus status = task.status(); assertEquals(TaskState.TASK_STATE_COMPLETED, status.state()); @@ -308,7 +308,7 @@ public void convertDeleteTaskPushNotificationConfigRequest() { "config-456" ); - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result = + org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest result = ProtoUtils.ToProto.deleteTaskPushNotificationConfigRequest(params); assertEquals("task-123", result.getTaskId()); @@ -325,7 +325,7 @@ public void convertDeleteTaskPushNotificationConfigRequest() { public void convertListTaskPushNotificationConfigsRequest() { ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams("task-789"); - io.a2a.grpc.ListTaskPushNotificationConfigsRequest result = + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest result = ProtoUtils.ToProto.listTaskPushNotificationConfigsRequest(params); assertEquals("task-789", result.getTaskId()); diff --git a/spec/src/main/java/io/a2a/spec/A2AClientError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientError.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/A2AClientError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AClientError.java index 018c468a5..fd8dd980c 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientError.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Base exception for A2A client-specific error conditions. diff --git a/spec/src/main/java/io/a2a/spec/A2AClientException.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientException.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/A2AClientException.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AClientException.java index 72eeebd47..058eb5cb5 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientException.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientException.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Exception indicating a client-side failure in A2A Protocol operations. diff --git a/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java index 5e7cd33a1..b840286be 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; /** * Client exception indicating an HTTP transport error with a specific status code. diff --git a/spec/src/main/java/io/a2a/spec/A2AClientInvalidArgsError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientInvalidArgsError.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/A2AClientInvalidArgsError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AClientInvalidArgsError.java index ecf87e395..ff51b6f39 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientInvalidArgsError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientInvalidArgsError.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Client exception indicating invalid arguments provided to a client operation. diff --git a/spec/src/main/java/io/a2a/spec/A2AClientInvalidStateError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientInvalidStateError.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/A2AClientInvalidStateError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AClientInvalidStateError.java index f710a85b3..eebd5a2e0 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientInvalidStateError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientInvalidStateError.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Client exception indicating an invalid state for the requested operation. diff --git a/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientJSONError.java similarity index 93% rename from spec/src/main/java/io/a2a/spec/A2AClientJSONError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AClientJSONError.java index 3cf7fa7ab..4620bac89 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientJSONError.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Client exception indicating a JSON serialization or deserialization error. @@ -17,7 +17,7 @@ *
                      {@code
                        * try {
                        *     AgentCard card = objectMapper.readValue(json, AgentCard.class);
                      - * } catch (io.a2a.json.JsonProcessingException e) {
                      + * } catch (org.a2aproject.sdk.json.JsonProcessingException e) {
                        *     throw new A2AClientJSONError("Failed to parse agent card", e);
                        * }
                        * }
                      diff --git a/spec/src/main/java/io/a2a/spec/A2AError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AError.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/A2AError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AError.java index eaec2b0fe..1b076cbde 100644 --- a/spec/src/main/java/io/a2a/spec/A2AError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AError.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AErrorCodes.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/A2AErrorCodes.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AErrorCodes.java index 1143d7dfc..79129944c 100644 --- a/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AErrorCodes.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/A2AException.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AException.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/A2AException.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AException.java index e48b5fc81..0283c318e 100644 --- a/spec/src/main/java/io/a2a/spec/A2AException.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AException.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Base exception for A2A Protocol-related failures. diff --git a/spec/src/main/java/io/a2a/spec/A2AMethods.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AMethods.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/A2AMethods.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AMethods.java index 782fa0d2e..65eec783b 100644 --- a/spec/src/main/java/io/a2a/spec/A2AMethods.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AMethods.java @@ -1,5 +1,5 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Constants defining the A2A protocol method names. diff --git a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AProtocolError.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/A2AProtocolError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AProtocolError.java index dfa4e961e..e17df3733 100644 --- a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AProtocolError.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/A2AServerException.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AServerException.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/A2AServerException.java rename to spec/src/main/java/org/a2aproject/sdk/spec/A2AServerException.java index e2d2cf85c..1bb4c1d15 100644 --- a/spec/src/main/java/io/a2a/spec/A2AServerException.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AServerException.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Exception indicating a server-side failure in A2A Protocol operations. diff --git a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java b/spec/src/main/java/org/a2aproject/sdk/spec/APIKeySecurityScheme.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java rename to spec/src/main/java/org/a2aproject/sdk/spec/APIKeySecurityScheme.java index 676d43835..88cff4596 100644 --- a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/APIKeySecurityScheme.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCapabilities.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/AgentCapabilities.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AgentCapabilities.java index e36088a42..0503dc209 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCapabilities.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.List; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/AgentCard.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/AgentCard.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java index 4bfca0284..af9a9ce2b 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCard.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java @@ -1,11 +1,11 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/AgentCardSignature.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCardSignature.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/AgentCardSignature.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AgentCardSignature.java index f87a9b25a..9d39a844f 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCardSignature.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCardSignature.java @@ -1,9 +1,9 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; import com.google.gson.annotations.SerializedName; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/AgentExtension.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentExtension.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/AgentExtension.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AgentExtension.java index de454efad..e5f06fbce 100644 --- a/spec/src/main/java/io/a2a/spec/AgentExtension.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentExtension.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/AgentInterface.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentInterface.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/AgentInterface.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AgentInterface.java index dccf4cc75..c14147eee 100644 --- a/spec/src/main/java/io/a2a/spec/AgentInterface.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentInterface.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; /** * Declares a combination of a target URL and protocol binding for accessing an agent. diff --git a/spec/src/main/java/io/a2a/spec/AgentProvider.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentProvider.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/AgentProvider.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AgentProvider.java index b78a7702b..9b0d063f4 100644 --- a/spec/src/main/java/io/a2a/spec/AgentProvider.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentProvider.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; /** * Represents information about the organization or entity providing an agent. diff --git a/spec/src/main/java/io/a2a/spec/AgentSkill.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentSkill.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/AgentSkill.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AgentSkill.java index 2bddf57bf..a081afd1e 100644 --- a/spec/src/main/java/io/a2a/spec/AgentSkill.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentSkill.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.List; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/Artifact.java b/spec/src/main/java/org/a2aproject/sdk/spec/Artifact.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/Artifact.java rename to spec/src/main/java/org/a2aproject/sdk/spec/Artifact.java index 6f9b5dc68..8053fd5f0 100644 --- a/spec/src/main/java/io/a2a/spec/Artifact.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/Artifact.java @@ -1,9 +1,9 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.List; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java b/spec/src/main/java/org/a2aproject/sdk/spec/AuthenticationInfo.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/AuthenticationInfo.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AuthenticationInfo.java index 347b7d10e..d54ae2a77 100644 --- a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AuthenticationInfo.java @@ -1,7 +1,7 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; /** * Authentication information for agent authentication and push notification endpoints. diff --git a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java b/spec/src/main/java/org/a2aproject/sdk/spec/AuthorizationCodeOAuthFlow.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java rename to spec/src/main/java/org/a2aproject/sdk/spec/AuthorizationCodeOAuthFlow.java index d3d399057..22166270f 100644 --- a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AuthorizationCodeOAuthFlow.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; /** * Configuration for the OAuth 2.0 Authorization Code flow. diff --git a/spec/src/main/java/io/a2a/spec/CancelTaskParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/CancelTaskParams.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/CancelTaskParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/CancelTaskParams.java index 2eee837e4..d950f1793 100644 --- a/spec/src/main/java/io/a2a/spec/CancelTaskParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/CancelTaskParams.java @@ -1,7 +1,7 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; -import io.a2a.util.Utils; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.util.Utils; import java.util.Collections; import java.util.Map; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java b/spec/src/main/java/org/a2aproject/sdk/spec/ClientCredentialsOAuthFlow.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java rename to spec/src/main/java/org/a2aproject/sdk/spec/ClientCredentialsOAuthFlow.java index f248eaa70..6d056fdb0 100644 --- a/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/ClientCredentialsOAuthFlow.java @@ -1,9 +1,9 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; /** * Configuration for the OAuth 2.0 Client Credentials flow. diff --git a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java b/spec/src/main/java/org/a2aproject/sdk/spec/ContentTypeNotSupportedError.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/ContentTypeNotSupportedError.java index b87addb87..a6dfbbc88 100644 --- a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/ContentTypeNotSupportedError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/DataPart.java b/spec/src/main/java/org/a2aproject/sdk/spec/DataPart.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/DataPart.java rename to spec/src/main/java/org/a2aproject/sdk/spec/DataPart.java index 3ed726d68..7724ec24e 100644 --- a/spec/src/main/java/io/a2a/spec/DataPart.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/DataPart.java @@ -1,11 +1,11 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; import com.google.gson.ToNumberPolicy; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import java.util.Map; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/DeleteTaskPushNotificationConfigParams.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/DeleteTaskPushNotificationConfigParams.java index 12d6c0624..96728e8fe 100644 --- a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/DeleteTaskPushNotificationConfigParams.java @@ -1,9 +1,9 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; -import io.a2a.util.Utils; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java b/spec/src/main/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlow.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java rename to spec/src/main/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlow.java index d2d25c047..f78895450 100644 --- a/spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlow.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; /** * Configuration details for the OAuth 2.0 Device Code flow (RFC 8628). diff --git a/spec/src/main/java/io/a2a/spec/Event.java b/spec/src/main/java/org/a2aproject/sdk/spec/Event.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/Event.java rename to spec/src/main/java/org/a2aproject/sdk/spec/Event.java index 2be6a757f..ebd01998b 100644 --- a/spec/src/main/java/io/a2a/spec/Event.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/Event.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Marker interface for all event types in the A2A Protocol. diff --git a/spec/src/main/java/io/a2a/spec/EventKind.java b/spec/src/main/java/org/a2aproject/sdk/spec/EventKind.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/EventKind.java rename to spec/src/main/java/org/a2aproject/sdk/spec/EventKind.java index a9713859b..8e1453a8c 100644 --- a/spec/src/main/java/io/a2a/spec/EventKind.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/EventKind.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Interface for events that can be returned from non-streaming A2A Protocol operations. diff --git a/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java b/spec/src/main/java/org/a2aproject/sdk/spec/ExtendedAgentCardNotConfiguredError.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/ExtendedAgentCardNotConfiguredError.java index 941788abd..aa778721d 100644 --- a/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/ExtendedAgentCardNotConfiguredError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java b/spec/src/main/java/org/a2aproject/sdk/spec/ExtensionSupportRequiredError.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/ExtensionSupportRequiredError.java index fd7882202..8fd91c376 100644 --- a/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/ExtensionSupportRequiredError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/FileContent.java b/spec/src/main/java/org/a2aproject/sdk/spec/FileContent.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/FileContent.java rename to spec/src/main/java/org/a2aproject/sdk/spec/FileContent.java index f258e3eb5..2f96bb4b5 100644 --- a/spec/src/main/java/io/a2a/spec/FileContent.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/FileContent.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Sealed interface representing file content in the A2A Protocol. diff --git a/spec/src/main/java/io/a2a/spec/FilePart.java b/spec/src/main/java/org/a2aproject/sdk/spec/FilePart.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/FilePart.java rename to spec/src/main/java/org/a2aproject/sdk/spec/FilePart.java index 8deec1e7d..dc883794e 100644 --- a/spec/src/main/java/io/a2a/spec/FilePart.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/FilePart.java @@ -1,7 +1,7 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import java.util.Map; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/FileWithBytes.java b/spec/src/main/java/org/a2aproject/sdk/spec/FileWithBytes.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/FileWithBytes.java rename to spec/src/main/java/org/a2aproject/sdk/spec/FileWithBytes.java index 53e448c5f..15e26b566 100644 --- a/spec/src/main/java/io/a2a/spec/FileWithBytes.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/FileWithBytes.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; diff --git a/spec/src/main/java/io/a2a/spec/FileWithUri.java b/spec/src/main/java/org/a2aproject/sdk/spec/FileWithUri.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/FileWithUri.java rename to spec/src/main/java/org/a2aproject/sdk/spec/FileWithUri.java index b3fb72363..338420cbd 100644 --- a/spec/src/main/java/io/a2a/spec/FileWithUri.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/FileWithUri.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Represents file content referenced by a URI location. diff --git a/spec/src/main/java/io/a2a/spec/GetExtendedAgentCardParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/GetExtendedAgentCardParams.java similarity index 90% rename from spec/src/main/java/io/a2a/spec/GetExtendedAgentCardParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/GetExtendedAgentCardParams.java index c103c6a2a..55a4a2b76 100644 --- a/spec/src/main/java/io/a2a/spec/GetExtendedAgentCardParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/GetExtendedAgentCardParams.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/GetTaskPushNotificationConfigParams.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/GetTaskPushNotificationConfigParams.java index f51063bcf..0d2bfc453 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/GetTaskPushNotificationConfigParams.java @@ -1,9 +1,9 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; -import io.a2a.util.Utils; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java b/spec/src/main/java/org/a2aproject/sdk/spec/HTTPAuthSecurityScheme.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java rename to spec/src/main/java/org/a2aproject/sdk/spec/HTTPAuthSecurityScheme.java index a34c64239..be0c4f13c 100644 --- a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/HTTPAuthSecurityScheme.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/InternalError.java b/spec/src/main/java/org/a2aproject/sdk/spec/InternalError.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/InternalError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/InternalError.java index d6809f314..fc8565823 100644 --- a/spec/src/main/java/io/a2a/spec/InternalError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/InternalError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java b/spec/src/main/java/org/a2aproject/sdk/spec/InvalidAgentResponseError.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/InvalidAgentResponseError.java index c6c2c2cc2..baff3db79 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/InvalidAgentResponseError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java b/spec/src/main/java/org/a2aproject/sdk/spec/InvalidParamsError.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/InvalidParamsError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/InvalidParamsError.java index 6c6751d41..89c1b58ac 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/InvalidParamsError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java b/spec/src/main/java/org/a2aproject/sdk/spec/InvalidRequestError.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/InvalidRequestError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/InvalidRequestError.java index 151f0631f..acf6d425a 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/InvalidRequestError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/JSONParseError.java b/spec/src/main/java/org/a2aproject/sdk/spec/JSONParseError.java similarity index 92% rename from spec/src/main/java/io/a2a/spec/JSONParseError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/JSONParseError.java index 5349add2d..6e976d9aa 100644 --- a/spec/src/main/java/io/a2a/spec/JSONParseError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/JSONParseError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; @@ -19,7 +19,7 @@ *
                      {@code
                        * try {
                        *     objectMapper.readValue(payload, JSONRPCRequest.class);
                      - * } catch (io.a2a.json.JsonProcessingException e) {
                      + * } catch (org.a2aproject.sdk.json.JsonProcessingException e) {
                        *     throw new JSONParseError("Malformed JSON: " + e.getMessage());
                        * }
                        * }
                      diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/ListTaskPushNotificationConfigsParams.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/ListTaskPushNotificationConfigsParams.java index 9f39987fb..1e2389b16 100644 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/ListTaskPushNotificationConfigsParams.java @@ -1,7 +1,7 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; -import io.a2a.util.Utils; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsResult.java b/spec/src/main/java/org/a2aproject/sdk/spec/ListTaskPushNotificationConfigsResult.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsResult.java rename to spec/src/main/java/org/a2aproject/sdk/spec/ListTaskPushNotificationConfigsResult.java index a2b9ebb4f..b8cffea07 100644 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigsResult.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/ListTaskPushNotificationConfigsResult.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.List; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/ListTasksParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/ListTasksParams.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/ListTasksParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/ListTasksParams.java index 3a1680af9..ee4387d26 100644 --- a/spec/src/main/java/io/a2a/spec/ListTasksParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/ListTasksParams.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import java.time.Instant; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/Message.java b/spec/src/main/java/org/a2aproject/sdk/spec/Message.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/Message.java rename to spec/src/main/java/org/a2aproject/sdk/spec/Message.java index 4459fd5b7..4587521d6 100644 --- a/spec/src/main/java/io/a2a/spec/Message.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/Message.java @@ -1,10 +1,10 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.List; import java.util.Map; import java.util.UUID; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java b/spec/src/main/java/org/a2aproject/sdk/spec/MessageSendConfiguration.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java rename to spec/src/main/java/org/a2aproject/sdk/spec/MessageSendConfiguration.java index a15e5da64..52ff37e70 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/MessageSendConfiguration.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.List; diff --git a/spec/src/main/java/io/a2a/spec/MessageSendParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/MessageSendParams.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/MessageSendParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/MessageSendParams.java index e1c75a668..bb0156d99 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/MessageSendParams.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java b/spec/src/main/java/org/a2aproject/sdk/spec/MethodNotFoundError.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/MethodNotFoundError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/MethodNotFoundError.java index b97f5acae..3d7d0a59f 100644 --- a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/MethodNotFoundError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java b/spec/src/main/java/org/a2aproject/sdk/spec/MutualTLSSecurityScheme.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java rename to spec/src/main/java/org/a2aproject/sdk/spec/MutualTLSSecurityScheme.java index 7210e1db7..50ed0fc77 100644 --- a/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/MutualTLSSecurityScheme.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * 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/org/a2aproject/sdk/spec/OAuth2SecurityScheme.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java rename to spec/src/main/java/org/a2aproject/sdk/spec/OAuth2SecurityScheme.java index 85e0f76cb..322cdebdb 100644 --- a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/OAuth2SecurityScheme.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/OAuthFlows.java b/spec/src/main/java/org/a2aproject/sdk/spec/OAuthFlows.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/OAuthFlows.java rename to spec/src/main/java/org/a2aproject/sdk/spec/OAuthFlows.java index 4349c4906..805973fbf 100644 --- a/spec/src/main/java/io/a2a/spec/OAuthFlows.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/OAuthFlows.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java b/spec/src/main/java/org/a2aproject/sdk/spec/OpenIdConnectSecurityScheme.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java rename to spec/src/main/java/org/a2aproject/sdk/spec/OpenIdConnectSecurityScheme.java index 371f18982..532c9fd25 100644 --- a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/OpenIdConnectSecurityScheme.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/Part.java b/spec/src/main/java/org/a2aproject/sdk/spec/Part.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/Part.java rename to spec/src/main/java/org/a2aproject/sdk/spec/Part.java index 631f87f88..f9678e838 100644 --- a/spec/src/main/java/io/a2a/spec/Part.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/Part.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Base interface for content parts within {@link Message}s and {@link Artifact}s. diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java b/spec/src/main/java/org/a2aproject/sdk/spec/PushNotificationNotSupportedError.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/PushNotificationNotSupportedError.java index e167bb64a..7c347f868 100644 --- a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/PushNotificationNotSupportedError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/SecurityRequirement.java b/spec/src/main/java/org/a2aproject/sdk/spec/SecurityRequirement.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/SecurityRequirement.java rename to spec/src/main/java/org/a2aproject/sdk/spec/SecurityRequirement.java index 1a3729369..eca8d0d01 100644 --- a/spec/src/main/java/io/a2a/spec/SecurityRequirement.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/SecurityRequirement.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import static java.util.Collections.unmodifiableMap; @@ -6,7 +6,7 @@ import java.util.List; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; /** * Represents a security requirement in the A2A Protocol. diff --git a/spec/src/main/java/io/a2a/spec/SecurityScheme.java b/spec/src/main/java/org/a2aproject/sdk/spec/SecurityScheme.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/SecurityScheme.java rename to spec/src/main/java/org/a2aproject/sdk/spec/SecurityScheme.java index 0fad71ed7..0f47b2b0e 100644 --- a/spec/src/main/java/io/a2a/spec/SecurityScheme.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/SecurityScheme.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Base interface for security schemes used to authenticate access to agent endpoints. diff --git a/spec/src/main/java/io/a2a/spec/StreamingEventKind.java b/spec/src/main/java/org/a2aproject/sdk/spec/StreamingEventKind.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/StreamingEventKind.java rename to spec/src/main/java/org/a2aproject/sdk/spec/StreamingEventKind.java index a8d0dd628..0cfe02d30 100644 --- a/spec/src/main/java/io/a2a/spec/StreamingEventKind.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/StreamingEventKind.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Sealed interface for events that can be emitted during streaming A2A Protocol operations. diff --git a/spec/src/main/java/io/a2a/spec/Task.java b/spec/src/main/java/org/a2aproject/sdk/spec/Task.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/Task.java rename to spec/src/main/java/org/a2aproject/sdk/spec/Task.java index fd7cfce01..d592dedea 100644 --- a/spec/src/main/java/io/a2a/spec/Task.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/Task.java @@ -1,9 +1,9 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.List; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskArtifactUpdateEvent.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskArtifactUpdateEvent.java index 1d009673d..459334aee 100644 --- a/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskArtifactUpdateEvent.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.util.Map; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/TaskIdParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskIdParams.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/TaskIdParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskIdParams.java index f61c74684..1bef6d7a9 100644 --- a/spec/src/main/java/io/a2a/spec/TaskIdParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskIdParams.java @@ -1,7 +1,7 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; -import io.a2a.util.Utils; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskNotCancelableError.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskNotCancelableError.java index 49d86fa52..441206c57 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskNotCancelableError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskNotFoundError.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/TaskNotFoundError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskNotFoundError.java index 817175f84..628dd4472 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskNotFoundError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskPushNotificationConfig.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskPushNotificationConfig.java index 7f1d21b91..571300120 100644 --- a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskPushNotificationConfig.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/TaskQueryParams.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskQueryParams.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/TaskQueryParams.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskQueryParams.java index 9f5805f98..281357929 100644 --- a/spec/src/main/java/io/a2a/spec/TaskQueryParams.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskQueryParams.java @@ -1,7 +1,7 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; -import io.a2a.util.Utils; +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/TaskState.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskState.java similarity index 99% rename from spec/src/main/java/io/a2a/spec/TaskState.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskState.java index 831ac0fb5..2044581b1 100644 --- a/spec/src/main/java/io/a2a/spec/TaskState.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskState.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Defines the lifecycle states of a {@link Task} in the A2A Protocol. diff --git a/spec/src/main/java/io/a2a/spec/TaskStatus.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskStatus.java similarity index 97% rename from spec/src/main/java/io/a2a/spec/TaskStatus.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskStatus.java index 95e70da0d..5f8cb1466 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatus.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskStatus.java @@ -1,8 +1,8 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import java.time.OffsetDateTime; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import java.time.ZoneOffset; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskStatusUpdateEvent.java similarity index 92% rename from spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TaskStatusUpdateEvent.java index bacf9afc6..f56339bdc 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskStatusUpdateEvent.java @@ -1,15 +1,15 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.spec.TaskState.TASK_STATE_CANCELED; -import static io.a2a.spec.TaskState.TASK_STATE_COMPLETED; -import static io.a2a.spec.TaskState.TASK_STATE_FAILED; -import static io.a2a.spec.TaskState.TASK_STATE_INPUT_REQUIRED; -import static io.a2a.spec.TaskState.TASK_STATE_REJECTED; +import static org.a2aproject.sdk.spec.TaskState.TASK_STATE_CANCELED; +import static org.a2aproject.sdk.spec.TaskState.TASK_STATE_COMPLETED; +import static org.a2aproject.sdk.spec.TaskState.TASK_STATE_FAILED; +import static org.a2aproject.sdk.spec.TaskState.TASK_STATE_INPUT_REQUIRED; +import static org.a2aproject.sdk.spec.TaskState.TASK_STATE_REJECTED; import java.util.Map; import com.google.gson.annotations.SerializedName; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/spec/TextPart.java b/spec/src/main/java/org/a2aproject/sdk/spec/TextPart.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/TextPart.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TextPart.java index e76cdd19d..5cf9f9ab4 100644 --- a/spec/src/main/java/io/a2a/spec/TextPart.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TextPart.java @@ -1,7 +1,7 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import io.a2a.util.Assert; +import org.a2aproject.sdk.util.Assert; import java.util.Map; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/spec/TransportProtocol.java b/spec/src/main/java/org/a2aproject/sdk/spec/TransportProtocol.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/TransportProtocol.java rename to spec/src/main/java/org/a2aproject/sdk/spec/TransportProtocol.java index 4c852903b..b4e614f6d 100644 --- a/spec/src/main/java/io/a2a/spec/TransportProtocol.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TransportProtocol.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Enumeration of supported transport protocols for A2A Protocol communication. diff --git a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java b/spec/src/main/java/org/a2aproject/sdk/spec/UnsupportedOperationError.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/UnsupportedOperationError.java index a0ced6f74..fad7291df 100644 --- a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/UnsupportedOperationError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/UpdateEvent.java b/spec/src/main/java/org/a2aproject/sdk/spec/UpdateEvent.java similarity index 96% rename from spec/src/main/java/io/a2a/spec/UpdateEvent.java rename to spec/src/main/java/org/a2aproject/sdk/spec/UpdateEvent.java index 996977498..386e3173a 100644 --- a/spec/src/main/java/io/a2a/spec/UpdateEvent.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/UpdateEvent.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; /** * Sealed interface for incremental update events during task execution. diff --git a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java b/spec/src/main/java/org/a2aproject/sdk/spec/VersionNotSupportedError.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java rename to spec/src/main/java/org/a2aproject/sdk/spec/VersionNotSupportedError.java index 41dbed471..e0eaed2b4 100644 --- a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/VersionNotSupportedError.java @@ -1,6 +1,6 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; -import static io.a2a.util.Utils.defaultIfNull; +import static org.a2aproject.sdk.util.Utils.defaultIfNull; import java.util.Map; diff --git a/spec/src/main/java/io/a2a/spec/package-info.java b/spec/src/main/java/org/a2aproject/sdk/spec/package-info.java similarity index 89% rename from spec/src/main/java/io/a2a/spec/package-info.java rename to spec/src/main/java/org/a2aproject/sdk/spec/package-info.java index f91b3a08c..6184a7d57 100644 --- a/spec/src/main/java/io/a2a/spec/package-info.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/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.spec; +package org.a2aproject.sdk.spec; diff --git a/spec/src/main/java/io/a2a/util/PageToken.java b/spec/src/main/java/org/a2aproject/sdk/util/PageToken.java similarity index 96% rename from spec/src/main/java/io/a2a/util/PageToken.java rename to spec/src/main/java/org/a2aproject/sdk/util/PageToken.java index c703a903a..4e27e39b4 100644 --- a/spec/src/main/java/io/a2a/util/PageToken.java +++ b/spec/src/main/java/org/a2aproject/sdk/util/PageToken.java @@ -1,8 +1,8 @@ -package io.a2a.util; +package org.a2aproject.sdk.util; import java.time.Instant; -import io.a2a.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidParamsError; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/util/Utils.java b/spec/src/main/java/org/a2aproject/sdk/util/Utils.java similarity index 96% rename from spec/src/main/java/io/a2a/util/Utils.java rename to spec/src/main/java/org/a2aproject/sdk/util/Utils.java index 68fe2bef7..36de686b2 100644 --- a/spec/src/main/java/io/a2a/util/Utils.java +++ b/spec/src/main/java/org/a2aproject/sdk/util/Utils.java @@ -1,6 +1,6 @@ -package io.a2a.util; +package org.a2aproject.sdk.util; -import static io.a2a.util.Assert.checkNotNullParam; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; import java.util.ArrayList; import java.util.HashMap; @@ -9,13 +9,13 @@ import java.util.logging.Logger; import com.google.gson.Gson; -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 org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; import org.jspecify.annotations.Nullable; /** diff --git a/spec/src/main/java/io/a2a/util/package-info.java b/spec/src/main/java/org/a2aproject/sdk/util/package-info.java similarity index 78% rename from spec/src/main/java/io/a2a/util/package-info.java rename to spec/src/main/java/org/a2aproject/sdk/util/package-info.java index 78adaa656..86921d528 100644 --- a/spec/src/main/java/io/a2a/util/package-info.java +++ b/spec/src/main/java/org/a2aproject/sdk/util/package-info.java @@ -2,7 +2,7 @@ * Utility classes and helpers for the A2A Java SDK. */ @NullMarked -package io.a2a.util; +package org.a2aproject.sdk.util; import org.jspecify.annotations.NullMarked; diff --git a/spec/src/test/java/io/a2a/spec/DataPartTest.java b/spec/src/test/java/org/a2aproject/sdk/spec/DataPartTest.java similarity index 98% rename from spec/src/test/java/io/a2a/spec/DataPartTest.java rename to spec/src/test/java/org/a2aproject/sdk/spec/DataPartTest.java index 93f8d477a..73fa6f366 100644 --- a/spec/src/test/java/io/a2a/spec/DataPartTest.java +++ b/spec/src/test/java/org/a2aproject/sdk/spec/DataPartTest.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; diff --git a/spec/src/test/java/io/a2a/spec/FileWithBytesTest.java b/spec/src/test/java/org/a2aproject/sdk/spec/FileWithBytesTest.java similarity index 99% rename from spec/src/test/java/io/a2a/spec/FileWithBytesTest.java rename to spec/src/test/java/org/a2aproject/sdk/spec/FileWithBytesTest.java index 5cf556198..53ea9268b 100644 --- a/spec/src/test/java/io/a2a/spec/FileWithBytesTest.java +++ b/spec/src/test/java/org/a2aproject/sdk/spec/FileWithBytesTest.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package org.a2aproject.sdk.spec; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/spec/src/test/java/io/a2a/util/PageTokenTest.java b/spec/src/test/java/org/a2aproject/sdk/util/PageTokenTest.java similarity index 98% rename from spec/src/test/java/io/a2a/util/PageTokenTest.java rename to spec/src/test/java/org/a2aproject/sdk/util/PageTokenTest.java index aef9c8192..0ee373210 100644 --- a/spec/src/test/java/io/a2a/util/PageTokenTest.java +++ b/spec/src/test/java/org/a2aproject/sdk/util/PageTokenTest.java @@ -1,4 +1,4 @@ -package io.a2a.util; +package org.a2aproject.sdk.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -8,7 +8,7 @@ import java.time.Instant; import java.util.stream.Stream; -import io.a2a.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidParamsError; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; diff --git a/spec/src/test/java/io/a2a/util/UtilsTest.java b/spec/src/test/java/org/a2aproject/sdk/util/UtilsTest.java similarity index 99% rename from spec/src/test/java/io/a2a/util/UtilsTest.java rename to spec/src/test/java/org/a2aproject/sdk/util/UtilsTest.java index d5695a8af..3304149f1 100644 --- a/spec/src/test/java/io/a2a/util/UtilsTest.java +++ b/spec/src/test/java/org/a2aproject/sdk/util/UtilsTest.java @@ -1,10 +1,10 @@ -package io.a2a.util; +package org.a2aproject.sdk.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import io.a2a.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentInterface; import org.junit.jupiter.api.Test; /** diff --git a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java b/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentCardProducer.java similarity index 87% rename from tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java rename to tck/src/main/java/org/a2aproject/sdk/tck/server/AgentCardProducer.java index 571e2bb1f..15262001f 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java +++ b/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentCardProducer.java @@ -1,4 +1,4 @@ -package io.a2a.tck.server; +package org.a2aproject.sdk.tck.server; import java.util.Collections; @@ -7,12 +7,12 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.TransportProtocol; @ApplicationScoped public class AgentCardProducer { diff --git a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java b/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentExecutorProducer.java similarity index 89% rename from tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java rename to tck/src/main/java/org/a2aproject/sdk/tck/server/AgentExecutorProducer.java index b69a902e4..55bd4a71b 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java +++ b/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentExecutorProducer.java @@ -1,4 +1,4 @@ -package io.a2a.tck.server; +package org.a2aproject.sdk.tck.server; import java.util.List; @@ -6,14 +6,14 @@ 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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; @ApplicationScoped public class AgentExecutorProducer { diff --git a/tck/src/main/java/io/a2a/tck/server/package-info.java b/tck/src/main/java/org/a2aproject/sdk/tck/server/package-info.java similarity index 84% rename from tck/src/main/java/io/a2a/tck/server/package-info.java rename to tck/src/main/java/org/a2aproject/sdk/tck/server/package-info.java index f2b9319f2..dc93d6473 100644 --- a/tck/src/main/java/io/a2a/tck/server/package-info.java +++ b/tck/src/main/java/org/a2aproject/sdk/tck/server/package-info.java @@ -1,5 +1,5 @@ @NullMarked -package io.a2a.tck.server; +package org.a2aproject.sdk.tck.server; import org.jspecify.annotations.NullMarked; diff --git a/tck/src/main/resources/application.properties b/tck/src/main/resources/application.properties index b23747b00..b9b442693 100644 --- a/tck/src/main/resources/application.properties +++ b/tck/src/main/resources/application.properties @@ -9,10 +9,10 @@ a2a.executor.max-pool-size=15 a2a.executor.keep-alive-seconds=60 # Enable debug logging for troubleshooting TCK failures -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.tasks".level=DEBUG -io.a2a.server.diagnostics.ThreadStats.level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG +org.a2aproject.sdk.server.diagnostics.ThreadStats.level=DEBUG # Log to file for analysis quarkus.log.file.enable=true diff --git a/test-utils-docker/README.md b/test-utils-docker/README.md index 9544fc3e1..c80730b7e 100644 --- a/test-utils-docker/README.md +++ b/test-utils-docker/README.md @@ -21,7 +21,7 @@ Add the dependency to your test module: Annotate test classes that require Docker: ```java -import io.a2a.testutils.docker.RequiresDocker; +import org.a2aproject.sdk.testutils.docker.RequiresDocker; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; diff --git a/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerAvailability.java b/test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/DockerAvailability.java similarity index 98% rename from test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerAvailability.java rename to test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/DockerAvailability.java index 3d5b6b4fb..70a92a3ee 100644 --- a/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerAvailability.java +++ b/test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/DockerAvailability.java @@ -1,4 +1,4 @@ -package io.a2a.testutils.docker; +package org.a2aproject.sdk.testutils.docker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerRequiredExtension.java b/test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/DockerRequiredExtension.java similarity index 97% rename from test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerRequiredExtension.java rename to test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/DockerRequiredExtension.java index f1b89b160..491a63496 100644 --- a/test-utils-docker/src/main/java/io/a2a/testutils/docker/DockerRequiredExtension.java +++ b/test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/DockerRequiredExtension.java @@ -1,4 +1,4 @@ -package io.a2a.testutils.docker; +package org.a2aproject.sdk.testutils.docker; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; diff --git a/test-utils-docker/src/main/java/io/a2a/testutils/docker/RequiresDocker.java b/test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/RequiresDocker.java similarity index 95% rename from test-utils-docker/src/main/java/io/a2a/testutils/docker/RequiresDocker.java rename to test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/RequiresDocker.java index d34e7104c..08b7ce0ba 100644 --- a/test-utils-docker/src/main/java/io/a2a/testutils/docker/RequiresDocker.java +++ b/test-utils-docker/src/main/java/org/a2aproject/sdk/testutils/docker/RequiresDocker.java @@ -1,4 +1,4 @@ -package io.a2a.testutils.docker; +package org.a2aproject.sdk.testutils.docker; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/A2AGsonObjectMapper.java similarity index 85% rename from tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/A2AGsonObjectMapper.java index c64e5051c..f4145e9cc 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/A2AGsonObjectMapper.java @@ -2,10 +2,10 @@ * Copyright The WildFly Authors * SPDX-License-Identifier: Apache-2.0 */ -package io.a2a.server.apps.common; +package org.a2aproject.sdk.server.apps.common; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.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/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java similarity index 97% rename from tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index 8f44d045b..8d75f783a 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -1,6 +1,6 @@ -package io.a2a.server.apps.common; +package org.a2aproject.sdk.server.apps.common; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -34,57 +34,57 @@ import jakarta.ws.rs.core.MediaType; -import io.a2a.client.Client; -import io.a2a.client.ClientBuilder; -import io.a2a.client.ClientEvent; -import io.a2a.client.MessageEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -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; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Artifact; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.Event; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; -import io.a2a.spec.UnsupportedOperationError; - import io.restassured.RestAssured; import io.restassured.config.ObjectMapperConfig; import io.restassured.specification.RequestSpecification; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.MessageEvent; +import org.a2aproject.sdk.client.TaskEvent; +import org.a2aproject.sdk.client.TaskUpdateEvent; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AErrorResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.StreamingJSONRPCRequest; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.UpdateEvent; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -272,7 +272,7 @@ public void testListTasksSuccess() throws Exception { try { // Test listing all tasks (no filters) - io.a2a.spec.ListTasksParams params = ListTasksParams.builder().tenant("").build(); + org.a2aproject.sdk.spec.ListTasksParams params = ListTasksParams.builder().tenant("").build(); ListTasksResult result = getClient().listTasks(params); assertNotNull(result); @@ -311,7 +311,7 @@ public void testListTasksFilterByContextId() throws Exception { try { // Filter by contextId - io.a2a.spec.ListTasksParams params = ListTasksParams.builder() + org.a2aproject.sdk.spec.ListTasksParams params = ListTasksParams.builder() .contextId("context-filter-1") .tenant("") .build(); @@ -352,7 +352,7 @@ public void testListTasksFilterByStatus() throws Exception { try { // Filter by status WORKING - io.a2a.spec.ListTasksParams params = ListTasksParams.builder() + org.a2aproject.sdk.spec.ListTasksParams params = ListTasksParams.builder() .status(TaskState.TASK_STATE_WORKING) .tenant("") .build(); @@ -396,7 +396,7 @@ public void testListTasksWithPagination() throws Exception { try { // Get first page with pageSize=2 - io.a2a.spec.ListTasksParams params1 = ListTasksParams.builder() + org.a2aproject.sdk.spec.ListTasksParams params1 = ListTasksParams.builder() .contextId("page-context") .tenant("") .pageSize(2) @@ -409,7 +409,7 @@ public void testListTasksWithPagination() throws Exception { assertTrue(result1.hasMoreResults()); // Get second page using pageToken - io.a2a.spec.ListTasksParams params2 = ListTasksParams.builder() + org.a2aproject.sdk.spec.ListTasksParams params2 = ListTasksParams.builder() .contextId("page-context") .tenant("") .pageSize(2) @@ -446,7 +446,7 @@ public void testListTasksWithHistoryLimit() throws Exception { try { // List with history limited to 2 messages - io.a2a.spec.ListTasksParams params = ListTasksParams.builder() + org.a2aproject.sdk.spec.ListTasksParams params = ListTasksParams.builder() .contextId("context-history") .tenant("") .historyLength(2) @@ -987,7 +987,7 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce Thread.sleep(2000); // Track events received through subscription stream - CopyOnWriteArrayList receivedEvents = new CopyOnWriteArrayList<>(); + CopyOnWriteArrayList receivedEvents = new CopyOnWriteArrayList<>(); AtomicBoolean receivedInitialTask = new AtomicBoolean(false); AtomicBoolean streamClosedPrematurely = new AtomicBoolean(false); AtomicReference subscribeErrorRef = new AtomicReference<>(); @@ -1007,7 +1007,7 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce return; } } else if (event instanceof TaskUpdateEvent taskUpdateEvent) { - io.a2a.spec.UpdateEvent updateEvent = taskUpdateEvent.getUpdateEvent(); + org.a2aproject.sdk.spec.UpdateEvent updateEvent = taskUpdateEvent.getUpdateEvent(); receivedEvents.add(updateEvent); // Check if this is the final terminal state @@ -1636,7 +1636,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { // 2. Subscribe to task (queue should still be open) CountDownLatch resubEventLatch = new CountDownLatch(2); // artifact-2 + completion - List resubReceivedEvents = new CopyOnWriteArrayList<>(); + List resubReceivedEvents = new CopyOnWriteArrayList<>(); AtomicBoolean resubUnexpectedEvent = new AtomicBoolean(false); AtomicReference resubErrorRef = new AtomicReference<>(); AtomicBoolean resubReceivedInitialTask = new AtomicBoolean(false); @@ -1700,7 +1700,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { CountDownLatch streamEventLatch = new CountDownLatch(2); // artifact-2 + completion CountDownLatch streamConsumerReadyLatch = new CountDownLatch(1); - List streamReceivedEvents = new CopyOnWriteArrayList<>(); + List streamReceivedEvents = new CopyOnWriteArrayList<>(); AtomicBoolean streamUnexpectedEvent = new AtomicBoolean(false); BiConsumer streamConsumer = (event, agentCard) -> { @@ -1972,7 +1972,7 @@ public void testAuthRequiredWorkflow() throws Exception { if (event instanceof TaskEvent te) { state = te.getTask().status().state(); } else if (event instanceof TaskUpdateEvent tue) { - io.a2a.spec.UpdateEvent updateEvent = tue.getUpdateEvent(); + org.a2aproject.sdk.spec.UpdateEvent updateEvent = tue.getUpdateEvent(); if (updateEvent instanceof TaskStatusUpdateEvent statusUpdate) { state = statusUpdate.status().state(); } else { diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java similarity index 87% rename from tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java index 06cdb17f6..12baa654e 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java @@ -1,6 +1,6 @@ -package io.a2a.server.apps.common; +package org.a2aproject.sdk.server.apps.common; -import static io.a2a.spec.TransportProtocol.GRPC; +import static org.a2aproject.sdk.spec.TransportProtocol.GRPC; import java.io.IOException; import java.io.InputStream; @@ -12,11 +12,11 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import io.a2a.server.ExtendedAgentCard; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; +import org.a2aproject.sdk.server.ExtendedAgentCard; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; import io.quarkus.arc.profile.IfBuildProfile; import org.junit.jupiter.api.Assertions; diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java similarity index 92% rename from tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java index d69d49b9b..f6f72be1d 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java @@ -1,6 +1,6 @@ -package io.a2a.server.apps.common; +package org.a2aproject.sdk.server.apps.common; -import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; +import static org.a2aproject.sdk.server.ServerCallContext.TRANSPORT_KEY; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -9,28 +9,28 @@ import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; -import io.a2a.A2A; -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.ServerCallContext; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Artifact; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; -import io.a2a.spec.UnsupportedOperationError; +import org.a2aproject.sdk.A2A; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.TaskEvent; +import org.a2aproject.sdk.client.TaskUpdateEvent; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.a2aproject.sdk.spec.UnsupportedOperationError; import io.quarkus.arc.profile.IfBuildProfile; @ApplicationScoped diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentToAgentClientFactory.java similarity index 81% rename from tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentToAgentClientFactory.java index f3c06eb66..6b81c0ef1 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentToAgentClientFactory.java @@ -1,25 +1,25 @@ -package io.a2a.server.apps.common; +package org.a2aproject.sdk.server.apps.common; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; -import io.a2a.client.Client; -import io.a2a.client.ClientBuilder; -import io.a2a.client.ClientEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfigBuilder; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Task; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.TaskEvent; +import org.a2aproject.sdk.client.TaskUpdateEvent; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransport; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TransportProtocol; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestHttpClient.java similarity index 88% rename from tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestHttpClient.java index 9b8214ed7..2bb905bb1 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestHttpClient.java @@ -1,4 +1,4 @@ -package io.a2a.server.apps.common; +package org.a2aproject.sdk.server.apps.common; import java.io.IOException; import java.util.ArrayList; @@ -12,11 +12,11 @@ import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Alternative; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.Task; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.Task; @Dependent @Alternative diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestUtilsBean.java similarity index 91% rename from tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestUtilsBean.java index 3ef300412..7e771a32f 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestUtilsBean.java @@ -1,14 +1,14 @@ -package io.a2a.server.apps.common; +package org.a2aproject.sdk.server.apps.common; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import io.a2a.server.events.QueueManager; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Event; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.Task; +import org.a2aproject.sdk.server.events.QueueManager; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.Task; /** * Contains utilities to interact with the server side for the tests. diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/context/GrpcContextKeys.java similarity index 95% rename from transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java rename to transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/context/GrpcContextKeys.java index bea363271..221c84f4a 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java +++ b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/context/GrpcContextKeys.java @@ -1,4 +1,4 @@ -package io.a2a.transport.grpc.context; +package org.a2aproject.sdk.transport.grpc.context; import static java.util.Locale.ROOT; @@ -6,8 +6,8 @@ import java.util.Locale; import java.util.Map; -import io.a2a.common.A2AHeaders; -import io.a2a.spec.A2AMethods; +import org.a2aproject.sdk.common.A2AHeaders; +import org.a2aproject.sdk.spec.A2AMethods; import io.grpc.Context; /** @@ -39,7 +39,7 @@ * * @see io.grpc.Context * @see io.grpc.Metadata - * @see io.a2a.server.ServerCallContext + * @see org.a2aproject.sdk.server.ServerCallContext */ public final class GrpcContextKeys { @@ -106,7 +106,7 @@ public final class GrpcContextKeys { *
                    • DeleteTaskPushNotification → DeleteTaskPushNotificationConfig
                    • *
                    * - * @see io.a2a.spec.A2AMethods + * @see org.a2aproject.sdk.spec.A2AMethods */ public static final Map METHOD_MAPPING = Map.of( "SendMessage", A2AMethods.SEND_MESSAGE_METHOD, diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/CallContextFactory.java similarity index 85% rename from transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java rename to transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/CallContextFactory.java index 11a8edfaf..ed44ec7b9 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java +++ b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/CallContextFactory.java @@ -1,6 +1,6 @@ -package io.a2a.transport.grpc.handler; +package org.a2aproject.sdk.transport.grpc.handler; -import io.a2a.server.ServerCallContext; +import org.a2aproject.sdk.server.ServerCallContext; import io.grpc.stub.StreamObserver; /** @@ -52,18 +52,18 @@ * * @see ServerCallContext * @see GrpcHandler#createCallContext - * @see io.a2a.transport.grpc.context.GrpcContextKeys + * @see org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys */ public interface CallContextFactory { /** * Creates a {@link ServerCallContext} from gRPC request context. * *

                    This method is called for each incoming gRPC request to create the context - * that will be passed to the {@link io.a2a.server.requesthandlers.RequestHandler} - * and eventually to the {@link io.a2a.server.agentexecution.AgentExecutor}. + * that will be passed to the {@link org.a2aproject.sdk.server.requesthandlers.RequestHandler} + * and eventually to the {@link org.a2aproject.sdk.server.agentexecution.AgentExecutor}. * *

                    Implementations should extract information from the current {@link io.grpc.Context} - * using {@link io.a2a.transport.grpc.context.GrpcContextKeys} to access metadata, + * using {@link org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys} to access metadata, * method name, peer info, and A2A protocol headers. * * @param the response type for the gRPC method diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java similarity index 84% rename from transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java rename to transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java index fe21c5ce3..ec5da9c59 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java +++ b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java @@ -1,8 +1,8 @@ -package io.a2a.transport.grpc.handler; +package org.a2aproject.sdk.transport.grpc.handler; -import static io.a2a.grpc.utils.ProtoUtils.FromProto; -import static io.a2a.grpc.utils.ProtoUtils.ToProto; -import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; +import static org.a2aproject.sdk.grpc.utils.ProtoUtils.FromProto; +import static org.a2aproject.sdk.grpc.utils.ProtoUtils.ToProto; +import static org.a2aproject.sdk.server.ServerCallContext.TRANSPORT_KEY; import java.util.HashMap; import java.util.HashSet; @@ -18,49 +18,49 @@ 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.json.JsonUtil; -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.server.requesthandlers.RequestHandler; -import io.a2a.server.version.A2AVersionValidator; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -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.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TransportProtocol; -import io.a2a.spec.A2AErrorCodes; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; -import io.a2a.transport.grpc.context.GrpcContextKeys; +import org.a2aproject.sdk.common.A2AErrorMessages; +import org.a2aproject.sdk.grpc.A2AServiceGrpc; +import org.a2aproject.sdk.grpc.StreamResponse; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.server.AgentCardValidator; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.server.requesthandlers.RequestHandler; +import org.a2aproject.sdk.server.version.A2AVersionValidator; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidAgentResponseError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.a2aproject.sdk.spec.A2AErrorCodes; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; +import org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys; import io.grpc.Context; import io.grpc.Metadata; import io.grpc.Status; @@ -113,11 +113,11 @@ *

                    Error Handling

                    *

                    A2A errors are mapped to gRPC status codes: *

                      - *
                    • {@link io.a2a.spec.InvalidRequestError} → {@link Status#INVALID_ARGUMENT}
                    • - *
                    • {@link io.a2a.spec.MethodNotFoundError} → {@link Status#NOT_FOUND}
                    • - *
                    • {@link io.a2a.spec.TaskNotFoundError} → {@link Status#NOT_FOUND}
                    • - *
                    • {@link io.a2a.spec.InternalError} → {@link Status#INTERNAL}
                    • - *
                    • {@link io.a2a.spec.UnsupportedOperationError} → {@link Status#UNIMPLEMENTED}
                    • + *
                    • {@link org.a2aproject.sdk.spec.InvalidRequestError} → {@link Status#INVALID_ARGUMENT}
                    • + *
                    • {@link org.a2aproject.sdk.spec.MethodNotFoundError} → {@link Status#NOT_FOUND}
                    • + *
                    • {@link org.a2aproject.sdk.spec.TaskNotFoundError} → {@link Status#NOT_FOUND}
                    • + *
                    • {@link org.a2aproject.sdk.spec.InternalError} → {@link Status#INTERNAL}
                    • + *
                    • {@link org.a2aproject.sdk.spec.UnsupportedOperationError} → {@link Status#UNIMPLEMENTED}
                    • *
                    • {@link SecurityException} → {@link Status#UNAUTHENTICATED} or {@link Status#PERMISSION_DENIED}
                    • *
                    * @@ -145,10 +145,10 @@ * Subclasses should be CDI beans (e.g., {@code @GrpcService} in Quarkus) that * inject dependencies and provide them through the abstract methods. * - * @see io.a2a.grpc.A2AServiceGrpc.A2AServiceImplBase - * @see io.a2a.server.requesthandlers.RequestHandler + * @see org.a2aproject.sdk.grpc.A2AServiceGrpc.A2AServiceImplBase + * @see org.a2aproject.sdk.server.requesthandlers.RequestHandler * @see CallContextFactory - * @see io.a2a.transport.grpc.context.GrpcContextKeys + * @see org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys */ @Vetoed public abstract class GrpcHandler extends A2AServiceGrpc.A2AServiceImplBase { @@ -178,8 +178,8 @@ public GrpcHandler() { *
                      *
                    1. Validate A2A protocol version and extensions
                    2. *
                    3. Convert protobuf request to domain {@link MessageSendParams}
                    4. - *
                    5. Invoke {@link io.a2a.server.requesthandlers.RequestHandler#onMessageSend}
                    6. - *
                    7. Convert domain response to protobuf {@link io.a2a.grpc.SendMessageResponse}
                    8. + *
                    9. Invoke {@link org.a2aproject.sdk.server.requesthandlers.RequestHandler#onMessageSend}
                    10. + *
                    11. Convert domain response to protobuf {@link org.a2aproject.sdk.grpc.SendMessageResponse}
                    12. *
                    13. Send response and complete the RPC
                    14. *
                    * @@ -194,15 +194,15 @@ public GrpcHandler() { * @param responseObserver the gRPC response stream observer */ @Override - public void sendMessage(io.a2a.grpc.SendMessageRequest request, - StreamObserver responseObserver) { + public void sendMessage(org.a2aproject.sdk.grpc.SendMessageRequest request, + StreamObserver responseObserver) { try { ServerCallContext context = createCallContext(responseObserver); A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context); A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context); MessageSendParams params = FromProto.messageSendParams(request); EventKind taskOrMessage = getRequestHandler().onMessageSend(params, context); - io.a2a.grpc.SendMessageResponse response = ToProto.taskOrMessage(taskOrMessage); + org.a2aproject.sdk.grpc.SendMessageResponse response = ToProto.taskOrMessage(taskOrMessage); responseObserver.onNext(response); responseObserver.onCompleted(); } catch (A2AError e) { @@ -215,8 +215,8 @@ public void sendMessage(io.a2a.grpc.SendMessageRequest request, } @Override - public void getTask(io.a2a.grpc.GetTaskRequest request, - StreamObserver responseObserver) { + public void getTask(org.a2aproject.sdk.grpc.GetTaskRequest request, + StreamObserver responseObserver) { try { ServerCallContext context = createCallContext(responseObserver); TaskQueryParams params = FromProto.taskQueryParams(request); @@ -237,11 +237,11 @@ public void getTask(io.a2a.grpc.GetTaskRequest request, } @Override - public void listTasks(io.a2a.grpc.ListTasksRequest request, - StreamObserver responseObserver) { + public void listTasks(org.a2aproject.sdk.grpc.ListTasksRequest request, + StreamObserver responseObserver) { try { ServerCallContext context = createCallContext(responseObserver); - io.a2a.spec.ListTasksParams params = FromProto.listTasksParams(request); + org.a2aproject.sdk.spec.ListTasksParams params = FromProto.listTasksParams(request); ListTasksResult result = getRequestHandler().onListTasks(params, context); responseObserver.onNext(ToProto.listTasksResult(result)); responseObserver.onCompleted(); @@ -255,8 +255,8 @@ public void listTasks(io.a2a.grpc.ListTasksRequest request, } @Override - public void cancelTask(io.a2a.grpc.CancelTaskRequest request, - StreamObserver responseObserver) { + public void cancelTask(org.a2aproject.sdk.grpc.CancelTaskRequest request, + StreamObserver responseObserver) { try { ServerCallContext context = createCallContext(responseObserver); CancelTaskParams params = FromProto.cancelTaskParams(request); @@ -277,8 +277,8 @@ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, } @Override - public void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfig request, - StreamObserver responseObserver) { + public void createTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNotificationConfig request, + StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().pushNotifications()) { handleError(responseObserver, new PushNotificationNotSupportedError()); return; @@ -300,8 +300,8 @@ public void createTaskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationCon } @Override - public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request, - StreamObserver responseObserver) { + public void getTaskPushNotificationConfig(org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest request, + StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().pushNotifications()) { handleError(responseObserver, new PushNotificationNotSupportedError()); return; @@ -323,8 +323,8 @@ public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationCon } @Override - public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotificationConfigsRequest request, - StreamObserver responseObserver) { + public void listTaskPushNotificationConfigs(org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest request, + StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().pushNotifications()) { handleError(responseObserver, new PushNotificationNotSupportedError()); return; @@ -334,7 +334,7 @@ public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotification ServerCallContext context = createCallContext(responseObserver); ListTaskPushNotificationConfigsParams params = FromProto.listTaskPushNotificationConfigsParams(request); ListTaskPushNotificationConfigsResult result = getRequestHandler().onListTaskPushNotificationConfigs(params, context); - io.a2a.grpc.ListTaskPushNotificationConfigsResponse response = ToProto.listTaskPushNotificationConfigsResponse(result); + org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse response = ToProto.listTaskPushNotificationConfigsResponse(result); responseObserver.onNext(response); responseObserver.onCompleted(); } catch (A2AError e) { @@ -358,9 +358,9 @@ public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotification *
                  • Verify streaming capability is enabled in agent card
                  • *
                  • Validate A2A protocol version and extensions
                  • *
                  • Convert protobuf request to domain {@link MessageSendParams}
                  • - *
                  • Invoke {@link io.a2a.server.requesthandlers.RequestHandler#onMessageSendStream}
                  • + *
                  • Invoke {@link org.a2aproject.sdk.server.requesthandlers.RequestHandler#onMessageSendStream}
                  • *
                  • Subscribe to event publisher and stream responses
                  • - *
                  • Convert each domain event to protobuf {@link io.a2a.grpc.StreamResponse}
                  • + *
                  • Convert each domain event to protobuf {@link org.a2aproject.sdk.grpc.StreamResponse}
                  • *
                  • Complete RPC when final event received or error occurs
                  • *
                * @@ -374,7 +374,7 @@ public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotification * *

                Error Handling: *

                  - *
                • Streaming not enabled → {@link io.a2a.spec.InvalidRequestError}
                • + *
                • Streaming not enabled → {@link org.a2aproject.sdk.spec.InvalidRequestError}
                • *
                • Other {@link A2AError} → mapped to appropriate gRPC status code
                • *
                • {@link SecurityException} → {@code UNAUTHENTICATED} or {@code PERMISSION_DENIED}
                • *
                • {@link Throwable} → {@code INTERNAL} error
                • @@ -384,8 +384,8 @@ public void listTaskPushNotificationConfigs(io.a2a.grpc.ListTaskPushNotification * @param responseObserver the gRPC response stream observer */ @Override - public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, - StreamObserver responseObserver) { + public void sendStreamingMessage(org.a2aproject.sdk.grpc.SendMessageRequest request, + StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().streaming()) { handleError(responseObserver, new InvalidRequestError()); return; @@ -408,8 +408,8 @@ public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, } @Override - public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, - StreamObserver responseObserver) { + public void subscribeToTask(org.a2aproject.sdk.grpc.SubscribeToTaskRequest request, + StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().streaming()) { handleError(responseObserver, new InvalidRequestError()); return; @@ -467,7 +467,7 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, * @param context the server call context for disconnect detection */ private void convertToStreamResponse(Flow.Publisher publisher, - StreamObserver responseObserver, + StreamObserver responseObserver, ServerCallContext context) { CompletableFuture.runAsync(() -> { publisher.subscribe(new Flow.Subscriber() { @@ -504,11 +504,11 @@ public void onNext(StreamingEventKind event) { StreamResponse response = ToProto.streamResponse(event); responseObserver.onNext(response); if (response.hasStatusUpdate()) { - io.a2a.grpc.TaskState state = response.getStatusUpdate().getStatus().getState(); - boolean isFinal = state == io.a2a.grpc.TaskState.TASK_STATE_CANCELED - || state == io.a2a.grpc.TaskState.TASK_STATE_COMPLETED - || state == io.a2a.grpc.TaskState.TASK_STATE_FAILED - || state == io.a2a.grpc.TaskState.TASK_STATE_REJECTED; + org.a2aproject.sdk.grpc.TaskState state = response.getStatusUpdate().getStatus().getState(); + boolean isFinal = state == org.a2aproject.sdk.grpc.TaskState.TASK_STATE_CANCELED + || state == org.a2aproject.sdk.grpc.TaskState.TASK_STATE_COMPLETED + || state == org.a2aproject.sdk.grpc.TaskState.TASK_STATE_FAILED + || state == org.a2aproject.sdk.grpc.TaskState.TASK_STATE_REJECTED; if (isFinal) { responseObserver.onCompleted(); } else { @@ -546,8 +546,8 @@ public void onComplete() { } @Override - public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, - StreamObserver responseObserver) { + public void getExtendedAgentCard(org.a2aproject.sdk.grpc.GetExtendedAgentCardRequest request, + StreamObserver responseObserver) { try { if (!getAgentCard().capabilities().extendedAgentCard()) { handleError(responseObserver, new UnsupportedOperationError()); @@ -567,7 +567,7 @@ public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request } @Override - public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request, + public void deleteTaskPushNotificationConfig(org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest request, StreamObserver responseObserver) { if (!getAgentCardInternal().capabilities().pushNotifications()) { handleError(responseObserver, new PushNotificationNotSupportedError()); @@ -624,7 +624,7 @@ public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificat * @param responseObserver the gRPC response stream observer * @return the server call context * @see CallContextFactory - * @see io.a2a.transport.grpc.context.GrpcContextKeys + * @see org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys */ private ServerCallContext createCallContext(StreamObserver responseObserver) { CallContextFactory factory = getCallContextFactory(); diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/package-info.java similarity index 91% rename from transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java rename to transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/package-info.java index 3dfc56685..d2561dab4 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java +++ b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/package-info.java @@ -44,11 +44,11 @@ *
                • A2A protocol version and extensions
                • *
                * - * @see io.a2a.transport.grpc.handler.GrpcHandler - * @see io.a2a.transport.grpc.context.GrpcContextKeys + * @see org.a2aproject.sdk.transport.grpc.handler.GrpcHandler + * @see org.a2aproject.sdk.transport.grpc.context.GrpcContextKeys */ @NullMarked -package io.a2a.transport.grpc.handler; +package org.a2aproject.sdk.transport.grpc.handler; import org.jspecify.annotations.NullMarked; diff --git a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java similarity index 95% rename from transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java rename to transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java index 7c5a132fe..28b32cc4e 100644 --- a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java +++ b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java @@ -1,4 +1,4 @@ -package io.a2a.transport.grpc.handler; +package org.a2aproject.sdk.transport.grpc.handler; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -14,31 +14,49 @@ import com.google.protobuf.Empty; import com.google.protobuf.Struct; - -import io.a2a.grpc.*; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.events.EventConsumer; -import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; -import io.a2a.server.requesthandlers.DefaultRequestHandler; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.InternalError; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.UnsupportedOperationError; import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.internal.testing.StreamRecorder; import io.grpc.stub.StreamObserver; import mutiny.zero.ZeroPublisher; +import org.a2aproject.sdk.grpc.AuthenticationInfo; +import org.a2aproject.sdk.grpc.CancelTaskRequest; +import org.a2aproject.sdk.grpc.DeleteTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.grpc.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.grpc.GetTaskRequest; +import org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsRequest; +import org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse; +import org.a2aproject.sdk.grpc.ListTasksRequest; +import org.a2aproject.sdk.grpc.ListTasksResponse; +import org.a2aproject.sdk.grpc.Message; +import org.a2aproject.sdk.grpc.Part; +import org.a2aproject.sdk.grpc.Role; +import org.a2aproject.sdk.grpc.SendMessageRequest; +import org.a2aproject.sdk.grpc.SendMessageResponse; +import org.a2aproject.sdk.grpc.StreamResponse; +import org.a2aproject.sdk.grpc.SubscribeToTaskRequest; +import org.a2aproject.sdk.grpc.Task; +import org.a2aproject.sdk.grpc.TaskPushNotificationConfig; +import org.a2aproject.sdk.grpc.TaskState; +import org.a2aproject.sdk.grpc.TaskStatus; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.events.EventConsumer; +import org.a2aproject.sdk.server.requesthandlers.AbstractA2ARequestHandlerTest; +import org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler; +import org.a2aproject.sdk.server.requesthandlers.RequestHandler; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentExtension; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -106,7 +124,7 @@ public void testOnCancelTaskSuccess() throws Exception { // We need to cancel the task or the EventConsumer never finds a 'final' event. // Looking at the Python implementation, they typically use AgentExecutors that // don't support cancellation. So my theory is the Agent updates the task to the CANCEL status - io.a2a.spec.Task task = context.getTask(); + org.a2aproject.sdk.spec.Task task = context.getTask(); agentEmitter.cancel(); }; @@ -301,7 +319,7 @@ public void testOnMessageStreamNewMessageExistingTaskSuccess() throws Exception agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - io.a2a.spec.Task task = io.a2a.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) + org.a2aproject.sdk.spec.Task task = org.a2aproject.sdk.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) .history(new ArrayList<>()) .build(); taskStore.save(task, false); @@ -350,7 +368,7 @@ public void onCompleted() { public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - io.a2a.spec.Task task = io.a2a.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) + org.a2aproject.sdk.spec.Task task = org.a2aproject.sdk.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) .history(new ArrayList<>()) .build(); taskStore.save(task, false); @@ -368,7 +386,7 @@ public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() throws Excep TaskStatusUpdateEvent.builder() .taskId(task.id()) .contextId(task.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_WORKING)) + .status(new org.a2aproject.sdk.spec.TaskStatus(org.a2aproject.sdk.spec.TaskState.TASK_STATE_WORKING)) .build()); StreamRecorder streamRecorder; @@ -384,14 +402,14 @@ public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() throws Excep Assertions.assertEquals(2, result.size()); StreamResponse first = result.get(0); Assertions.assertTrue(first.hasArtifactUpdate()); - io.a2a.grpc.TaskArtifactUpdateEvent taskArtifactUpdateEvent = first.getArtifactUpdate(); + org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent taskArtifactUpdateEvent = first.getArtifactUpdate(); assertEquals(task.id(), taskArtifactUpdateEvent.getTaskId()); assertEquals(task.contextId(), taskArtifactUpdateEvent.getContextId()); assertEquals("11", taskArtifactUpdateEvent.getArtifact().getArtifactId()); assertEquals("text", taskArtifactUpdateEvent.getArtifact().getParts(0).getText()); StreamResponse second = result.get(1); Assertions.assertTrue(second.hasStatusUpdate()); - io.a2a.grpc.TaskStatusUpdateEvent taskStatusUpdateEvent = second.getStatusUpdate(); + org.a2aproject.sdk.grpc.TaskStatusUpdateEvent taskStatusUpdateEvent = second.getStatusUpdate(); assertEquals(task.id(), taskStatusUpdateEvent.getTaskId()); assertEquals(task.contextId(), taskStatusUpdateEvent.getContextId()); assertEquals(TaskState.TASK_STATE_WORKING, taskStatusUpdateEvent.getStatus().getState()); @@ -418,7 +436,7 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex TaskStatusUpdateEvent.builder() .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_COMPLETED)) + .status(new org.a2aproject.sdk.spec.TaskStatus(org.a2aproject.sdk.spec.TaskState.TASK_STATE_COMPLETED)) .build()); agentExecutorExecute = (context, agentEmitter) -> { @@ -459,8 +477,8 @@ public void onCompleted() { Assertions.assertEquals(3, httpClient.events.size()); // Event 0: Task event - Assertions.assertTrue(httpClient.events.get(0) instanceof io.a2a.spec.Task, "First event should be Task"); - io.a2a.spec.Task task1 = (io.a2a.spec.Task) httpClient.events.get(0); + Assertions.assertTrue(httpClient.events.get(0) instanceof org.a2aproject.sdk.spec.Task, "First event should be Task"); + org.a2aproject.sdk.spec.Task task1 = (org.a2aproject.sdk.spec.Task) httpClient.events.get(0); Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), task1.id()); Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), task1.contextId()); Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), task1.status().state()); @@ -479,7 +497,7 @@ public void onCompleted() { TaskStatusUpdateEvent statusUpdate = (TaskStatusUpdateEvent) httpClient.events.get(2); Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), statusUpdate.taskId()); Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), statusUpdate.contextId()); - Assertions.assertEquals(io.a2a.spec.TaskState.TASK_STATE_COMPLETED, statusUpdate.status().state()); + Assertions.assertEquals(org.a2aproject.sdk.spec.TaskState.TASK_STATE_COMPLETED, statusUpdate.status().state()); } finally { mainEventBusProcessor.setPushNotificationExecutor(null); } @@ -559,7 +577,7 @@ public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { TaskStatusUpdateEvent.builder() .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_WORKING)) + .status(new org.a2aproject.sdk.spec.TaskStatus(org.a2aproject.sdk.spec.TaskState.TASK_STATE_WORKING)) .build()); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -583,7 +601,7 @@ public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), first.getTask().getId()); StreamResponse second = result.get(1); Assertions.assertTrue(second.hasArtifactUpdate()); - io.a2a.grpc.TaskArtifactUpdateEvent event = second.getArtifactUpdate(); + org.a2aproject.sdk.grpc.TaskArtifactUpdateEvent event = second.getArtifactUpdate(); assertEquals("11", event.getArtifact().getArtifactId()); assertEquals("text", (event.getArtifact().getParts(0)).getText()); StreamResponse third = result.get(2); diff --git a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcTestTransportMetadata.java b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcTestTransportMetadata.java similarity index 55% rename from transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcTestTransportMetadata.java rename to transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcTestTransportMetadata.java index 5bdf4750d..6b3d2de38 100644 --- a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcTestTransportMetadata.java +++ b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcTestTransportMetadata.java @@ -1,7 +1,7 @@ -package io.a2a.transport.grpc.handler; +package org.a2aproject.sdk.transport.grpc.handler; -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.TransportMetadata; +import org.a2aproject.sdk.spec.TransportProtocol; public class GrpcTestTransportMetadata implements TransportMetadata { @Override diff --git a/transport/grpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata b/transport/grpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index 8fce961b2..000000000 --- a/transport/grpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1,2 +0,0 @@ -# Add a test TransportMetadata so we pass AgentCard validation -io.a2a.transport.grpc.handler.GrpcTestTransportMetadata \ No newline at end of file diff --git a/transport/grpc/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata b/transport/grpc/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata new file mode 100644 index 000000000..f45cd4161 --- /dev/null +++ b/transport/grpc/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata @@ -0,0 +1,2 @@ +# Add a test TransportMetadata so we pass AgentCard validation +org.a2aproject.sdk.transport.grpc.handler.GrpcTestTransportMetadata \ No newline at end of file diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java b/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/context/JSONRPCContextKeys.java similarity index 84% rename from transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java rename to transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/context/JSONRPCContextKeys.java index 963a1493e..dfb47798d 100644 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java +++ b/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/context/JSONRPCContextKeys.java @@ -1,10 +1,10 @@ -package io.a2a.transport.jsonrpc.context; +package org.a2aproject.sdk.transport.jsonrpc.context; /** * Shared JSON-RPC context keys for A2A protocol data. * *

                These keys provide access to JSON-RPC context information stored in - * {@link io.a2a.server.ServerCallContext}, enabling rich context access + * {@link org.a2aproject.sdk.server.ServerCallContext}, enabling rich context access * in service method implementations and middleware. * *

                Usage Example

                @@ -16,7 +16,7 @@ * } * } * - * @see io.a2a.server.ServerCallContext + * @see org.a2aproject.sdk.server.ServerCallContext */ public final class JSONRPCContextKeys { diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java b/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java similarity index 88% rename from transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java rename to transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java index be670e6df..53fc59b08 100644 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java +++ b/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java @@ -1,6 +1,6 @@ -package io.a2a.transport.jsonrpc.handler; +package org.a2aproject.sdk.transport.jsonrpc.handler; -import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.createTubeConfig; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -10,50 +10,50 @@ 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.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -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.ListTaskPushNotificationConfigsRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; -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.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -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.extensions.A2AExtensions; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.util.async.Internal; -import io.a2a.server.version.A2AVersionValidator; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.EventKind; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SubscribeToTaskRequest; +import org.a2aproject.sdk.server.AgentCardValidator; +import org.a2aproject.sdk.server.ExtendedAgentCard; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.server.requesthandlers.RequestHandler; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.server.version.A2AVersionValidator; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import mutiny.zero.ZeroPublisher; import org.jspecify.annotations.Nullable; @@ -125,8 +125,8 @@ *
              * * @see RequestHandler - * @see io.a2a.server.requesthandlers.DefaultRequestHandler - * @see io.a2a.spec.AgentCard + * @see org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler + * @see org.a2aproject.sdk.spec.AgentCard * @see ServerCallContext */ @ApplicationScoped @@ -225,7 +225,7 @@ public JSONRPCHandler(@PublicAgentCard AgentCard agentCard, RequestHandler reque * @param context the server call context containing authentication and metadata * @return JSON-RPC response with task or message result * @see #onMessageSendStream(SendStreamingMessageRequest, ServerCallContext) - * @see RequestHandler#onMessageSend(io.a2a.spec.MessageSendParams, ServerCallContext) + * @see RequestHandler#onMessageSend(org.a2aproject.sdk.spec.MessageSendParams, ServerCallContext) */ public SendMessageResponse onMessageSend(SendMessageRequest request, ServerCallContext context) { try { @@ -274,7 +274,7 @@ public SendMessageResponse onMessageSend(SendMessageRequest request, ServerCallC * @param context the server call context containing authentication and metadata * @return publisher of JSON-RPC response objects containing streaming events * @see #onMessageSend(SendMessageRequest, ServerCallContext) - * @see RequestHandler#onMessageSendStream(io.a2a.spec.MessageSendParams, ServerCallContext) + * @see RequestHandler#onMessageSendStream(org.a2aproject.sdk.spec.MessageSendParams, ServerCallContext) */ public Flow.Publisher onMessageSendStream( SendStreamingMessageRequest request, ServerCallContext context) { @@ -323,7 +323,7 @@ public Flow.Publisher onMessageSendStream( * @param context the server call context containing authentication and metadata * @return JSON-RPC response with the cancelled task * @see RequestHandler#onCancelTask(CancelTaskParams, ServerCallContext) - * @see io.a2a.server.agentexecution.AgentExecutor#cancel + * @see org.a2aproject.sdk.server.agentexecution.AgentExecutor#cancel */ public CancelTaskResponse onCancelTask(CancelTaskRequest request, ServerCallContext context) { try { @@ -370,7 +370,7 @@ public CancelTaskResponse onCancelTask(CancelTaskRequest request, ServerCallCont * @param request the JSON-RPC request containing task ID params * @param context the server call context containing authentication and metadata * @return publisher of JSON-RPC response objects containing task updates - * @see RequestHandler#onSubscribeToTask(io.a2a.spec.TaskIdParams, ServerCallContext) + * @see RequestHandler#onSubscribeToTask(org.a2aproject.sdk.spec.TaskIdParams, ServerCallContext) * @see #onMessageSendStream(SendStreamingMessageRequest, ServerCallContext) */ public Flow.Publisher onSubscribeToTask( @@ -504,7 +504,7 @@ public CreateTaskPushNotificationConfigResponse setPushNotificationConfig( * @param request the JSON-RPC request containing task query params * @param context the server call context containing authentication and metadata * @return JSON-RPC response with the task object - * @see RequestHandler#onGetTask(io.a2a.spec.TaskQueryParams, ServerCallContext) + * @see RequestHandler#onGetTask(org.a2aproject.sdk.spec.TaskQueryParams, ServerCallContext) */ public GetTaskResponse onGetTask(GetTaskRequest request, ServerCallContext context) { try { @@ -551,7 +551,7 @@ public GetTaskResponse onGetTask(GetTaskRequest request, ServerCallContext conte * @param request the JSON-RPC request containing list tasks params * @param context the server call context containing authentication and metadata * @return JSON-RPC response with list of tasks - * @see RequestHandler#onListTasks(io.a2a.spec.ListTasksParams, ServerCallContext) + * @see RequestHandler#onListTasks(org.a2aproject.sdk.spec.ListTasksParams, ServerCallContext) */ public ListTasksResponse onListTasks(ListTasksRequest request, ServerCallContext context) { try { diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java b/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/package-info.java similarity index 92% rename from transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java rename to transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/package-info.java index 8bd8eeee7..87670f3ec 100644 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java +++ b/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/package-info.java @@ -27,10 +27,10 @@ *
            • {@code deleteTaskPushNotificationConfig} - Delete push notification config
            • *
            * - * @see io.a2a.transport.jsonrpc.handler.JSONRPCHandler + * @see org.a2aproject.sdk.transport.jsonrpc.handler.JSONRPCHandler */ @NullMarked -package io.a2a.transport.jsonrpc.handler; +package org.a2aproject.sdk.transport.jsonrpc.handler; import org.jspecify.annotations.NullMarked; diff --git a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java b/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java similarity index 95% rename from transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java rename to transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java index 55b7aad91..83751e919 100644 --- a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java +++ b/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java @@ -1,4 +1,4 @@ -package io.a2a.transport.jsonrpc.handler; +package org.a2aproject.sdk.transport.jsonrpc.handler; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -20,66 +20,66 @@ 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.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -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.ListTaskPushNotificationConfigsRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; -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.SubscribeToTaskRequest; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.events.EventConsumer; -import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; -import io.a2a.server.requesthandlers.DefaultRequestHandler; -import io.a2a.server.tasks.ResultAggregator; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Artifact; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.Event; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTaskPushNotificationConfigsResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.SubscribeToTaskRequest; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.events.EventConsumer; +import org.a2aproject.sdk.server.requesthandlers.AbstractA2ARequestHandlerTest; +import org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler; +import org.a2aproject.sdk.server.tasks.ResultAggregator; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentExtension; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; import mutiny.zero.ZeroPublisher; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; diff --git a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java b/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java similarity index 55% rename from transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java rename to transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java index c2087cffc..09d9a344c 100644 --- a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java +++ b/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java @@ -1,7 +1,7 @@ -package io.a2a.transport.jsonrpc.handler; +package org.a2aproject.sdk.transport.jsonrpc.handler; -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.TransportMetadata; +import org.a2aproject.sdk.spec.TransportProtocol; public class JSONRPCTestTransportMetadata implements TransportMetadata { @Override diff --git a/transport/jsonrpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata b/transport/jsonrpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index e4ec9c45f..000000000 --- a/transport/jsonrpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1,2 +0,0 @@ -# Add a test TransportMetadata so we pass AgentCard validation -io.a2a.transport.jsonrpc.handler.JSONRPCTestTransportMetadata \ No newline at end of file diff --git a/transport/jsonrpc/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata b/transport/jsonrpc/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata new file mode 100644 index 000000000..0576cfcae --- /dev/null +++ b/transport/jsonrpc/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata @@ -0,0 +1,2 @@ +# Add a test TransportMetadata so we pass AgentCard validation +org.a2aproject.sdk.transport.jsonrpc.handler.JSONRPCTestTransportMetadata \ No newline at end of file diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/context/RestContextKeys.java similarity index 84% rename from transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java rename to transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/context/RestContextKeys.java index 86e78e1ad..71035d7d3 100644 --- a/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java +++ b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/context/RestContextKeys.java @@ -1,10 +1,10 @@ -package io.a2a.transport.rest.context; +package org.a2aproject.sdk.transport.rest.context; /** * Shared REST context keys for A2A protocol data. * *

            These keys provide access to REST context information stored in - * {@link io.a2a.server.ServerCallContext}, enabling rich context access + * {@link org.a2aproject.sdk.server.ServerCallContext}, enabling rich context access * in service method implementations and middleware. * *

            Usage Example

            @@ -16,7 +16,7 @@ * } * } * - * @see io.a2a.server.ServerCallContext + * @see org.a2aproject.sdk.server.ServerCallContext */ public final class RestContextKeys { diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java similarity index 90% rename from transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java rename to transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java index abb4adbb2..fd26c451f 100644 --- a/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java +++ b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java @@ -1,9 +1,7 @@ -package io.a2a.transport.rest.handler; +package org.a2aproject.sdk.transport.rest.handler; -import static io.a2a.common.MediaType.APPLICATION_JSON; -import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; - -import io.a2a.spec.A2AErrorCodes; +import static org.a2aproject.sdk.common.MediaType.APPLICATION_JSON; +import static org.a2aproject.sdk.server.util.async.AsyncUtils.createTubeConfig; import java.time.Instant; import java.time.format.DateTimeParseException; @@ -26,43 +24,44 @@ 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.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.AgentCardCacheMetadata; -import io.a2a.server.AgentCardValidator; -import io.a2a.server.ExtendedAgentCard; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.ServerCallContext; -import io.a2a.server.extensions.A2AExtensions; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.version.A2AVersionValidator; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskParams; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.ListTaskPushNotificationConfigsParams; -import io.a2a.spec.ListTaskPushNotificationConfigsResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.UnsupportedOperationError; import mutiny.zero.ZeroPublisher; +import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; +import org.a2aproject.sdk.server.AgentCardCacheMetadata; +import org.a2aproject.sdk.server.AgentCardValidator; +import org.a2aproject.sdk.server.ExtendedAgentCard; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.server.requesthandlers.RequestHandler; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.server.version.A2AVersionValidator; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.A2AErrorCodes; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.jspecify.annotations.Nullable; /** @@ -108,8 +107,8 @@ * * * @see RequestHandler - * @see io.a2a.server.requesthandlers.DefaultRequestHandler - * @see io.a2a.spec.AgentCard + * @see org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler + * @see org.a2aproject.sdk.spec.AgentCard * @see ServerCallContext */ @ApplicationScoped @@ -220,18 +219,18 @@ public RestHandler(AgentCard agentCard, AgentCardCacheMetadata cacheMetadata, * @param body the JSON request body containing the message to send * @return the HTTP response containing the task or message result * @see #sendStreamingMessage(ServerCallContext, String, String) - * @see RequestHandler#onMessageSend(io.a2a.spec.MessageSendParams, ServerCallContext) + * @see RequestHandler#onMessageSend(org.a2aproject.sdk.spec.MessageSendParams, ServerCallContext) */ public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, String body) { try { A2AVersionValidator.validateProtocolVersion(agentCard, context); A2AExtensions.validateRequiredExtensions(agentCard, context); - io.a2a.grpc.SendMessageRequest.Builder request = io.a2a.grpc.SendMessageRequest.newBuilder(); + org.a2aproject.sdk.grpc.SendMessageRequest.Builder request = org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder(); parseRequestBody(body, request); request.setTenant(tenant); EventKind result = requestHandler.onMessageSend(ProtoUtils.FromProto.messageSendParams(request), context); - return createSuccessResponse(200, io.a2a.grpc.SendMessageResponse.newBuilder(ProtoUtils.ToProto.taskOrMessage(result))); + return createSuccessResponse(200, org.a2aproject.sdk.grpc.SendMessageResponse.newBuilder(ProtoUtils.ToProto.taskOrMessage(result))); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { @@ -285,7 +284,7 @@ public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, St * @param body the JSON request body containing the message to send * @return the streaming HTTP response containing a publisher of events * @see #sendMessage(ServerCallContext, String, String) - * @see RequestHandler#onMessageSendStream(io.a2a.spec.MessageSendParams, ServerCallContext) + * @see RequestHandler#onMessageSendStream(org.a2aproject.sdk.spec.MessageSendParams, ServerCallContext) * @see HTTPRestStreamingResponse */ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String tenant, String body) { @@ -295,7 +294,7 @@ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String t } A2AVersionValidator.validateProtocolVersion(agentCard, context); A2AExtensions.validateRequiredExtensions(agentCard, context); - io.a2a.grpc.SendMessageRequest.Builder request = io.a2a.grpc.SendMessageRequest.newBuilder(); + org.a2aproject.sdk.grpc.SendMessageRequest.Builder request = org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder(); parseRequestBody(body, request); request.setTenant(tenant); Flow.Publisher publisher = requestHandler.onMessageSendStream(ProtoUtils.FromProto.messageSendParams(request), context); @@ -328,7 +327,7 @@ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String t * @return the HTTP response containing the cancelled task * @throws InvalidParamsError if taskId is null or empty * @see RequestHandler#onCancelTask(CancelTaskParams, ServerCallContext) - * @see io.a2a.server.agentexecution.AgentExecutor#cancel + * @see org.a2aproject.sdk.server.agentexecution.AgentExecutor#cancel */ @SuppressWarnings("unchecked") public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, String body, String taskId) { @@ -340,7 +339,7 @@ public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, Str CancelTaskParams params = CancelTaskParams.builder().id(taskId).tenant(tenant).metadata(metadata).build(); Task task = requestHandler.onCancelTask(params, context); if (task != null) { - return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); + return createSuccessResponse(200, org.a2aproject.sdk.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); } throw new UnsupportedOperationError(); } catch (A2AError e) { @@ -364,7 +363,7 @@ public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContex if (!agentCard.capabilities().pushNotifications()) { throw new PushNotificationNotSupportedError(); } - io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); + org.a2aproject.sdk.grpc.TaskPushNotificationConfig.Builder builder = org.a2aproject.sdk.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(body, builder); String taskIdFromBody = builder.getTaskId(); @@ -375,7 +374,7 @@ public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContex builder.setTenant(tenant); builder.setTaskId(taskId); TaskPushNotificationConfig result = requestHandler.onCreateTaskPushNotificationConfig(ProtoUtils.FromProto.createTaskPushNotificationConfig(builder), context); - return createSuccessResponse(201, io.a2a.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(result))); + return createSuccessResponse(201, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(result))); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { @@ -444,7 +443,7 @@ public HTTPRestResponse getTask(ServerCallContext context, String tenant, String TaskQueryParams params = new TaskQueryParams(taskId, historyLength, tenant); Task task = requestHandler.onGetTask(params, context); if (task != null) { - return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); + return createSuccessResponse(200, org.a2aproject.sdk.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); } throw new TaskNotFoundError(); } catch (IllegalArgumentException e) { @@ -550,7 +549,7 @@ public HTTPRestResponse listTasks(ServerCallContext context, String tenant, ListTasksParams params = paramsBuilder.build(); ListTasksResult result = requestHandler.onListTasks(params, context); - return createSuccessResponse(200, io.a2a.grpc.ListTasksResponse.newBuilder(ProtoUtils.ToProto.listTasksResult(result))); + return createSuccessResponse(200, org.a2aproject.sdk.grpc.ListTasksResponse.newBuilder(ProtoUtils.ToProto.listTasksResult(result))); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { @@ -574,7 +573,7 @@ public HTTPRestResponse getTaskPushNotificationConfiguration(ServerCallContext c } 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))); + return createSuccessResponse(200, org.a2aproject.sdk.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(config))); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { @@ -599,7 +598,7 @@ public HTTPRestResponse listTaskPushNotificationConfigurations(ServerCallContext } ListTaskPushNotificationConfigsParams params = new ListTaskPushNotificationConfigsParams(taskId, pageSize, pageToken, tenant); ListTaskPushNotificationConfigsResult result = requestHandler.onListTaskPushNotificationConfigs(params, context); - return createSuccessResponse(200, io.a2a.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(ProtoUtils.ToProto.listTaskPushNotificationConfigsResponse(result))); + return createSuccessResponse(200, org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse.newBuilder(ProtoUtils.ToProto.listTaskPushNotificationConfigsResponse(result))); } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/package-info.java similarity index 90% rename from transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java rename to transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/package-info.java index d8ea46ac7..d6b28295c 100644 --- a/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java +++ b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/package-info.java @@ -11,7 +11,7 @@ * */ @NullMarked -package io.a2a.transport.rest.handler; +package org.a2aproject.sdk.transport.rest.handler; import org.jspecify.annotations.NullMarked; diff --git a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java b/transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java similarity index 98% rename from transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java rename to transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java index f5184b2f4..5cd00114f 100644 --- a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java +++ b/transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java @@ -1,7 +1,7 @@ -package io.a2a.transport.rest.handler; +package org.a2aproject.sdk.transport.rest.handler; -import static io.a2a.common.MediaType.APPLICATION_JSON; +import static org.a2aproject.sdk.common.MediaType.APPLICATION_JSON; import java.util.Collections; import java.util.HashSet; @@ -17,17 +17,17 @@ import com.google.gson.JsonParser; import com.google.protobuf.InvalidProtocolBufferException; -import io.a2a.common.MediaType; -import io.a2a.server.AgentCardCacheMetadata; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.config.DefaultValuesConfigProvider; -import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Task; +import org.a2aproject.sdk.common.MediaType; +import org.a2aproject.sdk.server.AgentCardCacheMetadata; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.config.DefaultValuesConfigProvider; +import org.a2aproject.sdk.server.requesthandlers.AbstractA2ARequestHandlerTest; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentExtension; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Task; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; diff --git a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java b/transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestTestTransportMetadata.java similarity index 73% rename from transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java rename to transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestTestTransportMetadata.java index d9401d68e..69ede73d9 100644 --- a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java +++ b/transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestTestTransportMetadata.java @@ -1,7 +1,7 @@ -package io.a2a.transport.rest.handler; +package org.a2aproject.sdk.transport.rest.handler; -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; +import org.a2aproject.sdk.server.TransportMetadata; +import org.a2aproject.sdk.spec.TransportProtocol; /** * Test implementation of TransportMetadata for REST transport testing. diff --git a/transport/rest/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata b/transport/rest/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index 3604945b4..000000000 --- a/transport/rest/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1,2 +0,0 @@ -# Add a test TransportMetadata so we pass AgentCard validation -io.a2a.transport.rest.handler.RestTestTransportMetadata \ No newline at end of file diff --git a/transport/rest/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata b/transport/rest/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata new file mode 100644 index 000000000..f1071a88f --- /dev/null +++ b/transport/rest/src/test/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata @@ -0,0 +1,2 @@ +# Add a test TransportMetadata so we pass AgentCard validation +org.a2aproject.sdk.transport.rest.handler.RestTestTransportMetadata \ No newline at end of file From 98d2bdb9a1b7fd6e684375601ea7d95a626edcba Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Fri, 10 Apr 2026 17:35:03 +0200 Subject: [PATCH 106/192] fix: JsonRPC errors should have a 'data' field not a 'details' field. (#790) Signed-off-by: Emmanuel Hugonnet --- .../sdk/client/transport/jsonrpc/JsonMessages.java | 2 +- .../sdk/client/transport/jsonrpc/JsonStreamingMessages.java | 2 +- .../java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonMessages.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonMessages.java index e71e6b3b4..f73e9d8ed 100644 --- a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonMessages.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonMessages.java @@ -216,7 +216,7 @@ public class JsonMessages { "error": { "code": -32702, "message": "Invalid parameters", - "details": {"info": "Hello world"} + "data": {"info": "Hello world"} } }"""; diff --git a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonStreamingMessages.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonStreamingMessages.java index 7b36552b9..f9c006b2c 100644 --- a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonStreamingMessages.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JsonStreamingMessages.java @@ -99,7 +99,7 @@ public class JsonStreamingMessages { "error": { "code": -32602, "message": "Invalid parameters", - "details": {"info": "Missing required field"} + "data": {"info": "Missing required field"} } }"""; diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java index 270fde3a7..db43d92a9 100644 --- a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java @@ -392,8 +392,8 @@ 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; Map details = null; - if (error.has("details") && error.get("details").isJsonObject()) { - details =GSON.fromJson(error.get("details"), Map.class); + if (error.has("data") && error.get("data").isJsonObject()) { + details =GSON.fromJson(error.get("data"), Map.class); } if (code != null) { A2AErrorCodes errorCode = A2AErrorCodes.fromCode(code); @@ -606,7 +606,7 @@ public static String toJsonRPCErrorResponse(Object requestId, A2AError error) { output.name("code").value(error.getCode()); output.name("message").value(error.getMessage()); if (!error.getDetails().isEmpty()) { - output.name("details"); + output.name("data"); GSON.toJson(error.getDetails(), Map.class, output); } output.endObject(); From 786e5fd49636829755b9d323ea8dbf8d83e6f787 Mon Sep 17 00:00:00 2001 From: Jun Jeong <46917538+yyy9942@users.noreply.github.com> Date: Wed, 15 Apr 2026 18:32:48 +0900 Subject: [PATCH 107/192] fix: return TaskNotFoundError when SendMessage references non-existent taskId (#788) Per A2A spec section 3.4.2, when a client includes a taskId in a Message, it MUST reference an existing task. The SDK was creating a new task with that id instead. Added a guard in DefaultRequestHandler.initMessageSend() that throws TaskNotFoundError when the provided taskId does not reference an existing task. This fixes the issue on all three transports (JSON-RPC, gRPC, HTTP+JSON) since they all use the same DefaultRequestHandler code path. Also fixes a related contextId bug: when a follow-up message had a taskId but no contextId, RequestContext.Builder.build() was generating a fresh UUID, so the agent executor saw the wrong contextId. The rebuild now seeds contextId from the stored task. Existing tests that relied on the old taskId behavior have been updated. Fixes #766 --- ...otificationConfigStoreIntegrationTest.java | 29 ++- .../MultiInstanceReplicationTest.java | 33 ++- .../KafkaReplicationIntegrationTest.java | 39 ++-- .../JpaDatabaseTaskStoreIntegrationTest.java | 12 +- .../DefaultRequestHandler.java | 122 +++++------ .../DefaultRequestHandlerTest.java | 165 +++++++++++++++ .../apps/common/AbstractA2AServerTest.java | 194 ++++++++++-------- .../apps/common/AgentExecutorProducer.java | 82 +++----- .../grpc/handler/GrpcHandlerTest.java | 9 +- .../jsonrpc/handler/JSONRPCHandlerTest.java | 11 +- 10 files changed, 438 insertions(+), 258 deletions(-) diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java index 705dea4ed..3fc330215 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java @@ -11,11 +11,14 @@ import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.TaskEvent; +import org.a2aproject.sdk.client.TaskUpdateEvent; import org.a2aproject.sdk.client.config.ClientConfig; import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; @@ -98,23 +101,33 @@ public void testDirectNotificationTrigger() { @Test public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Exception { - final String taskId = "push-notify-test-" + System.currentTimeMillis(); - final String contextId = "test-context"; - - // Step 1: Create the task + // Step 1: Create the task (no client-provided taskId — server generates it) Message createMessage = Message.builder() .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("create"))) // Send the "create" command - .taskId(taskId) .messageId("test-msg-1") - .contextId(contextId) .build(); - // Use a latch to wait for the first operation to complete + // Use a latch to wait for the first operation to complete and capture server-generated ids CountDownLatch createLatch = new CountDownLatch(1); - client.sendMessage(createMessage, List.of((event, card) -> createLatch.countDown()), (e) -> createLatch.countDown()); + AtomicReference createdTaskRef = new AtomicReference<>(); + client.sendMessage(createMessage, List.of((event, card) -> { + if (event instanceof TaskEvent taskEvent) { + createdTaskRef.set(taskEvent.getTask()); + createLatch.countDown(); + return; + } + if (event instanceof TaskUpdateEvent taskUpdateEvent) { + createdTaskRef.set(taskUpdateEvent.getTask()); + createLatch.countDown(); + } + }), (e) -> createLatch.countDown()); assertTrue(createLatch.await(10, TimeUnit.SECONDS), "Timeout waiting for task creation"); + assertNotNull(createdTaskRef.get(), "Task should have been created"); + final String taskId = createdTaskRef.get().id(); + final String contextId = createdTaskRef.get().contextId(); + // Step 2: Set the push notification configuration TaskPushNotificationConfig taskPushConfig = TaskPushNotificationConfig.builder() .id("test-config-1") diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java index 4a42d34a4..61676ff00 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java @@ -9,7 +9,9 @@ import java.time.Duration; import java.util.Collections; import java.util.List; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -19,6 +21,7 @@ import org.a2aproject.sdk.A2A; import org.a2aproject.sdk.client.Client; import org.a2aproject.sdk.client.ClientEvent; +import org.a2aproject.sdk.client.TaskEvent; import org.a2aproject.sdk.client.config.ClientConfig; import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfig; @@ -254,15 +257,13 @@ public void testInfrastructureStartup() { */ @Test public void testMultiInstanceEventReplication() throws Exception { - final String taskId = "replication-test-task-" + System.currentTimeMillis(); - final String contextId = "replication-test-context"; - Throwable testFailure = null; + final String[] taskIdHolder = {null}; + final String[] contextIdHolder = {null}; + try { - // Step 1: Send initial message NON-streaming to create task + // Step 1: Send initial message NON-streaming to create task (no client-provided taskId) Message initialMessage = Message.builder(A2A.toUserMessage("Initial test message")) - .taskId(taskId) - .contextId(contextId) .build(); // Use NON-streaming client to create the task @@ -272,13 +273,22 @@ public void testMultiInstanceEventReplication() throws Exception { .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) .build(); - Task createdTask = null; try { - nonStreamingClient.sendMessage(initialMessage, null); + CountDownLatch createLatch = new CountDownLatch(1); + AtomicReference taskRef = new AtomicReference<>(); + nonStreamingClient.sendMessage(initialMessage, List.of((ClientEvent event, AgentCard card) -> { + if (event instanceof TaskEvent te) { + taskRef.set(te.getTask()); + } + createLatch.countDown(); + }), (Throwable err) -> createLatch.countDown()); + assertTrue(createLatch.await(15, TimeUnit.SECONDS), "Task creation timed out"); - // Retrieve the task to verify it was created - createdTask = nonStreamingClient.getTask(new TaskQueryParams(taskId), null); + Task createdTask = taskRef.get(); assertNotNull(createdTask, "Task should be created"); + taskIdHolder[0] = createdTask.id(); + contextIdHolder[0] = createdTask.contextId(); + assertNotNull(taskIdHolder[0], "Server-generated task ID should not be null"); // Task should be in a non-final state (SUBMITTED or WORKING are both valid) TaskState state = createdTask.status().state(); @@ -297,6 +307,9 @@ public void testMultiInstanceEventReplication() throws Exception { throw e; } + final String taskId = taskIdHolder[0]; + final String contextId = contextIdHolder[0]; + // Step 2: Subscribe from both app1 and app2 with proper latches // We need to wait for at least 3 new events after resubscription: diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java index 0b6e305ee..c8b7adb78 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java @@ -130,19 +130,14 @@ public void tearDown() throws Exception { @Test public void testA2AMessageReplicatedToKafka() throws Exception { - String taskId = "kafka-replication-test-" + System.currentTimeMillis(); - String contextId = "test-context-" + System.currentTimeMillis(); - // Clear any previous events testConsumer.clear(); - // Send A2A message that should trigger events and replication + // Send A2A message that should trigger events and replication (no client-provided taskId) Message message = Message.builder() .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("create"))) - .taskId(taskId) .messageId("test-msg-" + System.currentTimeMillis()) - .contextId(contextId) .build(); CountDownLatch a2aLatch = new CountDownLatch(1); @@ -166,7 +161,9 @@ public void testA2AMessageReplicatedToKafka() throws Exception { Task task = createdTask.get(); assertNotNull(task, "Task should be created"); - assertEquals(taskId, task.id()); + String taskId = task.id(); + String contextId = task.contextId(); + assertNotNull(taskId, "Server-generated task ID should not be null"); assertEquals(TaskState.TASK_STATE_SUBMITTED, task.status().state()); // Wait for the event to be replicated to Kafka @@ -193,19 +190,14 @@ public void testA2AMessageReplicatedToKafka() throws Exception { @Test public void testKafkaEventReceivedByA2AServer() throws Exception { - String taskId = "kafka-to-a2a-test-" + System.currentTimeMillis(); - String contextId = "test-context-" + System.currentTimeMillis(); - // Clear any previous events testConsumer.clear(); - // First create a task in the A2A system using non-streaming client + // First create a task in the A2A system using non-streaming client (no client-provided taskId) Message createMessage = Message.builder() .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("create"))) - .taskId(taskId) .messageId("create-msg-" + System.currentTimeMillis()) - .contextId(contextId) .build(); CountDownLatch createLatch = new CountDownLatch(1); @@ -223,6 +215,9 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { assertTrue(createLatch.await(15, TimeUnit.SECONDS), "Task creation timed out"); Task initialTask = createdTask.get(); assertNotNull(initialTask, "Task should be created"); + String taskId = initialTask.id(); + String contextId = initialTask.contextId(); + assertNotNull(taskId, "Server-generated task ID should not be null"); assertEquals(TaskState.TASK_STATE_SUBMITTED, initialTask.status().state(), "Initial task should be in SUBMITTED state"); // Add a small delay to ensure the task is fully processed before resubscription @@ -312,20 +307,15 @@ public void testKafkaEventReceivedByA2AServer() throws Exception { @Test public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { - String taskId = "queue-closed-test-" + System.currentTimeMillis(); - String contextId = "test-context-" + System.currentTimeMillis(); - // Clear any previous events testConsumer.clear(); - // Use polling (non-blocking) client with "working" command + // Use polling (non-blocking) client with "working" command (no client-provided taskId) // This creates task in WORKING state (non-final) and keeps queue alive Message workingMessage = Message.builder() .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("working"))) - .taskId(taskId) .messageId("working-msg-" + System.currentTimeMillis()) - .contextId(contextId) .build(); CountDownLatch workingLatch = new CountDownLatch(1); @@ -348,7 +338,7 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { assertTrue(workingLatch.await(15, TimeUnit.SECONDS), "Task creation timed out"); String createdTaskId = taskIdRef.get(); assertNotNull(createdTaskId, "Task should be created"); - assertEquals(taskId, createdTaskId); + String taskId = createdTaskId; // Set up streaming resubscription to listen for the QueueClosedEvent CountDownLatch streamCompletedLatch = new CountDownLatch(1); @@ -408,19 +398,14 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { @Test public void testPoisonPillGenerationOnTaskFinalization() throws Exception { - String taskId = "poison-pill-gen-test-" + System.currentTimeMillis(); - String contextId = "test-context-" + System.currentTimeMillis(); - // Clear any previous events testConsumer.clear(); - // Create a task that will be completed (finalized) + // Create a task that will be completed (finalized) - no client-provided taskId Message completeMessage = Message.builder() .role(Message.Role.ROLE_USER) .parts(List.of(new TextPart("complete"))) - .taskId(taskId) .messageId("complete-msg-" + System.currentTimeMillis()) - .contextId(contextId) .build(); CountDownLatch completeLatch = new CountDownLatch(1); @@ -439,6 +424,8 @@ public void testPoisonPillGenerationOnTaskFinalization() throws Exception { assertTrue(completeLatch.await(15, TimeUnit.SECONDS), "Task creation timed out"); Task createdTask = finalTask.get(); assertNotNull(createdTask, "Task should be created"); + String taskId = createdTask.id(); + assertNotNull(taskId, "Server-generated task ID should not be null"); // The task should complete very quickly since it's a simple operation // Wait a moment to ensure all events have been enqueued diff --git a/extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java b/extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java index 5f93de75e..7bc227553 100644 --- a/extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java +++ b/extras/task-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java @@ -3,7 +3,6 @@ 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.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Collections; @@ -69,17 +68,11 @@ public void testIsJpaDatabaseTaskStore() { @Test public void testJpaDatabaseTaskStore() throws Exception { - final String taskId = "test-task-1"; - final String contextId = "contextId"; - - // Send a message creating the Task - assertNull(taskStore.get(taskId)); + // Send a message creating the Task (no client-provided taskId — server generates it) Message userMessage = Message.builder() .role(Message.Role.ROLE_USER) .parts(Collections.singletonList(new TextPart("create"))) - .taskId(taskId) .messageId("test-msg-1") - .contextId(contextId) .build(); CountDownLatch latch = new CountDownLatch(1); @@ -102,6 +95,9 @@ public void testJpaDatabaseTaskStore() throws Exception { assertEquals(0, createdTask.artifacts().size()); assertEquals(TaskState.TASK_STATE_SUBMITTED, createdTask.status().state()); + final String taskId = createdTask.id(); + final String contextId = createdTask.contextId(); + // Send a message updating the Task userMessage = Message.builder() .role(Message.Role.ROLE_USER) diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java index 8184d7baf..aea2cbc68 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java @@ -1021,56 +1021,26 @@ private CompletableFuture cleanupProducer(@Nullable CompletableFuture { + throw new AssertionError("AgentExecutor must NOT be invoked when taskId is unknown"); + }; + + Message message = Message.builder() + .messageId("msg-unknown-task") + .role(Message.Role.ROLE_USER) + .taskId("does-not-exist-99999") + .parts(new TextPart("hello")) + .build(); + + MessageSendParams params = MessageSendParams.builder() + .message(message) + .configuration(DEFAULT_CONFIG) + .build(); + + assertThrows(TaskNotFoundError.class, + () -> requestHandler.onMessageSend(params, NULL_CONTEXT), + "Expected TaskNotFoundError when SendMessage references a non-existent taskId"); + } + /** * Test: SendStreamingMessage to a task in a terminal state must also return UnsupportedOperationError * (CORE-SEND-002, streaming path). @@ -740,4 +770,139 @@ void testSendMessageStream_ToCompletedTask_ThrowsUnsupportedOperationError() thr () -> requestHandler.onMessageSendStream(followUpParams, NULL_CONTEXT), "Expected UnsupportedOperationError when streaming message to a completed task"); } + + /** + * CORE-MULTI-004 (streaming path): onMessageSendStream with a client-provided + * taskId that does not reference an existing task must also return + * TaskNotFoundError. + */ + @Test + void testSendMessageStream_WithNonExistentTaskId_ThrowsTaskNotFoundError() { + agentExecutorExecute = (context, emitter) -> { + throw new AssertionError("AgentExecutor must NOT be invoked when taskId is unknown"); + }; + + Message message = Message.builder() + .messageId("msg-stream-unknown-task") + .role(Message.Role.ROLE_USER) + .taskId("does-not-exist-stream-99999") + .parts(new TextPart("hello")) + .build(); + + MessageSendParams params = MessageSendParams.builder() + .message(message) + .configuration(DEFAULT_CONFIG) + .build(); + + assertThrows(TaskNotFoundError.class, + () -> requestHandler.onMessageSendStream(params, NULL_CONTEXT), + "Expected TaskNotFoundError when onMessageSendStream references a non-existent taskId"); + } + + /** + * Verification for Codex adversarial review finding: + * When a follow-up message includes taskId but omits contextId, + * the emitted TaskStatusUpdateEvent should use the task's original + * contextId, NOT a freshly generated UUID. + */ + @Test + void testSendMessage_FollowUpWithTaskIdOnly_PreservesOriginalContextId() throws Exception { + final String originalContextId = "original-ctx-for-verification"; + + // Arrange: create a task with a known contextId via the handler so the task is + // in a non-terminal (SUBMITTED) state and stored in taskStore. + CountDownLatch firstAgentStarted = new CountDownLatch(1); + CountDownLatch releaseFirstAgent = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + emitter.startWork(); + firstAgentStarted.countDown(); + try { + releaseFirstAgent.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + emitter.complete(); + }; + + Message initialMessage = Message.builder() + .messageId("msg-initial-ctx-verify") + .role(Message.Role.ROLE_USER) + .contextId(originalContextId) + .parts(new TextPart("initial message")) + .build(); + + MessageSendParams initialParams = MessageSendParams.builder() + .message(initialMessage) + .configuration(DEFAULT_CONFIG) + .build(); + + EventKind initialResult = requestHandler.onMessageSend(initialParams, NULL_CONTEXT); + assertInstanceOf(Task.class, initialResult); + Task existingTask = (Task) initialResult; + + // Verify the task was stored with the expected contextId + assertEquals(originalContextId, existingTask.contextId(), + "Initial task must have the original contextId"); + + // Wait until the first agent is actively running (task is non-terminal/WORKING) + assertTrue(firstAgentStarted.await(5, TimeUnit.SECONDS), "First agent should start"); + + // Capture the contextId that the agent sees in its RequestContext on the follow-up call + AtomicReference observedContextId = new AtomicReference<>(); + CountDownLatch followUpAgentDone = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + observedContextId.set(context.getContextId()); + emitter.complete(); + followUpAgentDone.countDown(); + }; + + // Act: follow-up message with taskId only, NO contextId + Message followUp = Message.builder() + .messageId("follow-up-msg-ctx-verify") + .role(Message.Role.ROLE_USER) + .taskId(existingTask.id()) + // NOTE: intentionally NO .contextId(...) + .parts(new TextPart("follow up")) + .build(); + + MessageSendParams followUpParams = MessageSendParams.builder() + .message(followUp) + .configuration(DEFAULT_CONFIG) + .build(); + + // Release the first agent so the task reaches a non-terminal state that + // allows a follow-up (the test uses WORKING state, then we send a second message; + // but the spec only allows follow-up to non-terminal tasks so we send before + // completion by driving the task to SUBMITTED first via direct store manipulation). + // Instead: pre-store the task directly to control state precisely. + Task workingTask = new Task( + existingTask.id(), + originalContextId, + new TaskStatus(TaskState.TASK_STATE_WORKING), + null, + null, + null + ); + taskStore.save(workingTask, false); + + EventKind result = requestHandler.onMessageSend(followUpParams, NULL_CONTEXT); + + // Assert: the task returned must still have the ORIGINAL contextId + assertInstanceOf(Task.class, result); + Task returned = (Task) result; + assertEquals(originalContextId, returned.contextId(), + "Task's contextId must be preserved after follow-up without contextId"); + + // Wait for follow-up agent to run and capture its observed contextId + assertTrue(followUpAgentDone.await(5, TimeUnit.SECONDS), "Follow-up agent should complete"); + + // And the agent's view of the contextId must match the original + assertEquals(originalContextId, observedContextId.get(), + "Agent should see the original contextId, not a freshly generated one"); + + // Cleanup: release the first agent + releaseFirstAgent.countDown(); + } } diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index 8d75f783a..cc7ceb188 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -468,10 +468,7 @@ public void testListTasksWithHistoryLimit() throws Exception { @Test public void testSendMessageNewMessageSuccess() throws Exception { - assertTrue(getTaskFromTaskStore(MINIMAL_TASK.id()) == null); Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) .build(); CountDownLatch latch = new CountDownLatch(1); @@ -598,20 +595,25 @@ public void testGetPushNotificationSuccess() throws Exception { } @Test - public void testError() throws A2AClientException { - Message message = Message.builder(MESSAGE) - .taskId(SEND_MESSAGE_NOT_SUPPORTED.id()) - .contextId(SEND_MESSAGE_NOT_SUPPORTED.contextId()) - .build(); - + public void testError() throws Exception { + saveTaskInTaskStore(SEND_MESSAGE_NOT_SUPPORTED); try { - getNonStreamingClient().sendMessage(message); + Message message = Message.builder(MESSAGE) + .taskId(SEND_MESSAGE_NOT_SUPPORTED.id()) + .contextId(SEND_MESSAGE_NOT_SUPPORTED.contextId()) + .build(); - // For non-streaming clients, the error should still be thrown as an exception - fail("Expected A2AClientException for unsupported send message operation"); - } catch (A2AClientException e) { - // Expected - the client should throw an exception for unsupported operations - assertInstanceOf(UnsupportedOperationError.class, e.getCause()); + try { + getNonStreamingClient().sendMessage(message); + + // For non-streaming clients, the error should still be thrown as an exception + fail("Expected A2AClientException for unsupported send message operation"); + } catch (A2AClientException e) { + // Expected - the client should throw an exception for unsupported operations + assertInstanceOf(UnsupportedOperationError.class, e.getCause()); + } + } finally { + deleteTaskInTaskStore(SEND_MESSAGE_NOT_SUPPORTED.id()); } } @@ -934,19 +936,12 @@ public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Excepti @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exception { - // Use a taskId with the pattern the test agent recognizes - // When we send a message with a taskId to a non-existent task, it creates - // a new task with that ID, and context.getTask() is still null on first invocation - String taskId = "input-required-test-" + UUID.randomUUID(); + AtomicReference taskIdRef = new AtomicReference<>(); try { - // Create initial message with the special taskId pattern - // Use non-streaming client so agent can emit INPUT_REQUIRED and return immediately - // This ensures context.getTask() == null on first agent invocation + // No taskId - server generates one; routing is by message content prefix "input-required:" Message message = Message.builder(MESSAGE) - .taskId(taskId) - .contextId("test-context") - .parts(new TextPart("Trigger INPUT_REQUIRED")) + .parts(new TextPart("input-required:Trigger INPUT_REQUIRED")) .build(); // Send message with non-streaming client - agent will emit INPUT_REQUIRED and complete @@ -956,10 +951,12 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce getNonStreamingClient().sendMessage(message, List.of((event, agentCard) -> { if (event instanceof TaskEvent te) { + taskIdRef.compareAndSet(null, te.getTask().id()); finalStateRef.set(te.getTask().status().state()); sendLatch.countDown(); } else if (event instanceof TaskUpdateEvent tue) { if (tue.getUpdateEvent() instanceof TaskStatusUpdateEvent statusUpdate) { + taskIdRef.compareAndSet(null, statusUpdate.taskId()); finalStateRef.set(statusUpdate.status().state()); } } @@ -977,6 +974,9 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce assertEquals(TaskState.TASK_STATE_INPUT_REQUIRED, finalState, "Task should be in INPUT_REQUIRED state after agent completes"); + String taskId = taskIdRef.get(); + assertNotNull(taskId, "Should have captured server-generated taskId"); + // CRITICAL: At this point the agent has completed with INPUT_REQUIRED state // The grace period logic should NOT close the queue because INPUT_REQUIRED // is an interrupted state, not a terminal state @@ -1052,7 +1052,7 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce Message followUpMessage = Message.builder() .messageId("input-response-" + UUID.randomUUID()) .role(Message.Role.ROLE_USER) - .parts(new TextPart("User input")) + .parts(new TextPart("input-required:User input")) .taskId(taskId) .build(); @@ -1075,7 +1075,10 @@ public void testSubscribeToTaskWithInterruptedStateKeepsStreamOpen() throws Exce assertNull(subscribeErrorRef.get(), "Should not have any errors"); } finally { - deleteTaskInTaskStore(taskId); + String taskId = taskIdRef.get(); + if (taskId != null) { + deleteTaskInTaskStore(taskId); + } } } @@ -1603,13 +1606,12 @@ public void testDeletePushNotificationConfigSetWithoutConfigId() throws Exceptio @Test @Timeout(value = 1, unit = TimeUnit.MINUTES) public void testNonBlockingWithMultipleMessages() throws Exception { - String multiEventTaskId = "multi-event-test-" + java.util.UUID.randomUUID(); + AtomicReference generatedTaskIdRef = new AtomicReference<>(); try { - // 1. Send first non-blocking message to create task in WORKING state + // 1. Send first non-blocking message without taskId - server generates one + // Routing is by message content prefix "multi-event:first" Message message1 = Message.builder(MESSAGE) - .taskId(multiEventTaskId) - .contextId("test-context") - .parts(new TextPart("First request")) + .parts(new TextPart("multi-event:first")) .build(); AtomicReference taskIdRef = new AtomicReference<>(); @@ -1632,7 +1634,7 @@ public void testNonBlockingWithMultipleMessages() throws Exception { assertTrue(firstTaskLatch.await(10, TimeUnit.SECONDS)); String taskId = taskIdRef.get(); assertNotNull(taskId); - assertEquals(multiEventTaskId, taskId); + generatedTaskIdRef.set(taskId); // 2. Subscribe to task (queue should still be open) CountDownLatch resubEventLatch = new CountDownLatch(2); // artifact-2 + completion @@ -1693,9 +1695,8 @@ public void testNonBlockingWithMultipleMessages() throws Exception { // 3. Send second streaming message to same taskId Message message2 = Message.builder(MESSAGE) - .taskId(multiEventTaskId) // Same taskId - .contextId("test-context") - .parts(new TextPart("Second request")) + .taskId(taskId) + .parts(new TextPart("multi-event:second")) .build(); CountDownLatch streamEventLatch = new CountDownLatch(2); // artifact-2 + completion @@ -1784,7 +1785,10 @@ public void testNonBlockingWithMultipleMessages() throws Exception { assertEquals("Second message artifact", ((TextPart) streamArtifact.artifact().parts().get(0)).text()); } finally { - deleteTaskInTaskStore(multiEventTaskId); + String taskId = generatedTaskIdRef.get(); + if (taskId != null) { + deleteTaskInTaskStore(taskId); + } } } @@ -1819,14 +1823,13 @@ private boolean awaitChildQueueCountStable(String taskId, int expectedCount, lon @Test @Timeout(value = 1, unit = TimeUnit.MINUTES) public void testInputRequiredWorkflow() throws Exception { - String inputRequiredTaskId = "input-required-test-" + java.util.UUID.randomUUID(); - boolean taskCreated = false; + AtomicBoolean taskCreated = new AtomicBoolean(false); + AtomicReference inputRequiredTaskIdRef = new AtomicReference<>(); try { - // 1. Send initial message - AgentExecutor will transition task to INPUT_REQUIRED + // 1. Send initial message without taskId - server generates one + // Routing is by message content prefix "input-required:" Message initialMessage = Message.builder(MESSAGE) - .taskId(inputRequiredTaskId) - .contextId("test-context") - .parts(new TextPart("Initial request")) + .parts(new TextPart("input-required:Initial request")) .build(); CountDownLatch initialLatch = new CountDownLatch(1); @@ -1839,10 +1842,12 @@ public void testInputRequiredWorkflow() throws Exception { return; } if (event instanceof TaskEvent te) { + inputRequiredTaskIdRef.compareAndSet(null, te.getTask().id()); TaskState state = te.getTask().status().state(); initialState.set(state); // Only count down when we receive INPUT_REQUIRED, not intermediate states like WORKING if (state == TaskState.TASK_STATE_INPUT_REQUIRED) { + taskCreated.set(true); initialLatch.countDown(); } } else { @@ -1855,13 +1860,14 @@ public void testInputRequiredWorkflow() throws Exception { assertTrue(initialLatch.await(10, TimeUnit.SECONDS)); assertFalse(initialUnexpectedEvent.get()); assertEquals(TaskState.TASK_STATE_INPUT_REQUIRED, initialState.get()); - taskCreated = true; + + String inputRequiredTaskId = inputRequiredTaskIdRef.get(); + assertNotNull(inputRequiredTaskId, "Should have captured server-generated taskId"); // 2. Send input message - AgentExecutor will complete the task Message inputMessage = Message.builder(MESSAGE) .taskId(inputRequiredTaskId) - .contextId("test-context") - .parts(new TextPart("User input")) + .parts(new TextPart("input-required:User input")) .build(); CountDownLatch completionLatch = new CountDownLatch(1); @@ -1892,8 +1898,11 @@ public void testInputRequiredWorkflow() throws Exception { assertEquals(TaskState.TASK_STATE_COMPLETED, completedState.get()); } finally { - if (taskCreated) { - deleteTaskInTaskStore(inputRequiredTaskId); + if (taskCreated.get()) { + String taskId = inputRequiredTaskIdRef.get(); + if (taskId != null) { + deleteTaskInTaskStore(taskId); + } } } } @@ -1917,14 +1926,13 @@ public void testInputRequiredWorkflow() throws Exception { @Test @Timeout(value = 1, unit = TimeUnit.MINUTES) public void testAuthRequiredWorkflow() throws Exception { - String authRequiredTaskId = "auth-required-test-" + java.util.UUID.randomUUID(); - boolean taskCreated = false; + AtomicBoolean taskCreated = new AtomicBoolean(false); + AtomicReference authRequiredTaskIdRef = new AtomicReference<>(); try { - // 1. Send initial message - AgentExecutor will transition task to AUTH_REQUIRED then continue in background + // 1. Send initial message without taskId - server generates one + // Routing is by message content prefix "auth-required:" Message initialMessage = Message.builder(MESSAGE) - .taskId(authRequiredTaskId) - .contextId("test-context") - .parts(new TextPart("Initial request requiring auth")) + .parts(new TextPart("auth-required:Initial request requiring auth")) .build(); CountDownLatch initialLatch = new CountDownLatch(1); @@ -1937,10 +1945,12 @@ public void testAuthRequiredWorkflow() throws Exception { return; } if (event instanceof TaskEvent te) { + authRequiredTaskIdRef.compareAndSet(null, te.getTask().id()); TaskState state = te.getTask().status().state(); initialState.set(state); // Only count down when we receive AUTH_REQUIRED, not intermediate states like WORKING if (state == TaskState.TASK_STATE_AUTH_REQUIRED) { + taskCreated.set(true); initialLatch.countDown(); } } else { @@ -1953,7 +1963,9 @@ public void testAuthRequiredWorkflow() throws Exception { assertTrue(initialLatch.await(10, TimeUnit.SECONDS), "Should receive AUTH_REQUIRED state"); assertFalse(initialUnexpectedEvent.get(), "Should only receive TaskEvent"); assertEquals(TaskState.TASK_STATE_AUTH_REQUIRED, initialState.get(), "Task should be in AUTH_REQUIRED state"); - taskCreated = true; + + String authRequiredTaskId = authRequiredTaskIdRef.get(); + assertNotNull(authRequiredTaskId, "Should have captured server-generated taskId"); // 2. Subscribe to task to catch background completion // Agent continues executing after returning AUTH_REQUIRED (simulating out-of-band auth flow) @@ -2010,20 +2022,23 @@ public void testAuthRequiredWorkflow() throws Exception { assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS), "Subscription should be established"); // Note: We don't use awaitChildQueueCountStable() here because the agent is already running - // in the background (sleeping for 3s). By the time we check, it might have already completed. + // in the background (sleeping for 2s). By the time we check, it might have already completed. // The subscriptionLatch already ensures the subscription is established, and completionLatch // below will catch the COMPLETED event from the background agent. // 3. Verify subscription receives COMPLETED state from background agent execution - // Agent should complete after simulating out-of-band auth delay (500ms) + // Agent should complete after simulating out-of-band auth delay (2000ms) assertTrue(completionLatch.await(10, TimeUnit.SECONDS), "Should receive COMPLETED state from background agent"); assertFalse(completionUnexpectedEvent.get(), "Should only receive TaskEvent"); assertNull(errorRef.get(), "Should not receive errors"); assertEquals(TaskState.TASK_STATE_COMPLETED, completedState.get(), "Task should be COMPLETED after background auth"); } finally { - if (taskCreated) { - deleteTaskInTaskStore(authRequiredTaskId); + if (taskCreated.get()) { + String taskId = authRequiredTaskIdRef.get(); + if (taskId != null) { + deleteTaskInTaskStore(taskId); + } } } } @@ -2199,6 +2214,8 @@ public void testStreamingMethodWithoutAcceptHeader() throws Exception { } private void testSendStreamingMessageWithHttpClient(String mediaType) throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { Message message = Message.builder(MESSAGE) .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) @@ -2245,6 +2262,9 @@ private void testSendStreamingMessageWithHttpClient(String mediaType) throws Exc Assertions.assertTrue(dataRead); Assertions.assertNull(errorRef.get()); + } finally { + deleteTaskInTaskStore(MINIMAL_TASK.id()); + } } public void testSendStreamingMessage(boolean createTask) throws Exception { @@ -2252,10 +2272,11 @@ public void testSendStreamingMessage(boolean createTask) throws Exception { saveTaskInTaskStore(MINIMAL_TASK); } try { - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); + Message.Builder messageBuilder = Message.builder(MESSAGE); + if (createTask) { + messageBuilder.taskId(MINIMAL_TASK.id()).contextId(MINIMAL_TASK.contextId()); + } + Message message = messageBuilder.build(); CountDownLatch latch = new CountDownLatch(1); AtomicReference receivedMessage = new AtomicReference<>(); @@ -2759,30 +2780,29 @@ public void testMainQueueStaysOpenForNonFinalTasks() throws Exception { @Test @Timeout(value = 2, unit = TimeUnit.MINUTES) public void testMainQueueClosesForFinalizedTasks() throws Exception { - String taskId = "completed-task-integration"; - String contextId = "completed-ctx"; - - // Send a message that will create and complete the task + // Send a message without taskId - server generates one Message message = Message.builder(MESSAGE) - .taskId(taskId) - .contextId(contextId) .parts(new TextPart("complete task")) .build(); CountDownLatch completionLatch = new CountDownLatch(1); AtomicReference errorRef = new AtomicReference<>(); + AtomicReference generatedTaskId = new AtomicReference<>(); BiConsumer consumer = (event, agentCard) -> { if (event instanceof TaskEvent te) { + generatedTaskId.compareAndSet(null, te.getTask().id()); // Might get Task with final state if (te.getTask().status().state().isFinal()) { completionLatch.countDown(); } } else if (event instanceof MessageEvent me) { - // Message is considered a final event + // Message is considered a final event - capture taskId from the message + generatedTaskId.compareAndSet(null, me.getMessage().taskId()); completionLatch.countDown(); } else if (event instanceof TaskUpdateEvent tue && tue.getUpdateEvent() instanceof TaskStatusUpdateEvent status) { + generatedTaskId.compareAndSet(null, status.taskId()); if (status.isFinal()) { completionLatch.countDown(); } @@ -2804,6 +2824,9 @@ public void testMainQueueClosesForFinalizedTasks() throws Exception { "Should receive final event"); assertNull(errorRef.get(), "Should not have errors during message send"); + String taskId = generatedTaskId.get(); + assertNotNull(taskId, "Should have captured server-generated taskId"); + // Give cleanup time to run after final event Thread.sleep(2000); @@ -2857,13 +2880,16 @@ public void testMainQueueClosesForFinalizedTasks() throws Exception { } finally { // Task might not exist in store if created via message send - try { - Task task = getTaskFromTaskStore(taskId); - if (task != null) { - deleteTaskInTaskStore(taskId); + String taskId = generatedTaskId.get(); + if (taskId != null) { + try { + Task task = getTaskFromTaskStore(taskId); + if (task != null) { + deleteTaskInTaskStore(taskId); + } + } catch (Exception e) { + // Ignore cleanup errors } - } catch (Exception e) { - // Ignore cleanup errors - task might not have been persisted } } } @@ -2887,11 +2913,8 @@ public void testMainQueueClosesForFinalizedTasks() throws Exception { */ @Test public void testAgentToAgentDelegation() throws Exception { - String delegationTaskId = "agent-to-agent-test-" + UUID.randomUUID(); - + // No taskId - server generates one; routing is by message content prefix "delegate:" Message delegationMessage = Message.builder() - .taskId(delegationTaskId) - .contextId("agent-to-agent-context") .role(Message.Role.ROLE_USER) .parts(new TextPart("delegate:What is 2+2?")) .build(); @@ -2928,10 +2951,6 @@ public void testAgentToAgentDelegation() throws Exception { String delegatedText = extractTextFromTask(delegationResult); assertTrue(delegatedText.contains("Handled locally:"), "Delegated content should have been handled locally by target agent. Got: " + delegatedText); - - // Verify the task ID is the original one (not the delegated task's ID) - assertEquals(delegationTaskId, delegationResult.id(), - "Task ID should be the original task ID, not the delegated task's ID"); } /** @@ -2949,13 +2968,10 @@ public void testAgentToAgentDelegation() throws Exception { */ @Test public void testAgentToAgentLocalHandling() throws Exception { - String localTaskId = "agent-to-agent-test-" + UUID.randomUUID(); - + // No taskId - server generates one; routing is by message content prefix "a2a-local:" Message localMessage = Message.builder() - .taskId(localTaskId) - .contextId("agent-to-agent-context") .role(Message.Role.ROLE_USER) - .parts(new TextPart("Hello directly")) + .parts(new TextPart("a2a-local:Hello directly")) .build(); CountDownLatch localLatch = new CountDownLatch(1); diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java index f6f72be1d..ba9ce0676 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java @@ -48,92 +48,72 @@ public AgentExecutor agentExecutor() { @Override public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { String taskId = context.getTaskId(); + String input = context.getMessage() != null ? extractTextFromMessage(context.getMessage()) : ""; - // Agent-to-agent communication test - if (taskId != null && taskId.startsWith("agent-to-agent-test")) { + // Agent-to-agent communication test (routed by message content prefix) + if (input.startsWith("delegate:") || input.startsWith("a2a-local:")) { handleAgentToAgentTest(context, agentEmitter); return; } - // Special handling for multi-event test - if (taskId != null && taskId.startsWith("multi-event-test")) { - // First call: context.getTask() == null (new task) - if (context.getTask() == null) { - agentEmitter.startWork(); - // Return immediately - queue stays open because task is in WORKING state - return; - } else { - // Second call: context.getTask() != null (existing task) - agentEmitter.addArtifact( - List.of(new TextPart("Second message artifact")), - "artifact-2", "Second Artifact", null); - agentEmitter.complete(); - return; - } + // Special handling for multi-event test (routed by message content) + if (input.startsWith("multi-event:first")) { + agentEmitter.startWork(); + // Return immediately - queue stays open because task is in WORKING state + return; + } + if (input.startsWith("multi-event:second")) { + agentEmitter.addArtifact( + List.of(new TextPart("Second message artifact")), + "artifact-2", "Second Artifact", null); + agentEmitter.complete(); + return; } - // Special handling for input-required test - if (taskId != null && taskId.startsWith("input-required-test")) { - String input = extractTextFromMessage(context.getMessage()); + // Special handling for input-required test (routed by message content) + if (input.startsWith("input-required:")) { + String payload = input.substring("input-required:".length()); // Second call: user provided the required input - complete the task - if ("User input".equals(input)) { - // Go directly to COMPLETED without intermediate WORKING state - // This avoids race condition where blocking call interrupts on WORKING + if ("User input".equals(payload)) { agentEmitter.complete(); return; } - // First call: any other message - emit INPUT_REQUIRED - // Go directly to INPUT_REQUIRED without intermediate WORKING state - // This avoids race condition where blocking call interrupts on WORKING - // before INPUT_REQUIRED is persisted to TaskStore + // First call: emit INPUT_REQUIRED agentEmitter.requiresInput(agentEmitter.newAgentMessage( List.of(new TextPart("Please provide additional information")), context.getMessage().metadata())); - // Return immediately - queue stays open because task is in INPUT_REQUIRED state return; } - // Special handling for auth-required test - if (taskId != null && taskId.startsWith("auth-required-test")) { - // AUTH_REQUIRED workflow: agent emits AUTH_REQUIRED, simulates out-of-band auth delay, then completes - // Go directly to AUTH_REQUIRED without intermediate WORKING state - // This avoids race condition where blocking call interrupts on WORKING - // before AUTH_REQUIRED is persisted to TaskStore + // Special handling for auth-required test (routed by message content) + if (input.startsWith("auth-required:")) { agentEmitter.requiresAuth(agentEmitter.newAgentMessage( List.of(new TextPart("Please authenticate with OAuth provider")), context.getMessage().metadata())); try { - // Simulate out-of-band authentication delay (user authenticates externally) - // Sleep long enough for test to establish subscription and wait for completion Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new InternalError("Auth simulation interrupted: " + e.getMessage()); } - // Complete task (auth "received" out-of-band) - // Agent continues after AUTH_REQUIRED without new request agentEmitter.complete(); return; } - if (context.getTaskId().equals("task-not-supported-123")) { + if ("task-not-supported-123".equals(taskId)) { throw new UnsupportedOperationError(); } // Check for delegated agent-to-agent messages (marked with special prefix) - if (context.getMessage() != null) { - String userInput = extractTextFromMessage(context.getMessage()); - if (userInput.startsWith("#a2a-delegated#")) { - // This is a delegated message from agent-to-agent test - complete it - String actualContent = userInput.substring("#a2a-delegated#".length()); - agentEmitter.startWork(); - String response = "Handled locally: " + actualContent; - agentEmitter.addArtifact(List.of(new TextPart(response))); - agentEmitter.complete(); - return; - } + if (input.startsWith("#a2a-delegated#")) { + String actualContent = input.substring("#a2a-delegated#".length()); + agentEmitter.startWork(); + String response = "Handled locally: " + actualContent; + agentEmitter.addArtifact(List.of(new TextPart(response))); + agentEmitter.complete(); + return; } // Default handler: echo back message or task @@ -182,6 +162,8 @@ private void handleAgentToAgentTest(RequestContext context, AgentEmitter agentEm // Check for delegation pattern if (userInput.startsWith("delegate:")) { handleDelegation(userInput, transportProtocol, agentEmitter); + } else if (userInput.startsWith("a2a-local:")) { + handleLocally(userInput.substring("a2a-local:".length()), agentEmitter); } else { handleLocally(userInput, agentEmitter); } diff --git a/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java index 28b32cc4e..a3f281b3b 100644 --- a/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java +++ b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java @@ -180,6 +180,7 @@ public void testOnCancelTaskNotFound() throws Exception { @Test public void testOnMessageNewMessageSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); }; @@ -212,6 +213,7 @@ public void testOnMessageNewMessageWithExistingTaskSuccess() throws Exception { @Test public void testOnMessageError() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.fail(new UnsupportedOperationError()); }; @@ -297,8 +299,9 @@ public void testOnSetPushNotificationNoPushNotifierConfig() throws Exception { @Test public void testOnMessageStreamNewMessageSuccess() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentEmitter.sendMessage(context.getMessage()); }; StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); @@ -774,6 +777,7 @@ public void testOnGetExtendedAgentCard() throws Exception { @Test public void testStreamingDoesNotBlockMainThread() throws Exception { GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); // Track if the main thread gets blocked during streaming AtomicBoolean eventReceived = new AtomicBoolean(false); @@ -944,6 +948,7 @@ public ServerCallContext create(StreamObserver streamObserver) { }; } }; + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); @@ -1085,6 +1090,7 @@ public ServerCallContext create(StreamObserver streamObserver) { }; } }; + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); @@ -1136,6 +1142,7 @@ public ServerCallContext create(StreamObserver streamObserver) { }; } }; + taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); diff --git a/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java b/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java index 83751e919..f8d4cf74d 100644 --- a/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java +++ b/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java @@ -174,6 +174,7 @@ public void testOnCancelTaskNotFound() { @Test public void testOnMessageNewMessageSuccess() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); }; @@ -209,6 +210,7 @@ public void testOnMessageError() { // See testMessageOnErrorMocks() for a test more similar to the Python implementation, using mocks for // EventConsumer.consumeAll() JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.fail(new UnsupportedOperationError()); }; @@ -226,6 +228,7 @@ public void testOnMessageError() { @Test public void testOnMessageErrorMocks() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); Message message = Message.builder(MESSAGE) .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) @@ -248,8 +251,9 @@ public void testOnMessageErrorMocks() { @Test public void testOnMessageStreamNewMessageSuccess() throws InterruptedException { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + agentEmitter.sendMessage(context.getMessage()); }; Message message = Message.builder(MESSAGE) @@ -307,6 +311,7 @@ public void testOnMessageStreamNewMessageMultipleEventsSuccess() throws Interrup // Note: Do NOT set callback - DefaultRequestHandler has a permanent callback // We'll verify persistence by checking TaskStore after streaming completes JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); // Create multiple events to be sent during streaming Task taskEvent = Task.builder(MINIMAL_TASK) @@ -426,6 +431,7 @@ public void onComplete() { @Test public void testOnMessageStreamNewMessageSuccessMocks() { JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); // This is used to send events from a mock List events = List.of( @@ -1728,6 +1734,7 @@ public void testRequiredExtensionProvidedSuccess() { .build(); JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); // Create context WITH the required extension Set requestedExtensions = new HashSet<>(); @@ -1887,6 +1894,7 @@ public void testCompatibleVersionSuccess() { .build(); JSONRPCHandler handler = new JSONRPCHandler(agentCard, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); // Create context with compatible version 1.1 ServerCallContext contextWithVersion = new ServerCallContext( @@ -1930,6 +1938,7 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { .build(); JSONRPCHandler handler = new JSONRPCHandler(agentCard, requestHandler, internalExecutor); + taskStore.save(MINIMAL_TASK, false); // Use default callContext (no version - should default to 1.0) agentExecutorExecute = (context, agentEmitter) -> { From e3e436ab7bbcd1a8825304245d01a49e87b6b203 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Thu, 16 Apr 2026 16:16:24 +0200 Subject: [PATCH 108/192] ci: update TCK workflow to use a2a-tck 1.0-dev branch with codegen SUT (#779) Switch the TCK CI workflow to pull from the 1.0-dev branch of a2a-tck and use its codegen to generate and run the a2a-java SUT, instead of the local tck/ module. --------- Signed-off-by: Jeff Mesnil Co-authored-by: Claude Opus 4.6 --- .github/workflows/run-tck.yml | 140 ++++++------------ pom.xml | 1 - tck/pom.xml | 65 -------- .../sdk/tck/server/AgentCardProducer.java | 59 -------- .../sdk/tck/server/AgentExecutorProducer.java | 100 ------------- .../sdk/tck/server/package-info.java | 10 -- tck/src/main/resources/application.properties | 21 --- 7 files changed, 46 insertions(+), 350 deletions(-) delete mode 100644 tck/pom.xml delete mode 100644 tck/src/main/java/org/a2aproject/sdk/tck/server/AgentCardProducer.java delete mode 100644 tck/src/main/java/org/a2aproject/sdk/tck/server/AgentExecutorProducer.java delete mode 100644 tck/src/main/java/org/a2aproject/sdk/tck/server/package-info.java delete mode 100644 tck/src/main/resources/application.properties diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index 87a16980d..d0a0212be 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -1,7 +1,6 @@ name: Run TCK on: - # Handle all branches for now push: branches: - main @@ -12,17 +11,10 @@ on: env: # Tag/branch of the TCK - TCK_VERSION: main - # Tell the TCK runner to report failure if the quality tests fail - A2A_TCK_FAIL_ON_QUALITY: 1 - # Tell the TCK runner to report failure if the features tests fail - A2A_TCK_FAIL_ON_FEATURES: 1 + TCK_VERSION: 1.0-dev # Tells uv to not need a venv, and instead use system UV_SYSTEM_PYTHON: 1 - # SUT_JSONRPC_URL to use for the TCK and the server agent - SUT_JSONRPC_URL: http://localhost:9999 - # Slow system on CI - TCK_STREAMING_TIMEOUT: 5.0 + SUT_URL: http://localhost:9999 # Only run the latest job concurrency: @@ -34,142 +26,102 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java-version: [17, 21, 25] + java-version: [17] steps: - name: Checkout a2a-java uses: actions/checkout@v6 - - name: Checkout a2a-tck - uses: actions/checkout@v6 - with: - repository: a2aproject/a2a-tck - path: tck/a2a-tck - ref: ${{ env.TCK_VERSION }} - name: Set up JDK ${{ matrix.java-version }} uses: actions/setup-java@v5 with: java-version: ${{ matrix.java-version }} distribution: 'temurin' cache: maven - - name: check java_home - run: echo $JAVA_HOME + - name: Build a2a-java SDK + run: mvn -B install -DskipTests + - name: Extract a2a-java version + id: extract-version + run: | + A2A_JAVA_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + echo "version=$A2A_JAVA_VERSION" >> $GITHUB_OUTPUT + echo "Detected a2a-java version: $A2A_JAVA_VERSION" + - name: Checkout a2a-tck + uses: actions/checkout@v6 + with: + repository: a2aproject/a2a-tck + path: a2a-tck + ref: ${{ env.TCK_VERSION }} - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: - python-version-file: "tck/a2a-tck/pyproject.toml" + python-version-file: "a2a-tck/pyproject.toml" - name: Install uv and Python dependencies run: | pip install uv uv pip install -e . - working-directory: tck/a2a-tck - - name: Build with Maven, skipping tests - run: mvn -B install -DskipTests + working-directory: a2a-tck + - name: Generate a2a-java SUT + run: A2A_JAVA_SDK_VERSION=${{ steps.extract-version.outputs.version }} make codegen-a2a-java-sut + working-directory: a2a-tck - name: Start SUT - run: SUT_GRPC_URL=${{ env.SUT_JSONRPC_URL }} SUT_REST_URL=${{ env.SUT_JSONRPC_URL }} mvn -B quarkus:dev & #SUT_JSONRPC_URL already set - working-directory: tck + run: mvn -B quarkus:dev -Dquarkus.console.enabled=false & + working-directory: a2a-tck/sut/a2a-java - name: Wait for SUT to start run: | - URL="${{ env.SUT_JSONRPC_URL }}/.well-known/agent-card.json" + URL="${{ env.SUT_URL }}/.well-known/agent-card.json" EXPECTED_STATUS=200 TIMEOUT=120 RETRY_INTERVAL=2 START_TIME=$(date +%s) while true; do - # Calculate elapsed time CURRENT_TIME=$(date +%s) ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) - # Check for timeout if [ "$ELAPSED_TIME" -ge "$TIMEOUT" ]; then - echo "❌ Timeout: Server did not respond with status $EXPECTED_STATUS within $TIMEOUT seconds." + echo "Timeout: Server did not respond with status $EXPECTED_STATUS within $TIMEOUT seconds." exit 1 fi - # Get HTTP status code. || true is to reporting a failure to connect as an error HTTP_STATUS=$(curl --output /dev/null --silent --write-out "%{http_code}" "$URL") || true - echo "STATUS: ${HTTP_STATUS}" - # Check if we got the correct status code if [ "$HTTP_STATUS" -eq "$EXPECTED_STATUS" ]; then - echo "✅ Server is up! Received status $HTTP_STATUS after $ELAPSED_TIME seconds." + echo "Server is up! Received status $HTTP_STATUS after $ELAPSED_TIME seconds." break; fi - # Wait before retrying - echo "⏳ Server not ready (status: $HTTP_STATUS). Retrying in $RETRY_INTERVAL seconds..." + echo "Server not ready (status: $HTTP_STATUS). Retrying in $RETRY_INTERVAL seconds..." sleep "$RETRY_INTERVAL" done - - name: Run TCK id: run-tck timeout-minutes: 5 run: | set -o pipefail - ./run_tck.py --sut-url ${{ env.SUT_JSONRPC_URL }} --category all --transports jsonrpc,grpc,rest --compliance-report report.json 2>&1 | tee tck-output.log - working-directory: tck/a2a-tck - - name: Capture Diagnostics on Failure - if: failure() + uv run ./run_tck.py --sut-host ${{ env.SUT_URL }} -v 2>&1 | tee tck-output.log + working-directory: a2a-tck + - name: TCK Summary + if: always() && steps.run-tck.outcome != 'skipped' run: | - echo "=== Capturing diagnostic information ===" - - # Create diagnostics directory - mkdir -p tck/target/diagnostics - - # Capture process list - echo "📋 Capturing process list..." - ps auxww > tck/target/diagnostics/processes.txt - - # Find the actual Quarkus JVM (child of Maven process), not the Maven parent - # Look for the dev.jar process which is the actual application - QUARKUS_PID=$(pgrep -f "a2a-tck-server-dev.jar" || echo "") - if [ -n "$QUARKUS_PID" ]; then - echo "📊 Capturing thread dump for Quarkus JVM PID $QUARKUS_PID" - jstack $QUARKUS_PID > tck/target/diagnostics/thread-dump.txt || echo "Failed to capture thread dump" - if [ -f tck/target/diagnostics/thread-dump.txt ]; then - echo "✅ Thread dump captured ($(wc -l < tck/target/diagnostics/thread-dump.txt) lines)" + if [ -f a2a-tck/tck-output.log ]; then + # Extract everything after the first ═══ separator line + SUMMARY=$(sed -n '/^═══/,$p' a2a-tck/tck-output.log) + if [ -n "$SUMMARY" ]; then + echo '### TCK Results (Java ${{ matrix.java-version }})' >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "$SUMMARY" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY fi - else - echo "⚠️ No Quarkus JVM process found for thread dump" - echo "Available Java processes:" - ps aux | grep java | tee -a tck/target/diagnostics/processes.txt || true - fi - - # Capture Quarkus application logs (if available) - echo "📝 Checking for Quarkus logs..." - if [ -f tck/target/quarkus.log ]; then - cp tck/target/quarkus.log tck/target/diagnostics/ - echo "✅ Copied quarkus.log ($(wc -l < tck/target/quarkus.log) lines)" fi - - # Copy TCK server logs - if [ -f tck/target/tck-test.log ]; then - cp tck/target/tck-test.log tck/target/diagnostics/ - echo "✅ Copied tck-test.log ($(wc -l < tck/target/tck-test.log) lines)" - fi - - echo "" - echo "=== Diagnostic capture complete ===" - - name: Stop Quarkus Server + - name: Stop SUT if: always() run: | - # Find and kill the Quarkus process to ensure logs are flushed pkill -f "quarkus:dev" || true sleep 2 - - name: Upload TCK Diagnostics - if: failure() - uses: actions/upload-artifact@v6 - with: - name: tck-diagnostics-java-${{ matrix.java-version }} - path: | - tck/target/diagnostics/ - tck/a2a-tck/tck-output.log - retention-days: 7 - if-no-files-found: warn - - name: Upload TCK Compliance Report + - name: Upload TCK Reports if: always() uses: actions/upload-artifact@v6 with: - name: tck-compliance-report-java-${{ matrix.java-version }} - path: tck/a2a-tck/report.json + name: tck-reports-java-${{ matrix.java-version }} + path: a2a-tck/reports/ retention-days: 14 - if-no-files-found: ignore + if-no-files-found: warn \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8078b339a..31c762137 100644 --- a/pom.xml +++ b/pom.xml @@ -570,7 +570,6 @@ server-common spec spec-grpc - tck test-utils-docker tests/server-common transport/jsonrpc diff --git a/tck/pom.xml b/tck/pom.xml deleted file mode 100644 index 026715dfb..000000000 --- a/tck/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - - org.a2aproject.sdk - a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT - - - a2a-tck-server - - Java SDK A2A TCK Server - Server example to use with the A2A TCK - - - - ${project.groupId} - a2a-java-sdk-reference-jsonrpc - - - org.a2aproject.sdk - a2a-java-sdk-reference-grpc - - - org.a2aproject.sdk - a2a-java-sdk-reference-rest - - - io.quarkus - quarkus-rest - provided - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - jakarta.ws.rs - jakarta.ws.rs-api - - - - - - - io.quarkus - quarkus-maven-plugin - true - - - - build - generate-code - generate-code-tests - - - - - - - diff --git a/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentCardProducer.java b/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentCardProducer.java deleted file mode 100644 index 15262001f..000000000 --- a/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentCardProducer.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.a2aproject.sdk.tck.server; - - -import java.util.Collections; -import java.util.List; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import org.a2aproject.sdk.server.PublicAgentCard; -import org.a2aproject.sdk.spec.AgentCapabilities; -import org.a2aproject.sdk.spec.AgentCard; -import org.a2aproject.sdk.spec.AgentInterface; -import org.a2aproject.sdk.spec.AgentSkill; -import org.a2aproject.sdk.spec.TransportProtocol; - -@ApplicationScoped -public class AgentCardProducer { - - private static final String DEFAULT_SUT_URL = "http://localhost:9999"; - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - - String sutJsonRpcUrl = getEnvOrDefault("SUT_JSONRPC_URL", DEFAULT_SUT_URL); - String sutGrpcUrl = getEnvOrDefault("SUT_GRPC_URL", DEFAULT_SUT_URL); - String sutRestcUrl = getEnvOrDefault("SUT_REST_URL", DEFAULT_SUT_URL); - return AgentCard.builder() - .name("Hello World Agent") - .description("Just a hello world agent") - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.JSONRPC.asString(), sutJsonRpcUrl), - new AgentInterface(TransportProtocol.GRPC.asString(), sutGrpcUrl), - new AgentInterface(TransportProtocol.HTTP_JSON.asString(), sutRestcUrl))) - .version("1.0.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(AgentSkill.builder() - .id("hello_world") - .name("Returns hello world") - .description("just returns hello world") - .tags(Collections.singletonList("hello world")) - .examples(List.of("hi", "hello world")) - .build())) - .build(); - } - - private static String getEnvOrDefault(String envVar, String defaultValue) { - String value = System.getenv(envVar); - return value == null || value.isBlank() ? defaultValue : value; - } -} - diff --git a/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentExecutorProducer.java b/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentExecutorProducer.java deleted file mode 100644 index 55bd4a71b..000000000 --- a/tck/src/main/java/org/a2aproject/sdk/tck/server/AgentExecutorProducer.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.a2aproject.sdk.tck.server; - -import java.util.List; - -import jakarta.annotation.PreDestroy; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import org.a2aproject.sdk.server.agentexecution.AgentExecutor; -import org.a2aproject.sdk.server.agentexecution.RequestContext; -import org.a2aproject.sdk.server.tasks.AgentEmitter; -import org.a2aproject.sdk.spec.A2AError; -import org.a2aproject.sdk.spec.Task; -import org.a2aproject.sdk.spec.TaskNotCancelableError; -import org.a2aproject.sdk.spec.TaskState; -import org.a2aproject.sdk.spec.TaskStatus; - -@ApplicationScoped -public class AgentExecutorProducer { - - @Produces - public AgentExecutor agentExecutor() { - return new FireAndForgetAgentExecutor(); - } - - private static class FireAndForgetAgentExecutor implements AgentExecutor { - - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - Task task = context.getTask(); - - if (task == null) { - if (context == null) { - throw new IllegalArgumentException("RequestContext may not be null"); - } - if (context.getTaskId() == null) { - throw new IllegalArgumentException("Parameter 'id' may not be null"); - } - if (context.getContextId() == null) { - throw new IllegalArgumentException("Parameter 'contextId' may not be null"); - } - task = Task.builder() - .id(context.getTaskId()) - .contextId(context.getContextId()) - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .history(List.of(context.getMessage())) - .build(); - agentEmitter.addTask(task); - } - - // Sleep to allow task state persistence before TCK subscribe test - if (context.getMessage() != null && context.getMessage().messageId().startsWith("test-subscribe-message-id")) { - int timeoutMs = Integer.parseInt(System.getenv().getOrDefault("RESUBSCRIBE_TIMEOUT_MS", "3000")); - System.out.println("====> task id starts with test-subscribe-message-id, sleeping for " + timeoutMs + " ms"); - try { - Thread.sleep(timeoutMs); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - // Immediately set to WORKING state - agentEmitter.startWork(); - System.out.println("====> task set to WORKING, starting background execution"); - - // Method returns immediately - task continues in background - System.out.println("====> execute() method returning immediately, task running in background"); - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - System.out.println("====> task cancel request received"); - Task task = context.getTask(); - if (task == null) { - System.out.println("====> No task found"); - throw new TaskNotCancelableError(); - } - if (task.status().state() == TaskState.TASK_STATE_CANCELED) { - System.out.println("====> task already canceled"); - throw new TaskNotCancelableError(); - } - - if (task.status().state() == TaskState.TASK_STATE_COMPLETED) { - System.out.println("====> task already completed"); - throw new TaskNotCancelableError(); - } - - agentEmitter.cancel(); - System.out.println("====> task canceled"); - } - - /** - * Cleanup method for proper resource management - */ - @PreDestroy - public void cleanup() { - System.out.println("====> shutting down task executor"); - } - } -} diff --git a/tck/src/main/java/org/a2aproject/sdk/tck/server/package-info.java b/tck/src/main/java/org/a2aproject/sdk/tck/server/package-info.java deleted file mode 100644 index dc93d6473..000000000 --- a/tck/src/main/java/org/a2aproject/sdk/tck/server/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -@NullMarked -package org.a2aproject.sdk.tck.server; - -import org.jspecify.annotations.NullMarked; - -//The following had @Nullable annotation applied from JSpecify -//AgentCardProducer.java getEnvOrDefault method, -//AgentExecutorProducer.java execute method -// - diff --git a/tck/src/main/resources/application.properties b/tck/src/main/resources/application.properties deleted file mode 100644 index b9b442693..000000000 --- a/tck/src/main/resources/application.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Use the new gRPC implementation which uses the main HTTP port -quarkus.grpc.server.use-separate-server=false -%dev.quarkus.http.port=9999 - -# Thread pool configuration for TCK testing -# Limit max threads to prevent resource exhaustion in CI environments -a2a.executor.core-pool-size=5 -a2a.executor.max-pool-size=15 -a2a.executor.keep-alive-seconds=60 - -# Enable debug logging for troubleshooting TCK failures -quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG -quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG -quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG -org.a2aproject.sdk.server.diagnostics.ThreadStats.level=DEBUG - -# Log to file for analysis -quarkus.log.file.enable=true -quarkus.log.file.path=target/tck-test.log -quarkus.log.file.level=DEBUG -quarkus.log.console.level=INFO From cc272288d27acd470877f46eaadd9ae354fdfb1b Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 16 Apr 2026 16:50:35 +0200 Subject: [PATCH 109/192] fix: Fixing last TCK issues (#795) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #791 🦕 --------- Signed-off-by: Emmanuel Hugonnet --- .../sdk/client/http/VertxA2AHttpClient.java | 273 +++++++++++++----- .../client/http/VertxA2AHttpClientTest.java | 2 +- .../OpenTelemetryRequestHandlerDecorator.java | 8 +- .../sdk/client/http/JdkA2AHttpClient.java | 24 +- .../server/apps/quarkus/A2AServerRoutes.java | 11 +- .../DefaultRequestHandler.java | 38 ++- .../requesthandlers/RequestHandler.java | 3 + .../sdk/grpc/utils/JSONRPCUtils.java | 28 +- .../sdk/grpc/utils/JSONRPCUtilsTest.java | 101 ++++++- .../org/a2aproject/sdk/util/ErrorDetail.java | 31 ++ .../jsonrpc/handler/JSONRPCHandler.java | 15 +- .../transport/rest/handler/RestHandler.java | 27 +- 12 files changed, 434 insertions(+), 127 deletions(-) create mode 100644 spec/src/main/java/org/a2aproject/sdk/util/ErrorDetail.java diff --git a/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java b/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java index 74a744b51..8daf859d0 100644 --- a/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java +++ b/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java @@ -18,8 +18,17 @@ import org.jspecify.annotations.Nullable; import org.a2aproject.sdk.common.A2AErrorMessages; +import org.a2aproject.sdk.util.Assert; +import io.vertx.core.AsyncResult; +import io.vertx.core.Future; +import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpClientOptions; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.RequestOptions; +import io.vertx.core.streams.WriteStream; import io.vertx.ext.web.client.HttpRequest; import io.vertx.ext.web.client.HttpResponse; import io.vertx.ext.web.client.WebClient; @@ -121,6 +130,7 @@ public class VertxA2AHttpClient implements A2AHttpClient, AutoCloseable { private final Vertx vertx; private final WebClient webClient; + private final HttpClient httpClient; private boolean ownsVertx; private static final Logger log = Logger.getLogger(VertxA2AHttpClient.class.getName()); @@ -144,6 +154,7 @@ public VertxA2AHttpClient() { .setFollowRedirects(true) .setKeepAlive(true); this.webClient = WebClient.create(vertx, options); + this.httpClient = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true)); log.fine("Vert.x client is ready."); } @@ -177,18 +188,16 @@ private Vertx createVertx() { * such as Quarkus applications. * * @param vertx the Vert.x instance to use; must not be null - * @throws NullPointerException if vertx is null + * @throws IllegalArgumentException if vertx is null */ public VertxA2AHttpClient(Vertx vertx) { - if (vertx == null) { - throw new NullPointerException("vertx must not be null"); - } - this.vertx = vertx; + this.vertx = Assert.checkNotNullParam("vertx", vertx); this.ownsVertx = false; WebClientOptions options = new WebClientOptions() .setFollowRedirects(true) .setKeepAlive(true); this.webClient = WebClient.create(vertx, options); + this.httpClient = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true)); log.fine("Vert.x client is ready."); } @@ -203,6 +212,7 @@ public VertxA2AHttpClient(Vertx vertx) { @Override public void close() { webClient.close(); + httpClient.close(); if (ownsVertx) { vertx.close(); } @@ -337,7 +347,13 @@ private void handleResponse( /** * Common method to execute async SSE requests (GET or POST). * - * @param baseRequest the base HTTP request (HttpRequest<Buffer>) configured with method and URL + *

            Uses the lower-level {@link HttpClient} so that the response status and + * {@code Content-Type} header are available before any body bytes flow. The + * response is paused immediately on arrival; the appropriate body handler is then + * wired up and the response is resumed via {@code pipe().to(...)}. + * + * @param httpMethod the HTTP method (GET or POST) + * @param url the absolute request URL * @param headers custom headers to add to the request * @param bodyBuffer optional body buffer for POST requests (null for GET) * @param messageConsumer callback for each SSE message received @@ -346,7 +362,8 @@ private void handleResponse( * @return CompletableFuture that completes when the stream ends */ private CompletableFuture executeAsyncSSE( - HttpRequest baseRequest, + HttpMethod httpMethod, + String url, Map headers, @Nullable Buffer bodyBuffer, Consumer messageConsumer, @@ -354,72 +371,84 @@ private CompletableFuture executeAsyncSSE( Runnable completeRunnable) { CompletableFuture future = new CompletableFuture<>(); - AtomicBoolean successOccurred = new AtomicBoolean(false); - AtomicBoolean streamEnded = new AtomicBoolean(false); AtomicBoolean futureCompleted = new AtomicBoolean(false); - HttpRequest request = baseRequest - .putHeader(ACCEPT, EVENT_STREAM) - .as(BodyCodec.sseStream(stream -> { - stream.handler(event -> { - String data = event.data(); - if (data != null) { - data = data.trim(); - if (!data.isEmpty()) { - messageConsumer.accept(data); - } - } - }); - - stream.endHandler(v -> { - streamEnded.set(true); - // Only complete if we've validated success and haven't completed yet - if (successOccurred.get() && futureCompleted.compareAndSet(false, true)) { - completeRunnable.run(); - future.complete(null); - } - }); - - stream.exceptionHandler(error -> { - if (futureCompleted.compareAndSet(false, true)) { - errorConsumer.accept(error); - future.complete(null); - } - }); - })); - - // Add custom headers + RequestOptions options = new RequestOptions() + .setAbsoluteURI(url) + .setMethod(httpMethod) + .addHeader(ACCEPT, EVENT_STREAM); for (Map.Entry entry : headers.entrySet()) { - request.putHeader(entry.getKey(), entry.getValue()); + options.addHeader(entry.getKey(), entry.getValue()); } - // Send with or without body - var sendFuture = (bodyBuffer != null) ? request.sendBuffer(bodyBuffer) : request.send(); - - sendFuture + httpClient.request(options) + .compose(req -> bodyBuffer != null ? req.send(bodyBuffer) : req.send()) .onSuccess(response -> { - // Validate status code manually since .expecting() doesn't work with SSE streams + // Pause before inspecting headers so no body bytes are lost while we + // set up the appropriate handler. pipe().to(...) will resume the response. + response.pause(); int statusCode = response.statusCode(); - if (statusCode < 200 || statusCode >= 300) { - // Error - don't set successOccurred, just report error + if (statusCode == HTTP_UNAUTHORIZED || statusCode == HTTP_FORBIDDEN) { if (futureCompleted.compareAndSet(false, true)) { - // Use same error messages as sync requests for consistency - IOException error = switch (statusCode) { - case HTTP_UNAUTHORIZED -> new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); - case HTTP_FORBIDDEN -> new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); - default -> new IOException("HTTP " + statusCode + ": " + response.bodyAsString()); - }; + IOException error = (statusCode == HTTP_UNAUTHORIZED) + ? new IOException(A2AErrorMessages.AUTHENTICATION_FAILED) + : new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); errorConsumer.accept(error); future.complete(null); } + return; + } + String contentType = response.getHeader("Content-Type"); + boolean isSse = statusCode >= HTTP_OK && statusCode < HTTP_MULT_CHOICE + && contentType != null && contentType.contains(EVENT_STREAM); + if (isSse) { + BodyCodec.sseStream(readStream -> + readStream.handler(event -> { + String data = event.data(); + if (data != null) { + data = data.trim(); + if (!data.isEmpty()) { + messageConsumer.accept(data); + } + } + }) + ).create(ar -> { + if (ar.failed()) { + if (futureCompleted.compareAndSet(false, true)) { + errorConsumer.accept(ar.cause()); + future.complete(null); + } + return; + } + response.pipe().to(ar.result()) + .onSuccess(v -> { + if (futureCompleted.compareAndSet(false, true)) { + completeRunnable.run(); + future.complete(null); + } + }) + .onFailure(cause -> { + if (futureCompleted.compareAndSet(false, true)) { + errorConsumer.accept(cause); + future.complete(null); + } + }); + }); } else { - // Success - mark as successful - successOccurred.set(true); - // If stream already ended, complete now - if (streamEnded.get() && futureCompleted.compareAndSet(false, true)) { - completeRunnable.run(); - future.complete(null); - } + // Non-SSE response (error body): deliver lines to messageConsumer so + // the SSEEventListener up the call stack can parse the JSON-RPC error. + response.pipe().to(new PlainBodyWriteStream(messageConsumer)) + .onSuccess(v -> { + if (futureCompleted.compareAndSet(false, true)) { + future.complete(null); + } + }) + .onFailure(cause -> { + if (futureCompleted.compareAndSet(false, true)) { + errorConsumer.accept(cause); + future.complete(null); + } + }); } }) .onFailure(cause -> { @@ -461,8 +490,7 @@ public CompletableFuture getAsyncSSE( Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { - HttpRequest request = webClient.getAbs(url); - return executeAsyncSSE(request, headers, null, messageConsumer, errorConsumer, completeRunnable); + return executeAsyncSSE(HttpMethod.GET, url, headers, null, messageConsumer, errorConsumer, completeRunnable); } } @@ -504,9 +532,8 @@ public CompletableFuture postAsyncSSE( Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { - HttpRequest request = webClient.postAbs(url); Buffer bodyBuffer = Buffer.buffer(body, StandardCharsets.UTF_8.name()); - return executeAsyncSSE(request, headers, bodyBuffer, messageConsumer, errorConsumer, completeRunnable); + return executeAsyncSSE(HttpMethod.POST, url, headers, bodyBuffer, messageConsumer, errorConsumer, completeRunnable); } } @@ -534,6 +561,122 @@ public A2AHttpResponse delete() throws IOException, InterruptedException { } } + /** + * A {@link WriteStream} that handles plain (non-SSE) response bodies, e.g. JSON error + * responses returned when the stream never opens. Accumulates raw bytes, splits into lines + * on {@code \n} (decoding complete lines as UTF-8 to correctly handle multi-byte characters + * that may be split across consecutive write calls), and forwards each non-empty line to the + * message consumer so the SSEEventListener can parse the typed error. + * + *

            A hard cap of {@value #MAX_BUFFER_BYTES} bytes is enforced on the internal buffer + * to prevent Denial-of-Service via {@link OutOfMemoryError} for arbitrarily large inputs. + */ + private static class PlainBodyWriteStream implements WriteStream { + /** Maximum number of raw bytes that may be buffered before further writes are rejected. */ + private static final int MAX_BUFFER_BYTES = 1024 * 1024; // 1 MB + + private final Consumer messageConsumer; + /** + * Raw bytes waiting for a complete line delimiter. We buffer raw bytes — rather than + * decoded characters — so that multi-byte UTF-8 sequences split across consecutive + * {@link #write} calls are never decoded prematurely. + */ + private Buffer rawBuffer = Buffer.buffer(); + private @Nullable Handler exceptionHandler; + + PlainBodyWriteStream(Consumer messageConsumer) { + this.messageConsumer = messageConsumer; + } + + /** + * Scans {@link #rawBuffer} for {@code '\n'} bytes (0x0A, which never appears as a + * continuation byte in UTF-8), decodes each complete line as UTF-8, trims whitespace, + * and forwards non-empty lines to the message consumer. Unconsumed bytes are retained + * in the buffer for the next write. + */ + private void processLines() { + int start = 0; + int len = rawBuffer.length(); + while (true) { + int nlIdx = -1; + for (int i = start; i < len; i++) { + if (rawBuffer.getByte(i) == '\n') { + nlIdx = i; + break; + } + } + if (nlIdx < 0) break; + String line = new String(rawBuffer.getBytes(start, nlIdx), StandardCharsets.UTF_8).trim(); + start = nlIdx + 1; + if (!line.isEmpty()) { + messageConsumer.accept(line); + } + } + if (start > 0) { + rawBuffer = rawBuffer.getBuffer(start, len); + } + } + + @Override + public Future write(Buffer data) { + if (rawBuffer.length() + data.length() > MAX_BUFFER_BYTES) { + IllegalStateException ex = new IllegalStateException( + "Response body exceeded maximum allowed size of " + MAX_BUFFER_BYTES + " bytes"); + Handler eh = exceptionHandler; + if (eh != null) { + eh.handle(ex); + } + return Future.failedFuture(ex); + } + rawBuffer.appendBuffer(data); + processLines(); + return Future.succeededFuture(); + } + + @Override + public void write(Buffer data, Handler> handler) { + Future result = write(data); + if (handler != null) { + handler.handle(result); + } + } + + @Override + public void end(Handler> handler) { + if (rawBuffer.length() > 0) { + String remaining = rawBuffer.toString(StandardCharsets.UTF_8).trim(); + rawBuffer = Buffer.buffer(); + if (!remaining.isEmpty()) { + messageConsumer.accept(remaining); + } + } + if (handler != null) { + handler.handle(Future.succeededFuture()); + } + } + + @Override + public WriteStream exceptionHandler(@Nullable Handler handler) { + this.exceptionHandler = handler; + return this; + } + + @Override + public WriteStream setWriteQueueMaxSize(int maxSize) { + return this; + } + + @Override + public boolean writeQueueFull() { + return false; + } + + @Override + public WriteStream drainHandler(@Nullable Handler handler) { + return this; + } + } + private record VertxHttpResponse(int status, String body) implements A2AHttpResponse { @Override diff --git a/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientTest.java b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientTest.java index d0780b20d..90fdb4c57 100644 --- a/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientTest.java +++ b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientTest.java @@ -25,7 +25,7 @@ public void testVertxParameterConstructor() { @Test public void testVertxParameterConstructorNullThrows() { - assertThrows(NullPointerException.class, () -> { + assertThrows(IllegalArgumentException.class, () -> { new VertxA2AHttpClient(null); }); } diff --git a/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java b/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java index d0da323c2..d99729284 100644 --- a/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java +++ b/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java @@ -43,6 +43,7 @@ import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; import java.util.concurrent.Flow; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -455,7 +456,12 @@ public void onDeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigP span.end(); } } - + + @Override + public void validateRequestedTask(@Nullable String requestedTaskId) throws A2AError { + delegate.validateRequestedTask(requestedTaskId); + } + private boolean extractRequest() { return Boolean.getBoolean(EXTRACT_REQUEST_SYS_PROPERTY); } diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java index 6c8f7ec53..6f2837058 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java @@ -142,6 +142,8 @@ protected CompletableFuture asyncRequest( Flow.Subscriber subscriber = new Flow.Subscriber() { private Flow.@Nullable Subscription subscription; private volatile boolean errorRaised = false; + private boolean isSseStream = false; + private boolean firstMeaningfulLineSeen = false; @Override public void onSubscribe(Flow.Subscription subscription) { @@ -151,10 +153,23 @@ public void onSubscribe(Flow.Subscription subscription) { @Override public void onNext(String item) { - // SSE messages sometimes start with "data:". Strip that off - if (item != null && item.startsWith("data:")) { - item = item.substring(5).trim(); - if (!item.isEmpty()) { + if (item != null && !item.isEmpty()) { + if (!firstMeaningfulLineSeen) { + firstMeaningfulLineSeen = true; + isSseStream = item.startsWith("data:") || item.startsWith(":") + || item.startsWith("event:") || item.startsWith("id:") + || item.startsWith("retry:"); + } + if (isSseStream) { + if (item.startsWith("data:")) { + String data = item.substring(5).trim(); + if (!data.isEmpty()) { + messageConsumer.accept(data); + } + } + // Other SSE control lines (event:, id:, retry:, :) are ignored + } else { + // Plain error body: deliver so SSEEventListener can parse the typed error messageConsumer.accept(item); } } @@ -300,7 +315,6 @@ private HttpRequest.Builder createRequestBuilder(boolean SSE) throws IOException @Override public A2AHttpResponse post() throws IOException, InterruptedException { HttpRequest request = createRequestBuilder(false) - .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)) .build(); HttpResponse response = httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); diff --git a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index a43c119a6..e6433df77 100644 --- a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -438,7 +438,12 @@ private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest * @return a Multi stream of JSON-RPC responses */ private Multi> processStreamingRequest( - A2ARequest request, ServerCallContext context) { + A2ARequest request, ServerCallContext context) throws A2AError { + if (request instanceof SendStreamingMessageRequest req) { + jsonRpcHandler.validateRequestedTask(req.getParams().message().taskId()); + } else if (request instanceof SubscribeToTaskRequest req) { + jsonRpcHandler.validateRequestedTask(req.getParams().id()); + } try { Flow.Publisher> publisher; if (request instanceof SendStreamingMessageRequest req) { @@ -450,8 +455,6 @@ private Multi> processStreamingRequest( } return Multi.createFrom().publisher(publisher); } catch (A2AError error) { - // For streaming endpoints, wrap immediate errors (like TaskNotFoundError, - // UnsupportedOperationError) in error response and send as first SSE event return Multi.createFrom().item(generateErrorResponse(request, error)); } } @@ -601,7 +604,7 @@ private String extractTenant(RoutingContext rc) { * "error": { * "code": -32602, * "message": "Invalid params", - * "details": { ... } + * "data": [ ... ] * } * } * } diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java index aea2cbc68..0e3aab7f4 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java @@ -339,7 +339,7 @@ public ListTasksResult onListTasks(ListTasksParams params, ServerCallContext con Instant now = Instant.now(); if (params.statusTimestampAfter().isAfter(now)) { Map errorData = new HashMap<>(); - errorData.put("parameter", "lastUpdatedAfter"); + errorData.put("parameter", "statusTimestampAfter"); errorData.put("reason", "Timestamp cannot be in the future"); throw new InvalidParamsError(null, "Invalid params", errorData); } @@ -1061,6 +1061,23 @@ private MessageSendSetup initMessageSend(MessageSendParams params, ServerCallCon return new MessageSendSetup(taskManager, task, requestContext); } + @Override + public void validateRequestedTask(@Nullable String requestedTaskId) throws A2AError { + if (requestedTaskId == null) { + return; + } + Task task = taskStore.get(requestedTaskId); + if (task == null) { + throw new TaskNotFoundError(); + } + + if (task.status().state().isFinal()) { + throw new UnsupportedOperationError(null, String.format( + "Cannot send message to task %s: task is in terminal state %s and cannot accept further messages", + task.id(), task.status().state()), null); + } + } + private @Nullable Task validateRequestedTask(MessageSendParams params) throws A2AError { String requestedTaskId = params.message().taskId(); if (requestedTaskId == null) { @@ -1162,24 +1179,5 @@ private void logThreadStats(String label) { THREAD_STATS_LOGGER.debug("=== END THREAD STATS ==="); } - /** - * Check if an event represents a final task state. - * - * @param eventKind the event to check - * @return true if the event represents a final state (COMPLETED, FAILED, CANCELED, REJECTED, UNKNOWN) - */ - private boolean isFinalEvent(EventKind eventKind) { - if (!(eventKind instanceof Event event)) { - return false; - } - if (event instanceof Task task) { - return task.status() != null && task.status().state() != null - && task.status().state().isFinal(); - } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { - return statusUpdate.isFinal(); - } - return false; - } - private record MessageSendSetup(TaskManager taskManager, @Nullable Task task, RequestContext requestContext) {} } diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/RequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/RequestHandler.java index 8edad37c0..402150a97 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/RequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/RequestHandler.java @@ -18,6 +18,7 @@ import org.a2aproject.sdk.spec.TaskIdParams; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskQueryParams; +import org.jspecify.annotations.Nullable; public interface RequestHandler { Task onGetTask( @@ -59,4 +60,6 @@ ListTaskPushNotificationConfigsResult onListTaskPushNotificationConfigs( void onDeleteTaskPushNotificationConfig( DeleteTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError; + + void validateRequestedTask(@Nullable String requestedTaskId) throws A2AError; } diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java index db43d92a9..adbdd87ff 100644 --- a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java @@ -1,12 +1,14 @@ package org.a2aproject.sdk.grpc.utils; import org.a2aproject.sdk.spec.A2AErrorCodes; + import static org.a2aproject.sdk.spec.A2AMethods.CANCEL_TASK_METHOD; import static org.a2aproject.sdk.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; import static org.a2aproject.sdk.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; import java.io.IOException; import java.io.StringWriter; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.logging.Level; @@ -66,6 +68,7 @@ import org.a2aproject.sdk.spec.TaskNotFoundError; import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.a2aproject.sdk.spec.VersionNotSupportedError; +import org.a2aproject.sdk.util.ErrorDetail; import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; @@ -284,11 +287,12 @@ public static StreamResponse parseResponseEvent(String body) throws JsonMappingE JsonElement jelement = JsonParser.parseString(body); JsonObject jsonRpc = jelement.getAsJsonObject(); String version = getAndValidateJsonrpc(jsonRpc); - Object id = getAndValidateId(jsonRpc); - JsonElement paramsNode = jsonRpc.get("result"); + // Check for error before validating id: per JSON-RPC spec, error responses may have null id if (jsonRpc.has("error")) { throw processError(jsonRpc.getAsJsonObject("error")); } + Object id = getAndValidateId(jsonRpc); + JsonElement paramsNode = jsonRpc.get("result"); StreamResponse.Builder builder = StreamResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); return builder.build(); @@ -392,8 +396,16 @@ 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; Map details = null; - if (error.has("data") && error.get("data").isJsonObject()) { - details =GSON.fromJson(error.get("data"), Map.class); + if (error.has("data")) { + JsonElement data = error.get("data"); + if (data.isJsonObject()) { + details = GSON.fromJson(data, Map.class); + } else if (data.isJsonArray() && !data.getAsJsonArray().isEmpty()) { + JsonElement first = data.getAsJsonArray().get(0); + if (first.isJsonObject()) { + details = GSON.fromJson(first.getAsJsonObject(), Map.class); + } + } } if (code != null) { A2AErrorCodes errorCode = A2AErrorCodes.fromCode(code); @@ -605,10 +617,10 @@ public static String toJsonRPCErrorResponse(Object requestId, A2AError error) { output.beginObject(); output.name("code").value(error.getCode()); output.name("message").value(error.getMessage()); - if (!error.getDetails().isEmpty()) { - output.name("data"); - GSON.toJson(error.getDetails(), Map.class, output); - } + A2AErrorCodes a2aErrorCode = A2AErrorCodes.fromCode(error.getCode()); + String reason = a2aErrorCode != null ? a2aErrorCode.name() : A2AErrorCodes.INTERNAL.name(); + output.name("data"); + GSON.toJson(List.of(ErrorDetail.of(reason, error.getDetails())), List.class, output); output.endObject(); output.endObject(); return result.toString(); diff --git a/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java index d692be94e..0a89eb194 100644 --- a/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java +++ b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java @@ -7,8 +7,11 @@ 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 static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import com.google.gson.JsonArray; +import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import org.a2aproject.sdk.jsonrpc.common.json.InvalidParamsJsonMappingException; @@ -20,7 +23,9 @@ import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.util.ErrorDetail; import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.TaskNotFoundError; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.junit.jupiter.api.Test; @@ -143,7 +148,7 @@ public void testParseInvalidProtoStructure_ThrowsInvalidParamsJsonMappingExcepti @Test public void testParseNumericalTimestampThrowsInvalidParamsJsonMappingException() { - String valideRequest = """ + String validRequest = """ { "jsonrpc": "2.0", "method": "ListTasks", @@ -165,7 +170,7 @@ public void testParseNumericalTimestampThrowsInvalidParamsJsonMappingException() """; try { - A2ARequest request = JSONRPCUtils.parseRequestBody(valideRequest, null); + A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest, null); assertEquals(1, request.getId()); } catch (JsonProcessingException e) { fail(e); @@ -208,7 +213,7 @@ public void testParseMissingField_ThrowsInvalidParamsError() throws JsonMappingE @Test public void testParseUnknownField_ThrowsJsonMappingException() throws JsonMappingException { - String unkownFieldMessage= """ + String unknownFieldMessage= """ { "jsonrpc":"2.0", "method":"SendMessage", @@ -232,7 +237,7 @@ public void testParseUnknownField_ThrowsJsonMappingException() throws JsonMappin }"""; JsonMappingException exception = assertThrows( JsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(unkownFieldMessage, null) + () -> JSONRPCUtils.parseRequestBody(unknownFieldMessage, null) ); assertEquals(ERROR_MESSAGE.formatted("unknown in message lf.a2a.v1.Message"), exception.getMessage()); } @@ -391,4 +396,92 @@ public void testParseErrorResponse_ParseError() throws Exception { assertEquals(-32700, response.getError().getCode()); assertEquals("Parse error", response.getError().getMessage()); } + + @Test + public void testToJsonRPCErrorResponse_KnownErrorCode_ProducesDataArray() { + TaskNotFoundError error = new TaskNotFoundError(); + + String json = JSONRPCUtils.toJsonRPCErrorResponse("req-1", error); + + var jsonObject = JsonParser.parseString(json).getAsJsonObject(); + var errorObj = jsonObject.getAsJsonObject("error"); + assertTrue(errorObj.has("data"), "error should have a 'data' field"); + assertTrue(errorObj.get("data").isJsonArray(), "'data' field should be a JSON array"); + JsonArray dataArray = errorObj.getAsJsonArray("data"); + assertEquals(1, dataArray.size()); + var detail = dataArray.get(0).getAsJsonObject(); + assertEquals(ErrorDetail.ERROR_INFO_TYPE, detail.get("@type").getAsString()); + assertEquals("TASK_NOT_FOUND", detail.get("reason").getAsString()); + assertEquals(ErrorDetail.ERROR_DOMAIN, detail.get("domain").getAsString()); + } + + @Test + public void testProcessError_ArrayFormData_ExtractsFirstElement() throws Exception { + String errorResponse = """ + { + "jsonrpc": "2.0", + "id": "8", + "error": { + "code": -32001, + "message": "Task not found", + "data": [ + { + "@type": "type.googleapis.com/google.rpc.ErrorInfo", + "reason": "TASK_NOT_FOUND", + "domain": "a2a-protocol.org", + "metadata": {} + } + ] + } + } + """; + + CreateTaskPushNotificationConfigResponse response = + (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + + assertNotNull(response); + assertInstanceOf(TaskNotFoundError.class, response.getError()); + assertEquals(-32001, response.getError().getCode()); + assertEquals("Task not found", response.getError().getMessage()); + } + + @Test + public void testProcessError_ArrayFormData_NonObjectElement_DoesNotThrow() throws Exception { + // Verifies that a non-object first array element does not cause a ClassCastException + String errorResponse = """ + { + "jsonrpc": "2.0", + "id": "9", + "error": { + "code": -32001, + "message": "Task not found", + "data": ["unexpected-string-element"] + } + } + """; + + CreateTaskPushNotificationConfigResponse response = + (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + + assertNotNull(response); + assertInstanceOf(TaskNotFoundError.class, response.getError()); + // details should be empty since the array element was not an object + assertTrue(response.getError().getDetails().isEmpty()); + } + + @Test + public void testToJsonRPCErrorResponse_RoundTrip() throws Exception { + TaskNotFoundError original = new TaskNotFoundError("Custom message", null); + + String json = JSONRPCUtils.toJsonRPCErrorResponse("req-rt", original); + CreateTaskPushNotificationConfigResponse response = + (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody( + json, + SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); + + assertNotNull(response); + assertInstanceOf(TaskNotFoundError.class, response.getError()); + assertEquals(-32001, response.getError().getCode()); + assertEquals("Custom message", response.getError().getMessage()); + } } diff --git a/spec/src/main/java/org/a2aproject/sdk/util/ErrorDetail.java b/spec/src/main/java/org/a2aproject/sdk/util/ErrorDetail.java new file mode 100644 index 000000000..5ae87248c --- /dev/null +++ b/spec/src/main/java/org/a2aproject/sdk/util/ErrorDetail.java @@ -0,0 +1,31 @@ +package org.a2aproject.sdk.util; + +import java.util.Map; + +import com.google.gson.annotations.SerializedName; +import org.jspecify.annotations.Nullable; + +/** + * Represents a single entry in the JSON-RPC {@code error.data} array, following + * the Google {@code ErrorInfo} format ({@code type.googleapis.com/google.rpc.ErrorInfo}). + */ +public record ErrorDetail( + @SerializedName("@type") String type, + String reason, + String domain, + @Nullable Map metadata) { + + public static final String ERROR_INFO_TYPE = "type.googleapis.com/google.rpc.ErrorInfo"; + public static final String ERROR_DOMAIN = "a2a-protocol.org"; + + public ErrorDetail { + Assert.checkNotNullParam("type", type); + Assert.checkNotNullParam("reason", reason); + Assert.checkNotNullParam("domain", domain); + } + + /** Convenience factory using the standard A2A ErrorInfo type and domain. */ + public static ErrorDetail of(String reason, @Nullable Map metadata) { + return new ErrorDetail(ERROR_INFO_TYPE, reason, ERROR_DOMAIN, metadata); + } +} diff --git a/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java b/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java index 53fc59b08..ed7008bc4 100644 --- a/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java +++ b/transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java @@ -374,23 +374,20 @@ public CancelTaskResponse onCancelTask(CancelTaskRequest request, ServerCallCont * @see #onMessageSendStream(SendStreamingMessageRequest, ServerCallContext) */ public Flow.Publisher onSubscribeToTask( - SubscribeToTaskRequest request, ServerCallContext context) { + SubscribeToTaskRequest request, ServerCallContext context) throws A2AError { if (!agentCard.capabilities().streaming()) { return ZeroPublisher.fromItems( new SendStreamingMessageResponse( request.getId(), new InvalidRequestError("Streaming is not supported by the agent"))); } - + requestHandler.validateRequestedTask(request.getParams().id()); try { Flow.Publisher publisher = requestHandler.onSubscribeToTask(request.getParams(), context); // 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 (TaskNotFoundError | UnsupportedOperationError e) { - // Re-throw initial validation errors for routing layer to wrap in SSE format - throw e; } catch (A2AError e) { // Other A2AError types - wrap inline as part of the stream return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), e)); @@ -434,7 +431,7 @@ public GetTaskPushNotificationConfigResponse getPushNotificationConfig( requestHandler.onGetTaskPushNotificationConfig(request.getParams(), context); return new GetTaskPushNotificationConfigResponse(request.getId(), config); } catch (A2AError e) { - return new GetTaskPushNotificationConfigResponse(request.getId().toString(), e); + return new GetTaskPushNotificationConfigResponse(request.getId(), e); } catch (Throwable t) { return new GetTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); } @@ -474,7 +471,7 @@ public CreateTaskPushNotificationConfigResponse setPushNotificationConfig( try { TaskPushNotificationConfig config = requestHandler.onCreateTaskPushNotificationConfig(request.getParams(), context); - return new CreateTaskPushNotificationConfigResponse(request.getId().toString(), config); + return new CreateTaskPushNotificationConfigResponse(request.getId(), config); } catch (A2AError e) { return new CreateTaskPushNotificationConfigResponse(request.getId(), e); } catch (Throwable t) { @@ -745,4 +742,8 @@ public void onComplete() { }, executor); }); } + + public void validateRequestedTask(String requestedTaskId) { + requestHandler.validateRequestedTask(requestedTaskId); + } } diff --git a/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java index fd26c451f..3ca6a1878 100644 --- a/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java +++ b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java @@ -26,6 +26,7 @@ import com.google.protobuf.util.JsonFormat; import mutiny.zero.ZeroPublisher; import org.a2aproject.sdk.grpc.utils.ProtoUtils; +import org.a2aproject.sdk.util.ErrorDetail; import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; @@ -53,6 +54,7 @@ import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; import org.a2aproject.sdk.spec.ListTasksParams; +import org.a2aproject.sdk.spec.MessageSendParams; import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; import org.a2aproject.sdk.spec.StreamingEventKind; import org.a2aproject.sdk.spec.Task; @@ -297,7 +299,13 @@ public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String t org.a2aproject.sdk.grpc.SendMessageRequest.Builder request = org.a2aproject.sdk.grpc.SendMessageRequest.newBuilder(); parseRequestBody(body, request); request.setTenant(tenant); - Flow.Publisher publisher = requestHandler.onMessageSendStream(ProtoUtils.FromProto.messageSendParams(request), context); + MessageSendParams params = ProtoUtils.FromProto.messageSendParams(request); + try { + requestHandler.validateRequestedTask(params.message().taskId()); + } catch (A2AError e) { + return createErrorResponse(e); + } + Flow.Publisher publisher = requestHandler.onMessageSendStream(params, context); return createStreamingResponse(publisher); } catch (A2AError e) { return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(e).toJson())); @@ -370,7 +378,6 @@ public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContex if (!taskIdFromBody.isEmpty() && !taskIdFromBody.equals(taskId)) { throw new InvalidParamsError("Task ID in request body (" + taskIdFromBody + ") does not match task ID in URL path (" + taskId + ")."); } - builder.setTenant(tenant); builder.setTaskId(taskId); TaskPushNotificationConfig result = requestHandler.onCreateTaskPushNotificationConfig(ProtoUtils.FromProto.createTaskPushNotificationConfig(builder), context); @@ -420,6 +427,11 @@ public HTTPRestResponse subscribeToTask(ServerCallContext context, String tenant return createErrorResponse(new InvalidRequestError("Streaming is not supported by the agent")); } TaskIdParams params = TaskIdParams.builder().id(taskId).tenant(tenant).build(); + try { + requestHandler.validateRequestedTask(params.id()); + } catch (A2AError e) { + return createErrorResponse(e); + } Flow.Publisher publisher = requestHandler.onSubscribeToTask(params, context); return createStreamingResponse(publisher); } catch (A2AError e) { @@ -946,9 +958,6 @@ public Flow.Publisher getPublisher() { } } - private static final String ERROR_INFO_TYPE = "type.googleapis.com/google.rpc.ErrorInfo"; - private static final String ERROR_DOMAIN = "a2a-protocol.org"; - /** * Represents an HTTP error response containing A2A error details in the Google Cloud API error format. *

            @@ -984,7 +993,7 @@ private HTTPRestErrorResponse(A2AError a2aError) { String reason = errorCode != null ? errorCode.name() : "INTERNAL"; String message = a2aError.getMessage() == null ? a2aError.getClass().getName() : a2aError.getMessage(); - ErrorDetail detail = new ErrorDetail(ERROR_INFO_TYPE, reason, ERROR_DOMAIN, a2aError.getDetails()); + ErrorDetail detail = ErrorDetail.of(reason, a2aError.getDetails()); this.error = new ErrorBody(httpCode, status, message, List.of(detail)); } @@ -1003,11 +1012,5 @@ public String toString() { } private record ErrorBody(int code, String status, String message, List details) {} - - private record ErrorDetail( - @com.google.gson.annotations.SerializedName("@type") String type, - String reason, - String domain, - Map metadata) {} } } From ef0d71364a9dd13cef4b0e941b625529fec6b747 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Fri, 17 Apr 2026 12:36:56 +0200 Subject: [PATCH 110/192] chore: release 1.0.0.Beta1 Signed-off-by: Emmanuel Hugonnet --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../sdk/examples/helloworld/HelloWorldRunner.java | 12 ++++++------ examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- extras/opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 2 +- .../tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- .../tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- test-utils-docker/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 50 files changed, 55 insertions(+), 55 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 099cf8b7c..9250e0b5e 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 36ef852d9..5f6874468 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index cbc5fb075..e371a8780 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index f71e33b50..276e87268 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index 93daf1a10..de4bb55b9 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 45d27e74b..ab0c9e656 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 3cea636cb..3404af28d 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index ea69e52e0..3a4f7634a 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index aaf1dc9f4..5429b8444 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index 3303b94f4..7d212ff48 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-common diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index d4850fc2a..9920728ff 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index c2c6d9a22..0da413632 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-examples-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java index 57735e0f8..457f3273e 100644 --- a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Beta1-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Beta1-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Beta1-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Beta1-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Beta1-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Beta1-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Beta1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Beta1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Beta1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Beta1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Beta1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Beta1 //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index b0d652df3..6cc332cb6 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 79c06db81..b34ef2a2f 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-examples-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index 3f121f0ae..ca9836b08 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 9dfecd261..c393e8246 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index 9d09aa7d4..f42fbb330 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-opentelemetry-client-propagation diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index f93398818..549b135c4 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-opentelemetry-client diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index 0c14ecb43..4760cbd24 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-opentelemetry-common diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index 06f70ff24..14a8cc370 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-opentelemetry-integration-tests diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 73c393bea..034d99b93 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index 9b1c69bc9..41fa104aa 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-opentelemetry-server diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index c6bdb6f76..311d343db 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 7a5f06a73..249a2dd35 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 39cbc82c7..25b95548e 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 91ea1c53b..7273e7876 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index de60e9dea..a6d9811c9 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index 90ff65774..a657100d6 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index f0776700b..fe98ecbab 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index f80647a36..392673f35 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index 6a1d8292d..ed18eddd4 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index f8c1ca0e5..a0ae840d8 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 0332ed906..72e484c2c 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index af41894f7..c5f8ea8a5 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 8cf8ddbca..0d500d57f 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index 5c032c743..7e3e65c70 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index 31c762137..95114e372 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index 6cba35a4a..6299dfe24 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index b37623553..bb4e0c2f1 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 9cf3d567b..4796818b1 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index 9e6375d7d..ce37373d1 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index 21f078782..0dea7a42d 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index bf41e3cc1..481a231ed 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index 82dfa2278..4a372bd42 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 a2a-java-sdk-spec diff --git a/test-utils-docker/pom.xml b/test-utils-docker/pom.xml index 6f8c021bd..20381e093 100644 --- a/test-utils-docker/pom.xml +++ b/test-utils-docker/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../pom.xml diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index 74930c263..21a9d160c 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index 718430633..9d04eb2bc 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index de91da75d..604d7fe71 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index ffcdc2115..250e85c52 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1-SNAPSHOT + 1.0.0.Beta1 ../../pom.xml a2a-java-sdk-transport-rest From 3fc30855b40829e7c38ceb09c188ac56efdb64f4 Mon Sep 17 00:00:00 2001 From: Pratik Lala Date: Thu, 16 Apr 2026 21:08:34 -0700 Subject: [PATCH 111/192] fix: expose HTTP status code in JSONRPCTransport errors Previously, when the JSONRPC transport received a non-2xx HTTP response, it threw a plain IOException with the status code embedded as a string (e.g. "Request failed 503"). This made it impossible for callers to programmatically distinguish 4xx from 5xx errors without fragile string parsing. This change makes the structured HTTP status code available while remaining fully backward compatible: - JSONRPCTransport.sendPostRequest now throws A2AClientException with an A2AClientHTTPError as the cause, instead of a plain IOException. All transport methods already declared 'throws A2AClientException' and already had 'catch (A2AClientException e) { throw e; }', so no caller signatures change. - A2AClientHTTPError gains a new 'responseBody' field (and getResponseBody() accessor) so callers can also inspect the raw error payload returned by the server (e.g. a gateway's JSON error body on a 429 or 503). The existing 'code', 'message', and getCode() are preserved unchanged. The old Object-typed constructor is deprecated in favour of the new String-typed one that actually stores the body. Callers that want the status code can now opt in with a simple instanceof check, while existing catch blocks for A2AClientException continue to work without modification: } catch (A2AClientException e) { if (e.getCause() instanceof A2AClientHTTPError httpErr) { int status = httpErr.getCode(); // e.g. 503 String body = httpErr.getResponseBody(); // raw response body } } Fixes #799 --- .../transport/jsonrpc/JSONRPCTransport.java | 7 ++- .../jsonrpc/JSONRPCTransportTest.java | 43 +++++++++++++++ .../sdk/spec/A2AClientHTTPError.java | 53 +++++++++++++++---- 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java index 070f564e5..bc7844084 100644 --- a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java @@ -46,6 +46,7 @@ import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import org.a2aproject.sdk.spec.A2AClientError; import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AClientHTTPError; import org.a2aproject.sdk.spec.A2AError; import org.a2aproject.sdk.spec.AgentCard; import org.a2aproject.sdk.spec.AgentInterface; @@ -321,10 +322,12 @@ private PayloadAndHeaders applyInterceptors(String methodName, @Nullable Object } private String sendPostRequest(String url, PayloadAndHeaders payloadAndHeaders, String method) throws IOException, InterruptedException, JsonProcessingException { - A2AHttpClient.PostBuilder builder = createPostBuilder(url, payloadAndHeaders,method); + A2AHttpClient.PostBuilder builder = createPostBuilder(url, payloadAndHeaders, method); A2AHttpResponse response = builder.post(); if (!response.success()) { - throw new IOException("Request failed " + response.status()); + int status = response.status(); + String message = "Request failed with HTTP " + status; + throw new A2AClientException(message, new A2AClientHTTPError(status, message, response.body())); } return response.body(); } diff --git a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportTest.java index 93c391aa2..5c1ab098d 100644 --- a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportTest.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransportTest.java @@ -38,6 +38,7 @@ import java.util.Map; import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AClientHTTPError; import org.a2aproject.sdk.spec.AgentCard; import org.a2aproject.sdk.spec.ExtensionSupportRequiredError; import org.a2aproject.sdk.spec.VersionNotSupportedError; @@ -644,6 +645,48 @@ public void testExtensionSupportRequiredErrorUnmarshalling() throws Exception { } } + /** + * Test that HTTP error responses expose the status code via A2AClientHTTPError cause, + * while remaining backward compatible (A2AClientException is still thrown). + */ + @Test + public void testHttpErrorExposeStatusCode() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + ) + .respond( + response() + .withStatusCode(503) + .withBody("{\"error\": \"Service Unavailable\"}") + ); + + JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); + MessageSendParams params = MessageSendParams.builder() + .message(Message.builder() + .role(Message.Role.ROLE_USER) + .parts(Collections.singletonList(new TextPart("hello"))) + .contextId("ctx") + .messageId("msg") + .build()) + .build(); + + try { + client.sendMessage(params, null); + fail("Expected A2AClientException to be thrown"); + } catch (A2AClientException e) { + // Backward compatible: still throws A2AClientException + assertTrue(e.getMessage().contains("503"), "Expected message to contain '503' but was: " + e.getMessage()); + // New: cause carries structured HTTP status + assertInstanceOf(A2AClientHTTPError.class, e.getCause()); + A2AClientHTTPError httpError = (A2AClientHTTPError) e.getCause(); + assertEquals(503, httpError.getCode()); + assertNotNull(httpError.getResponseBody()); + assertTrue(httpError.getResponseBody().contains("Service Unavailable"), "Expected response body to contain 'Service Unavailable' but was: " + httpError.getResponseBody()); + } + } + /** * Test that VersionNotSupportedError is properly unmarshalled from JSON-RPC error response. */ diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java index b840286be..b90ddb09c 100644 --- a/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java @@ -1,6 +1,7 @@ package org.a2aproject.sdk.spec; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Client exception indicating an HTTP transport error with a specific status code. @@ -15,14 +16,14 @@ *

          • 5xx - Server errors (500 Internal Server Error, 503 Service Unavailable, etc.)
          • * *

            - * Usage example: + * This exception is set as the cause of {@link A2AClientException} so that callers + * can inspect the HTTP status code while remaining backward compatible: *

            {@code
            - * if (response.statusCode() >= 400) {
            - *     throw new A2AClientHTTPError(
            - *         response.statusCode(),
            - *         "HTTP error: " + response.statusMessage(),
            - *         response.body()
            - *     );
            + * } catch (A2AClientException e) {
            + *     if (e.getCause() instanceof A2AClientHTTPError httpError) {
            + *         int status = httpError.getCode();           // e.g. 401, 503
            + *         String body = httpError.getResponseBody();  // raw response body, may be null
            + *     }
              * }
              * }
            * @@ -40,6 +41,12 @@ public class A2AClientHTTPError extends A2AClientError { */ private final String message; + /** + * The raw HTTP response body, may be {@code null}. + */ + @Nullable + private final String responseBody; + /** * Creates a new HTTP client error with the specified status code and message. * @@ -47,25 +54,42 @@ public class A2AClientHTTPError extends A2AClientError { * @param message the error message * @param data additional error data (may be the response body) * @throws IllegalArgumentException if code or message is null + * @deprecated Use {@link #A2AClientHTTPError(int, String, String)} instead to preserve the response body. */ + @Deprecated(since = "1.0.0.Beta1", forRemoval = true) public A2AClientHTTPError(int code, String message, Object data) { Assert.checkNotNullParam("code", code); Assert.checkNotNullParam("message", message); this.code = code; this.message = message; + this.responseBody = data instanceof String s ? s : null; } /** - * Gets the error code + * Creates a new HTTP client error with the specified status code, message, and response body. * - * @return the error code + * @param code the HTTP status code (e.g. 401, 503) + * @param message the error message + * @param responseBody the raw HTTP response body, may be {@code null} + */ + public A2AClientHTTPError(int code, String message, @Nullable String responseBody) { + Assert.checkNotNullParam("message", message); + this.code = code; + this.message = message; + this.responseBody = responseBody; + } + + /** + * Gets the HTTP status code. + * + * @return the HTTP status code (e.g. 401, 404, 500, 503) */ public int getCode() { return code; } /** - * Gets the error message + * Gets the error message. * * @return the error message */ @@ -73,4 +97,13 @@ public int getCode() { public String getMessage() { return message; } + + /** + * Returns the raw HTTP response body, if available. + * + * @return the response body, or {@code null} if not available + */ + public @Nullable String getResponseBody() { + return responseBody; + } } From 6b6cb4ef4b0b10d8203b02990670105a53777a0b Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Fri, 17 Apr 2026 15:22:09 +0200 Subject: [PATCH 112/192] chore: fixing setup-java version (#803) Signed-off-by: Emmanuel Hugonnet --- .github/workflows/release-to-maven-central.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-to-maven-central.yml b/.github/workflows/release-to-maven-central.yml index c8995e953..9f3d06dbe 100644 --- a/.github/workflows/release-to-maven-central.yml +++ b/.github/workflows/release-to-maven-central.yml @@ -4,7 +4,6 @@ on: push: tags: - 'v?[0-9]+.[0-9]+.[0-9]+*' # Trigger on tags like v1.0.0, 1.2.3, v1.2.3.Alpha1 etc. - jobs: publish: # Only run this job for the main repository, not for forks @@ -18,7 +17,7 @@ jobs: uses: actions/checkout@v6 - name: Set up JDK 17 - uses: actions/setup-java@v6 + uses: actions/setup-java@v5 with: java-version: '17' distribution: 'temurin' @@ -26,7 +25,7 @@ jobs: # Use secrets to import GPG key - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@v6 + uses: crazy-max/ghaction-import-gpg@v7 with: gpg_private_key: ${{ secrets.GPG_SIGNING_KEY }} passphrase: ${{ secrets.GPG_SIGNING_PASSPHRASE }} From 66fefdbf1c802da7939e6427ec19f74d11bc0282 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Fri, 17 Apr 2026 15:08:57 +0200 Subject: [PATCH 113/192] chore: Next SNAPSHOT version Signed-off-by: Emmanuel Hugonnet --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../sdk/examples/helloworld/HelloWorldRunner.java | 12 ++++++------ examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- extras/opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 2 +- .../tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- .../tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- test-utils-docker/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 50 files changed, 55 insertions(+), 55 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 9250e0b5e..9d5defe72 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 5f6874468..6314ca466 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index e371a8780..d907539d9 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 276e87268..88bec8cfb 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index de4bb55b9..9b6fb9670 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index ab0c9e656..2186c985c 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 3404af28d..7de354428 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index 3a4f7634a..97b77613b 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index 5429b8444..867cdf58f 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index 7d212ff48..b02dddbfe 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-common diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index 9920728ff..189b2f787 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index 0da413632..a04d72a45 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-examples-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java index 457f3273e..32b14361c 100644 --- a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Beta1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Beta1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Beta1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Beta1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Beta1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Beta1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Beta2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Beta2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Beta2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Beta2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Beta2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Beta2-SNAPSHOT //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 6cc332cb6..4a4ee2d71 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index b34ef2a2f..eb8b72ce1 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-examples-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index ca9836b08..e0acd1961 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index c393e8246..cec470583 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index f42fbb330..c1692cc9b 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-opentelemetry-client-propagation diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index 549b135c4..dcd3a7c68 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-opentelemetry-client diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index 4760cbd24..0d2a689c4 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-opentelemetry-common diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index 14a8cc370..d51edb70e 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-opentelemetry-integration-tests diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 034d99b93..390293310 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index 41fa104aa..e335a3a45 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-opentelemetry-server diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 311d343db..9b7e4b694 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 249a2dd35..019507c91 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 25b95548e..3dcf5e5cb 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 7273e7876..621dc1a9e 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index a6d9811c9..c80f72dae 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index a657100d6..9857d400b 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index fe98ecbab..9bf5c7e05 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index 392673f35..9471b7773 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index ed18eddd4..c7114b22c 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index a0ae840d8..3297eaf07 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 72e484c2c..1476a3944 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index c5f8ea8a5..c41097374 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 0d500d57f..1c9d07758 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index 7e3e65c70..2b126e4b2 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index 95114e372..006996c22 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index 6299dfe24..f03eea9a9 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index bb4e0c2f1..f89667b73 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 4796818b1..ff6fe6272 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index ce37373d1..eb917df8d 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index 0dea7a42d..0bdff9805 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index 481a231ed..090a28a62 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index 4a372bd42..4c982f996 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT a2a-java-sdk-spec diff --git a/test-utils-docker/pom.xml b/test-utils-docker/pom.xml index 20381e093..7f22cd7a0 100644 --- a/test-utils-docker/pom.xml +++ b/test-utils-docker/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../pom.xml diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index 21a9d160c..31ee8fbb2 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index 9d04eb2bc..e19859b9a 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index 604d7fe71..270566b2f 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 250e85c52..24991513b 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta1 + 1.0.0.Beta2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-rest From efe00bc96152ed5433bd5a658edade93bb71b93e Mon Sep 17 00:00:00 2001 From: Pratik Lala Date: Fri, 17 Apr 2026 10:47:05 -0700 Subject: [PATCH 114/192] ci: retrigger CI From 513a2a3034be3dbf19fd8f1db063d40c57f42abb Mon Sep 17 00:00:00 2001 From: Pratik Lala Date: Fri, 17 Apr 2026 10:57:07 -0700 Subject: [PATCH 115/192] ci: retrigger CI From 376cb261f76af71a210ec0e63d05156defe0de69 Mon Sep 17 00:00:00 2001 From: neo1027144 Date: Wed, 1 Apr 2026 21:10:16 +0800 Subject: [PATCH 116/192] test: add unit tests for DeviceCodeOAuthFlow Test cases: - Construction with all fields populated - Null refreshUrl (optional field) - Empty scopes map with full field assertions - Null validation for required fields (deviceAuthorizationUrl, tokenUrl, scopes) - Record equality, hashCode consistency, and inequality edge cases - Scopes map immutability (defensive copy via Map.copyOf) Also fix: override scopes() to return Map.copyOf(scopes) for defensive copying Fixes #607 --- .../sdk/spec/DeviceCodeOAuthFlow.java | 11 ++ .../sdk/spec/DeviceCodeOAuthFlowTest.java | 107 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 spec/src/test/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlowTest.java diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlow.java b/spec/src/main/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlow.java index f78895450..8f3b8a9f8 100644 --- a/spec/src/main/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlow.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlow.java @@ -33,5 +33,16 @@ public record DeviceCodeOAuthFlow(String deviceAuthorizationUrl, String tokenUrl Assert.checkNotNullParam("deviceAuthorizationUrl", deviceAuthorizationUrl); Assert.checkNotNullParam("tokenUrl", tokenUrl); Assert.checkNotNullParam("scopes", scopes); + scopes = Map.copyOf(scopes); + } + + /** + * Returns an unmodifiable copy of the scopes map. + * + * @return unmodifiable map of available OAuth scopes to their descriptions + */ + @Override + public Map scopes() { + return Map.copyOf(scopes); } } diff --git a/spec/src/test/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlowTest.java b/spec/src/test/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlowTest.java new file mode 100644 index 000000000..02b2f9e19 --- /dev/null +++ b/spec/src/test/java/org/a2aproject/sdk/spec/DeviceCodeOAuthFlowTest.java @@ -0,0 +1,107 @@ +package org.a2aproject.sdk.spec; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.Map; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link DeviceCodeOAuthFlow}. + *

            + * Tests cover construction with valid parameters, null validation of required + * fields, and handling of the optional {@code refreshUrl} field. + * + * @see DeviceCodeOAuthFlow + */ +class DeviceCodeOAuthFlowTest { + + private static final String DEVICE_AUTH_URL = "https://auth.example.com/device/code"; + private static final String TOKEN_URL = "https://auth.example.com/token"; + private static final String REFRESH_URL = "https://auth.example.com/refresh"; + private static final Map SCOPES = Map.of("read", "Read access", "write", "Write access"); + + @Test + void testConstruction_withAllFields() { + DeviceCodeOAuthFlow flow = new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, REFRESH_URL, SCOPES); + + assertEquals(DEVICE_AUTH_URL, flow.deviceAuthorizationUrl()); + assertEquals(TOKEN_URL, flow.tokenUrl()); + assertEquals(REFRESH_URL, flow.refreshUrl()); + assertEquals(SCOPES, flow.scopes()); + } + + @Test + void testConstruction_withNullRefreshUrl() { + DeviceCodeOAuthFlow flow = new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, null, SCOPES); + + assertEquals(DEVICE_AUTH_URL, flow.deviceAuthorizationUrl()); + assertEquals(TOKEN_URL, flow.tokenUrl()); + assertNull(flow.refreshUrl()); + assertEquals(SCOPES, flow.scopes()); + } + + @Test + void testConstruction_withEmptyScopes() { + Map emptyScopes = Map.of(); + DeviceCodeOAuthFlow flow = new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, null, emptyScopes); + + assertEquals(DEVICE_AUTH_URL, flow.deviceAuthorizationUrl()); + assertEquals(TOKEN_URL, flow.tokenUrl()); + assertNull(flow.refreshUrl()); + assertEquals(emptyScopes, flow.scopes()); + } + + @Test + void testConstruction_nullDeviceAuthorizationUrl_throwsException() { + assertThrows(IllegalArgumentException.class, + () -> new DeviceCodeOAuthFlow(null, TOKEN_URL, REFRESH_URL, SCOPES)); + } + + @Test + void testConstruction_nullTokenUrl_throwsException() { + assertThrows(IllegalArgumentException.class, + () -> new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, null, REFRESH_URL, SCOPES)); + } + + @Test + void testConstruction_nullScopes_throwsException() { + assertThrows(IllegalArgumentException.class, + () -> new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, REFRESH_URL, null)); + } + + @Test + void testEqualityAndHashCode() { + DeviceCodeOAuthFlow flow1 = new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, REFRESH_URL, SCOPES); + DeviceCodeOAuthFlow flow2 = new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, REFRESH_URL, SCOPES); + DeviceCodeOAuthFlow flow3 = new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, null, SCOPES); + DeviceCodeOAuthFlow flow4 = new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, null, SCOPES); + + // Test for equality and hashCode consistency + assertEquals(flow1, flow2); + assertEquals(flow1.hashCode(), flow2.hashCode()); + assertEquals(flow3, flow4); + assertEquals(flow3.hashCode(), flow4.hashCode()); + + // Test for inequality with different field values + assertNotEquals(flow1, flow3); + assertNotEquals(flow1, new DeviceCodeOAuthFlow("https://other.com", TOKEN_URL, REFRESH_URL, SCOPES)); + assertNotEquals(flow1, null); + assertNotEquals(flow1, "not a flow"); + } + + @Test + void testScopesImmutability() { + Map mutableScopes = new java.util.HashMap<>(); + mutableScopes.put("read", "Read access"); + DeviceCodeOAuthFlow flow = new DeviceCodeOAuthFlow(DEVICE_AUTH_URL, TOKEN_URL, REFRESH_URL, mutableScopes); + + // Modifying the original map should not affect the record + mutableScopes.put("write", "Write access"); + assertNotEquals(mutableScopes.size(), flow.scopes().size(), + "Record should be immutable and perform a defensive copy of the scopes map"); + } +} From 116d0f32b9d3de153b1563f586631f59a9702032 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 27 Apr 2026 14:20:17 +0200 Subject: [PATCH 117/192] chore: Update Dependabot configuration for Maven and GitHub Actions Added Maven and GitHub Actions package ecosystems to Dependabot configuration. Group together components for the Maven updates. Signed-off-by: Jeff Mesnil --- .github/dependabot.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..14a90626a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,35 @@ +version: 2 +updates: + - package-ecosystem: maven + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 + commit-message: + prefix: "chore" + groups: + jakarta: + patterns: + - 'jakarta.*' + quarkus: + patterns: + - 'io.quarkus:*' + grpc: + patterns: + - 'io.grpc:*' + maven-plugins: + patterns: + - 'org.apache.maven.plugins:*' + testing: + patterns: + - 'org.junit.*' + - 'org.mockito:*' + - 'org.testcontainers:*' + - 'io.rest-assured:*' + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 + commit-message: + prefix: "chore" \ No newline at end of file From a8fc346196441d27db5e6d0804f9319718b585ea Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Mon, 27 Apr 2026 15:13:37 +0200 Subject: [PATCH 118/192] chore(dep): Upgrading gson to 2.14.0 Signed-off-by: Emmanuel Hugonnet --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 006996c22..c33efb934 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ 4.2.1 0.8.0 5.0.3 - 2.13.2 + 2.14.0 4.1.0 2.0.1 2.1.3 @@ -625,4 +625,4 @@ - \ No newline at end of file + From 9bf325c0765135c32ba94bd6690e6d1179546adf Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 27 Apr 2026 15:26:46 +0200 Subject: [PATCH 119/192] fix: Remove invalid 'final' field from TaskStatusUpdateEvent JSON serialization The 'final' field was being serialized as part of TaskStatusUpdateEvent payloads but is not defined in the A2A specification for this type. Removed isFinal from the record components and replaced it with a derived method that computes the value from status.state().isFinal(). Also simplified the delegation of the `isFinalOrInterrupted()` method. Fixes #811 Co-Authored-By: Claude Opus 4.6 --- .../jsonrpc/sse/SSEEventListenerTest.java | 2 -- .../spi/sse/SSEEventListenerTest.java | 12 ++++------ .../core/EventSerializationTest.java | 2 +- .../StreamingEventKindSerializationTest.java | 5 ++-- .../server/tasks/ResultAggregatorTest.java | 1 - .../sdk/server/tasks/TaskManagerTest.java | 1 - .../mapper/TaskStatusUpdateEventMapper.java | 7 ------ .../sdk/grpc/utils/ToProtoTest.java | 2 -- .../sdk/spec/TaskStatusUpdateEvent.java | 23 ++++++++++--------- 9 files changed, 20 insertions(+), 35 deletions(-) diff --git a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java index 6b95de871..4f8efc50b 100644 --- a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java @@ -185,12 +185,10 @@ public void testOnFailure() { @Test public void testFinalTaskStatusUpdateEventCancels() { TaskStatus completedStatus = new TaskStatus(TaskState.TASK_STATE_COMPLETED); - // Use constructor since Builder doesn't have isFinal method TaskStatusUpdateEvent tsue = new TaskStatusUpdateEvent( "1234", completedStatus, "xyz", - completedStatus.state().isFinal(), // Derive from state null ); diff --git a/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java index fa337551a..b40ee0f51 100644 --- a/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java +++ b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java @@ -114,13 +114,11 @@ private static Task createTask(TaskState state) { .build(); } - private static TaskStatusUpdateEvent createTaskStatusUpdateEvent(TaskState state, boolean isFinal) { - // Use constructor since Builder doesn't have isFinal method + private static TaskStatusUpdateEvent createTaskStatusUpdateEvent(TaskState state) { return new TaskStatusUpdateEvent( TEST_TASK_ID, new TaskStatus(state), TEST_CONTEXT_ID, - isFinal, null ); } @@ -206,7 +204,7 @@ public void testOnErrorCancelsFuture() { @Test public void testShouldAutoCloseWithFinalTaskStatusUpdateEvent() { TestSSEEventListener listener = createBasicListener(); - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED); assertTrue(listener.shouldAutoClose(finalEvent)); } @@ -214,7 +212,7 @@ public void testShouldAutoCloseWithFinalTaskStatusUpdateEvent() { @Test public void testShouldAutoCloseWithNonFinalTaskStatusUpdateEvent() { TestSSEEventListener listener = createBasicListener(); - TaskStatusUpdateEvent nonFinalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_WORKING, false); + TaskStatusUpdateEvent nonFinalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_WORKING); assertFalse(listener.shouldAutoClose(nonFinalEvent)); } @@ -252,7 +250,7 @@ public void testAutoCloseCancelsFutureForFinalEvent() { AtomicReference receivedEvent = new AtomicReference<>(); TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED); CancelCapturingFuture future = new CancelCapturingFuture(); listener.setEventToHandle(finalEvent); @@ -283,7 +281,7 @@ public void testAutoCloseWithNullFuture() { AtomicReference receivedEvent = new AtomicReference<>(); TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); + TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED); // Should not throw with null future listener.setEventToHandle(finalEvent); diff --git a/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/EventSerializationTest.java b/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/EventSerializationTest.java index 84e6d068e..66b10694f 100644 --- a/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/EventSerializationTest.java +++ b/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/EventSerializationTest.java @@ -116,7 +116,7 @@ public void testTaskStatusUpdateEventSerialization() throws JsonProcessingExcept String json = JsonUtil.toJson((Event) originalEvent); assertTrue(json.contains("\"statusUpdate\""), "JSON should contain statusUpdate wrapper"); assertTrue(json.contains("\"taskId\":\"test-task-abc\""), "JSON should contain task ID"); - assertTrue(json.contains("\"final\":true"), "JSON should contain final flag"); + assertFalse(json.contains("\"final\""), "JSON should not contain final field"); // Test deserialization back to StreamingEventKind StreamingEventKind deserializedEvent = JsonUtil.fromJson(json, StreamingEventKind.class); diff --git a/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/StreamingEventKindSerializationTest.java b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/StreamingEventKindSerializationTest.java index 46062671b..80e178c51 100644 --- a/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/StreamingEventKindSerializationTest.java +++ b/jsonrpc-common/src/test/java/org/a2aproject/sdk/jsonrpc/common/json/StreamingEventKindSerializationTest.java @@ -107,7 +107,7 @@ void testTaskStatusUpdateEventSerialization() throws JsonProcessingException { assertTrue(json.contains("\"statusUpdate\"")); assertTrue(json.contains("\"taskId\":\"task-abc\"")); assertTrue(json.contains("\"state\":\"TASK_STATE_WORKING\"")); - assertTrue(json.contains("\"final\":false")); + assertFalse(json.contains("\"final\"")); assertFalse(json.contains("\"kind\"")); // Deserialize back to StreamingEventKind @@ -217,8 +217,7 @@ void testUnwrappedTaskStatusUpdateEventDeserialization() throws JsonProcessingEx "contextId": "context-999", "status": { "state": "TASK_STATE_WORKING" - }, - "final": false + } } """; diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java index 591c5d472..e641c5631 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java @@ -374,7 +374,6 @@ void testAuthRequiredWithTaskStatusUpdateEvent() throws Exception { taskId, new TaskStatus(TaskState.TASK_STATE_AUTH_REQUIRED), "ctx1", - false, // isFinal=false for AUTH_REQUIRED null ); diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerTest.java index 74ffcf79c..3df19522f 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerTest.java @@ -84,7 +84,6 @@ public void testSaveTaskEventStatusUpdate() throws A2AServerException { minimalTask.id(), newStatus, minimalTask.contextId(), - false, new HashMap<>()); diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusUpdateEventMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusUpdateEventMapper.java index a06a5a4bb..54530d8e7 100644 --- a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusUpdateEventMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/TaskStatusUpdateEventMapper.java @@ -7,9 +7,6 @@ /** * Mapper between {@link org.a2aproject.sdk.spec.TaskStatusUpdateEvent} and {@link org.a2aproject.sdk.grpc.TaskStatusUpdateEvent}. - *

            - * Now fully declarative using Builder pattern with @BeanMapping. - * Builder's isFinal() method handles the Java "final" keyword mapping. */ @Mapper(config = A2AProtoMapperConfig.class, uses = {TaskStatusMapper.class, A2ACommonFieldMapper.class}) public interface TaskStatusUpdateEventMapper { @@ -18,15 +15,12 @@ public interface TaskStatusUpdateEventMapper { /** * Converts domain TaskStatusUpdateEvent to proto. - * Uses declarative mapping with CommonFieldMapper for metadata conversion. - * Note: isFinal field is ignored as it has been removed from the proto (field 4 is reserved). */ @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") org.a2aproject.sdk.grpc.TaskStatusUpdateEvent toProto(TaskStatusUpdateEvent domain); /** * Converts proto TaskStatusUpdateEvent to domain. - * Note: isFinal is derived from status.state().isFinal() since the field has been removed from the proto (field 4 is reserved). */ default TaskStatusUpdateEvent fromProto(org.a2aproject.sdk.grpc.TaskStatusUpdateEvent proto) { if (proto == null) { @@ -37,7 +31,6 @@ default TaskStatusUpdateEvent fromProto(org.a2aproject.sdk.grpc.TaskStatusUpdate proto.getTaskId(), status, proto.getContextId(), - status != null && status.state() != null && status.state().isFinal(), A2ACommonFieldMapper.INSTANCE.metadataFromProto(proto.getMetadata()) ); } diff --git a/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/ToProtoTest.java index d27b2ce63..009bb8a5d 100644 --- a/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/ToProtoTest.java +++ b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/ToProtoTest.java @@ -256,12 +256,10 @@ public void convertTaskArtifactUpdateEvent() { @Test public void convertTaskStatusUpdateEvent() { TaskStatus completedStatus = new TaskStatus(TaskState.TASK_STATE_COMPLETED); - // Use constructor since Builder doesn't have isFinal method TaskStatusUpdateEvent tsue = new TaskStatusUpdateEvent( "1234", completedStatus, "xyz", - completedStatus.state().isFinal(), // Derive from state null ); org.a2aproject.sdk.grpc.TaskStatusUpdateEvent result = ProtoUtils.ToProto.taskStatusUpdateEvent(tsue); diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/TaskStatusUpdateEvent.java b/spec/src/main/java/org/a2aproject/sdk/spec/TaskStatusUpdateEvent.java index f56339bdc..5c2b582a2 100644 --- a/spec/src/main/java/org/a2aproject/sdk/spec/TaskStatusUpdateEvent.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/TaskStatusUpdateEvent.java @@ -8,7 +8,6 @@ import java.util.Map; -import com.google.gson.annotations.SerializedName; import org.a2aproject.sdk.util.Assert; import org.jspecify.annotations.Nullable; @@ -19,11 +18,10 @@ * @param taskId the task identifier (required) * @param status the task status (required) * @param contextId the context identifier (required) - * @param isFinal whether this is a final status * @param metadata additional metadata (optional) */ public record TaskStatusUpdateEvent(String taskId, TaskStatus status, String contextId, - @SerializedName("final") boolean isFinal, @Nullable Map metadata) implements EventKind, StreamingEventKind, UpdateEvent { + @Nullable Map metadata) implements EventKind, StreamingEventKind, UpdateEvent { /** * The identifier when used in streaming responses @@ -36,7 +34,6 @@ public record TaskStatusUpdateEvent(String taskId, TaskStatus status, String con * @param taskId the task identifier (required) * @param status the task status (required) * @param contextId the context identifier (required) - * @param isFinal whether this is a final status * @param metadata additional metadata (optional) * @throws IllegalArgumentException if taskId, status, or contextId is null */ @@ -44,9 +41,6 @@ public record TaskStatusUpdateEvent(String taskId, TaskStatus status, String con Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("status", status); Assert.checkNotNullParam("contextId", contextId); - if (isFinal != status.state().isFinal()) { - throw new IllegalArgumentException("isFinal must be the same as the Status state"); - } } @Override @@ -55,11 +49,19 @@ public String kind() { } /** - * Indicates if the task is fianl or waiting for some inputs from the client. - * @return true if the task is fianl or waiting for some inputs from the client - false otherwise. + * Indicates if this is a final status event, derived from the task state. + * @return true if the task state is terminal - false otherwise. + */ + public boolean isFinal() { + return status.state().isFinal(); + } + + /** + * Indicates if the task is final or waiting for some inputs from the client. + * @return true if the task is final or waiting for some inputs from the client - false otherwise. */ public boolean isFinalOrInterrupted() { - return status.state() == TASK_STATE_COMPLETED || status.state() == TASK_STATE_FAILED || status.state() == TASK_STATE_CANCELED || status.state() == TASK_STATE_REJECTED || status.state() == TASK_STATE_INPUT_REQUIRED; + return status.state().isFinal() || status.state().isInterrupted(); } /** @@ -155,7 +157,6 @@ public TaskStatusUpdateEvent build() { Assert.checkNotNullParam("taskId", taskId), Assert.checkNotNullParam("status", status), Assert.checkNotNullParam("contextId", contextId), - Assert.checkNotNullParam("status", status).state().isFinal(), metadata); } } From 54a8ad7c08c1a45cbf84ddab39941b5f20535f9f Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 27 Apr 2026 16:09:01 +0200 Subject: [PATCH 120/192] fix: Include Authorization header in push notification webhook requests When PushNotificationConfig includes authentication info, the agent must include the Authorization header in webhook requests per A2A spec section 4.3.3 (PUSH-DELIVER-001). The header is formatted as "{scheme} {credentials}" from the AuthenticationInfo record. This fixes #810 Co-Authored-By: Claude Opus 4.6 --- .../sdk/server/tasks/BasePushNotificationSender.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java index 6d8991f22..53f1a38d3 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java @@ -4,7 +4,6 @@ import static org.a2aproject.sdk.client.http.A2AHttpClient.CONTENT_TYPE; import static org.a2aproject.sdk.common.A2AHeaders.X_A2A_NOTIFICATION_TOKEN; -import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import jakarta.annotation.Nullable; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -25,6 +24,7 @@ import org.a2aproject.sdk.spec.StreamingEventKind; import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -135,6 +135,10 @@ private boolean dispatchNotification(StreamingEventKind event, TaskPushNotificat if (token != null && !token.isBlank()) { postBuilder.addHeader(X_A2A_NOTIFICATION_TOKEN, token); } + if (pushInfo.authentication() != null && pushInfo.authentication().credentials() != null) { + postBuilder.addHeader("Authorization", + pushInfo.authentication().scheme() + " " + pushInfo.authentication().credentials()); + } String body; try { From 17a29be04af4ea32d6f5845c1e59188533feab29 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Tue, 28 Apr 2026 16:18:47 +0200 Subject: [PATCH 121/192] fix: Apply historyLength from MessageSendConfiguration in SendMessage response The onMessageSend() method was not applying the historyLength parameter from MessageSendConfiguration to the returned Task. When historyLength=0, the spec (CORE-HIST-003, Section 3.2.4) requires no history to be returned, but the full history was being included. The fix reuses the existing limitTaskHistory() method (already used by onGetTask) to filter the Task history before returning from onMessageSend(). This fixes #816 Co-Authored-By: Claude Opus 4.6 --- .../DefaultRequestHandler.java | 5 ++ .../apps/common/AbstractA2AServerTest.java | 63 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java index 0e3aab7f4..3cf09abc6 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java @@ -625,6 +625,11 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte }); } + if (kind instanceof Task task) { + Integer historyLength = params.configuration() != null ? params.configuration().historyLength() : null; + kind = limitTaskHistory(task, historyLength); + } + LOGGER.debug("Returning: {}", kind); return kind; } diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index cc7ceb188..c2e5a4781 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -69,6 +69,7 @@ import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; import org.a2aproject.sdk.spec.ListTasksParams; import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.MessageSendConfiguration; import org.a2aproject.sdk.spec.MessageSendParams; import org.a2aproject.sdk.spec.MethodNotFoundError; import org.a2aproject.sdk.spec.Part; @@ -3022,4 +3023,66 @@ private String extractTextFromTask(Task task) { .collect(Collectors.joining("\n")); } + @Test + @Timeout(value = 30, unit = TimeUnit.SECONDS) + public void testSendMessageWithHistoryLengthZero() throws Exception { + AtomicReference taskIdRef = new AtomicReference<>(); + + try { + Message initialMessage = Message.builder(MESSAGE) + .parts(new TextPart("input-required:Trigger INPUT_REQUIRED")) + .build(); + + CountDownLatch initialLatch = new CountDownLatch(1); + getNonStreamingClient().sendMessage(initialMessage, List.of((event, agentCard) -> { + if (event instanceof TaskEvent te) { + taskIdRef.set(te.getTask().id()); + initialLatch.countDown(); + } else if (event instanceof TaskUpdateEvent tue) { + if (tue.getUpdateEvent() instanceof TaskStatusUpdateEvent statusUpdate) { + taskIdRef.set(statusUpdate.taskId()); + } + initialLatch.countDown(); + } + }), null); + + assertTrue(initialLatch.await(15, TimeUnit.SECONDS), "Initial sendMessage should complete"); + String taskId = taskIdRef.get(); + assertNotNull(taskId, "Should have captured task ID"); + + Message followUp = Message.builder(MESSAGE) + .taskId(taskId) + .parts(new TextPart("input-required:User input")) + .build(); + + MessageSendParams params = MessageSendParams.builder() + .message(followUp) + .configuration(MessageSendConfiguration.builder() + .historyLength(0) + .build()) + .build(); + + CountDownLatch followUpLatch = new CountDownLatch(1); + AtomicReference resultTaskRef = new AtomicReference<>(); + getNonStreamingClient().sendMessage(params, List.of((BiConsumer) (event, agentCard) -> { + if (event instanceof TaskEvent te) { + resultTaskRef.set(te.getTask()); + followUpLatch.countDown(); + } + }), null, null); + + assertTrue(followUpLatch.await(15, TimeUnit.SECONDS), "Follow-up sendMessage should complete"); + Task resultTask = resultTaskRef.get(); + assertNotNull(resultTask, "Should have received a Task response"); + assertTrue(resultTask.history().isEmpty(), + "historyLength=0 should return no history, but got " + + resultTask.history().size() + " messages"); + } finally { + String taskId = taskIdRef.get(); + if (taskId != null) { + deleteTaskInTaskStore(taskId); + } + } + } + } From 6a851f93ded28a03c501dcc439516b00380f831b Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 28 Apr 2026 18:56:09 +0100 Subject: [PATCH 122/192] fix: Get cloud deployment example working with Strimzi (#818) Pin version of operator to current latest version --- examples/cloud-deployment/README.md | 4 +- examples/cloud-deployment/k8s/02-kafka.yaml | 4 +- .../cloud-deployment/k8s/03-kafka-topic.yaml | 2 +- examples/cloud-deployment/scripts/deploy.sh | 10 +- .../strimzi-cluster-operator-1.0.0.yaml | 18469 ++++++++++++++++ 5 files changed, 18478 insertions(+), 11 deletions(-) create mode 100644 examples/cloud-deployment/strimzi-1.0.0/strimzi-cluster-operator-1.0.0.yaml diff --git a/examples/cloud-deployment/README.md b/examples/cloud-deployment/README.md index 11ebf4979..3028f0e29 100644 --- a/examples/cloud-deployment/README.md +++ b/examples/cloud-deployment/README.md @@ -447,7 +447,7 @@ kubectl logs -n kafka kubectl get crd kafkas.kafka.strimzi.io # If missing, reinstall Strimzi -kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka +kubectl create -f '../strimzi-1.0.0/strimzi-cluster-operator-1.0.0.yaml' -n kafka ``` ### Kind Resource Issues @@ -531,6 +531,8 @@ cloud-deployment/ │ ├── 03-kafka-topic.yaml # Kafka topic │ ├── 04-agent-configmap.yaml # Configuration │ └── 05-agent-deployment.yaml # Agent deployment + service +├── strimzi-1.0.0/ +│ └── strimzi-cluster-operator-1.0.0.yaml # Pinned from https://strimzi.io/install/latest?namespace=kafka ├── scripts/ │ ├── deploy.sh # Automated deployment │ ├── verify.sh # Health checks diff --git a/examples/cloud-deployment/k8s/02-kafka.yaml b/examples/cloud-deployment/k8s/02-kafka.yaml index a4ad8eb0f..26e7f1862 100644 --- a/examples/cloud-deployment/k8s/02-kafka.yaml +++ b/examples/cloud-deployment/k8s/02-kafka.yaml @@ -1,6 +1,6 @@ --- # KafkaNodePool for KRaft mode -apiVersion: kafka.strimzi.io/v1beta2 +apiVersion: kafka.strimzi.io/v1 kind: KafkaNodePool metadata: name: broker @@ -23,7 +23,7 @@ spec: cpu: "500m" --- # Kafka cluster -apiVersion: kafka.strimzi.io/v1beta2 +apiVersion: kafka.strimzi.io/v1 kind: Kafka metadata: name: a2a-kafka diff --git a/examples/cloud-deployment/k8s/03-kafka-topic.yaml b/examples/cloud-deployment/k8s/03-kafka-topic.yaml index 2fa7fca9c..5373d544b 100644 --- a/examples/cloud-deployment/k8s/03-kafka-topic.yaml +++ b/examples/cloud-deployment/k8s/03-kafka-topic.yaml @@ -1,6 +1,6 @@ --- # Kafka topic for A2A event replication -apiVersion: kafka.strimzi.io/v1beta2 +apiVersion: kafka.strimzi.io/v1 kind: KafkaTopic metadata: name: a2a-replicated-events diff --git a/examples/cloud-deployment/scripts/deploy.sh b/examples/cloud-deployment/scripts/deploy.sh index 26d5b0d79..ce5696f5d 100755 --- a/examples/cloud-deployment/scripts/deploy.sh +++ b/examples/cloud-deployment/scripts/deploy.sh @@ -177,13 +177,9 @@ if ! kubectl get namespace kafka > /dev/null 2>&1; then fi if ! kubectl get crd kafkas.kafka.strimzi.io > /dev/null 2>&1; then -# Keep this around in case we need to hardcode operator version again in the future -# echo "Installing Strimzi operator... at https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.50.1/strimzi-cluster-operator-0.50.1.yaml" -# curl -sL 'https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.50.1/strimzi-cluster-operator-0.50.1.yaml' \ -# | sed 's/namespace: .*/namespace: kafka/' \ -# | kubectl apply -f - -n kafka - echo "Installing Strimzi operator..." - kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka + # Pinned version of https://strimzi.io/install/latest?namespace=kafka + echo "Installing Strimzi operator (1.0.0)..." + kubectl create -f '../strimzi-1.0.0/strimzi-cluster-operator-1.0.0.yaml' -n kafka echo "Waiting for Strimzi operator deployment to be created..." for i in {1..30}; do diff --git a/examples/cloud-deployment/strimzi-1.0.0/strimzi-cluster-operator-1.0.0.yaml b/examples/cloud-deployment/strimzi-1.0.0/strimzi-cluster-operator-1.0.0.yaml new file mode 100644 index 000000000..2affcd27e --- /dev/null +++ b/examples/cloud-deployment/strimzi-1.0.0/strimzi-cluster-operator-1.0.0.yaml @@ -0,0 +1,18469 @@ + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: strimzi-cluster-operator-leader-election + labels: + app: strimzi + namespace: kafka +subjects: + - kind: ServiceAccount + name: strimzi-cluster-operator + namespace: kafka +roleRef: + kind: ClusterRole + name: strimzi-cluster-operator-leader-election + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: strimzi-entity-operator + labels: + app: strimzi +rules: + - apiGroups: + - kafka.strimzi.io + resources: + - kafkatopics + verbs: + - get + - list + - watch + - create + - patch + - update + - delete + - apiGroups: + - kafka.strimzi.io + resources: + - kafkausers + verbs: + - get + - list + - watch + - create + - patch + - update + - apiGroups: + - kafka.strimzi.io + resources: + - kafkatopics/status + - kafkausers/status + verbs: + - get + - patch + - update + - apiGroups: + - kafka.strimzi.io + resources: + - kafkatopics/finalizers + - kafkausers/finalizers + verbs: + - update + - apiGroups: + - '' + resources: + - secrets + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: strimzi-cluster-operator + labels: + app: strimzi + namespace: kafka +subjects: + - kind: ServiceAccount + name: strimzi-cluster-operator + namespace: kafka +roleRef: + kind: ClusterRole + name: strimzi-cluster-operator-namespaced + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: strimzi-kafka-client + labels: + app: strimzi +rules: + - apiGroups: + - '' + resources: + - nodes + verbs: + - get + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkausers.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: KafkaUser + listKind: KafkaUserList + singular: kafkauser + plural: kafkausers + shortNames: + - ku + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Cluster + description: The name of the Kafka cluster this user belongs to + jsonPath: .metadata.labels.strimzi\.io/cluster + type: string + - name: Authentication + description: How the user is authenticated + jsonPath: .spec.authentication.type + type: string + - name: Authorization + description: How the user is authorised + jsonPath: .spec.authorization.type + type: string + - name: Ready + description: The state of the custom resource + jsonPath: '.status.conditions[?(@.type=="Ready")].status' + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + authentication: + type: object + properties: + password: + type: object + properties: + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Selects a key of a Secret in the resource's + namespace. + description: Secret from which the password should be read. + required: + - valueFrom + description: >- + Specify the password for the user. If not set, a new + password is generated by the User Operator. + type: + type: string + enum: + - tls + - tls-external + - scram-sha-512 + description: Authentication type. + required: + - type + description: >- + Authentication mechanism enabled for this Kafka user. The + supported authentication mechanisms are `scram-sha-512`, + `tls`, and `tls-external`. + + + * `scram-sha-512` generates a secret with SASL SCRAM-SHA-512 + credentials. + + * `tls` generates a secret with user certificate for mutual + TLS authentication. + + * `tls-external` does not generate a user certificate. But + prepares the user for using mutual TLS authentication using + a user certificate generated outside the User Operator. + ACLs and quotas set for this user are configured in the `CN=` format. + + Authentication is optional. If authentication is not + configured, no credentials are generated. ACLs and quotas + set for the user are configured in the `` format + suitable for SASL authentication. + authorization: + type: object + properties: + acls: + type: array + items: + type: object + properties: + type: + type: string + enum: + - allow + - deny + description: >- + The type of the rule. ACL rules with type `allow` + are used to allow user to execute the specified + operations. ACL rules with type `deny` are used to + deny user to execute the specified operations. + Default value is `allow`. + resource: + type: object + properties: + name: + type: string + description: >- + Name of resource for which given ACL rule + applies. Can be combined with `patternType` + field to use prefix pattern. + patternType: + type: string + enum: + - literal + - prefix + description: >- + Describes the pattern used in the resource + field. The supported types are `literal` and + `prefix`. With `literal` pattern type, the + resource field will be used as a definition of + a full name. With `prefix` pattern type, the + resource name will be used only as a prefix. + Default value is `literal`. + type: + type: string + enum: + - topic + - group + - cluster + - transactionalId + description: >- + Resource type. The available resource types + are `topic`, `group`, `cluster`, and + `transactionalId`. + required: + - type + description: >- + Indicates the resource for which given ACL rule + applies. + host: + type: string + description: >- + The host from which the action described in the + ACL rule is allowed or denied. If not set, it + defaults to `*`, allowing or denying the action + from any host. + operations: + type: array + items: + type: string + enum: + - Read + - Write + - Create + - Delete + - Alter + - Describe + - ClusterAction + - AlterConfigs + - DescribeConfigs + - IdempotentWrite + - All + description: >- + List of operations to allow or deny. Supported + operations are: Read, Write, Create, Delete, + Alter, Describe, ClusterAction, AlterConfigs, + DescribeConfigs, IdempotentWrite and All. Only + certain operations work with the specified + resource. + required: + - resource + - operations + description: List of ACL rules which should be applied to this user. + type: + type: string + enum: + - simple + description: >- + Authorization type. Currently the only supported type is + `simple`. `simple` authorization type uses the Kafka + Admin API for managing the ACL rules. + required: + - acls + - type + description: Authorization rules for this Kafka user. + quotas: + type: object + properties: + producerByteRate: + type: integer + minimum: 0 + description: >- + A quota on the maximum bytes per-second that each client + group can publish to a broker before the clients in the + group are throttled. Defined on a per-broker basis. + consumerByteRate: + type: integer + minimum: 0 + description: >- + A quota on the maximum bytes per-second that each client + group can fetch from a broker before the clients in the + group are throttled. Defined on a per-broker basis. + requestPercentage: + type: integer + minimum: 0 + description: >- + A quota on the maximum CPU utilization of each client + group as a percentage of network and I/O threads. + controllerMutationRate: + type: number + minimum: 0 + description: >- + A quota on the rate at which mutations are accepted for + the create topics request, the create partitions request + and the delete topics request. The rate is accumulated + by the number of partitions created or deleted. + description: >- + Quotas on requests to control the broker resources used by + clients. Network bandwidth and request rate quotas can be + enforced. For more information, see the Apache Kafka design + documentation about quotas. + template: + type: object + properties: + secret: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: >- + Template for KafkaUser resources. The template allows + users to specify how the `Secret` with password or TLS + certificates is generated. + description: Template to specify how Kafka User `Secrets` are generated. + description: The specification of the user. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + username: + type: string + description: Username. + secret: + type: string + description: The name of `Secret` where the credentials are stored. + description: The status of the Kafka User. + required: + - spec + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: strimzi-cluster-operator-watched + labels: + app: strimzi +rules: + - apiGroups: + - '' + resources: + - pods + verbs: + - watch + - list + - apiGroups: + - kafka.strimzi.io + resources: + - kafkas + - kafkanodepools + - kafkaconnects + - kafkaconnectors + - kafkabridges + - kafkamirrormaker2s + - kafkarebalances + verbs: + - get + - list + - watch + - create + - patch + - update + - apiGroups: + - kafka.strimzi.io + resources: + - kafkas/status + - kafkanodepools/status + - kafkaconnects/status + - kafkaconnectors/status + - kafkabridges/status + - kafkamirrormaker2s/status + - kafkarebalances/status + verbs: + - get + - patch + - update + - apiGroups: + - kafka.strimzi.io + resources: + - kafkas/finalizers + - kafkanodepools/finalizers + - kafkaconnects/finalizers + - kafkaconnectors/finalizers + - kafkabridges/finalizers + - kafkamirrormaker2s/finalizers + - kafkarebalances/finalizers + verbs: + - update + - apiGroups: + - core.strimzi.io + resources: + - strimzipodsets + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - core.strimzi.io + resources: + - strimzipodsets/status + verbs: + - get + - patch + - update + - apiGroups: + - core.strimzi.io + resources: + - strimzipodsets/finalizers + verbs: + - update + - apiGroups: + - kafka.strimzi.io + resources: + - kafkarebalances + verbs: + - delete + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkaconnectors.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: KafkaConnector + listKind: KafkaConnectorList + singular: kafkaconnector + plural: kafkaconnectors + shortNames: + - kctr + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + scale: + specReplicasPath: .spec.tasksMax + statusReplicasPath: .status.tasksMax + additionalPrinterColumns: + - name: Cluster + description: The name of the Kafka Connect cluster this connector belongs to + jsonPath: .metadata.labels.strimzi\.io/cluster + type: string + - name: Connector class + description: The class used by this connector + jsonPath: .spec.class + type: string + - name: Max Tasks + description: Maximum number of tasks + jsonPath: .spec.tasksMax + type: integer + - name: Ready + description: The state of the custom resource + jsonPath: '.status.conditions[?(@.type=="Ready")].status' + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + class: + type: string + description: The Class for the Kafka Connector. + tasksMax: + type: integer + minimum: 1 + description: The maximum number of tasks for the Kafka Connector. + autoRestart: + type: object + properties: + enabled: + type: boolean + description: >- + Whether automatic restart for failed connectors and + tasks should be enabled or disabled. + maxRestarts: + type: integer + description: >- + The maximum number of connector restarts that the + operator will try. If the connector remains in a failed + state after reaching this limit, it must be restarted + manually by the user. Defaults to an unlimited number of + restarts. + description: Automatic restart of connector and tasks configuration. + version: + type: string + description: >- + Desired version or version range to respect when starting + the Kafka Connector. This is only supported when using Kafka + Connect version 4.1.0 and higher. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The Kafka Connector configuration. The following properties + cannot be set: name, connector.class, tasks.max, + connector.plugin.version. + state: + type: string + enum: + - paused + - stopped + - running + description: The state the connector should be in. Defaults to running. + listOffsets: + type: object + properties: + toConfigMap: + type: object + properties: + name: + type: string + description: >- + Reference to the ConfigMap where the list of offsets + will be written to. + required: + - toConfigMap + description: Configuration for listing offsets. + alterOffsets: + type: object + properties: + fromConfigMap: + type: object + properties: + name: + type: string + description: >- + Reference to the ConfigMap where the new offsets are + stored. + required: + - fromConfigMap + description: Configuration for altering offsets. + description: The specification of the Kafka Connector. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + autoRestart: + type: object + properties: + count: + type: integer + description: The number of times the connector or task is restarted. + connectorName: + type: string + description: The name of the connector being restarted. + lastRestartTimestamp: + type: string + description: >- + The last time the automatic restart was attempted. The + required format is 'yyyy-MM-ddTHH:mm:ssZ' in the UTC + time zone. + description: The auto restart status. + connectorStatus: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The connector status, as reported by the Kafka Connect REST + API. + tasksMax: + type: integer + description: The maximum number of tasks for the Kafka Connector. + topics: + type: array + items: + type: string + description: The list of topics used by the Kafka Connector. + description: The status of the Kafka Connector. + required: + - spec + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: strimzi-cluster-operator-entity-operator-delegation + labels: + app: strimzi + namespace: kafka +subjects: + - kind: ServiceAccount + name: strimzi-cluster-operator + namespace: kafka +roleRef: + kind: ClusterRole + name: strimzi-entity-operator + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkarebalances.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: KafkaRebalance + listKind: KafkaRebalanceList + singular: kafkarebalance + plural: kafkarebalances + shortNames: + - kr + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Cluster + description: The name of the Kafka cluster this resource rebalances + jsonPath: .metadata.labels.strimzi\.io/cluster + type: string + - name: Template + description: If this rebalance resource is a template + jsonPath: .metadata.annotations.strimzi\.io/rebalance-template + type: string + - name: Status + description: Status of the current rebalancing operation + jsonPath: '.status.conditions[*].type' + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + mode: + type: string + enum: + - full + - add-brokers + - remove-brokers + - remove-disks + description: >- + Mode to run the rebalancing. The supported modes are `full`, + `add-brokers`, `remove-brokers`. + + If not specified, the `full` mode is used by default. + + + * `full` mode runs the rebalancing across all the brokers in + the cluster. + + * `add-brokers` mode can be used after scaling up the + cluster to move some replicas to the newly added brokers. + + * `remove-brokers` mode can be used before scaling down the + cluster to move replicas out of the brokers to be removed. + + * `remove-disks` mode can be used to move data across the + volumes within the same broker + + . + brokers: + type: array + items: + type: integer + description: >- + The list of newly added brokers in case of scaling up or the + ones to be removed in case of scaling down to use for + rebalancing. This list can be used only with rebalancing + mode `add-brokers` and `removed-brokers`. It is ignored with + `full` mode. + goals: + type: array + items: + type: string + description: >- + A list of goals, ordered by decreasing priority, to use for + generating and executing the rebalance proposal. The + supported goals are available at + https://github.com/linkedin/cruise-control#goals. If an + empty goals list is provided, the goals declared in the + default.goals Cruise Control configuration parameter are + used. + skipHardGoalCheck: + type: boolean + description: >- + Whether to allow the hard goals specified in the Kafka CR to + be skipped in optimization proposal generation. This can be + useful when some of those hard goals are preventing a + balance solution being found. Default is false. + rebalanceDisk: + type: boolean + description: >- + Enables intra-broker disk balancing, which balances disk + space utilization between disks on the same broker. Only + applies to Kafka deployments that use JBOD storage with + multiple disks. When enabled, inter-broker balancing is + disabled. Default is false. + excludedTopics: + type: string + description: >- + A regular expression where any matching topics will be + excluded from the calculation of optimization proposals. + This expression will be parsed by the + java.util.regex.Pattern class; for more information on the + supported format consult the documentation for that class. + concurrentPartitionMovementsPerBroker: + type: integer + minimum: 0 + description: >- + The upper bound of ongoing partition replica movements going + into/out of each broker. Default is 5. + concurrentIntraBrokerPartitionMovements: + type: integer + minimum: 0 + description: >- + The upper bound of ongoing partition replica movements + between disks within each broker. Default is 2. + concurrentLeaderMovements: + type: integer + minimum: 0 + description: >- + The upper bound of ongoing partition leadership movements. + Default is 1000. + replicationThrottle: + type: integer + minimum: 0 + description: >- + The upper bound, in bytes per second, on the bandwidth used + to move replicas. There is no limit by default. + replicaMovementStrategies: + type: array + items: + type: string + description: >- + A list of strategy class names used to determine the + execution order for the replica movements in the generated + optimization proposal. By default + BaseReplicaMovementStrategy is used, which will execute the + replica movements in the order that they were generated. + moveReplicasOffVolumes: + type: array + minItems: 1 + items: + type: object + properties: + brokerId: + type: integer + description: >- + ID of the broker that contains the disk from which you + want to move the partition replicas. + volumeIds: + type: array + minItems: 1 + items: + type: integer + description: >- + IDs of the disks from which the partition replicas + need to be moved. + description: >- + List of brokers and their corresponding volumes from which + replicas need to be moved. + description: The specification of the Kafka rebalance. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + sessionId: + type: string + description: >- + The session identifier for requests to Cruise Control + pertaining to this KafkaRebalance resource. This is used by + the Kafka Rebalance operator to track the status of ongoing + rebalancing operations. + progress: + type: object + properties: + rebalanceProgressConfigMap: + type: string + description: >- + The name of the `ConfigMap` containing information + related to the progress of a partition rebalance. + description: A reference to Config Map with the progress information. + optimizationResult: + x-kubernetes-preserve-unknown-fields: true + type: object + description: A JSON object describing the optimization result. + description: The status of the Kafka rebalance. + required: + - spec + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: strimzi-cluster-operator-kafka-client-delegation + labels: + app: strimzi +subjects: + - kind: ServiceAccount + name: strimzi-cluster-operator + namespace: kafka +roleRef: + kind: ClusterRole + name: strimzi-kafka-client + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: strimzi-cluster-operator-watched + labels: + app: strimzi + namespace: kafka +subjects: + - kind: ServiceAccount + name: strimzi-cluster-operator + namespace: kafka +roleRef: + kind: ClusterRole + name: strimzi-cluster-operator-watched + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: strimzi-cluster-operator-namespaced + labels: + app: strimzi +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - '' + resources: + - pods + - serviceaccounts + - configmaps + - services + - endpoints + - secrets + - persistentvolumeclaims + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - '' + resources: + - pods/resize + verbs: + - patch + - update + - apiGroups: + - apps + resources: + - deployments + - replicasets + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - apps + resources: + - deployments/scale + verbs: + - get + - patch + - update + - apiGroups: + - events.k8s.io + resources: + - events + verbs: + - create + - apiGroups: + - build.openshift.io + resources: + - buildconfigs + - buildconfigs/instantiate + - builds + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - networking.k8s.io + resources: + - networkpolicies + - ingresses + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - route.openshift.io + resources: + - routes + - routes/custom-host + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - image.openshift.io + resources: + - imagestreams + verbs: + - get + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: strimzi-cluster-operator-leader-election + labels: + app: strimzi +rules: + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + - strimzi-cluster-operator + verbs: + - get + - list + - watch + - delete + - patch + - update + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: strimzi-cluster-operator + labels: + app: strimzi + namespace: kafka +spec: + replicas: 1 + selector: + matchLabels: + name: strimzi-cluster-operator + strimzi.io/kind: cluster-operator + template: + metadata: + labels: + name: strimzi-cluster-operator + strimzi.io/kind: cluster-operator + spec: + serviceAccountName: strimzi-cluster-operator + volumes: + - name: strimzi-tmp + emptyDir: + medium: Memory + sizeLimit: 1Mi + - name: co-config-volume + configMap: + name: strimzi-cluster-operator + containers: + - name: strimzi-cluster-operator + image: 'quay.io/strimzi/operator:1.0.0' + ports: + - containerPort: 8080 + name: http + args: + - /opt/strimzi/bin/cluster_operator_run.sh + volumeMounts: + - name: strimzi-tmp + mountPath: /tmp + - name: co-config-volume + mountPath: /opt/strimzi/custom-config/ + env: + - name: STRIMZI_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: STRIMZI_FULL_RECONCILIATION_INTERVAL_MS + value: '120000' + - name: STRIMZI_OPERATION_TIMEOUT_MS + value: '300000' + - name: STRIMZI_DEFAULT_KAFKA_EXPORTER_IMAGE + value: 'quay.io/strimzi/kafka:1.0.0-kafka-4.2.0' + - name: STRIMZI_DEFAULT_CRUISE_CONTROL_IMAGE + value: 'quay.io/strimzi/kafka:1.0.0-kafka-4.2.0' + - name: STRIMZI_KAFKA_IMAGES + value: | + 4.1.0=quay.io/strimzi/kafka:1.0.0-kafka-4.1.0 + 4.1.1=quay.io/strimzi/kafka:1.0.0-kafka-4.1.1 + 4.1.2=quay.io/strimzi/kafka:1.0.0-kafka-4.1.2 + 4.2.0=quay.io/strimzi/kafka:1.0.0-kafka-4.2.0 + - name: STRIMZI_KAFKA_CONNECT_IMAGES + value: | + 4.1.0=quay.io/strimzi/kafka:1.0.0-kafka-4.1.0 + 4.1.1=quay.io/strimzi/kafka:1.0.0-kafka-4.1.1 + 4.1.2=quay.io/strimzi/kafka:1.0.0-kafka-4.1.2 + 4.2.0=quay.io/strimzi/kafka:1.0.0-kafka-4.2.0 + - name: STRIMZI_KAFKA_MIRROR_MAKER_2_IMAGES + value: | + 4.1.0=quay.io/strimzi/kafka:1.0.0-kafka-4.1.0 + 4.1.1=quay.io/strimzi/kafka:1.0.0-kafka-4.1.1 + 4.1.2=quay.io/strimzi/kafka:1.0.0-kafka-4.1.2 + 4.2.0=quay.io/strimzi/kafka:1.0.0-kafka-4.2.0 + - name: STRIMZI_DEFAULT_TOPIC_OPERATOR_IMAGE + value: 'quay.io/strimzi/operator:1.0.0' + - name: STRIMZI_DEFAULT_USER_OPERATOR_IMAGE + value: 'quay.io/strimzi/operator:1.0.0' + - name: STRIMZI_DEFAULT_KAFKA_INIT_IMAGE + value: 'quay.io/strimzi/operator:1.0.0' + - name: STRIMZI_DEFAULT_KAFKA_BRIDGE_IMAGE + value: 'quay.io/strimzi/kafka-bridge:1.0.0' + - name: STRIMZI_DEFAULT_KANIKO_EXECUTOR_IMAGE + value: 'quay.io/strimzi/kaniko-executor:1.0.0' + - name: STRIMZI_DEFAULT_BUILDAH_IMAGE + value: 'quay.io/strimzi/buildah:1.0.0' + - name: STRIMZI_DEFAULT_MAVEN_BUILDER + value: 'quay.io/strimzi/maven-builder:1.0.0' + - name: STRIMZI_OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: STRIMZI_FEATURE_GATES + value: '' + - name: STRIMZI_LEADER_ELECTION_ENABLED + value: 'true' + - name: STRIMZI_LEADER_ELECTION_LEASE_NAME + value: strimzi-cluster-operator + - name: STRIMZI_LEADER_ELECTION_LEASE_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: STRIMZI_LEADER_ELECTION_IDENTITY + valueFrom: + fieldRef: + fieldPath: metadata.name + livenessProbe: + httpGet: + path: /healthy + port: http + initialDelaySeconds: 10 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /ready + port: http + initialDelaySeconds: 10 + periodSeconds: 30 + resources: + limits: + cpu: 1000m + memory: 384Mi + requests: + cpu: 200m + memory: 384Mi + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkabridges.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: KafkaBridge + listKind: KafkaBridgeList + singular: kafkabridge + plural: kafkabridges + shortNames: + - kb + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + scale: + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas + labelSelectorPath: .status.labelSelector + additionalPrinterColumns: + - name: Desired replicas + description: The desired number of Kafka Bridge replicas + jsonPath: .spec.replicas + type: integer + - name: Bootstrap Servers + description: The boostrap servers + jsonPath: .spec.bootstrapServers + type: string + priority: 1 + - name: Ready + description: The state of the custom resource + jsonPath: '.status.conditions[?(@.type=="Ready")].status' + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + replicas: + type: integer + minimum: 0 + description: >- + The number of pods in the `Deployment`. Required in the `v1` + version of the Strimzi API. Defaults to `1` in the `v1beta2` + version of the Strimzi API. + image: + type: string + description: >- + The container image used for HTTP Bridge pods. If no image + name is explicitly specified, the image name corresponds to + the image specified in the Cluster Operator configuration. + If an image name is not defined in the Cluster Operator + configuration, a default value is used. + bootstrapServers: + type: string + description: >- + A list of host:port pairs for establishing the initial + connection to the Kafka cluster. + tls: + type: object + properties: + trustedCertificates: + type: array + items: + type: object + properties: + secretName: + type: string + description: The name of the Secret containing the certificate. + certificate: + type: string + description: The name of the file certificate in the secret. + pattern: + type: string + description: >- + Pattern for the certificate files in the secret. + Use the + link:https://en.wikipedia.org/wiki/Glob_(programming)[_glob + syntax_] for the pattern. All files in the secret + that match the pattern are used. + oneOf: + - properties: + certificate: {} + required: + - certificate + - properties: + pattern: {} + required: + - pattern + required: + - secretName + description: Trusted certificates for TLS connection. + description: TLS configuration for connecting HTTP Bridge to the cluster. + authentication: + type: object + properties: + certificateAndKey: + type: object + properties: + secretName: + type: string + description: The name of the Secret containing the certificate. + certificate: + type: string + description: The name of the file certificate in the Secret. + key: + type: string + description: >- + The name of the private key in the secret. The + private key must be in unencrypted PKCS #8 format. + For more information, see RFC 5208: + https://datatracker.ietf.org/doc/html/rfc5208. + required: + - secretName + - certificate + - key + description: >- + Reference to the `Secret` which holds the certificate + and private key pair. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + Configuration for the custom authentication mechanism. + Only properties with the `sasl.` and `ssl.keystore.` + prefixes are allowed. Specify other options in the + regular configuration section of the custom resource. + passwordSecret: + type: object + properties: + secretName: + type: string + description: The name of the Secret containing the password. + password: + type: string + description: >- + The name of the key in the Secret under which the + password is stored. + required: + - secretName + - password + description: Reference to the `Secret` which holds the password. + sasl: + type: boolean + description: Enable or disable SASL on this authentication mechanism. + type: + type: string + enum: + - tls + - scram-sha-256 + - scram-sha-512 + - plain + - custom + description: >- + Specifies the authentication type. Supported types are + `tls`, `scram-sha-256`, `scram-sha-512`, `plain`, + 'oauth', and `custom`. `tls` uses TLS client + authentication and is supported only over TLS + connections. `scram-sha-256` and `scram-sha-512` use + SASL SCRAM-SHA-256 and SASL SCRAM-SHA-512 + authentication, respectively. `plain` uses SASL PLAIN + authentication. `oauth` uses SASL OAUTHBEARER + authentication. `custom` allows you to configure a + custom authentication mechanism. As of Strimzi 0.49.0, + `oauth` type is deprecated and will be removed in the + `v1` API version. Please use `custom` type instead. + username: + type: string + description: Username used for the authentication. + required: + - type + description: Authentication configuration for connecting to the cluster. + http: + type: object + properties: + port: + type: integer + minimum: 1023 + description: Port the server listens on. + tls: + type: object + properties: + certificateAndKey: + type: object + properties: + secretName: + type: string + description: >- + The name of the Secret containing the + certificate. + certificate: + type: string + description: The name of the file certificate in the Secret. + key: + type: string + description: >- + The name of the private key in the secret. The + private key must be in unencrypted PKCS #8 + format. For more information, see RFC 5208: + https://datatracker.ietf.org/doc/html/rfc5208. + required: + - secretName + - certificate + - key + description: >- + Reference to the `Secret` which holds the + certificate and private key pair. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + Additional configuration for the HTTP server TLS. + Properties with the following prefixes cannot be + set: ssl. (with the exception of: + ssl.enabled.cipher.suites, ssl.enabled.protocols). + required: + - certificateAndKey + description: >- + TLS configuration for clients connections to the HTTP + Bridge. + cors: + type: object + properties: + allowedOrigins: + type: array + items: + type: string + description: >- + List of allowed origins. Java regular expressions + can be used. + allowedMethods: + type: array + items: + type: string + description: List of allowed HTTP methods. + required: + - allowedOrigins + - allowedMethods + description: CORS configuration for the HTTP Bridge. + description: The HTTP related configuration. + adminClient: + type: object + properties: + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The Kafka AdminClient configuration used for AdminClient + instances created by the bridge. + description: Kafka AdminClient related configuration. + consumer: + type: object + properties: + enabled: + type: boolean + description: >- + Whether the HTTP consumer should be enabled or disabled. + The default is enabled (`true`). + timeoutSeconds: + type: integer + description: >- + The timeout in seconds for deleting inactive consumers, + default is -1 (disabled). + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The Kafka consumer configuration used for consumer + instances created by the bridge. Properties with the + following prefixes cannot be set: ssl., + bootstrap.servers, group.id, sasl., security. (with the + exception of: ssl.endpoint.identification.algorithm, + ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols). + description: Kafka consumer related configuration. + producer: + type: object + properties: + enabled: + type: boolean + description: >- + Whether the HTTP producer should be enabled or disabled. + The default is enabled (`true`). + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The Kafka producer configuration used for producer + instances created by the bridge. Properties with the + following prefixes cannot be set: ssl., + bootstrap.servers, sasl., security. (with the exception + of: ssl.endpoint.identification.algorithm, + ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols). + description: Kafka producer related configuration. + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: CPU and memory resources to reserve. + jvmOptions: + type: object + properties: + '-XX': + additionalProperties: + type: string + type: object + description: A map of -XX options to the JVM. + '-Xmx': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xmx option to to the JVM.' + '-Xms': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xms option to to the JVM.' + gcLoggingEnabled: + type: boolean + description: >- + Specifies whether the Garbage Collection logging is + enabled. The default is false. + javaSystemProperties: + type: array + items: + type: object + properties: + name: + type: string + description: The system property name. + value: + type: string + description: The system property value. + description: >- + A map of additional system properties which will be + passed using the `-D` option to the JVM. + description: JVM Options for pods. + logging: + type: object + properties: + loggers: + additionalProperties: + type: string + type: object + description: A Map from logger name to logger level. + type: + type: string + enum: + - inline + - external + description: 'Logging type, must be either ''inline'' or ''external''.' + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing the + configuration. + description: >- + `ConfigMap` entry where the logging configuration is + stored. + required: + - type + description: Logging configuration for HTTP Bridge. + clientRackInitImage: + type: string + description: >- + The image of the init container used for initializing the + `client.rack`. + rack: + type: object + properties: + envVarName: + type: string + description: >- + The name of the environment variable that defines the + rack ID. Its value sets the `broker.rack` configuration + for Kafka brokers and the `client.rack` configuration + for Kafka Connect or MirrorMaker 2. + topologyKey: + type: string + example: topology.kubernetes.io/zone + description: >- + A key that matches labels assigned to the Kubernetes + cluster nodes. The value of the label is used to set a + broker's `broker.rack` config, and the `client.rack` + config for Kafka Connect or MirrorMaker 2. + type: + type: string + enum: + - topology-label + - environment-variable + description: >- + Specifies the rack awareness type. Supported types are + `topology-label` and `environment-variable`. + `topology-label` uses a Kubernetes worker node label to + set the `broker.rack` configuration for Kafka brokers + and the `client.rack` configuration for Kafka Connect + and MirrorMaker 2. `environment-variable` uses an + environment variable to set the `broker.rack` + configuration for Kafka brokers and the `client.rack` + configuration for Kafka Connect and MirrorMaker 2. When + not specified, `topology-label` type is used by default. + description: >- + Configuration of the node label which will be used as the + client.rack consumer configuration. + x-kubernetes-validations: + - rule: >- + (has(self.type) && self.type != "topology-label") || + self.topologyKey != "" + message: topologyKey property is required + - rule: >- + has(self.type) == false || self.type != + "environment-variable" || self.envVarName != "" + message: envVarName property is required + metricsConfig: + type: object + properties: + type: + type: string + enum: + - jmxPrometheusExporter + - strimziMetricsReporter + description: >- + Metrics type. The supported types are + `jmxPrometheusExporter` and `strimziMetricsReporter`. + Type `jmxPrometheusExporter` uses the Prometheus JMX + Exporter to expose Kafka JMX metrics in Prometheus + format through an HTTP endpoint. Type + `strimziMetricsReporter` uses the Strimzi Metrics + Reporter to directly expose Kafka metrics in Prometheus + format through an HTTP endpoint. + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing the + configuration. + description: >- + ConfigMap entry where the Prometheus JMX Exporter + configuration is stored. + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: >- + A list of regex patterns to filter the metrics to + collect. Should contain at least one element. + description: Configuration values for the Strimzi Metrics Reporter. + required: + - type + description: Metrics configuration. + x-kubernetes-validations: + - rule: >- + self.type != 'jmxPrometheusExporter' || + has(self.valueFrom) + message: valueFrom property is required + livenessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default to + 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default to + 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to + 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. + Minimum value is 1. + description: Pod liveness checking. + readinessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default to + 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default to + 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to + 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. + Minimum value is 1. + description: Pod readiness checking. + template: + type: object + properties: + deployment: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + deploymentStrategy: + type: string + enum: + - RollingUpdate + - Recreate + description: >- + Pod replacement strategy for deployment + configuration changes. Valid values are + `RollingUpdate` and `Recreate`. Defaults to + `RollingUpdate`. + description: Template for HTTP Bridge `Deployment`. + pod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same namespace + to use for pulling any of the images used by this + Pod. When the `STRIMZI_IMAGE_PULL_SECRETS` + environment variable in Cluster Operator and the + `imagePullSecrets` option are specified, only the + `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and common + container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds after + the processes running in the pod are sent a + termination signal, and the time when the processes + are forcibly halted with a kill signal. Set this + value to longer than the expected cleanup time for + your process. Value must be a non-negative integer. + A zero value indicates delete immediately. You might + need to increase the grace period for very large + Kafka clusters, so that the Kafka brokers have + enough time to transfer their work to another broker + before they are terminated. Defaults to 30 seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler will + be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an optional + list of hosts and IPs that will be injected into the + Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be merged + to the generated DNS configuration based on the + DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services should + be injected into Pod's environment variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated for + the temporary `EmptyDir` volume `/tmp`. Specify the + allocation in memory units, for example, `100Mi` for + 100 mebibytes. Default value is `5Mi`. The `/tmp` + volume is backed by pod memory, not disk storage, so + avoid setting a high value as it consumes pod memory + resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage required + for this EmptyDir volume (for example + 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to populate + the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to populate + the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: Additional volumes that can be mounted to the pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults to + `true`. When `true` or not set, the pod runs in the + host user namespace. This is required when the pod + needs features available only in the host namespace, + such as loading kernel modules with + `CAP_SYS_MODULE`.When set to `false`, the pod runs + in a new user namespace. Setting `false` helps + mitigate container breakout vulnerabilities and + allows containers to run as `root` without granting + `root` privileges on the host. This property is + alpha-level in Kubernetes and is supported only by + Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: Template for HTTP Bridge `Pods`. + apiService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the service. + Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`. + `SingleStack` is for a single IP family. + `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP family + on single-stack clusters. `RequireDualStack` fails + unless there are two IP families on dual-stack + configured clusters. If unspecified, Kubernetes will + choose the default value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the default + value based on the `ipFamilyPolicy` setting. + description: Template for HTTP Bridge API `Service`. + podDisruptionBudget: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + maxUnavailable: + type: integer + minimum: 0 + description: >- + Maximum number of unavailable pods to allow + automatic Pod eviction. A Pod eviction is allowed + when the `maxUnavailable` number of pods or fewer + are unavailable after the eviction. Setting this + value to 0 prevents all voluntary evictions, so the + pods must be evicted manually. Defaults to 1. + description: Template for HTTP Bridge `PodDisruptionBudget`. + bridgeContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: Template for the HTTP Bridge container. + clusterRoleBinding: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for the HTTP Bridge ClusterRoleBinding. + serviceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for the HTTP Bridge service account. + initContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: Template for the HTTP Bridge init container. + description: >- + Template for HTTP Bridge resources. The template allows + users to specify how a `Deployment` and `Pod` is generated. + tracing: + type: object + properties: + type: + type: string + enum: + - opentelemetry + description: >- + Type of the tracing used. Currently the only supported + type is `opentelemetry` for OpenTelemetry tracing. As of + Strimzi 0.37.0, `jaeger` type is not supported anymore + and this option is ignored. + required: + - type + description: The configuration of tracing in HTTP Bridge. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + Additional configuration for the HTTP bridge. The following + prefixes cannot be set: kafka., http., bridge.metrics. The + following options cannot be set: bridge.id, bridge.tracing, + bridge.metrics. + required: + - replicas + - bootstrapServers + description: The specification of the HTTP Bridge. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + url: + type: string + description: >- + The URL at which external client applications can access the + HTTP Bridge. + replicas: + type: integer + description: >- + The current number of pods being used to provide this + resource. + labelSelector: + type: string + description: Label selector for pods providing this resource. + description: The status of the HTTP Bridge. + required: + - spec + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: strimzi-cluster-operator-kafka-broker-delegation + labels: + app: strimzi +subjects: + - kind: ServiceAccount + name: strimzi-cluster-operator + namespace: kafka +roleRef: + kind: ClusterRole + name: strimzi-kafka-broker + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: strimzi-kafka-broker + labels: + app: strimzi +rules: + - apiGroups: + - '' + resources: + - nodes + verbs: + - get + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: strimzipodsets.core.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: core.strimzi.io + names: + kind: StrimziPodSet + listKind: StrimziPodSetList + singular: strimzipodset + plural: strimzipodsets + shortNames: + - sps + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Pods + description: Number of pods managed by the StrimziPodSet + jsonPath: .status.pods + type: integer + - name: Ready Pods + description: Number of ready pods managed by the StrimziPodSet + jsonPath: .status.readyPods + type: integer + - name: Current Pods + description: Number of up-to-date pods managed by the StrimziPodSet + jsonPath: .status.currentPods + type: integer + - name: Age + description: Age of the StrimziPodSet + jsonPath: .metadata.creationTimestamp + type: date + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + selector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + description: >- + Selector is a label query which matches all the pods managed + by this `StrimziPodSet`. Only `matchLabels` is supported. If + `matchExpressions` is set, it will be ignored. + pods: + type: array + items: + x-kubernetes-preserve-unknown-fields: true + type: object + description: The Pods managed by this StrimziPodSet. + required: + - selector + - pods + description: The specification of the StrimziPodSet. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + pods: + type: integer + description: Number of pods managed by this `StrimziPodSet` resource. + readyPods: + type: integer + description: >- + Number of pods managed by this `StrimziPodSet` resource that + are ready. + currentPods: + type: integer + description: >- + Number of pods managed by this `StrimziPodSet` resource that + have the current revision. + description: The status of the StrimziPodSet. + required: + - spec + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: strimzi-cluster-operator + labels: + app: strimzi +subjects: + - kind: ServiceAccount + name: strimzi-cluster-operator + namespace: kafka +roleRef: + kind: ClusterRole + name: strimzi-cluster-operator-global + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkas.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: Kafka + listKind: KafkaList + singular: kafka + plural: kafkas + shortNames: + - k + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Ready + description: The state of the custom resource + jsonPath: '.status.conditions[?(@.type=="Ready")].status' + type: string + - name: Warnings + description: Warnings related to the custom resource + jsonPath: '.status.conditions[?(@.type=="Warning")].status' + type: string + - name: Kafka version + description: The Kafka version used by the cluster + jsonPath: .status.kafkaVersion + type: string + - name: Metadata version + description: The Kafka metadata version used by the cluster + jsonPath: .status.kafkaMetadataVersion + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + kafka: + type: object + properties: + version: + type: string + description: >- + The Kafka broker version. Defaults to the latest + version. Consult the user documentation to understand + the process required to upgrade or downgrade the + version. + metadataVersion: + type: string + description: >- + The KRaft metadata version used by the Kafka cluster. + This property is ignored when running in ZooKeeper mode. + If the property is not set, it defaults to the metadata + version that corresponds to the `version` property. + image: + type: string + description: >- + The container image used for Kafka pods. If the property + is not set, the default Kafka image version is + determined based on the `version` configuration. The + image names are specifically mapped to corresponding + versions in the Cluster Operator configuration. Changing + the Kafka image version does not automatically update + the image versions for other components, such as Kafka + Exporter. + listeners: + type: array + minItems: 1 + items: + type: object + properties: + name: + type: string + pattern: '^[a-z0-9]{1,11}$' + description: >- + Name of the listener. The name will be used to + identify the listener and the related Kubernetes + objects. The name has to be unique within given a + Kafka cluster. The name can consist of lowercase + characters and numbers and be up to 11 characters + long. + port: + type: integer + minimum: 9092 + description: >- + Port number used by the listener inside Kafka. The + port number has to be unique within a given Kafka + cluster. Allowed port numbers are 9092 and higher + with the exception of ports 9404 and 9999, which + are already used for Prometheus and JMX. Depending + on the listener type, the port number might not be + the same as the port number that connects Kafka + clients. + type: + type: string + enum: + - internal + - route + - loadbalancer + - nodeport + - ingress + - cluster-ip + description: > + Type of the listener. The supported types are as + follows: + + + * `internal` type exposes Kafka internally only + within the Kubernetes cluster. + + * `route` type uses OpenShift Routes to expose + Kafka. + + * `loadbalancer` type uses LoadBalancer type + services to expose Kafka. + + * `nodeport` type uses NodePort type services to + expose Kafka. + + * `ingress` (deprecated) type uses Kubernetes + Nginx Ingress to expose Kafka with TLS + passthrough. + + * `cluster-ip` type uses a per-broker `ClusterIP` + service. + tls: + type: boolean + description: >- + Enables TLS encryption on the listener. This is a + required property. For `route` and `ingress` type + listeners, TLS encryption must be always enabled. + authentication: + type: object + properties: + listenerConfig: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + Configuration to be used for a specific + listener. All values are prefixed with + `listener.name.`. + sasl: + type: boolean + description: Enable or disable SASL on this listener. + type: + type: string + enum: + - tls + - scram-sha-512 + - custom + description: >- + Authentication type. `oauth` type uses SASL + OAUTHBEARER Authentication. `scram-sha-512` + type uses SASL SCRAM-SHA-512 Authentication. + `tls` type uses TLS Client Authentication. + `tls` type is supported only on TLS listeners. + `custom` type allows for any authentication + type to be used. As of Strimzi 0.49.0, `oauth` + type is deprecated and will be removed in the + `v1` API version. Please use `custom` type + instead. + required: + - type + description: Authentication configuration for this listener. + configuration: + type: object + properties: + brokerCertChainAndKey: + type: object + properties: + secretName: + type: string + description: >- + The name of the Secret containing the + certificate. + certificate: + type: string + description: >- + The name of the file certificate in the + Secret. + key: + type: string + description: >- + The name of the private key in the secret. + The private key must be in unencrypted + PKCS #8 format. For more information, see + RFC 5208: + https://datatracker.ietf.org/doc/html/rfc5208. + required: + - secretName + - certificate + - key + description: >- + Reference to the `Secret` which holds the + certificate and private key pair which will be + used for this listener. The certificate can + optionally contain the whole chain. This field + can be used only with listeners with enabled + TLS encryption. + class: + type: string + description: >- + Configures a specific class for `Ingress` and + `LoadBalancer` that defines which controller + is used. If not specified, the default + controller is used. + + + * For an `ingress` listener, the operator uses + this property to set the `ingressClassName` + property in the `Ingress` resources. + + * For a `loadbalancer` listener, the operator + uses this property to set the + `loadBalancerClass` property in the `Service` + resources. + + + For `ingress` and `loadbalancer` listeners + only. + externalTrafficPolicy: + type: string + enum: + - Local + - Cluster + description: >- + Specifies whether the service routes external + traffic to cluster-wide or node-local + endpoints: + + + * `Cluster` may cause a second hop to another + node and obscures the client source IP. + + * `Local` avoids a second hop for + `LoadBalancer` and `Nodeport` type services + and preserves the client source IP (when + supported by the infrastructure). + + + If unspecified, Kubernetes uses `Cluster` as + the default. For `loadbalancer` or `nodeport` + listeners only. + loadBalancerSourceRanges: + type: array + items: + type: string + description: >- + A list of CIDR ranges (for example + `10.0.0.0/8` or `130.211.204.1/32`) from which + clients can connect to loadbalancer listeners. + If supported by the platform, traffic through + the loadbalancer is restricted to the + specified CIDR ranges. This field is + applicable only for loadbalancer type services + and is ignored if the cloud provider does not + support the feature. For `loadbalancer` + listeners only. + bootstrap: + type: object + properties: + alternativeNames: + type: array + items: + type: string + description: >- + Additional alternative names for the + bootstrap service. The alternative names + will be added to the list of subject + alternative names of the TLS certificates. + host: + type: string + description: >- + Specifies the hostname used for the + bootstrap resource. For `route` (optional) + or `ingress` (required) listeners only. + Ensure the hostname resolves to the + Ingress endpoints; no validation is + performed by Strimzi. + nodePort: + type: integer + description: >- + Node port for the bootstrap service. For + `nodeport` listeners only. + loadBalancerIP: + type: string + description: >- + The loadbalancer is requested with the IP + address specified in this property. This + feature depends on whether the underlying + cloud provider supports specifying the + `loadBalancerIP` when a load balancer is + created. This property is ignored if the + cloud provider does not support the + feature. For `loadbalancer` listeners + only. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to `Ingress`, `Route`, + or `Service` resources. You can use this + property to configure DNS providers such + as External DNS. For `loadbalancer`, + `nodeport`, `route`, or `ingress` + listeners only. + labels: + additionalProperties: + type: string + type: object + description: >- + Labels added to `Ingress`, `Route`, or + `Service` resources. For `loadbalancer`, + `nodeport`, `route`, or `ingress` + listeners only. + externalIPs: + type: array + items: + type: string + description: >- + External IPs associated to the nodeport + service. These IPs are used by clients + external to the Kubernetes cluster to + access the Kafka brokers. This property is + helpful when `nodeport` without + `externalIP` is not sufficient. For + example on bare-metal Kubernetes clusters + that do not support Loadbalancer service + types. For `nodeport` listeners only. + description: Bootstrap configuration. + brokers: + type: array + items: + type: object + properties: + broker: + type: integer + description: >- + ID of the kafka broker (broker + identifier). Broker IDs start from 0 and + correspond to the number of broker + replicas. + advertisedHost: + type: string + description: >- + The host name used in the brokers' + `advertised.listeners`. + advertisedPort: + type: integer + description: >- + The port number used in the brokers' + `advertised.listeners`. + host: + type: string + description: >- + The broker host. This field will be used + in the Ingress resource or in the Route + resource to specify the desired + hostname. This field can be used only + with `route` (optional) or `ingress` + (required) type listeners. + nodePort: + type: integer + description: >- + Node port for the per-broker service. + This field can be used only with + `nodeport` type listener. + loadBalancerIP: + type: string + description: >- + The loadbalancer is requested with the + IP address specified in this field. This + feature depends on whether the + underlying cloud provider supports + specifying the `loadBalancerIP` when a + load balancer is created. This field is + ignored if the cloud provider does not + support the feature.This field can be + used only with `loadbalancer` type + listener. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations that will be added to the + `Ingress` or `Service` resource. You can + use this field to configure DNS + providers such as External DNS. This + field can be used only with + `loadbalancer`, `nodeport`, or `ingress` + type listeners. + labels: + additionalProperties: + type: string + type: object + description: >- + Labels that will be added to the + `Ingress`, `Route`, or `Service` + resource. This field can be used only + with `loadbalancer`, `nodeport`, + `route`, or `ingress` type listeners. + externalIPs: + type: array + items: + type: string + description: >- + External IPs associated to the nodeport + service. These IPs are used by clients + external to the Kubernetes cluster to + access the Kafka brokers. This field is + helpful when `nodeport` without + `externalIP` is not sufficient. For + example on bare-metal Kubernetes + clusters that do not support + Loadbalancer service types. This field + can only be used with `nodeport` type + listener. + required: + - broker + description: Per-broker configurations. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the + service. Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`: + + + * `SingleStack` is for a single IP family. + + * `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP + family on single-stack clusters. + + * `RequireDualStack` fails unless there are + two IP families on dual-stack configured + clusters. + + + If unspecified, Kubernetes will choose the + default value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the + default value based on the `ipFamilyPolicy` + setting. + createBootstrapService: + type: boolean + description: >- + Whether to create the bootstrap service or + not. The bootstrap service is created by + default (if not specified differently). This + field can be used with the `loadbalancer` + listener. + finalizers: + type: array + items: + type: string + description: >- + A list of finalizers configured for the + `LoadBalancer` type services created for this + listener. If supported by the platform, the + finalizer + `service.kubernetes.io/load-balancer-cleanup` + to make sure that the external load balancer + is deleted together with the service.For more + information, see + https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#garbage-collecting-load-balancers. + For `loadbalancer` listeners only. + useServiceDnsDomain: + type: boolean + description: >- + Configures whether the Kubernetes service DNS + domain should be included in the generated + addresses. + + + * If set to `false`, the generated addresses + do not contain the service DNS domain suffix. + For example, + `my-cluster-kafka-0.my-cluster-kafka-brokers.myproject.svc`. + + * If set to `true`, the generated addresses + contain the service DNS domain suffix. For + example, + `my-cluster-kafka-0.my-cluster-kafka-brokers.myproject.svc.cluster.local`. + + + The default is `.cluster.local`, but this is + customizable using the environment variable + `KUBERNETES_SERVICE_DNS_DOMAIN`. For + `internal` and `cluster-ip` listeners only. + maxConnections: + type: integer + description: >- + The maximum number of connections we allow for + this listener in the broker at any time. New + connections are blocked if the limit is + reached. + maxConnectionCreationRate: + type: integer + description: >- + The maximum connection creation rate we allow + in this listener at any time. New connections + will be throttled if the limit is reached. + preferredNodePortAddressType: + type: string + enum: + - ExternalIP + - ExternalDNS + - InternalIP + - InternalDNS + - Hostname + description: >- + Defines which address type should be used as + the node address. Available types are: + `ExternalDNS`, `ExternalIP`, `InternalDNS`, + `InternalIP` and `Hostname`. By default, the + addresses are used in the following order (the + first one found is used): + + + * `ExternalDNS` + + * `ExternalIP` + + * `InternalDNS` + + * `InternalIP` + + * `Hostname` + + + This property is used to select the preferred + address type, which is checked first. If no + address is found for this address type, the + other types are checked in the default order. + For `nodeport` listeners only. + publishNotReadyAddresses: + type: boolean + description: >- + Configures whether the service endpoints are + considered "ready" even if the Pods themselves + are not. Defaults to `false`. This field can + not be used with `internal` listeners. + hostTemplate: + type: string + description: >- + Configures the template for generating the + hostnames of the individual brokers. Valid + placeholders that you can use in the template + are `{nodeId}` and `{nodePodName}`. + advertisedHostTemplate: + type: string + description: >- + Configures the template for generating the + advertised hostnames of the individual + brokers. Valid placeholders that you can use + in the template are `{nodeId}` and + `{nodePodName}`. + advertisedPortTemplate: + type: string + description: >- + Configures the template for generating the + advertised ports of the individual brokers. It + allows to specify a simple mathematics formula + that will be used to calculate the port. The + only valid placeholder that you can use in the + template is `{nodeId}`. Supported operations + are `+`, `-`, and `*`. For example, `9000 + + {nodeId}` will generate ports `9000`, `9001`, + `9002`, and so on for the individual brokers. + You can also use a fixed port number in the + template, for example `9000`, which will + generate the same port for all brokers. + allocateLoadBalancerNodePorts: + type: boolean + description: >- + Configures whether to allocate NodePort + automatically for the `Service` with type + `LoadBalancer`. + + This is a one to one with the + `spec.allocateLoadBalancerNodePorts` + configuration in the `Service` type + + For `loadbalancer` listeners only. + description: Additional listener configuration. + networkPolicyPeers: + type: array + items: + type: object + properties: + ipBlock: + type: object + properties: + cidr: + type: string + except: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + podSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + description: >- + List of peers which should be able to connect to + this listener. Peers in this list are combined + using a logical OR operation. If this field is + empty or missing, all connections will be allowed + for this listener. If this field is present and + contains at least one item, the listener only + allows the traffic which matches at least one item + in this list. + required: + - name + - port + - type + - tls + description: Configures listeners to provide access to Kafka brokers. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + Kafka broker config properties with certain prefixes + cannot be set unless it is in the exception list. + Consult the documentation for the list of forbidden + prefixes and exceptions. + authorization: + type: object + properties: + authorizerClass: + type: string + description: >- + Authorization implementation class, which must be + available in classpath. + superUsers: + type: array + items: + type: string + description: >- + List of super users, which are user principals with + unlimited access rights. + supportsAdminApi: + type: boolean + description: >- + Indicates whether the custom authorizer supports the + APIs for managing ACLs using the Kafka Admin API. + Defaults to `false`. + type: + type: string + enum: + - simple + - custom + description: >- + Authorization type. Currently, the supported types + are `simple`, `keycloak`, `opa` and `custom`. + `simple` authorization type uses Kafka's built-in + authorizer for authorization. `keycloak` + authorization type uses Keycloak Authorization + Services for authorization. `opa` authorization type + uses Open Policy Agent based authorization. `custom` + authorization type uses user-provided implementation + for authorization. `opa` (as of Strimzi 0.46.0) and + `keycloak` (as of Strimzi 0.49.0) types are + deprecated and will be removed in the `v1` API + version. Please use `custom` type instead. + required: + - type + description: Authorization configuration for Kafka brokers. + rack: + type: object + properties: + envVarName: + type: string + description: >- + The name of the environment variable that defines + the rack ID. Its value sets the `broker.rack` + configuration for Kafka brokers and the + `client.rack` configuration for Kafka Connect or + MirrorMaker 2. + topologyKey: + type: string + example: topology.kubernetes.io/zone + description: >- + A key that matches labels assigned to the Kubernetes + cluster nodes. The value of the label is used to set + a broker's `broker.rack` config, and the + `client.rack` config for Kafka Connect or + MirrorMaker 2. + type: + type: string + enum: + - topology-label + - environment-variable + description: >- + Specifies the rack awareness type. Supported types + are `topology-label` and `environment-variable`. + `topology-label` uses a Kubernetes worker node label + to set the `broker.rack` configuration for Kafka + brokers and the `client.rack` configuration for + Kafka Connect and MirrorMaker 2. + `environment-variable` uses an environment variable + to set the `broker.rack` configuration for Kafka + brokers and the `client.rack` configuration for + Kafka Connect and MirrorMaker 2. When not specified, + `topology-label` type is used by default. + description: Configuration of the `broker.rack` broker config. + x-kubernetes-validations: + - rule: >- + (has(self.type) && self.type != "topology-label") || + self.topologyKey != "" + message: topologyKey property is required + - rule: >- + has(self.type) == false || self.type != + "environment-variable" || self.envVarName != "" + message: envVarName property is required + brokerRackInitImage: + type: string + description: >- + The image of the init container used for initializing + the `broker.rack`. + livenessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default + to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults + to 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + description: Pod liveness checking. + readinessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default + to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults + to 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + description: Pod readiness checking. + jvmOptions: + type: object + properties: + '-XX': + additionalProperties: + type: string + type: object + description: A map of -XX options to the JVM. + '-Xmx': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xmx option to to the JVM.' + '-Xms': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xms option to to the JVM.' + gcLoggingEnabled: + type: boolean + description: >- + Specifies whether the Garbage Collection logging is + enabled. The default is false. + javaSystemProperties: + type: array + items: + type: object + properties: + name: + type: string + description: The system property name. + value: + type: string + description: The system property value. + description: >- + A map of additional system properties which will be + passed using the `-D` option to the JVM. + description: JVM Options for pods. + jmxOptions: + type: object + properties: + authentication: + type: object + properties: + type: + type: string + enum: + - password + description: >- + Authentication type. Currently the only + supported types are `password`.`password` type + creates a username and protected port with no + TLS. + required: + - type + description: >- + Authentication configuration for connecting to the + JMX port. + description: JMX Options for Kafka brokers. + metricsConfig: + type: object + properties: + type: + type: string + enum: + - jmxPrometheusExporter + - strimziMetricsReporter + description: >- + Metrics type. The supported types are + `jmxPrometheusExporter` and + `strimziMetricsReporter`. Type + `jmxPrometheusExporter` uses the Prometheus JMX + Exporter to expose Kafka JMX metrics in Prometheus + format through an HTTP endpoint. Type + `strimziMetricsReporter` uses the Strimzi Metrics + Reporter to directly expose Kafka metrics in + Prometheus format through an HTTP endpoint. + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing + the configuration. + description: >- + ConfigMap entry where the Prometheus JMX Exporter + configuration is stored. + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: >- + A list of regex patterns to filter the metrics + to collect. Should contain at least one element. + description: >- + Configuration values for the Strimzi Metrics + Reporter. + required: + - type + description: Metrics configuration. + x-kubernetes-validations: + - rule: >- + self.type != 'jmxPrometheusExporter' || + has(self.valueFrom) + message: valueFrom property is required + logging: + type: object + properties: + loggers: + additionalProperties: + type: string + type: object + description: A Map from logger name to logger level. + type: + type: string + enum: + - inline + - external + description: 'Logging type, must be either ''inline'' or ''external''.' + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing + the configuration. + description: >- + `ConfigMap` entry where the logging configuration is + stored. + required: + - type + description: Logging configuration for Kafka. + template: + type: object + properties: + pod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same + namespace to use for pulling any of the images + used by this Pod. When the + `STRIMZI_IMAGE_PULL_SECRETS` environment + variable in Cluster Operator and the + `imagePullSecrets` option are specified, only + the `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is + ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and + common container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds + after the processes running in the pod are sent + a termination signal, and the time when the + processes are forcibly halted with a kill + signal. Set this value to longer than the + expected cleanup time for your process. Value + must be a non-negative integer. A zero value + indicates delete immediately. You might need to + increase the grace period for very large Kafka + clusters, so that the Kafka brokers have enough + time to transfer their work to another broker + before they are terminated. Defaults to 30 + seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler + will be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an + optional list of hosts and IPs that will be + injected into the Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be + merged to the generated DNS configuration based + on the DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services + should be injected into Pod's environment + variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated + for the temporary `EmptyDir` volume `/tmp`. + Specify the allocation in memory units, for + example, `100Mi` for 100 mebibytes. Default + value is `5Mi`. The `/tmp` volume is backed by + pod memory, not disk storage, so avoid setting a + high value as it consumes pod memory resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage + required for this EmptyDir volume (for + example 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to + populate the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to + populate the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: >- + Additional volumes that can be mounted to the + pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults + to `true`. When `true` or not set, the pod runs + in the host user namespace. This is required + when the pod needs features available only in + the host namespace, such as loading kernel + modules with `CAP_SYS_MODULE`.When set to + `false`, the pod runs in a new user namespace. + Setting `false` helps mitigate container + breakout vulnerabilities and allows containers + to run as `root` without granting `root` + privileges on the host. This property is + alpha-level in Kubernetes and is supported only + by Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: Template for Kafka `Pods`. + bootstrapService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the + service. Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`. + `SingleStack` is for a single IP family. + `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP + family on single-stack clusters. + `RequireDualStack` fails unless there are two IP + families on dual-stack configured clusters. If + unspecified, Kubernetes will choose the default + value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the default + value based on the `ipFamilyPolicy` setting. + description: Template for Kafka bootstrap `Service`. + brokersService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the + service. Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`. + `SingleStack` is for a single IP family. + `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP + family on single-stack clusters. + `RequireDualStack` fails unless there are two IP + families on dual-stack configured clusters. If + unspecified, Kubernetes will choose the default + value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the default + value based on the `ipFamilyPolicy` setting. + description: Template for Kafka broker `Service`. + externalBootstrapService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for Kafka external bootstrap `Service`. + perPodService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: >- + Template for Kafka per-pod `Services` used for + access from outside of Kubernetes. + externalBootstrapRoute: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for Kafka external bootstrap `Route`. + perPodRoute: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: >- + Template for Kafka per-pod `Routes` used for access + from outside of OpenShift. + externalBootstrapIngress: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for Kafka external bootstrap `Ingress`. + perPodIngress: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: >- + Template for Kafka per-pod `Ingress` used for access + from outside of Kubernetes. + persistentVolumeClaim: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for all Kafka `PersistentVolumeClaims`. + podDisruptionBudget: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + maxUnavailable: + type: integer + minimum: 0 + description: >- + Maximum number of unavailable pods to allow + automatic Pod eviction. A Pod eviction is + allowed when the `maxUnavailable` number of pods + or fewer are unavailable after the eviction. + Setting this value to 0 prevents all voluntary + evictions, so the pods must be evicted manually. + Defaults to 1. + description: Template for Kafka `PodDisruptionBudget`. + kafkaContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map + property to which the environment variable + is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to + the container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied + to the container. + description: Template for the Kafka broker container. + initContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map + property to which the environment variable + is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to + the container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied + to the container. + description: Template for the Kafka init container. + clusterCaCert: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: >- + Template for Secret with Kafka Cluster certificate + public key. + serviceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for the Kafka service account. + jmxSecret: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: >- + Template for Secret of the Kafka Cluster JMX + authentication. + clusterRoleBinding: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for the Kafka ClusterRoleBinding. + podSet: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for Kafka `StrimziPodSet` resource. + description: >- + Template for Kafka cluster resources. The template + allows users to specify how the Kubernetes resources are + generated. + tieredStorage: + type: object + properties: + remoteStorageManager: + type: object + properties: + className: + type: string + description: >- + The class name for the `RemoteStorageManager` + implementation. + classPath: + type: string + description: >- + The class path for the `RemoteStorageManager` + implementation. + config: + additionalProperties: + type: string + type: object + description: >- + The additional configuration map for the + `RemoteStorageManager` implementation. Keys will + be automatically prefixed with `rsm.config.`, + and added to Kafka broker configuration. + description: Configuration for the Remote Storage Manager. + type: + type: string + enum: + - custom + description: >- + Storage type, only 'custom' is supported at the + moment. + required: + - type + description: Configure the tiered storage feature for Kafka brokers. + quotas: + type: object + properties: + consumerByteRate: + type: integer + minimum: 0 + description: >- + A per-broker byte-rate quota for clients consuming + from a broker, independent of their number. If + clients consume at maximum speed, the quota is + shared equally between all non-excluded consumers. + Otherwise, the quota is divided based on each + client's consumption rate. + controllerMutationRate: + type: number + minimum: 0 + description: >- + The default client quota on the rate at which + mutations are accepted per second for create topic + requests, create partition requests, and delete + topic requests, defined for each broker. The + mutations rate is measured by the number of + partitions created or deleted. Applied on a + per-broker basis. + excludedPrincipals: + type: array + items: + type: string + description: >- + List of principals that are excluded from the quota. + The principals have to be prefixed with `User:`, for + example `User:my-user;User:CN=my-other-user`. + minAvailableBytesPerVolume: + type: integer + minimum: 0 + description: >- + Stop message production if the available size (in + bytes) of the storage is lower than or equal to this + specified value. This condition is mutually + exclusive with `minAvailableRatioPerVolume`. + minAvailableRatioPerVolume: + type: number + minimum: 0 + maximum: 1 + description: >- + Stop message production if the percentage of + available storage space falls below or equals the + specified ratio (set as a decimal representing a + percentage). This condition is mutually exclusive + with `minAvailableBytesPerVolume`. + producerByteRate: + type: integer + minimum: 0 + description: >- + A per-broker byte-rate quota for clients producing + to a broker, independent of their number. If clients + produce at maximum speed, the quota is shared + equally between all non-excluded producers. + Otherwise, the quota is divided based on each + client's production rate. + requestPercentage: + type: integer + minimum: 0 + description: >- + The default client quota limits the maximum CPU + utilization of each client as a percentage of the + network and I/O threads of each broker. Applied on a + per-broker basis. + type: + type: string + enum: + - kafka + - strimzi + description: >- + Quotas plugin type. Currently, the supported types + are `kafka` and `strimzi`. `kafka` quotas type uses + Kafka's built-in quotas plugin. `strimzi` quotas + type uses Strimzi quotas plugin. + required: + - type + description: >- + Quotas plugin configuration for Kafka brokers allows + setting quotas for disk usage, produce/fetch rates, and + more. Supported plugin types include `kafka` (default) + and `strimzi`. If not specified, the default `kafka` + quotas plugin is used. + required: + - listeners + description: Configuration of the Kafka cluster. + entityOperator: + type: object + properties: + topicOperator: + type: object + properties: + watchedNamespace: + type: string + description: The namespace the Topic Operator should watch. + image: + type: string + description: The image to use for the Topic Operator. + reconciliationIntervalMs: + type: integer + minimum: 0 + description: >- + Interval between periodic reconciliations in + milliseconds. + startupProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is + first checked. Default to 15 seconds. Minimum + value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. + Default to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to + be considered successful after having failed. + Defaults to 1. Must be 1 for liveness. Minimum + value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + description: Pod startup checking. + livenessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is + first checked. Default to 15 seconds. Minimum + value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. + Default to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to + be considered successful after having failed. + Defaults to 1. Must be 1 for liveness. Minimum + value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + description: Pod liveness checking. + readinessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is + first checked. Default to 15 seconds. Minimum + value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. + Default to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to + be considered successful after having failed. + Defaults to 1. Must be 1 for liveness. Minimum + value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + description: Pod readiness checking. + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: CPU and memory resources to reserve. + logging: + type: object + properties: + loggers: + additionalProperties: + type: string + type: object + description: A Map from logger name to logger level. + type: + type: string + enum: + - inline + - external + description: >- + Logging type, must be either 'inline' or + 'external'. + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap + containing the configuration. + description: >- + `ConfigMap` entry where the logging + configuration is stored. + required: + - type + description: Logging configuration. + jvmOptions: + type: object + properties: + '-XX': + additionalProperties: + type: string + type: object + description: A map of -XX options to the JVM. + '-Xmx': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xmx option to to the JVM.' + '-Xms': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xms option to to the JVM.' + gcLoggingEnabled: + type: boolean + description: >- + Specifies whether the Garbage Collection logging + is enabled. The default is false. + javaSystemProperties: + type: array + items: + type: object + properties: + name: + type: string + description: The system property name. + value: + type: string + description: The system property value. + description: >- + A map of additional system properties which will + be passed using the `-D` option to the JVM. + description: JVM Options for pods. + description: Configuration of the Topic Operator. + userOperator: + type: object + properties: + watchedNamespace: + type: string + description: The namespace the User Operator should watch. + image: + type: string + description: The image to use for the User Operator. + reconciliationIntervalMs: + type: integer + minimum: 0 + description: >- + Interval between periodic reconciliations in + milliseconds. + secretPrefix: + type: string + description: >- + The prefix that will be added to the KafkaUser name + to be used as the Secret name. + livenessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is + first checked. Default to 15 seconds. Minimum + value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. + Default to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to + be considered successful after having failed. + Defaults to 1. Must be 1 for liveness. Minimum + value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + description: Pod liveness checking. + readinessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is + first checked. Default to 15 seconds. Minimum + value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. + Default to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to + be considered successful after having failed. + Defaults to 1. Must be 1 for liveness. Minimum + value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + description: Pod readiness checking. + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: CPU and memory resources to reserve. + logging: + type: object + properties: + loggers: + additionalProperties: + type: string + type: object + description: A Map from logger name to logger level. + type: + type: string + enum: + - inline + - external + description: >- + Logging type, must be either 'inline' or + 'external'. + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap + containing the configuration. + description: >- + `ConfigMap` entry where the logging + configuration is stored. + required: + - type + description: Logging configuration. + jvmOptions: + type: object + properties: + '-XX': + additionalProperties: + type: string + type: object + description: A map of -XX options to the JVM. + '-Xmx': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xmx option to to the JVM.' + '-Xms': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xms option to to the JVM.' + gcLoggingEnabled: + type: boolean + description: >- + Specifies whether the Garbage Collection logging + is enabled. The default is false. + javaSystemProperties: + type: array + items: + type: object + properties: + name: + type: string + description: The system property name. + value: + type: string + description: The system property value. + description: >- + A map of additional system properties which will + be passed using the `-D` option to the JVM. + description: JVM Options for pods. + description: Configuration of the User Operator. + template: + type: object + properties: + deployment: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + deploymentStrategy: + type: string + enum: + - RollingUpdate + - Recreate + description: >- + Pod replacement strategy for deployment + configuration changes. Valid values are + `RollingUpdate` and `Recreate`. Defaults to + `RollingUpdate`. + description: Template for Entity Operator `Deployment`. + pod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same + namespace to use for pulling any of the images + used by this Pod. When the + `STRIMZI_IMAGE_PULL_SECRETS` environment + variable in Cluster Operator and the + `imagePullSecrets` option are specified, only + the `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is + ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and + common container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds + after the processes running in the pod are sent + a termination signal, and the time when the + processes are forcibly halted with a kill + signal. Set this value to longer than the + expected cleanup time for your process. Value + must be a non-negative integer. A zero value + indicates delete immediately. You might need to + increase the grace period for very large Kafka + clusters, so that the Kafka brokers have enough + time to transfer their work to another broker + before they are terminated. Defaults to 30 + seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler + will be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an + optional list of hosts and IPs that will be + injected into the Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be + merged to the generated DNS configuration based + on the DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services + should be injected into Pod's environment + variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated + for the temporary `EmptyDir` volume `/tmp`. + Specify the allocation in memory units, for + example, `100Mi` for 100 mebibytes. Default + value is `5Mi`. The `/tmp` volume is backed by + pod memory, not disk storage, so avoid setting a + high value as it consumes pod memory resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage + required for this EmptyDir volume (for + example 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to + populate the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to + populate the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: >- + Additional volumes that can be mounted to the + pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults + to `true`. When `true` or not set, the pod runs + in the host user namespace. This is required + when the pod needs features available only in + the host namespace, such as loading kernel + modules with `CAP_SYS_MODULE`.When set to + `false`, the pod runs in a new user namespace. + Setting `false` helps mitigate container + breakout vulnerabilities and allows containers + to run as `root` without granting `root` + privileges on the host. This property is + alpha-level in Kubernetes and is supported only + by Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: Template for Entity Operator `Pods`. + topicOperatorContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map + property to which the environment variable + is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to + the container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied + to the container. + description: Template for the Entity Topic Operator container. + userOperatorContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map + property to which the environment variable + is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to + the container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied + to the container. + description: Template for the Entity User Operator container. + serviceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for the Entity Operator service account. + podDisruptionBudget: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + maxUnavailable: + type: integer + minimum: 0 + description: >- + Maximum number of unavailable pods to allow + automatic Pod eviction. A Pod eviction is + allowed when the `maxUnavailable` number of pods + or fewer are unavailable after the eviction. + Setting this value to 0 prevents all voluntary + evictions, so the pods must be evicted manually. + Defaults to 1. + description: >- + Template for the Entity Operator Pod Disruption + Budget. + entityOperatorRole: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for the Entity Operator Role. + topicOperatorRoleBinding: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for the Entity Topic Operator RoleBinding. + userOperatorRoleBinding: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for the Entity Topic Operator RoleBinding. + description: >- + Template for Entity Operator resources. The template + allows users to specify how a `Deployment` and `Pod` is + generated. + description: Configuration of the Entity Operator. + clusterCa: + type: object + properties: + generateCertificateAuthority: + type: boolean + description: >- + If true then Certificate Authority certificates will be + generated automatically. Otherwise the user will need to + provide a Secret with the CA certificate. Default is + true. + generateSecretOwnerReference: + type: boolean + description: >- + If `true`, the Cluster and Client CA Secrets are + configured with the `ownerReference` set to the `Kafka` + resource. If the `Kafka` resource is deleted when + `true`, the CA Secrets are also deleted. If `false`, the + `ownerReference` is disabled. If the `Kafka` resource is + deleted when `false`, the CA Secrets are retained and + available for reuse. Default is `true`. + validityDays: + type: integer + minimum: 1 + description: >- + The number of days generated certificates should be + valid for. The default is 365. + renewalDays: + type: integer + minimum: 1 + description: >- + The number of days in the certificate renewal period. + This is the number of days before the a certificate + expires during which renewal actions may be performed. + When `generateCertificateAuthority` is true, this will + cause the generation of a new certificate. When + `generateCertificateAuthority` is true, this will cause + extra logging at WARN level about the pending + certificate expiry. Default is 30. + certificateExpirationPolicy: + type: string + enum: + - renew-certificate + - replace-key + description: >- + How should CA certificate expiration be handled when + `generateCertificateAuthority=true`. The default is for + a new CA certificate to be generated reusing the + existing private key. + description: Configuration of the cluster certificate authority. + clientsCa: + type: object + properties: + generateCertificateAuthority: + type: boolean + description: >- + If true then Certificate Authority certificates will be + generated automatically. Otherwise the user will need to + provide a Secret with the CA certificate. Default is + true. + generateSecretOwnerReference: + type: boolean + description: >- + If `true`, the Cluster and Client CA Secrets are + configured with the `ownerReference` set to the `Kafka` + resource. If the `Kafka` resource is deleted when + `true`, the CA Secrets are also deleted. If `false`, the + `ownerReference` is disabled. If the `Kafka` resource is + deleted when `false`, the CA Secrets are retained and + available for reuse. Default is `true`. + validityDays: + type: integer + minimum: 1 + description: >- + The number of days generated certificates should be + valid for. The default is 365. + renewalDays: + type: integer + minimum: 1 + description: >- + The number of days in the certificate renewal period. + This is the number of days before the a certificate + expires during which renewal actions may be performed. + When `generateCertificateAuthority` is true, this will + cause the generation of a new certificate. When + `generateCertificateAuthority` is true, this will cause + extra logging at WARN level about the pending + certificate expiry. Default is 30. + certificateExpirationPolicy: + type: string + enum: + - renew-certificate + - replace-key + description: >- + How should CA certificate expiration be handled when + `generateCertificateAuthority=true`. The default is for + a new CA certificate to be generated reusing the + existing private key. + description: Configuration of the clients certificate authority. + cruiseControl: + type: object + properties: + image: + type: string + description: >- + The container image used for Cruise Control pods. If no + image name is explicitly specified, the image name + corresponds to the name specified in the Cluster + Operator configuration. If an image name is not defined + in the Cluster Operator configuration, a default value + is used. + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: >- + CPU and memory resources to reserve for the Cruise + Control container. + livenessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default + to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults + to 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + description: Pod liveness checking for the Cruise Control container. + readinessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default + to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults + to 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + description: Pod readiness checking for the Cruise Control container. + jvmOptions: + type: object + properties: + '-XX': + additionalProperties: + type: string + type: object + description: A map of -XX options to the JVM. + '-Xmx': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xmx option to to the JVM.' + '-Xms': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xms option to to the JVM.' + gcLoggingEnabled: + type: boolean + description: >- + Specifies whether the Garbage Collection logging is + enabled. The default is false. + javaSystemProperties: + type: array + items: + type: object + properties: + name: + type: string + description: The system property name. + value: + type: string + description: The system property value. + description: >- + A map of additional system properties which will be + passed using the `-D` option to the JVM. + description: JVM Options for the Cruise Control container. + logging: + type: object + properties: + loggers: + additionalProperties: + type: string + type: object + description: A Map from logger name to logger level. + type: + type: string + enum: + - inline + - external + description: 'Logging type, must be either ''inline'' or ''external''.' + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing + the configuration. + description: >- + `ConfigMap` entry where the logging configuration is + stored. + required: + - type + description: Logging configuration (Log4j 2) for Cruise Control. + template: + type: object + properties: + deployment: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + deploymentStrategy: + type: string + enum: + - RollingUpdate + - Recreate + description: >- + Pod replacement strategy for deployment + configuration changes. Valid values are + `RollingUpdate` and `Recreate`. Defaults to + `RollingUpdate`. + description: Template for Cruise Control `Deployment`. + pod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same + namespace to use for pulling any of the images + used by this Pod. When the + `STRIMZI_IMAGE_PULL_SECRETS` environment + variable in Cluster Operator and the + `imagePullSecrets` option are specified, only + the `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is + ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and + common container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds + after the processes running in the pod are sent + a termination signal, and the time when the + processes are forcibly halted with a kill + signal. Set this value to longer than the + expected cleanup time for your process. Value + must be a non-negative integer. A zero value + indicates delete immediately. You might need to + increase the grace period for very large Kafka + clusters, so that the Kafka brokers have enough + time to transfer their work to another broker + before they are terminated. Defaults to 30 + seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler + will be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an + optional list of hosts and IPs that will be + injected into the Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be + merged to the generated DNS configuration based + on the DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services + should be injected into Pod's environment + variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated + for the temporary `EmptyDir` volume `/tmp`. + Specify the allocation in memory units, for + example, `100Mi` for 100 mebibytes. Default + value is `5Mi`. The `/tmp` volume is backed by + pod memory, not disk storage, so avoid setting a + high value as it consumes pod memory resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage + required for this EmptyDir volume (for + example 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to + populate the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to + populate the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: >- + Additional volumes that can be mounted to the + pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults + to `true`. When `true` or not set, the pod runs + in the host user namespace. This is required + when the pod needs features available only in + the host namespace, such as loading kernel + modules with `CAP_SYS_MODULE`.When set to + `false`, the pod runs in a new user namespace. + Setting `false` helps mitigate container + breakout vulnerabilities and allows containers + to run as `root` without granting `root` + privileges on the host. This property is + alpha-level in Kubernetes and is supported only + by Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: Template for Cruise Control `Pods`. + apiService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the + service. Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`. + `SingleStack` is for a single IP family. + `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP + family on single-stack clusters. + `RequireDualStack` fails unless there are two IP + families on dual-stack configured clusters. If + unspecified, Kubernetes will choose the default + value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the default + value based on the `ipFamilyPolicy` setting. + description: Template for Cruise Control API `Service`. + podDisruptionBudget: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + maxUnavailable: + type: integer + minimum: 0 + description: >- + Maximum number of unavailable pods to allow + automatic Pod eviction. A Pod eviction is + allowed when the `maxUnavailable` number of pods + or fewer are unavailable after the eviction. + Setting this value to 0 prevents all voluntary + evictions, so the pods must be evicted manually. + Defaults to 1. + description: Template for Cruise Control `PodDisruptionBudget`. + cruiseControlContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map + property to which the environment variable + is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to + the container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied + to the container. + description: Template for the Cruise Control container. + serviceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for the Cruise Control service account. + description: >- + Template to specify how Cruise Control resources, + `Deployments` and `Pods`, are generated. + brokerCapacity: + type: object + properties: + cpu: + type: string + pattern: '^[0-9]+([.][0-9]{0,3}|[m]?)$' + description: >- + Broker capacity for CPU resource in cores or + millicores. For example, 1, 1.500, 1500m. For more + information on valid CPU resource units see + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-cpu. + inboundNetwork: + type: string + pattern: '^[0-9]+([KMG]i?)?B/s$' + description: >- + Broker capacity for inbound network throughput in + bytes per second. Use an integer value with standard + Kubernetes byte units (K, M, G) or their bibyte + (power of two) equivalents (Ki, Mi, Gi) per second. + For example, 10000KiB/s. + outboundNetwork: + type: string + pattern: '^[0-9]+([KMG]i?)?B/s$' + description: >- + Broker capacity for outbound network throughput in + bytes per second. Use an integer value with standard + Kubernetes byte units (K, M, G) or their bibyte + (power of two) equivalents (Ki, Mi, Gi) per second. + For example, 10000KiB/s. + overrides: + type: array + items: + type: object + properties: + brokers: + type: array + items: + type: integer + description: List of Kafka brokers (broker identifiers). + cpu: + type: string + pattern: '^[0-9]+([.][0-9]{0,3}|[m]?)$' + description: >- + Broker capacity for CPU resource in cores or + millicores. For example, 1, 1.500, 1500m. For + more information on valid CPU resource units + see + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-cpu. + inboundNetwork: + type: string + pattern: '^[0-9]+([KMG]i?)?B/s$' + description: >- + Broker capacity for inbound network throughput + in bytes per second. Use an integer value with + standard Kubernetes byte units (K, M, G) or + their bibyte (power of two) equivalents (Ki, + Mi, Gi) per second. For example, 10000KiB/s. + outboundNetwork: + type: string + pattern: '^[0-9]+([KMG]i?)?B/s$' + description: >- + Broker capacity for outbound network + throughput in bytes per second. Use an integer + value with standard Kubernetes byte units (K, + M, G) or their bibyte (power of two) + equivalents (Ki, Mi, Gi) per second. For + example, 10000KiB/s. + required: + - brokers + description: >- + Overrides for individual brokers. The `overrides` + property lets you specify a different capacity + configuration for different brokers. + description: The Cruise Control `brokerCapacity` configuration. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The Cruise Control configuration. For a full list of + configuration options refer to + https://github.com/linkedin/cruise-control/wiki/Configurations. + Note that properties with the following prefixes cannot + be set: bootstrap.servers, client.id, zookeeper., + network., security., + failed.brokers.zk.path,webserver.http., + webserver.api.urlprefix, webserver.session.path, + webserver.accesslog., two.step., + request.reason.required,metric.reporter.sampler.bootstrap.servers, + capacity.config.file, self.healing., ssl., + kafka.broker.failure.detection.enable, + topic.config.provider.class (with the exception of: + ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, + webserver.http.cors.enabled, webserver.http.cors.origin, + webserver.http.cors.exposeheaders, + webserver.security.enable, webserver.ssl.enable). + metricsConfig: + type: object + properties: + type: + type: string + enum: + - jmxPrometheusExporter + - strimziMetricsReporter + description: >- + Metrics type. The supported types are + `jmxPrometheusExporter` and + `strimziMetricsReporter`. Type + `jmxPrometheusExporter` uses the Prometheus JMX + Exporter to expose Kafka JMX metrics in Prometheus + format through an HTTP endpoint. Type + `strimziMetricsReporter` uses the Strimzi Metrics + Reporter to directly expose Kafka metrics in + Prometheus format through an HTTP endpoint. + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing + the configuration. + description: >- + ConfigMap entry where the Prometheus JMX Exporter + configuration is stored. + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: >- + A list of regex patterns to filter the metrics + to collect. Should contain at least one element. + description: >- + Configuration values for the Strimzi Metrics + Reporter. + required: + - type + description: >- + Metrics configuration. Only `jmxPrometheusExporter` can + be configured, as this component does not support + `strimziMetricsReporter`. + x-kubernetes-validations: + - rule: >- + self.type != 'jmxPrometheusExporter' || + has(self.valueFrom) + message: valueFrom property is required + - rule: self.type != 'strimziMetricsReporter' + message: value type not supported + apiUsers: + type: object + properties: + type: + type: string + enum: + - hashLoginService + description: >- + Type of the Cruise Control API users configuration. + Supported format is: `hashLoginService`. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Selects a key of a Secret in the resource's + namespace. + description: >- + Secret from which the custom Cruise Control API + authentication credentials are read. + required: + - type + - valueFrom + description: Configuration of the Cruise Control REST API users. + autoRebalance: + type: array + minItems: 1 + items: + type: object + properties: + mode: + type: string + enum: + - add-brokers + - remove-brokers + description: > + Specifies the mode for automatically rebalancing + when brokers are added or removed. Supported modes + are `add-brokers` and `remove-brokers`. + template: + type: object + properties: + name: + type: string + description: >- + Reference to the KafkaRebalance custom resource to + be used as the configuration template for the + auto-rebalancing on scaling when running for the + corresponding mode. + required: + - mode + description: >- + Auto-rebalancing on scaling related configuration + listing the modes, when brokers are added or removed, + with the corresponding rebalance template + configurations.If this field is set, at least one mode + has to be defined. + description: >- + Configuration for Cruise Control deployment. Deploys a + Cruise Control instance when specified. + kafkaExporter: + type: object + properties: + image: + type: string + description: >- + The container image used for the Kafka Exporter pods. If + no image name is explicitly specified, the image name + corresponds to the version specified in the Cluster + Operator configuration. If an image name is not defined + in the Cluster Operator configuration, a default value + is used. + groupRegex: + type: string + description: >- + Regular expression to specify which consumer groups to + collect. Default value is `.*`. + topicRegex: + type: string + description: >- + Regular expression to specify which topics to collect. + Default value is `.*`. + groupExcludeRegex: + type: string + description: >- + Regular expression to specify which consumer groups to + exclude. + topicExcludeRegex: + type: string + description: Regular expression to specify which topics to exclude. + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: CPU and memory resources to reserve. + logging: + type: string + description: >- + Only log messages with the given severity or above. + Valid levels: [`info`, `debug`, `trace`]. Default log + level is `info`. + livenessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default + to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults + to 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + description: Pod liveness check. + readinessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default + to 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults + to 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + description: Pod readiness check. + enableSaramaLogging: + type: boolean + description: >- + Enable Sarama logging, a Go client library used by the + Kafka Exporter. + showAllOffsets: + type: boolean + description: >- + Whether show the offset/lag for all consumer group, + otherwise, only show connected consumer groups. + template: + type: object + properties: + deployment: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + deploymentStrategy: + type: string + enum: + - RollingUpdate + - Recreate + description: >- + Pod replacement strategy for deployment + configuration changes. Valid values are + `RollingUpdate` and `Recreate`. Defaults to + `RollingUpdate`. + description: Template for Kafka Exporter `Deployment`. + pod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same + namespace to use for pulling any of the images + used by this Pod. When the + `STRIMZI_IMAGE_PULL_SECRETS` environment + variable in Cluster Operator and the + `imagePullSecrets` option are specified, only + the `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is + ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and + common container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds + after the processes running in the pod are sent + a termination signal, and the time when the + processes are forcibly halted with a kill + signal. Set this value to longer than the + expected cleanup time for your process. Value + must be a non-negative integer. A zero value + indicates delete immediately. You might need to + increase the grace period for very large Kafka + clusters, so that the Kafka brokers have enough + time to transfer their work to another broker + before they are terminated. Defaults to 30 + seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler + will be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an + optional list of hosts and IPs that will be + injected into the Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be + merged to the generated DNS configuration based + on the DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services + should be injected into Pod's environment + variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated + for the temporary `EmptyDir` volume `/tmp`. + Specify the allocation in memory units, for + example, `100Mi` for 100 mebibytes. Default + value is `5Mi`. The `/tmp` volume is backed by + pod memory, not disk storage, so avoid setting a + high value as it consumes pod memory resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage + required for this EmptyDir volume (for + example 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to + populate the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to + populate the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: >- + Additional volumes that can be mounted to the + pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults + to `true`. When `true` or not set, the pod runs + in the host user namespace. This is required + when the pod needs features available only in + the host namespace, such as loading kernel + modules with `CAP_SYS_MODULE`.When set to + `false`, the pod runs in a new user namespace. + Setting `false` helps mitigate container + breakout vulnerabilities and allows containers + to run as `root` without granting `root` + privileges on the host. This property is + alpha-level in Kubernetes and is supported only + by Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: Template for Kafka Exporter `Pods`. + container: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map + property to which the environment variable + is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to + the container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied + to the container. + description: Template for the Kafka Exporter container. + serviceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: Metadata applied to the resource. + description: Template for the Kafka Exporter service account. + podDisruptionBudget: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: >- + Annotations added to the Kubernetes + resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + maxUnavailable: + type: integer + minimum: 0 + description: >- + Maximum number of unavailable pods to allow + automatic Pod eviction. A Pod eviction is + allowed when the `maxUnavailable` number of pods + or fewer are unavailable after the eviction. + Setting this value to 0 prevents all voluntary + evictions, so the pods must be evicted manually. + Defaults to 1. + description: >- + Template for the Pod Disruption Budget for Kafka + Exporter pods. + description: Customization of deployment templates and pods. + description: >- + Configuration of the Kafka Exporter. Kafka Exporter can + provide additional metrics, for example lag of consumer + group at topic/partition. + maintenanceTimeWindows: + type: array + items: + type: string + description: >- + A list of time windows for maintenance tasks (that is, + certificates renewal). Each time window is defined by a cron + expression. + required: + - kafka + description: The specification of the Kafka cluster. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + listeners: + type: array + items: + type: object + properties: + name: + type: string + description: The name of the listener. + addresses: + type: array + items: + type: object + properties: + host: + type: string + description: >- + The DNS name or IP address of the Kafka + bootstrap service. + port: + type: integer + description: The port of the Kafka bootstrap service. + description: A list of the addresses for this listener. + bootstrapServers: + type: string + description: >- + A comma-separated list of `host:port` pairs for + connecting to the Kafka cluster using this listener. + certificates: + type: array + items: + type: string + description: >- + A list of TLS certificates which can be used to verify + the identity of the server when connecting to the + given listener. Set only for `tls` and `external` + listeners. + description: Addresses of the internal and external listeners. + kafkaNodePools: + type: array + items: + type: object + properties: + name: + type: string + description: >- + The name of the KafkaNodePool used by this Kafka + resource. + description: List of the KafkaNodePools used by this Kafka cluster. + clusterId: + type: string + description: Kafka cluster Id. + operatorLastSuccessfulVersion: + type: string + description: >- + The version of the Strimzi Cluster Operator which performed + the last successful reconciliation. + kafkaVersion: + type: string + description: The version of Kafka currently deployed in the cluster. + kafkaMetadataVersion: + type: string + description: >- + The KRaft metadata.version currently used by the Kafka + cluster. + autoRebalance: + type: object + properties: + state: + type: string + enum: + - Idle + - RebalanceOnScaleDown + - RebalanceOnScaleUp + description: >- + The current state of an auto-rebalancing operation. + Possible values are: + + + * `Idle` as the initial state when an auto-rebalancing + is requested or as final state when it completes or + fails. + + * `RebalanceOnScaleDown` if an auto-rebalance related to + a scale-down operation is running. + + * `RebalanceOnScaleUp` if an auto-rebalance related to a + scale-up operation is running. + lastTransitionTime: + type: string + description: >- + The timestamp of the latest auto-rebalancing state + update. + modes: + type: array + items: + type: object + properties: + mode: + type: string + enum: + - add-brokers + - remove-brokers + description: >- + Mode for which there is an auto-rebalancing + operation in progress or queued, when brokers are + added or removed. The possible modes are + `add-brokers` and `remove-brokers`. + brokers: + type: array + items: + type: integer + description: > + List of broker IDs involved in an auto-rebalancing + operation related to the current mode. + + The list contains one of the following: + + + * Broker IDs for a current auto-rebalance. + + * Broker IDs for a queued auto-rebalance (if a + previous auto-rebalance is still in progress). + description: >- + List of modes where an auto-rebalancing operation is + either running or queued. + + Each mode entry (`add-brokers` or `remove-brokers`) + includes one of the following: + + + * Broker IDs for a current auto-rebalance. + + * Broker IDs for a queued auto-rebalance (if a previous + rebalance is still in progress). + description: >- + The status of an auto-rebalancing triggered by a cluster + scaling request. + description: The status of the Kafka cluster. + required: + - spec + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkanodepools.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: KafkaNodePool + listKind: KafkaNodePoolList + singular: kafkanodepool + plural: kafkanodepools + shortNames: + - knp + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + scale: + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas + labelSelectorPath: .status.labelSelector + additionalPrinterColumns: + - name: Desired replicas + description: The desired number of replicas + jsonPath: .spec.replicas + type: integer + - name: Roles + description: Roles of the nodes in the pool + jsonPath: .status.roles + type: string + - name: NodeIds + description: Node IDs used by Kafka nodes in this pool + jsonPath: .status.nodeIds + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + replicas: + type: integer + minimum: 0 + description: The number of pods in the pool. + storage: + type: object + properties: + class: + type: string + description: The storage class to use for dynamic volume allocation. + deleteClaim: + type: boolean + description: >- + Specifies whether the persistent volume claim is deleted + when a Kafka node is deleted. Optional. Defaults to + `false`. + id: + type: integer + minimum: 0 + description: >- + Storage identification number. It is mandatory only for + storage volumes defined in a storage of type 'jbod'. + kraftMetadata: + type: string + enum: + - shared + description: >- + Specifies whether this volume should be used for storing + KRaft metadata. This property is optional. When set, the + only currently supported value is `shared`. At most one + volume can have this property set. + selector: + additionalProperties: + type: string + type: object + description: >- + Specifies a specific persistent volume to use. It + contains key:value pairs representing labels for + selecting such a volume. + size: + type: string + description: >- + When `type=persistent-claim`, defines the size of the + persistent volume claim, such as 100Gi. Mandatory when + `type=persistent-claim`. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + When type=ephemeral, defines the total amount of local + storage required for this EmptyDir volume (for example + 1Gi). + type: + type: string + enum: + - ephemeral + - persistent-claim + - jbod + description: >- + Storage type, must be either 'ephemeral', + 'persistent-claim', or 'jbod'. + volumeAttributesClass: + type: string + description: >- + Specifies `VolumeAttributeClass` name for dynamically + configuring storage attributes. + volumes: + type: array + items: + type: object + properties: + class: + type: string + description: >- + The storage class to use for dynamic volume + allocation. + deleteClaim: + type: boolean + description: >- + Specifies whether the persistent volume claim is + deleted when a Kafka node is deleted. Optional. + Defaults to `false`. + id: + type: integer + minimum: 0 + description: >- + Storage identification number. Mandatory for + storage volumes defined with a `jbod` storage type + configuration. + kraftMetadata: + type: string + enum: + - shared + description: >- + Specifies whether this volume should be used for + storing KRaft metadata. This property is optional. + When set, the only currently supported value is + `shared`. At most one volume can have this + property set. + selector: + additionalProperties: + type: string + type: object + description: >- + Specifies a specific persistent volume to use. It + contains key:value pairs representing labels for + selecting such a volume. + size: + type: string + description: >- + When `type=persistent-claim`, defines the size of + the persistent volume claim, such as 100Gi. + Mandatory when `type=persistent-claim`. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + When type=ephemeral, defines the total amount of + local storage required for this EmptyDir volume + (for example 1Gi). + type: + type: string + enum: + - ephemeral + - persistent-claim + description: >- + Storage type, must be either 'ephemeral' or + 'persistent-claim'. + volumeAttributesClass: + type: string + description: >- + Specifies `VolumeAttributeClass` name for + dynamically configuring storage attributes. + required: + - type + description: >- + List of volumes as Storage objects representing the JBOD + disks array. + required: + - type + description: Storage configuration (disk). Cannot be updated. + roles: + type: array + items: + type: string + enum: + - controller + - broker + description: >- + The roles assigned to the node pool. Supported values are + `broker` and `controller`. This property is required. + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: CPU and memory resources to reserve. + jvmOptions: + type: object + properties: + '-XX': + additionalProperties: + type: string + type: object + description: A map of -XX options to the JVM. + '-Xmx': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xmx option to to the JVM.' + '-Xms': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xms option to to the JVM.' + gcLoggingEnabled: + type: boolean + description: >- + Specifies whether the Garbage Collection logging is + enabled. The default is false. + javaSystemProperties: + type: array + items: + type: object + properties: + name: + type: string + description: The system property name. + value: + type: string + description: The system property value. + description: >- + A map of additional system properties which will be + passed using the `-D` option to the JVM. + description: JVM Options for pods. + template: + type: object + properties: + podSet: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for Kafka `StrimziPodSet` resource. + pod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same namespace + to use for pulling any of the images used by this + Pod. When the `STRIMZI_IMAGE_PULL_SECRETS` + environment variable in Cluster Operator and the + `imagePullSecrets` option are specified, only the + `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and common + container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds after + the processes running in the pod are sent a + termination signal, and the time when the processes + are forcibly halted with a kill signal. Set this + value to longer than the expected cleanup time for + your process. Value must be a non-negative integer. + A zero value indicates delete immediately. You might + need to increase the grace period for very large + Kafka clusters, so that the Kafka brokers have + enough time to transfer their work to another broker + before they are terminated. Defaults to 30 seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler will + be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an optional + list of hosts and IPs that will be injected into the + Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be merged + to the generated DNS configuration based on the + DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services should + be injected into Pod's environment variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated for + the temporary `EmptyDir` volume `/tmp`. Specify the + allocation in memory units, for example, `100Mi` for + 100 mebibytes. Default value is `5Mi`. The `/tmp` + volume is backed by pod memory, not disk storage, so + avoid setting a high value as it consumes pod memory + resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage required + for this EmptyDir volume (for example + 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to populate + the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to populate + the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: Additional volumes that can be mounted to the pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults to + `true`. When `true` or not set, the pod runs in the + host user namespace. This is required when the pod + needs features available only in the host namespace, + such as loading kernel modules with + `CAP_SYS_MODULE`.When set to `false`, the pod runs + in a new user namespace. Setting `false` helps + mitigate container breakout vulnerabilities and + allows containers to run as `root` without granting + `root` privileges on the host. This property is + alpha-level in Kubernetes and is supported only by + Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: Template for Kafka `Pods`. + perPodService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: >- + Template for Kafka per-pod `Services` used for access + from outside of Kubernetes. + perPodRoute: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: >- + Template for Kafka per-pod `Routes` used for access from + outside of OpenShift. + perPodIngress: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: >- + Template for Kafka per-pod `Ingress` used for access + from outside of Kubernetes. + persistentVolumeClaim: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for all Kafka `PersistentVolumeClaims`. + kafkaContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: Template for the Kafka broker container. + initContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: Template for the Kafka init container. + description: >- + Template for pool resources. The template allows users to + specify how the resources belonging to this pool are + generated. + required: + - replicas + - storage + - roles + description: The specification of the KafkaNodePool. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + nodeIds: + type: array + items: + type: integer + description: Node IDs used by Kafka nodes in this pool. + clusterId: + type: string + description: Kafka cluster ID. + roles: + type: array + items: + type: string + enum: + - controller + - broker + description: The roles currently assigned to this pool. + replicas: + type: integer + description: >- + The current number of pods being used to provide this + resource. + labelSelector: + type: string + description: Label selector for pods providing this resource. + description: The status of the KafkaNodePool. + required: + - spec + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: strimzi-cluster-operator-global + labels: + app: strimzi +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + verbs: + - get + - list + - watch + - create + - delete + - patch + - update + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - apiGroups: + - '' + resources: + - nodes + verbs: + - list + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkaconnects.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: KafkaConnect + listKind: KafkaConnectList + singular: kafkaconnect + plural: kafkaconnects + shortNames: + - kc + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + scale: + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas + labelSelectorPath: .status.labelSelector + additionalPrinterColumns: + - name: Desired replicas + description: The desired number of Kafka Connect replicas + jsonPath: .spec.replicas + type: integer + - name: Ready + description: The state of the custom resource + jsonPath: '.status.conditions[?(@.type=="Ready")].status' + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + version: + type: string + description: >- + The Kafka Connect version. Defaults to the latest version. + Consult the user documentation to understand the process + required to upgrade or downgrade the version. + replicas: + type: integer + description: >- + The number of pods in the Kafka Connect group. Required in + the `v1` version of the Strimzi API. Defaults to `3` in the + `v1beta2` version of the Strimzi API. + image: + type: string + description: >- + The container image used for Kafka Connect pods. If no image + name is explicitly specified, it is determined based on the + `spec.version` configuration. The image names are + specifically mapped to corresponding versions in the Cluster + Operator configuration. + bootstrapServers: + type: string + description: >- + Bootstrap servers to connect to. This should be given as a + comma separated list of __:__ pairs. + groupId: + type: string + description: A unique ID that identifies the Connect cluster group. + configStorageTopic: + type: string + description: >- + The name of the Kafka topic where connector configurations + are stored. + statusStorageTopic: + type: string + description: >- + The name of the Kafka topic where connector and task status + are stored. + offsetStorageTopic: + type: string + description: >- + The name of the Kafka topic where source connector offsets + are stored. + tls: + type: object + properties: + trustedCertificates: + type: array + items: + type: object + properties: + secretName: + type: string + description: The name of the Secret containing the certificate. + certificate: + type: string + description: The name of the file certificate in the secret. + pattern: + type: string + description: >- + Pattern for the certificate files in the secret. + Use the + link:https://en.wikipedia.org/wiki/Glob_(programming)[_glob + syntax_] for the pattern. All files in the secret + that match the pattern are used. + oneOf: + - properties: + certificate: {} + required: + - certificate + - properties: + pattern: {} + required: + - pattern + required: + - secretName + description: Trusted certificates for TLS connection. + description: TLS configuration. + authentication: + type: object + properties: + certificateAndKey: + type: object + properties: + secretName: + type: string + description: The name of the Secret containing the certificate. + certificate: + type: string + description: The name of the file certificate in the Secret. + key: + type: string + description: >- + The name of the private key in the secret. The + private key must be in unencrypted PKCS #8 format. + For more information, see RFC 5208: + https://datatracker.ietf.org/doc/html/rfc5208. + required: + - secretName + - certificate + - key + description: >- + Reference to the `Secret` which holds the certificate + and private key pair. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + Configuration for the custom authentication mechanism. + Only properties with the `sasl.` and `ssl.keystore.` + prefixes are allowed. Specify other options in the + regular configuration section of the custom resource. + passwordSecret: + type: object + properties: + secretName: + type: string + description: The name of the Secret containing the password. + password: + type: string + description: >- + The name of the key in the Secret under which the + password is stored. + required: + - secretName + - password + description: Reference to the `Secret` which holds the password. + sasl: + type: boolean + description: Enable or disable SASL on this authentication mechanism. + type: + type: string + enum: + - tls + - scram-sha-256 + - scram-sha-512 + - plain + - custom + description: >- + Specifies the authentication type. Supported types are + `tls`, `scram-sha-256`, `scram-sha-512`, `plain`, + 'oauth', and `custom`. `tls` uses TLS client + authentication and is supported only over TLS + connections. `scram-sha-256` and `scram-sha-512` use + SASL SCRAM-SHA-256 and SASL SCRAM-SHA-512 + authentication, respectively. `plain` uses SASL PLAIN + authentication. `oauth` uses SASL OAUTHBEARER + authentication. `custom` allows you to configure a + custom authentication mechanism. As of Strimzi 0.49.0, + `oauth` type is deprecated and will be removed in the + `v1` API version. Please use `custom` type instead. + username: + type: string + description: Username used for the authentication. + required: + - type + description: Authentication configuration for Kafka Connect. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The Kafka Connect configuration. Properties with the + following prefixes cannot be set: group.id, + config.storage.topic, offset.storage.topic, + status.storage.topic, ssl., sasl., security., listeners, + plugin.path, rest., bootstrap.servers, + consumer.interceptor.classes, producer.interceptor.classes, + prometheus.metrics.reporter. (with the exception of: + ssl.endpoint.identification.algorithm, ssl.cipher.suites, + ssl.protocol, ssl.enabled.protocols). + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: >- + The maximum limits for CPU and memory resources and the + requested initial resources. + livenessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default to + 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default to + 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to + 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. + Minimum value is 1. + description: Pod liveness checking. + readinessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default to + 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default to + 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to + 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. + Minimum value is 1. + description: Pod readiness checking. + jvmOptions: + type: object + properties: + '-XX': + additionalProperties: + type: string + type: object + description: A map of -XX options to the JVM. + '-Xmx': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xmx option to to the JVM.' + '-Xms': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xms option to to the JVM.' + gcLoggingEnabled: + type: boolean + description: >- + Specifies whether the Garbage Collection logging is + enabled. The default is false. + javaSystemProperties: + type: array + items: + type: object + properties: + name: + type: string + description: The system property name. + value: + type: string + description: The system property value. + description: >- + A map of additional system properties which will be + passed using the `-D` option to the JVM. + description: JVM Options for pods. + jmxOptions: + type: object + properties: + authentication: + type: object + properties: + type: + type: string + enum: + - password + description: >- + Authentication type. Currently the only supported + types are `password`.`password` type creates a + username and protected port with no TLS. + required: + - type + description: >- + Authentication configuration for connecting to the JMX + port. + description: JMX Options. + logging: + type: object + properties: + loggers: + additionalProperties: + type: string + type: object + description: A Map from logger name to logger level. + type: + type: string + enum: + - inline + - external + description: 'Logging type, must be either ''inline'' or ''external''.' + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing the + configuration. + description: >- + `ConfigMap` entry where the logging configuration is + stored. + required: + - type + description: Logging configuration for Kafka Connect. + clientRackInitImage: + type: string + description: >- + The image of the init container used for initializing the + `client.rack`. + rack: + type: object + properties: + envVarName: + type: string + description: >- + The name of the environment variable that defines the + rack ID. Its value sets the `broker.rack` configuration + for Kafka brokers and the `client.rack` configuration + for Kafka Connect or MirrorMaker 2. + topologyKey: + type: string + example: topology.kubernetes.io/zone + description: >- + A key that matches labels assigned to the Kubernetes + cluster nodes. The value of the label is used to set a + broker's `broker.rack` config, and the `client.rack` + config for Kafka Connect or MirrorMaker 2. + type: + type: string + enum: + - topology-label + - environment-variable + description: >- + Specifies the rack awareness type. Supported types are + `topology-label` and `environment-variable`. + `topology-label` uses a Kubernetes worker node label to + set the `broker.rack` configuration for Kafka brokers + and the `client.rack` configuration for Kafka Connect + and MirrorMaker 2. `environment-variable` uses an + environment variable to set the `broker.rack` + configuration for Kafka brokers and the `client.rack` + configuration for Kafka Connect and MirrorMaker 2. When + not specified, `topology-label` type is used by default. + description: >- + Configuration of the node label which will be used as the + `client.rack` consumer configuration. + x-kubernetes-validations: + - rule: >- + (has(self.type) && self.type != "topology-label") || + self.topologyKey != "" + message: topologyKey property is required + - rule: >- + has(self.type) == false || self.type != + "environment-variable" || self.envVarName != "" + message: envVarName property is required + metricsConfig: + type: object + properties: + type: + type: string + enum: + - jmxPrometheusExporter + - strimziMetricsReporter + description: >- + Metrics type. The supported types are + `jmxPrometheusExporter` and `strimziMetricsReporter`. + Type `jmxPrometheusExporter` uses the Prometheus JMX + Exporter to expose Kafka JMX metrics in Prometheus + format through an HTTP endpoint. Type + `strimziMetricsReporter` uses the Strimzi Metrics + Reporter to directly expose Kafka metrics in Prometheus + format through an HTTP endpoint. + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing the + configuration. + description: >- + ConfigMap entry where the Prometheus JMX Exporter + configuration is stored. + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: >- + A list of regex patterns to filter the metrics to + collect. Should contain at least one element. + description: Configuration values for the Strimzi Metrics Reporter. + required: + - type + description: Metrics configuration. + x-kubernetes-validations: + - rule: >- + self.type != 'jmxPrometheusExporter' || + has(self.valueFrom) + message: valueFrom property is required + tracing: + type: object + properties: + type: + type: string + enum: + - opentelemetry + description: >- + Type of the tracing used. Currently the only supported + type is `opentelemetry` for OpenTelemetry tracing. As of + Strimzi 0.37.0, `jaeger` type is not supported anymore + and this option is ignored. + required: + - type + description: The configuration of tracing in Kafka Connect. + template: + type: object + properties: + podSet: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for Kafka Connect `StrimziPodSet` resource. + pod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same namespace + to use for pulling any of the images used by this + Pod. When the `STRIMZI_IMAGE_PULL_SECRETS` + environment variable in Cluster Operator and the + `imagePullSecrets` option are specified, only the + `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and common + container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds after + the processes running in the pod are sent a + termination signal, and the time when the processes + are forcibly halted with a kill signal. Set this + value to longer than the expected cleanup time for + your process. Value must be a non-negative integer. + A zero value indicates delete immediately. You might + need to increase the grace period for very large + Kafka clusters, so that the Kafka brokers have + enough time to transfer their work to another broker + before they are terminated. Defaults to 30 seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler will + be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an optional + list of hosts and IPs that will be injected into the + Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be merged + to the generated DNS configuration based on the + DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services should + be injected into Pod's environment variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated for + the temporary `EmptyDir` volume `/tmp`. Specify the + allocation in memory units, for example, `100Mi` for + 100 mebibytes. Default value is `5Mi`. The `/tmp` + volume is backed by pod memory, not disk storage, so + avoid setting a high value as it consumes pod memory + resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage required + for this EmptyDir volume (for example + 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to populate + the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to populate + the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: Additional volumes that can be mounted to the pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults to + `true`. When `true` or not set, the pod runs in the + host user namespace. This is required when the pod + needs features available only in the host namespace, + such as loading kernel modules with + `CAP_SYS_MODULE`.When set to `false`, the pod runs + in a new user namespace. Setting `false` helps + mitigate container breakout vulnerabilities and + allows containers to run as `root` without granting + `root` privileges on the host. This property is + alpha-level in Kubernetes and is supported only by + Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: Template for Kafka Connect `Pods`. + apiService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the service. + Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`. + `SingleStack` is for a single IP family. + `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP family + on single-stack clusters. `RequireDualStack` fails + unless there are two IP families on dual-stack + configured clusters. If unspecified, Kubernetes will + choose the default value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the default + value based on the `ipFamilyPolicy` setting. + description: Template for Kafka Connect API `Service`. + headlessService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the service. + Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`. + `SingleStack` is for a single IP family. + `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP family + on single-stack clusters. `RequireDualStack` fails + unless there are two IP families on dual-stack + configured clusters. If unspecified, Kubernetes will + choose the default value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the default + value based on the `ipFamilyPolicy` setting. + description: Template for Kafka Connect headless `Service`. + connectContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: Template for the Kafka Connect container. + initContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: Template for the Kafka init container. + podDisruptionBudget: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + maxUnavailable: + type: integer + minimum: 0 + description: >- + Maximum number of unavailable pods to allow + automatic Pod eviction. A Pod eviction is allowed + when the `maxUnavailable` number of pods or fewer + are unavailable after the eviction. Setting this + value to 0 prevents all voluntary evictions, so the + pods must be evicted manually. Defaults to 1. + description: Template for Kafka Connect `PodDisruptionBudget`. + serviceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for the Kafka Connect service account. + clusterRoleBinding: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for the Kafka Connect ClusterRoleBinding. + buildPod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same namespace + to use for pulling any of the images used by this + Pod. When the `STRIMZI_IMAGE_PULL_SECRETS` + environment variable in Cluster Operator and the + `imagePullSecrets` option are specified, only the + `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and common + container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds after + the processes running in the pod are sent a + termination signal, and the time when the processes + are forcibly halted with a kill signal. Set this + value to longer than the expected cleanup time for + your process. Value must be a non-negative integer. + A zero value indicates delete immediately. You might + need to increase the grace period for very large + Kafka clusters, so that the Kafka brokers have + enough time to transfer their work to another broker + before they are terminated. Defaults to 30 seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler will + be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an optional + list of hosts and IPs that will be injected into the + Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be merged + to the generated DNS configuration based on the + DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services should + be injected into Pod's environment variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated for + the temporary `EmptyDir` volume `/tmp`. Specify the + allocation in memory units, for example, `100Mi` for + 100 mebibytes. Default value is `5Mi`. The `/tmp` + volume is backed by pod memory, not disk storage, so + avoid setting a high value as it consumes pod memory + resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage required + for this EmptyDir volume (for example + 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to populate + the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to populate + the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: Additional volumes that can be mounted to the pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults to + `true`. When `true` or not set, the pod runs in the + host user namespace. This is required when the pod + needs features available only in the host namespace, + such as loading kernel modules with + `CAP_SYS_MODULE`.When set to `false`, the pod runs + in a new user namespace. Setting `false` helps + mitigate container breakout vulnerabilities and + allows containers to run as `root` without granting + `root` privileges on the host. This property is + alpha-level in Kubernetes and is supported only by + Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: >- + Template for Kafka Connect Build `Pods`. The build pod + is used only on Kubernetes. + buildContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: >- + Template for the Kafka Connect Build container. The + build container is used only on Kubernetes. + buildConfig: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + pullSecret: + type: string + description: >- + Container Registry Secret with the credentials for + pulling the base image. + description: >- + Template for the Kafka Connect BuildConfig used to build + new container images. The BuildConfig is used only on + OpenShift. + buildServiceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for the Kafka Connect Build service account. + jmxSecret: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: >- + Template for Secret of the Kafka Connect Cluster JMX + authentication. + description: >- + Template for Kafka Connect and Kafka MirrorMaker 2 + resources. The template allows users to specify how the + `Pods`, `Service`, and other services are generated. + build: + type: object + properties: + output: + type: object + properties: + additionalBuildOptions: + type: array + items: + type: string + description: >- + Configures additional options to pass to the `build` + command of either Kaniko or Buildah (depending on + the feature gate setting) when building a new Kafka + Connect image. Allowed Kaniko options: + --customPlatform, --custom-platform, --insecure, + --insecure-pull, --insecure-registry, --log-format, + --log-timestamp, --registry-mirror, --reproducible, + --single-snapshot, --skip-tls-verify, + --skip-tls-verify-pull, --skip-tls-verify-registry, + --verbosity, --snapshotMode, --use-new-run, + --registry-certificate, --registry-client-cert, + --ignore-path. Allowed Buildah `build` options: + --authfile, --cert-dir, --creds, --decryption-key, + --retry, --retry-delay, --tls-verify. Those options + are used only on Kubernetes, where Kaniko and + Buildah are available. They are ignored on + OpenShift. For more information, see the + link:https://github.com/GoogleContainerTools/kaniko[Kaniko + GitHub repository^] or the + link:https://github.com/containers/buildah/blob/main/docs/buildah-build.1.md[Buildah + build document^]. Changing this field does not + trigger a rebuild of the Kafka Connect image. + additionalPushOptions: + type: array + items: + type: string + description: >- + Configures additional options to pass to the Buildah + `push` command when pushing a new Connect image. + Allowed options: --authfile, --cert-dir, --creds, + --quiet, --retry, --retry-delay, --tls-verify. Those + options are used only on Kubernetes, where Buildah + is available. They are ignored on OpenShift. For + more information, see the + link:https://github.com/containers/buildah/blob/main/docs/buildah-push.1.md[Buildah + push document^]. Changing this field does not + trigger a rebuild of the Kafka Connect image. + image: + type: string + description: The name of the image which will be built. Required. + pushSecret: + type: string + description: >- + Container Registry Secret with the credentials for + pushing the newly built image. + type: + type: string + enum: + - docker + - imagestream + description: >- + Output type. Must be either `docker` for pushing the + newly build image to Docker compatible registry or + `imagestream` for pushing the image to OpenShift + ImageStream. Required. + required: + - image + - type + description: >- + Configures where should the newly built image be stored. + Required. + plugins: + type: array + items: + type: object + properties: + name: + type: string + pattern: '^[a-z0-9][-_a-z0-9]*[a-z0-9]$' + description: >- + The unique name of the connector plugin. Will be + used to generate the path where the connector + artifacts will be stored. The name has to be + unique within the KafkaConnect resource. The name + has to follow the following pattern: + `^[a-z][-_a-z0-9]*[a-z]$`. Required. + artifacts: + type: array + items: + type: object + properties: + artifact: + type: string + description: >- + Maven artifact id. Applicable to the `maven` + artifact type only. + fileName: + type: string + description: >- + Name under which the artifact will be + stored. + group: + type: string + description: >- + Maven group id. Applicable to the `maven` + artifact type only. + insecure: + type: boolean + description: >- + By default, connections using TLS are + verified to check they are secure. The + server certificate used must be valid, + trusted, and contain the server name. By + setting this option to `true`, all TLS + verification is disabled and the artifact + will be downloaded, even when the server is + considered insecure. + repository: + type: string + description: >- + Maven repository to download the artifact + from. Applicable to the `maven` artifact + type only. + sha512sum: + type: string + description: >- + SHA512 checksum of the artifact. Optional. + If specified, the checksum will be verified + while building the new container. If not + specified, the downloaded artifact will not + be verified. Not applicable to the `maven` + artifact type. + type: + type: string + enum: + - jar + - tgz + - zip + - maven + - other + description: >- + Artifact type. Currently, the supported + artifact types are `tgz`, `jar`, `zip`, + `other` and `maven`. + url: + type: string + pattern: >- + ^(https?|ftp)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]$ + description: >- + URL of the artifact which will be + downloaded. Strimzi does not do any security + scanning of the downloaded artifacts. For + security reasons, you should first verify + the artifacts manually and configure the + checksum verification to make sure the same + artifact is used in the automated build. + Required for `jar`, `zip`, `tgz` and `other` + artifacts. Not applicable to the `maven` + artifact type. + version: + type: string + description: >- + Maven version number. Applicable to the + `maven` artifact type only. + required: + - type + description: >- + List of artifacts which belong to this connector + plugin. Required. + required: + - name + - artifacts + description: >- + List of connector plugins which should be added to the + Kafka Connect. Required. + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: CPU and memory resources to reserve for the build. + required: + - output + - plugins + description: >- + Configures how the Connect container image should be built. + Optional. + plugins: + type: array + items: + type: object + properties: + name: + type: string + pattern: '^[a-z0-9][-_a-z0-9]*[a-z0-9]$' + description: >- + A unique name for the connector plugin. This name is + used to generate the mount path for the connector + artifacts. The name has to be unique within the + KafkaConnect resource. The name must be unique within + the `KafkaConnect` resource and match the pattern: + `^[a-z][-_a-z0-9]*[a-z]$`. Required. + artifacts: + type: array + items: + type: object + properties: + pullPolicy: + type: string + description: >- + Policy that determines when the container image + (OCI artifact) is pulled. + + + Possible values are: + + + * `Always`: Always pull the image. If the pull + fails, container creation fails. + + * `Never`: Never pull the image. Use only a + locally available image. Container creation + fails if the image isn’t present. + + * `IfNotPresent`: Pull the image only if it’s + not already available locally. Container + creation fails if the image isn’t present and + the pull fails. + + + Defaults to `Always` if `:latest` tag is + specified, or `IfNotPresent` otherwise. + reference: + type: string + description: >- + Reference to the container image (OCI artifact) + containing the Kafka Connect plugin. The image + is mounted as a volume and provides the plugin + binary. Required. + type: + type: string + enum: + - image + description: >- + Artifact type. Currently, the only supported + artifact type is `image`. + required: + - reference + - type + description: >- + List of artifacts associated with this connector + plugin. Required. + required: + - name + - artifacts + description: >- + List of connector plugins to mount into the `KafkaConnect` + pod. + required: + - replicas + - bootstrapServers + - groupId + - configStorageTopic + - statusStorageTopic + - offsetStorageTopic + description: The specification of the Kafka Connect cluster. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + url: + type: string + description: >- + The URL of the REST API endpoint for managing and monitoring + Kafka Connect connectors. + connectorPlugins: + type: array + items: + type: object + properties: + class: + type: string + description: The class of the connector plugin. + type: + type: string + description: >- + The type of the connector plugin. The available types + are `sink` and `source`. + version: + type: string + description: The version of the connector plugin. + description: >- + The list of connector plugins available in this Kafka + Connect deployment. + replicas: + type: integer + description: >- + The current number of pods being used to provide this + resource. + labelSelector: + type: string + description: Label selector for pods providing this resource. + description: The status of the Kafka Connect cluster. + required: + - spec + +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: strimzi-cluster-operator + labels: + app: strimzi + namespace: kafka +data: + log4j2.properties: > + name = COConfig + + monitorInterval = 30 + + + appender.console.type = Console + + appender.console.name = STDOUT + + appender.console.layout.type = PatternLayout + + appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - + %m%n + + + rootLogger.level = ${env:STRIMZI_LOG_LEVEL:-INFO} + + rootLogger.appenderRefs = stdout + + rootLogger.appenderRef.console.ref = STDOUT + + + # Kafka AdminClient logging is a bit noisy at INFO level + + logger.kafka.name = org.apache.kafka + + logger.kafka.level = WARN + + + # Keeps separate level for Netty logging -> to not be changed by the root + logger + + logger.netty.name = io.netty + + logger.netty.level = INFO + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkamirrormaker2s.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: KafkaMirrorMaker2 + listKind: KafkaMirrorMaker2List + singular: kafkamirrormaker2 + plural: kafkamirrormaker2s + shortNames: + - kmm2 + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + scale: + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas + labelSelectorPath: .status.labelSelector + additionalPrinterColumns: + - name: Desired replicas + description: The desired number of Kafka MirrorMaker 2 replicas + jsonPath: .spec.replicas + type: integer + - name: Ready + description: The state of the custom resource + jsonPath: '.status.conditions[?(@.type=="Ready")].status' + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + version: + type: string + description: >- + The Kafka Connect version. Defaults to the latest version. + Consult the user documentation to understand the process + required to upgrade or downgrade the version. + replicas: + type: integer + description: >- + The number of pods in the Kafka Connect group. Required in + the `v1` version of the Strimzi API. Defaults to `3` in the + `v1beta2` version of the Strimzi API. + image: + type: string + description: >- + The container image used for Kafka Connect pods. If no image + name is explicitly specified, it is determined based on the + `spec.version` configuration. The image names are + specifically mapped to corresponding versions in the Cluster + Operator configuration. + target: + type: object + properties: + alias: + type: string + pattern: '^[a-zA-Z0-9\._\-]{1,100}$' + description: Alias used to reference the Kafka cluster. + bootstrapServers: + type: string + description: >- + A comma-separated list of `host:port` pairs for + establishing the connection to the Kafka cluster. + groupId: + type: string + description: >- + A unique ID that identifies the Connect cluster group. + Required. + configStorageTopic: + type: string + description: >- + The name of the Kafka topic where connector + configurations are stored. Required. + statusStorageTopic: + type: string + description: >- + The name of the Kafka topic where connector and task + statuses are stored. Required. + offsetStorageTopic: + type: string + description: >- + The name of the Kafka topic where source connector + offsets are stored. Required. + tls: + type: object + properties: + trustedCertificates: + type: array + items: + type: object + properties: + secretName: + type: string + description: >- + The name of the Secret containing the + certificate. + certificate: + type: string + description: >- + The name of the file certificate in the + secret. + pattern: + type: string + description: >- + Pattern for the certificate files in the + secret. Use the + link:https://en.wikipedia.org/wiki/Glob_(programming)[_glob + syntax_] for the pattern. All files in the + secret that match the pattern are used. + oneOf: + - properties: + certificate: {} + required: + - certificate + - properties: + pattern: {} + required: + - pattern + required: + - secretName + description: Trusted certificates for TLS connection. + description: >- + TLS configuration for connecting MirrorMaker 2 + connectors to a cluster. + authentication: + type: object + properties: + certificateAndKey: + type: object + properties: + secretName: + type: string + description: >- + The name of the Secret containing the + certificate. + certificate: + type: string + description: The name of the file certificate in the Secret. + key: + type: string + description: >- + The name of the private key in the secret. The + private key must be in unencrypted PKCS #8 + format. For more information, see RFC 5208: + https://datatracker.ietf.org/doc/html/rfc5208. + required: + - secretName + - certificate + - key + description: >- + Reference to the `Secret` which holds the + certificate and private key pair. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + Configuration for the custom authentication + mechanism. Only properties with the `sasl.` and + `ssl.keystore.` prefixes are allowed. Specify other + options in the regular configuration section of the + custom resource. + passwordSecret: + type: object + properties: + secretName: + type: string + description: The name of the Secret containing the password. + password: + type: string + description: >- + The name of the key in the Secret under which + the password is stored. + required: + - secretName + - password + description: Reference to the `Secret` which holds the password. + sasl: + type: boolean + description: >- + Enable or disable SASL on this authentication + mechanism. + type: + type: string + enum: + - tls + - scram-sha-256 + - scram-sha-512 + - plain + - custom + description: >- + Specifies the authentication type. Supported types + are `tls`, `scram-sha-256`, `scram-sha-512`, + `plain`, 'oauth', and `custom`. `tls` uses TLS + client authentication and is supported only over TLS + connections. `scram-sha-256` and `scram-sha-512` use + SASL SCRAM-SHA-256 and SASL SCRAM-SHA-512 + authentication, respectively. `plain` uses SASL + PLAIN authentication. `oauth` uses SASL OAUTHBEARER + authentication. `custom` allows you to configure a + custom authentication mechanism. As of Strimzi + 0.49.0, `oauth` type is deprecated and will be + removed in the `v1` API version. Please use `custom` + type instead. + username: + type: string + description: Username used for the authentication. + required: + - type + description: >- + Authentication configuration for connecting to the + cluster. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The MirrorMaker 2 cluster config. Properties with the + following prefixes cannot be set: group.id, + config.storage.topic, offset.storage.topic, + status.storage.topic, ssl., sasl., security., listeners, + plugin.path, rest., bootstrap.servers, + consumer.interceptor.classes, + producer.interceptor.classes (with the exception of: + ssl.endpoint.identification.algorithm, + ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols). + required: + - alias + - bootstrapServers + - groupId + - configStorageTopic + - statusStorageTopic + - offsetStorageTopic + description: >- + The target Apache Kafka cluster. The target Kafka cluster is + used by the underlying Kafka Connect framework for its + internal topics. + mirrors: + type: array + items: + type: object + properties: + source: + type: object + properties: + alias: + type: string + pattern: '^[a-zA-Z0-9\._\-]{1,100}$' + description: Alias used to reference the Kafka cluster. + bootstrapServers: + type: string + description: >- + A comma-separated list of `host:port` pairs for + establishing the connection to the Kafka cluster. + tls: + type: object + properties: + trustedCertificates: + type: array + items: + type: object + properties: + secretName: + type: string + description: >- + The name of the Secret containing the + certificate. + certificate: + type: string + description: >- + The name of the file certificate in the + secret. + pattern: + type: string + description: >- + Pattern for the certificate files in the + secret. Use the + link:https://en.wikipedia.org/wiki/Glob_(programming)[_glob + syntax_] for the pattern. All files in + the secret that match the pattern are + used. + oneOf: + - properties: + certificate: {} + required: + - certificate + - properties: + pattern: {} + required: + - pattern + required: + - secretName + description: Trusted certificates for TLS connection. + description: >- + TLS configuration for connecting MirrorMaker 2 + connectors to a cluster. + authentication: + type: object + properties: + certificateAndKey: + type: object + properties: + secretName: + type: string + description: >- + The name of the Secret containing the + certificate. + certificate: + type: string + description: >- + The name of the file certificate in the + Secret. + key: + type: string + description: >- + The name of the private key in the secret. + The private key must be in unencrypted + PKCS #8 format. For more information, see + RFC 5208: + https://datatracker.ietf.org/doc/html/rfc5208. + required: + - secretName + - certificate + - key + description: >- + Reference to the `Secret` which holds the + certificate and private key pair. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + Configuration for the custom authentication + mechanism. Only properties with the `sasl.` + and `ssl.keystore.` prefixes are allowed. + Specify other options in the regular + configuration section of the custom resource. + passwordSecret: + type: object + properties: + secretName: + type: string + description: >- + The name of the Secret containing the + password. + password: + type: string + description: >- + The name of the key in the Secret under + which the password is stored. + required: + - secretName + - password + description: >- + Reference to the `Secret` which holds the + password. + sasl: + type: boolean + description: >- + Enable or disable SASL on this authentication + mechanism. + type: + type: string + enum: + - tls + - scram-sha-256 + - scram-sha-512 + - plain + - custom + description: >- + Specifies the authentication type. Supported + types are `tls`, `scram-sha-256`, + `scram-sha-512`, `plain`, 'oauth', and + `custom`. `tls` uses TLS client authentication + and is supported only over TLS connections. + `scram-sha-256` and `scram-sha-512` use SASL + SCRAM-SHA-256 and SASL SCRAM-SHA-512 + authentication, respectively. `plain` uses + SASL PLAIN authentication. `oauth` uses SASL + OAUTHBEARER authentication. `custom` allows + you to configure a custom authentication + mechanism. As of Strimzi 0.49.0, `oauth` type + is deprecated and will be removed in the `v1` + API version. Please use `custom` type instead. + username: + type: string + description: Username used for the authentication. + required: + - type + description: >- + Authentication configuration for connecting to the + cluster. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The MirrorMaker 2 cluster config. Properties with + the following prefixes cannot be set: group.id, + config.storage.topic, offset.storage.topic, + status.storage.topic, ssl., sasl., security., + listeners, plugin.path, rest., bootstrap.servers, + consumer.interceptor.classes, + producer.interceptor.classes (with the exception + of: ssl.endpoint.identification.algorithm, + ssl.cipher.suites, ssl.protocol, + ssl.enabled.protocols). + required: + - alias + - bootstrapServers + description: >- + The source Apache Kafka cluster. The source Kafka + cluster is used by the Kafka MirrorMaker 2 connectors. + sourceConnector: + type: object + properties: + tasksMax: + type: integer + minimum: 1 + description: >- + The maximum number of tasks for the Kafka + Connector. + version: + type: string + description: >- + Desired version or version range to respect when + starting the Kafka Connector. This is only + supported when using Kafka Connect version 4.1.0 + and higher. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The Kafka Connector configuration. The following + properties cannot be set: name, connector.class, + tasks.max, connector.plugin.version. + state: + type: string + enum: + - paused + - stopped + - running + description: >- + The state the connector should be in. Defaults to + running. + autoRestart: + type: object + properties: + enabled: + type: boolean + description: >- + Whether automatic restart for failed + connectors and tasks should be enabled or + disabled. + maxRestarts: + type: integer + description: >- + The maximum number of connector restarts that + the operator will try. If the connector + remains in a failed state after reaching this + limit, it must be restarted manually by the + user. Defaults to an unlimited number of + restarts. + description: >- + Automatic restart of connector and tasks + configuration. + listOffsets: + type: object + properties: + toConfigMap: + type: object + properties: + name: + type: string + description: >- + Reference to the ConfigMap where the list of + offsets will be written to. + required: + - toConfigMap + description: Configuration for listing offsets. + alterOffsets: + type: object + properties: + fromConfigMap: + type: object + properties: + name: + type: string + description: >- + Reference to the ConfigMap where the new + offsets are stored. + required: + - fromConfigMap + description: Configuration for altering offsets. + description: >- + The specification of the Kafka MirrorMaker 2 source + connector. + checkpointConnector: + type: object + properties: + tasksMax: + type: integer + minimum: 1 + description: >- + The maximum number of tasks for the Kafka + Connector. + version: + type: string + description: >- + Desired version or version range to respect when + starting the Kafka Connector. This is only + supported when using Kafka Connect version 4.1.0 + and higher. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + The Kafka Connector configuration. The following + properties cannot be set: name, connector.class, + tasks.max, connector.plugin.version. + state: + type: string + enum: + - paused + - stopped + - running + description: >- + The state the connector should be in. Defaults to + running. + autoRestart: + type: object + properties: + enabled: + type: boolean + description: >- + Whether automatic restart for failed + connectors and tasks should be enabled or + disabled. + maxRestarts: + type: integer + description: >- + The maximum number of connector restarts that + the operator will try. If the connector + remains in a failed state after reaching this + limit, it must be restarted manually by the + user. Defaults to an unlimited number of + restarts. + description: >- + Automatic restart of connector and tasks + configuration. + listOffsets: + type: object + properties: + toConfigMap: + type: object + properties: + name: + type: string + description: >- + Reference to the ConfigMap where the list of + offsets will be written to. + required: + - toConfigMap + description: Configuration for listing offsets. + alterOffsets: + type: object + properties: + fromConfigMap: + type: object + properties: + name: + type: string + description: >- + Reference to the ConfigMap where the new + offsets are stored. + required: + - fromConfigMap + description: Configuration for altering offsets. + description: >- + The specification of the Kafka MirrorMaker 2 + checkpoint connector. + topicsPattern: + type: string + description: >- + A regular expression matching the topics to be + mirrored, for example, "topic1\|topic2\|topic3". + Comma-separated lists are also supported. + topicsExcludePattern: + type: string + description: >- + A regular expression matching the topics to exclude + from mirroring. Comma-separated lists are also + supported. + groupsPattern: + type: string + description: >- + A regular expression matching the consumer groups to + be mirrored. Comma-separated lists are also supported. + groupsExcludePattern: + type: string + description: >- + A regular expression matching the consumer groups to + exclude from mirroring. Comma-separated lists are also + supported. + required: + - source + description: Configuration of the MirrorMaker 2 connectors. + resources: + type: object + properties: + claims: + type: array + items: + type: object + properties: + name: + type: string + request: + type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: >- + ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + description: >- + The maximum limits for CPU and memory resources and the + requested initial resources. + livenessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default to + 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default to + 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to + 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. + Minimum value is 1. + description: Pod liveness checking. + readinessProbe: + type: object + properties: + initialDelaySeconds: + type: integer + minimum: 0 + description: >- + The initial delay before first the health is first + checked. Default to 15 seconds. Minimum value is 0. + timeoutSeconds: + type: integer + minimum: 1 + description: >- + The timeout for each attempted health check. Default to + 5 seconds. Minimum value is 1. + periodSeconds: + type: integer + minimum: 1 + description: >- + How often (in seconds) to perform the probe. Default to + 10 seconds. Minimum value is 1. + successThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to + 1. Must be 1 for liveness. Minimum value is 1. + failureThreshold: + type: integer + minimum: 1 + description: >- + Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. + Minimum value is 1. + description: Pod readiness checking. + jvmOptions: + type: object + properties: + '-XX': + additionalProperties: + type: string + type: object + description: A map of -XX options to the JVM. + '-Xmx': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xmx option to to the JVM.' + '-Xms': + type: string + pattern: '^[0-9]+[mMgG]?$' + description: '-Xms option to to the JVM.' + gcLoggingEnabled: + type: boolean + description: >- + Specifies whether the Garbage Collection logging is + enabled. The default is false. + javaSystemProperties: + type: array + items: + type: object + properties: + name: + type: string + description: The system property name. + value: + type: string + description: The system property value. + description: >- + A map of additional system properties which will be + passed using the `-D` option to the JVM. + description: JVM Options for pods. + jmxOptions: + type: object + properties: + authentication: + type: object + properties: + type: + type: string + enum: + - password + description: >- + Authentication type. Currently the only supported + types are `password`.`password` type creates a + username and protected port with no TLS. + required: + - type + description: >- + Authentication configuration for connecting to the JMX + port. + description: JMX Options. + logging: + type: object + properties: + loggers: + additionalProperties: + type: string + type: object + description: A Map from logger name to logger level. + type: + type: string + enum: + - inline + - external + description: 'Logging type, must be either ''inline'' or ''external''.' + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing the + configuration. + description: >- + `ConfigMap` entry where the logging configuration is + stored. + required: + - type + description: Logging configuration for Kafka Connect. + clientRackInitImage: + type: string + description: >- + The image of the init container used for initializing the + `client.rack`. + rack: + type: object + properties: + envVarName: + type: string + description: >- + The name of the environment variable that defines the + rack ID. Its value sets the `broker.rack` configuration + for Kafka brokers and the `client.rack` configuration + for Kafka Connect or MirrorMaker 2. + topologyKey: + type: string + example: topology.kubernetes.io/zone + description: >- + A key that matches labels assigned to the Kubernetes + cluster nodes. The value of the label is used to set a + broker's `broker.rack` config, and the `client.rack` + config for Kafka Connect or MirrorMaker 2. + type: + type: string + enum: + - topology-label + - environment-variable + description: >- + Specifies the rack awareness type. Supported types are + `topology-label` and `environment-variable`. + `topology-label` uses a Kubernetes worker node label to + set the `broker.rack` configuration for Kafka brokers + and the `client.rack` configuration for Kafka Connect + and MirrorMaker 2. `environment-variable` uses an + environment variable to set the `broker.rack` + configuration for Kafka brokers and the `client.rack` + configuration for Kafka Connect and MirrorMaker 2. When + not specified, `topology-label` type is used by default. + description: >- + Configuration of the node label which will be used as the + `client.rack` consumer configuration. + x-kubernetes-validations: + - rule: >- + (has(self.type) && self.type != "topology-label") || + self.topologyKey != "" + message: topologyKey property is required + - rule: >- + has(self.type) == false || self.type != + "environment-variable" || self.envVarName != "" + message: envVarName property is required + metricsConfig: + type: object + properties: + type: + type: string + enum: + - jmxPrometheusExporter + - strimziMetricsReporter + description: >- + Metrics type. The supported types are + `jmxPrometheusExporter` and `strimziMetricsReporter`. + Type `jmxPrometheusExporter` uses the Prometheus JMX + Exporter to expose Kafka JMX metrics in Prometheus + format through an HTTP endpoint. Type + `strimziMetricsReporter` uses the Strimzi Metrics + Reporter to directly expose Kafka metrics in Prometheus + format through an HTTP endpoint. + valueFrom: + type: object + properties: + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: >- + Reference to the key in the ConfigMap containing the + configuration. + description: >- + ConfigMap entry where the Prometheus JMX Exporter + configuration is stored. + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: >- + A list of regex patterns to filter the metrics to + collect. Should contain at least one element. + description: Configuration values for the Strimzi Metrics Reporter. + required: + - type + description: Metrics configuration. + x-kubernetes-validations: + - rule: >- + self.type != 'jmxPrometheusExporter' || + has(self.valueFrom) + message: valueFrom property is required + tracing: + type: object + properties: + type: + type: string + enum: + - opentelemetry + description: >- + Type of the tracing used. Currently the only supported + type is `opentelemetry` for OpenTelemetry tracing. As of + Strimzi 0.37.0, `jaeger` type is not supported anymore + and this option is ignored. + required: + - type + description: The configuration of tracing in Kafka Connect. + template: + type: object + properties: + podSet: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for Kafka Connect `StrimziPodSet` resource. + pod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same namespace + to use for pulling any of the images used by this + Pod. When the `STRIMZI_IMAGE_PULL_SECRETS` + environment variable in Cluster Operator and the + `imagePullSecrets` option are specified, only the + `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and common + container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds after + the processes running in the pod are sent a + termination signal, and the time when the processes + are forcibly halted with a kill signal. Set this + value to longer than the expected cleanup time for + your process. Value must be a non-negative integer. + A zero value indicates delete immediately. You might + need to increase the grace period for very large + Kafka clusters, so that the Kafka brokers have + enough time to transfer their work to another broker + before they are terminated. Defaults to 30 seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler will + be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an optional + list of hosts and IPs that will be injected into the + Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be merged + to the generated DNS configuration based on the + DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services should + be injected into Pod's environment variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated for + the temporary `EmptyDir` volume `/tmp`. Specify the + allocation in memory units, for example, `100Mi` for + 100 mebibytes. Default value is `5Mi`. The `/tmp` + volume is backed by pod memory, not disk storage, so + avoid setting a high value as it consumes pod memory + resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage required + for this EmptyDir volume (for example + 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to populate + the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to populate + the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: Additional volumes that can be mounted to the pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults to + `true`. When `true` or not set, the pod runs in the + host user namespace. This is required when the pod + needs features available only in the host namespace, + such as loading kernel modules with + `CAP_SYS_MODULE`.When set to `false`, the pod runs + in a new user namespace. Setting `false` helps + mitigate container breakout vulnerabilities and + allows containers to run as `root` without granting + `root` privileges on the host. This property is + alpha-level in Kubernetes and is supported only by + Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: Template for Kafka Connect `Pods`. + apiService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the service. + Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`. + `SingleStack` is for a single IP family. + `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP family + on single-stack clusters. `RequireDualStack` fails + unless there are two IP families on dual-stack + configured clusters. If unspecified, Kubernetes will + choose the default value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the default + value based on the `ipFamilyPolicy` setting. + description: Template for Kafka Connect API `Service`. + headlessService: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + ipFamilyPolicy: + type: string + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + description: >- + Specifies the IP Family Policy used by the service. + Available options are `SingleStack`, + `PreferDualStack` and `RequireDualStack`. + `SingleStack` is for a single IP family. + `PreferDualStack` is for two IP families on + dual-stack configured clusters or a single IP family + on single-stack clusters. `RequireDualStack` fails + unless there are two IP families on dual-stack + configured clusters. If unspecified, Kubernetes will + choose the default value based on the service type. + ipFamilies: + type: array + items: + type: string + enum: + - IPv4 + - IPv6 + description: >- + Specifies the IP Families used by the service. + Available options are `IPv4` and `IPv6`. If + unspecified, Kubernetes will choose the default + value based on the `ipFamilyPolicy` setting. + description: Template for Kafka Connect headless `Service`. + connectContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: Template for the Kafka Connect container. + initContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: Template for the Kafka init container. + podDisruptionBudget: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + maxUnavailable: + type: integer + minimum: 0 + description: >- + Maximum number of unavailable pods to allow + automatic Pod eviction. A Pod eviction is allowed + when the `maxUnavailable` number of pods or fewer + are unavailable after the eviction. Setting this + value to 0 prevents all voluntary evictions, so the + pods must be evicted manually. Defaults to 1. + description: Template for Kafka Connect `PodDisruptionBudget`. + serviceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for the Kafka Connect service account. + clusterRoleBinding: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for the Kafka Connect ClusterRoleBinding. + buildPod: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + imagePullSecrets: + type: array + items: + type: object + properties: + name: + type: string + description: >- + List of references to secrets in the same namespace + to use for pulling any of the images used by this + Pod. When the `STRIMZI_IMAGE_PULL_SECRETS` + environment variable in Cluster Operator and the + `imagePullSecrets` option are specified, only the + `imagePullSecrets` variable is used and the + `STRIMZI_IMAGE_PULL_SECRETS` variable is ignored. + securityContext: + type: object + properties: + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + fsGroup: + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + supplementalGroups: + type: array + items: + type: integer + supplementalGroupsPolicy: + type: string + sysctls: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: >- + Configures pod-level security attributes and common + container settings. + terminationGracePeriodSeconds: + type: integer + minimum: 0 + description: >- + The grace period is the duration in seconds after + the processes running in the pod are sent a + termination signal, and the time when the processes + are forcibly halted with a kill signal. Set this + value to longer than the expected cleanup time for + your process. Value must be a non-negative integer. + A zero value indicates delete immediately. You might + need to increase the grace period for very large + Kafka clusters, so that the Kafka brokers have + enough time to transfer their work to another broker + before they are terminated. Defaults to 30 seconds. + affinity: + type: object + properties: + nodeAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + preference: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: object + properties: + nodeSelectorTerms: + type: array + items: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchFields: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + podAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + podAntiAffinity: + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + podAffinityTerm: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + weight: + type: integer + requiredDuringSchedulingIgnoredDuringExecution: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + mismatchLabelKeys: + type: array + items: + type: string + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + namespaces: + type: array + items: + type: string + topologyKey: + type: string + description: The pod's affinity rules. + tolerations: + type: array + items: + type: object + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + type: integer + value: + type: string + description: The pod's tolerations. + topologySpreadConstraints: + type: array + items: + type: object + properties: + labelSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + type: string + values: + type: array + items: + type: string + matchLabels: + additionalProperties: + type: string + type: object + matchLabelKeys: + type: array + items: + type: string + maxSkew: + type: integer + minDomains: + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + description: The pod's topology spread constraints. + priorityClassName: + type: string + description: >- + The name of the priority class used to assign + priority to the pods. + schedulerName: + type: string + description: >- + The name of the scheduler used to dispatch this + `Pod`. If not specified, the default scheduler will + be used. + hostAliases: + type: array + items: + type: object + properties: + hostnames: + type: array + items: + type: string + ip: + type: string + description: >- + The pod's HostAliases. HostAliases is an optional + list of hosts and IPs that will be injected into the + Pod's hosts file if specified. + dnsPolicy: + type: string + enum: + - ClusterFirst + - ClusterFirstWithHostNet + - Default + - None + description: >- + The pod's DNSPolicy. Defaults to `ClusterFirst`. + Valid values are `ClusterFirstWithHostNet`, + `ClusterFirst`, `Default` or `None`. + dnsConfig: + type: object + properties: + nameservers: + type: array + items: + type: string + options: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + searches: + type: array + items: + type: string + description: >- + The pod's DNSConfig. If specified, it will be merged + to the generated DNS configuration based on the + DNSPolicy. + enableServiceLinks: + type: boolean + description: >- + Indicates whether information about services should + be injected into Pod's environment variables. + tmpDirSizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + Defines the total amount of pod memory allocated for + the temporary `EmptyDir` volume `/tmp`. Specify the + allocation in memory units, for example, `100Mi` for + 100 mebibytes. Default value is `5Mi`. The `/tmp` + volume is backed by pod memory, not disk storage, so + avoid setting a high value as it consumes pod memory + resources. + volumes: + type: array + items: + type: object + properties: + name: + type: string + description: Name to use for the volume. Required. + secret: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + optional: + type: boolean + secretName: + type: string + description: '`Secret` to use to populate the volume.' + configMap: + type: object + properties: + defaultMode: + type: integer + items: + type: array + items: + type: object + properties: + key: + type: string + mode: + type: integer + path: + type: string + name: + type: string + optional: + type: boolean + description: '`ConfigMap` to use to populate the volume.' + emptyDir: + type: object + properties: + medium: + type: string + enum: + - Memory + description: >- + Medium represents the type of storage + medium should back this volume. Valid + values are unset or `Memory`. When not + set, it will use the node's default + medium. + sizeLimit: + type: string + pattern: '^([0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$' + description: >- + The total amount of local storage required + for this EmptyDir volume (for example + 1Gi). + description: '`EmptyDir` to use to populate the volume.' + persistentVolumeClaim: + type: object + properties: + claimName: + type: string + readOnly: + type: boolean + description: >- + `PersistentVolumeClaim` object to use to + populate the volume. + csi: + type: object + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + type: object + properties: + name: + type: string + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + description: >- + `CSIVolumeSource` object to use to populate + the volume. + image: + type: object + properties: + pullPolicy: + type: string + reference: + type: string + description: >- + `ImageVolumeSource` object to use to populate + the volume. + oneOf: + - properties: + secret: {} + configMap: {} + emptyDir: {} + persistentVolumeClaim: {} + csi: {} + image: {} + description: Additional volumes that can be mounted to the pod. + hostUsers: + type: boolean + description: >- + Use the host user namespace. Optional. Defaults to + `true`. When `true` or not set, the pod runs in the + host user namespace. This is required when the pod + needs features available only in the host namespace, + such as loading kernel modules with + `CAP_SYS_MODULE`.When set to `false`, the pod runs + in a new user namespace. Setting `false` helps + mitigate container breakout vulnerabilities and + allows containers to run as `root` without granting + `root` privileges on the host. This property is + alpha-level in Kubernetes and is supported only by + Kubernetes clusters that enable the + `UserNamespacesSupport` feature. + description: >- + Template for Kafka Connect Build `Pods`. The build pod + is used only on Kubernetes. + buildContainer: + type: object + properties: + env: + type: array + items: + type: object + properties: + name: + type: string + description: The environment variable key. + value: + type: string + description: The environment variable value. + valueFrom: + type: object + properties: + secretKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a secret. + configMapKeyRef: + type: object + properties: + key: + type: string + name: + type: string + optional: + type: boolean + description: Reference to a key in a config map. + oneOf: + - properties: + secretKeyRef: {} + required: + - secretKeyRef + - properties: + configMapKeyRef: {} + required: + - configMapKeyRef + description: >- + Reference to the secret or config map property + to which the environment variable is set. + oneOf: + - properties: + value: {} + required: + - value + - properties: + valueFrom: {} + required: + - valueFrom + description: >- + Environment variables which should be applied to the + container. + securityContext: + type: object + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + capabilities: + type: object + properties: + add: + type: array + items: + type: string + drop: + type: array + items: + type: string + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + runAsUser: + type: integer + seLinuxOptions: + type: object + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + seccompProfile: + type: object + properties: + localhostProfile: + type: string + type: + type: string + windowsOptions: + type: object + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + description: Security context for the container. + volumeMounts: + type: array + items: + type: object + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + description: >- + Additional volume mounts which should be applied to + the container. + description: >- + Template for the Kafka Connect Build container. The + build container is used only on Kubernetes. + buildConfig: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: >- + Metadata to apply to the + `PodDisruptionBudgetTemplate` resource. + pullSecret: + type: string + description: >- + Container Registry Secret with the credentials for + pulling the base image. + description: >- + Template for the Kafka Connect BuildConfig used to build + new container images. The BuildConfig is used only on + OpenShift. + buildServiceAccount: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: Template for the Kafka Connect Build service account. + jmxSecret: + type: object + properties: + metadata: + type: object + properties: + labels: + additionalProperties: + type: string + type: object + description: Labels added to the Kubernetes resource. + annotations: + additionalProperties: + type: string + type: object + description: Annotations added to the Kubernetes resource. + description: Metadata applied to the resource. + description: >- + Template for Secret of the Kafka Connect Cluster JMX + authentication. + description: >- + Template for Kafka Connect and Kafka MirrorMaker 2 + resources. The template allows users to specify how the + `Pods`, `Service`, and other services are generated. + required: + - replicas + - target + - mirrors + description: The specification of the Kafka MirrorMaker 2 cluster. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + url: + type: string + description: >- + The URL of the REST API endpoint for managing and monitoring + Kafka Connect connectors. + connectors: + type: array + items: + x-kubernetes-preserve-unknown-fields: true + type: object + description: >- + List of MirrorMaker 2 connector statuses, as reported by the + Kafka Connect REST API. + autoRestartStatuses: + type: array + items: + type: object + properties: + count: + type: integer + description: >- + The number of times the connector or task is + restarted. + connectorName: + type: string + description: The name of the connector being restarted. + lastRestartTimestamp: + type: string + description: >- + The last time the automatic restart was attempted. The + required format is 'yyyy-MM-ddTHH:mm:ssZ' in the UTC + time zone. + description: List of MirrorMaker 2 connector auto restart statuses. + connectorPlugins: + type: array + items: + type: object + properties: + class: + type: string + description: The class of the connector plugin. + type: + type: string + description: >- + The type of the connector plugin. The available types + are `sink` and `source`. + version: + type: string + description: The version of the connector plugin. + description: >- + The list of connector plugins available in this Kafka + Connect deployment. + labelSelector: + type: string + description: Label selector for pods providing this resource. + replicas: + type: integer + description: >- + The current number of pods being used to provide this + resource. + description: The status of the Kafka MirrorMaker 2 cluster. + required: + - spec + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kafkatopics.kafka.strimzi.io + labels: + app: strimzi + strimzi.io/crd-install: 'true' +spec: + group: kafka.strimzi.io + names: + kind: KafkaTopic + listKind: KafkaTopicList + singular: kafkatopic + plural: kafkatopics + shortNames: + - kt + categories: + - strimzi + scope: Namespaced + conversion: + strategy: None + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Cluster + description: The name of the Kafka cluster this topic belongs to + jsonPath: .metadata.labels.strimzi\.io/cluster + type: string + - name: Partitions + description: The desired number of partitions in the topic + jsonPath: .spec.partitions + type: integer + - name: Replication factor + description: The desired number of replicas of each partition + jsonPath: .spec.replicas + type: integer + - name: Ready + description: The state of the custom resource + jsonPath: '.status.conditions[?(@.type=="Ready")].status' + type: string + schema: + openAPIV3Schema: + type: object + properties: + apiVersion: + type: string + description: >- + APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + kind: + type: string + description: >- + Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + metadata: + type: object + spec: + type: object + properties: + topicName: + type: string + description: >- + The name of the topic. When absent this will default to the + metadata.name of the topic. It is recommended to not set + this unless the topic name is not a valid Kubernetes + resource name. + partitions: + type: integer + minimum: 1 + description: >- + The number of partitions the topic should have. This cannot + be decreased after topic creation. It can be increased after + topic creation, but it is important to understand the + consequences that has, especially for topics with semantic + partitioning. When absent this will default to the broker + configuration for `num.partitions`. + replicas: + type: integer + minimum: 1 + maximum: 32767 + description: >- + The number of replicas the topic should have. When absent + this will default to the broker configuration for + `default.replication.factor`. + config: + x-kubernetes-preserve-unknown-fields: true + type: object + description: The topic configuration. + description: The specification of the topic. + status: + type: object + properties: + conditions: + type: array + items: + type: object + properties: + type: + type: string + description: >- + The unique identifier of a condition, used to + distinguish between other conditions in the resource. + status: + type: string + description: >- + The status of the condition, either True, False or + Unknown. + lastTransitionTime: + type: string + description: >- + Last time the condition of a type changed from one + status to another. The required format is + 'yyyy-MM-ddTHH:mm:ssZ', in the UTC time zone. + reason: + type: string + description: >- + The reason for the condition's last transition (a + single word in CamelCase). + message: + type: string + description: >- + Human-readable message indicating details about the + condition's last transition. + description: List of status conditions. + observedGeneration: + type: integer + description: >- + The generation of the CRD that was last reconciled by the + operator. + topicName: + type: string + description: Topic name. + topicId: + type: string + description: >- + The topic's id. For a KafkaTopic with the ready condition, + this will change only if the topic gets deleted and + recreated with the same name. + replicasChange: + type: object + properties: + targetReplicas: + type: integer + description: >- + The target replicas value requested by the user. This + may be different from .spec.replicas when a change is + ongoing. + state: + type: string + enum: + - pending + - ongoing + description: >- + Current state of the replicas change operation. This can + be `pending`, when the change has been requested, or + `ongoing`, when the change has been successfully + submitted to Cruise Control. + message: + type: string + description: >- + Message for the user related to the replicas change + request. This may contain transient error messages that + would disappear on periodic reconciliations. + sessionId: + type: string + description: >- + The session identifier for replicas change requests + pertaining to this KafkaTopic resource. This is used by + the Topic Operator to track the status of `ongoing` + replicas change operations. + description: Replication factor change status. + description: The status of the topic. + required: + - spec + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: strimzi-cluster-operator + labels: + app: strimzi + namespace: kafka From 2b3db9fc3e95094e6f313562683191634337dfa4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 09:08:12 +0000 Subject: [PATCH 123/192] chore: bump org.sonatype.central:central-publishing-maven-plugin Bumps [org.sonatype.central:central-publishing-maven-plugin](https://github.com/sonatype/central-publishing-maven-plugin) from 0.8.0 to 0.10.0. - [Commits](https://github.com/sonatype/central-publishing-maven-plugin/commits) --- updated-dependencies: - dependency-name: org.sonatype.central:central-publishing-maven-plugin dependency-version: 0.10.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c33efb934..dd1561031 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ 3.8.0 3.2.4 4.2.1 - 0.8.0 + 0.10.0 5.0.3 2.14.0 4.1.0 From 1114c81edb8f8df6aada981adde529ed8010a9c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 08:53:55 +0200 Subject: [PATCH 124/192] chore: bump amannn/action-semantic-pull-request from 5.5.3 to 6.1.1 (#827) Bumps [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) from 5.5.3 to 6.1.1. - [Release notes](https://github.com/amannn/action-semantic-pull-request/releases) - [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/main/CHANGELOG.md) - [Commits](https://github.com/amannn/action-semantic-pull-request/compare/v5.5.3...v6.1.1) --- updated-dependencies: - dependency-name: amannn/action-semantic-pull-request dependency-version: 6.1.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/conventional-commits.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml index d23da45d7..2072f1e9e 100644 --- a/.github/workflows/conventional-commits.yml +++ b/.github/workflows/conventional-commits.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: semantic-pull-request - uses: amannn/action-semantic-pull-request@v5.5.3 + uses: amannn/action-semantic-pull-request@v6.1.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: From 873ba93d3d864c73f0f8ec1c424f6558a63fb2a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 08:54:27 +0200 Subject: [PATCH 125/192] chore: bump actions/setup-java from 4 to 5 (#822) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4 to 5. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-and-test.yml | 2 +- .github/workflows/build-with-release-profile-run.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 69cc8a178..e006efa09 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v6 - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: ${{ matrix.java-version }} distribution: 'temurin' diff --git a/.github/workflows/build-with-release-profile-run.yml b/.github/workflows/build-with-release-profile-run.yml index 83cace348..c379111ee 100644 --- a/.github/workflows/build-with-release-profile-run.yml +++ b/.github/workflows/build-with-release-profile-run.yml @@ -75,7 +75,7 @@ jobs: ref: ${{ steps.pr_info.outputs.pr_sha }} - name: Set up JDK 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: '17' distribution: 'temurin' From 215c383be7ff6b4f60183bca6466666ba9f126bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 08:55:39 +0200 Subject: [PATCH 126/192] chore: bump actions/github-script from 7 to 9 (#823) Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v7...v9) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: '9' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-with-release-profile-run.yml | 4 ++-- .github/workflows/create-github-release.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-with-release-profile-run.yml b/.github/workflows/build-with-release-profile-run.yml index c379111ee..3306cb604 100644 --- a/.github/workflows/build-with-release-profile-run.yml +++ b/.github/workflows/build-with-release-profile-run.yml @@ -54,7 +54,7 @@ jobs: - name: Report pending status to PR if: steps.pr_info.outputs.pr_sha - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | await github.rest.repos.createCommitStatus({ @@ -125,7 +125,7 @@ jobs: - name: Report status to PR if: always() && steps.pr_info.outputs.pr_sha - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | const state = '${{ job.status }}' === 'success' ? 'success' : 'failure'; diff --git a/.github/workflows/create-github-release.yml b/.github/workflows/create-github-release.yml index c86b139a5..11faf4717 100644 --- a/.github/workflows/create-github-release.yml +++ b/.github/workflows/create-github-release.yml @@ -29,7 +29,7 @@ jobs: - name: Generate release notes id: release_notes - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | const version = '${{ steps.version.outputs.version }}'; @@ -86,7 +86,7 @@ jobs: return releaseNotes; - name: Create GitHub Release - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | const version = '${{ steps.version.outputs.version }}'; From 3d6cc30d0a5a2dfd5e7476d2c490ffb00e72b5c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 08:56:35 +0200 Subject: [PATCH 127/192] chore: bump googleapis/release-please-action from 4 to 5 (#824) Bumps [googleapis/release-please-action](https://github.com/googleapis/release-please-action) from 4 to 5. - [Release notes](https://github.com/googleapis/release-please-action/releases) - [Changelog](https://github.com/googleapis/release-please-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/release-please-action/compare/v4...v5) --- updated-dependencies: - dependency-name: googleapis/release-please-action dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-please.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index a38b0f7be..a609f92d5 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -13,7 +13,7 @@ jobs: release-please: runs-on: ubuntu-latest steps: - - uses: googleapis/release-please-action@v4 + - uses: googleapis/release-please-action@v5 with: token: ${{ secrets.A2A_BOT_PAT }} release-type: java From a1f91640beb4c65e84c1a71043134bb8605a58ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:11:22 +0200 Subject: [PATCH 128/192] chore: bump crazy-max/ghaction-import-gpg from 6 to 7 (#821) Bumps [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) from 6 to 7. - [Release notes](https://github.com/crazy-max/ghaction-import-gpg/releases) - [Commits](https://github.com/crazy-max/ghaction-import-gpg/compare/v6...v7) --- updated-dependencies: - dependency-name: crazy-max/ghaction-import-gpg dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-with-release-profile-run.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-with-release-profile-run.yml b/.github/workflows/build-with-release-profile-run.yml index 3306cb604..958727163 100644 --- a/.github/workflows/build-with-release-profile-run.yml +++ b/.github/workflows/build-with-release-profile-run.yml @@ -83,7 +83,7 @@ jobs: # Use secrets to import GPG key - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@v6 + uses: crazy-max/ghaction-import-gpg@v7 with: gpg_private_key: ${{ secrets.GPG_SIGNING_KEY }} passphrase: ${{ secrets.GPG_SIGNING_PASSPHRASE }} From 2752fa394130e53b42d2c48be9ee1e0c09664aae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:24:14 +0200 Subject: [PATCH 129/192] chore: bump the maven-plugins group with 7 updates (#830) Bumps the maven-plugins group with 7 updates: | Package | From | To | | --- | --- | --- | | [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) | `3.14.1` | `3.15.0` | | [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.1.2` | `3.5.5` | | [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) | `3.4.2` | `3.5.0` | | [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) | `3.3.1` | `3.4.0` | | [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) | `3.8.0` | `3.12.0` | | [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) | `3.2.4` | `3.2.8` | | [org.apache.maven.plugins:maven-invoker-plugin](https://github.com/apache/maven-invoker-plugin) | `3.8.0` | `3.10.0` | Updates `org.apache.maven.plugins:maven-compiler-plugin` from 3.14.1 to 3.15.0 - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.14.1...maven-compiler-plugin-3.15.0) Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.1.2 to 3.5.5 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.5.5) Updates `org.apache.maven.plugins:maven-jar-plugin` from 3.4.2 to 3.5.0 - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.2...maven-jar-plugin-3.5.0) Updates `org.apache.maven.plugins:maven-source-plugin` from 3.3.1 to 3.4.0 - [Release notes](https://github.com/apache/maven-source-plugin/releases) - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.1...maven-source-plugin-3.4.0) Updates `org.apache.maven.plugins:maven-javadoc-plugin` from 3.8.0 to 3.12.0 - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.8.0...maven-javadoc-plugin-3.12.0) Updates `org.apache.maven.plugins:maven-gpg-plugin` from 3.2.4 to 3.2.8 - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.4...maven-gpg-plugin-3.2.8) Updates `org.apache.maven.plugins:maven-invoker-plugin` from 3.8.0 to 3.10.0 - [Release notes](https://github.com/apache/maven-invoker-plugin/releases) - [Commits](https://github.com/apache/maven-invoker-plugin/compare/maven-invoker-plugin-3.8.0...maven-invoker-plugin-3.10.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-version: 3.15.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-version: 3.5.5 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins - dependency-name: org.apache.maven.plugins:maven-jar-plugin dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-version: 3.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-version: 3.12.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-version: 3.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: maven-plugins - dependency-name: org.apache.maven.plugins:maven-invoker-plugin dependency-version: 3.10.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven-plugins ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- pom.xml | 12 ++++++------ reference/rest/pom.xml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 9d5defe72..799a09dde 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -97,7 +97,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.8.0 + 3.10.0 ${project.build.directory}/it ${project.build.directory}/local-repo diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 6314ca466..f1efe016e 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -83,7 +83,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.8.0 + 3.10.0 ${project.build.directory}/it ${project.build.directory}/local-repo diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index d907539d9..c0f0da9a2 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -235,7 +235,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.8.0 + 3.10.0 ${project.build.directory}/it ${project.build.directory}/local-repo diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 88bec8cfb..7576207ed 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -28,7 +28,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.14.1 + 3.15.0 diff --git a/pom.xml b/pom.xml index c33efb934..600029034 100644 --- a/pom.xml +++ b/pom.xml @@ -41,13 +41,13 @@ 1.77.0 UTF-8 3.5.0 - 3.14.1 + 3.15.0 3.6.2 3.4.2 - 3.3.1 - 3.1.2 - 3.8.0 - 3.2.4 + 3.4.0 + 3.5.5 + 3.12.0 + 3.2.8 4.2.1 0.8.0 5.0.3 @@ -461,7 +461,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.4.2 + 3.5.0 io.quarkus diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index eb917df8d..d9429ba98 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -112,7 +112,7 @@ maven-surefire-plugin - 3.5.4 + 3.5.5 org.jboss.logmanager.LogManager From 84b7562ccdbfaf4a17b532e2b26c4a30af1a6e23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 10:20:37 +0200 Subject: [PATCH 130/192] chore: bump actions/upload-artifact from 6 to 7 (#826) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-and-test.yml | 4 ++-- .github/workflows/build-with-release-profile.yml | 2 +- .github/workflows/run-tck.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index e006efa09..78cd467f3 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -29,7 +29,7 @@ jobs: run: mvn -B package --file pom.xml -fae - name: Upload Test Reports if: failure() - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: surefire-reports-java-${{ matrix.java-version }} path: | @@ -39,7 +39,7 @@ jobs: if-no-files-found: warn - name: Upload Build Logs if: failure() - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: build-logs-java-${{ matrix.java-version }} path: | diff --git a/.github/workflows/build-with-release-profile.yml b/.github/workflows/build-with-release-profile.yml index 70737fca9..305de985d 100644 --- a/.github/workflows/build-with-release-profile.yml +++ b/.github/workflows/build-with-release-profile.yml @@ -43,7 +43,7 @@ jobs: cat pr_info/* - name: Upload PR info - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: pr-info path: pr_info/ diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index d0a0212be..8184cdc2b 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -119,7 +119,7 @@ jobs: sleep 2 - name: Upload TCK Reports if: always() - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: tck-reports-java-${{ matrix.java-version }} path: a2a-tck/reports/ From 8327d00d138757daf7e6b08972575a0809a75039 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 29 Apr 2026 14:17:19 +0200 Subject: [PATCH 131/192] chore: Upgrading NullAway to 0.13.4 and error prone to 2.49.0 Signed-off-by: Emmanuel Hugonnet --- pom.xml | 4 ++-- .../a2aproject/sdk/server/events/MainEventBusProcessor.java | 3 +-- .../sdk/server/requesthandlers/DefaultRequestHandler.java | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 600029034..48e69372c 100644 --- a/pom.xml +++ b/pom.xml @@ -70,8 +70,8 @@ 2.0.17 1.5.18 1.21.4 - 2.47.0 - 0.13.1 + 2.49.0 + 0.13.4 -XDaddTypeAnnotationsToSymbol=true -Xplugin:ErrorProne -XepDisableAllChecks -Xep:NullAway:ERROR -Xep:RequireExplicitNullMarking:WARN -XepOpt:NullAway:ExhaustiveOverride=true -XepOpt:NullAway:OnlyNullMarked=true -XepOpt:NullAway:JSpecifyMode=true -XepExcludedPaths:.*/src/test/.* -XepDisableWarningsInGeneratedCode diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java index 3b5019856..9bb9b9c26 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java @@ -14,10 +14,8 @@ import org.a2aproject.sdk.server.tasks.TaskSerializationException; import org.a2aproject.sdk.server.tasks.TaskStore; import org.a2aproject.sdk.spec.A2AError; -import org.a2aproject.sdk.spec.A2AServerException; import org.a2aproject.sdk.spec.Event; import org.a2aproject.sdk.spec.InternalError; -import org.a2aproject.sdk.spec.Message; import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.StreamingEventKind; import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; @@ -134,6 +132,7 @@ public void setPushNotificationExecutor(java.util.concurrent.Executor executor) this.pushNotificationExecutor = executor; } + @SuppressWarnings("NullAway.Init") @PostConstruct void start() { processorThread = new Thread(this, "MainEventBusProcessor"); diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java index 3cf09abc6..71aab7e94 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java @@ -66,7 +66,6 @@ import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskQueryParams; import org.a2aproject.sdk.spec.TaskState; -import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; @@ -270,6 +269,7 @@ public DefaultRequestHandler(AgentExecutor agentExecutor, TaskStore taskStore, this.requestContextBuilder = () -> new SimpleRequestContextBuilder(taskStore, false); } + @SuppressWarnings("NullAway.Init") @PostConstruct void initConfig() { agentCompletionTimeoutSeconds = Integer.parseInt( From de2ddc69b87d26cfdeccf915f1005c000d3bfb2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 01:06:25 +0000 Subject: [PATCH 132/192] chore: bump groovy.version from 5.0.3 to 5.0.5 Bumps `groovy.version` from 5.0.3 to 5.0.5. Updates `org.apache.groovy:groovy` from 5.0.3 to 5.0.5 - [Commits](https://github.com/apache/groovy/commits) Updates `org.apache.groovy:groovy-ant` from 5.0.3 to 5.0.5 - [Commits](https://github.com/apache/groovy/commits) --- updated-dependencies: - dependency-name: org.apache.groovy:groovy dependency-version: 5.0.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.groovy:groovy-ant dependency-version: 5.0.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 48e69372c..2118386a2 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 3.2.8 4.2.1 0.8.0 - 5.0.3 + 5.0.5 2.14.0 4.1.0 2.0.1 From b8a616930c7336d68a909136575eb1ea523523eb Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 23 Apr 2026 13:54:09 +0100 Subject: [PATCH 133/192] feat: Migrate Reactive Routes to Vert.X Web and add security tests --- .../interceptors/auth/AuthInterceptor.java | 12 +- .../auth/AuthInterceptorTest.java | 15 + .../opentelemetry/integration-tests/pom.xml | 4 +- .../opentelemetry/it/A2ATestRoutes.java | 74 ++-- .../it/OpenTelemetryA2ABaseTest.java | 3 +- .../pom.xml | 5 - extras/task-store-database-jpa/pom.xml | 5 - .../sdk/client/http/JdkA2AHttpClient.java | 14 + reference/common/pom.xml | 18 +- .../common/quarkus/VertxSecurityHelper.java | 160 +++++++++ reference/grpc/pom.xml | 16 + .../server/grpc/quarkus/A2ATestResource.java | 2 + .../server/grpc/quarkus/AuthTestProfile.java | 47 +++ .../quarkus/QuarkusA2AGrpcWithAuthTest.java | 128 +++++++ .../quarkus/TestAuthorizationController.java | 34 ++ reference/jsonrpc/README.md | 2 +- reference/jsonrpc/pom.xml | 20 +- .../server/apps/quarkus/A2AServerRoutes.java | 94 +++-- .../server/apps/quarkus/A2ATestRoutes.java | 128 +++++-- .../server/apps/quarkus/AuthTestProfile.java | 47 +++ .../QuarkusA2AJSONRPCWithAuthJdkTest.java | 65 ++++ .../QuarkusA2AJSONRPCWithAuthVertxTest.java | 70 ++++ .../apps/quarkus/TestIdentityProvider.java | 37 ++ .../src/test/resources/application.properties | 7 + reference/rest/README.md | 2 +- reference/rest/pom.xml | 21 +- .../server/rest/quarkus/A2AServerRoutes.java | 179 ++++++++-- .../sdk/server/rest/quarkus/package-info.java | 4 +- .../server/rest/quarkus/A2ATestRoutes.java | 158 +++++++-- .../server/rest/quarkus/AuthTestProfile.java | 48 +++ .../QuarkusA2ARestWithAuthJdkTest.java | 77 ++++ .../QuarkusA2ARestWithAuthVertxTest.java | 78 ++++ .../rest/quarkus/TestIdentityProvider.java | 37 ++ .../src/test/resources/application.properties | 9 +- .../common/AbstractA2AServerWithAuthTest.java | 332 ++++++++++++++++++ .../server/apps/common/AgentCardProducer.java | 21 ++ .../transport/grpc/handler/GrpcHandler.java | 28 +- 37 files changed, 1841 insertions(+), 160 deletions(-) create mode 100644 reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java create mode 100644 reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/AuthTestProfile.java create mode 100644 reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcWithAuthTest.java create mode 100644 reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/TestAuthorizationController.java create mode 100644 reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/AuthTestProfile.java create mode 100644 reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthJdkTest.java create mode 100644 reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthVertxTest.java create mode 100644 reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/TestIdentityProvider.java create mode 100644 reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/AuthTestProfile.java create mode 100644 reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthJdkTest.java create mode 100644 reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthVertxTest.java create mode 100644 reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/TestIdentityProvider.java create mode 100644 tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerWithAuthTest.java diff --git a/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptor.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptor.java index a946ce9d0..21eb6f02d 100644 --- a/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptor.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptor.java @@ -24,8 +24,10 @@ public class AuthInterceptor extends ClientCallInterceptor { private static final String BEARER_SCHEME = "bearer"; + private static final String BASIC_SCHEME = "basic"; public static final String AUTHORIZATION = "Authorization"; private static final String BEARER = "Bearer "; + private static final String BASIC = "Basic "; private final CredentialService credentialService; public AuthInterceptor(final CredentialService credentialService) { @@ -51,9 +53,13 @@ public PayloadAndHeaders intercept(String methodName, @Nullable Object payload, continue; } if (securityScheme instanceof HTTPAuthSecurityScheme httpAuthSecurityScheme) { - if (httpAuthSecurityScheme.scheme().toLowerCase(Locale.ROOT).equals(BEARER_SCHEME)) { + String scheme = httpAuthSecurityScheme.scheme().toLowerCase(Locale.ROOT); + if (scheme.equals(BEARER_SCHEME)) { updatedHeaders.put(AUTHORIZATION, getBearerValue(credential)); return new PayloadAndHeaders(payload, updatedHeaders); + } else if (scheme.equals(BASIC_SCHEME)) { + updatedHeaders.put(AUTHORIZATION, getBasicValue(credential)); + return new PayloadAndHeaders(payload, updatedHeaders); } } else if (securityScheme instanceof OAuth2SecurityScheme || securityScheme instanceof OpenIdConnectSecurityScheme) { @@ -72,4 +78,8 @@ public PayloadAndHeaders intercept(String methodName, @Nullable Object payload, private static String getBearerValue(String credential) { return BEARER + credential; } + + private static String getBasicValue(String credential) { + return BASIC + credential; + } } diff --git a/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptorTest.java b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptorTest.java index b59f16329..b8195149f 100644 --- a/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptorTest.java +++ b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/interceptors/auth/AuthInterceptorTest.java @@ -129,6 +129,21 @@ public void testBearerSecurityScheme() { testSecurityScheme(authTestCase); } + @Test + public void testBasicAuthSecurityScheme() { + // Credential should be pre-encoded base64("testuser:testpass") = "dGVzdHVzZXI6dGVzdHBhc3M=" + AuthTestCase authTestCase = new AuthTestCase( + "http://agent.com/rpc", + "session-id", + "basic", + "dGVzdHVzZXI6dGVzdHBhc3M=", + new HTTPAuthSecurityScheme(null, "basic", "HTTP Basic authentication"), + "Authorization", + "Basic dGVzdHVzZXI6dGVzdHBhc3M=" + ); + testSecurityScheme(authTestCase); + } + private void testSecurityScheme(AuthTestCase authTestCase) { credentialStore.setCredential(authTestCase.sessionId, authTestCase.schemeName, authTestCase.credential); diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index d51edb70e..c9085d121 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -40,10 +40,10 @@ quarkus-opentelemetry - + io.quarkus - quarkus-reactive-routes + quarkus-vertx-http diff --git a/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java index c2640ef8f..ac3952d4b 100644 --- a/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java +++ b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java @@ -18,11 +18,11 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.opentelemetry.sdk.trace.data.SpanData; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Param; -import io.quarkus.vertx.web.Route; +import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -48,8 +48,47 @@ public class A2ATestRoutes { @Inject Tracer tracer; - @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void saveTask(@Body String body, RoutingContext rc) { + void setupRoutes(@Observes Router router) { + router.post("/test/task") + .consumes(APPLICATION_JSON) + .blockingHandler(ctx -> saveTask(ctx.body().asString(), ctx)); + + router.get("/test/task/:taskId") + .produces(APPLICATION_JSON) + .blockingHandler(ctx -> getTask(ctx.pathParam("taskId"), ctx)); + + router.delete("/test/task/:taskId") + .blockingHandler(ctx -> deleteTask(ctx.pathParam("taskId"), ctx)); + + router.post("/test/queue/ensure/:taskId") + .handler(ctx -> ensureTaskQueue(ctx.pathParam("taskId"), ctx)); + + router.post("/test/queue/enqueueTaskStatusUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> enqueueTaskStatusUpdateEvent(ctx.pathParam("taskId"), ctx.body().asString(), ctx)); + + router.post("/test/queue/enqueueTaskArtifactUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> enqueueTaskArtifactUpdateEvent(ctx.pathParam("taskId"), ctx.body().asString(), ctx)); + + router.get("/test/queue/childCount/:taskId") + .produces(TEXT_PLAIN) + .handler(ctx -> getChildQueueCount(ctx.pathParam("taskId"), ctx)); + + router.get("/hello") + .produces(TEXT_PLAIN) + .handler(ctx -> hello(ctx)); + + router.get("/export") + .produces(APPLICATION_JSON) + .handler(ctx -> exportSpans(ctx)); + + router.get("/reset") + .produces(TEXT_PLAIN) + .handler(ctx -> reset(ctx)); + } + + public void saveTask(String body, RoutingContext rc) { try { Task task = JsonUtil.fromJson(body, Task.class); testUtilsBean.saveTask(task); @@ -61,8 +100,7 @@ public void saveTask(@Body String body, RoutingContext rc) { } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void getTask(@Param String taskId, RoutingContext rc) { + public void getTask(String taskId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -81,8 +119,7 @@ public void getTask(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTask(@Param String taskId, RoutingContext rc) { + public void deleteTask(String taskId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -100,8 +137,7 @@ public void deleteTask(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) - public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { + public void ensureTaskQueue(String taskId, RoutingContext rc) { try { testUtilsBean.ensureQueue(taskId); rc.response() @@ -112,8 +148,7 @@ public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + public void enqueueTaskStatusUpdateEvent(String taskId, String body, RoutingContext rc) { try { TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); testUtilsBean.enqueueEvent(taskId, event); @@ -125,8 +160,7 @@ public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body } } - @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + public void enqueueTaskArtifactUpdateEvent(String taskId, String body, RoutingContext rc) { try { TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); testUtilsBean.enqueueEvent(taskId, event); @@ -138,15 +172,13 @@ public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String bo } } - @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getChildQueueCount(@Param String taskId, RoutingContext rc) { + public void getChildQueueCount(String taskId, RoutingContext rc) { int count = testUtilsBean.getChildQueueCount(taskId); rc.response() .setStatusCode(200) .end(String.valueOf(count)); } - @Route(path = "/hello", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) public void hello(RoutingContext rc) { Span span = tracer.spanBuilder("hello").startSpan(); try (Scope scope = span.makeCurrent()) { @@ -159,8 +191,7 @@ public void hello(RoutingContext rc) { } } - @Route(path = "/export", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}) - public void exportSpans(@Param String taskId, RoutingContext rc) { + public void exportSpans(RoutingContext rc) { List spans = inMemorySpanExporter.getFinishedSpanItems() .stream() .filter(sd -> !sd.getName().contains("export") && !sd.getName().contains("reset")) @@ -202,8 +233,7 @@ private JsonElement serialize(List spanDatas) { return spans; } - @Route(path = "/reset", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void reset(@Param String taskId, RoutingContext rc) { + public void reset(RoutingContext rc) { inMemorySpanExporter.reset(); rc.response().setStatusCode(200).end(); } diff --git a/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java index efb45eba1..cbe09435b 100644 --- a/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java +++ b/extras/opentelemetry/integration-tests/src/test/java/org/a2aproject/sdk/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java @@ -1,6 +1,5 @@ package org.a2aproject.sdk.extras.opentelemetry.it; -import static io.quarkus.vertx.web.ReactiveRoutes.APPLICATION_JSON; import static io.restassured.RestAssured.given; import static java.net.HttpURLConnection.HTTP_OK; import static java.util.concurrent.TimeUnit.SECONDS; @@ -243,7 +242,7 @@ protected void saveTaskInTaskStore(Task task) throws Exception { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://localhost:" + serverPort + "/test/task")) .POST(HttpRequest.BodyPublishers.ofString(JsonUtil.toJson(task))) - .header("Content-Type", APPLICATION_JSON) + .header("Content-Type", "application/json") .build(); HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 9b7e4b694..fcc1c47fa 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -103,10 +103,5 @@ a2a-java-sdk-client test - - io.quarkus - quarkus-reactive-routes - test - diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 1476a3944..49c434ceb 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -102,10 +102,5 @@ a2a-java-sdk-client test - - io.quarkus - quarkus-reactive-routes - test - \ No newline at end of file diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java index 6f2837058..7f530e2e0 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java @@ -267,6 +267,13 @@ public A2AHttpResponse get() throws IOException, InterruptedException { .build(); HttpResponse response = httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); + + if (response.statusCode() == HTTP_UNAUTHORIZED) { + throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); + } else if (response.statusCode() == HTTP_FORBIDDEN) { + throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); + } + return new JdkHttpResponse(response); } @@ -289,6 +296,13 @@ public A2AHttpResponse delete() throws IOException, InterruptedException { HttpRequest request = super.createRequestBuilder().DELETE().build(); HttpResponse response = httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); + + if (response.statusCode() == HTTP_UNAUTHORIZED) { + throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); + } else if (response.statusCode() == HTTP_FORBIDDEN) { + throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); + } + return new JdkHttpResponse(response); } diff --git a/reference/common/pom.xml b/reference/common/pom.xml index f03eea9a9..fe90bd1de 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -35,7 +35,11 @@ io.quarkus - quarkus-reactive-routes + quarkus-vertx-http + + + io.quarkus + quarkus-arc jakarta.enterprise @@ -73,5 +77,17 @@ rest-assured test + + + io.quarkus + quarkus-security + true + + + io.quarkus + quarkus-elytron-security-properties-file + true + \ No newline at end of file diff --git a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java new file mode 100644 index 000000000..8419b8426 --- /dev/null +++ b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java @@ -0,0 +1,160 @@ +package org.a2aproject.sdk.server.common.quarkus; + +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.ManagedContext; +import io.quarkus.security.identity.CurrentIdentityAssociation; +import io.quarkus.vertx.http.runtime.security.HttpAuthenticator; +import io.vertx.ext.web.RoutingContext; + +/** + * CDI helper for integrating Quarkus security with Vert.x Web routes. + * + *

            When using {@code @Observes Router} to register Vert.x routes (instead of Quarkus Reactive Routes), + * the standard Quarkus HTTP authentication flow is bypassed. This helper provides utilities to manually + * trigger authentication and activate the CDI request context so that {@code @Authenticated} interceptors + * work correctly. + * + *

            Background

            + *

            Quarkus Reactive Routes (using {@code @Route}) automatically: + *

              + *
            • Trigger HTTP authentication mechanisms (Basic, OAuth, etc.)
            • + *
            • Activate the CDI request context
            • + *
            • Populate {@code CurrentIdentityAssociation} with the authenticated identity
            • + *
            + * + *

            However, when using {@code @Observes Router} to register raw Vert.x Web routes, none of this happens + * automatically. This helper bridges the gap by: + *

              + *
            • Triggering authentication via {@link HttpAuthenticator}
            • + *
            • Activating the CDI request context
            • + *
            • Populating {@code CurrentIdentityAssociation} with the authenticated identity
            • + *
            • Executing {@code @Authenticated} methods within the active context
            • + *
            + * + *

            Usage Pattern

            + *
            {@code
            + * @Inject VertxSecurityHelper securityHelper;
            + *
            + * void setupRoutes(@Observes Router router) {
            + *     router.post("/api/endpoint")
            + *         .blockingHandler(ctx -> {
            + *             try {
            + *                 // Authenticate and execute within request context
            + *                 securityHelper.runInRequestContext(ctx, () -> {
            + *                     myAuthenticatedMethod(); // Has @Authenticated annotation
            + *                 });
            + *             } catch (UnauthorizedException | ForbiddenException e) {
            + *                 VertxSecurityHelper.handleAuthError(ctx, e);
            + *             } catch (Exception e) {
            + *                 VertxSecurityHelper.handleGenericError(ctx);
            + *             }
            + *         });
            + * }
            + * }
            + * + * @see HttpAuthenticator + * @see CurrentIdentityAssociation + */ +@Singleton +public final class VertxSecurityHelper { + + @Inject + Instance httpAuthenticator; + + @Inject + Instance currentIdentityAssociation; + + + public VertxSecurityHelper() { + // Utility class - no instantiation + } + + /** + * Authenticates the request and executes a task within an active CDI request context. + * + *

            This method performs the full authentication and context setup flow required for + * Vert.x Web routes registered via {@code @Observes Router}: + *

              + *
            1. Triggers HTTP authentication via {@link HttpAuthenticator#attemptAuthentication}
            2. + *
            3. Activates the CDI request context if needed
            4. + *
            5. Sets the authenticated identity in {@link CurrentIdentityAssociation}
            6. + *
            7. Executes the task (which may call {@code @Authenticated} methods)
            8. + *
            9. Terminates the request context if it was activated by this method
            10. + *
            + * + *

            Thread Safety: This must be called on a Vert.x worker thread (e.g., from a + * {@code blockingHandler}), not the event loop thread. The authentication call blocks + * the worker thread using {@code await().indefinitely()}, which is safe on worker threads + * but would block the event loop on event loop threads. + * + * @param ctx the Vert.x routing context containing the HTTP request + * @param task the code to execute within the authenticated request context + * @throws io.quarkus.security.UnauthorizedException if authentication fails + * @throws io.quarkus.security.ForbiddenException if authorization fails + * @throws RuntimeException if the task throws an exception + */ + public void runInRequestContext(RoutingContext ctx, Runnable task) { + ManagedContext requestContext = Arc.container().requestContext(); + boolean wasActive = requestContext.isActive(); + if (!wasActive) { + requestContext.activate(); + } + try { + if (!httpAuthenticator.isUnsatisfied()) { + var identity = httpAuthenticator.get().attemptAuthentication(ctx).await().indefinitely(); + currentIdentityAssociation.get().setIdentity(identity); + } + task.run(); + } finally { + if (!wasActive) { + requestContext.terminate(); + } + } + } + + /** + * Handles authentication or authorization errors by sending the appropriate HTTP error response. + * + *

            This should be called when catching {@code UnauthorizedException} or {@code ForbiddenException} + * thrown by {@code @Authenticated} interceptors or authentication mechanisms. + * + *

              + *
            • {@code ForbiddenException} → HTTP 403 Forbidden
            • + *
            • All other auth errors → HTTP 401 Unauthorized with {@code WWW-Authenticate: Basic} header
            • + *
            + * + * @param ctx the routing context + * @param e the authentication or authorization exception + */ + public static void handleAuthError(RoutingContext ctx, Exception e) { + if (!ctx.response().ended()) { + if (e instanceof io.quarkus.security.ForbiddenException) { + ctx.response() + .setStatusCode(403) + .end(); + } else { + ctx.response() + .setStatusCode(401) + .putHeader("WWW-Authenticate", "Basic realm=\"Quarkus\"") + .end(); + } + } + } + + /** + * Handles generic errors by sending a 500 Internal Server Error response. + * + * @param ctx the routing context + */ + public static void handleGenericError(RoutingContext ctx) { + if (!ctx.response().ended()) { + ctx.response() + .setStatusCode(500) + .end("Internal Server Error"); + } + } +} diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index f89667b73..0895d7b7f 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -94,6 +94,22 @@ rest-assured test + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + \ No newline at end of file diff --git a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/A2ATestResource.java b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/A2ATestResource.java index b2ec9e1f0..a241c3ec8 100644 --- a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/A2ATestResource.java +++ b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/A2ATestResource.java @@ -19,7 +19,9 @@ import jakarta.ws.rs.core.Response; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.PublicAgentCard; import org.a2aproject.sdk.server.apps.common.TestUtilsBean; +import org.a2aproject.sdk.spec.AgentCard; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; diff --git a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/AuthTestProfile.java b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/AuthTestProfile.java new file mode 100644 index 000000000..610e2a825 --- /dev/null +++ b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/AuthTestProfile.java @@ -0,0 +1,47 @@ +package org.a2aproject.sdk.server.grpc.quarkus; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +/** + * Quarkus test profile that enables security for authentication tests. + *

            + * This profile: + *

              + *
            • Enables embedded user store with a test user
            • + *
            • Configures HTTP Basic authentication
            • + *
            • Provides test credentials: username=testuser, password=testpass
            • + *
            + */ +public class AuthTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + // Disable test security (injected test user) - we want REAL authentication + Map.entry("quarkus.test.security.auth.enabled", "false"), + + // Enable embedded user store + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + + // Enable security in agent card + Map.entry("test.agent.security.enabled", "true"), + + // Enable authorization so @Authenticated is enforced + Map.entry("test.authorization.enabled", "true"), + + // Enable HTTP Basic authentication + Map.entry("quarkus.http.auth.basic", "true") + ); + } + + @Override + public String getConfigProfile() { + // Use "test" profile to ensure test beans are active + return "test"; + } +} diff --git a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcWithAuthTest.java b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcWithAuthTest.java new file mode 100644 index 000000000..1693150db --- /dev/null +++ b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcWithAuthTest.java @@ -0,0 +1,128 @@ +package org.a2aproject.sdk.server.grpc.quarkus; + +import java.util.concurrent.TimeUnit; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransport; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.TransportProtocol; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import jakarta.inject.Inject; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +/** + * Authentication tests for gRPC transport. + *

            + * Validates that: + *

              + *
            • {@code @Authenticated} annotations at class level are enforced
            • + *
            • Protected endpoints require valid credentials
            • + *
            + *

            + * Note: gRPC doesn't have a separate agent card endpoint like HTTP transports, + * so the public endpoint and HTTP-specific tests are skipped. + */ +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class QuarkusA2AGrpcWithAuthTest extends AbstractA2AServerWithAuthTest { + + @Inject + @PublicAgentCard + AgentCard agentCard; + + private static ManagedChannel authenticatedChannel; + private static ManagedChannel unauthenticatedChannel; + + public QuarkusA2AGrpcWithAuthTest() { + super(8081); // HTTP server port for utility endpoints + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.GRPC.asString(); + } + + @Override + protected String getTransportUrl() { + // gRPC server runs on port 8081, same as main web server + return "localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + // Use AuthInterceptor with inline CredentialService + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder() + .channelFactory(target -> { + authenticatedChannel = ManagedChannelBuilder + .forTarget(target) + .usePlaintext() + .build(); + return authenticatedChannel; + }) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + // No auth (for unauthenticated client creation) + builder.withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder().channelFactory(target -> { + unauthenticatedChannel = ManagedChannelBuilder + .forTarget(target) + .usePlaintext() + .build(); + return unauthenticatedChannel; + })); + } + + @AfterAll + public static void closeChannels() { + if (authenticatedChannel != null) { + authenticatedChannel.shutdownNow(); + try { + authenticatedChannel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + if (unauthenticatedChannel != null) { + unauthenticatedChannel.shutdownNow(); + try { + unauthenticatedChannel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + @Override + protected AgentCard fetchAgentCardFromServer() { + return agentCard; + } + + @Test + @Override + @Disabled + public void testGetAgentCardIsPublic() { + // Skip - gRPC doesn't have /.well-known/agent-card.json endpoint + } + + @Test + @Override + @Disabled + public void testBasicAuthWorksViaHttp() { + // Skip - HTTP-specific test + } +} diff --git a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/TestAuthorizationController.java b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/TestAuthorizationController.java new file mode 100644 index 000000000..a3ae4436f --- /dev/null +++ b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/TestAuthorizationController.java @@ -0,0 +1,34 @@ +package org.a2aproject.sdk.server.grpc.quarkus; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.Alternative; +import jakarta.inject.Singleton; +import jakarta.interceptor.Interceptor; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import io.quarkus.security.spi.runtime.AuthorizationController; + +/** + * Disables authorization for regular gRPC tests. + *

            + * The {@code @Authenticated} CDI interceptor checks {@link AuthorizationController#isAuthorizationEnabled()} + * before enforcing. When disabled, {@code @Authenticated} becomes a no-op, allowing + * regular tests to run without credentials. + *

            + * {@link AuthTestProfile} sets {@code test.authorization.enabled=true} to enforce + * real authentication for auth-specific tests. + */ +@Alternative +@Priority(Interceptor.Priority.LIBRARY_AFTER + 1) +@Singleton +public class TestAuthorizationController extends AuthorizationController { + + @ConfigProperty(name = "test.authorization.enabled", defaultValue = "false") + boolean enabled; + + @Override + public boolean isAuthorizationEnabled() { + return enabled; + } +} diff --git a/reference/jsonrpc/README.md b/reference/jsonrpc/README.md index 2a7f0f902..8fe43d752 100644 --- a/reference/jsonrpc/README.md +++ b/reference/jsonrpc/README.md @@ -2,6 +2,6 @@ This is a reference server for the A2A SDK for Java, that we use to run tests, as well as to demonstrate examples. -It is based on [Quarkus](https://quarkus.io), and makes use of Quarkus's [Reactive Routes](https://quarkus.io/guides/reactive-routes). +It is based on [Quarkus](https://quarkus.io), and uses the [Vert.x Web Router](https://vertx.io/docs/vertx-web/java/) for HTTP route registration. It is a great choice if you use Quarkus! \ No newline at end of file diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index ff6fe6272..5a236f3d1 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -57,10 +57,6 @@ a2a-java-sdk-client-transport-jsonrpc test - - io.quarkus - quarkus-reactive-routes - jakarta.enterprise jakarta.enterprise.cdi-api @@ -103,5 +99,21 @@ mockito-junit-jupiter test + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + diff --git a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index e6433df77..8e5f52b82 100644 --- a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -1,12 +1,12 @@ package org.a2aproject.sdk.server.apps.quarkus; +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 static org.a2aproject.sdk.server.ServerCallContext.TRANSPORT_KEY; import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_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; @@ -16,13 +16,25 @@ import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicLong; +import jakarta.enterprise.event.Observes; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import jakarta.inject.Singleton; import com.google.gson.JsonSyntaxException; +import io.quarkus.security.Authenticated; +import io.quarkus.security.ForbiddenException; +import io.quarkus.security.UnauthorizedException; +import io.smallrye.mutiny.Multi; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; import org.a2aproject.sdk.common.A2AHeaders; -import org.a2aproject.sdk.server.util.sse.SseFormatter; import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; import org.a2aproject.sdk.jsonrpc.common.json.IdJsonMappingException; import org.a2aproject.sdk.jsonrpc.common.json.InvalidParamsJsonMappingException; @@ -35,6 +47,8 @@ import org.a2aproject.sdk.jsonrpc.common.wrappers.A2AResponse; import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskRequest; import org.a2aproject.sdk.jsonrpc.common.wrappers.CancelTaskResponse; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; import org.a2aproject.sdk.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; import org.a2aproject.sdk.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; @@ -52,30 +66,21 @@ import org.a2aproject.sdk.jsonrpc.common.wrappers.SendMessageResponse; import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageRequest; import org.a2aproject.sdk.jsonrpc.common.wrappers.SendStreamingMessageResponse; -import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; -import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; import org.a2aproject.sdk.jsonrpc.common.wrappers.SubscribeToTaskRequest; +import org.a2aproject.sdk.server.AgentCardCacheMetadata; import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.UnauthenticatedUser; import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.server.extensions.A2AExtensions; import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.server.util.sse.SseFormatter; import org.a2aproject.sdk.spec.A2AError; import org.a2aproject.sdk.spec.InternalError; import org.a2aproject.sdk.spec.JSONParseError; import org.a2aproject.sdk.spec.TransportProtocol; import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.a2aproject.sdk.transport.jsonrpc.handler.JSONRPCHandler; -import io.quarkus.security.Authenticated; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Route; -import io.smallrye.mutiny.Multi; -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RoutingContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -173,7 +178,7 @@ public class A2AServerRoutes { JSONRPCHandler jsonRpcHandler; @Inject - org.a2aproject.sdk.server.AgentCardCacheMetadata cacheMetadata; + AgentCardCacheMetadata cacheMetadata; // Hook so testing can wait until the MultiSseSupport is subscribed. // Without this we get intermittent failures @@ -186,6 +191,53 @@ public class A2AServerRoutes { @Inject Instance callContextFactory; + @Inject + VertxSecurityHelper vertxSecurityHelper; + + /** + * Configures Vert.x Web Router with JSON-RPC routes. + * + *

            This method is invoked during application startup to register all HTTP routes + * for the JSON-RPC transport. Routes are configured with direct Vert.x Web Router + * instead of Quarkus Reactive Routes. + * + * @param router the Vert.x Web Router instance to configure + */ + void setupRoutes(@Observes Router router) { + // Add BodyHandler to parse request bodies + router.route().handler(BodyHandler.create()); + + // Main JSON-RPC endpoint: POST / + router.post("/") + .consumes(APPLICATION_JSON) + .blockingHandler(ctx -> { + try { + vertxSecurityHelper.runInRequestContext(ctx, () -> { + invokeJSONRPCHandler(ctx.body().asString(), ctx); + }); + } catch (UnauthorizedException | ForbiddenException e) { + VertxSecurityHelper.handleAuthError(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }); + + // Agent card endpoint: GET /.well-known/agent-card.json + router.get("/.well-known/agent-card.json") + .produces(APPLICATION_JSON) + .handler(ctx -> { + try { + String agentCard = getAgentCard(ctx); + ctx.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(agentCard); + } catch (JsonProcessingException e) { + ctx.response().setStatusCode(500).end("Internal Server Error"); + } + }); + } + /** * Main entry point for all JSON-RPC requests. * @@ -258,9 +310,8 @@ public class A2AServerRoutes { * @param rc the Vert.x routing context containing HTTP request/response * @throws A2AError if request processing fails */ - @Route(path = "/", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) @Authenticated - public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { + public void invokeJSONRPCHandler(String body, RoutingContext rc) { boolean streaming = false; ServerCallContext context = createCallContext(rc); A2AResponse nonStreamingResponse = null; @@ -286,9 +337,7 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { } catch (JsonMappingException e) { // General JsonMappingException - treat as InvalidRequest error = new A2AErrorResponse(new org.a2aproject.sdk.spec.InvalidRequestError(null, e.getMessage(), null)); - } catch (JsonSyntaxException e) { - error = new A2AErrorResponse(new JSONParseError(e.getMessage())); - } catch (JsonProcessingException e) { + } catch (JsonSyntaxException | JsonProcessingException e) { error = new A2AErrorResponse(new JSONParseError(e.getMessage())); } catch (Throwable t) { error = new A2AErrorResponse(new InternalError(t.getMessage())); @@ -360,7 +409,6 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { * @throws JsonProcessingException if serialization fails * @see JSONRPCHandler#getAgentCard() */ - @Route(path = "/.well-known/agent-card.json", methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) public String getAgentCard(RoutingContext rc) throws JsonProcessingException { // Add caching headers per A2A specification section 8.6 cacheMetadata.getHttpHeadersMap().forEach((k, v) -> rc.response().putHeader(k, v)); diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java index 31af95c1d..17be340f8 100644 --- a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java @@ -7,6 +7,7 @@ import java.util.concurrent.atomic.AtomicInteger; import jakarta.annotation.PostConstruct; +import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -16,13 +17,12 @@ import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Param; -import io.quarkus.vertx.web.Route; +import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; /** - * Exposes the {@link TestUtilsBean} via REST using Quarkus Reactive Routes + * Exposes the {@link TestUtilsBean} via REST using the Vert.x Web Router */ @Singleton public class A2ATestRoutes { @@ -39,9 +39,97 @@ public void init() { A2AServerRoutes.setStreamingMultiSseSupportSubscribedRunnable(() -> streamingSubscribedCount.incrementAndGet()); } + void setupRoutes(@Observes Router router) { + // Save task: POST /test/task + router.post("/test/task") + .consumes(APPLICATION_JSON) + .blockingHandler(ctx -> { + String body = ctx.body().asString(); + saveTask(body, ctx); + }); - @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void saveTask(@Body String body, RoutingContext rc) { + // Get task: GET /test/task/:taskId + router.get("/test/task/:taskId") + .produces(APPLICATION_JSON) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getTask(taskId, ctx); + }); + + // Delete task: DELETE /test/task/:taskId + router.delete("/test/task/:taskId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + deleteTask(taskId, ctx); + }); + + // Ensure task queue: POST /test/queue/ensure/:taskId + router.post("/test/queue/ensure/:taskId") + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + ensureTaskQueue(taskId, ctx); + }); + + // Enqueue task status update event: POST /test/queue/enqueueTaskStatusUpdateEvent/:taskId + router.post("/test/queue/enqueueTaskStatusUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + enqueueTaskStatusUpdateEvent(taskId, body, ctx); + }); + + // Enqueue task artifact update event: POST /test/queue/enqueueTaskArtifactUpdateEvent/:taskId + router.post("/test/queue/enqueueTaskArtifactUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + enqueueTaskArtifactUpdateEvent(taskId, body, ctx); + }); + + // Get streaming subscribed count: GET /test/streamingSubscribedCount + router.get("/test/streamingSubscribedCount") + .produces(TEXT_PLAIN) + .handler(ctx -> { + getStreamingSubscribedCount(ctx); + }); + + // Get child queue count: GET /test/queue/childCount/:taskId + router.get("/test/queue/childCount/:taskId") + .produces(TEXT_PLAIN) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getChildQueueCount(taskId, ctx); + }); + + // Delete task push notification config: DELETE /test/task/:taskId/config/:configId + router.delete("/test/task/:taskId/config/:configId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String configId = ctx.pathParam("configId"); + deleteTaskPushNotificationConfig(taskId, configId, ctx); + }); + + // Save task push notification config: POST /test/task/:taskId + router.post("/test/task/:taskId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + saveTaskPushNotificationConfig(taskId, body, ctx); + }); + + // Await child queue count stable: POST /test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs + router.post("/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String expectedCount = ctx.pathParam("expectedCount"); + String timeoutMs = ctx.pathParam("timeoutMs"); + awaitChildQueueCountStable(taskId, expectedCount, timeoutMs, ctx); + }); + } + + public void saveTask(String body, RoutingContext rc) { try { Task task = JsonUtil.fromJson(body, Task.class); testUtilsBean.saveTask(task); @@ -53,8 +141,7 @@ public void saveTask(@Body String body, RoutingContext rc) { } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void getTask(@Param String taskId, RoutingContext rc) { + public void getTask(String taskId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -73,8 +160,7 @@ public void getTask(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTask(@Param String taskId, RoutingContext rc) { + public void deleteTask(String taskId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -92,8 +178,7 @@ public void deleteTask(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) - public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { + public void ensureTaskQueue(String taskId, RoutingContext rc) { try { testUtilsBean.ensureQueue(taskId); rc.response() @@ -104,8 +189,7 @@ public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + public void enqueueTaskStatusUpdateEvent(String taskId, String body, RoutingContext rc) { try { TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); @@ -118,8 +202,7 @@ public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body } } - @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + public void enqueueTaskArtifactUpdateEvent(String taskId, String body, RoutingContext rc) { try { TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); @@ -132,23 +215,20 @@ public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String bo } } - @Route(path = "/test/streamingSubscribedCount", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) public void getStreamingSubscribedCount(RoutingContext rc) { rc.response() .setStatusCode(200) .end(String.valueOf(streamingSubscribedCount.get())); } - @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getChildQueueCount(@Param String taskId, RoutingContext rc) { + public void getChildQueueCount(String taskId, RoutingContext rc) { int count = testUtilsBean.getChildQueueCount(taskId); rc.response() .setStatusCode(200) .end(String.valueOf(count)); } - @Route(path = "/test/task/:taskId/config/:configId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String configId, RoutingContext rc) { + public void deleteTaskPushNotificationConfig(String taskId, String configId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -166,8 +246,7 @@ public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { + public void saveTaskPushNotificationConfig(String taskId, String body, RoutingContext rc) { try { TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); if (notificationConfig == null) { @@ -195,8 +274,7 @@ public void saveTaskPushNotificationConfig(@Param String taskId, @Body String bo * @param timeoutMsStr maximum time to wait in milliseconds (as string) * @param rc the Vert.x routing context */ - @Route(path = "/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void awaitChildQueueCountStable(@Param("taskId") String taskId, @Param("expectedCount") String expectedCountStr, @Param("timeoutMs") String timeoutMsStr, RoutingContext rc) { + public void awaitChildQueueCountStable(String taskId, String expectedCountStr, String timeoutMsStr, RoutingContext rc) { try { int expectedCount = Integer.parseInt(expectedCountStr); long timeoutMs = Long.parseLong(timeoutMsStr); diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/AuthTestProfile.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/AuthTestProfile.java new file mode 100644 index 000000000..31e0d22dd --- /dev/null +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/AuthTestProfile.java @@ -0,0 +1,47 @@ +package org.a2aproject.sdk.server.apps.quarkus; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +/** + * Quarkus test profile that enables security for authentication tests. + *

            + * This profile: + *

              + *
            • Enables embedded user store with a test user
            • + *
            • Configures HTTP Basic authentication
            • + *
            • Provides test credentials: username=testuser, password=testpass
            • + *
            + */ +public class AuthTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + // Disable the TestIdentityProvider - we want real authentication + Map.entry("test.identity.auto-auth", "false"), + + // Enable security in AgentCard (server advertises Basic Auth support) + Map.entry("test.agent.security.enabled", "true"), + + // Enable embedded user store + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + + // Enable HTTP Basic authentication + Map.entry("quarkus.http.auth.basic", "true"), + + // Enable proactive authentication - authenticate at HTTP layer before route handler + Map.entry("quarkus.http.auth.proactive", "true") + ); + } + + @Override + public String getConfigProfile() { + // Use "test" profile to ensure test beans are active + return "test"; + } +} diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthJdkTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthJdkTest.java new file mode 100644 index 000000000..ba65e7cfa --- /dev/null +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthJdkTest.java @@ -0,0 +1,65 @@ +package org.a2aproject.sdk.server.apps.quarkus; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.spec.TransportProtocol; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +/** + * Authentication tests for JSON-RPC transport with JDK HTTP client. + *

            + * Validates that: + *

              + *
            • {@code @Authenticated} annotations are enforced
            • + *
            • {@code @ActivateRequestContext} is present (required for security context)
            • + *
            • Public endpoints remain accessible without authentication
            • + *
            • Protected endpoints require valid credentials
            • + *
            + */ +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class QuarkusA2AJSONRPCWithAuthJdkTest extends AbstractA2AServerWithAuthTest { + + public QuarkusA2AJSONRPCWithAuthJdkTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + // Use AuthInterceptor with inline CredentialService + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder() + .httpClient(new JdkA2AHttpClient()) + .addInterceptor(authInterceptor) + .build(); + + builder.withTransport(JSONRPCTransport.class, config); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + // No auth (for unauthenticated client creation) + builder.withTransport(JSONRPCTransport.class, + new JSONRPCTransportConfigBuilder() + .httpClient(new JdkA2AHttpClient())); + } +} diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthVertxTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthVertxTest.java new file mode 100644 index 000000000..34c5f77da --- /dev/null +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthVertxTest.java @@ -0,0 +1,70 @@ +package org.a2aproject.sdk.server.apps.quarkus; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.spec.TransportProtocol; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; + +/** + * Authentication tests for JSON-RPC transport with Vert.x HTTP client. + *

            + * Validates that: + *

              + *
            • {@code @Authenticated} annotations are enforced
            • + *
            • {@code @ActivateRequestContext} is present (required for security context)
            • + *
            • Public endpoints remain accessible without authentication
            • + *
            • Protected endpoints require valid credentials
            • + *
            + */ +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class QuarkusA2AJSONRPCWithAuthVertxTest extends AbstractA2AServerWithAuthTest { + + @Inject + Vertx vertx; + + public QuarkusA2AJSONRPCWithAuthVertxTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + // Use AuthInterceptor with inline CredentialService + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx)) + .addInterceptor(authInterceptor) + .build(); + + builder.withTransport(JSONRPCTransport.class, config); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + // No auth (for unauthenticated client creation) + builder.withTransport(JSONRPCTransport.class, + new JSONRPCTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx))); + } +} diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/TestIdentityProvider.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/TestIdentityProvider.java new file mode 100644 index 000000000..d6049a3e4 --- /dev/null +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/TestIdentityProvider.java @@ -0,0 +1,37 @@ +package org.a2aproject.sdk.server.apps.quarkus; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.quarkus.arc.properties.IfBuildProperty; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; +import io.quarkus.security.identity.SecurityIdentityAugmentor; +import io.quarkus.arc.Unremovable; + +/** + * Test identity provider that always returns an authenticated user. + *

            + * This allows regular tests to work with {@code @Authenticated} annotations + * without requiring actual HTTP Basic Auth credentials. + *

            + * This bean is disabled when using {@link AuthTestProfile}, which tests real authentication. + */ +@ApplicationScoped +@Unremovable +@IfBuildProperty(name = "test.identity.auto-auth", stringValue = "true", enableIfMissing = true) +public class TestIdentityProvider implements SecurityIdentityAugmentor { + + @Override + public Uni augment(SecurityIdentity identity, io.quarkus.security.identity.AuthenticationRequestContext context) { + // If anonymous, inject a test user + if (identity.isAnonymous()) { + return Uni.createFrom().item(QuarkusSecurityIdentity.builder() + .setPrincipal(() -> "testuser") + .addRole("user") + .setAnonymous(false) + .build()); + } + return Uni.createFrom().item(identity); + } +} diff --git a/reference/jsonrpc/src/test/resources/application.properties b/reference/jsonrpc/src/test/resources/application.properties index d5acb5291..f3e1a801d 100644 --- a/reference/jsonrpc/src/test/resources/application.properties +++ b/reference/jsonrpc/src/test/resources/application.properties @@ -4,3 +4,10 @@ quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttp quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG + +# Security configuration for regular tests +# Provide a test identity provider that always authenticates +# AuthTestProfile overrides this to require real HTTP Basic Auth +%test.quarkus.test-security.test-enabled=true +%test.quarkus.test-security.user=testuser +%test.quarkus.test-security.roles=user diff --git a/reference/rest/README.md b/reference/rest/README.md index 2a7f0f902..8fe43d752 100644 --- a/reference/rest/README.md +++ b/reference/rest/README.md @@ -2,6 +2,6 @@ This is a reference server for the A2A SDK for Java, that we use to run tests, as well as to demonstrate examples. -It is based on [Quarkus](https://quarkus.io), and makes use of Quarkus's [Reactive Routes](https://quarkus.io/guides/reactive-routes). +It is based on [Quarkus](https://quarkus.io), and uses the [Vert.x Web Router](https://vertx.io/docs/vertx-web/java/) for HTTP route registration. It is a great choice if you use Quarkus! \ No newline at end of file diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index d9429ba98..1f94b651e 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -61,10 +61,6 @@ protobuf-java-util test - - io.quarkus - quarkus-reactive-routes - jakarta.enterprise jakarta.enterprise.cdi-api @@ -107,7 +103,24 @@ mockito-junit-jupiter test + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + + diff --git a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java index 14e7e45f0..a718644fd 100644 --- a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java @@ -16,10 +16,12 @@ import java.util.concurrent.Executor; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; import org.a2aproject.sdk.server.util.sse.SseFormatter; -import jakarta.annotation.security.PermitAll; +import jakarta.annotation.Priority; +import jakarta.enterprise.event.Observes; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -39,17 +41,21 @@ import org.a2aproject.sdk.transport.rest.handler.RestHandler; import org.a2aproject.sdk.transport.rest.handler.RestHandler.HTTPRestResponse; import org.a2aproject.sdk.transport.rest.handler.RestHandler.HTTPRestStreamingResponse; +import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.util.Utils; import io.quarkus.security.Authenticated; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Route; +import io.quarkus.security.ForbiddenException; +import io.quarkus.security.UnauthorizedException; import io.smallrye.mutiny.Multi; +import jakarta.annotation.security.PermitAll; import io.vertx.core.AsyncResult; import io.vertx.core.Handler; import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; import org.jspecify.annotations.Nullable; import static org.a2aproject.sdk.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; @@ -65,10 +71,10 @@ import static org.a2aproject.sdk.transport.rest.context.RestContextKeys.TENANT_KEY; /** - * Quarkus reactive routes for A2A protocol REST endpoints. + * Vert.x Web Router routes for A2A protocol REST endpoints. * - *

            This class defines all HTTP routes for the A2A protocol using Quarkus Reactive Routes - * (Vert.x web). Each method is annotated with {@code @Route} to map HTTP requests to + *

            This class defines all HTTP routes for the A2A protocol using the Vert.x Web Router API + * ({@code @Observes Router}). Routes are registered programmatically to map HTTP requests to * A2A operations, delegating to {@link RestHandler} for processing. * *

            Route Mapping

            @@ -120,7 +126,6 @@ * @see CallContextFactory */ @Singleton -@Authenticated public class A2AServerRoutes { private static final String HISTORY_LENGTH_PARAM = "historyLength"; @@ -143,6 +148,118 @@ public class A2AServerRoutes { @Inject Instance callContextFactory; + @Inject + VertxSecurityHelper vertxSecurityHelper; + + /** + * Initializes Vert.x Web Router with all A2A REST endpoints. + * + *

            This method observes the Router bean creation and configures all routes. + * Replaces the deprecated @Route annotation-based routing with direct Router API. + * + * @param router the Vert.x router to configure + */ + void setupRouter(@Observes @Priority(10) Router router) { + // Don't add a global BodyHandler - it interferes with gRPC routes + // Instead, BodyHandler is added per-route below + + // Message Routes + + // POST /{tenant}/message:send - Non-streaming message send + router.postWithRegex("^\\/(?[^\\/]*\\/?)message:send$") + .handler(BodyHandler.create()) + .blockingHandler(authenticated(ctx -> { + String body = extractBody(ctx); + sendMessage(body, ctx); + })); + + // POST /{tenant}/message:stream - Streaming message with SSE + router.postWithRegex("^\\/(?[^\\/]*\\/?)message:stream$") + .handler(BodyHandler.create()) + .blockingHandler(authenticated(ctx -> { + String body = extractBody(ctx); + sendMessageStreaming(body, ctx); + })); + + // Task Routes + + // GET /{tenant}/tasks - List tasks with query params + router.getWithRegex("^\\/(?[^\\/]*\\/?)tasks\\??") + .order(0) + .blockingHandler(authenticated(this::listTasks)); + + // GET /{tenant}/tasks/{taskId} - Get specific task + router.getWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^:^/]+)$") + .order(1) + .blockingHandler(authenticated(this::getTask)); + + // POST /{tenant}/tasks/{taskId}:cancel - Cancel task + router.postWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):cancel$") + .order(1) + .handler(BodyHandler.create()) + .blockingHandler(authenticated(ctx -> { + String body = extractBody(ctx); + cancelTask(body, ctx); + })); + + // POST /{tenant}/tasks/{taskId}:subscribe - Subscribe to task updates (SSE) + router.postWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):subscribe$") + .order(1) + .blockingHandler(authenticated(this::subscribeToTask)); + + // Push Notification Routes + + // POST /{tenant}/tasks/{taskId}/pushNotificationConfigs + router.postWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs$") + .order(1) + .handler(BodyHandler.create()) + .blockingHandler(authenticated(ctx -> { + String body = extractBody(ctx); + createTaskPushNotificationConfiguration(body, ctx); + })); + + // GET /{tenant}/tasks/{taskId}/pushNotificationConfigs/{configId} + router.getWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^\\/]+)") + .order(2) + .blockingHandler(authenticated(this::getTaskPushNotificationConfiguration)); + + // GET /{tenant}/tasks/{taskId}/pushNotificationConfigs + router.getWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/?$") + .order(3) + .blockingHandler(authenticated(this::listTaskPushNotificationConfigurations)); + + // DELETE /{tenant}/tasks/{taskId}/pushNotificationConfigs/{configId} + router.deleteWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^/]+)") + .order(1) + .blockingHandler(authenticated(this::deleteTaskPushNotificationConfiguration)); + + // Discovery Routes + + // GET /.well-known/agent-card.json - Public agent card (no auth required) + router.get("/.well-known/agent-card.json") + .order(1) + .produces(APPLICATION_JSON) + .handler(this::getAgentCard); + + // GET /{tenant}/extendedAgentCard - Extended agent card (auth required) + router.getWithRegex("^\\/(?[^\\/]*\\/?)extendedAgentCard$") + .order(1) + .produces(APPLICATION_JSON) + .blockingHandler(authenticated(this::getExtendedAgentCard)); + } + + private Handler authenticated(Consumer action) { + return ctx -> { + try { + vertxSecurityHelper.runInRequestContext(ctx, () -> action.accept(ctx)); + } catch (UnauthorizedException | ForbiddenException e) { + VertxSecurityHelper.handleAuthError(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }; + } + /** * Handles blocking message send requests. * @@ -166,8 +283,8 @@ public class A2AServerRoutes { * @param body the JSON request body * @param rc the Vert.x routing context */ - @Route(regex = "^\\/(?[^\\/]*\\/?)message:send$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void sendMessage(@Body String body, RoutingContext rc) { + @Authenticated + public void sendMessage(String body, RoutingContext rc) { if(!validateContentType(rc)) { return; } @@ -202,8 +319,8 @@ public void sendMessage(@Body String body, RoutingContext rc) { * @param body the JSON request body * @param rc the Vert.x routing context */ - @Route(regex = "^\\/(?[^\\/]*\\/?)message:stream$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void sendMessageStreaming(@Body String body, RoutingContext rc) { + @Authenticated + public void sendMessageStreaming(String body, RoutingContext rc) { if(!validateContentType(rc)) { return; } @@ -255,7 +372,7 @@ public void sendMessageStreaming(@Body String body, RoutingContext rc) { * * @param rc the Vert.x routing context */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\??", order = 0, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) + @Authenticated public void listTasks(RoutingContext rc) { ServerCallContext context = createCallContext(rc, LIST_TASK_METHOD); HTTPRestResponse response = null; @@ -310,7 +427,7 @@ public void listTasks(RoutingContext rc) { * * @param rc the Vert.x routing context (taskId extracted from path) */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^:^/]+)$", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) + @Authenticated public void getTask(RoutingContext rc) { String taskId = rc.pathParam("taskId"); ServerCallContext context = createCallContext(rc, GET_TASK_METHOD); @@ -344,8 +461,8 @@ public void getTask(RoutingContext rc) { * * @param rc the Vert.x routing context (taskId extracted from path) */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void cancelTask(@Body String body, RoutingContext rc) { + @Authenticated + public void cancelTask(String body, RoutingContext rc) { if (!validateContentTypeForOptionalBody(rc, body)) { return; } @@ -410,7 +527,7 @@ private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response * * @param rc the Vert.x routing context (taskId extracted from path) */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):subscribe$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) + @Authenticated public void subscribeToTask(RoutingContext rc) { String taskId = rc.pathParam("taskId"); ServerCallContext context = createCallContext(rc, SUBSCRIBE_TO_TASK_METHOD); @@ -457,8 +574,8 @@ public void subscribeToTask(RoutingContext rc) { * @param body the JSON request body with notification configuration * @param rc the Vert.x routing context (taskId extracted from path) */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void createTaskPushNotificationConfiguration(@Body String body, RoutingContext rc) { + @Authenticated + public void createTaskPushNotificationConfiguration(String body, RoutingContext rc) { if(!validateContentType(rc)) { return; } @@ -488,7 +605,7 @@ public void createTaskPushNotificationConfiguration(@Body String body, RoutingCo * * @param rc the Vert.x routing context (taskId and configId extracted from path) */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^\\/]+)", order = 2, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) + @Authenticated public void getTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("taskId"); String configId = rc.pathParam("configId"); @@ -526,7 +643,7 @@ public void getTaskPushNotificationConfiguration(RoutingContext rc) { * * @param rc the Vert.x routing context (taskId extracted from path) */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/?$", order = 3, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) + @Authenticated public void listTaskPushNotificationConfigurations(RoutingContext rc) { String taskId = rc.pathParam("taskId"); ServerCallContext context = createCallContext(rc, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); @@ -566,7 +683,7 @@ public void listTaskPushNotificationConfigurations(RoutingContext rc) { * * @param rc the Vert.x routing context (taskId and configId extracted from path) */ - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^/]+)", order = 1, methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) + @Authenticated public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("taskId"); String configId = rc.pathParam("configId"); @@ -587,6 +704,17 @@ public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { } } + /** + * Extracts request body from routing context, returning empty string if null. + * + * @param rc the routing context + * @return the request body, or empty string if null + */ + private static String extractBody(RoutingContext rc) { + String body = rc.body().asString(); + return body != null ? body : ""; + } + /** * Extracts tenant ID from the routing context path parameter. * @@ -616,7 +744,7 @@ private String extractTenant(RoutingContext rc) { /** * Check if the request content type is application/json. - * @param rc + * @param rc the routing context * @return true if the content type is application/json - false otherwise. */ private boolean validateContentType(RoutingContext rc) { @@ -668,7 +796,6 @@ private boolean validateContentTypeForOptionalBody(RoutingContext rc, @Nullable * * @param rc the Vert.x routing context */ - @Route(path = "/.well-known/agent-card.json", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) @PermitAll public void getAgentCard(RoutingContext rc) { HTTPRestResponse response = jsonRestHandler.getAgentCard(); @@ -687,7 +814,7 @@ public void getAgentCard(RoutingContext rc) { * * @param rc the Vert.x routing context */ - @Route(regex = "^\\/(?[^\\/]*\\/?)extendedAgentCard$", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) + @Authenticated public void getExtendedAgentCard(RoutingContext rc) { HTTPRestResponse response = jsonRestHandler.getExtendedAgentCard(createCallContext(rc, GET_EXTENDED_AGENT_CARD_METHOD), extractTenant(rc)); sendResponse(rc, response); @@ -704,7 +831,6 @@ public void getExtendedAgentCard(RoutingContext rc) { * * @param rc the Vert.x routing context */ - @Route(path = "^/.*", order = 100, methods = {Route.HttpMethod.DELETE, Route.HttpMethod.GET, Route.HttpMethod.HEAD, Route.HttpMethod.OPTIONS, Route.HttpMethod.POST, Route.HttpMethod.PUT}, produces = APPLICATION_JSON) public void methodNotFoundMessage(RoutingContext rc) { HTTPRestResponse response = jsonRestHandler.createErrorResponse(new MethodNotFoundError()); sendResponse(rc, response); @@ -769,9 +895,6 @@ public String getUsername() { }; } Map state = new HashMap<>(); - // TODO Python's impl has - // state['auth'] = request.auth - // in jsonrpc_app.py. Figure out what this maps to in what Vert.X gives us Map headers = new HashMap<>(); Set headerNames = rc.request().headers().names(); diff --git a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/package-info.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/package-info.java index e8d6e2168..7d6fb1928 100644 --- a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/package-info.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/package-info.java @@ -7,7 +7,7 @@ * *

            Key Components

            *
              - *
            • {@link A2AServerRoutes} - Vert.x route definitions mapping HTTP paths to A2A operations
            • + *
            • {@link A2AServerRoutes} - Vert.x Web Router route definitions mapping HTTP paths to A2A operations
            • *
            • {@link CallContextFactory} - Extensible factory for creating {@link org.a2aproject.sdk.server.ServerCallContext}
            • *
            • {@link QuarkusRestTransportMetadata} - Transport protocol metadata implementation
            • *
            @@ -16,7 +16,7 @@ *
              * HTTP Request (Quarkus/Vert.x)
              *     ↓
            - * A2AServerRoutes (@Route methods)
            + * A2AServerRoutes (Vert.x Web Router)
              *     ↓
              * RestHandler (transport/rest)
              *     ↓
            diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2ATestRoutes.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2ATestRoutes.java
            index b71e98164..c45d551f2 100644
            --- a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2ATestRoutes.java
            +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/A2ATestRoutes.java
            @@ -7,6 +7,8 @@
             import java.util.concurrent.atomic.AtomicInteger;
             
             import jakarta.annotation.PostConstruct;
            +import jakarta.annotation.Priority;
            +import jakarta.enterprise.event.Observes;
             import jakarta.inject.Inject;
             import jakarta.inject.Singleton;
             
            @@ -16,13 +18,12 @@
             import org.a2aproject.sdk.spec.Task;
             import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent;
             import org.a2aproject.sdk.spec.TaskStatusUpdateEvent;
            -import io.quarkus.vertx.web.Body;
            -import io.quarkus.vertx.web.Param;
            -import io.quarkus.vertx.web.Route;
            +import io.vertx.ext.web.Router;
             import io.vertx.ext.web.RoutingContext;
            +import io.vertx.ext.web.handler.BodyHandler;
             
             /**
            - * Exposes the {@link TestUtilsBean} via REST using Quarkus Reactive Routes
            + * Exposes the {@link TestUtilsBean} via REST using the Vert.x Web Router
              */
             @Singleton
             public class A2ATestRoutes {
            @@ -39,9 +40,126 @@ public void init() {
                     A2AServerRoutes.setStreamingMultiSseSupportSubscribedRunnable(() -> streamingSubscribedCount.incrementAndGet());
                 }
             
            +    void setupRouter(@Observes @Priority(1) Router router) {
            +        // Test routes - no authentication required (these are test utilities)
            +        // Don't add global BodyHandler - it interferes with gRPC routes
            +        // Instead, add BodyHandler per-route below
             
            -    @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING)
            -    public void saveTask(@Body String body, RoutingContext rc) {
            +        // POST /test/task - Save task
            +        router.post("/test/task")
            +            .order(0)  // High priority to match before other routes
            +            .consumes(APPLICATION_JSON)
            +            .handler(BodyHandler.create())
            +            .blockingHandler(ctx -> {
            +                String body = ctx.body().asString();
            +                if (body == null) {
            +                    body = "";
            +                }
            +                saveTask(body, ctx);
            +            });
            +
            +        // GET /test/task/:taskId - Get task
            +        router.get("/test/task/:taskId")
            +            .order(0)
            +            .produces(APPLICATION_JSON)
            +            .blockingHandler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                getTask(taskId, ctx);
            +            });
            +
            +        // DELETE /test/task/:taskId - Delete task
            +        router.delete("/test/task/:taskId")
            +            .order(0)
            +            .blockingHandler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                deleteTask(taskId, ctx);
            +            });
            +
            +        // POST /test/queue/ensure/:taskId - Ensure task queue
            +        router.post("/test/queue/ensure/:taskId")
            +            .order(0)
            +            .handler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                ensureTaskQueue(taskId, ctx);
            +            });
            +
            +        // POST /test/queue/enqueueTaskStatusUpdateEvent/:taskId
            +        router.post("/test/queue/enqueueTaskStatusUpdateEvent/:taskId")
            +            .order(0)
            +            .handler(BodyHandler.create())
            +            .handler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                String body = ctx.body().asString();
            +                if (body == null) {
            +                    body = "";
            +                }
            +                enqueueTaskStatusUpdateEvent(taskId, body, ctx);
            +            });
            +
            +        // POST /test/queue/enqueueTaskArtifactUpdateEvent/:taskId
            +        router.post("/test/queue/enqueueTaskArtifactUpdateEvent/:taskId")
            +            .order(0)
            +            .handler(BodyHandler.create())
            +            .handler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                String body = ctx.body().asString();
            +                if (body == null) {
            +                    body = "";
            +                }
            +                enqueueTaskArtifactUpdateEvent(taskId, body, ctx);
            +            });
            +
            +        // GET /test/streamingSubscribedCount
            +        router.get("/test/streamingSubscribedCount")
            +            .order(0)
            +            .produces(TEXT_PLAIN)
            +            .handler(ctx -> {
            +                getStreamingSubscribedCount(ctx);
            +            });
            +
            +        // GET /test/queue/childCount/:taskId
            +        router.get("/test/queue/childCount/:taskId")
            +            .order(0)
            +            .produces(TEXT_PLAIN)
            +            .handler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                getChildQueueCount(taskId, ctx);
            +            });
            +
            +        // DELETE /test/task/:taskId/config/:configId
            +        router.delete("/test/task/:taskId/config/:configId")
            +            .order(0)
            +            .blockingHandler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                String configId = ctx.pathParam("configId");
            +                deleteTaskPushNotificationConfig(taskId, configId, ctx);
            +            });
            +
            +        // POST /test/task/:taskId - Save task push notification config
            +        router.post("/test/task/:taskId")
            +            .order(0)
            +            .handler(BodyHandler.create())
            +            .blockingHandler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                String body = ctx.body().asString();
            +                if (body == null) {
            +                    body = "";
            +                }
            +                saveTaskPushNotificationConfig(taskId, body, ctx);
            +            });
            +
            +        // POST /test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs
            +        router.post("/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs")
            +            .order(0)
            +            .blockingHandler(ctx -> {
            +                String taskId = ctx.pathParam("taskId");
            +                String expectedCountStr = ctx.pathParam("expectedCount");
            +                String timeoutMsStr = ctx.pathParam("timeoutMs");
            +                awaitChildQueueCountStable(taskId, expectedCountStr, timeoutMsStr, ctx);
            +            });
            +    }
            +
            +    public void saveTask(String body, RoutingContext rc) {
                     try {
                         Task task = JsonUtil.fromJson(body, Task.class);
                         testUtilsBean.saveTask(task);
            @@ -53,8 +171,7 @@ public void saveTask(@Body String body, RoutingContext rc) {
                     }
                 }
             
            -    @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING)
            -    public void getTask(@Param String taskId,  RoutingContext rc) {
            +    public void getTask(String taskId, RoutingContext rc) {
                     try {
                         Task task = testUtilsBean.getTask(taskId);
                         if (task == null) {
            @@ -73,8 +190,7 @@ public void getTask(@Param String taskId,  RoutingContext rc) {
                     }
                 }
             
            -    @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING)
            -    public void deleteTask(@Param String taskId, RoutingContext rc) {
            +    public void deleteTask(String taskId, RoutingContext rc) {
                     try {
                         Task task = testUtilsBean.getTask(taskId);
                         if (task == null) {
            @@ -92,8 +208,7 @@ public void deleteTask(@Param String taskId, RoutingContext rc) {
                     }
                 }
             
            -    @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST})
            -    public void ensureTaskQueue(@Param String taskId, RoutingContext rc) {
            +    public void ensureTaskQueue(String taskId, RoutingContext rc) {
                     try {
                         testUtilsBean.ensureQueue(taskId);
                         rc.response()
            @@ -104,8 +219,7 @@ public void ensureTaskQueue(@Param String taskId, RoutingContext rc) {
                     }
                 }
             
            -    @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST})
            -    public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) {
            +    public void enqueueTaskStatusUpdateEvent(String taskId, String body, RoutingContext rc) {
             
                     try {
                         TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class);
            @@ -118,8 +232,7 @@ public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body
                     }
                 }
             
            -    @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST})
            -    public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) {
            +    public void enqueueTaskArtifactUpdateEvent(String taskId, String body, RoutingContext rc) {
             
                     try {
                         TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class);
            @@ -132,23 +245,20 @@ public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String bo
                     }
                 }
             
            -    @Route(path = "/test/streamingSubscribedCount", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN})
                 public void getStreamingSubscribedCount(RoutingContext rc) {
                     rc.response()
                             .setStatusCode(200)
                             .end(String.valueOf(streamingSubscribedCount.get()));
                 }
             
            -    @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN})
            -    public void getChildQueueCount(@Param String taskId, RoutingContext rc) {
            +    public void getChildQueueCount(String taskId, RoutingContext rc) {
                     int count = testUtilsBean.getChildQueueCount(taskId);
                     rc.response()
                             .setStatusCode(200)
                             .end(String.valueOf(count));
                 }
             
            -    @Route(path = "/test/task/:taskId/config/:configId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING)
            -    public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String configId, RoutingContext rc) {
            +    public void deleteTaskPushNotificationConfig(String taskId, String configId, RoutingContext rc) {
                     try {
                         Task task = testUtilsBean.getTask(taskId);
                         if (task == null) {
            @@ -166,8 +276,7 @@ public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String
                     }
                 }
             
            -    @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING)
            -    public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) {
            +    public void saveTaskPushNotificationConfig(String taskId, String body, RoutingContext rc) {
                     try {
                         TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class);
                         if (notificationConfig == null) {
            @@ -195,8 +304,7 @@ public void saveTaskPushNotificationConfig(@Param String taskId, @Body String bo
                  * @param timeoutMsStr maximum time to wait in milliseconds (as string)
                  * @param rc the Vert.x routing context
                  */
            -    @Route(path = "/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING)
            -    public void awaitChildQueueCountStable(@Param("taskId") String taskId, @Param("expectedCount") String expectedCountStr, @Param("timeoutMs") String timeoutMsStr, RoutingContext rc) {
            +    public void awaitChildQueueCountStable(String taskId, String expectedCountStr, String timeoutMsStr, RoutingContext rc) {
                     try {
                         int expectedCount = Integer.parseInt(expectedCountStr);
                         long timeoutMs = Long.parseLong(timeoutMsStr);
            diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/AuthTestProfile.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/AuthTestProfile.java
            new file mode 100644
            index 000000000..d27013723
            --- /dev/null
            +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/AuthTestProfile.java
            @@ -0,0 +1,48 @@
            +package org.a2aproject.sdk.server.rest.quarkus;
            +
            +import java.util.Map;
            +
            +import io.quarkus.test.junit.QuarkusTestProfile;
            +
            +/**
            + * Quarkus test profile that enables security for authentication tests.
            + * 

            + * This profile: + *

              + *
            • Enables embedded user store with a test user
            • + *
            • Configures HTTP Basic authentication
            • + *
            • Provides test credentials: username=testuser, password=testpass
            • + *
            + */ +public class AuthTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + // Disable test security (injected test user) - we want REAL authentication + Map.entry("quarkus.test.security.auth.enabled", "false"), + + // Disable TestIdentityProvider auto-authentication (from JSON-RPC tests) + Map.entry("test.identity.auto-auth", "false"), + + // Enable security in agent card + Map.entry("test.agent.security.enabled", "true"), + + // Enable embedded user store + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + + // Enable HTTP Basic authentication + Map.entry("quarkus.http.auth.basic", "true"), + Map.entry("quarkus.http.auth.proactive", "true") + ); + } + + @Override + public String getConfigProfile() { + // Use "test" profile to ensure test beans are active + return "test"; + } +} diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthJdkTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthJdkTest.java new file mode 100644 index 000000000..e55dffa18 --- /dev/null +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthJdkTest.java @@ -0,0 +1,77 @@ +package org.a2aproject.sdk.server.rest.quarkus; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.spec.TransportProtocol; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.junit.jupiter.api.Test; + +/** + * Authentication tests for REST (HTTP JSON) transport with JDK HTTP client. + *

            + * Validates that: + *

              + *
            • {@code @Authenticated} annotations are enforced
            • + *
            • {@code @PermitAll} on getAgentCard() allows public access
            • + *
            • Protected endpoints require valid credentials
            • + *
            + */ +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class QuarkusA2ARestWithAuthJdkTest extends AbstractA2AServerWithAuthTest { + + public QuarkusA2ARestWithAuthJdkTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + // Use AuthInterceptor with inline CredentialService + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new JdkA2AHttpClient()) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + // No auth (for unauthenticated client creation) + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new JdkA2AHttpClient())); + } + + @Test + @Override + public void testBasicAuthWorksViaHttp() throws Exception { + // Override: the base test posts JSON-RPC to "/", which is only + // a valid route in the JSON-RPC module. For REST, use a GET endpoint. + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .get("/tasks/" + MINIMAL_TASK.id()) + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.id()); + } +} diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthVertxTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthVertxTest.java new file mode 100644 index 000000000..8b61061d2 --- /dev/null +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthVertxTest.java @@ -0,0 +1,78 @@ +package org.a2aproject.sdk.server.rest.quarkus; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.spec.TransportProtocol; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; + +/** + * Authentication tests for REST (HTTP JSON) transport with Vert.x HTTP client. + *

            + * Validates that: + *

              + *
            • {@code @Authenticated} annotations are enforced
            • + *
            • {@code @PermitAll} on getAgentCard() allows public access
            • + *
            • Protected endpoints require valid credentials
            • + *
            + */ +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class QuarkusA2ARestWithAuthVertxTest extends AbstractA2AServerWithAuthTest { + + @Inject + Vertx vertx; + + public QuarkusA2ARestWithAuthVertxTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx)) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx))); + } + + @Test + @Override + public void testBasicAuthWorksViaHttp() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .get("/tasks/" + MINIMAL_TASK.id()) + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.id()); + } +} diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/TestIdentityProvider.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/TestIdentityProvider.java new file mode 100644 index 000000000..9bfc6b209 --- /dev/null +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/TestIdentityProvider.java @@ -0,0 +1,37 @@ +package org.a2aproject.sdk.server.rest.quarkus; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.quarkus.arc.properties.IfBuildProperty; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; +import io.quarkus.security.identity.SecurityIdentityAugmentor; +import io.quarkus.arc.Unremovable; + +/** + * Test identity provider that always returns an authenticated user. + *

            + * This allows regular tests to work with {@code @Authenticated} annotations + * without requiring actual HTTP Basic Auth credentials. + *

            + * This bean is disabled when using {@link AuthTestProfile}, which tests real authentication. + */ +@ApplicationScoped +@Unremovable +@IfBuildProperty(name = "test.identity.auto-auth", stringValue = "true", enableIfMissing = true) +public class TestIdentityProvider implements SecurityIdentityAugmentor { + + @Override + public Uni augment(SecurityIdentity identity, io.quarkus.security.identity.AuthenticationRequestContext context) { + // If anonymous, inject a test user + if (identity.isAnonymous()) { + return Uni.createFrom().item(QuarkusSecurityIdentity.builder() + .setPrincipal(() -> "testuser") + .addRole("user") + .setAnonymous(false) + .build()); + } + return Uni.createFrom().item(identity); + } +} diff --git a/reference/rest/src/test/resources/application.properties b/reference/rest/src/test/resources/application.properties index 3700cdf7e..7fbdf1058 100644 --- a/reference/rest/src/test/resources/application.properties +++ b/reference/rest/src/test/resources/application.properties @@ -1 +1,8 @@ -quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttpClient \ No newline at end of file +quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttpClient + +# Security configuration for regular tests +# Inject a test user automatically so @Authenticated checks pass without requiring credentials +# AuthTestProfile overrides this to require REAL HTTP Basic Auth +quarkus.test.security.auth.enabled=true +quarkus.test.security.default-user=testuser +quarkus.test.security.default-roles=user \ No newline at end of file diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerWithAuthTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerWithAuthTest.java new file mode 100644 index 000000000..98b65fbf4 --- /dev/null +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerWithAuthTest.java @@ -0,0 +1,332 @@ +package org.a2aproject.sdk.server.apps.common; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Map; + + +import io.restassured.RestAssured; +import io.restassured.config.ObjectMapperConfig; +import io.restassured.specification.RequestSpecification; +import jakarta.ws.rs.core.MediaType; +import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.config.ClientConfig; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.apps.common.A2AGsonObjectMapper; +import org.a2aproject.sdk.spec.A2AClientException; +import org.a2aproject.sdk.spec.A2AClientHTTPError; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; +import org.a2aproject.sdk.spec.SecurityRequirement; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.junit.jupiter.api.Test; + +/** + * Abstract base class for authentication tests. + *

            + * Provides minimal infrastructure for testing authentication without the full + * server test setup. Tests verify that: + *

              + *
            • {@code @Authenticated} annotations are enforced
            • + *
            • {@code @ActivateRequestContext} is present (prevents CDI context errors)
            • + *
            • Public endpoints remain accessible without credentials
            • + *
            + *

            + * Concrete test classes must implement: + *

              + *
            • {@link #getTransportProtocol()} - protocol identifier
            • + *
            • {@link #getTransportUrl()} - server URL
            • + *
            • {@link #configureTransportWithAuth(ClientBuilder)} - add auth to transport
            • + *
            • {@link #configureTransport(ClientBuilder)} - transport without auth
            • + *
            + */ +public abstract class AbstractA2AServerWithAuthTest { + + protected static final String TEST_USERNAME = "testuser"; + protected static final String TEST_PASSWORD = "testpass"; + protected static final String BASIC_AUTH_SCHEME_NAME = "basicAuth"; + + /** + * Get base64-encoded Basic Auth credentials. + */ + protected static String getEncodedCredentials() { + String credentials = TEST_USERNAME + ":" + TEST_PASSWORD; + return Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8)); + } + + // Minimal test task + protected static final Task MINIMAL_TASK = Task.builder() + .id("task-123") + .contextId("session-xyz") + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) + .build(); + + protected final int serverPort; + private Client authenticatedClient; + private Client unauthenticatedClient; + + protected AbstractA2AServerWithAuthTest(int serverPort) { + this.serverPort = serverPort; + } + + /** + * Get the transport protocol identifier. + */ + protected abstract String getTransportProtocol(); + + /** + * Get the transport URL. + */ + protected abstract String getTransportUrl(); + + /** + * Configure transport without authentication. + */ + protected abstract void configureTransport(ClientBuilder builder); + + /** + * Configure the transport with authentication credentials. + *

            + * Subclasses implement this to add transport-specific authentication + * (e.g., HTTP headers, gRPC call credentials). + * + * @param builder the client builder to configure + */ + protected abstract void configureTransportWithAuth(ClientBuilder builder); + + /** + * Get or create an authenticated client. + */ + protected Client getAuthenticatedClient() throws A2AClientException { + if (authenticatedClient == null) { + authenticatedClient = createAuthenticatedClient(); + } + return authenticatedClient; + } + + /** + * Get or create an unauthenticated client for testing auth failures. + */ + protected Client getUnauthenticatedClient() throws A2AClientException { + if (unauthenticatedClient == null) { + unauthenticatedClient = createUnauthenticatedClient(); + } + return unauthenticatedClient; + } + + /** + * Create an authenticated client. + */ + private Client createAuthenticatedClient() throws A2AClientException { + AgentCard agentCard = fetchAgentCardFromServer(); + ClientConfig clientConfig = new ClientConfig.Builder() + .setStreaming(false) // Non-streaming for simple tests + .build(); + + ClientBuilder clientBuilder = Client.builder(agentCard) + .clientConfig(clientConfig); + + configureTransportWithAuth(clientBuilder); + + return clientBuilder.build(); + } + + /** + * Create an unauthenticated client for testing authentication failures. + */ + private Client createUnauthenticatedClient() throws A2AClientException { + AgentCard agentCard = fetchAgentCardFromServer(); + ClientConfig clientConfig = new ClientConfig.Builder() + .setStreaming(false) + .build(); + + ClientBuilder clientBuilder = Client.builder(agentCard) + .clientConfig(clientConfig); + + configureTransport(clientBuilder); // No auth + + return clientBuilder.build(); + } + + /** + * Fetch the AgentCard from the server's /.well-known/agent-card.json endpoint. + * Subclasses can override for transports that don't serve the agent card via HTTP. + */ + protected AgentCard fetchAgentCardFromServer() { + try { + HttpClient httpClient = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/.well-known/agent-card.json")) + .GET() + .build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() != 200) { + throw new RuntimeException("Failed to fetch agent card: " + response.statusCode()); + } + + return JsonUtil.fromJson(response.body(), AgentCard.class); + } catch (Exception e) { + throw new RuntimeException("Failed to fetch AgentCard from server", e); + } + } + + /** + * RestAssured helper configured with Gson object mapper. + */ + protected static RequestSpecification given() { + return RestAssured.given() + .config(RestAssured.config() + .objectMapperConfig(new ObjectMapperConfig(A2AGsonObjectMapper.INSTANCE))); + } + + /** + * RestAssured helper with authentication. + */ + protected RequestSpecification givenAuthenticated() { + return given() + .auth().basic(TEST_USERNAME, TEST_PASSWORD); + } + + /** + * RestAssured helper without authentication. + */ + protected RequestSpecification givenUnauthenticated() { + return given(); + } + + /** + * Save a task in the test task store via HTTP. + */ + protected void saveTaskInTaskStore(Task task) throws Exception { + HttpClient httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task")) + .header("Content-Type", MediaType.APPLICATION_JSON) + .POST(HttpRequest.BodyPublishers.ofString(JsonUtil.toJson(task))) + .build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200 && response.statusCode() != 204) { + throw new RuntimeException("Failed to save task: " + response.statusCode() + " " + response.body()); + } + } + + /** + * Delete a task from the test task store via HTTP. + */ + protected void deleteTaskInTaskStore(String taskId) throws Exception { + HttpClient httpClient = HttpClient.newHttpClient(); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task/" + taskId)) + .DELETE() + .build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() != 200 && response.statusCode() != 204) { + throw new RuntimeException("Failed to delete task: " + response.statusCode() + " " + response.body()); + } + } + + /** + * Test that getTask() requires authentication. + *

            + * The AuthTestProfile configures HTTP Basic Auth and an embedded user store. + * This test verifies that unauthenticated requests fail. + */ + @Test + public void testGetTaskRequiresAuthenticationUnauthenticated() throws Exception { + // Save task in store + saveTaskInTaskStore(MINIMAL_TASK); + + // Test unauthenticated request fails + Client unauthClient = getUnauthenticatedClient(); + A2AClientException error = assertThrows(A2AClientException.class, () -> { + unauthClient.getTask(new TaskQueryParams(MINIMAL_TASK.id())); + }); + // Verify it's an authentication failure + assertTrue(error.getMessage().contains("Authentication failed") || + error.getMessage().contains("401") || + error.getMessage().contains("Unauthorized"), + "Expected authentication error, got: " + error.getMessage()); + + // Cleanup + deleteTaskInTaskStore(MINIMAL_TASK.id()); + } + + /** + * Test that getTask() succeeds with authentication. + *

            + * The client sends Basic Auth headers matching the credentials in the embedded user store. + */ + @Test + public void testGetTaskWithAuthentication() throws Exception { + // Save task in store + saveTaskInTaskStore(MINIMAL_TASK); + + // Test authenticated request succeeds (client includes Basic Auth headers) + Client client = getAuthenticatedClient(); + Task result = client.getTask(new TaskQueryParams(MINIMAL_TASK.id())); + assertNotNull(result); + + // Cleanup + deleteTaskInTaskStore(MINIMAL_TASK.id()); + } + + /** + * Test that getAgentCard() is publicly accessible without authentication. + *

            + * The /.well-known/agent-card.json endpoint should be accessible without + * credentials to allow agent discovery, even when HTTP Basic Auth is enabled. + */ + @Test + public void testGetAgentCardIsPublic() { + givenUnauthenticated() + .get("/.well-known/agent-card.json") + .then() + .statusCode(200); + } + + /** + * Test that Basic Auth credentials actually work via direct HTTP. + *

            + * This test uses RestAssured with Basic Auth to verify the embedded user store + * is properly configured and accepts our test credentials. + */ + @Test + public void testBasicAuthWorksViaHttp() throws Exception { + // Save task in store + saveTaskInTaskStore(MINIMAL_TASK); + + // Test with valid credentials via RestAssured + givenAuthenticated() + .contentType("application/json") + .body("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"getTask\",\"params\":{\"id\":\"" + MINIMAL_TASK.id() + "\"}}") + .post("/") + .then() + .statusCode(200); + + // Cleanup + deleteTaskInTaskStore(MINIMAL_TASK.id()); + } +} diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java index 12baa654e..fa90cbfd8 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java @@ -11,12 +11,16 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; import org.a2aproject.sdk.server.ExtendedAgentCard; import org.a2aproject.sdk.server.PublicAgentCard; import org.a2aproject.sdk.spec.AgentCapabilities; import org.a2aproject.sdk.spec.AgentCard; import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; +import org.a2aproject.sdk.spec.SecurityRequirement; +import org.eclipse.microprofile.config.inject.ConfigProperty; import io.quarkus.arc.profile.IfBuildProfile; import org.junit.jupiter.api.Assertions; @@ -27,6 +31,11 @@ public class AgentCardProducer { private static final String PREFERRED_TRANSPORT = "preferred-transport"; private static final String A2A_REQUESTHANDLER_TEST_PROPERTIES = "/a2a-requesthandler-test.properties"; + private static final String BASIC_AUTH_SCHEME_NAME = "basicAuth"; + + @Inject + @ConfigProperty(name = "test.agent.security.enabled", defaultValue = "false") + boolean securityEnabled; @Produces @PublicAgentCard @@ -50,6 +59,18 @@ public AgentCard agentCard() { .defaultOutputModes(Collections.singletonList("text")) .skills(new ArrayList<>()) .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, transportUrl))); + + // Add security configuration if enabled (for authentication tests) + if (securityEnabled) { + builder.securitySchemes(java.util.Map.of( + BASIC_AUTH_SCHEME_NAME, + new HTTPAuthSecurityScheme(null, "basic", "HTTP Basic authentication"))) + .securityRequirements(java.util.List.of( + SecurityRequirement.builder() + .scheme(BASIC_AUTH_SCHEME_NAME, java.util.List.of()) + .build())); + } + return builder.build(); } diff --git a/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java index ec5da9c59..90e99e848 100644 --- a/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java +++ b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java @@ -472,6 +472,7 @@ private void convertToStreamResponse(Flow.Publisher publishe CompletableFuture.runAsync(() -> { publisher.subscribe(new Flow.Subscriber() { private Flow.@Nullable Subscription subscription; + private final AtomicBoolean completed = new AtomicBoolean(false); @Override public void onSubscribe(Flow.Subscription subscription) { @@ -510,7 +511,11 @@ public void onNext(StreamingEventKind event) { || state == org.a2aproject.sdk.grpc.TaskState.TASK_STATE_FAILED || state == org.a2aproject.sdk.grpc.TaskState.TASK_STATE_REJECTED; if (isFinal) { - responseObserver.onCompleted(); + // Cancel subscription to prevent onComplete() from being called after we close the stream + if (this.subscription != null) { + subscription.cancel(); + } + completeStream(); } else { if (this.subscription != null) { subscription.request(1); @@ -534,12 +539,19 @@ public void onError(Throwable throwable) { } else { handleInternalError(responseObserver, throwable); } - responseObserver.onCompleted(); + completeStream(); } @Override public void onComplete() { - responseObserver.onCompleted(); + completeStream(); + } + + private void completeStream() { + // Atomically check and set - only the first caller will proceed + if (completed.compareAndSet(false, true)) { + responseObserver.onCompleted(); + } } }); }, getExecutor()); @@ -652,12 +664,12 @@ private ServerCallContext createCallContext(StreamObserver responseObserv io.grpc.Metadata grpcMetadata = GrpcContextKeys.METADATA_KEY.get(currentContext); if (grpcMetadata != null) { state.put("grpc_metadata", grpcMetadata); + Map headers = new HashMap<>(); + for (String key : grpcMetadata.keys()) { + headers.put(key, grpcMetadata.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER))); + } + state.put("headers", headers); } - Map headers= new HashMap<>(); - for(String key : grpcMetadata.keys()) { - headers.put(key, grpcMetadata.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER))); - } - state.put("headers", headers); String methodName = GrpcContextKeys.GRPC_METHOD_NAME_KEY.get(currentContext); if (methodName != null) { state.put("grpc_method_name", methodName); From 815d07b0d76c8e178e585ee60cd321e443a6750a Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 5 May 2026 11:35:15 +0100 Subject: [PATCH 134/192] Review fixes --- .../common/quarkus/VertxSecurityHelper.java | 28 ++++++++--- reference/grpc/pom.xml | 7 +-- .../server/grpc/quarkus/AuthTestProfile.java | 47 ------------------ .../quarkus/QuarkusA2AGrpcWithAuthTest.java | 1 + reference/jsonrpc/pom.xml | 5 -- .../server/apps/quarkus/A2AServerRoutes.java | 2 +- .../QuarkusA2AJSONRPCWithAuthJdkTest.java | 1 + .../QuarkusA2AJSONRPCWithAuthVertxTest.java | 1 + .../src/test/resources/application.properties | 7 --- reference/rest/pom.xml | 5 -- .../server/rest/quarkus/A2AServerRoutes.java | 2 +- .../server/rest/quarkus/AuthTestProfile.java | 48 ------------------- .../QuarkusA2ARestWithAuthJdkTest.java | 1 + .../QuarkusA2ARestWithAuthVertxTest.java | 1 + .../rest/quarkus/TestIdentityProvider.java | 37 -------------- .../src/test/resources/application.properties | 7 --- tests/server-common/pom.xml | 10 ++++ .../server/apps/common}/AuthTestProfile.java | 10 +++- .../apps/common}/TestIdentityProvider.java | 2 +- 19 files changed, 48 insertions(+), 174 deletions(-) delete mode 100644 reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/AuthTestProfile.java delete mode 100644 reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/AuthTestProfile.java delete mode 100644 reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/TestIdentityProvider.java rename {reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus => tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common}/AuthTestProfile.java (80%) rename {reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus => tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common}/TestIdentityProvider.java (96%) diff --git a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java index 8419b8426..9aa1799b4 100644 --- a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java +++ b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java @@ -7,7 +7,9 @@ import io.quarkus.arc.Arc; import io.quarkus.arc.ManagedContext; import io.quarkus.security.identity.CurrentIdentityAssociation; +import io.quarkus.vertx.http.runtime.security.ChallengeData; import io.quarkus.vertx.http.runtime.security.HttpAuthenticator; +import io.vertx.core.Context; import io.vertx.ext.web.RoutingContext; /** @@ -48,7 +50,7 @@ * myAuthenticatedMethod(); // Has @Authenticated annotation * }); * } catch (UnauthorizedException | ForbiddenException e) { - * VertxSecurityHelper.handleAuthError(ctx, e); + * securityHelper.handleAuthError(ctx, e); * } catch (Exception e) { * VertxSecurityHelper.handleGenericError(ctx); * } @@ -68,9 +70,8 @@ public final class VertxSecurityHelper { @Inject Instance currentIdentityAssociation; - public VertxSecurityHelper() { - // Utility class - no instantiation + // CDI-managed constructor } /** @@ -98,6 +99,10 @@ public VertxSecurityHelper() { * @throws RuntimeException if the task throws an exception */ public void runInRequestContext(RoutingContext ctx, Runnable task) { + if (Context.isOnEventLoopThread()) { + throw new IllegalStateException( + "Cannot perform blocking authentication on event loop thread. Use blockingHandler()."); + } ManagedContext requestContext = Arc.container().requestContext(); boolean wasActive = requestContext.isActive(); if (!wasActive) { @@ -124,22 +129,31 @@ public void runInRequestContext(RoutingContext ctx, Runnable task) { * *

              *
            • {@code ForbiddenException} → HTTP 403 Forbidden
            • - *
            • All other auth errors → HTTP 401 Unauthorized with {@code WWW-Authenticate: Basic} header
            • + *
            • All other auth errors → delegates to {@link HttpAuthenticator#getChallenge} to obtain + * the correct {@code WWW-Authenticate} header for the configured auth mechanism + * (Basic, Bearer, etc.) and sends HTTP 401 with the challenge header
            • *
            * * @param ctx the routing context * @param e the authentication or authorization exception */ - public static void handleAuthError(RoutingContext ctx, Exception e) { + public void handleAuthError(RoutingContext ctx, Exception e) { if (!ctx.response().ended()) { if (e instanceof io.quarkus.security.ForbiddenException) { ctx.response() .setStatusCode(403) .end(); } else { + int status = 401; + if (!httpAuthenticator.isUnsatisfied()) { + ChallengeData challenge = httpAuthenticator.get().getChallenge(ctx).await().indefinitely(); + if (challenge != null) { + status = challenge.status; + ctx.response().putHeader(challenge.headerName, challenge.headerContent); + } + } ctx.response() - .setStatusCode(401) - .putHeader("WWW-Authenticate", "Basic realm=\"Quarkus\"") + .setStatusCode(status) .end(); } } diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index 0895d7b7f..74240053a 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -105,11 +105,6 @@ quarkus-elytron-security-properties-file test - - io.quarkus - quarkus-test-security - test - - \ No newline at end of file + \ No newline at end of file diff --git a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/AuthTestProfile.java b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/AuthTestProfile.java deleted file mode 100644 index 610e2a825..000000000 --- a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/AuthTestProfile.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.a2aproject.sdk.server.grpc.quarkus; - -import java.util.Map; - -import io.quarkus.test.junit.QuarkusTestProfile; - -/** - * Quarkus test profile that enables security for authentication tests. - *

            - * This profile: - *

              - *
            • Enables embedded user store with a test user
            • - *
            • Configures HTTP Basic authentication
            • - *
            • Provides test credentials: username=testuser, password=testpass
            • - *
            - */ -public class AuthTestProfile implements QuarkusTestProfile { - - @Override - public Map getConfigOverrides() { - return Map.ofEntries( - // Disable test security (injected test user) - we want REAL authentication - Map.entry("quarkus.test.security.auth.enabled", "false"), - - // Enable embedded user store - Map.entry("quarkus.security.users.embedded.enabled", "true"), - Map.entry("quarkus.security.users.embedded.plain-text", "true"), - Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), - Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), - - // Enable security in agent card - Map.entry("test.agent.security.enabled", "true"), - - // Enable authorization so @Authenticated is enforced - Map.entry("test.authorization.enabled", "true"), - - // Enable HTTP Basic authentication - Map.entry("quarkus.http.auth.basic", "true") - ); - } - - @Override - public String getConfigProfile() { - // Use "test" profile to ensure test beans are active - return "test"; - } -} diff --git a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcWithAuthTest.java b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcWithAuthTest.java index 1693150db..106e3953c 100644 --- a/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcWithAuthTest.java +++ b/reference/grpc/src/test/java/org/a2aproject/sdk/server/grpc/quarkus/QuarkusA2AGrpcWithAuthTest.java @@ -8,6 +8,7 @@ import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; import org.a2aproject.sdk.server.PublicAgentCard; import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.server.apps.common.AuthTestProfile; import org.a2aproject.sdk.spec.AgentCard; import org.a2aproject.sdk.spec.TransportProtocol; import io.grpc.ManagedChannel; diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 5a236f3d1..d82c52ab6 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -110,10 +110,5 @@ quarkus-elytron-security-properties-file test - - io.quarkus - quarkus-test-security - test - diff --git a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index 8e5f52b82..aadcc5d12 100644 --- a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -216,7 +216,7 @@ void setupRoutes(@Observes Router router) { invokeJSONRPCHandler(ctx.body().asString(), ctx); }); } catch (UnauthorizedException | ForbiddenException e) { - VertxSecurityHelper.handleAuthError(ctx, e); + vertxSecurityHelper.handleAuthError(ctx, e); } catch (Exception e) { VertxSecurityHelper.handleGenericError(ctx); } diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthJdkTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthJdkTest.java index ba65e7cfa..60c3ca1a1 100644 --- a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthJdkTest.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthJdkTest.java @@ -7,6 +7,7 @@ import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.server.apps.common.AuthTestProfile; import org.a2aproject.sdk.spec.TransportProtocol; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthVertxTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthVertxTest.java index 34c5f77da..1625c47a5 100644 --- a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthVertxTest.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthVertxTest.java @@ -7,6 +7,7 @@ import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.server.apps.common.AuthTestProfile; import org.a2aproject.sdk.spec.TransportProtocol; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; diff --git a/reference/jsonrpc/src/test/resources/application.properties b/reference/jsonrpc/src/test/resources/application.properties index f3e1a801d..d5acb5291 100644 --- a/reference/jsonrpc/src/test/resources/application.properties +++ b/reference/jsonrpc/src/test/resources/application.properties @@ -4,10 +4,3 @@ quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttp quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG - -# Security configuration for regular tests -# Provide a test identity provider that always authenticates -# AuthTestProfile overrides this to require real HTTP Basic Auth -%test.quarkus.test-security.test-enabled=true -%test.quarkus.test-security.user=testuser -%test.quarkus.test-security.roles=user diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index 1f94b651e..deef848fd 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -114,11 +114,6 @@ quarkus-elytron-security-properties-file test - - io.quarkus - quarkus-test-security - test - diff --git a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java index a718644fd..a563f20a9 100644 --- a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java @@ -253,7 +253,7 @@ private Handler authenticated(Consumer action) { try { vertxSecurityHelper.runInRequestContext(ctx, () -> action.accept(ctx)); } catch (UnauthorizedException | ForbiddenException e) { - VertxSecurityHelper.handleAuthError(ctx, e); + vertxSecurityHelper.handleAuthError(ctx, e); } catch (Exception e) { VertxSecurityHelper.handleGenericError(ctx); } diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/AuthTestProfile.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/AuthTestProfile.java deleted file mode 100644 index d27013723..000000000 --- a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/AuthTestProfile.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.a2aproject.sdk.server.rest.quarkus; - -import java.util.Map; - -import io.quarkus.test.junit.QuarkusTestProfile; - -/** - * Quarkus test profile that enables security for authentication tests. - *

            - * This profile: - *

              - *
            • Enables embedded user store with a test user
            • - *
            • Configures HTTP Basic authentication
            • - *
            • Provides test credentials: username=testuser, password=testpass
            • - *
            - */ -public class AuthTestProfile implements QuarkusTestProfile { - - @Override - public Map getConfigOverrides() { - return Map.ofEntries( - // Disable test security (injected test user) - we want REAL authentication - Map.entry("quarkus.test.security.auth.enabled", "false"), - - // Disable TestIdentityProvider auto-authentication (from JSON-RPC tests) - Map.entry("test.identity.auto-auth", "false"), - - // Enable security in agent card - Map.entry("test.agent.security.enabled", "true"), - - // Enable embedded user store - Map.entry("quarkus.security.users.embedded.enabled", "true"), - Map.entry("quarkus.security.users.embedded.plain-text", "true"), - Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), - Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), - - // Enable HTTP Basic authentication - Map.entry("quarkus.http.auth.basic", "true"), - Map.entry("quarkus.http.auth.proactive", "true") - ); - } - - @Override - public String getConfigProfile() { - // Use "test" profile to ensure test beans are active - return "test"; - } -} diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthJdkTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthJdkTest.java index e55dffa18..663bd836a 100644 --- a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthJdkTest.java +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthJdkTest.java @@ -6,6 +6,7 @@ import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.server.apps.common.AuthTestProfile; import org.a2aproject.sdk.spec.TransportProtocol; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthVertxTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthVertxTest.java index 8b61061d2..500f896f7 100644 --- a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthVertxTest.java +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthVertxTest.java @@ -6,6 +6,7 @@ import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.server.apps.common.AuthTestProfile; import org.a2aproject.sdk.spec.TransportProtocol; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/TestIdentityProvider.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/TestIdentityProvider.java deleted file mode 100644 index 9bfc6b209..000000000 --- a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/TestIdentityProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.a2aproject.sdk.server.rest.quarkus; - -import jakarta.enterprise.context.ApplicationScoped; - -import io.quarkus.arc.properties.IfBuildProperty; -import io.quarkus.security.identity.SecurityIdentity; -import io.quarkus.security.runtime.QuarkusSecurityIdentity; -import io.smallrye.mutiny.Uni; -import io.quarkus.security.identity.SecurityIdentityAugmentor; -import io.quarkus.arc.Unremovable; - -/** - * Test identity provider that always returns an authenticated user. - *

            - * This allows regular tests to work with {@code @Authenticated} annotations - * without requiring actual HTTP Basic Auth credentials. - *

            - * This bean is disabled when using {@link AuthTestProfile}, which tests real authentication. - */ -@ApplicationScoped -@Unremovable -@IfBuildProperty(name = "test.identity.auto-auth", stringValue = "true", enableIfMissing = true) -public class TestIdentityProvider implements SecurityIdentityAugmentor { - - @Override - public Uni augment(SecurityIdentity identity, io.quarkus.security.identity.AuthenticationRequestContext context) { - // If anonymous, inject a test user - if (identity.isAnonymous()) { - return Uni.createFrom().item(QuarkusSecurityIdentity.builder() - .setPrincipal(() -> "testuser") - .addRole("user") - .setAnonymous(false) - .build()); - } - return Uni.createFrom().item(identity); - } -} diff --git a/reference/rest/src/test/resources/application.properties b/reference/rest/src/test/resources/application.properties index 7fbdf1058..aa8c7caf1 100644 --- a/reference/rest/src/test/resources/application.properties +++ b/reference/rest/src/test/resources/application.properties @@ -1,8 +1 @@ quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttpClient - -# Security configuration for regular tests -# Inject a test user automatically so @Authenticated checks pass without requiring credentials -# AuthTestProfile overrides this to require REAL HTTP Basic Auth -quarkus.test.security.auth.enabled=true -quarkus.test.security.default-user=testuser -quarkus.test.security.default-roles=user \ No newline at end of file diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index 31ee8fbb2..3c688564e 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -55,6 +55,16 @@ quarkus-arc test + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-junit5 + test + org.a2aproject.sdk a2a-java-sdk-client-transport-jsonrpc diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/AuthTestProfile.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AuthTestProfile.java similarity index 80% rename from reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/AuthTestProfile.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AuthTestProfile.java index 31e0d22dd..86d1546c3 100644 --- a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/AuthTestProfile.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AuthTestProfile.java @@ -1,4 +1,4 @@ -package org.a2aproject.sdk.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.common; import java.util.Map; @@ -19,12 +19,18 @@ public class AuthTestProfile implements QuarkusTestProfile { @Override public Map getConfigOverrides() { return Map.ofEntries( - // Disable the TestIdentityProvider - we want real authentication + // Disable TestIdentityProvider auto-authentication Map.entry("test.identity.auto-auth", "false"), + // Disable Quarkus test security + Map.entry("quarkus.test.security.auth.enabled", "false"), + // Enable security in AgentCard (server advertises Basic Auth support) Map.entry("test.agent.security.enabled", "true"), + // Enable authorization so @Authenticated is enforced (used by gRPC) + Map.entry("test.authorization.enabled", "true"), + // Enable embedded user store Map.entry("quarkus.security.users.embedded.enabled", "true"), Map.entry("quarkus.security.users.embedded.plain-text", "true"), diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/TestIdentityProvider.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestIdentityProvider.java similarity index 96% rename from reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/TestIdentityProvider.java rename to tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestIdentityProvider.java index d6049a3e4..2f964c445 100644 --- a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/TestIdentityProvider.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestIdentityProvider.java @@ -1,4 +1,4 @@ -package org.a2aproject.sdk.server.apps.quarkus; +package org.a2aproject.sdk.server.apps.common; import jakarta.enterprise.context.ApplicationScoped; From 294bd1cef3d0edb5fe4c04104fffa93746181daf Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 5 May 2026 14:36:32 +0200 Subject: [PATCH 135/192] Apply suggestion from @ehsavoie --- .../main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java index b90ddb09c..bdce6e275 100644 --- a/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AClientHTTPError.java @@ -62,7 +62,7 @@ public A2AClientHTTPError(int code, String message, Object data) { Assert.checkNotNullParam("message", message); this.code = code; this.message = message; - this.responseBody = data instanceof String s ? s : null; + this.responseBody = data instanceof String s ? s : ""; } /** From 534e4e5c7888c473c1be1bd88ce8f30ed19a756a Mon Sep 17 00:00:00 2001 From: Daria Wieliczko Date: Mon, 4 May 2026 13:06:55 +0000 Subject: [PATCH 136/192] feat(client): add Android HTTP client and remove fallback in factory - Port changes from PR 806 to main branch - Add AndroidA2AHttpClient using HttpURLConnection in a new extras module - Update A2AHttpClientFactory to fail fast if no provider is found - Add abstract test classes in http-client and concrete implementations in android module --- boms/extras/pom.xml | 5 + boms/extras/src/it/extras-usage-test/pom.xml | 4 + extras/http-client-android/pom.xml | 60 ++++ .../sdk/client/http/AndroidA2AHttpClient.java | 290 ++++++++++++++++++ .../http/AndroidA2AHttpClientProvider.java | 33 ++ ...ject.sdk.client.http.A2AHttpClientProvider | 1 + .../http/AndroidA2AHttpClientFactoryTest.java | 41 +++ .../AndroidA2AHttpClientIntegrationTest.java | 9 + .../http/AndroidA2AHttpClientSSETest.java | 9 + .../client/http/AndroidA2AHttpClientTest.java | 59 ++++ http-client/pom.xml | 20 ++ .../sdk/client/http/A2AHttpClientFactory.java | 22 +- .../AbstractA2AHttpClientIntegrationTest.java | 216 +++++++++++++ .../http/AbstractA2AHttpClientSSETest.java | 255 +++++++++++++++ pom.xml | 13 + 15 files changed, 1030 insertions(+), 7 deletions(-) create mode 100644 extras/http-client-android/pom.xml create mode 100644 extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClient.java create mode 100644 extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientProvider.java create mode 100644 extras/http-client-android/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider create mode 100644 extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientFactoryTest.java create mode 100644 extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientIntegrationTest.java create mode 100644 extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientSSETest.java create mode 100644 extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientTest.java create mode 100644 http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientIntegrationTest.java create mode 100644 http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientSSETest.java diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 799a09dde..2e36f899d 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -34,6 +34,11 @@ a2a-java-extras-common ${project.version} + + ${project.groupId} + a2a-java-sdk-http-client-android + ${project.version} + ${project.groupId} a2a-java-sdk-http-client-vertx diff --git a/boms/extras/src/it/extras-usage-test/pom.xml b/boms/extras/src/it/extras-usage-test/pom.xml index 67792ea5d..bca59ad4f 100644 --- a/boms/extras/src/it/extras-usage-test/pom.xml +++ b/boms/extras/src/it/extras-usage-test/pom.xml @@ -44,6 +44,10 @@ org.a2aproject.sdk a2a-java-extras-common + + org.a2aproject.sdk + a2a-java-sdk-http-client-android + org.a2aproject.sdk a2a-java-sdk-http-client-vertx diff --git a/extras/http-client-android/pom.xml b/extras/http-client-android/pom.xml new file mode 100644 index 000000000..6964df341 --- /dev/null +++ b/extras/http-client-android/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.0.Beta2-SNAPSHOT + ../../pom.xml + + a2a-java-sdk-http-client-android + jar + + Java SDK A2A HTTP Client: Android + Java SDK for the Agent2Agent Protocol (A2A) - Android HTTP Client + + + + ${project.groupId} + a2a-java-sdk-http-client + + + ${project.groupId} + a2a-java-sdk-spec + + + + ${project.groupId} + a2a-java-sdk-http-client + test-jar + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + org.mock-server + mockserver-netty + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + Android Runtime + + + + + + diff --git a/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClient.java b/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClient.java new file mode 100644 index 000000000..21e585398 --- /dev/null +++ b/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClient.java @@ -0,0 +1,290 @@ +package org.a2aproject.sdk.client.http; + +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; +import static java.net.HttpURLConnection.HTTP_MULT_CHOICE; +import static java.net.HttpURLConnection.HTTP_OK; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; + +import org.a2aproject.sdk.common.A2AErrorMessages; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.function.Consumer; + +/** Android-specific implementation of {@link A2AHttpClient} using {@link HttpURLConnection}. */ +public class AndroidA2AHttpClient implements A2AHttpClient { + + private static final Executor NET_EXECUTOR = Executors.newCachedThreadPool(r -> { + Thread t = new Thread(r, "A2A-Android-Net"); + t.setDaemon(true); + return t; + }); + + @Override + public GetBuilder createGet() { + return new AndroidGetBuilder(); + } + + @Override + public PostBuilder createPost() { + return new AndroidPostBuilder(); + } + + @Override + public DeleteBuilder createDelete() { + return new AndroidDeleteBuilder(); + } + + private abstract static class AndroidBuilder> implements Builder { + protected String url = ""; + protected Map headers = new HashMap<>(); + + @Override + public T url(String url) { + this.url = url; + return self(); + } + + @Override + public T addHeader(String name, String value) { + headers.put(name, value); + return self(); + } + + @Override + public T addHeaders(Map headers) { + if (headers != null) { + this.headers.putAll(headers); + } + return self(); + } + + @SuppressWarnings("unchecked") + protected T self() { + return (T) this; + } + + protected HttpURLConnection createConnection(String method, boolean isSSE) throws IOException { + URL urlObj; + try { + urlObj = new URI(url).toURL(); + } catch (URISyntaxException e) { + throw new MalformedURLException("Invalid URL: " + url); + } + HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection(); + connection.setRequestMethod(method); + connection.setConnectTimeout(15000); // 15 seconds + connection.setReadTimeout(60000); // 60 seconds + for (Map.Entry header : headers.entrySet()) { + connection.setRequestProperty(header.getKey(), header.getValue()); + } + if (isSSE) { + connection.setRequestProperty(A2AHttpClient.ACCEPT, A2AHttpClient.EVENT_STREAM); + } + return connection; + } + + protected static String readStreamWithLimit(InputStream is) throws IOException { + if (is == null) { + return ""; + } + int maxResponseSize = 10 * 1024 * 1024; // 10 MB + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + StringBuilder sb = new StringBuilder(); + String line; + boolean first = true; + while ((line = reader.readLine()) != null) { + if (sb.length() + line.length() > maxResponseSize) { + throw new IOException("Response size exceeds limit"); + } + if (!first) { + sb.append('\n'); + } + sb.append(line); + first = false; + } + return sb.toString(); + } + } + + protected A2AHttpResponse execute(HttpURLConnection connection) throws IOException { + int status = connection.getResponseCode(); + String body = ""; + try (InputStream is = + (status >= HTTP_OK && status < HTTP_MULT_CHOICE) + ? connection.getInputStream() + : connection.getErrorStream()) { + body = readStreamWithLimit(is); + } + + if (status == HTTP_UNAUTHORIZED) { + throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); + } else if (status == HTTP_FORBIDDEN) { + throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); + } + + return new AndroidHttpResponse(status, body); + } + + protected void processSSEResponse( + HttpURLConnection connection, + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) { + try { + int status = connection.getResponseCode(); + if (status != HTTP_OK) { + if (status == HTTP_UNAUTHORIZED) { + errorConsumer.accept(new IOException(A2AErrorMessages.AUTHENTICATION_FAILED)); + return; + } else if (status == HTTP_FORBIDDEN) { + errorConsumer.accept(new IOException(A2AErrorMessages.AUTHORIZATION_FAILED)); + return; + } + + String errorBody = ""; + try (InputStream es = connection.getErrorStream()) { + errorBody = readStreamWithLimit(es); + } + errorConsumer.accept( + new IOException("Request failed with status " + status + ":" + errorBody)); + return; + } + + try (InputStream is = connection.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("data:")) { + String data = line.substring(5).trim(); + if (!data.isEmpty()) { + messageConsumer.accept(data); + } + } + } + completeRunnable.run(); + } + } catch (Exception e) { + errorConsumer.accept(e); + } finally { + connection.disconnect(); + } + } + + protected CompletableFuture executeAsyncSSE( + HttpURLConnection connection, + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) { + return CompletableFuture.runAsync( + () -> processSSEResponse(connection, messageConsumer, errorConsumer, completeRunnable), + NET_EXECUTOR); + } + } + + private static class AndroidGetBuilder extends AndroidBuilder implements GetBuilder { + @Override + public A2AHttpResponse get() throws IOException { + HttpURLConnection connection = createConnection("GET", false); + try { + return execute(connection); + } catch (IOException e) { + connection.disconnect(); + throw e; + } + } + + @Override + public CompletableFuture getAsyncSSE( + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) + throws IOException { + HttpURLConnection connection = createConnection("GET", true); + return executeAsyncSSE(connection, messageConsumer, errorConsumer, completeRunnable); + } + } + + private static class AndroidPostBuilder extends AndroidBuilder + implements PostBuilder { + private String body = ""; + + @Override + public PostBuilder body(String body) { + this.body = body; + return this; + } + + @Override + public A2AHttpResponse post() throws IOException { + HttpURLConnection connection = createConnection("POST", false); + connection.setDoOutput(true); + try { + try (OutputStream os = connection.getOutputStream()) { + os.write(body.getBytes(StandardCharsets.UTF_8)); + } + return execute(connection); + } catch (IOException e) { + connection.disconnect(); + throw e; + } + } + + @Override + public CompletableFuture postAsyncSSE( + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) + throws IOException { + HttpURLConnection connection = createConnection("POST", true); + connection.setDoOutput(true); + + return CompletableFuture.runAsync( + () -> { + try { + try (OutputStream os = connection.getOutputStream()) { + os.write(body.getBytes(StandardCharsets.UTF_8)); + } + processSSEResponse(connection, messageConsumer, errorConsumer, completeRunnable); + } catch (Exception e) { + errorConsumer.accept(e); + connection.disconnect(); + } + }, NET_EXECUTOR); + } + } + + private static class AndroidDeleteBuilder extends AndroidBuilder + implements DeleteBuilder { + @Override + public A2AHttpResponse delete() throws IOException { + HttpURLConnection connection = createConnection("DELETE", false); + try { + return execute(connection); + } catch (IOException e) { + connection.disconnect(); + throw e; + } + } + } + + private record AndroidHttpResponse(int status, String body) implements A2AHttpResponse { + @Override + public boolean success() { + return status >= HTTP_OK && status < HTTP_MULT_CHOICE; + } + } +} diff --git a/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientProvider.java b/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientProvider.java new file mode 100644 index 000000000..25214a60e --- /dev/null +++ b/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientProvider.java @@ -0,0 +1,33 @@ +package org.a2aproject.sdk.client.http; + +/** + * Service provider for {@link AndroidA2AHttpClient}. + */ +public final class AndroidA2AHttpClientProvider implements A2AHttpClientProvider { + + private static final boolean ANDROID_AVAILABLE = isAndroidAvailable(); + + private static boolean isAndroidAvailable() { + String runtimeName = System.getProperty("java.runtime.name"); + return runtimeName != null && runtimeName.toLowerCase(java.util.Locale.ENGLISH).contains("android"); + } + + @Override + public A2AHttpClient create() { + if (!ANDROID_AVAILABLE) { + throw new IllegalStateException( + "Android classes are not available. This provider is only supported on Android."); + } + return new AndroidA2AHttpClient(); + } + + @Override + public int priority() { + return ANDROID_AVAILABLE ? 110 : -1; // Higher priority than Vert.x on Android + } + + @Override + public String name() { + return "android"; + } +} diff --git a/extras/http-client-android/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider b/extras/http-client-android/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider new file mode 100644 index 000000000..9bf99369a --- /dev/null +++ b/extras/http-client-android/src/main/resources/META-INF/services/org.a2aproject.sdk.client.http.A2AHttpClientProvider @@ -0,0 +1 @@ +org.a2aproject.sdk.client.http.AndroidA2AHttpClientProvider diff --git a/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientFactoryTest.java b/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientFactoryTest.java new file mode 100644 index 000000000..fd5c0be2a --- /dev/null +++ b/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientFactoryTest.java @@ -0,0 +1,41 @@ +package org.a2aproject.sdk.client.http; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import org.junit.jupiter.api.Test; + +public class AndroidA2AHttpClientFactoryTest { + + @Test + public void testCreateReturnsAndroidClient() { + // When both JDK and Android are on classpath, Android should be preferred due to higher priority (100) + A2AHttpClient client = A2AHttpClientFactory.create(); + assertNotNull(client); + assertInstanceOf(AndroidA2AHttpClient.class, client, + "Factory should return AndroidA2AHttpClient when Android provider is available"); + } + + @Test + public void testCreateWithAndroidProviderName() { + A2AHttpClient client = A2AHttpClientFactory.create("android"); + assertNotNull(client); + assertInstanceOf(AndroidA2AHttpClient.class, client, + "Factory should return AndroidA2AHttpClient when 'android' provider is requested"); + } + + @Test + public void testAndroidClientIsUsable() { + A2AHttpClient client = A2AHttpClientFactory.create("android"); + assertNotNull(client); + + // Verify we can create builders + A2AHttpClient.GetBuilder getBuilder = client.createGet(); + assertNotNull(getBuilder, "Should be able to create GET builder"); + + A2AHttpClient.PostBuilder postBuilder = client.createPost(); + assertNotNull(postBuilder, "Should be able to create POST builder"); + + A2AHttpClient.DeleteBuilder deleteBuilder = client.createDelete(); + assertNotNull(deleteBuilder, "Should be able to create DELETE builder"); + } +} diff --git a/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientIntegrationTest.java b/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientIntegrationTest.java new file mode 100644 index 000000000..80d65ab75 --- /dev/null +++ b/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientIntegrationTest.java @@ -0,0 +1,9 @@ +package org.a2aproject.sdk.client.http; + +public class AndroidA2AHttpClientIntegrationTest extends AbstractA2AHttpClientIntegrationTest { + + @Override + protected A2AHttpClient createClient() { + return new AndroidA2AHttpClient(); + } +} diff --git a/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientSSETest.java b/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientSSETest.java new file mode 100644 index 000000000..499310790 --- /dev/null +++ b/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientSSETest.java @@ -0,0 +1,9 @@ +package org.a2aproject.sdk.client.http; + +public class AndroidA2AHttpClientSSETest extends AbstractA2AHttpClientSSETest { + + @Override + protected A2AHttpClient createClient() { + return new AndroidA2AHttpClient(); + } +} diff --git a/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientTest.java b/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientTest.java new file mode 100644 index 000000000..d2b4a97ca --- /dev/null +++ b/extras/http-client-android/src/test/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClientTest.java @@ -0,0 +1,59 @@ +package org.a2aproject.sdk.client.http; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import org.junit.jupiter.api.Test; + +public class AndroidA2AHttpClientTest { + + @Test + public void testNoArgsConstructor() { + AndroidA2AHttpClient client = new AndroidA2AHttpClient(); + assertNotNull(client); + } + + @Test + public void testCreateGet() { + AndroidA2AHttpClient client = new AndroidA2AHttpClient(); + A2AHttpClient.GetBuilder builder = client.createGet(); + assertNotNull(builder); + } + + @Test + public void testCreatePost() { + AndroidA2AHttpClient client = new AndroidA2AHttpClient(); + A2AHttpClient.PostBuilder builder = client.createPost(); + assertNotNull(builder); + } + + @Test + public void testCreateDelete() { + AndroidA2AHttpClient client = new AndroidA2AHttpClient(); + A2AHttpClient.DeleteBuilder builder = client.createDelete(); + assertNotNull(builder); + } + + @Test + public void testBuilderUrlSetting() { + AndroidA2AHttpClient client = new AndroidA2AHttpClient(); + A2AHttpClient.GetBuilder builder = client.createGet(); + A2AHttpClient.GetBuilder result = builder.url("https://example.com"); + assertSame(builder, result, "Builder should return itself for method chaining"); + } + + @Test + public void testBuilderHeaderSetting() { + AndroidA2AHttpClient client = new AndroidA2AHttpClient(); + A2AHttpClient.GetBuilder builder = client.createGet(); + A2AHttpClient.GetBuilder result = builder.addHeader("Accept", "application/json"); + assertSame(builder, result, "Builder should return itself for method chaining"); + } + + @Test + public void testPostBuilderBody() { + AndroidA2AHttpClient client = new AndroidA2AHttpClient(); + A2AHttpClient.PostBuilder builder = client.createPost(); + A2AHttpClient.PostBuilder result = builder.body("{\"key\":\"value\"}"); + assertSame(builder, result, "Builder should return itself for method chaining"); + } +} diff --git a/http-client/pom.xml b/http-client/pom.xml index c41097374..468432f9d 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -43,4 +43,24 @@ + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + **/Abstract*.class + + + + + + + \ No newline at end of file diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java index 97ace7996..068a47046 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java @@ -1,7 +1,9 @@ package org.a2aproject.sdk.client.http; import java.util.Comparator; +import java.util.List; import java.util.ServiceLoader; +import java.util.stream.Collectors; import java.util.stream.StreamSupport; /** @@ -9,8 +11,8 @@ * *

            * This factory discovers available {@link A2AHttpClientProvider} implementations at runtime - * and selects the one with the highest priority. If no providers are found, it falls back - * to creating a {@link JdkA2AHttpClient}. + * and selects the one with the highest priority. If no providers are found, it throws + * an {@link IllegalStateException}. * *

            Usage

            *
            {@code
            @@ -40,6 +42,13 @@
              */
             public final class A2AHttpClientFactory {
             
            +    private static final List PROVIDERS;
            +
            +    static {
            +        PROVIDERS = StreamSupport.stream(ServiceLoader.load(A2AHttpClientProvider.class).spliterator(), false)
            +                .collect(Collectors.toList());
            +    }
            +
                 private A2AHttpClientFactory() {
                     // Utility class
                 }
            @@ -49,17 +58,16 @@ private A2AHttpClientFactory() {
                  *
                  * 

            * This method uses the ServiceLoader mechanism to discover providers at runtime. - * If no providers are found, it falls back to creating a {@link JdkA2AHttpClient}. + * If no providers are found, it throws an {@link IllegalStateException}. * * @return a new A2AHttpClient instance + * @throws IllegalStateException if no providers are found */ public static A2AHttpClient create() { - ServiceLoader loader = ServiceLoader.load(A2AHttpClientProvider.class); - - return StreamSupport.stream(loader.spliterator(), false) + return PROVIDERS.stream() .max(Comparator.comparingInt(A2AHttpClientProvider::priority)) .map(A2AHttpClientProvider::create) - .orElseGet(JdkA2AHttpClient::new); + .orElseThrow(() -> new IllegalStateException("No A2AHttpClientProvider found")); } /** diff --git a/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientIntegrationTest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientIntegrationTest.java new file mode 100644 index 000000000..e0b45f9b3 --- /dev/null +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientIntegrationTest.java @@ -0,0 +1,216 @@ +package org.a2aproject.sdk.client.http; + +import static org.junit.jupiter.api.Assertions.assertEquals; +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 static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import org.a2aproject.sdk.common.A2AErrorMessages; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; + +import java.io.IOException; + +public abstract class AbstractA2AHttpClientIntegrationTest { + + private ClientAndServer mockServer; + private A2AHttpClient client; + + protected abstract A2AHttpClient createClient(); + + @BeforeEach + public void setup() { + mockServer = ClientAndServer.startClientAndServer(0); + client = createClient(); + } + + @AfterEach + public void teardown() { + if (mockServer != null) { + mockServer.stop(); + } + } + + private String getBaseUrl() { + return "http://localhost:" + mockServer.getPort(); + } + + @Test + public void testGetRequestSuccess() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/test")) + .respond(response().withStatusCode(200).withBody("success")); + + A2AHttpResponse response = client.createGet() + .url(getBaseUrl() + "/test") + .get(); + + assertEquals(200, response.status()); + assertTrue(response.success()); + assertEquals("success", response.body()); + } + + @Test + public void testPostRequestSuccess() throws Exception { + mockServer + .when(request() + .withMethod("POST") + .withPath("/test") + .withBody("{\"key\":\"value\"}")) + .respond(response().withStatusCode(201).withBody("created")); + + A2AHttpResponse response = client.createPost() + .url(getBaseUrl() + "/test") + .body("{\"key\":\"value\"}") + .post(); + + assertEquals(201, response.status()); + assertTrue(response.success()); + assertEquals("created", response.body()); + } + + @Test + public void testDeleteRequestSuccess() throws Exception { + mockServer + .when(request().withMethod("DELETE").withPath("/test")) + .respond(response().withStatusCode(204)); + + A2AHttpResponse response = client.createDelete() + .url(getBaseUrl() + "/test") + .delete(); + + assertEquals(204, response.status()); + assertTrue(response.success()); + } + + @Test + public void test401AuthenticationErrorOnGet() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/test")) + .respond(response().withStatusCode(401)); + + Exception exception = assertThrows(IOException.class, () -> { + client.createGet() + .url(getBaseUrl() + "/test") + .get(); + }); + + assertEquals(A2AErrorMessages.AUTHENTICATION_FAILED, exception.getMessage()); + } + + @Test + public void test403AuthorizationErrorOnGet() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/test")) + .respond(response().withStatusCode(403)); + + Exception exception = assertThrows(IOException.class, () -> { + client.createGet() + .url(getBaseUrl() + "/test") + .get(); + }); + + assertEquals(A2AErrorMessages.AUTHORIZATION_FAILED, exception.getMessage()); + } + + @Test + public void test401AuthenticationErrorOnPost() throws Exception { + mockServer + .when(request().withMethod("POST").withPath("/test")) + .respond(response().withStatusCode(401)); + + Exception exception = assertThrows(IOException.class, () -> { + client.createPost() + .url(getBaseUrl() + "/test") + .body("{}") + .post(); + }); + + assertEquals(A2AErrorMessages.AUTHENTICATION_FAILED, exception.getMessage()); + } + + @Test + public void test403AuthorizationErrorOnPost() throws Exception { + mockServer + .when(request().withMethod("POST").withPath("/test")) + .respond(response().withStatusCode(403)); + + Exception exception = assertThrows(IOException.class, () -> { + client.createPost() + .url(getBaseUrl() + "/test") + .body("{}") + .post(); + }); + + assertEquals(A2AErrorMessages.AUTHORIZATION_FAILED, exception.getMessage()); + } + + @Test + public void test401AuthenticationErrorOnDelete() throws Exception { + mockServer + .when(request().withMethod("DELETE").withPath("/test")) + .respond(response().withStatusCode(401)); + + Exception exception = assertThrows(IOException.class, () -> { + client.createDelete() + .url(getBaseUrl() + "/test") + .delete(); + }); + + assertEquals(A2AErrorMessages.AUTHENTICATION_FAILED, exception.getMessage()); + } + + @Test + public void testHeaderPropagation() throws Exception { + mockServer + .when(request() + .withMethod("GET") + .withPath("/test") + .withHeader("Authorization", "Bearer token") + .withHeader("X-Custom-Header", "custom-value")) + .respond(response().withStatusCode(200).withBody("ok")); + + A2AHttpResponse response = client.createGet() + .url(getBaseUrl() + "/test") + .addHeader("Authorization", "Bearer token") + .addHeader("X-Custom-Header", "custom-value") + .get(); + + assertEquals(200, response.status()); + assertEquals("ok", response.body()); + } + + @Test + public void testNonSuccessStatusCode() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/test")) + .respond(response().withStatusCode(500).withBody("Internal Server Error")); + + A2AHttpResponse response = client.createGet() + .url(getBaseUrl() + "/test") + .get(); + + assertEquals(500, response.status()); + assertFalse(response.success()); + assertEquals("Internal Server Error", response.body()); + } + + @Test + public void test404NotFound() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/test")) + .respond(response().withStatusCode(404).withBody("Not Found")); + + A2AHttpResponse response = client.createGet() + .url(getBaseUrl() + "/test") + .get(); + + assertEquals(404, response.status()); + assertFalse(response.success()); + assertEquals("Not Found", response.body()); + } +} diff --git a/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientSSETest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientSSETest.java new file mode 100644 index 000000000..30a9a244f --- /dev/null +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientSSETest.java @@ -0,0 +1,255 @@ +package org.a2aproject.sdk.client.http; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import org.a2aproject.sdk.common.A2AErrorMessages; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +public abstract class AbstractA2AHttpClientSSETest { + + private ClientAndServer mockServer; + private A2AHttpClient client; + + protected abstract A2AHttpClient createClient(); + + @BeforeEach + public void setup() { + mockServer = ClientAndServer.startClientAndServer(0); + client = createClient(); + } + + @AfterEach + public void teardown() { + if (mockServer != null) { + mockServer.stop(); + } + } + + private String getBaseUrl() { + return "http://localhost:" + mockServer.getPort(); + } + + @Test + public void testGetAsyncSSE() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("data: event1\n\ndata: event2\n\ndata: event3\n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE( + events::add, + error::set, + latch::countDown + ); + + assertTrue(latch.await(5, TimeUnit.SECONDS), "Expected completion handler to be called"); + assertNull(error.get(), "Expected no errors"); + assertEquals(3, events.size(), "Expected to receive 3 events"); + assertTrue(events.contains("event1")); + assertTrue(events.contains("event2")); + assertTrue(events.contains("event3")); + } + + @Test + public void testPostAsyncSSE() throws Exception { + mockServer + .when(request() + .withMethod("POST") + .withPath("/sse") + .withBody("{\"subscribe\":true}")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("data: message1\n\ndata: message2\n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createPost() + .url(getBaseUrl() + "/sse") + .body("{\"subscribe\":true}") + .postAsyncSSE( + events::add, + error::set, + latch::countDown + ); + + assertTrue(latch.await(5, TimeUnit.SECONDS), "Expected completion handler to be called"); + assertNull(error.get(), "Expected no errors"); + assertEquals(2, events.size(), "Expected to receive 2 events"); + assertTrue(events.contains("message1")); + assertTrue(events.contains("message2")); + } + + @Test + public void testSSEDataPrefixStripping() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("data: content here\n\ndata:no space\n\ndata: extra spaces \n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE( + events::add, + error::set, + latch::countDown + ); + + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertNull(error.get()); + assertTrue(events.contains("content here"), "Should have stripped 'data: ' prefix"); + assertTrue(events.contains("no space"), "Should handle 'data:' without space"); + assertTrue(events.contains("extra spaces"), "Should trim whitespace"); + } + + @Test + public void testSSEAuthenticationError() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response().withStatusCode(401)); + + CountDownLatch errorLatch = new CountDownLatch(1); + AtomicReference error = new AtomicReference<>(); + AtomicBoolean completed = new AtomicBoolean(false); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE( + msg -> {}, + e -> { + error.set(e); + errorLatch.countDown(); + }, + () -> completed.set(true) + ); + + assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Expected error handler to be called"); + assertNotNull(error.get(), "Expected an error"); + assertTrue(error.get() instanceof IOException, "Expected IOException"); + assertTrue(error.get().getMessage().contains(A2AErrorMessages.AUTHENTICATION_FAILED), + "Expected authentication error message but got: " + error.get().getMessage()); + assertFalse(completed.get(), "Should not call completion handler on error"); + } + + @Test + public void testSSEAuthorizationError() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response().withStatusCode(403)); + + CountDownLatch errorLatch = new CountDownLatch(1); + AtomicReference error = new AtomicReference<>(); + AtomicBoolean completed = new AtomicBoolean(false); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE( + msg -> {}, + e -> { + error.set(e); + errorLatch.countDown(); + }, + () -> completed.set(true) + ); + + assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Expected error handler to be called"); + assertNotNull(error.get(), "Expected an error"); + assertTrue(error.get() instanceof IOException, "Expected IOException"); + assertTrue(error.get().getMessage().contains(A2AErrorMessages.AUTHORIZATION_FAILED), + "Expected authorization error message but got: " + error.get().getMessage()); + assertFalse(completed.get(), "Should not call completion handler on error"); + } + + @Test + public void testSSEEmptyLinesIgnored() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("data: first\n\n\n\ndata: second\n\ndata: \n\ndata: third\n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE( + events::add, + error::set, + latch::countDown + ); + + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertNull(error.get()); + assertEquals(3, events.size(), "Should have received 3 non-empty events"); + assertTrue(events.contains("first")); + assertTrue(events.contains("second")); + assertTrue(events.contains("third")); + } + + @Test + public void testSSEHeaderPropagation() throws Exception { + mockServer + .when(request() + .withMethod("GET") + .withPath("/sse") + .withHeader("Accept", "text/event-stream") + .withHeader("Authorization", "Bearer token")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("data: authenticated\n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createGet() + .url(getBaseUrl() + "/sse") + .addHeader("Authorization", "Bearer token") + .getAsyncSSE( + events::add, + error::set, + latch::countDown + ); + + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertNull(error.get()); + assertTrue(events.contains("authenticated")); + } +} diff --git a/pom.xml b/pom.xml index 48e69372c..bfe5ed8b8 100644 --- a/pom.xml +++ b/pom.xml @@ -120,6 +120,18 @@ a2a-java-sdk-http-client ${project.version} + + ${project.groupId} + a2a-java-sdk-http-client + ${project.version} + test-jar + test + + + ${project.groupId} + a2a-java-sdk-http-client-android + ${project.version} + ${project.groupId} a2a-java-sdk-http-client-vertx @@ -560,6 +572,7 @@ extras/push-notification-config-store-database-jpa extras/queue-manager-replicated extras/http-client-vertx + extras/http-client-android http-client jsonrpc-common integrations/microprofile-config From 4949f66e99d7b187339ca8991d6f78b1aaadb0ff Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 6 May 2026 08:16:27 +0200 Subject: [PATCH 137/192] chore: upgrade Quarkus to 3.35.2 and align dependency versions (#850) - Quarkus 3.30.6 -> 3.35.2 - JUnit 5.13.4 -> 6.0.3 - gRPC 1.77.0 -> 1.79.0 - Protobuf 4.33.1 -> 4.33.2 - Testcontainers 1.21.4-> 2.0.5 - Update VertxSecurityHelper to use challenge.getHeaders() map instead of the removed headerName/headerContent fields (API change in Quarkus 3.35.x) Signed-off-by: Emmanuel Hugonnet --- examples/cloud-deployment/server/pom.xml | 1 - .../tests-multi-instance/tests/pom.xml | 6 +++--- pom.xml | 10 +++++----- .../sdk/server/common/quarkus/VertxSecurityHelper.java | 5 ++++- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index 189b2f787..7d334401d 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -21,7 +21,6 @@ org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc - ${project.version} diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index c7114b22c..7c00ebbe6 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -42,17 +42,17 @@ org.testcontainers - junit-jupiter + testcontainers-junit-jupiter test org.testcontainers - kafka + testcontainers-kafka test org.testcontainers - postgresql + testcontainers-postgresql test diff --git a/pom.xml b/pom.xml index 48e69372c..3a5a0de62 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ - 1.77.0 + 1.79.0 UTF-8 3.5.0 3.15.0 @@ -56,20 +56,20 @@ 2.0.1 2.1.3 3.1.0 - 5.13.4 + 6.0.3 1.6.3 1.52.0 5.17.0 5.15.0 1.1.1 1.7.1 - 4.33.1 + 4.33.2 0.6.1 - 3.30.6 + 3.35.2 5.5.1 2.0.17 1.5.18 - 1.21.4 + 2.0.5 2.49.0 0.13.4 -XDaddTypeAnnotationsToSymbol=true diff --git a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java index 9aa1799b4..264c89688 100644 --- a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java +++ b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java @@ -11,6 +11,7 @@ import io.quarkus.vertx.http.runtime.security.HttpAuthenticator; import io.vertx.core.Context; import io.vertx.ext.web.RoutingContext; +import java.util.Map; /** * CDI helper for integrating Quarkus security with Vert.x Web routes. @@ -149,7 +150,9 @@ public void handleAuthError(RoutingContext ctx, Exception e) { ChallengeData challenge = httpAuthenticator.get().getChallenge(ctx).await().indefinitely(); if (challenge != null) { status = challenge.status; - ctx.response().putHeader(challenge.headerName, challenge.headerContent); + for(Map.Entry header : challenge.getHeaders().entrySet()) { + ctx.response().putHeader(header.getKey(), header.getValue()); + } } } ctx.response() From dbbf0f7f463cea70a735eb7c47542b77b8b737e4 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 10 Apr 2026 13:49:40 +0200 Subject: [PATCH 138/192] feat: Add 0.3 protocol version compatibility layer This passes the 0.3 TCK, and all unit tests. At the moment 0.3 and 1.0 are NOT co-hosted, you need to select one --- .claude/architecture/compatibility_0.3.md | 544 ++ .../sdk/test/ExtrasBomVerifier.java | 1 + .../sdk/test/ReferenceBomVerifier.java | 3 +- boms/sdk/pom.xml | 80 + boms/sdk/src/it/sdk-usage-test/pom.xml | 66 + .../a2aproject/sdk/test/SdkBomVerifier.java | 1 + compat-0.3/client/base/pom.xml | 84 + .../org/a2aproject/sdk/compat03/A2A_v0_3.java | 188 + .../compat03/client/AbstractClient_v0_3.java | 392 ++ .../compat03/client/ClientBuilder_v0_3.java | 169 + .../sdk/compat03/client/ClientEvent_v0_3.java | 4 + .../client/ClientTaskManager_v0_3.java | 139 + .../sdk/compat03/client/Client_v0_3.java | 243 + .../compat03/client/MessageEvent_v0_3.java | 26 + .../sdk/compat03/client/TaskEvent_v0_3.java | 27 + .../compat03/client/TaskUpdateEvent_v0_3.java | 37 + .../client/config/ClientConfig_v0_3.java | 114 + .../compat03/client/config/package-info.java | 5 + .../sdk/compat03/client/package-info.java | 5 + .../src/main/resources/META-INF/beans.xml | 0 .../sdk/compat03/A2A_v0_3_Test.java | 147 + ...AuthenticationAuthorization_v0_3_Test.java | 380 ++ .../client/ClientBuilder_v0_3_Test.java | 96 + compat-0.3/client/transport/grpc/pom.xml | 57 + .../grpc/EventStreamObserver_v0_3.java | 64 + .../transport/grpc/GrpcErrorMapper_v0_3.java | 102 + .../grpc/GrpcTransportConfigBuilder_v0_3.java | 32 + .../grpc/GrpcTransportConfig_v0_3.java | 21 + .../grpc/GrpcTransportProvider_v0_3.java | 35 + .../transport/grpc/GrpcTransport_v0_3.java | 389 ++ .../client/transport/grpc/package-info.java | 4 + ...transport.spi.ClientTransportProvider_v0_3 | 1 + .../grpc/GrpcErrorMapper_v0_3_Test.java | 293 + compat-0.3/client/transport/jsonrpc/pom.xml | 49 + .../JSONRPCTransportConfigBuilder_v0_3.java | 28 + .../jsonrpc/JSONRPCTransportConfig_v0_3.java | 21 + .../JSONRPCTransportProvider_v0_3.java | 29 + .../jsonrpc/JSONRPCTransport_v0_3.java | 424 ++ .../jsonrpc/sse/SSEEventListener_v0_3.java | 88 + ...transport.spi.ClientTransportProvider_v0_3 | 1 + .../JSONRPCTransportStreaming_v0_3_Test.java | 174 + .../jsonrpc/JSONRPCTransport_v0_3_Test.java | 683 +++ .../transport/jsonrpc/JsonMessages_v0_3.java | 769 +++ .../jsonrpc/JsonStreamingMessages_v0_3.java | 145 + .../sse/SSEEventListener_v0_3_Test.java | 267 + compat-0.3/client/transport/rest/pom.xml | 62 + .../transport/rest/RestErrorMapper_v0_3.java | 64 + .../rest/RestTransportConfigBuilder_v0_3.java | 28 + .../rest/RestTransportConfig_v0_3.java | 22 + .../rest/RestTransportProvider_v0_3.java | 29 + .../transport/rest/RestTransport_v0_3.java | 401 ++ .../client/transport/rest/package-info.java | 5 + .../rest/sse/RestSSEEventListener_v0_3.java | 67 + .../transport/rest/sse/package-info.java | 5 + ...transport.spi.ClientTransportProvider_v0_3 | 1 + .../transport/rest/JsonRestMessages_v0_3.java | 654 +++ .../rest/RestTransport_v0_3_Test.java | 452 ++ compat-0.3/client/transport/spi/pom.xml | 36 + .../ClientTransportConfigBuilder_v0_3.java | 22 + .../spi/ClientTransportConfig_v0_3.java | 22 + .../spi/ClientTransportProvider_v0_3.java | 30 + .../transport/spi/ClientTransport_v0_3.java | 141 + .../interceptors/ClientCallContext_v0_3.java | 27 + .../ClientCallInterceptor_v0_3.java | 27 + .../interceptors/PayloadAndHeaders_v0_3.java | 25 + .../auth/AuthInterceptor_v0_3.java | 71 + .../auth/CredentialService_v0_3.java | 19 + ...InMemoryContextCredentialService_v0_3.java | 55 + .../spi/interceptors/auth/package-info.java | 5 + .../spi/interceptors/package-info.java | 5 + .../client/transport/spi/package-info.java | 5 + .../auth/AuthInterceptor_v0_3_Test.java | 328 ++ compat-0.3/http-client/pom.xml | 39 + .../client/http/A2ACardResolver_v0_3.java | 113 + .../client/http/A2AHttpClient_v0_3.java | 42 + .../client/http/A2AHttpResponse_v0_3.java | 9 + .../client/http/JdkA2AHttpClient_v0_3.java | 316 + .../compat03/client/http/package-info.java | 5 + .../http/A2ACardResolver_v0_3_Test.java | 177 + .../client/http/JsonMessages_v0_3.java | 164 + compat-0.3/pom.xml | 148 + compat-0.3/reference/grpc/pom.xml | 114 + .../A2AExtensionsInterceptor_v0_3.java | 70 + .../grpc/quarkus/QuarkusGrpcHandler_v0_3.java | 52 + .../QuarkusGrpcTransportMetadata_v0_3.java | 11 + .../src/main/resources/META-INF/beans.xml | 0 ...rg.a2aproject.sdk.server.TransportMetadata | 1 + .../grpc/quarkus/A2ATestResource_v0_3.java | 144 + .../quarkus/QuarkusA2AGrpc_v0_3_Test.java | 55 + .../src/test/resources/application.properties | 27 + .../compat-0.3-requesthandler-test.properties | 1 + compat-0.3/reference/jsonrpc/pom.xml | 107 + .../apps/quarkus/A2AServerRoutes_v0_3.java | 390 ++ .../apps/quarkus/CallContextFactory_v0_3.java | 8 + .../QuarkusJSONRPCTransportMetadata_v0_3.java | 12 + .../src/main/resources/META-INF/beans.xml | 6 + .../apps/quarkus/A2ATestRoutes_v0_3.java | 196 + .../quarkus/QuarkusA2AJSONRPC_v0_3_Test.java | 31 + .../src/test/resources/application.properties | 12 + .../compat-0.3-requesthandler-test.properties | 1 + compat-0.3/reference/rest/pom.xml | 107 + .../rest/quarkus/A2AServerRoutes_v0_3.java | 453 ++ .../rest/quarkus/CallContextFactory_v0_3.java | 8 + .../QuarkusRestTransportMetadata_v0_3.java | 10 + .../server/rest/quarkus/package-info.java | 4 + .../src/main/resources/META-INF/beans.xml | 6 + .../rest/quarkus/A2ATestRoutes_v0_3.java | 196 + .../quarkus/QuarkusA2ARest_v0_3_Test.java | 60 + .../src/test/resources/application.properties | 20 + .../compat-0.3-requesthandler-test.properties | 1 + compat-0.3/server-conversion/pom.xml | 140 + .../Convert_v0_3_To10RequestHandler.java | 385 ++ .../conversion/ErrorConverter_v0_3.java | 91 + .../mappers/config/A03ToV10MapperConfig.java | 42 + .../mappers/config/A2AMappers_v0_3.java | 69 + .../mappers/domain/ArtifactMapper_v0_3.java | 83 + .../domain/AuthenticationInfoMapper_v0_3.java | 119 + .../mappers/domain/EventKindMapper_v0_3.java | 97 + .../domain/FileContentMapper_v0_3.java | 92 + .../mappers/domain/MessageMapper_v0_3.java | 96 + .../mappers/domain/PartMapper_v0_3.java | 104 + .../mappers/domain/RoleMapper_v0_3.java | 60 + .../domain/StreamingEventKindMapper_v0_3.java | 100 + .../TaskArtifactUpdateEventMapper_v0_3.java | 74 + .../mappers/domain/TaskMapper_v0_3.java | 111 + ...TaskPushNotificationConfigMapper_v0_3.java | 89 + .../mappers/domain/TaskStateMapper_v0_3.java | 115 + .../mappers/domain/TaskStatusMapper_v0_3.java | 71 + .../TaskStatusUpdateEventMapper_v0_3.java | 71 + .../params/CancelTaskParamsMapper_v0_3.java | 72 + .../MessageSendConfigurationMapper_v0_3.java | 107 + .../params/MessageSendParamsMapper_v0_3.java | 75 + .../params/TaskIdParamsMapper_v0_3.java | 66 + .../params/TaskQueryParamsMapper_v0_3.java | 84 + ...hNotificationConfigsResultMapper_v0_3.java | 79 + .../src/main/resources/META-INF/beans.xml | 6 + .../AbstractA2ARequestHandlerTest_v0_3.java | 287 + .../AbstractA2AServerServerTest_v0_3.java | 2038 +++++++ .../conversion/AgentCardProducer_v0_3.java | 73 + .../AgentExecutorProducer_v0_3.java | 106 + .../conversion/GsonObjectMapper_v0_3.java | 39 + .../conversion/TestHttpClient_v0_3.java | 106 + .../conversion/TestUtilsBean_v0_3.java | 118 + .../conversion/V10GsonObjectMapper_v0_3.java | 39 + .../mappers/domain/TaskMapper_v0_3_Test.java | 186 + .../src/test/resources/META-INF/beans.xml | 7 + compat-0.3/spec-grpc/pom.xml | 147 + .../org/a2aproject/sdk/compat03/grpc/A2A.java | 827 +++ .../sdk/compat03/grpc/A2AServiceGrpc.java | 1323 +++++ .../compat03/grpc/APIKeySecurityScheme.java | 858 +++ .../grpc/APIKeySecuritySchemeOrBuilder.java | 72 + .../sdk/compat03/grpc/AgentCapabilities.java | 986 ++++ .../grpc/AgentCapabilitiesOrBuilder.java | 76 + .../sdk/compat03/grpc/AgentCard.java | 5131 +++++++++++++++++ .../sdk/compat03/grpc/AgentCardOrBuilder.java | 626 ++ .../sdk/compat03/grpc/AgentCardSignature.java | 952 +++ .../grpc/AgentCardSignatureOrBuilder.java | 81 + .../sdk/compat03/grpc/AgentExtension.java | 1044 ++++ .../grpc/AgentExtensionOrBuilder.java | 94 + .../sdk/compat03/grpc/AgentInterface.java | 716 +++ .../grpc/AgentInterfaceOrBuilder.java | 56 + .../sdk/compat03/grpc/AgentProvider.java | 716 +++ .../compat03/grpc/AgentProviderOrBuilder.java | 56 + .../sdk/compat03/grpc/AgentSkill.java | 2435 ++++++++ .../compat03/grpc/AgentSkillOrBuilder.java | 318 + .../sdk/compat03/grpc/Artifact.java | 1799 ++++++ .../sdk/compat03/grpc/ArtifactOrBuilder.java | 184 + .../sdk/compat03/grpc/AuthenticationInfo.java | 779 +++ .../grpc/AuthenticationInfoOrBuilder.java | 73 + .../grpc/AuthorizationCodeOAuthFlow.java | 1213 ++++ .../AuthorizationCodeOAuthFlowOrBuilder.java | 137 + .../sdk/compat03/grpc/CancelTaskRequest.java | 530 ++ .../grpc/CancelTaskRequestOrBuilder.java | 32 + .../grpc/ClientCredentialsOAuthFlow.java | 1042 ++++ .../ClientCredentialsOAuthFlowOrBuilder.java | 115 + ...eateTaskPushNotificationConfigRequest.java | 866 +++ ...ushNotificationConfigRequestOrBuilder.java | 61 + .../sdk/compat03/grpc/DataPart.java | 567 ++ .../sdk/compat03/grpc/DataPartOrBuilder.java | 27 + ...leteTaskPushNotificationConfigRequest.java | 530 ++ ...ushNotificationConfigRequestOrBuilder.java | 32 + .../sdk/compat03/grpc/FilePart.java | 855 +++ .../sdk/compat03/grpc/FilePartOrBuilder.java | 54 + .../compat03/grpc/GetAgentCardRequest.java | 367 ++ .../grpc/GetAgentCardRequestOrBuilder.java | 12 + .../GetTaskPushNotificationConfigRequest.java | 530 ++ ...ushNotificationConfigRequestOrBuilder.java | 32 + .../sdk/compat03/grpc/GetTaskRequest.java | 596 ++ .../grpc/GetTaskRequestOrBuilder.java | 38 + .../compat03/grpc/HTTPAuthSecurityScheme.java | 893 +++ .../grpc/HTTPAuthSecuritySchemeOrBuilder.java | 82 + .../sdk/compat03/grpc/ImplicitOAuthFlow.java | 1042 ++++ .../grpc/ImplicitOAuthFlowOrBuilder.java | 115 + ...ListTaskPushNotificationConfigRequest.java | 819 +++ ...ushNotificationConfigRequestOrBuilder.java | 74 + ...istTaskPushNotificationConfigResponse.java | 891 +++ ...shNotificationConfigResponseOrBuilder.java | 58 + .../a2aproject/sdk/compat03/grpc/Message.java | 1983 +++++++ .../sdk/compat03/grpc/MessageOrBuilder.java | 217 + .../grpc/MutualTlsSecurityScheme.java | 530 ++ .../MutualTlsSecuritySchemeOrBuilder.java | 32 + .../compat03/grpc/OAuth2SecurityScheme.java | 942 +++ .../grpc/OAuth2SecuritySchemeOrBuilder.java | 81 + .../sdk/compat03/grpc/OAuthFlows.java | 1273 ++++ .../compat03/grpc/OAuthFlowsOrBuilder.java | 74 + .../grpc/OpenIdConnectSecurityScheme.java | 701 +++ .../OpenIdConnectSecuritySchemeOrBuilder.java | 54 + .../a2aproject/sdk/compat03/grpc/Part.java | 1042 ++++ .../sdk/compat03/grpc/PartOrBuilder.java | 61 + .../sdk/compat03/grpc/PasswordOAuthFlow.java | 1042 ++++ .../grpc/PasswordOAuthFlowOrBuilder.java | 115 + .../compat03/grpc/PushNotificationConfig.java | 1107 ++++ .../grpc/PushNotificationConfigOrBuilder.java | 99 + .../a2aproject/sdk/compat03/grpc/Role.java | 150 + .../sdk/compat03/grpc/Security.java | 672 +++ .../sdk/compat03/grpc/SecurityOrBuilder.java | 46 + .../sdk/compat03/grpc/SecurityScheme.java | 1481 +++++ .../grpc/SecuritySchemeOrBuilder.java | 89 + .../grpc/SendMessageConfiguration.java | 1037 ++++ .../SendMessageConfigurationOrBuilder.java | 104 + .../sdk/compat03/grpc/SendMessageRequest.java | 937 +++ .../grpc/SendMessageRequestOrBuilder.java | 57 + .../compat03/grpc/SendMessageResponse.java | 865 +++ .../grpc/SendMessageResponseOrBuilder.java | 44 + .../sdk/compat03/grpc/StreamResponse.java | 1297 +++++ .../grpc/StreamResponseOrBuilder.java | 74 + .../sdk/compat03/grpc/StringList.java | 563 ++ .../compat03/grpc/StringListOrBuilder.java | 37 + .../a2aproject/sdk/compat03/grpc/Task.java | 2114 +++++++ .../grpc/TaskArtifactUpdateEvent.java | 1344 +++++ .../TaskArtifactUpdateEventOrBuilder.java | 126 + .../sdk/compat03/grpc/TaskOrBuilder.java | 204 + .../grpc/TaskPushNotificationConfig.java | 723 +++ .../TaskPushNotificationConfigOrBuilder.java | 47 + .../sdk/compat03/grpc/TaskState.java | 268 + .../sdk/compat03/grpc/TaskStatus.java | 980 ++++ .../compat03/grpc/TaskStatusOrBuilder.java | 88 + .../compat03/grpc/TaskStatusUpdateEvent.java | 1261 ++++ .../grpc/TaskStatusUpdateEventOrBuilder.java | 116 + .../grpc/TaskSubscriptionRequest.java | 530 ++ .../TaskSubscriptionRequestOrBuilder.java | 32 + .../compat03/grpc/utils/ProtoUtils_v0_3.java | 1025 ++++ .../sdk/compat03/grpc/utils/package-info.java | 5 + compat-0.3/spec-grpc/src/main/proto/a2a.proto | 717 +++ .../src/main/resources/META-INF/beans.xml | 0 .../grpc/utils/ToProto_v0_3_Test.java | 292 + compat-0.3/spec/pom.xml | 42 + .../sdk/compat03/common/A2AHeaders_v0_3.java | 18 + .../json/JsonMappingException_v0_3.java | 102 + .../json/JsonProcessingException_v0_3.java | 55 + .../sdk/compat03/json/JsonUtil_v0_3.java | 1048 ++++ .../sdk/compat03/json/package-info.java | 8 + .../compat03/spec/A2AClientError_v0_3.java | 17 + .../spec/A2AClientException_v0_3.java | 23 + .../spec/A2AClientHTTPError_v0_3.java | 34 + .../spec/A2AClientInvalidArgsError_v0_3.java | 15 + .../spec/A2AClientInvalidStateError_v0_3.java | 15 + .../spec/A2AClientJSONError_v0_3.java | 40 + .../sdk/compat03/spec/A2AErrorCodes_v0_3.java | 22 + .../sdk/compat03/spec/A2AError_v0_3.java | 4 + .../sdk/compat03/spec/A2AException_v0_3.java | 44 + .../spec/A2AServerException_v0_3.java | 23 + .../spec/APIKeySecurityScheme_v0_3.java | 110 + .../compat03/spec/AgentCapabilities_v0_3.java | 42 + .../spec/AgentCardSignature_v0_3.java | 44 + .../sdk/compat03/spec/AgentCard_v0_3.java | 199 + .../compat03/spec/AgentExtension_v0_3.java | 47 + .../compat03/spec/AgentInterface_v0_3.java | 15 + .../sdk/compat03/spec/AgentProvider_v0_3.java | 14 + .../sdk/compat03/spec/AgentSkill_v0_3.java | 77 + .../sdk/compat03/spec/Artifact_v0_3.java | 82 + ...edExtendedCardNotConfiguredError_v0_3.java | 20 + .../spec/AuthenticationInfo_v0_3.java | 15 + .../spec/AuthorizationCodeOAuthFlow_v0_3.java | 19 + .../compat03/spec/CancelTaskRequest_v0_3.java | 70 + .../spec/CancelTaskResponse_v0_3.java | 21 + .../spec/ClientCredentialsOAuthFlow_v0_3.java | 19 + .../ContentTypeNotSupportedError_v0_3.java | 20 + .../sdk/compat03/spec/DataPart_v0_3.java | 43 + ...TaskPushNotificationConfigParams_v0_3.java | 46 + ...askPushNotificationConfigRequest_v0_3.java | 67 + ...skPushNotificationConfigResponse_v0_3.java | 20 + .../sdk/compat03/spec/EventKind_v0_3.java | 25 + .../sdk/compat03/spec/Event_v0_3.java | 4 + .../sdk/compat03/spec/FileContent_v0_3.java | 32 + .../sdk/compat03/spec/FilePart_v0_3.java | 43 + .../sdk/compat03/spec/FileWithBytes_v0_3.java | 7 + .../sdk/compat03/spec/FileWithUri_v0_3.java | 8 + ...AuthenticatedExtendedCardRequest_v0_3.java | 62 + ...uthenticatedExtendedCardResponse_v0_3.java | 20 + ...TaskPushNotificationConfigParams_v0_3.java | 50 + ...askPushNotificationConfigRequest_v0_3.java | 67 + ...skPushNotificationConfigResponse_v0_3.java | 20 + .../compat03/spec/GetTaskRequest_v0_3.java | 71 + .../compat03/spec/GetTaskResponse_v0_3.java | 19 + .../spec/HTTPAuthSecurityScheme_v0_3.java | 73 + .../spec/IdJsonMappingException_v0_3.java | 22 + .../compat03/spec/ImplicitOAuthFlow_v0_3.java | 17 + .../compat03/spec/IntegerJsonrpcId_v0_3.java | 4 + .../sdk/compat03/spec/InternalError_v0_3.java | 23 + .../spec/InvalidAgentResponseError_v0_3.java | 50 + .../spec/InvalidParamsError_v0_3.java | 50 + ...nvalidParamsJsonMappingException_v0_3.java | 12 + .../spec/InvalidRequestError_v0_3.java | 51 + .../compat03/spec/JSONErrorResponse_v0_3.java | 19 + .../compat03/spec/JSONParseError_v0_3.java | 50 + .../spec/JSONRPCErrorResponse_v0_3.java | 33 + .../sdk/compat03/spec/JSONRPCError_v0_3.java | 49 + .../compat03/spec/JSONRPCMessage_v0_3.java | 13 + .../compat03/spec/JSONRPCRequest_v0_3.java | 47 + .../compat03/spec/JSONRPCResponse_v0_3.java | 57 + .../sdk/compat03/spec/JsonrpcId_v0_3.java | 4 + ...TaskPushNotificationConfigParams_v0_3.java | 19 + ...askPushNotificationConfigRequest_v0_3.java | 67 + ...skPushNotificationConfigResponse_v0_3.java | 22 + .../spec/MessageSendConfiguration_v0_3.java | 54 + .../compat03/spec/MessageSendParams_v0_3.java | 47 + .../sdk/compat03/spec/Message_v0_3.java | 209 + .../spec/MethodNotFoundError_v0_3.java | 20 + ...thodNotFoundJsonMappingException_v0_3.java | 12 + .../spec/MutualTLSSecurityScheme_v0_3.java | 40 + .../spec/NonStreamingJSONRPCRequest_v0_3.java | 10 + .../spec/OAuth2SecurityScheme_v0_3.java | 73 + .../sdk/compat03/spec/OAuthFlows_v0_3.java | 39 + .../OpenIdConnectSecurityScheme_v0_3.java | 62 + .../sdk/compat03/spec/Part_v0_3.java | 35 + .../compat03/spec/PasswordOAuthFlow_v0_3.java | 16 + ...shNotificationAuthenticationInfo_v0_3.java | 14 + .../spec/PushNotificationConfig_v0_3.java | 54 + ...ushNotificationNotSupportedError_v0_3.java | 25 + .../compat03/spec/SecurityScheme_v0_3.java | 11 + .../spec/SendMessageRequest_v0_3.java | 100 + .../spec/SendMessageResponse_v0_3.java | 19 + .../SendStreamingMessageRequest_v0_3.java | 82 + .../SendStreamingMessageResponse_v0_3.java | 19 + ...askPushNotificationConfigRequest_v0_3.java | 69 + ...skPushNotificationConfigResponse_v0_3.java | 19 + .../spec/StreamingEventKind_v0_3.java | 35 + .../spec/StreamingJSONRPCRequest_v0_3.java | 10 + .../compat03/spec/StringJsonrpcId_v0_3.java | 4 + .../spec/TaskArtifactUpdateEvent_v0_3.java | 128 + .../sdk/compat03/spec/TaskIdParams_v0_3.java | 19 + .../spec/TaskNotCancelableError_v0_3.java | 30 + .../compat03/spec/TaskNotFoundError_v0_3.java | 22 + .../spec/TaskPushNotificationConfig_v0_3.java | 14 + .../compat03/spec/TaskQueryParams_v0_3.java | 30 + .../spec/TaskResubscriptionRequest_v0_3.java | 68 + .../sdk/compat03/spec/TaskState_v0_3.java | 69 + .../spec/TaskStatusUpdateEvent_v0_3.java | 116 + .../sdk/compat03/spec/TaskStatus_v0_3.java | 31 + .../sdk/compat03/spec/Task_v0_3.java | 136 + .../sdk/compat03/spec/TextPart_v0_3.java | 41 + .../compat03/spec/TransportProtocol_v0_3.java | 45 + .../spec/UnsupportedOperationError_v0_3.java | 22 + .../sdk/compat03/spec/UpdateEvent_v0_3.java | 4 + .../sdk/compat03/util/Utils_v0_3.java | 168 + .../src/main/resources/META-INF/beans.xml | 0 .../JSONRPCErrorSerialization_v0_3_Test.java | 82 + .../spec/SubTypeSerialization_v0_3_Test.java | 102 + .../spec/TaskSerialization_v0_3_Test.java | 713 +++ compat-0.3/tck/pom.xml | 70 + .../tck/server/AgentCardProducer_v0_3.java | 61 + .../server/AgentExecutorProducer_v0_3.java | 84 + .../sdk/compat03/tck/server/package-info.java | 10 + .../src/main/resources/application.properties | 20 + compat-0.3/transport/grpc/pom.xml | 93 + .../grpc/context/GrpcContextKeys_v0_3.java | 45 + .../grpc/handler/CallContextFactory_v0_3.java | 12 + .../grpc/handler/GrpcHandler_v0_3.java | 403 ++ .../grpc/handler/GrpcHandler_v0_3_Test.java | 555 ++ .../GrpcTestTransportMetadata_v0_3.java | 9 + compat-0.3/transport/jsonrpc/pom.xml | 64 + .../context/JSONRPCContextKeys_v0_3.java | 24 + .../jsonrpc/handler/JSONRPCHandler_v0_3.java | 283 + .../src/main/resources/META-INF/beans.xml | 6 + .../handler/JSONRPCHandler_v0_3_Test.java | 1150 ++++ .../JSONRPCTestTransportMetadata_v0_3.java | 19 + compat-0.3/transport/rest/pom.xml | 81 + .../rest/context/RestContextKeys_v0_3.java | 24 + .../rest/handler/RestHandler_v0_3.java | 451 ++ .../transport/rest/handler/package-info.java | 4 + .../src/main/resources/META-INF/beans.xml | 6 + .../rest/handler/RestHandler_v0_3_Test.java | 376 ++ .../RestTestTransportMetadata_v0_3.java | 9 + pom.xml | 3 + .../sdk/server/ServerCallContext.java | 11 +- .../DefaultRequestHandler.java | 16 +- .../transport/rest/handler/RestHandler.java | 2 +- 388 files changed, 85698 insertions(+), 6 deletions(-) create mode 100644 .claude/architecture/compatibility_0.3.md create mode 100644 compat-0.3/client/base/pom.xml create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/AbstractClient_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientEvent_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientTaskManager_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/Client_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/MessageEvent_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/TaskEvent_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/TaskUpdateEvent_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/config/ClientConfig_v0_3.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/config/package-info.java create mode 100644 compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/package-info.java create mode 100644 compat-0.3/client/base/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/A2A_v0_3_Test.java create mode 100644 compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/AuthenticationAuthorization_v0_3_Test.java create mode 100644 compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3_Test.java create mode 100644 compat-0.3/client/transport/grpc/pom.xml create mode 100644 compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/EventStreamObserver_v0_3.java create mode 100644 compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcErrorMapper_v0_3.java create mode 100644 compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportConfigBuilder_v0_3.java create mode 100644 compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportConfig_v0_3.java create mode 100644 compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportProvider_v0_3.java create mode 100644 compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransport_v0_3.java create mode 100644 compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/package-info.java create mode 100644 compat-0.3/client/transport/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 create mode 100644 compat-0.3/client/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcErrorMapper_v0_3_Test.java create mode 100644 compat-0.3/client/transport/jsonrpc/pom.xml create mode 100644 compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfigBuilder_v0_3.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfig_v0_3.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportProvider_v0_3.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 create mode 100644 compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportStreaming_v0_3_Test.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3_Test.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JsonMessages_v0_3.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JsonStreamingMessages_v0_3.java create mode 100644 compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3_Test.java create mode 100644 compat-0.3/client/transport/rest/pom.xml create mode 100644 compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java create mode 100644 compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfigBuilder_v0_3.java create mode 100644 compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfig_v0_3.java create mode 100644 compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportProvider_v0_3.java create mode 100644 compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java create mode 100644 compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/package-info.java create mode 100644 compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/sse/RestSSEEventListener_v0_3.java create mode 100644 compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/sse/package-info.java create mode 100644 compat-0.3/client/transport/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 create mode 100644 compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/JsonRestMessages_v0_3.java create mode 100644 compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3_Test.java create mode 100644 compat-0.3/client/transport/spi/pom.xml create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportConfigBuilder_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportConfig_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportProvider_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransport_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/ClientCallContext_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/ClientCallInterceptor_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/PayloadAndHeaders_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/CredentialService_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/InMemoryContextCredentialService_v0_3.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/package-info.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/package-info.java create mode 100644 compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/package-info.java create mode 100644 compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3_Test.java create mode 100644 compat-0.3/http-client/pom.xml create mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java create mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpClient_v0_3.java create mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpResponse_v0_3.java create mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java create mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/package-info.java create mode 100644 compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java create mode 100644 compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java create mode 100644 compat-0.3/pom.xml create mode 100644 compat-0.3/reference/grpc/pom.xml create mode 100644 compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/A2AExtensionsInterceptor_v0_3.java create mode 100644 compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcHandler_v0_3.java create mode 100644 compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcTransportMetadata_v0_3.java create mode 100644 compat-0.3/reference/grpc/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/reference/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata create mode 100644 compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/A2ATestResource_v0_3.java create mode 100644 compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_Test.java create mode 100644 compat-0.3/reference/grpc/src/test/resources/application.properties create mode 100644 compat-0.3/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties create mode 100644 compat-0.3/reference/jsonrpc/pom.xml create mode 100644 compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java create mode 100644 compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java create mode 100644 compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusJSONRPCTransportMetadata_v0_3.java create mode 100644 compat-0.3/reference/jsonrpc/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2ATestRoutes_v0_3.java create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_Test.java create mode 100644 compat-0.3/reference/jsonrpc/src/test/resources/application.properties create mode 100644 compat-0.3/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties create mode 100644 compat-0.3/reference/rest/pom.xml create mode 100644 compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java create mode 100644 compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java create mode 100644 compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusRestTransportMetadata_v0_3.java create mode 100644 compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/package-info.java create mode 100644 compat-0.3/reference/rest/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2ATestRoutes_v0_3.java create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_Test.java create mode 100644 compat-0.3/reference/rest/src/test/resources/application.properties create mode 100644 compat-0.3/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties create mode 100644 compat-0.3/server-conversion/pom.xml create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/ErrorConverter_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/config/A03ToV10MapperConfig.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/config/A2AMappers_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/ArtifactMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/AuthenticationInfoMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/EventKindMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/FileContentMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/MessageMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/PartMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/RoleMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/StreamingEventKindMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskArtifactUpdateEventMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskPushNotificationConfigMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStateMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusUpdateEventMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/CancelTaskParamsMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/MessageSendConfigurationMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/MessageSendParamsMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/TaskIdParamsMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/TaskQueryParamsMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/result/ListTaskPushNotificationConfigsResultMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentCardProducer_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/GsonObjectMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestHttpClient_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestUtilsBean_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/V10GsonObjectMapper_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3_Test.java create mode 100644 compat-0.3/server-conversion/src/test/resources/META-INF/beans.xml create mode 100644 compat-0.3/spec-grpc/pom.xml create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/A2A.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/A2AServiceGrpc.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/APIKeySecurityScheme.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/APIKeySecuritySchemeOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCapabilities.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCapabilitiesOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCard.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardSignature.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardSignatureOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentExtension.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentExtensionOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentInterface.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentInterfaceOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentProvider.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentProviderOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentSkill.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentSkillOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Artifact.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ArtifactOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthenticationInfo.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthenticationInfoOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthorizationCodeOAuthFlow.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthorizationCodeOAuthFlowOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CancelTaskRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CancelTaskRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ClientCredentialsOAuthFlow.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ClientCredentialsOAuthFlowOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CreateTaskPushNotificationConfigRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DataPart.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DataPartOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DeleteTaskPushNotificationConfigRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/FilePart.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/FilePartOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetAgentCardRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetAgentCardRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskPushNotificationConfigRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/HTTPAuthSecurityScheme.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/HTTPAuthSecuritySchemeOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ImplicitOAuthFlow.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ImplicitOAuthFlowOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigResponse.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Message.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MessageOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MutualTlsSecurityScheme.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MutualTlsSecuritySchemeOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuth2SecurityScheme.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuth2SecuritySchemeOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuthFlows.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuthFlowsOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OpenIdConnectSecurityScheme.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OpenIdConnectSecuritySchemeOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Part.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PartOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PasswordOAuthFlow.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PasswordOAuthFlowOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PushNotificationConfig.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PushNotificationConfigOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Role.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Security.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecurityOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecurityScheme.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecuritySchemeOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageConfiguration.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageConfigurationOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageResponse.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageResponseOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StreamResponse.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StreamResponseOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StringList.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StringListOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Task.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskArtifactUpdateEvent.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskArtifactUpdateEventOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskPushNotificationConfig.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskPushNotificationConfigOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskState.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatus.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusUpdateEvent.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusUpdateEventOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskSubscriptionRequest.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskSubscriptionRequestOrBuilder.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java create mode 100644 compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/package-info.java create mode 100644 compat-0.3/spec-grpc/src/main/proto/a2a.proto create mode 100644 compat-0.3/spec-grpc/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/spec-grpc/src/test/java/org/a2aproject/sdk/compat03/grpc/utils/ToProto_v0_3_Test.java create mode 100644 compat-0.3/spec/pom.xml create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/common/A2AHeaders_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonMappingException_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonProcessingException_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/package-info.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientException_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientHTTPError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientInvalidArgsError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientInvalidStateError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientJSONError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AErrorCodes_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AException_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AServerException_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCapabilities_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCardSignature_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCard_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentExtension_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentInterface_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentProvider_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentSkill_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Artifact_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthenticatedExtendedCardNotConfiguredError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthenticationInfo_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthorizationCodeOAuthFlow_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ClientCredentialsOAuthFlow_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ContentTypeNotSupportedError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigParams_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/EventKind_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Event_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileContent_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileWithBytes_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileWithUri_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigParams_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IdJsonMappingException_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ImplicitOAuthFlow_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IntegerJsonrpcId_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InternalError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidAgentResponseError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidParamsError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidParamsJsonMappingException_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidRequestError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONErrorResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONParseError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCErrorResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCMessage_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JsonrpcId_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigParams_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendConfiguration_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendParams_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MethodNotFoundError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MethodNotFoundJsonMappingException_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/NonStreamingJSONRPCRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuthFlows_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OpenIdConnectSecurityScheme_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Part_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PasswordOAuthFlow_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationAuthenticationInfo_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationConfig_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationNotSupportedError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SecurityScheme_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigResponse_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingEventKind_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingJSONRPCRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StringJsonrpcId_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskIdParams_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskNotCancelableError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskNotFoundError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskPushNotificationConfig_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskQueryParams_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskResubscriptionRequest_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskState_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatus_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TransportProtocol_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/UnsupportedOperationError_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/UpdateEvent_v0_3.java create mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/util/Utils_v0_3.java create mode 100644 compat-0.3/spec/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/JSONRPCErrorSerialization_v0_3_Test.java create mode 100644 compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/SubTypeSerialization_v0_3_Test.java create mode 100644 compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java create mode 100644 compat-0.3/tck/pom.xml create mode 100644 compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/AgentCardProducer_v0_3.java create mode 100644 compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/AgentExecutorProducer_v0_3.java create mode 100644 compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/package-info.java create mode 100644 compat-0.3/tck/src/main/resources/application.properties create mode 100644 compat-0.3/transport/grpc/pom.xml create mode 100644 compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/context/GrpcContextKeys_v0_3.java create mode 100644 compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/CallContextFactory_v0_3.java create mode 100644 compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java create mode 100644 compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java create mode 100644 compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcTestTransportMetadata_v0_3.java create mode 100644 compat-0.3/transport/jsonrpc/pom.xml create mode 100644 compat-0.3/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/transport/jsonrpc/context/JSONRPCContextKeys_v0_3.java create mode 100644 compat-0.3/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3.java create mode 100644 compat-0.3/transport/jsonrpc/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java create mode 100644 compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCTestTransportMetadata_v0_3.java create mode 100644 compat-0.3/transport/rest/pom.xml create mode 100644 compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/context/RestContextKeys_v0_3.java create mode 100644 compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3.java create mode 100644 compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/package-info.java create mode 100644 compat-0.3/transport/rest/src/main/resources/META-INF/beans.xml create mode 100644 compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java create mode 100644 compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestTestTransportMetadata_v0_3.java diff --git a/.claude/architecture/compatibility_0.3.md b/.claude/architecture/compatibility_0.3.md new file mode 100644 index 000000000..5316027f9 --- /dev/null +++ b/.claude/architecture/compatibility_0.3.md @@ -0,0 +1,544 @@ +# PRD: A2A Protocol 0.3 Backward Compatibility Layer + +> **Goal**: Allow the A2A Java SDK (v1.0) to interoperate with agents running protocol v0.3 through a dedicated compatibility layer. + +--- + +## Motivation + +The A2A protocol evolved from v0.3 to v1.0 with significant breaking changes. Existing agents deployed with v0.3 cannot immediately upgrade. This compatibility layer enables a v1.0 SDK to communicate with v0.3 agents across all three transports (JSON-RPC, gRPC, REST) and allows v1.0 servers to accept v0.3 client requests. + +--- + +## Scope + +### In Scope + +- Dedicated `compat-0.3` Maven module structure containing **only** 0.3-specific code +- gRPC code generation from the v0.3 `a2a.proto` +- Dedicated v0.3 client (`Client_v0_3`) exposing only features available in v0.3 +- Server-side conversion layer (`Convert_v0_3_To10RequestHandler`) that accepts v0.3 requests and delegates to v1.0 server-common +- Server-side transport handlers for v0.3 (JSON-RPC, gRPC, REST) +- Bidirectional mapping layer between v0.3 and v1.0 domain objects +- Quarkus reference server implementations for v0.3 +- TCK conformance tests for v0.3 +- Integration test infrastructure (test-jar) for validating conversion layer +- Inclusion in the SDK BOM as separate optional dependencies + +### Out of Scope + +- Changes to existing v1.0 modules (no regressions, no API changes) +- Automatic protocol version detection (client must explicitly choose API version) +- Extras modules (OpenTelemetry, JPA stores, etc.) for v0.3 +- v0.3 format agent card (v0.3 clients must be able to parse v1.0 agent card format) + +### Deferred + +- **Dual-version server deployment**: Running both v1.0 and v0.3 transports simultaneously in a single server instance with a unified agent card + - **Current state**: v0.3 reference servers work standalone; need integration pattern for dual deployment + - **Remaining work**: Define CDI qualifier pattern, path prefix strategy, and unified agent card production + +--- + +## Breaking Changes: v0.3 → v1.0 + +The compatibility layer bridges the following differences: + +### 1. Proto Package Namespace +| Aspect | v0.3 | v1.0 | +|--------|------|------| +| Package | `a2a.v1` | `lf.a2a.v1` | + +### 2. RPC Method Changes +| v0.3 | v1.0 | Change | +|------|------|--------| +| `TaskSubscription` | `SubscribeToTask` | Renamed | +| `GetAgentCard` | `GetExtendedAgentCard` | Renamed | +| `ListTaskPushNotificationConfig` | `ListTaskPushNotificationConfigs` | Pluralized | +| `CreateTaskPushNotificationConfig(CreateTaskPushNotificationConfigRequest)` | `CreateTaskPushNotificationConfig(TaskPushNotificationConfig)` | Parameter type changed | +| — | `ListTasks` | New in v1.0 (no v0.3 equivalent) | + +### 3. HTTP Endpoint Changes +| v0.3 | v1.0 | +|------|------| +| `/v1/message:send` | `/message:send` (+ `/{tenant}/message:send`) | +| `/v1/message:stream` | `/message:stream` (+ tenant) | +| `/v1/{name=tasks/*}` | `/tasks/{id=*}` (+ tenant) | +| `/v1/{name=tasks/*}:cancel` | `/tasks/{id=*}:cancel` (+ tenant) | +| `/v1/{name=tasks/*}:subscribe` | `/tasks/{id=*}:subscribe` (+ tenant) | +| `/v1/card` | `/extendedAgentCard` (+ tenant) | +| `/v1/{parent=task/*/pushNotificationConfigs}` | `/tasks/{task_id=*}/pushNotificationConfigs` (+ tenant) | + +### 4. Configuration Field Changes +| v0.3 `SendMessageConfiguration` | v1.0 `SendMessageConfiguration` | +|----------------------------------|----------------------------------| +| `push_notification` (PushNotificationConfig) | `task_push_notification_config` (TaskPushNotificationConfig) | +| `blocking` (bool, default true) | `return_immediately` (bool, default false) — inverted semantics | +| `history_length` (int32, 0 = unlimited) | `history_length` (optional int32, unset = no limit) | + +### 5. AgentCard / AgentInterface Changes +| v0.3 | v1.0 | +|------|------| +| `url` + `preferred_transport` on AgentCard | Removed; replaced by `supported_interfaces` | +| `additional_interfaces` | Folded into `supported_interfaces` | +| No `tenant` field | `tenant` field added to AgentInterface | +| `transport` field | Renamed to `protocol_binding` | + +### 6. Task State Naming +| v0.3 | v1.0 | +|------|------| +| `TASK_STATE_CANCELLED` | `TASK_STATE_CANCELED` | + +### 7. Structural Changes +- v1.0 removed the `kind` discriminator field from messages +- v1.0 added `reference_task_ids` to `Message` +- v1.0 added `TASK_STATE_REJECTED` enum value (no v0.3 equivalent) + +--- + +## Design Decisions + +### Naming Convention: `_v0_3` Suffix + +All compat-0.3 classes use a `_v0_3` suffix to avoid naming conflicts with v1.0 classes and improve IDE navigation: + +- `Task_v0_3`, `AgentCard_v0_3`, `Client_v0_3` +- `JSONRPCHandler_v0_3`, `GrpcHandler_v0_3`, `RestHandler_v0_3` +- `Convert_v0_3_To10RequestHandler`, `ErrorConverter_v0_3` +- Mappers: `TaskMapper_v0_3`, `MessageSendParamsMapper_v0_3`, etc. + +**Exception**: Generated gRPC classes use the package name `org.a2aproject.sdk.compat03.grpc` without suffix (controlled by proto `java_package` option). + +### Dedicated v0.3 Client + +The compat layer exposes a **dedicated `Client_v0_3`** that only provides features available in v0.3: + +- No `listTasks()` method (absent in v0.3) +- Method names reflect v0.3 semantics where they differ +- The client is a standalone API, not a wrapper around the v1.0 `Client` + +Users must explicitly check the `protocolVersion` field from the agent card and instantiate the correct client accordingly. No automatic version detection. + +### Server-Side Conversion Layer + +Instead of embedding conversion logic in each transport handler, the implementation uses a **dedicated conversion layer** that sits between v0.3 transport handlers and v1.0 server-common: + +``` +v0.3 Client Request + ↓ +v0.3 Transport Handler (JSONRPC/gRPC/REST) + ↓ +Convert_v0_3_To10RequestHandler + ↓ (converts v0.3 → v1.0) +v1.0 DefaultRequestHandler + ↓ +AgentExecutor → AgentEmitter → MainEventBus + ↓ +v1.0 Response + ↓ (converts v1.0 → v0.3) +Convert_v0_3_To10RequestHandler + ↓ +v0.3 Transport Handler + ↓ +v0.3 Client Response +``` + +**Benefits:** +- **Single conversion point**: All v0.3↔v1.0 translation logic lives in `server-conversion` module +- **Transport independence**: JSONRPC, gRPC, and REST handlers share identical conversion logic +- **Testability**: Conversion layer can be tested independently of transport concerns +- **Maintainability**: Changes to conversion rules require updates in one place only + +### TASK_STATE_REJECTED Handling + +`TASK_STATE_REJECTED` (v1.0-only) is mapped to `TASK_STATE_FAILED` when converting to v0.3 wire format. The original state is preserved in metadata (`"original_state": "REJECTED"`) so information is not entirely lost. Both are terminal states, so v0.3 clients can handle the result correctly. + +### Agent Card: v1.0 Only + +The agent card (`/.well-known/agent-card.json`) is produced only using the v1.0 format. The compat layer does not produce a v0.3-format agent card. + +A server that supports both versions should advertise this via a single v1.0 agent card containing multiple `AgentInterface` entries — one per version — each with its own URL and `protocolVersion` field. v0.3 clients must be able to parse the v1.0 agent card format to discover their endpoint. + +**Pros:** +- **Single source of truth**: one agent card at one well-known URL describes all supported versions and transports +- **Simpler server implementation**: no need for separate v0.3 agent card endpoint, serializer, or CDI producer +- **Forward-looking**: encourages v0.3 clients to understand the v1.0 discovery format + +**Cons:** +- **v0.3 clients must parse v1.0 agent card**: pure v0.3 clients that only understand the v0.3 structure need updating + +--- + +## Module Structure + +All compatibility code lives under a top-level `compat-0.3/` directory: + +``` +compat-0.3/ +├── pom.xml # Parent POM for all compat-0.3 submodules +├── spec/ # v0.3 spec types (POJOs) +│ ├── pom.xml +│ └── src/main/java/org/a2aproject/sdk/compat03/spec/ +│ ├── Task_v0_3.java +│ ├── AgentCard_v0_3.java +│ ├── Message_v0_3.java +│ ├── A2AError_v0_3.java # Base error class +│ ├── *Error_v0_3.java # Specific error types +│ └── ... +├── spec-grpc/ # v0.3 proto + generated classes +│ ├── pom.xml +│ └── src/main/ +│ ├── proto/a2a_v0_3.proto # v0.3 proto file (package a2a.v1) +│ └── java/org/a2aproject/sdk/compat03/grpc/ +│ └── [generated classes] # No _v0_3 suffix (generated code) +├── http-client/ # HTTP client abstraction for v0.3 +│ └── pom.xml +├── server-conversion/ # ⭐ Core conversion layer (NEW) +│ ├── pom.xml +│ └── src/main/java/org/a2aproject/sdk/compat03/conversion/ +│ ├── Convert_v0_3_To10RequestHandler.java # Main adapter +│ ├── ErrorConverter_v0_3.java # Error conversion +│ └── mappers/ +│ ├── config/ +│ │ ├── A03ToV10MapperConfig.java # MapStruct config +│ │ └── A2AMappers_v0_3.java # Mapper registry +│ ├── params/ # Request param mappers +│ │ ├── MessageSendParamsMapper_v0_3.java +│ │ ├── TaskQueryParamsMapper_v0_3.java +│ │ ├── CancelTaskParamsMapper_v0_3.java +│ │ └── ... +│ ├── domain/ # Domain object mappers +│ │ ├── TaskMapper_v0_3.java +│ │ ├── MessageMapper_v0_3.java +│ │ ├── TaskStateMapper_v0_3.java +│ │ ├── EventKindMapper_v0_3.java +│ │ └── ... +│ └── result/ # Response result mappers +│ └── ListTaskPushNotificationConfigsResultMapper_v0_3.java +├── client/ # v0.3-compatible client +│ ├── base/ # Client_v0_3 — dedicated 0.3 API +│ │ └── pom.xml +│ └── transport/ +│ ├── spi/ # Transport SPI +│ │ └── pom.xml +│ ├── jsonrpc/ # JSON-RPC client transport for v0.3 +│ │ └── pom.xml +│ ├── grpc/ # gRPC client transport for v0.3 +│ │ └── pom.xml +│ └── rest/ # REST client transport for v0.3 +│ └── pom.xml +├── transport/ # Server-side transport handlers for v0.3 +│ ├── jsonrpc/ # Accept v0.3 JSON-RPC requests +│ │ └── pom.xml +│ ├── grpc/ # Accept v0.3 gRPC requests +│ │ └── pom.xml +│ └── rest/ # Accept v0.3 REST requests +│ └── pom.xml +├── reference/ # Quarkus reference servers for v0.3 +│ ├── jsonrpc/ # Reference JSON-RPC server +│ │ └── pom.xml +│ ├── grpc/ # Reference gRPC server +│ │ └── pom.xml +│ └── rest/ # Reference REST server +│ └── pom.xml +└── tck/ # v0.3 conformance tests + └── pom.xml +``` + +### Java Package Convention + +All compat-0.3 code uses the `org.a2aproject.sdk.compat03` package root: + +- `org.a2aproject.sdk.compat03.spec` — v0.3 spec types +- `org.a2aproject.sdk.compat03.grpc` — generated proto classes +- `org.a2aproject.sdk.compat03.conversion` — conversion layer and mappers +- `org.a2aproject.sdk.compat03.client` — dedicated v0.3 client API +- `org.a2aproject.sdk.compat03.client.transport.{jsonrpc,grpc,rest}` — client transports +- `org.a2aproject.sdk.compat03.transport.{jsonrpc,grpc,rest}` — server transports +- `org.a2aproject.sdk.compat03.server.{apps,grpc,rest}.quarkus` — reference servers +- `org.a2aproject.sdk.compat03.tck` — conformance tests + +**Note**: During this implementation, the main codebase was migrated from `io.github.a2asdk` (groupId) and `io.a2a` (package) to `org.a2aproject.sdk` (both groupId and package) via PRs #750 and #786. + +--- + +## Conversion Layer Architecture + +### Core Component: `Convert_v0_3_To10RequestHandler` + +This is the central adapter that bridges v0.3 transport handlers and v1.0 server-common: + +**Responsibilities:** +- Convert v0.3 params → v1.0 params using mappers +- Delegate to v1.0 `RequestHandler` +- Convert v1.0 results → v0.3 results +- Handle streaming publishers with element-by-element conversion +- Map method name differences (e.g., `onSetTaskPushNotificationConfig` → `onCreateTaskPushNotificationConfig`) + +**Location**: `compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java` + +### Mapper Organization + +Mappers are organized by function using MapStruct: + +| Category | Purpose | Examples | +|----------|---------|----------| +| **params/** | Convert v0.3 request params → v1.0 | `MessageSendParamsMapper_v0_3`, `TaskQueryParamsMapper_v0_3` | +| **domain/** | Convert core domain objects bidirectionally | `TaskMapper_v0_3`, `MessageMapper_v0_3`, `TaskStateMapper_v0_3` | +| **result/** | Convert v1.0 results → v0.3 | `ListTaskPushNotificationConfigsResultMapper_v0_3` | + +**Key Mappings:** + +| v1.0 Type | v0.3 Type | Notes | +|-----------|-----------|-------| +| `SendMessageConfiguration` | `SendMessageConfiguration_v0_3` | `return_immediately` ↔ `!blocking`, `task_push_notification_config` ↔ `push_notification` | +| `Task` | `Task_v0_3` | `CANCELED` ↔ `CANCELLED` | +| `TaskState.TASK_STATE_REJECTED` | `TaskState_v0_3.TASK_STATE_FAILED` | Map to FAILED + metadata `"original_state": "REJECTED"` | +| `Message` | `Message_v0_3` | Drop `reference_task_ids` for v0.3 | + +### Error Mapping + +The `ErrorConverter_v0_3` class centralizes error translation between v0.3 and v1.0: + +**v0.3 → v1.0 (receiving errors):** +- Extract `code` and `message` from v0.3 `A2AError_v0_3` +- Convert `data` (Object) to `details` (Map): if `data` is a Map, use directly; otherwise wrap as `{"data": value}` +- Instantiate correct v1.0 error class using `A2AErrorCodes.fromCode(code)` + +**v1.0 → v0.3 (sending errors):** +- Extract `code`, `message`, and `details` from v1.0 `A2AError` +- Convert `details` (Map) to `data` (Object) +- For v1.0-only error codes, produce generic error with same code/message + +**Location**: `compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/ErrorConverter_v0_3.java` + +--- + +## Test Infrastructure + +### Test-JAR Pattern + +The `server-conversion` module produces a test-jar containing shared test infrastructure: + +**Exported Classes:** +- `AbstractA2ARequestHandlerTest_v0_3` — Base test class with v1.0 backend setup +- `AbstractA2AServerServerTest_v0_3` — Integration test base for reference servers +- Test fixtures and utilities + +**Maven Configuration:** +```xml + + maven-jar-plugin + + + + test-jar + + + + +``` + +**Consumers:** +- `compat-0.3/transport/jsonrpc` — `JSONRPCHandlerTest_v0_3` +- `compat-0.3/transport/grpc` — `GrpcHandlerTest_v0_3` +- `compat-0.3/transport/rest` — `RestHandlerTest_v0_3` +- `compat-0.3/reference/{jsonrpc,grpc,rest}` — Integration tests + +### Test Coverage + +✅ **Complete:** +- Core transport handler tests (JSONRPC, gRPC, REST) +- Streaming tests (Flow.Publisher, SSE, gRPC server streaming) +- Error mapping tests +- Task state conversion tests +- Reference server integration tests + +🔲 **Deferred:** +- Push notification tests (depends on TestHttpClient porting) +- Test metadata classes (classpath scanning) + +--- + +## User Experience + +### Client: Talking to a v0.3 Agent + +**1. Add the compat client dependency:** + +```xml + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client + + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + +``` + +**2. Check the agent card and choose the right client:** + +```java +AgentCard card = // ... fetch agent card from /.well-known/agent-card.json + +for (AgentInterface iface : card.supportedInterfaces()) { + if ("0.3".equals(iface.protocolVersion())) { + // Use the compat client for v0.3 agents + Client_v0_3 client = ClientBuilder_v0_3.forUrl(iface.url()) + .transport("JSONRPC") + .build(); + } else if ("1.0".equals(iface.protocolVersion())) { + // Use the standard client for v1.0 agents + Client client = ClientBuilder.forUrl(iface.url()) + .transport("JSONRPC") + .build(); + } +} +``` + +**3. Use the v0.3 client API:** + +`Client_v0_3` exposes only operations available in v0.3. Return types are v0.3 `org.a2aproject.sdk.compat03.spec` domain objects. + +### Server: Serving v0.3 Clients + +A server operator that wants to accept v0.3 clients: + +**1. Add the compat Maven dependency:** + +```xml + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-jsonrpc + +``` + +**2. Provide a v0.3 AgentCard:** + +```java +@Produces @PublicAgentCard +public AgentCard_v0_3 agentCard() { + return AgentCard_v0_3.builder() + .name("My Agent") + .url("http://localhost:8081") + .preferredTransport("JSONRPC") + // ... rest of agent card + .build(); +} +``` + +**3. No changes to AgentExecutor:** + +The existing `AgentExecutor` implementation works unchanged. The compat reference module registers v0.3 transport endpoints via Quarkus CDI auto-discovery and delegates to the same `AgentExecutor` through the v1.0 server pipeline. + +### Server: Serving Both v0.3 and v1.0 (Deferred) + +**Status**: Architecture is in place but dual-version deployment pattern is not yet defined. + +**Remaining work:** +- Define CDI qualifier pattern to differentiate v0.3 and v1.0 beans +- Establish path prefix strategy (e.g., `/v0.3` for compat endpoints) +- Unified agent card production with multiple `AgentInterface` entries +- Integration testing for dual-version scenarios + +**Recommended approach:** +1. Use separate URLs per protocol version (e.g., `http://localhost:9999` for v1.0, `http://localhost:9999/v0.3` for v0.3) +2. Declare both in the v1.0 agent card with different `protocolVersion` values +3. Register both transport handlers via Quarkus CDI with path-based routing + +--- + +## Implementation Summary + +The implementation was completed in phases: + +### Phase 1: Foundation +- Set up module structure and POMs +- Port v0.3 spec types to `compat-0.3/spec` +- Generate v0.3 gRPC classes in `compat-0.3/spec-grpc` +- Apply `_v0_3` suffix naming convention + +### Phase 2: Conversion Layer +- Create `server-conversion` module +- Implement `Convert_v0_3_To10RequestHandler` +- Build MapStruct mappers (params, domain, result) +- Centralize error conversion in `ErrorConverter_v0_3` +- Export test infrastructure via test-jar + +### Phase 3: Transport Handlers +- Implement server-side transport handlers (JSONRPC, gRPC, REST) +- Wire each transport to `Convert_v0_3_To10RequestHandler` +- Test with v1.0 backend via `AbstractA2ARequestHandlerTest_v0_3` + +### Phase 4: Client +- Implement `Client_v0_3` API +- Build client transports (JSONRPC, gRPC, REST) +- Validate against v0.3 spec constraints + +### Phase 5: Reference Servers +- Port Quarkus reference servers (JSONRPC, gRPC, REST) +- Integrate with test infrastructure +- Run integration tests using v0.3 client against v0.3 reference servers + +### Phase 6: Testing & Validation +- Port transport handler tests (37+ tests across 3 transports) +- Port streaming tests (Flow.Publisher, SSE, gRPC) +- Port reference server tests (125+ integration tests passing) +- Enable TCK module + +--- + +## Key Differences from Original Plan + +1. **Conversion layer as separate module**: Original plan embedded mapping in `spec-grpc`; implementation uses dedicated `server-conversion` module with `Convert_v0_3_To10RequestHandler` + +2. **`_v0_3` suffix naming**: Not in original plan; adopted to eliminate IDE naming conflicts (233 out of 284 classes had conflicts) + +3. **No `reference/common` module**: Each reference server is standalone; no shared reference base + +4. **Test-jar pattern**: Test infrastructure exported from `server-conversion` module rather than reference common + +5. **Package migration during implementation**: The main codebase migrated from `io.a2a` to `org.a2aproject.sdk` while this work was in progress (PRs #750, #786) + +6. **Implementation order**: Test infrastructure built early; tests ported incrementally to validate conversion layer + +--- + +## Testing Strategy + +| Component | Test Type | Coverage | +|-----------|-----------|----------| +| Mappers | Unit tests | Round-trip conversion for every mapped type; edge cases (missing fields, v1.0-only features, REJECTED→FAILED) | +| `Convert_v0_3_To10RequestHandler` | Integration tests | Via transport handler tests using real v1.0 backend | +| Transport handlers | Unit + Integration | Handler-level tests + end-to-end via reference servers | +| Client transports | Unit tests | Mocked v0.3 endpoints | +| `Client_v0_3` | Unit tests | API coverage, absence of v1.0-only methods | +| Reference servers | Integration tests | Full request/response cycle with v0.3 client | +| TCK | Conformance tests | Protocol conformance against v0.3 spec | + +--- + +## Status + +✅ **Complete:** +- Module structure and POMs +- v0.3 spec types and gRPC generation +- Server conversion layer with all mappers +- Server-side transport handlers (JSONRPC, gRPC, REST) +- Client API and transports +- Reference servers (JSONRPC, gRPC, REST) +- Test infrastructure (test-jar pattern) +- Core integration tests (125+ passing) +- TCK module enabled + +🔲 **Deferred:** +- Dual v1.0/v0.3 server deployment pattern +- Push notification test porting (requires TestHttpClient) +- Test metadata classes (classpath scanning) + +🧹 **Nice-to-have cleanup:** +- Replace FQNs with imports (97 occurrences in 34 files) +- Unify AgentCard producers across reference modules +- Remove obsolete TODOs diff --git a/boms/extras/src/it/extras-usage-test/src/main/java/org/a2aproject/sdk/test/ExtrasBomVerifier.java b/boms/extras/src/it/extras-usage-test/src/main/java/org/a2aproject/sdk/test/ExtrasBomVerifier.java index 8357ce447..c5b727633 100644 --- a/boms/extras/src/it/extras-usage-test/src/main/java/org/a2aproject/sdk/test/ExtrasBomVerifier.java +++ b/boms/extras/src/it/extras-usage-test/src/main/java/org/a2aproject/sdk/test/ExtrasBomVerifier.java @@ -17,6 +17,7 @@ public class ExtrasBomVerifier extends DynamicBomVerifier { "tck/", // TCK test suite "tests/", // Integration tests "test-utils-docker/", // Test utilities for Docker-based tests + "compat-0.3/", // Compat 0.3 modules (part of SDK BOM, not extras BOM) "extras/queue-manager-replicated/tests-multi-instance/", // Test harness applications "extras/queue-manager-replicated/tests-single-instance/", // Test harness applications "extras/opentelemetry/integration-tests/" // Test harness applications diff --git a/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java b/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java index 6b20bb50e..d25473846 100644 --- a/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java +++ b/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java @@ -16,7 +16,8 @@ public class ReferenceBomVerifier extends DynamicBomVerifier { "examples/", // Example applications "tck/", // TCK test suite "tests/", // Integration tests - "test-utils-docker/" // Test utilities for Docker-based tests + "test-utils-docker/", // Test utilities for Docker-based tests + "compat-0.3/" // Compat 0.3 modules (part of SDK BOM, not reference BOM) // Note: reference/ is NOT in this list - we want to verify those classes load ); diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index c0f0da9a2..d901f680d 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -108,6 +108,86 @@ ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec-grpc + ${project.version} + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-http-client + ${project.version} + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-spi + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-grpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-rest + ${project.version} + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-grpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-rest + ${project.version} + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-grpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-rest + ${project.version} + + ${project.groupId} diff --git a/boms/sdk/src/it/sdk-usage-test/pom.xml b/boms/sdk/src/it/sdk-usage-test/pom.xml index 5da56e93e..3d158598b 100644 --- a/boms/sdk/src/it/sdk-usage-test/pom.xml +++ b/boms/sdk/src/it/sdk-usage-test/pom.xml @@ -103,6 +103,72 @@ a2a-java-sdk-transport-rest + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-spec + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-spec-grpc + + + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-http-client + + + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client-transport-spi + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client-transport-grpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client-transport-rest + + + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-transport-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-transport-grpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-transport-rest + + + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-grpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-rest + + org.slf4j diff --git a/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java b/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java index f69d70b85..7f0607b8d 100644 --- a/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java +++ b/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java @@ -15,6 +15,7 @@ public class SdkBomVerifier extends DynamicBomVerifier { "boms/", // BOM test modules themselves "examples/", // Example applications "tck/", // TCK test suite + "compat-0.3/tck/", // Compat 0.3 TCK (not yet enabled) "tests/", // Integration tests "test-utils-docker/" // Test utilities for Docker-based tests ); diff --git a/compat-0.3/client/base/pom.xml b/compat-0.3/client/base/pom.xml new file mode 100644 index 000000000..6fa0036ff --- /dev/null +++ b/compat-0.3/client/base/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../.. + + a2a-java-sdk-compat-0.3-client + + jar + + Java SDK A2A Compat 0.3 Client + Java SDK for the Agent2Agent Protocol (A2A) - Client + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-http-client + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-spi + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-grpc + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-rest + test + + + ${project.groupId} + a2a-java-sdk-common + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec-grpc + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + org.mock-server + mockserver-netty + test + + + org.slf4j + slf4j-jdk14 + test + + + io.grpc + grpc-testing + test + + + io.grpc + grpc-inprocess + test + + + + \ No newline at end of file diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A_v0_3.java new file mode 100644 index 000000000..2be60b7ad --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A_v0_3.java @@ -0,0 +1,188 @@ +package org.a2aproject.sdk.compat03; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.compat03.client.http.A2ACardResolver_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientJSONError_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; + + +/** + * Constants and utility methods related to the A2A protocol. + */ +public class A2A_v0_3 { + + /** + * Convert the given text to a user message. + * + * @param text the message text + * @return the user message + */ + public static Message_v0_3 toUserMessage(String text) { + return toMessage(text, Message_v0_3.Role.USER, null); + } + + /** + * Convert the given text to a user message. + * + * @param text the message text + * @param messageId the message ID to use + * @return the user message + */ + public static Message_v0_3 toUserMessage(String text, String messageId) { + return toMessage(text, Message_v0_3.Role.USER, messageId); + } + + /** + * Convert the given text to an agent message. + * + * @param text the message text + * @return the agent message + */ + public static Message_v0_3 toAgentMessage(String text) { + return toMessage(text, Message_v0_3.Role.AGENT, null); + } + + /** + * Convert the given text to an agent message. + * + * @param text the message text + * @param messageId the message ID to use + * @return the agent message + */ + public static Message_v0_3 toAgentMessage(String text, String messageId) { + return toMessage(text, Message_v0_3.Role.AGENT, messageId); + } + + /** + * Create a user message with text content and optional context and task IDs. + * + * @param text the message text (required) + * @param contextId the context ID to use (optional) + * @param taskId the task ID to use (optional) + * @return the user message + */ + public static Message_v0_3 createUserTextMessage(String text, String contextId, String taskId) { + return toMessage(text, Message_v0_3.Role.USER, null, contextId, taskId); + } + + /** + * Create an agent message with text content and optional context and task IDs. + * + * @param text the message text (required) + * @param contextId the context ID to use (optional) + * @param taskId the task ID to use (optional) + * @return the agent message + */ + public static Message_v0_3 createAgentTextMessage(String text, String contextId, String taskId) { + return toMessage(text, Message_v0_3.Role.AGENT, null, contextId, taskId); + } + + /** + * Create an agent message with custom parts and optional context and task IDs. + * + * @param parts the message parts (required) + * @param contextId the context ID to use (optional) + * @param taskId the task ID to use (optional) + * @return the agent message + */ + public static Message_v0_3 createAgentPartsMessage(List> parts, String contextId, String taskId) { + if (parts == null || parts.isEmpty()) { + throw new IllegalArgumentException("Parts cannot be null or empty"); + } + return toMessage(parts, Message_v0_3.Role.AGENT, null, contextId, taskId); + } + + private static Message_v0_3 toMessage(String text, Message_v0_3.Role role, String messageId) { + return toMessage(text, role, messageId, null, null); + } + + private static Message_v0_3 toMessage(String text, Message_v0_3.Role role, String messageId, String contextId, String taskId) { + Message_v0_3.Builder messageBuilder = new Message_v0_3.Builder() + .role(role) + .parts(Collections.singletonList(new TextPart_v0_3(text))) + .contextId(contextId) + .taskId(taskId); + if (messageId != null) { + messageBuilder.messageId(messageId); + } + return messageBuilder.build(); + } + + private static Message_v0_3 toMessage(List> parts, Message_v0_3.Role role, String messageId, String contextId, String taskId) { + Message_v0_3.Builder messageBuilder = new Message_v0_3.Builder() + .role(role) + .parts(parts) + .contextId(contextId) + .taskId(taskId); + if (messageId != null) { + messageBuilder.messageId(messageId); + } + return messageBuilder.build(); + } + + /** + * Get the agent card for an A2A agent. + * + * @param agentUrl the base URL for the agent whose agent card we want to retrieve + * @return the agent card + * @throws A2AClientError_v0_3 If an HTTP error occurs fetching the card + * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema + */ + public static AgentCard_v0_3 getAgentCard(String agentUrl) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { + return getAgentCard(new JdkA2AHttpClient_v0_3(), agentUrl); + } + + /** + * Get the agent card for an A2A agent. + * + * @param httpClient the http client to use + * @param agentUrl the base URL for the agent whose agent card we want to retrieve + * @return the agent card + * @throws A2AClientError_v0_3 If an HTTP error occurs fetching the card + * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema + */ + public static AgentCard_v0_3 getAgentCard(A2AHttpClient_v0_3 httpClient, String agentUrl) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { + return getAgentCard(httpClient, agentUrl, null, null); + } + + /** + * Get the agent card for an A2A agent. + * + * @param agentUrl the base URL for the agent whose agent card we want to retrieve + * @param relativeCardPath optional path to the agent card endpoint relative to the base + * agent URL, defaults to ".well-known/agent-card.json" + * @param authHeaders the HTTP authentication headers to use + * @return the agent card + * @throws A2AClientError_v0_3 If an HTTP error occurs fetching the card + * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema + */ + public static AgentCard_v0_3 getAgentCard(String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { + return getAgentCard(new JdkA2AHttpClient_v0_3(), agentUrl, relativeCardPath, authHeaders); + } + + /** + * Get the agent card for an A2A agent. + * + * @param httpClient the http client to use + * @param agentUrl the base URL for the agent whose agent card we want to retrieve + * @param relativeCardPath optional path to the agent card endpoint relative to the base + * agent URL, defaults to ".well-known/agent-card.json" + * @param authHeaders the HTTP authentication headers to use + * @return the agent card + * @throws A2AClientError_v0_3 If an HTTP error occurs fetching the card + * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema + */ + public static AgentCard_v0_3 getAgentCard(A2AHttpClient_v0_3 httpClient, String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(httpClient, agentUrl, relativeCardPath, authHeaders); + return resolver.getAgentCard(); + } +} diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/AbstractClient_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/AbstractClient_v0_3.java new file mode 100644 index 000000000..d27372f69 --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/AbstractClient_v0_3.java @@ -0,0 +1,392 @@ +package org.a2aproject.sdk.compat03.client; + +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + +/** + * Abstract class representing an A2A client. Provides a standard set + * of methods for interacting with an A2A agent, regardless of the underlying + * transport protocol. It supports sending messages, managing tasks, and + * handling event streams. + */ +public abstract class AbstractClient_v0_3 { + + private final List> consumers; + private final @Nullable Consumer streamingErrorHandler; + + public AbstractClient_v0_3(List> consumers) { + this(consumers, null); + } + + public AbstractClient_v0_3(@NonNull List> consumers, @Nullable Consumer streamingErrorHandler) { + checkNotNullParam("consumers", consumers); + this.consumers = consumers; + this.streamingErrorHandler = streamingErrorHandler; + } + + /** + * Send a message to the remote agent. This method will automatically use + * the streaming or non-streaming approach as determined by the server's + * agent card and the client configuration. The configured client consumers + * will be used to handle messages, tasks, and update events received + * from the remote agent. The configured streaming error handler will be used + * if an error occurs during streaming. The configured client push notification + * configuration will get used for streaming. + * + * @param request the message + * @throws A2AClientException_v0_3 if sending the message fails for any reason + */ + public void sendMessage(Message_v0_3 request) throws A2AClientException_v0_3 { + sendMessage(request, null); + } + + /** + * Send a message to the remote agent. This method will automatically use + * the streaming or non-streaming approach as determined by the server's + * agent card and the client configuration. The configured client consumers + * will be used to handle messages, tasks, and update events received + * from the remote agent. The configured streaming error handler will be used + * if an error occurs during streaming. The configured client push notification + * configuration will get used for streaming. + * + * @param request the message + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if sending the message fails for any reason + */ + public abstract void sendMessage(Message_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Send a message to the remote agent. This method will automatically use + * the streaming or non-streaming approach as determined by the server's + * agent card and the client configuration. The specified client consumers + * will be used to handle messages, tasks, and update events received + * from the remote agent. The specified streaming error handler will be used + * if an error occurs during streaming. The configured client push notification + * configuration will get used for streaming. + * + * @param request the message + * @param consumers a list of consumers to pass responses from the remote agent to + * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs + * @throws A2AClientException_v0_3 if sending the message fails for any reason + */ + public void sendMessage(Message_v0_3 request, + List> consumers, + Consumer streamingErrorHandler) throws A2AClientException_v0_3 { + sendMessage(request, consumers, streamingErrorHandler, null); + } + + /** + * Send a message to the remote agent. This method will automatically use + * the streaming or non-streaming approach as determined by the server's + * agent card and the client configuration. The specified client consumers + * will be used to handle messages, tasks, and update events received + * from the remote agent. The specified streaming error handler will be used + * if an error occurs during streaming. The configured client push notification + * configuration will get used for streaming. + * + * @param request the message + * @param consumers a list of consumers to pass responses from the remote agent to + * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if sending the message fails for any reason + */ + public abstract void sendMessage(Message_v0_3 request, + List> consumers, + Consumer streamingErrorHandler, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Send a message to the remote agent. This method will automatically use + * the streaming or non-streaming approach as determined by the server's + * agent card and the client configuration. The configured client consumers + * will be used to handle messages, tasks, and update events received from + * the remote agent. The configured streaming error handler will be used + * if an error occurs during streaming. + * + * @param request the message + * @param pushNotificationConfiguration the push notification configuration that should be + * used if the streaming approach is used + * @param metadata the optional metadata to include when sending the message + * @throws A2AClientException_v0_3 if sending the message fails for any reason + */ + public void sendMessage(Message_v0_3 request, PushNotificationConfig_v0_3 pushNotificationConfiguration, + Map metadata) throws A2AClientException_v0_3 { + sendMessage(request, pushNotificationConfiguration, metadata, null); + } + + /** + * Send a message to the remote agent. This method will automatically use + * the streaming or non-streaming approach as determined by the server's + * agent card and the client configuration. The configured client consumers + * will be used to handle messages, tasks, and update events received from + * the remote agent. The configured streaming error handler will be used + * if an error occurs during streaming. + * + * @param request the message + * @param pushNotificationConfiguration the push notification configuration that should be + * used if the streaming approach is used + * @param metadata the optional metadata to include when sending the message + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if sending the message fails for any reason + */ + public abstract void sendMessage(Message_v0_3 request, PushNotificationConfig_v0_3 pushNotificationConfiguration, + Map metadata, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Retrieve the current state and history of a specific task. + * + * @param request the task query parameters specifying which task to retrieve + * @return the task + * @throws A2AClientException_v0_3 if retrieving the task fails for any reason + */ + public Task_v0_3 getTask(TaskQueryParams_v0_3 request) throws A2AClientException_v0_3 { + return getTask(request, null); + } + + /** + * Retrieve the current state and history of a specific task. + * + * @param request the task query parameters specifying which task to retrieve + * @param context optional client call context for the request (may be {@code null}) + * @return the task + * @throws A2AClientException_v0_3 if retrieving the task fails for any reason + */ + public abstract Task_v0_3 getTask(TaskQueryParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Request the agent to cancel a specific task. + * + * @param request the task ID parameters specifying which task to cancel + * @return the cancelled task + * @throws A2AClientException_v0_3 if cancelling the task fails for any reason + */ + public Task_v0_3 cancelTask(TaskIdParams_v0_3 request) throws A2AClientException_v0_3 { + return cancelTask(request, null); + } + + /** + * Request the agent to cancel a specific task. + * + * @param request the task ID parameters specifying which task to cancel + * @param context optional client call context for the request (may be {@code null}) + * @return the cancelled task + * @throws A2AClientException_v0_3 if cancelling the task fails for any reason + */ + public abstract Task_v0_3 cancelTask(TaskIdParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Set or update the push notification configuration for a specific task. + * + * @param request the push notification configuration to set for the task + * @return the configured TaskPushNotificationConfig + * @throws A2AClientException_v0_3 if setting the task push notification configuration fails for any reason + */ + public TaskPushNotificationConfig_v0_3 setTaskPushNotificationConfiguration( + TaskPushNotificationConfig_v0_3 request) throws A2AClientException_v0_3 { + return setTaskPushNotificationConfiguration(request, null); + } + + /** + * Set or update the push notification configuration for a specific task. + * + * @param request the push notification configuration to set for the task + * @param context optional client call context for the request (may be {@code null}) + * @return the configured TaskPushNotificationConfig + * @throws A2AClientException_v0_3 if setting the task push notification configuration fails for any reason + */ + public abstract TaskPushNotificationConfig_v0_3 setTaskPushNotificationConfiguration( + TaskPushNotificationConfig_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Retrieve the push notification configuration for a specific task. + * + * @param request the parameters specifying which task's notification config to retrieve + * @return the task push notification config + * @throws A2AClientException_v0_3 if getting the task push notification config fails for any reason + */ + public TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration( + GetTaskPushNotificationConfigParams_v0_3 request) throws A2AClientException_v0_3 { + return getTaskPushNotificationConfiguration(request, null); + } + + /** + * Retrieve the push notification configuration for a specific task. + * + * @param request the parameters specifying which task's notification config to retrieve + * @param context optional client call context for the request (may be {@code null}) + * @return the task push notification config + * @throws A2AClientException_v0_3 if getting the task push notification config fails for any reason + */ + public abstract TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration( + GetTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Retrieve the list of push notification configurations for a specific task. + * + * @param request the parameters specifying which task's notification configs to retrieve + * @return the list of task push notification configs + * @throws A2AClientException_v0_3 if getting the task push notification configs fails for any reason + */ + public List listTaskPushNotificationConfigurations( + ListTaskPushNotificationConfigParams_v0_3 request) throws A2AClientException_v0_3 { + return listTaskPushNotificationConfigurations(request, null); + } + + /** + * Retrieve the list of push notification configurations for a specific task. + * + * @param request the parameters specifying which task's notification configs to retrieve + * @param context optional client call context for the request (may be {@code null}) + * @return the list of task push notification configs + * @throws A2AClientException_v0_3 if getting the task push notification configs fails for any reason + */ + public abstract List listTaskPushNotificationConfigurations( + ListTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Delete the list of push notification configurations for a specific task. + * + * @param request the parameters specifying which task's notification configs to delete + * @throws A2AClientException_v0_3 if deleting the task push notification configs fails for any reason + */ + public void deleteTaskPushNotificationConfigurations( + DeleteTaskPushNotificationConfigParams_v0_3 request) throws A2AClientException_v0_3 { + deleteTaskPushNotificationConfigurations(request, null); + } + + /** + * Delete the list of push notification configurations for a specific task. + * + * @param request the parameters specifying which task's notification configs to delete + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if deleting the task push notification configs fails for any reason + */ + public abstract void deleteTaskPushNotificationConfigurations( + DeleteTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Resubscribe to a task's event stream. + * This is only available if both the client and server support streaming. + * The configured client consumers will be used to handle messages, tasks, + * and update events received from the remote agent. The configured streaming + * error handler will be used if an error occurs during streaming. + * + * @param request the parameters specifying which task's notification configs to delete + * @throws A2AClientException_v0_3 if resubscribing fails for any reason + */ + public void resubscribe(TaskIdParams_v0_3 request) throws A2AClientException_v0_3 { + resubscribe(request, null); + } + + /** + * Resubscribe to a task's event stream. + * This is only available if both the client and server support streaming. + * The configured client consumers will be used to handle messages, tasks, + * and update events received from the remote agent. The configured streaming + * error handler will be used if an error occurs during streaming. + * + * @param request the parameters specifying which task's notification configs to delete + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if resubscribing fails for any reason + */ + public abstract void resubscribe(TaskIdParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Resubscribe to a task's event stream. + * This is only available if both the client and server support streaming. + * The specified client consumers will be used to handle messages, tasks, and + * update events received from the remote agent. The specified streaming error + * handler will be used if an error occurs during streaming. + * + * @param request the parameters specifying which task's notification configs to delete + * @param consumers a list of consumers to pass responses from the remote agent to + * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs + * @throws A2AClientException_v0_3 if resubscribing fails for any reason + */ + public void resubscribe(TaskIdParams_v0_3 request, List> consumers, + Consumer streamingErrorHandler) throws A2AClientException_v0_3 { + resubscribe(request, consumers, streamingErrorHandler, null); + } + + /** + * Resubscribe to a task's event stream. + * This is only available if both the client and server support streaming. + * The specified client consumers will be used to handle messages, tasks, and + * update events received from the remote agent. The specified streaming error + * handler will be used if an error occurs during streaming. + * + * @param request the parameters specifying which task's notification configs to delete + * @param consumers a list of consumers to pass responses from the remote agent to + * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if resubscribing fails for any reason + */ + public abstract void resubscribe(TaskIdParams_v0_3 request, List> consumers, + Consumer streamingErrorHandler, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Retrieve the AgentCard. + * + * @return the AgentCard + * @throws A2AClientException_v0_3 if retrieving the agent card fails for any reason + */ + public AgentCard_v0_3 getAgentCard() throws A2AClientException_v0_3 { + return getAgentCard(null); + } + + /** + * Retrieve the AgentCard. + * + * @param context optional client call context for the request (may be {@code null}) + * @return the AgentCard + * @throws A2AClientException_v0_3 if retrieving the agent card fails for any reason + */ + public abstract AgentCard_v0_3 getAgentCard(@Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Close the transport and release any associated resources. + */ + public abstract void close(); + + /** + * Process the event using all configured consumers. + */ + void consume(ClientEvent_v0_3 clientEventOrMessage, AgentCard_v0_3 agentCard) { + for (BiConsumer consumer : consumers) { + consumer.accept(clientEventOrMessage, agentCard); + } + } + + /** + * Get the error handler that should be used during streaming. + * + * @return the streaming error handler + */ + public @Nullable Consumer getStreamingErrorHandler() { + return streamingErrorHandler; + } + +} \ No newline at end of file diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3.java new file mode 100644 index 000000000..b2fe661c2 --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3.java @@ -0,0 +1,169 @@ +package org.a2aproject.sdk.compat03.client; + +import org.a2aproject.sdk.compat03.client.config.ClientConfig_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfig_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentInterface_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; + +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; + +public class ClientBuilder_v0_3 { + + private static final Map>> transportProviderRegistry = new HashMap<>(); + private static final Map, String> transportProtocolMapping = new HashMap<>(); + + static { + ServiceLoader loader = ServiceLoader.load(ClientTransportProvider_v0_3.class); + for (ClientTransportProvider_v0_3 transport : loader) { + transportProviderRegistry.put(transport.getTransportProtocol(), transport); + transportProtocolMapping.put(transport.getTransportProtocolClass(), transport.getTransportProtocol()); + } + } + + private final AgentCard_v0_3 agentCard; + + private final List> consumers = new ArrayList<>(); + private @Nullable Consumer streamErrorHandler; + private ClientConfig_v0_3 clientConfig = new ClientConfig_v0_3.Builder().build(); + + private final Map, ClientTransportConfig_v0_3> clientTransports = new LinkedHashMap<>(); + + ClientBuilder_v0_3(@NonNull AgentCard_v0_3 agentCard) { + this.agentCard = agentCard; + } + + public ClientBuilder_v0_3 withTransport(Class clazz, ClientTransportConfigBuilder_v0_3, ?> configBuilder) { + return withTransport(clazz, configBuilder.build()); + } + + public ClientBuilder_v0_3 withTransport(Class clazz, ClientTransportConfig_v0_3 config) { + clientTransports.put(clazz, config); + + return this; + } + + public ClientBuilder_v0_3 addConsumer(BiConsumer consumer) { + this.consumers.add(consumer); + return this; + } + + public ClientBuilder_v0_3 addConsumers(List> consumers) { + this.consumers.addAll(consumers); + return this; + } + + public ClientBuilder_v0_3 streamingErrorHandler(Consumer streamErrorHandler) { + this.streamErrorHandler = streamErrorHandler; + return this; + } + + public ClientBuilder_v0_3 clientConfig(@NonNull ClientConfig_v0_3 clientConfig) { + this.clientConfig = clientConfig; + return this; + } + + public Client_v0_3 build() throws A2AClientException_v0_3 { + if (this.clientConfig == null) { + this.clientConfig = new ClientConfig_v0_3.Builder().build(); + } + + ClientTransport_v0_3 clientTransport = buildClientTransport(); + + return new Client_v0_3(agentCard, clientConfig, clientTransport, consumers, streamErrorHandler); + } + + @SuppressWarnings("unchecked") + private ClientTransport_v0_3 buildClientTransport() throws A2AClientException_v0_3 { + // Get the preferred transport + AgentInterface_v0_3 agentInterface = findBestClientTransport(); + + // Get the transport provider associated with the protocol + ClientTransportProvider_v0_3 clientTransportProvider = transportProviderRegistry.get(agentInterface.transport()); + if (clientTransportProvider == null) { + throw new A2AClientException_v0_3("No client available for " + agentInterface.transport()); + } + Class transportProtocolClass = clientTransportProvider.getTransportProtocolClass(); + + // Retrieve the configuration associated with the preferred transport + ClientTransportConfig_v0_3 clientTransportConfig = clientTransports.get(transportProtocolClass); + + if (clientTransportConfig == null) { + throw new A2AClientException_v0_3("Missing required TransportConfig for " + agentInterface.transport()); + } + + return clientTransportProvider.create(clientTransportConfig, agentCard, agentInterface.url()); + } + + private Map getServerPreferredTransports() { + Map serverPreferredTransports = new LinkedHashMap<>(); + serverPreferredTransports.put(agentCard.preferredTransport(), agentCard.url()); + if (agentCard.additionalInterfaces() != null) { + for (AgentInterface_v0_3 agentInterface : agentCard.additionalInterfaces()) { + serverPreferredTransports.putIfAbsent(agentInterface.transport(), agentInterface.url()); + } + } + return serverPreferredTransports; + } + + private List getClientPreferredTransports() { + List supportedClientTransports = new ArrayList<>(); + + if (clientTransports.isEmpty()) { + // default to JSONRPC if not specified + supportedClientTransports.add(TransportProtocol_v0_3.JSONRPC.asString()); + } else { + clientTransports.forEach((aClass, clientTransportConfig) -> supportedClientTransports.add(transportProtocolMapping.get(aClass))); + } + return supportedClientTransports; + } + + private AgentInterface_v0_3 findBestClientTransport() throws A2AClientException_v0_3 { + // Retrieve transport supported by the A2A server + Map serverPreferredTransports = getServerPreferredTransports(); + + // Retrieve transport configured for this client (using withTransport methods) + List clientPreferredTransports = getClientPreferredTransports(); + + String transportProtocol = null; + String transportUrl = null; + if (clientConfig.isUseClientPreference()) { + for (String clientPreferredTransport : clientPreferredTransports) { + if (serverPreferredTransports.containsKey(clientPreferredTransport)) { + transportProtocol = clientPreferredTransport; + transportUrl = serverPreferredTransports.get(transportProtocol); + break; + } + } + } else { + for (Map.Entry transport : serverPreferredTransports.entrySet()) { + if (clientPreferredTransports.contains(transport.getKey())) { + transportProtocol = transport.getKey(); + transportUrl = transport.getValue(); + break; + } + } + } + if (transportProtocol == null || transportUrl == null) { + throw new A2AClientException_v0_3("No compatible transport found"); + } + if (! transportProviderRegistry.containsKey(transportProtocol)) { + throw new A2AClientException_v0_3("No client available for " + transportProtocol); + } + + return new AgentInterface_v0_3(transportProtocol, transportUrl); + } +} diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientEvent_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientEvent_v0_3.java new file mode 100644 index 000000000..498814a56 --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientEvent_v0_3.java @@ -0,0 +1,4 @@ +package org.a2aproject.sdk.compat03.client; + +public sealed interface ClientEvent_v0_3 permits MessageEvent_v0_3, TaskEvent_v0_3, TaskUpdateEvent_v0_3 { +} diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientTaskManager_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientTaskManager_v0_3.java new file mode 100644 index 000000000..0a29a0aa6 --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientTaskManager_v0_3.java @@ -0,0 +1,139 @@ +package org.a2aproject.sdk.compat03.client; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.appendArtifactToTask; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientInvalidArgsError_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientInvalidStateError_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.jspecify.annotations.Nullable; + +/** + * Helps manage a task's lifecycle during the execution of a request. + * Responsible for retrieving, saving, and updating the task based on + * events received from the agent. + */ +public class ClientTaskManager_v0_3 { + + private @Nullable Task_v0_3 currentTask; + private @Nullable String taskId; + private @Nullable String contextId; + + public ClientTaskManager_v0_3() { + this.currentTask = null; + this.taskId = null; + this.contextId = null; + } + + public Task_v0_3 getCurrentTask() throws A2AClientInvalidStateError_v0_3 { + if (currentTask == null) { + throw new A2AClientInvalidStateError_v0_3("No current task"); + } + return currentTask; + } + + public Task_v0_3 saveTaskEvent(Task_v0_3 task) throws A2AClientInvalidArgsError_v0_3 { + if (currentTask != null) { + throw new A2AClientInvalidArgsError_v0_3("Task is already set, create new manager for new tasks."); + } + saveTask(task); + return task; + } + + public Task_v0_3 saveTaskEvent(TaskStatusUpdateEvent_v0_3 taskStatusUpdateEvent) throws A2AClientError_v0_3 { + if (taskId == null) { + taskId = taskStatusUpdateEvent.getTaskId(); + } + if (contextId == null) { + contextId = taskStatusUpdateEvent.getContextId(); + } + Task_v0_3 task = currentTask; + if (task == null) { + task = new Task_v0_3.Builder() + .status(new TaskStatus_v0_3(TaskState_v0_3.UNKNOWN)) + .id(taskId) + .contextId(contextId == null ? "" : contextId) + .build(); + } + + Task_v0_3.Builder taskBuilder = new Task_v0_3.Builder(task); + if (taskStatusUpdateEvent.getStatus().message() != null) { + if (task.getHistory() == null) { + taskBuilder.history(taskStatusUpdateEvent.getStatus().message()); + } else { + List history = new ArrayList<>(task.getHistory()); + history.add(taskStatusUpdateEvent.getStatus().message()); + taskBuilder.history(history); + } + } + if (taskStatusUpdateEvent.getMetadata() != null) { + Map newMetadata = task.getMetadata() != null ? new HashMap<>(task.getMetadata()) : new HashMap<>(); + newMetadata.putAll(taskStatusUpdateEvent.getMetadata()); + taskBuilder.metadata(newMetadata); + } + taskBuilder.status(taskStatusUpdateEvent.getStatus()); + currentTask = taskBuilder.build(); + return currentTask; + } + + public Task_v0_3 saveTaskEvent(TaskArtifactUpdateEvent_v0_3 taskArtifactUpdateEvent) { + if (taskId == null) { + taskId = taskArtifactUpdateEvent.getTaskId(); + } + if (contextId == null) { + contextId = taskArtifactUpdateEvent.getContextId(); + } + Task_v0_3 task = currentTask; + if (task == null) { + task = new Task_v0_3.Builder() + .status(new TaskStatus_v0_3(TaskState_v0_3.UNKNOWN)) + .id(taskId) + .contextId(contextId == null ? "" : contextId) + .build(); + } + currentTask = appendArtifactToTask(task, taskArtifactUpdateEvent, taskId); + return currentTask; + } + + /** + * Update a task by adding a message to its history. If the task has a message in its current status, + * that message is moved to the history first. + * + * @param message the new message to add to the history + * @param task the task to update + * @return the updated task + */ + public Task_v0_3 updateWithMessage(Message_v0_3 message, Task_v0_3 task) { + Task_v0_3.Builder taskBuilder = new Task_v0_3.Builder(task); + List history = task.getHistory(); + if (history == null) { + history = new ArrayList<>(); + } + if (task.getStatus().message() != null) { + history.add(task.getStatus().message()); + taskBuilder.status(new TaskStatus_v0_3(task.getStatus().state(), null, task.getStatus().timestamp())); + } + history.add(message); + taskBuilder.history(history); + currentTask = taskBuilder.build(); + return currentTask; + } + + private void saveTask(Task_v0_3 task) { + currentTask = task; + if (taskId == null) { + taskId = currentTask.getId(); + contextId = currentTask.getContextId(); + } + } +} \ No newline at end of file diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/Client_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/Client_v0_3.java new file mode 100644 index 000000000..d264326d2 --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/Client_v0_3.java @@ -0,0 +1,243 @@ +package org.a2aproject.sdk.compat03.client; + +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import org.a2aproject.sdk.compat03.client.config.ClientConfig_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransport_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientInvalidStateError_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendConfiguration_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; + +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + +public class Client_v0_3 extends AbstractClient_v0_3 { + + private final ClientConfig_v0_3 clientConfig; + private final ClientTransport_v0_3 clientTransport; + private AgentCard_v0_3 agentCard; + + Client_v0_3(AgentCard_v0_3 agentCard, ClientConfig_v0_3 clientConfig, ClientTransport_v0_3 clientTransport, + List> consumers, @Nullable Consumer streamingErrorHandler) { + super(consumers, streamingErrorHandler); + checkNotNullParam("agentCard", agentCard); + + this.agentCard = agentCard; + this.clientConfig = clientConfig; + this.clientTransport = clientTransport; + } + + public static ClientBuilder_v0_3 builder(AgentCard_v0_3 agentCard) { + return new ClientBuilder_v0_3(agentCard); + } + + @Override + public void sendMessage(Message_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + MessageSendParams_v0_3 messageSendParams = getMessageSendParams(request, clientConfig); + sendMessage(messageSendParams, null, null, context); + } + + @Override + public void sendMessage(Message_v0_3 request, List> consumers, + Consumer streamingErrorHandler, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + MessageSendParams_v0_3 messageSendParams = getMessageSendParams(request, clientConfig); + sendMessage(messageSendParams, consumers, streamingErrorHandler, context); + } + + @Override + public void sendMessage(Message_v0_3 request, PushNotificationConfig_v0_3 pushNotificationConfiguration, + Map metatadata, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + MessageSendConfiguration_v0_3 messageSendConfiguration = createMessageSendConfiguration(pushNotificationConfiguration); + + MessageSendParams_v0_3 messageSendParams = new MessageSendParams_v0_3.Builder() + .message(request) + .configuration(messageSendConfiguration) + .metadata(metatadata) + .build(); + + sendMessage(messageSendParams, null, null, context); + } + + @Override + public Task_v0_3 getTask(TaskQueryParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + return clientTransport.getTask(request, context); + } + + @Override + public Task_v0_3 cancelTask(TaskIdParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + return clientTransport.cancelTask(request, context); + } + + @Override + public TaskPushNotificationConfig_v0_3 setTaskPushNotificationConfiguration( + TaskPushNotificationConfig_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + return clientTransport.setTaskPushNotificationConfiguration(request, context); + } + + @Override + public TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration( + GetTaskPushNotificationConfigParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + return clientTransport.getTaskPushNotificationConfiguration(request, context); + } + + @Override + public List listTaskPushNotificationConfigurations( + ListTaskPushNotificationConfigParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + return clientTransport.listTaskPushNotificationConfigurations(request, context); + } + + @Override + public void deleteTaskPushNotificationConfigurations( + DeleteTaskPushNotificationConfigParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + clientTransport.deleteTaskPushNotificationConfigurations(request, context); + } + + @Override + public void resubscribe(TaskIdParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + resubscribeToTask(request, null, null, context); + } + + @Override + public void resubscribe(TaskIdParams_v0_3 request, @Nullable List> consumers, + @Nullable Consumer streamingErrorHandler, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + resubscribeToTask(request, consumers, streamingErrorHandler, context); + } + + @Override + public AgentCard_v0_3 getAgentCard(@Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + agentCard = clientTransport.getAgentCard(context); + return agentCard; + } + + @Override + public void close() { + clientTransport.close(); + } + + private ClientEvent_v0_3 getClientEvent(StreamingEventKind_v0_3 event, ClientTaskManager_v0_3 taskManager) throws A2AClientError_v0_3 { + if (event instanceof Message_v0_3 message) { + return new MessageEvent_v0_3(message); + } else if (event instanceof Task_v0_3 task) { + taskManager.saveTaskEvent(task); + return new TaskEvent_v0_3(taskManager.getCurrentTask()); + } else if (event instanceof TaskStatusUpdateEvent_v0_3 updateEvent) { + taskManager.saveTaskEvent(updateEvent); + return new TaskUpdateEvent_v0_3(taskManager.getCurrentTask(), updateEvent); + } else if (event instanceof TaskArtifactUpdateEvent_v0_3 updateEvent) { + taskManager.saveTaskEvent(updateEvent); + return new TaskUpdateEvent_v0_3(taskManager.getCurrentTask(), updateEvent); + } else { + throw new A2AClientInvalidStateError_v0_3("Invalid client event"); + } + } + + private MessageSendConfiguration_v0_3 createMessageSendConfiguration(@Nullable PushNotificationConfig_v0_3 pushNotificationConfig) { + return new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(clientConfig.getAcceptedOutputModes()) + .blocking(!clientConfig.isPolling()) + .historyLength(clientConfig.getHistoryLength()) + .pushNotificationConfig(pushNotificationConfig) + .build(); + } + + private void sendMessage(MessageSendParams_v0_3 messageSendParams, @Nullable List> consumers, + @Nullable Consumer errorHandler, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + if (! clientConfig.isStreaming() || ! agentCard.capabilities().streaming()) { + EventKind_v0_3 eventKind = clientTransport.sendMessage(messageSendParams, context); + ClientEvent_v0_3 clientEvent; + if (eventKind instanceof Task_v0_3 task) { + clientEvent = new TaskEvent_v0_3(task); + } else { + // must be a message + clientEvent = new MessageEvent_v0_3((Message_v0_3) eventKind); + } + consume(clientEvent, agentCard, consumers); + } else { + ClientTaskManager_v0_3 tracker = new ClientTaskManager_v0_3(); + Consumer overriddenErrorHandler = getOverriddenErrorHandler(errorHandler); + Consumer eventHandler = event -> { + try { + ClientEvent_v0_3 clientEvent = getClientEvent(event, tracker); + consume(clientEvent, agentCard, consumers); + } catch (A2AClientError_v0_3 e) { + overriddenErrorHandler.accept(e); + } + }; + clientTransport.sendMessageStreaming(messageSendParams, eventHandler, overriddenErrorHandler, context); + } + } + + private void resubscribeToTask(TaskIdParams_v0_3 request, @Nullable List> consumers, + @Nullable Consumer errorHandler, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + if (! clientConfig.isStreaming() || ! agentCard.capabilities().streaming()) { + throw new A2AClientException_v0_3("Client and/or server does not support resubscription"); + } + ClientTaskManager_v0_3 tracker = new ClientTaskManager_v0_3(); + Consumer overriddenErrorHandler = getOverriddenErrorHandler(errorHandler); + Consumer eventHandler = event -> { + try { + ClientEvent_v0_3 clientEvent = getClientEvent(event, tracker); + consume(clientEvent, agentCard, consumers); + } catch (A2AClientError_v0_3 e) { + overriddenErrorHandler.accept(e); + } + }; + clientTransport.resubscribe(request, eventHandler, overriddenErrorHandler, context); + } + + private @NonNull Consumer getOverriddenErrorHandler(@Nullable Consumer errorHandler) { + return e -> { + if (errorHandler != null) { + errorHandler.accept(e); + } else { + if (getStreamingErrorHandler() != null) { + getStreamingErrorHandler().accept(e); + } + } + }; + } + + private void consume(ClientEvent_v0_3 clientEvent, AgentCard_v0_3 agentCard, @Nullable List> consumers) { + if (consumers != null) { + // use specified consumers + for (BiConsumer consumer : consumers) { + consumer.accept(clientEvent, agentCard); + } + } else { + // use configured consumers + consume(clientEvent, agentCard); + } + } + + private MessageSendParams_v0_3 getMessageSendParams(Message_v0_3 request, ClientConfig_v0_3 clientConfig) { + MessageSendConfiguration_v0_3 messageSendConfiguration = createMessageSendConfiguration(clientConfig.getPushNotificationConfig()); + + return new MessageSendParams_v0_3.Builder() + .message(request) + .configuration(messageSendConfiguration) + .metadata(clientConfig.getMetadata()) + .build(); + } +} diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/MessageEvent_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/MessageEvent_v0_3.java new file mode 100644 index 000000000..2c321e0da --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/MessageEvent_v0_3.java @@ -0,0 +1,26 @@ +package org.a2aproject.sdk.compat03.client; + +import org.a2aproject.sdk.compat03.spec.Message_v0_3; + +/** + * A message event received by a client. + */ +public final class MessageEvent_v0_3 implements ClientEvent_v0_3 { + + private final Message_v0_3 message; + + /** + * A message event. + * + * @param message the message received + */ + public MessageEvent_v0_3(Message_v0_3 message) { + this.message = message; + } + + public Message_v0_3 getMessage() { + return message; + } +} + + diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/TaskEvent_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/TaskEvent_v0_3.java new file mode 100644 index 000000000..504fe8559 --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/TaskEvent_v0_3.java @@ -0,0 +1,27 @@ +package org.a2aproject.sdk.compat03.client; + +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + +import org.a2aproject.sdk.compat03.spec.Task_v0_3; + +/** + * A task event received by a client. + */ +public final class TaskEvent_v0_3 implements ClientEvent_v0_3 { + + private final Task_v0_3 task; + + /** + * A client task event. + * + * @param task the task received + */ + public TaskEvent_v0_3(Task_v0_3 task) { + checkNotNullParam("task", task); + this.task = task; + } + + public Task_v0_3 getTask() { + return task; + } +} diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/TaskUpdateEvent_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/TaskUpdateEvent_v0_3.java new file mode 100644 index 000000000..9459a2b04 --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/TaskUpdateEvent_v0_3.java @@ -0,0 +1,37 @@ +package org.a2aproject.sdk.compat03.client; + +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.UpdateEvent_v0_3; + +/** + * A task update event received by a client. + */ +public final class TaskUpdateEvent_v0_3 implements ClientEvent_v0_3 { + + private final Task_v0_3 task; + private final UpdateEvent_v0_3 updateEvent; + + /** + * A task update event. + * + * @param task the current task + * @param updateEvent the update event received for the current task + */ + public TaskUpdateEvent_v0_3(Task_v0_3 task, UpdateEvent_v0_3 updateEvent) { + checkNotNullParam("task", task); + checkNotNullParam("updateEvent", updateEvent); + this.task = task; + this.updateEvent = updateEvent; + } + + public Task_v0_3 getTask() { + return task; + } + + public UpdateEvent_v0_3 getUpdateEvent() { + return updateEvent; + } + +} diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/config/ClientConfig_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/config/ClientConfig_v0_3.java new file mode 100644 index 000000000..ca143a45e --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/config/ClientConfig_v0_3.java @@ -0,0 +1,114 @@ +package org.a2aproject.sdk.compat03.client.config; + +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import java.util.ArrayList; +import java.util.HashMap; +import org.jspecify.annotations.Nullable; + +/** + * Configuration for the A2A client factory. + */ +public class ClientConfig_v0_3 { + + private final Boolean streaming; + private final Boolean polling; + private final Boolean useClientPreference; + private final List acceptedOutputModes; + private final @Nullable PushNotificationConfig_v0_3 pushNotificationConfig; + private final @Nullable Integer historyLength; + private final Map metadata; + + private ClientConfig_v0_3(Builder builder) { + this.streaming = builder.streaming == null ? true : builder.streaming; + this.polling = builder.polling == null ? false : builder.polling; + this.useClientPreference = builder.useClientPreference == null ? false : builder.useClientPreference; + this.acceptedOutputModes = builder.acceptedOutputModes; + this.pushNotificationConfig = builder.pushNotificationConfig; + this.historyLength = builder.historyLength; + this.metadata = builder.metadata; + } + + public boolean isStreaming() { + return streaming; + } + + public boolean isPolling() { + return polling; + } + + public boolean isUseClientPreference() { + return useClientPreference; + } + + public List getAcceptedOutputModes() { + return acceptedOutputModes; + } + + public @Nullable PushNotificationConfig_v0_3 getPushNotificationConfig() { + return pushNotificationConfig; + } + + public @Nullable Integer getHistoryLength() { + return historyLength; + } + + public Map getMetadata() { + return metadata; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private @Nullable Boolean streaming; + private @Nullable Boolean polling; + private @Nullable Boolean useClientPreference; + private List acceptedOutputModes = new ArrayList<>(); + private @Nullable PushNotificationConfig_v0_3 pushNotificationConfig; + private @Nullable Integer historyLength; + private Map metadata = new HashMap<>(); + + public Builder setStreaming(@Nullable Boolean streaming) { + this.streaming = streaming; + return this; + } + + public Builder setPolling(@Nullable Boolean polling) { + this.polling = polling; + return this; + } + + public Builder setUseClientPreference(@Nullable Boolean useClientPreference) { + this.useClientPreference = useClientPreference; + return this; + } + + public Builder setAcceptedOutputModes(List acceptedOutputModes) { + this.acceptedOutputModes = new ArrayList<>(acceptedOutputModes); + return this; + } + + public Builder setPushNotificationConfig(PushNotificationConfig_v0_3 pushNotificationConfig) { + this.pushNotificationConfig = pushNotificationConfig; + return this; + } + + public Builder setHistoryLength(Integer historyLength) { + this.historyLength = historyLength; + return this; + } + + public Builder setMetadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public ClientConfig_v0_3 build() { + return new ClientConfig_v0_3(this); + } + } +} \ No newline at end of file diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/config/package-info.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/config/package-info.java new file mode 100644 index 000000000..bfae93f4b --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/config/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client.config; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/package-info.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/package-info.java new file mode 100644 index 000000000..9bd22f637 --- /dev/null +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/client/base/src/main/resources/META-INF/beans.xml b/compat-0.3/client/base/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..e69de29bb diff --git a/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/A2A_v0_3_Test.java b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/A2A_v0_3_Test.java new file mode 100644 index 000000000..1187518eb --- /dev/null +++ b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/A2A_v0_3_Test.java @@ -0,0 +1,147 @@ +package org.a2aproject.sdk.compat03; + +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.junit.jupiter.api.Test; + +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; + +public class A2A_v0_3_Test { + + @Test + public void testToUserMessage() { + String text = "Hello, world!"; + Message_v0_3 message = A2A_v0_3.toUserMessage(text); + + assertEquals(Message_v0_3.Role.USER, message.getRole()); + assertEquals(1, message.getParts().size()); + assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); + assertNotNull(message.getMessageId()); + assertNull(message.getContextId()); + assertNull(message.getTaskId()); + } + + @Test + public void testToUserMessageWithId() { + String text = "Hello, world!"; + String messageId = "test-message-id"; + Message_v0_3 message = A2A_v0_3.toUserMessage(text, messageId); + + assertEquals(Message_v0_3.Role.USER, message.getRole()); + assertEquals(messageId, message.getMessageId()); + } + + @Test + public void testToAgentMessage() { + String text = "Hello, I'm an agent!"; + Message_v0_3 message = A2A_v0_3.toAgentMessage(text); + + assertEquals(Message_v0_3.Role.AGENT, message.getRole()); + assertEquals(1, message.getParts().size()); + assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); + assertNotNull(message.getMessageId()); + } + + @Test + public void testToAgentMessageWithId() { + String text = "Hello, I'm an agent!"; + String messageId = "agent-message-id"; + Message_v0_3 message = A2A_v0_3.toAgentMessage(text, messageId); + + assertEquals(Message_v0_3.Role.AGENT, message.getRole()); + assertEquals(messageId, message.getMessageId()); + } + + @Test + public void testCreateUserTextMessage() { + String text = "User message with context"; + String contextId = "context-123"; + String taskId = "task-456"; + + Message_v0_3 message = A2A_v0_3.createUserTextMessage(text, contextId, taskId); + + assertEquals(Message_v0_3.Role.USER, message.getRole()); + assertEquals(contextId, message.getContextId()); + assertEquals(taskId, message.getTaskId()); + assertEquals(1, message.getParts().size()); + assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); + assertNotNull(message.getMessageId()); + assertNull(message.getMetadata()); + assertNull(message.getReferenceTaskIds()); + } + + @Test + public void testCreateUserTextMessageWithNullParams() { + String text = "Simple user message"; + + Message_v0_3 message = A2A_v0_3.createUserTextMessage(text, null, null); + + assertEquals(Message_v0_3.Role.USER, message.getRole()); + assertNull(message.getContextId()); + assertNull(message.getTaskId()); + assertEquals(1, message.getParts().size()); + assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); + } + + @Test + public void testCreateAgentTextMessage() { + String text = "Agent message with context"; + String contextId = "context-789"; + String taskId = "task-012"; + + Message_v0_3 message = A2A_v0_3.createAgentTextMessage(text, contextId, taskId); + + assertEquals(Message_v0_3.Role.AGENT, message.getRole()); + assertEquals(contextId, message.getContextId()); + assertEquals(taskId, message.getTaskId()); + assertEquals(1, message.getParts().size()); + assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); + assertNotNull(message.getMessageId()); + } + + @Test + public void testCreateAgentPartsMessage() { + List> parts = Arrays.asList( + new TextPart_v0_3("Part 1"), + new TextPart_v0_3("Part 2") + ); + String contextId = "context-parts"; + String taskId = "task-parts"; + + Message_v0_3 message = A2A_v0_3.createAgentPartsMessage(parts, contextId, taskId); + + assertEquals(Message_v0_3.Role.AGENT, message.getRole()); + assertEquals(contextId, message.getContextId()); + assertEquals(taskId, message.getTaskId()); + assertEquals(2, message.getParts().size()); + assertEquals("Part 1", ((TextPart_v0_3) message.getParts().get(0)).getText()); + assertEquals("Part 2", ((TextPart_v0_3) message.getParts().get(1)).getText()); + } + + @Test + public void testCreateAgentPartsMessageWithNullParts() { + try { + A2A_v0_3.createAgentPartsMessage(null, "context", "task"); + org.junit.jupiter.api.Assertions.fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + assertEquals("Parts cannot be null or empty", e.getMessage()); + } + } + + @Test + public void testCreateAgentPartsMessageWithEmptyParts() { + try { + A2A_v0_3.createAgentPartsMessage(Collections.emptyList(), "context", "task"); + org.junit.jupiter.api.Assertions.fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + assertEquals("Parts cannot be null or empty", e.getMessage()); + } + } +} \ No newline at end of file diff --git a/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/AuthenticationAuthorization_v0_3_Test.java b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/AuthenticationAuthorization_v0_3_Test.java new file mode 100644 index 000000000..228a08c09 --- /dev/null +++ b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/AuthenticationAuthorization_v0_3_Test.java @@ -0,0 +1,380 @@ +package org.a2aproject.sdk.compat03.client; + +import org.a2aproject.sdk.compat03.client.config.ClientConfig_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.grpc.A2AServiceGrpc; +import org.a2aproject.sdk.compat03.grpc.SendMessageRequest; +import org.a2aproject.sdk.compat03.grpc.SendMessageResponse; +import org.a2aproject.sdk.compat03.grpc.StreamResponse; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentInterface_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.grpc.ManagedChannel; +import io.grpc.Server; +import io.grpc.Status; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.stub.StreamObserver; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; + +import java.io.IOException; +import java.util.Collections; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +/** + * Tests for handling HTTP 401 (Unauthorized) and 403 (Forbidden) responses + * when the client sends streaming and non-streaming messages. + * + * These tests verify that the client properly fails when the server returns + * authentication or authorization errors. + */ +public class AuthenticationAuthorization_v0_3_Test { + + private static final String AGENT_URL = "http://localhost:4001"; + private static final String AUTHENTICATION_FAILED_MESSAGE = "Authentication failed"; + private static final String AUTHORIZATION_FAILED_MESSAGE = "Authorization failed"; + + private ClientAndServer server; + private Message_v0_3 MESSAGE; + private AgentCard_v0_3 agentCard; + private Server grpcServer; + private ManagedChannel grpcChannel; + private String grpcServerName; + + @BeforeEach + public void setUp() { + server = new ClientAndServer(4001); + MESSAGE = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("test message"))) + .contextId("context-1234") + .messageId("message-1234") + .build(); + + grpcServerName = InProcessServerBuilder.generateName(); + + agentCard = new AgentCard_v0_3.Builder() + .name("Test Agent") + .description("Test agent for auth tests") + .url(AGENT_URL) + .version("1.0.0") + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(true) // Support streaming for all tests + .build()) + .defaultInputModes(Collections.singletonList("text")) + .defaultOutputModes(Collections.singletonList("text")) + .skills(Collections.singletonList(new AgentSkill_v0_3.Builder() + .id("test_skill") + .name("Test skill") + .description("Test skill") + .tags(Collections.singletonList("test")) + .build())) + .protocolVersion("0.3.0") + .additionalInterfaces(java.util.Arrays.asList( + new AgentInterface_v0_3(TransportProtocol_v0_3.JSONRPC.asString(), AGENT_URL), + new AgentInterface_v0_3(TransportProtocol_v0_3.HTTP_JSON.asString(), AGENT_URL), + new AgentInterface_v0_3(TransportProtocol_v0_3.GRPC.asString(), grpcServerName))) + .build(); + } + + @AfterEach + public void tearDown() { + server.stop(); + if (grpcChannel != null) { + grpcChannel.shutdownNow(); + } + if (grpcServer != null) { + grpcServer.shutdownNow(); + } + } + + // ========== JSON-RPC Transport Tests ========== + + @Test + public void testJsonRpcNonStreamingUnauthenticated() throws A2AClientException_v0_3 { + // Mock server to return 401 for non-streaming message + server.when( + request() + .withMethod("POST") + .withPath("/") + ).respond( + response() + .withStatusCode(401) + ); + + Client_v0_3 client = getJSONRPCClientBuilder(false).build(); + + A2AClientException_v0_3 exception = assertThrows(A2AClientException_v0_3.class, () -> { + client.sendMessage(MESSAGE); + }); + + assertTrue(exception.getMessage().contains(AUTHENTICATION_FAILED_MESSAGE)); + } + + @Test + public void testJsonRpcNonStreamingUnauthorized() throws A2AClientException_v0_3 { + // Mock server to return 403 for non-streaming message + server.when( + request() + .withMethod("POST") + .withPath("/") + ).respond( + response() + .withStatusCode(403) + ); + + Client_v0_3 client = getJSONRPCClientBuilder(false).build(); + + A2AClientException_v0_3 exception = assertThrows(A2AClientException_v0_3.class, () -> { + client.sendMessage(MESSAGE); + }); + + assertTrue(exception.getMessage().contains(AUTHORIZATION_FAILED_MESSAGE)); + } + + @Test + public void testJsonRpcStreamingUnauthenticated() throws Exception { + // Mock server to return 401 for streaming message + server.when( + request() + .withMethod("POST") + .withPath("/") + ).respond( + response() + .withStatusCode(401) + ); + + assertStreamingError( + getJSONRPCClientBuilder(true), + AUTHENTICATION_FAILED_MESSAGE); + } + + @Test + public void testJsonRpcStreamingUnauthorized() throws Exception { + // Mock server to return 403 for streaming message + server.when( + request() + .withMethod("POST") + .withPath("/") + ).respond( + response() + .withStatusCode(403) + ); + + assertStreamingError( + getJSONRPCClientBuilder(true), + AUTHORIZATION_FAILED_MESSAGE); + } + + // ========== REST Transport Tests ========== + + @Test + public void testRestNonStreamingUnauthenticated() throws A2AClientException_v0_3 { + // Mock server to return 401 for non-streaming message + server.when( + request() + .withMethod("POST") + .withPath("/v1/message:send") + ).respond( + response() + .withStatusCode(401) + ); + + Client_v0_3 client = getRestClientBuilder(false).build(); + + A2AClientException_v0_3 exception = assertThrows(A2AClientException_v0_3.class, () -> { + client.sendMessage(MESSAGE); + }); + + assertTrue(exception.getMessage().contains(AUTHENTICATION_FAILED_MESSAGE)); + } + + @Test + public void testRestNonStreamingUnauthorized() throws A2AClientException_v0_3 { + // Mock server to return 403 for non-streaming message + server.when( + request() + .withMethod("POST") + .withPath("/v1/message:send") + ).respond( + response() + .withStatusCode(403) + ); + + Client_v0_3 client = getRestClientBuilder(false).build(); + + A2AClientException_v0_3 exception = assertThrows(A2AClientException_v0_3.class, () -> { + client.sendMessage(MESSAGE); + }); + + assertTrue(exception.getMessage().contains(AUTHORIZATION_FAILED_MESSAGE)); + } + + @Test + public void testRestStreamingUnauthenticated() throws Exception { + // Mock server to return 401 for streaming message + server.when( + request() + .withMethod("POST") + .withPath("/v1/message:stream") + ).respond( + response() + .withStatusCode(401) + ); + + assertStreamingError( + getRestClientBuilder(true), + AUTHENTICATION_FAILED_MESSAGE); + } + + @Test + public void testRestStreamingUnauthorized() throws Exception { + // Mock server to return 403 for streaming message + server.when( + request() + .withMethod("POST") + .withPath("/v1/message:stream") + ).respond( + response() + .withStatusCode(403) + ); + + assertStreamingError( + getRestClientBuilder(true), + AUTHORIZATION_FAILED_MESSAGE); + } + + // ========== gRPC Transport Tests ========== + + @Test + public void testGrpcNonStreamingUnauthenticated() throws Exception { + setupGrpcServer(Status.UNAUTHENTICATED); + + Client_v0_3 client = getGrpcClientBuilder(false).build(); + + A2AClientException_v0_3 exception = assertThrows(A2AClientException_v0_3.class, () -> { + client.sendMessage(MESSAGE); + }); + + assertTrue(exception.getMessage().contains(AUTHENTICATION_FAILED_MESSAGE)); + } + + @Test + public void testGrpcNonStreamingUnauthorized() throws Exception { + setupGrpcServer(Status.PERMISSION_DENIED); + + Client_v0_3 client = getGrpcClientBuilder(false).build(); + + A2AClientException_v0_3 exception = assertThrows(A2AClientException_v0_3.class, () -> { + client.sendMessage(MESSAGE); + }); + + assertTrue(exception.getMessage().contains(AUTHORIZATION_FAILED_MESSAGE)); + } + + @Test + public void testGrpcStreamingUnauthenticated() throws Exception { + setupGrpcServer(Status.UNAUTHENTICATED); + + assertStreamingError( + getGrpcClientBuilder(true), + AUTHENTICATION_FAILED_MESSAGE); + } + + @Test + public void testGrpcStreamingUnauthorized() throws Exception { + setupGrpcServer(Status.PERMISSION_DENIED); + + assertStreamingError( + getGrpcClientBuilder(true), + AUTHORIZATION_FAILED_MESSAGE); + } + + private ClientBuilder_v0_3 getJSONRPCClientBuilder(boolean streaming) { + return Client_v0_3.builder(agentCard) + .clientConfig(new ClientConfig_v0_3.Builder().setStreaming(streaming).build()) + .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); + } + + private ClientBuilder_v0_3 getRestClientBuilder(boolean streaming) { + return Client_v0_3.builder(agentCard) + .clientConfig(new ClientConfig_v0_3.Builder().setStreaming(streaming).build()) + .withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); + } + + private ClientBuilder_v0_3 getGrpcClientBuilder(boolean streaming) { + return Client_v0_3.builder(agentCard) + .clientConfig(new ClientConfig_v0_3.Builder().setStreaming(streaming).build()) + .withTransport(GrpcTransport_v0_3.class, new GrpcTransportConfigBuilder_v0_3() + .channelFactory(target -> grpcChannel)); + } + + private void assertStreamingError(ClientBuilder_v0_3 clientBuilder, String expectedErrorMessage) throws Exception { + AtomicReference errorRef = new AtomicReference<>(); + CountDownLatch errorLatch = new CountDownLatch(1); + + Consumer errorHandler = error -> { + errorRef.set(error); + errorLatch.countDown(); + }; + + Client_v0_3 client = clientBuilder.streamingErrorHandler(errorHandler).build(); + + try { + client.sendMessage(MESSAGE); + // If no immediate exception, wait for async error + assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Expected error handler to be called"); + Throwable error = errorRef.get(); + assertTrue(error.getMessage().contains(expectedErrorMessage), + "Expected error message to contain '" + expectedErrorMessage + "' but got: " + error.getMessage()); + } catch (Exception e) { + // Immediate exception is also acceptable + assertTrue(e.getMessage().contains(expectedErrorMessage), + "Expected error message to contain '" + expectedErrorMessage + "' but got: " + e.getMessage()); + } + } + + private void setupGrpcServer(Status status) throws IOException { + grpcServerName = InProcessServerBuilder.generateName(); + grpcServer = InProcessServerBuilder.forName(grpcServerName) + .directExecutor() + .addService(new A2AServiceGrpc.A2AServiceImplBase() { + @Override + public void sendMessage(SendMessageRequest request, StreamObserver responseObserver) { + responseObserver.onError(status.asRuntimeException()); + } + + @Override + public void sendStreamingMessage(SendMessageRequest request, StreamObserver responseObserver) { + responseObserver.onError(status.asRuntimeException()); + } + }) + .build() + .start(); + + grpcChannel = InProcessChannelBuilder.forName(grpcServerName) + .directExecutor() + .build(); + } +} \ No newline at end of file diff --git a/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3_Test.java b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3_Test.java new file mode 100644 index 000000000..4b4e31d0b --- /dev/null +++ b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3_Test.java @@ -0,0 +1,96 @@ +package org.a2aproject.sdk.compat03.client; + +import org.a2aproject.sdk.compat03.client.config.ClientConfig_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfig_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentInterface_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; + +public class ClientBuilder_v0_3_Test { + + private AgentCard_v0_3 card = new AgentCard_v0_3.Builder() + .name("Hello World Agent") + .description("Just a hello world agent") + .url("http://localhost:9999") + .version("1.0.0") + .documentationUrl("http://example.com/docs") + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(true) + .pushNotifications(true) + .stateTransitionHistory(true) + .build()) + .defaultInputModes(Collections.singletonList("text")) + .defaultOutputModes(Collections.singletonList("text")) + .skills(Collections.singletonList(new AgentSkill_v0_3.Builder() + .id("hello_world") + .name("Returns hello world") + .description("just returns hello world") + .tags(Collections.singletonList("hello world")) + .examples(List.of("hi", "hello world")) + .build())) + .protocolVersion("0.3.0") + .additionalInterfaces(List.of( + new AgentInterface_v0_3(TransportProtocol_v0_3.JSONRPC.asString(), "http://localhost:9999"))) + .build(); + + @Test + public void shouldNotFindCompatibleTransport() throws A2AClientException_v0_3 { + A2AClientException_v0_3 exception = Assertions.assertThrows(A2AClientException_v0_3.class, + () -> Client_v0_3 + .builder(card) + .clientConfig(new ClientConfig_v0_3.Builder().setUseClientPreference(true).build()) + .withTransport(GrpcTransport_v0_3.class, new GrpcTransportConfigBuilder_v0_3() + .channelFactory(s -> null)) + .build()); + + Assertions.assertTrue(exception.getMessage() != null && exception.getMessage().contains("No compatible transport found")); + } + + @Test + public void shouldNotFindConfigurationTransport() throws A2AClientException_v0_3 { + A2AClientException_v0_3 exception = Assertions.assertThrows(A2AClientException_v0_3.class, + () -> Client_v0_3 + .builder(card) + .clientConfig(new ClientConfig_v0_3.Builder().setUseClientPreference(true).build()) + .build()); + + Assertions.assertTrue(exception.getMessage() != null && exception.getMessage().startsWith("Missing required TransportConfig for")); + } + + @Test + public void shouldCreateJSONRPCClient() throws A2AClientException_v0_3 { + Client_v0_3 client = Client_v0_3 + .builder(card) + .clientConfig(new ClientConfig_v0_3.Builder().setUseClientPreference(true).build()) + .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3() + .addInterceptor(null) + .httpClient(null)) + .build(); + + Assertions.assertNotNull(client); + } + + @Test + public void shouldCreateClient_differentConfigurations() throws A2AClientException_v0_3 { + Client_v0_3 client = Client_v0_3 + .builder(card) + .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()) + .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfig_v0_3(new JdkA2AHttpClient_v0_3())) + .build(); + + Assertions.assertNotNull(client); + } +} diff --git a/compat-0.3/client/transport/grpc/pom.xml b/compat-0.3/client/transport/grpc/pom.xml new file mode 100644 index 000000000..97c24e11a --- /dev/null +++ b/compat-0.3/client/transport/grpc/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../../.. + + a2a-java-sdk-compat-0.3-client-transport-grpc + jar + + Java SDK A2A Compat 0.3 Client Transport: gRPC + Java SDK for the Agent2Agent Protocol (A2A) - gRPC Client Transport + + + + ${project.groupId} + a2a-java-sdk-common + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec-grpc + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-spi + + + io.grpc + grpc-protobuf + + + io.grpc + grpc-stub + + + org.junit.jupiter + junit-jupiter-api + test + + + + org.mock-server + mockserver-netty + test + + + + \ No newline at end of file diff --git a/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/EventStreamObserver_v0_3.java b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/EventStreamObserver_v0_3.java new file mode 100644 index 000000000..4f353748c --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/EventStreamObserver_v0_3.java @@ -0,0 +1,64 @@ +package org.a2aproject.sdk.compat03.client.transport.grpc; + + +import org.a2aproject.sdk.compat03.grpc.StreamResponse; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import io.grpc.stub.StreamObserver; + +import java.util.function.Consumer; +import java.util.logging.Logger; + +import static org.a2aproject.sdk.compat03.grpc.utils.ProtoUtils_v0_3.FromProto; + +public class EventStreamObserver_v0_3 implements StreamObserver { + + private static final Logger log = Logger.getLogger(EventStreamObserver_v0_3.class.getName()); + private final Consumer eventHandler; + private final Consumer errorHandler; + + public EventStreamObserver_v0_3(Consumer eventHandler, Consumer errorHandler) { + this.eventHandler = eventHandler; + this.errorHandler = errorHandler; + } + + @Override + public void onNext(StreamResponse response) { + StreamingEventKind_v0_3 event; + switch (response.getPayloadCase()) { + case MSG: + event = FromProto.message(response.getMsg()); + break; + case TASK: + event = FromProto.task(response.getTask()); + break; + case STATUS_UPDATE: + event = FromProto.taskStatusUpdateEvent(response.getStatusUpdate()); + break; + case ARTIFACT_UPDATE: + event = FromProto.taskArtifactUpdateEvent(response.getArtifactUpdate()); + break; + default: + log.warning("Invalid stream response " + response.getPayloadCase()); + errorHandler.accept(new IllegalStateException("Invalid stream response from server: " + response.getPayloadCase())); + return; + } + eventHandler.accept(event); + } + + @Override + public void onError(Throwable t) { + if (errorHandler != null) { + // Map gRPC errors to proper A2A exceptions + if (t instanceof io.grpc.StatusRuntimeException) { + errorHandler.accept(GrpcErrorMapper_v0_3.mapGrpcError((io.grpc.StatusRuntimeException) t)); + } else { + errorHandler.accept(t); + } + } + } + + @Override + public void onCompleted() { + // done + } +} diff --git a/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcErrorMapper_v0_3.java b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcErrorMapper_v0_3.java new file mode 100644 index 000000000..a66bbf610 --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcErrorMapper_v0_3.java @@ -0,0 +1,102 @@ +package org.a2aproject.sdk.compat03.client.transport.grpc; + +import org.a2aproject.sdk.common.A2AErrorMessages; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +import io.grpc.Status; +import io.grpc.StatusException; +import io.grpc.StatusRuntimeException; + +/** + * Utility class to map gRPC StatusRuntimeException to appropriate A2A error types + */ +public class GrpcErrorMapper_v0_3 { + + // Overload for StatusRuntimeException (original 0.3.x signature) + public static A2AClientException_v0_3 mapGrpcError(StatusRuntimeException e) { + return mapGrpcError(e, "gRPC error: "); + } + + public static A2AClientException_v0_3 mapGrpcError(StatusRuntimeException e, String errorPrefix) { + return mapGrpcErrorInternal(e.getStatus().getCode(), e.getStatus().getDescription(), e, errorPrefix); + } + + // Overload for StatusException (gRPC 1.77+ compatibility) + public static A2AClientException_v0_3 mapGrpcError(StatusException e) { + return mapGrpcError(e, "gRPC error: "); + } + + public static A2AClientException_v0_3 mapGrpcError(StatusException e, String errorPrefix) { + return mapGrpcErrorInternal(e.getStatus().getCode(), e.getStatus().getDescription(), e, errorPrefix); + } + + // Dispatcher for multi-catch (StatusRuntimeException | StatusException) + public static A2AClientException_v0_3 mapGrpcError(Exception e, String errorPrefix) { + if (e instanceof StatusRuntimeException) { + return mapGrpcError((StatusRuntimeException) e, errorPrefix); + } else if (e instanceof StatusException) { + return mapGrpcError((StatusException) e, errorPrefix); + } else { + return new A2AClientException_v0_3(errorPrefix + e.getMessage(), e); + } + } + + private static A2AClientException_v0_3 mapGrpcErrorInternal(Status.Code code, @org.jspecify.annotations.Nullable String description, @org.jspecify.annotations.Nullable Throwable cause, String errorPrefix) { + + // Extract the actual error type from the description if possible + // (using description because the same code can map to multiple errors - + // see GrpcHandler#handleError) + if (description != null) { + if (description.contains("TaskNotFoundError")) { + return new A2AClientException_v0_3(errorPrefix + description, new TaskNotFoundError_v0_3()); + } else if (description.contains("UnsupportedOperationError")) { + return new A2AClientException_v0_3(errorPrefix + description, new UnsupportedOperationError_v0_3()); + } else if (description.contains("InvalidParamsError")) { + return new A2AClientException_v0_3(errorPrefix + description, new InvalidParamsError_v0_3()); + } else if (description.contains("InvalidRequestError")) { + return new A2AClientException_v0_3(errorPrefix + description, new InvalidRequestError_v0_3()); + } else if (description.contains("MethodNotFoundError")) { + return new A2AClientException_v0_3(errorPrefix + description, new MethodNotFoundError_v0_3()); + } else if (description.contains("TaskNotCancelableError")) { + return new A2AClientException_v0_3(errorPrefix + description, new TaskNotCancelableError_v0_3()); + } else if (description.contains("PushNotificationNotSupportedError")) { + return new A2AClientException_v0_3(errorPrefix + description, new PushNotificationNotSupportedError_v0_3()); + } else if (description.contains("JSONParseError")) { + return new A2AClientException_v0_3(errorPrefix + description, new JSONParseError_v0_3()); + } else if (description.contains("ContentTypeNotSupportedError")) { + return new A2AClientException_v0_3(errorPrefix + description, new ContentTypeNotSupportedError_v0_3(null, description, null)); + } else if (description.contains("InvalidAgentResponseError")) { + return new A2AClientException_v0_3(errorPrefix + description, new InvalidAgentResponseError_v0_3(null, description, null)); + } + } + + // Fall back to mapping based on status code + String message = description != null ? description : (cause != null ? cause.getMessage() : "Unknown error"); + switch (code) { + case NOT_FOUND: + return new A2AClientException_v0_3(errorPrefix + message, new TaskNotFoundError_v0_3()); + case UNIMPLEMENTED: + return new A2AClientException_v0_3(errorPrefix + message, new UnsupportedOperationError_v0_3()); + case INVALID_ARGUMENT: + return new A2AClientException_v0_3(errorPrefix + message, new InvalidParamsError_v0_3()); + case INTERNAL: + return new A2AClientException_v0_3(errorPrefix + message, new InternalError_v0_3(null, message, null)); + case UNAUTHENTICATED: + return new A2AClientException_v0_3(errorPrefix + A2AErrorMessages.AUTHENTICATION_FAILED); + case PERMISSION_DENIED: + return new A2AClientException_v0_3(errorPrefix + A2AErrorMessages.AUTHORIZATION_FAILED); + default: + return new A2AClientException_v0_3(errorPrefix + message, cause); + } + } +} diff --git a/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportConfigBuilder_v0_3.java b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportConfigBuilder_v0_3.java new file mode 100644 index 000000000..cfc3b97c6 --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportConfigBuilder_v0_3.java @@ -0,0 +1,32 @@ +package org.a2aproject.sdk.compat03.client.transport.grpc; + +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.util.Assert; +import io.grpc.Channel; + +import java.util.function.Function; + +import org.jspecify.annotations.Nullable; + +public class GrpcTransportConfigBuilder_v0_3 extends ClientTransportConfigBuilder_v0_3 { + + private @Nullable Function channelFactory; + + public GrpcTransportConfigBuilder_v0_3 channelFactory(Function channelFactory) { + Assert.checkNotNullParam("channelFactory", channelFactory); + + this.channelFactory = channelFactory; + + return this; + } + + @Override + public GrpcTransportConfig_v0_3 build() { + if (channelFactory == null) { + throw new IllegalStateException("channelFactory must be set"); + } + GrpcTransportConfig_v0_3 config = new GrpcTransportConfig_v0_3(channelFactory); + config.setInterceptors(interceptors); + return config; + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportConfig_v0_3.java b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportConfig_v0_3.java new file mode 100644 index 000000000..34122cc53 --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportConfig_v0_3.java @@ -0,0 +1,21 @@ +package org.a2aproject.sdk.compat03.client.transport.grpc; + +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfig_v0_3; +import org.a2aproject.sdk.util.Assert; +import io.grpc.Channel; + +import java.util.function.Function; + +public class GrpcTransportConfig_v0_3 extends ClientTransportConfig_v0_3 { + + private final Function channelFactory; + + public GrpcTransportConfig_v0_3(Function channelFactory) { + Assert.checkNotNullParam("channelFactory", channelFactory); + this.channelFactory = channelFactory; + } + + public Function getChannelFactory() { + return this.channelFactory; + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportProvider_v0_3.java b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportProvider_v0_3.java new file mode 100644 index 000000000..1faac044a --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransportProvider_v0_3.java @@ -0,0 +1,35 @@ +package org.a2aproject.sdk.compat03.client.transport.grpc; + +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.grpc.Channel; + +/** + * Provider for gRPC transport implementation. + */ +public class GrpcTransportProvider_v0_3 implements ClientTransportProvider_v0_3 { + + @Override + public GrpcTransport_v0_3 create(GrpcTransportConfig_v0_3 grpcTransportConfig, AgentCard_v0_3 agentCard, String agentUrl) throws A2AClientException_v0_3 { + // not making use of the interceptors for gRPC for now + + Channel channel = grpcTransportConfig.getChannelFactory().apply(agentUrl); + if (channel != null) { + return new GrpcTransport_v0_3(channel, agentCard, grpcTransportConfig.getInterceptors()); + } + + throw new A2AClientException_v0_3("Missing required GrpcTransportConfig"); + } + + @Override + public String getTransportProtocol() { + return TransportProtocol_v0_3.GRPC.asString(); + } + + @Override + public Class getTransportProtocolClass() { + return GrpcTransport_v0_3.class; + } +} diff --git a/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransport_v0_3.java b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransport_v0_3.java new file mode 100644 index 000000000..50f73e641 --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcTransport_v0_3.java @@ -0,0 +1,389 @@ +package org.a2aproject.sdk.compat03.client.transport.grpc; + +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallInterceptor_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.PayloadAndHeaders_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.grpc.A2AServiceGrpc; +import org.a2aproject.sdk.compat03.grpc.A2AServiceGrpc.A2AServiceBlockingV2Stub; +import org.a2aproject.sdk.compat03.grpc.A2AServiceGrpc.A2AServiceStub; +import org.a2aproject.sdk.compat03.grpc.CancelTaskRequest; +import org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.compat03.grpc.GetTaskRequest; +import org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.compat03.grpc.SendMessageRequest; +import org.a2aproject.sdk.compat03.grpc.SendMessageResponse; +import org.a2aproject.sdk.compat03.grpc.StreamResponse; +import org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest; +import org.a2aproject.sdk.compat03.grpc.utils.ProtoUtils_v0_3.FromProto; +import org.a2aproject.sdk.compat03.grpc.utils.ProtoUtils_v0_3.ToProto; +import io.grpc.StatusException; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskResubscriptionRequest_v0_3; +import io.grpc.Channel; +import io.grpc.Metadata; +import io.grpc.StatusRuntimeException; +import io.grpc.stub.MetadataUtils; +import io.grpc.stub.StreamObserver; +import org.jspecify.annotations.Nullable; + +public class GrpcTransport_v0_3 implements ClientTransport_v0_3 { + + private static final Metadata.Key AUTHORIZATION_METADATA_KEY = Metadata.Key.of( + AuthInterceptor_v0_3.AUTHORIZATION, + Metadata.ASCII_STRING_MARSHALLER); + private static final Metadata.Key EXTENSIONS_KEY = Metadata.Key.of( + "X-A2A-Extensions", + Metadata.ASCII_STRING_MARSHALLER); + private final A2AServiceBlockingV2Stub blockingStub; + private final A2AServiceStub asyncStub; + private final @Nullable List interceptors; + private AgentCard_v0_3 agentCard; + + public GrpcTransport_v0_3(Channel channel, AgentCard_v0_3 agentCard) { + this(channel, agentCard, null); + } + + public GrpcTransport_v0_3(Channel channel, AgentCard_v0_3 agentCard, @Nullable List interceptors) { + checkNotNullParam("channel", channel); + checkNotNullParam("agentCard", agentCard); + this.asyncStub = A2AServiceGrpc.newStub(channel); + this.blockingStub = A2AServiceGrpc.newBlockingV2Stub(channel); + this.agentCard = agentCard; + this.interceptors = interceptors; + } + + @Override + public EventKind_v0_3 sendMessage(MessageSendParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + + SendMessageRequest sendMessageRequest = createGrpcSendMessageRequest(request, context); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SendMessageRequest_v0_3.METHOD, sendMessageRequest, + agentCard, context); + + try { + A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); + SendMessageResponse response = stubWithMetadata.sendMessage(sendMessageRequest); + if (response.hasMsg()) { + return FromProto.message(response.getMsg()); + } else if (response.hasTask()) { + return FromProto.task(response.getTask()); + } else { + throw new A2AClientException_v0_3("Server response did not contain a message or task"); + } + } catch (StatusRuntimeException | StatusException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to send message: "); + } + } + + @Override + public void sendMessageStreaming(MessageSendParams_v0_3 request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + checkNotNullParam("eventConsumer", eventConsumer); + SendMessageRequest grpcRequest = createGrpcSendMessageRequest(request, context); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SendStreamingMessageRequest_v0_3.METHOD, + grpcRequest, agentCard, context); + StreamObserver streamObserver = new EventStreamObserver_v0_3(eventConsumer, errorConsumer); + + try { + A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders); + stubWithMetadata.sendStreamingMessage(grpcRequest, streamObserver); + } catch (StatusRuntimeException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to send streaming message request: "); + } + } + + @Override + public Task_v0_3 getTask(TaskQueryParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + + GetTaskRequest.Builder requestBuilder = GetTaskRequest.newBuilder(); + requestBuilder.setName("tasks/" + request.id()); + requestBuilder.setHistoryLength(request.historyLength()); + GetTaskRequest getTaskRequest = requestBuilder.build(); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetTaskRequest_v0_3.METHOD, getTaskRequest, + agentCard, context); + + try { + A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); + return FromProto.task(stubWithMetadata.getTask(getTaskRequest)); + } catch (StatusRuntimeException | StatusException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to get task: "); + } + } + + @Override + public Task_v0_3 cancelTask(TaskIdParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + + CancelTaskRequest cancelTaskRequest = CancelTaskRequest.newBuilder() + .setName("tasks/" + request.id()) + .build(); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(CancelTaskRequest_v0_3.METHOD, cancelTaskRequest, + agentCard, context); + + try { + A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); + return FromProto.task(stubWithMetadata.cancelTask(cancelTaskRequest)); + } catch (StatusRuntimeException | StatusException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to cancel task: "); + } + } + + @Override + public TaskPushNotificationConfig_v0_3 setTaskPushNotificationConfiguration(TaskPushNotificationConfig_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + + String configId = request.pushNotificationConfig().id(); + CreateTaskPushNotificationConfigRequest grpcRequest = CreateTaskPushNotificationConfigRequest.newBuilder() + .setParent("tasks/" + request.taskId()) + .setConfig(ToProto.taskPushNotificationConfig(request)) + .setConfigId(configId != null ? configId : request.taskId()) + .build(); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SetTaskPushNotificationConfigRequest_v0_3.METHOD, + grpcRequest, agentCard, context); + + try { + A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); + return FromProto.taskPushNotificationConfig(stubWithMetadata.createTaskPushNotificationConfig(grpcRequest)); + } catch (StatusRuntimeException | StatusException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to create task push notification config: "); + } + } + + @Override + public TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration( + GetTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + + GetTaskPushNotificationConfigRequest grpcRequest = GetTaskPushNotificationConfigRequest.newBuilder() + .setName(getTaskPushNotificationConfigName(request)) + .build(); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetTaskPushNotificationConfigRequest_v0_3.METHOD, + grpcRequest, agentCard, context); + + try { + A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); + return FromProto.taskPushNotificationConfig(stubWithMetadata.getTaskPushNotificationConfig(grpcRequest)); + } catch (StatusRuntimeException | StatusException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to get task push notification config: "); + } + } + + @Override + public List listTaskPushNotificationConfigurations( + ListTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + + ListTaskPushNotificationConfigRequest grpcRequest = ListTaskPushNotificationConfigRequest.newBuilder() + .setParent("tasks/" + request.id()) + .build(); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(ListTaskPushNotificationConfigRequest_v0_3.METHOD, + grpcRequest, agentCard, context); + + try { + A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); + return stubWithMetadata.listTaskPushNotificationConfig(grpcRequest).getConfigsList().stream() + .map(FromProto::taskPushNotificationConfig) + .collect(Collectors.toList()); + } catch (StatusRuntimeException | StatusException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to list task push notification config: "); + } + } + + @Override + public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + + DeleteTaskPushNotificationConfigRequest grpcRequest = DeleteTaskPushNotificationConfigRequest.newBuilder() + .setName(getTaskPushNotificationConfigName(request.id(), request.pushNotificationConfigId())) + .build(); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(DeleteTaskPushNotificationConfigRequest_v0_3.METHOD, + grpcRequest, agentCard, context); + + try { + A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); + stubWithMetadata.deleteTaskPushNotificationConfig(grpcRequest); + } catch (StatusRuntimeException | StatusException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to delete task push notification config: "); + } + } + + @Override + public void resubscribe(TaskIdParams_v0_3 request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + checkNotNullParam("eventConsumer", eventConsumer); + + TaskSubscriptionRequest grpcRequest = TaskSubscriptionRequest.newBuilder() + .setName("tasks/" + request.id()) + .build(); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(TaskResubscriptionRequest_v0_3.METHOD, + grpcRequest, agentCard, context); + + StreamObserver streamObserver = new EventStreamObserver_v0_3(eventConsumer, errorConsumer); + + try { + A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders); + stubWithMetadata.taskSubscription(grpcRequest, streamObserver); + } catch (StatusRuntimeException e) { + throw GrpcErrorMapper_v0_3.mapGrpcError(e, "Failed to resubscribe task push notification config: "); + } + } + + @Override + public AgentCard_v0_3 getAgentCard(@Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + // TODO: Determine how to handle retrieving the authenticated extended agent card + return agentCard; + } + + @Override + public void close() { + } + + private SendMessageRequest createGrpcSendMessageRequest(MessageSendParams_v0_3 messageSendParams, @Nullable ClientCallContext_v0_3 context) { + SendMessageRequest.Builder builder = SendMessageRequest.newBuilder(); + builder.setRequest(ToProto.message(messageSendParams.message())); + if (messageSendParams.configuration() != null) { + builder.setConfiguration(ToProto.messageSendConfiguration(messageSendParams.configuration())); + } + if (messageSendParams.metadata() != null) { + builder.setMetadata(ToProto.struct(messageSendParams.metadata())); + } + return builder.build(); + } + + /** + * Creates gRPC metadata from ClientCallContext headers. + * Extracts headers like X-A2A-Extensions and sets them as gRPC metadata. + * @param context the client call context containing headers, may be null + * @param payloadAndHeaders the payload and headers wrapper, may be null + * @return the gRPC metadata + */ + private Metadata createGrpcMetadata(@Nullable ClientCallContext_v0_3 context, @Nullable PayloadAndHeaders_v0_3 payloadAndHeaders) { + Metadata metadata = new Metadata(); + + if (context != null && context.getHeaders() != null) { + // Set X-A2A-Extensions header if present + String extensionsHeader = context.getHeaders().get("X-A2A-Extensions"); + if (extensionsHeader != null) { + metadata.put(EXTENSIONS_KEY, extensionsHeader); + } + + // Add other headers as needed in the future + // For now, we only handle X-A2A-Extensions + } + if (payloadAndHeaders != null && payloadAndHeaders.getHeaders() != null) { + // Handle all headers from interceptors (including auth headers) + for (Map.Entry headerEntry : payloadAndHeaders.getHeaders().entrySet()) { + String headerName = headerEntry.getKey(); + String headerValue = headerEntry.getValue(); + + if (headerValue != null) { + // Use static key for common Authorization header, create dynamic keys for others + if (AuthInterceptor_v0_3.AUTHORIZATION.equals(headerName)) { + metadata.put(AUTHORIZATION_METADATA_KEY, headerValue); + } else { + // Create a metadata key dynamically for API keys and other custom headers + Metadata.Key metadataKey = Metadata.Key.of(headerName, Metadata.ASCII_STRING_MARSHALLER); + metadata.put(metadataKey, headerValue); + } + } + } + } + + return metadata; + } + + /** + * Creates a blocking stub with metadata attached from the ClientCallContext. + * + * @param context the client call context + * @param payloadAndHeaders the payloadAndHeaders after applying any interceptors + * @return blocking stub with metadata interceptor + */ + private A2AServiceBlockingV2Stub createBlockingStubWithMetadata(@Nullable ClientCallContext_v0_3 context, + PayloadAndHeaders_v0_3 payloadAndHeaders) { + Metadata metadata = createGrpcMetadata(context, payloadAndHeaders); + return blockingStub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(metadata)); + } + + /** + * Creates an async stub with metadata attached from the ClientCallContext. + * + * @param context the client call context + * @param payloadAndHeaders the payloadAndHeaders after applying any interceptors + * @return async stub with metadata interceptor + */ + private A2AServiceStub createAsyncStubWithMetadata(@Nullable ClientCallContext_v0_3 context, + PayloadAndHeaders_v0_3 payloadAndHeaders) { + Metadata metadata = createGrpcMetadata(context, payloadAndHeaders); + return asyncStub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(metadata)); + } + + private String getTaskPushNotificationConfigName(GetTaskPushNotificationConfigParams_v0_3 params) { + return getTaskPushNotificationConfigName(params.id(), params.pushNotificationConfigId()); + } + + private String getTaskPushNotificationConfigName(String taskId, @Nullable String pushNotificationConfigId) { + StringBuilder name = new StringBuilder(); + name.append("tasks/"); + name.append(taskId); + if (pushNotificationConfigId != null) { + name.append("/pushNotificationConfigs/"); + name.append(pushNotificationConfigId); + } + //name.append("/pushNotificationConfigs/"); + // Use taskId as default config ID if none provided + //name.append(pushNotificationConfigId != null ? pushNotificationConfigId : taskId); + return name.toString(); + } + + private PayloadAndHeaders_v0_3 applyInterceptors(String methodName, Object payload, + AgentCard_v0_3 agentCard, @Nullable ClientCallContext_v0_3 clientCallContext) { + PayloadAndHeaders_v0_3 payloadAndHeaders = new PayloadAndHeaders_v0_3(payload, + clientCallContext != null ? clientCallContext.getHeaders() : null); + if (interceptors != null && ! interceptors.isEmpty()) { + for (ClientCallInterceptor_v0_3 interceptor : interceptors) { + payloadAndHeaders = interceptor.intercept(methodName, payloadAndHeaders.getPayload(), + payloadAndHeaders.getHeaders(), agentCard, clientCallContext); + } + } + return payloadAndHeaders; + } + +} \ No newline at end of file diff --git a/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/package-info.java b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/package-info.java new file mode 100644 index 000000000..71bb5c883 --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/grpc/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client.transport.grpc; + +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/compat-0.3/client/transport/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 b/compat-0.3/client/transport/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 new file mode 100644 index 000000000..613914e98 --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 @@ -0,0 +1 @@ +org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportProvider_v0_3 \ No newline at end of file diff --git a/compat-0.3/client/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcErrorMapper_v0_3_Test.java b/compat-0.3/client/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcErrorMapper_v0_3_Test.java new file mode 100644 index 000000000..b2e402f03 --- /dev/null +++ b/compat-0.3/client/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/grpc/GrpcErrorMapper_v0_3_Test.java @@ -0,0 +1,293 @@ +package org.a2aproject.sdk.compat03.client.transport.grpc; + +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 org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import org.junit.jupiter.api.Test; + +/** + * Tests for GrpcErrorMapper - verifies correct mapping of gRPC StatusRuntimeException + * to v0.3 A2A error types based on description string matching and status codes. + */ +public class GrpcErrorMapper_v0_3_Test { + + @Test + public void testTaskNotFoundErrorByDescription() { + String errorMessage = "TaskNotFoundError: Task task-123 not found"; + StatusRuntimeException grpcException = Status.NOT_FOUND + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(TaskNotFoundError_v0_3.class, result.getCause()); + assertTrue(result.getMessage().contains(errorMessage)); + } + + @Test + public void testTaskNotFoundErrorByStatusCode() { + // Test fallback to status code mapping when description doesn't contain error type + StatusRuntimeException grpcException = Status.NOT_FOUND + .withDescription("Generic not found error") + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(TaskNotFoundError_v0_3.class, result.getCause()); + } + + @Test + public void testUnsupportedOperationErrorByDescription() { + String errorMessage = "UnsupportedOperationError: Operation not supported"; + StatusRuntimeException grpcException = Status.UNIMPLEMENTED + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(UnsupportedOperationError_v0_3.class, result.getCause()); + } + + @Test + public void testUnsupportedOperationErrorByStatusCode() { + StatusRuntimeException grpcException = Status.UNIMPLEMENTED + .withDescription("Generic unimplemented error") + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(UnsupportedOperationError_v0_3.class, result.getCause()); + } + + @Test + public void testInvalidParamsErrorByDescription() { + String errorMessage = "InvalidParamsError: Invalid parameters provided"; + StatusRuntimeException grpcException = Status.INVALID_ARGUMENT + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(InvalidParamsError_v0_3.class, result.getCause()); + } + + @Test + public void testInvalidParamsErrorByStatusCode() { + StatusRuntimeException grpcException = Status.INVALID_ARGUMENT + .withDescription("Generic invalid argument") + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(InvalidParamsError_v0_3.class, result.getCause()); + } + + @Test + public void testInvalidRequestError() { + String errorMessage = "InvalidRequestError: Request is malformed"; + StatusRuntimeException grpcException = Status.INVALID_ARGUMENT + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(InvalidRequestError_v0_3.class, result.getCause()); + } + + @Test + public void testMethodNotFoundError() { + String errorMessage = "MethodNotFoundError: Method does not exist"; + StatusRuntimeException grpcException = Status.NOT_FOUND + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(MethodNotFoundError_v0_3.class, result.getCause()); + } + + @Test + public void testTaskNotCancelableError() { + String errorMessage = "TaskNotCancelableError: Task cannot be cancelled"; + StatusRuntimeException grpcException = Status.UNIMPLEMENTED + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(TaskNotCancelableError_v0_3.class, result.getCause()); + } + + @Test + public void testPushNotificationNotSupportedError() { + String errorMessage = "PushNotificationNotSupportedError: Push notifications not supported"; + StatusRuntimeException grpcException = Status.UNIMPLEMENTED + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(PushNotificationNotSupportedError_v0_3.class, result.getCause()); + } + + @Test + public void testJSONParseError() { + String errorMessage = "JSONParseError: Failed to parse JSON"; + StatusRuntimeException grpcException = Status.INTERNAL + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(JSONParseError_v0_3.class, result.getCause()); + } + + @Test + public void testContentTypeNotSupportedError() { + String errorMessage = "ContentTypeNotSupportedError: Content type application/xml not supported"; + StatusRuntimeException grpcException = Status.INVALID_ARGUMENT + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(ContentTypeNotSupportedError_v0_3.class, result.getCause()); + + ContentTypeNotSupportedError_v0_3 contentTypeError = (ContentTypeNotSupportedError_v0_3) result.getCause(); + assertNotNull(contentTypeError.getMessage()); + assertTrue(contentTypeError.getMessage().contains("Content type application/xml not supported")); + } + + @Test + public void testInvalidAgentResponseError() { + String errorMessage = "InvalidAgentResponseError: Agent response is invalid"; + StatusRuntimeException grpcException = Status.INTERNAL + .withDescription(errorMessage) + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(InvalidAgentResponseError_v0_3.class, result.getCause()); + + InvalidAgentResponseError_v0_3 agentResponseError = (InvalidAgentResponseError_v0_3) result.getCause(); + assertNotNull(agentResponseError.getMessage()); + assertTrue(agentResponseError.getMessage().contains("Agent response is invalid")); + } + + @Test + public void testInternalErrorByStatusCode() { + StatusRuntimeException grpcException = Status.INTERNAL + .withDescription("Internal server error") + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(InternalError_v0_3.class, result.getCause()); + } + + @Test + public void testCustomErrorPrefix() { + String errorMessage = "TaskNotFoundError: Task not found"; + StatusRuntimeException grpcException = Status.NOT_FOUND + .withDescription(errorMessage) + .asRuntimeException(); + + String customPrefix = "Custom Error: "; + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException, customPrefix); + + assertNotNull(result); + assertTrue(result.getMessage().startsWith(customPrefix)); + assertInstanceOf(TaskNotFoundError_v0_3.class, result.getCause()); + } + + @Test + public void testAuthenticationFailed() { + StatusRuntimeException grpcException = Status.UNAUTHENTICATED + .withDescription("Authentication failed") + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertTrue(result.getMessage().contains("Authentication failed")); + } + + @Test + public void testAuthorizationFailed() { + StatusRuntimeException grpcException = Status.PERMISSION_DENIED + .withDescription("Permission denied") + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertTrue(result.getMessage().contains("Authorization failed")); + } + + @Test + public void testUnknownStatusCode() { + StatusRuntimeException grpcException = Status.DEADLINE_EXCEEDED + .withDescription("Request timeout") + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertTrue(result.getMessage().contains("Request timeout")); + } + + @Test + public void testNullDescription() { + StatusRuntimeException grpcException = Status.NOT_FOUND + .asRuntimeException(); + + A2AClientException_v0_3 result = GrpcErrorMapper_v0_3.mapGrpcError(grpcException); + + assertNotNull(result); + assertNotNull(result.getCause()); + assertInstanceOf(TaskNotFoundError_v0_3.class, result.getCause()); + } +} diff --git a/compat-0.3/client/transport/jsonrpc/pom.xml b/compat-0.3/client/transport/jsonrpc/pom.xml new file mode 100644 index 000000000..fd099d2d0 --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../../.. + + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + jar + + Java SDK A2A Compat 0.3 Client Transport: JSONRPC + Java SDK for the Agent2Agent Protocol (A2A) - JSONRPC Client Transport + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-http-client + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-spi + + + ${project.groupId} + a2a-java-sdk-common + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + org.junit.jupiter + junit-jupiter-api + test + + + + org.mock-server + mockserver-netty + test + + + + \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfigBuilder_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfigBuilder_v0_3.java new file mode 100644 index 000000000..be9d95608 --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfigBuilder_v0_3.java @@ -0,0 +1,28 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc; + +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfigBuilder_v0_3; + +public class JSONRPCTransportConfigBuilder_v0_3 extends ClientTransportConfigBuilder_v0_3 { + + private A2AHttpClient_v0_3 httpClient; + + public JSONRPCTransportConfigBuilder_v0_3 httpClient(A2AHttpClient_v0_3 httpClient) { + this.httpClient = httpClient; + + return this; + } + + @Override + public JSONRPCTransportConfig_v0_3 build() { + // No HTTP client provided, fallback to the default one (JDK-based implementation) + if (httpClient == null) { + httpClient = new JdkA2AHttpClient_v0_3(); + } + + JSONRPCTransportConfig_v0_3 config = new JSONRPCTransportConfig_v0_3(httpClient); + config.setInterceptors(this.interceptors); + return config; + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfig_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfig_v0_3.java new file mode 100644 index 000000000..7e01e3e56 --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfig_v0_3.java @@ -0,0 +1,21 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc; + +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfig_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; + +public class JSONRPCTransportConfig_v0_3 extends ClientTransportConfig_v0_3 { + + private final A2AHttpClient_v0_3 httpClient; + + public JSONRPCTransportConfig_v0_3() { + this.httpClient = null; + } + + public JSONRPCTransportConfig_v0_3(A2AHttpClient_v0_3 httpClient) { + this.httpClient = httpClient; + } + + public A2AHttpClient_v0_3 getHttpClient() { + return httpClient; + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportProvider_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportProvider_v0_3.java new file mode 100644 index 000000000..afe66dadf --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportProvider_v0_3.java @@ -0,0 +1,29 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc; + +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; + +public class JSONRPCTransportProvider_v0_3 implements ClientTransportProvider_v0_3 { + + @Override + public JSONRPCTransport_v0_3 create(JSONRPCTransportConfig_v0_3 clientTransportConfig, AgentCard_v0_3 agentCard, String agentUrl) throws A2AClientException_v0_3 { + if (clientTransportConfig == null) { + clientTransportConfig = new JSONRPCTransportConfig_v0_3(new JdkA2AHttpClient_v0_3()); + } + + return new JSONRPCTransport_v0_3(clientTransportConfig.getHttpClient(), agentCard, agentUrl, clientTransportConfig.getInterceptors()); + } + + @Override + public String getTransportProtocol() { + return TransportProtocol_v0_3.JSONRPC.asString(); + } + + @Override + public Class getTransportProtocolClass() { + return JSONRPCTransport_v0_3.class; + } +} diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3.java new file mode 100644 index 000000000..d379277cd --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3.java @@ -0,0 +1,424 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc; + +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; + +import org.a2aproject.sdk.compat03.client.http.A2ACardResolver_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallInterceptor_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.PayloadAndHeaders_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransport_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskResponse_v0_3; + +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetAuthenticatedExtendedCardRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetAuthenticatedExtendedCardResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCMessage_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCResponse_v0_3; + +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskResubscriptionRequest_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.sse.SSEEventListener_v0_3; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; + +public class JSONRPCTransport_v0_3 implements ClientTransport_v0_3 { + + private static final Class SEND_MESSAGE_RESPONSE_REFERENCE = SendMessageResponse_v0_3.class; + private static final Class GET_TASK_RESPONSE_REFERENCE = GetTaskResponse_v0_3.class; + private static final Class CANCEL_TASK_RESPONSE_REFERENCE = CancelTaskResponse_v0_3.class; + private static final Class GET_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE = GetTaskPushNotificationConfigResponse_v0_3.class; + private static final Class SET_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE = SetTaskPushNotificationConfigResponse_v0_3.class; + private static final Class LIST_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE = ListTaskPushNotificationConfigResponse_v0_3.class; + private static final Class DELETE_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE = DeleteTaskPushNotificationConfigResponse_v0_3.class; + private static final Class GET_AUTHENTICATED_EXTENDED_CARD_RESPONSE_REFERENCE = GetAuthenticatedExtendedCardResponse_v0_3.class; + + private final A2AHttpClient_v0_3 httpClient; + private final String agentUrl; + private final List interceptors; + private AgentCard_v0_3 agentCard; + private boolean needsExtendedCard = false; + + public JSONRPCTransport_v0_3(String agentUrl) { + this(null, null, agentUrl, null); + } + + public JSONRPCTransport_v0_3(AgentCard_v0_3 agentCard) { + this(null, agentCard, agentCard.url(), null); + } + + public JSONRPCTransport_v0_3(A2AHttpClient_v0_3 httpClient, AgentCard_v0_3 agentCard, + String agentUrl, List interceptors) { + this.httpClient = httpClient == null ? new JdkA2AHttpClient_v0_3() : httpClient; + this.agentCard = agentCard; + this.agentUrl = agentUrl; + this.interceptors = interceptors; + this.needsExtendedCard = agentCard == null || agentCard.supportsAuthenticatedExtendedCard(); + } + + @Override + public EventKind_v0_3 sendMessage(MessageSendParams_v0_3 request, ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + SendMessageRequest_v0_3 sendMessageRequest = new SendMessageRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(SendMessageRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SendMessageRequest_v0_3.METHOD, sendMessageRequest, + agentCard, context); + + try { + String httpResponseBody = sendPostRequest(payloadAndHeaders); + SendMessageResponse_v0_3 response = unmarshalResponse(httpResponseBody, SEND_MESSAGE_RESPONSE_REFERENCE); + return response.getResult(); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to send message: " + e, e); + } + } + + @Override + public void sendMessageStreaming(MessageSendParams_v0_3 request, Consumer eventConsumer, + Consumer errorConsumer, ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + checkNotNullParam("eventConsumer", eventConsumer); + SendStreamingMessageRequest_v0_3 sendStreamingMessageRequest = new SendStreamingMessageRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(SendStreamingMessageRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SendStreamingMessageRequest_v0_3.METHOD, + sendStreamingMessageRequest, agentCard, context); + + AtomicReference> ref = new AtomicReference<>(); + SSEEventListener_v0_3 sseEventListener = new SSEEventListener_v0_3(eventConsumer, errorConsumer); + + try { + A2AHttpClient_v0_3.PostBuilder builder = createPostBuilder(payloadAndHeaders); + ref.set(builder.postAsyncSSE( + msg -> sseEventListener.onMessage(msg, ref.get()), + throwable -> sseEventListener.onError(throwable, ref.get()), + () -> { + // Signal normal stream completion to error handler (null error means success) + sseEventListener.onComplete(); + })); + } catch (IOException e) { + throw new A2AClientException_v0_3("Failed to send streaming message request: " + e, e); + } catch (InterruptedException e) { + throw new A2AClientException_v0_3("Send streaming message request timed out: " + e, e); + } catch (JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to process JSON for streaming message request: " + e, e); + } + } + + @Override + public Task_v0_3 getTask(TaskQueryParams_v0_3 request, ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + GetTaskRequest_v0_3 getTaskRequest = new GetTaskRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(GetTaskRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetTaskRequest_v0_3.METHOD, getTaskRequest, + agentCard, context); + + try { + String httpResponseBody = sendPostRequest(payloadAndHeaders); + GetTaskResponse_v0_3 response = unmarshalResponse(httpResponseBody, GET_TASK_RESPONSE_REFERENCE); + return response.getResult(); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to get task: " + e, e); + } + } + + @Override + public Task_v0_3 cancelTask(TaskIdParams_v0_3 request, ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + CancelTaskRequest_v0_3 cancelTaskRequest = new CancelTaskRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(CancelTaskRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(CancelTaskRequest_v0_3.METHOD, cancelTaskRequest, + agentCard, context); + + try { + String httpResponseBody = sendPostRequest(payloadAndHeaders); + CancelTaskResponse_v0_3 response = unmarshalResponse(httpResponseBody, CANCEL_TASK_RESPONSE_REFERENCE); + return response.getResult(); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to cancel task: " + e, e); + } + } + + @Override + public TaskPushNotificationConfig_v0_3 setTaskPushNotificationConfiguration(TaskPushNotificationConfig_v0_3 request, + ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + SetTaskPushNotificationConfigRequest_v0_3 setTaskPushNotificationRequest = new SetTaskPushNotificationConfigRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(SetTaskPushNotificationConfigRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SetTaskPushNotificationConfigRequest_v0_3.METHOD, + setTaskPushNotificationRequest, agentCard, context); + + try { + String httpResponseBody = sendPostRequest(payloadAndHeaders); + SetTaskPushNotificationConfigResponse_v0_3 response = unmarshalResponse(httpResponseBody, + SET_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE); + return response.getResult(); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to set task push notification config: " + e, e); + } + } + + @Override + public TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams_v0_3 request, + ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + GetTaskPushNotificationConfigRequest_v0_3 getTaskPushNotificationRequest = new GetTaskPushNotificationConfigRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(GetTaskPushNotificationConfigRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetTaskPushNotificationConfigRequest_v0_3.METHOD, + getTaskPushNotificationRequest, agentCard, context); + + try { + String httpResponseBody = sendPostRequest(payloadAndHeaders); + GetTaskPushNotificationConfigResponse_v0_3 response = unmarshalResponse(httpResponseBody, + GET_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE); + return response.getResult(); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to get task push notification config: " + e, e); + } + } + + @Override + public List listTaskPushNotificationConfigurations( + ListTaskPushNotificationConfigParams_v0_3 request, + ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + ListTaskPushNotificationConfigRequest_v0_3 listTaskPushNotificationRequest = new ListTaskPushNotificationConfigRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(ListTaskPushNotificationConfigRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(ListTaskPushNotificationConfigRequest_v0_3.METHOD, + listTaskPushNotificationRequest, agentCard, context); + + try { + String httpResponseBody = sendPostRequest(payloadAndHeaders); + ListTaskPushNotificationConfigResponse_v0_3 response = unmarshalResponse(httpResponseBody, + LIST_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE); + return response.getResult(); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to list task push notification configs: " + e, e); + } + } + + @Override + public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams_v0_3 request, + ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + DeleteTaskPushNotificationConfigRequest_v0_3 deleteTaskPushNotificationRequest = new DeleteTaskPushNotificationConfigRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(DeleteTaskPushNotificationConfigRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(DeleteTaskPushNotificationConfigRequest_v0_3.METHOD, + deleteTaskPushNotificationRequest, agentCard, context); + + try { + String httpResponseBody = sendPostRequest(payloadAndHeaders); + unmarshalResponse(httpResponseBody, DELETE_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to delete task push notification configs: " + e, e); + } + } + + @Override + public void resubscribe(TaskIdParams_v0_3 request, Consumer eventConsumer, + Consumer errorConsumer, ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + checkNotNullParam("eventConsumer", eventConsumer); + checkNotNullParam("errorConsumer", errorConsumer); + TaskResubscriptionRequest_v0_3 taskResubscriptionRequest = new TaskResubscriptionRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(TaskResubscriptionRequest_v0_3.METHOD) + .params(request) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(TaskResubscriptionRequest_v0_3.METHOD, + taskResubscriptionRequest, agentCard, context); + + AtomicReference> ref = new AtomicReference<>(); + SSEEventListener_v0_3 sseEventListener = new SSEEventListener_v0_3(eventConsumer, errorConsumer); + + try { + A2AHttpClient_v0_3.PostBuilder builder = createPostBuilder(payloadAndHeaders); + ref.set(builder.postAsyncSSE( + msg -> sseEventListener.onMessage(msg, ref.get()), + throwable -> sseEventListener.onError(throwable, ref.get()), + () -> { + // Signal normal stream completion to error handler (null error means success) + sseEventListener.onComplete(); + })); + } catch (IOException e) { + throw new A2AClientException_v0_3("Failed to send task resubscription request: " + e, e); + } catch (InterruptedException e) { + throw new A2AClientException_v0_3("Task resubscription request timed out: " + e, e); + } catch (JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to process JSON for task resubscription request: " + e, e); + } + } + + @Override + public AgentCard_v0_3 getAgentCard(ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + A2ACardResolver_v0_3 resolver; + try { + if (agentCard == null) { + resolver = new A2ACardResolver_v0_3(httpClient, agentUrl, null, getHttpHeaders(context)); + agentCard = resolver.getAgentCard(); + needsExtendedCard = agentCard.supportsAuthenticatedExtendedCard(); + } + if (!needsExtendedCard) { + return agentCard; + } + + GetAuthenticatedExtendedCardRequest_v0_3 getExtendedAgentCardRequest = new GetAuthenticatedExtendedCardRequest_v0_3.Builder() + .jsonrpc(JSONRPCMessage_v0_3.JSONRPC_VERSION) + .method(GetAuthenticatedExtendedCardRequest_v0_3.METHOD) + .build(); // id will be randomly generated + + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetAuthenticatedExtendedCardRequest_v0_3.METHOD, + getExtendedAgentCardRequest, agentCard, context); + + try { + String httpResponseBody = sendPostRequest(payloadAndHeaders); + GetAuthenticatedExtendedCardResponse_v0_3 response = unmarshalResponse(httpResponseBody, + GET_AUTHENTICATED_EXTENDED_CARD_RESPONSE_REFERENCE); + agentCard = response.getResult(); + needsExtendedCard = false; + return agentCard; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to get authenticated extended agent card: " + e, e); + } + } catch(A2AClientError_v0_3 e){ + throw new A2AClientException_v0_3("Failed to get agent card: " + e, e); + } + } + + @Override + public void close() { + // no-op + } + + private PayloadAndHeaders_v0_3 applyInterceptors(String methodName, Object payload, + AgentCard_v0_3 agentCard, ClientCallContext_v0_3 clientCallContext) { + PayloadAndHeaders_v0_3 payloadAndHeaders = new PayloadAndHeaders_v0_3(payload, getHttpHeaders(clientCallContext)); + if (interceptors != null && ! interceptors.isEmpty()) { + for (ClientCallInterceptor_v0_3 interceptor : interceptors) { + payloadAndHeaders = interceptor.intercept(methodName, payloadAndHeaders.getPayload(), + payloadAndHeaders.getHeaders(), agentCard, clientCallContext); + } + } + return payloadAndHeaders; + } + + private String sendPostRequest(PayloadAndHeaders_v0_3 payloadAndHeaders) throws IOException, InterruptedException, JsonProcessingException_v0_3 { + A2AHttpClient_v0_3.PostBuilder builder = createPostBuilder(payloadAndHeaders); + A2AHttpResponse_v0_3 response = builder.post(); + if (!response.success()) { + throw new IOException("Request failed " + response.status()); + } + return response.body(); + } + + private A2AHttpClient_v0_3.PostBuilder createPostBuilder(PayloadAndHeaders_v0_3 payloadAndHeaders) throws JsonProcessingException_v0_3 { + A2AHttpClient_v0_3.PostBuilder postBuilder = httpClient.createPost() + .url(agentUrl) + .addHeader("Content-Type", "application/json") + .body(JsonUtil_v0_3.toJson(payloadAndHeaders.getPayload())); + + if (payloadAndHeaders.getHeaders() != null) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + postBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + + return postBuilder; + } + + private > T unmarshalResponse(String response, Class responseClass) + throws A2AClientException_v0_3, JsonProcessingException_v0_3 { + T value = JsonUtil_v0_3.fromJson(response, responseClass); + JSONRPCError_v0_3 error = value.getError(); + if (error != null) { + throw new A2AClientException_v0_3(error.getMessage() + (error.getData() != null ? ": " + error.getData() : ""), error); + } + return value; + } + + private Map getHttpHeaders(ClientCallContext_v0_3 context) { + return context != null ? context.getHeaders() : null; + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3.java new file mode 100644 index 000000000..6ae5a944c --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3.java @@ -0,0 +1,88 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc.sse; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; + +import java.util.concurrent.Future; +import java.util.function.Consumer; +import java.util.logging.Logger; + +public class SSEEventListener_v0_3 { + private static final Logger log = Logger.getLogger(SSEEventListener_v0_3.class.getName()); + private final Consumer eventHandler; + private final Consumer errorHandler; + private volatile boolean completed = false; + + public SSEEventListener_v0_3(Consumer eventHandler, + Consumer errorHandler) { + this.eventHandler = eventHandler; + this.errorHandler = errorHandler; + } + + public void onMessage(String message, Future completableFuture) { + try { + handleMessage(JsonParser.parseString(message).getAsJsonObject(), completableFuture); + } catch (JsonSyntaxException e) { + log.warning("Failed to parse JSON message: " + message); + } catch (JsonProcessingException_v0_3 e) { + log.warning("Failed to process JSON message: " + message); + } catch (IllegalArgumentException e) { + log.warning("Invalid message format: " + message); + if (errorHandler != null) { + errorHandler.accept(e); + } + completableFuture.cancel(true); // close SSE channel + } + } + + public void onError(Throwable throwable, Future future) { + if (errorHandler != null) { + errorHandler.accept(throwable); + } + future.cancel(true); // close SSE channel + } + + public void onComplete() { + // Idempotent: only signal completion once, even if called multiple times + if (completed) { + log.fine("SSEEventListener.onComplete() called again - ignoring (already completed)"); + return; + } + completed = true; + + // Signal normal stream completion (null error means successful completion) + log.fine("SSEEventListener.onComplete() called - signaling successful stream completion"); + if (errorHandler != null) { + log.fine("Calling errorHandler.accept(null) to signal successful completion"); + errorHandler.accept(null); + } else { + log.warning("errorHandler is null, cannot signal completion"); + } + } + + private void handleMessage(JsonObject jsonObject, Future future) throws JsonProcessingException_v0_3 { + if (jsonObject.has("error")) { + JSONRPCError_v0_3 error = JsonUtil_v0_3.fromJson(jsonObject.get("error").toString(), JSONRPCError_v0_3.class); + if (errorHandler != null) { + errorHandler.accept(error); + } + } else if (jsonObject.has("result")) { + // result can be a Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent + String resultJson = jsonObject.get("result").toString(); + StreamingEventKind_v0_3 event = JsonUtil_v0_3.fromJson(resultJson, StreamingEventKind_v0_3.class); + eventHandler.accept(event); + if (event instanceof TaskStatusUpdateEvent_v0_3 && ((TaskStatusUpdateEvent_v0_3) event).isFinal()) { + future.cancel(true); // close SSE channel + } + } else { + throw new IllegalArgumentException("Unknown message type"); + } + } + +} diff --git a/compat-0.3/client/transport/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 b/compat-0.3/client/transport/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 new file mode 100644 index 000000000..baf961ea6 --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 @@ -0,0 +1 @@ +org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportProvider_v0_3 \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportStreaming_v0_3_Test.java b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportStreaming_v0_3_Test.java new file mode 100644 index 000000000..914b92078 --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportStreaming_v0_3_Test.java @@ -0,0 +1,174 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc; + +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonStreamingMessages_v0_3.SEND_MESSAGE_STREAMING_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonStreamingMessages_v0_3.SEND_MESSAGE_STREAMING_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonStreamingMessages_v0_3.TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonStreamingMessages_v0_3.TASK_RESUBSCRIPTION_TEST_REQUEST; +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.assertTrue; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendConfiguration_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.matchers.MatchType; +import org.mockserver.model.JsonBody; + +public class JSONRPCTransportStreaming_v0_3_Test { + + private ClientAndServer server; + + @BeforeEach + public void setUp() { + server = new ClientAndServer(4001); + } + + @AfterEach + public void tearDown() { + server.stop(); + } + + @Test + public void testSendStreamingMessageParams() { + // The goal here is just to verify the correct parameters are being used + // This is a unit test of the parameter construction, not the streaming itself + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("test message"))) + .contextId("context-test") + .messageId("message-test") + .build(); + + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(false) + .build(); + + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + + assertNotNull(params); + assertEquals(message, params.message()); + assertEquals(configuration, params.configuration()); + assertEquals(Message_v0_3.Role.USER, params.message().getRole()); + assertEquals("test message", ((TextPart_v0_3) params.message().getParts().get(0)).getText()); + } + + @Test + public void testA2AClientSendStreamingMessage() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(SEND_MESSAGE_STREAMING_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody(SEND_MESSAGE_STREAMING_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("tell me some jokes"))) + .contextId("context-1234") + .messageId("message-1234") + .build(); + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(false) + .build(); + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + + AtomicReference receivedEvent = new AtomicReference<>(); + CountDownLatch latch = new CountDownLatch(1); + Consumer eventHandler = event -> { + receivedEvent.set(event); + latch.countDown(); + }; + Consumer errorHandler = error -> {}; + client.sendMessageStreaming(params, eventHandler, errorHandler, null); + + boolean eventReceived = latch.await(10, TimeUnit.SECONDS); + assertTrue(eventReceived); + assertNotNull(receivedEvent.get()); + } + + @Test + public void testA2AClientResubscribeToTask() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(TASK_RESUBSCRIPTION_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody(TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + TaskIdParams_v0_3 taskIdParams = new TaskIdParams_v0_3("task-1234"); + + AtomicReference receivedEvent = new AtomicReference<>(); + CountDownLatch latch = new CountDownLatch(1); + Consumer eventHandler = event -> { + receivedEvent.set(event); + latch.countDown(); + }; + Consumer errorHandler = error -> {}; + client.resubscribe(taskIdParams, eventHandler, errorHandler, null); + + boolean eventReceived = latch.await(10, TimeUnit.SECONDS); + assertTrue(eventReceived); + + StreamingEventKind_v0_3 eventKind = receivedEvent.get();; + assertNotNull(eventKind); + assertInstanceOf(Task_v0_3.class, eventKind); + Task_v0_3 task = (Task_v0_3) eventKind; + assertEquals("2", task.getId()); + assertEquals("context-1234", task.getContextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + List artifacts = task.getArtifacts(); + assertEquals(1, artifacts.size()); + Artifact_v0_3 artifact = artifacts.get(0); + assertEquals("artifact-1", artifact.artifactId()); + assertEquals("joke", artifact.name()); + Part_v0_3 part = artifact.parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3_Test.java b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3_Test.java new file mode 100644 index 000000000..b3ca67f9e --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3_Test.java @@ -0,0 +1,683 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc; + +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.AGENT_CARD; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.AGENT_CARD_SUPPORTS_EXTENDED; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.CANCEL_TASK_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.CANCEL_TASK_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.GET_TASK_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.GET_TASK_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_ERROR_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_WITH_ERROR_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonMessages_v0_3.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +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.fail; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentInterface_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.DataPart_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.FileContent_v0_3; +import org.a2aproject.sdk.compat03.spec.FilePart_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithBytes_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithUri_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendConfiguration_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.OpenIdConnectSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationAuthenticationInfo_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.SecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.matchers.MatchType; +import org.mockserver.model.JsonBody; + +public class JSONRPCTransport_v0_3_Test { + + private ClientAndServer server; + + @BeforeEach + public void setUp() { + server = new ClientAndServer(4001); + } + + @AfterEach + public void tearDown() { + server.stop(); + } + + @Test + public void testA2AClientSendMessage() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(SEND_MESSAGE_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(SEND_MESSAGE_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("tell me a joke"))) + .contextId("context-1234") + .messageId("message-1234") + .build(); + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(true) + .build(); + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + + EventKind_v0_3 result = client.sendMessage(params, null); + assertInstanceOf(Task_v0_3.class, result); + Task_v0_3 task = (Task_v0_3) result; + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); + assertNotNull(task.getContextId()); + assertEquals(TaskState_v0_3.COMPLETED,task.getStatus().state()); + assertEquals(1, task.getArtifacts().size()); + Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("artifact-1", artifact.artifactId()); + assertEquals("joke", artifact.name()); + assertEquals(1, artifact.parts().size()); + Part_v0_3 part = artifact.parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); + assertTrue(task.getMetadata().isEmpty()); + } + + @Test + public void testA2AClientSendMessageWithMessageResponse() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("tell me a joke"))) + .contextId("context-1234") + .messageId("message-1234") + .build(); + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(true) + .build(); + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + + EventKind_v0_3 result = client.sendMessage(params, null); + assertInstanceOf(Message_v0_3.class, result); + Message_v0_3 agentMessage = (Message_v0_3) result; + assertEquals(Message_v0_3.Role.AGENT, agentMessage.getRole()); + Part_v0_3 part = agentMessage.getParts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); + assertEquals("msg-456", agentMessage.getMessageId()); + } + + + @Test + public void testA2AClientSendMessageWithError() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(SEND_MESSAGE_WITH_ERROR_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(SEND_MESSAGE_ERROR_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("tell me a joke"))) + .contextId("context-1234") + .messageId("message-1234") + .build(); + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(true) + .build(); + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + + try { + client.sendMessage(params, null); + fail(); // should not reach here + } catch (A2AClientException_v0_3 e) { + assertTrue(e.getMessage().contains("Invalid parameters: Hello world")); + } + } + + @Test + public void testA2AClientGetTask() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(GET_TASK_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(GET_TASK_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + Task_v0_3 task = client.getTask(new TaskQueryParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", + 10), null); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); + assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.getContextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + assertEquals(1, task.getArtifacts().size()); + Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals(1, artifact.parts().size()); + assertEquals("artifact-1", artifact.artifactId()); + Part_v0_3 part = artifact.parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); + assertTrue(task.getMetadata().isEmpty()); + List history = task.getHistory(); + assertNotNull(history); + assertEquals(1, history.size()); + Message_v0_3 message = history.get(0); + assertEquals(Message_v0_3.Role.USER, message.getRole()); + List> parts = message.getParts(); + assertNotNull(parts); + assertEquals(3, parts.size()); + part = parts.get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("tell me a joke", ((TextPart_v0_3)part).getText()); + part = parts.get(1); + assertEquals(Part_v0_3.Kind.FILE, part.getKind()); + FileContent_v0_3 filePart = ((FilePart_v0_3) part).getFile(); + assertEquals("file:///path/to/file.txt", ((FileWithUri_v0_3) filePart).uri()); + assertEquals("text/plain", filePart.mimeType()); + part = parts.get(2); + assertEquals(Part_v0_3.Kind.FILE, part.getKind()); + filePart = ((FilePart_v0_3) part).getFile(); + assertEquals("aGVsbG8=", ((FileWithBytes_v0_3) filePart).bytes()); + assertEquals("hello.txt", filePart.name()); + assertTrue(task.getMetadata().isEmpty()); + } + + @Test + public void testA2AClientCancelTask() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(CANCEL_TASK_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(CANCEL_TASK_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + Task_v0_3 task = client.cancelTask(new TaskIdParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", + new HashMap<>()), null); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); + assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.getContextId()); + assertEquals(TaskState_v0_3.CANCELED, task.getStatus().state()); + assertTrue(task.getMetadata().isEmpty()); + } + + @Test + public void testA2AClientGetTaskPushNotificationConfig() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + TaskPushNotificationConfig_v0_3 taskPushNotificationConfig = client.getTaskPushNotificationConfiguration( + new GetTaskPushNotificationConfigParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", null, + new HashMap<>()), null); + PushNotificationConfig_v0_3 pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); + assertNotNull(pushNotificationConfig); + assertEquals("https://example.com/callback", pushNotificationConfig.url()); + PushNotificationAuthenticationInfo_v0_3 authenticationInfo = pushNotificationConfig.authentication(); + assertTrue(authenticationInfo.schemes().size() == 1); + assertEquals("jwt", authenticationInfo.schemes().get(0)); + } + + @Test + public void testA2AClientSetTaskPushNotificationConfig() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + TaskPushNotificationConfig_v0_3 taskPushNotificationConfig = client.setTaskPushNotificationConfiguration( + new TaskPushNotificationConfig_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", + new PushNotificationConfig_v0_3.Builder() + .url("https://example.com/callback") + .authenticationInfo(new PushNotificationAuthenticationInfo_v0_3(Collections.singletonList("jwt"), + null)) + .build()), null); + PushNotificationConfig_v0_3 pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); + assertNotNull(pushNotificationConfig); + assertEquals("https://example.com/callback", pushNotificationConfig.url()); + PushNotificationAuthenticationInfo_v0_3 authenticationInfo = pushNotificationConfig.authentication(); + assertEquals(1, authenticationInfo.schemes().size()); + assertEquals("jwt", authenticationInfo.schemes().get(0)); + } + + + @Test + public void testA2AClientGetAgentCard() throws Exception { + this.server.when( + request() + .withMethod("GET") + .withPath("/.well-known/agent-card.json") + ) + .respond( + response() + .withStatusCode(200) + .withBody(AGENT_CARD) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + AgentCard_v0_3 agentCard = client.getAgentCard(null); + assertEquals("GeoSpatial Route Planner Agent", agentCard.name()); + assertEquals("Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", agentCard.description()); + assertEquals("https://georoute-agent.example.com/a2a/v1", agentCard.url()); + assertEquals("Example Geo Services Inc.", agentCard.provider().organization()); + assertEquals("https://www.examplegeoservices.com", agentCard.provider().url()); + assertEquals("1.2.0", agentCard.version()); + assertEquals("https://docs.examplegeoservices.com/georoute-agent/api", agentCard.documentationUrl()); + assertTrue(agentCard.capabilities().streaming()); + assertTrue(agentCard.capabilities().pushNotifications()); + assertFalse(agentCard.capabilities().stateTransitionHistory()); + Map securitySchemes = agentCard.securitySchemes(); + assertNotNull(securitySchemes); + OpenIdConnectSecurityScheme_v0_3 google = (OpenIdConnectSecurityScheme_v0_3) securitySchemes.get("google"); + assertEquals("openIdConnect", google.getType()); + assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.getOpenIdConnectUrl()); + List>> security = agentCard.security(); + assertEquals(1, security.size()); + Map> securityMap = security.get(0); + List scopes = securityMap.get("google"); + List expectedScopes = List.of("openid", "profile", "email"); + assertEquals(expectedScopes, scopes); + List defaultInputModes = List.of("application/json", "text/plain"); + assertEquals(defaultInputModes, agentCard.defaultInputModes()); + List defaultOutputModes = List.of("application/json", "image/png"); + assertEquals(defaultOutputModes, agentCard.defaultOutputModes()); + List skills = agentCard.skills(); + assertEquals("route-optimizer-traffic", skills.get(0).id()); + assertEquals("Traffic-Aware Route Optimizer", skills.get(0).name()); + assertEquals("Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", skills.get(0).description()); + List tags = List.of("maps", "routing", "navigation", "directions", "traffic"); + assertEquals(tags, skills.get(0).tags()); + List examples = List.of("Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}"); + assertEquals(examples, skills.get(0).examples()); + assertEquals(defaultInputModes, skills.get(0).inputModes()); + List outputModes = List.of("application/json", "application/vnd.geo+json", "text/html"); + assertEquals(outputModes, skills.get(0).outputModes()); + assertEquals("custom-map-generator", skills.get(1).id()); + assertEquals("Personalized Map Generator", skills.get(1).name()); + assertEquals("Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", skills.get(1).description()); + tags = List.of("maps", "customization", "visualization", "cartography"); + assertEquals(tags, skills.get(1).tags()); + examples = List.of("Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location."); + assertEquals(examples, skills.get(1).examples()); + List inputModes = List.of("application/json"); + assertEquals(inputModes, skills.get(1).inputModes()); + outputModes = List.of("image/png", "image/jpeg", "application/json", "text/html"); + assertEquals(outputModes, skills.get(1).outputModes()); + assertFalse(agentCard.supportsAuthenticatedExtendedCard()); + assertEquals("https://georoute-agent.example.com/icon.png", agentCard.iconUrl()); + assertEquals("0.2.9", agentCard.protocolVersion()); + assertEquals("JSONRPC", agentCard.preferredTransport()); + List additionalInterfaces = agentCard.additionalInterfaces(); + assertEquals(3, additionalInterfaces.size()); + AgentInterface_v0_3 jsonrpc = new AgentInterface_v0_3(TransportProtocol_v0_3.JSONRPC.asString(), "https://georoute-agent.example.com/a2a/v1"); + AgentInterface_v0_3 grpc = new AgentInterface_v0_3(TransportProtocol_v0_3.GRPC.asString(), "https://georoute-agent.example.com/a2a/grpc"); + AgentInterface_v0_3 httpJson = new AgentInterface_v0_3(TransportProtocol_v0_3.HTTP_JSON.asString(), "https://georoute-agent.example.com/a2a/json"); + assertEquals(jsonrpc, additionalInterfaces.get(0)); + assertEquals(grpc, additionalInterfaces.get(1)); + assertEquals(httpJson, additionalInterfaces.get(2)); + } + + @Test + public void testA2AClientGetAuthenticatedExtendedAgentCard() throws Exception { + this.server.when( + request() + .withMethod("GET") + .withPath("/.well-known/agent-card.json") + ) + .respond( + response() + .withStatusCode(200) + .withBody(AGENT_CARD_SUPPORTS_EXTENDED) + ); + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + ) + .respond( + response() + .withStatusCode(200) + .withBody(GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + AgentCard_v0_3 agentCard = client.getAgentCard(null); + assertEquals("GeoSpatial Route Planner Agent Extended", agentCard.name()); + assertEquals("Extended description", agentCard.description()); + assertEquals("https://georoute-agent.example.com/a2a/v1", agentCard.url()); + assertEquals("Example Geo Services Inc.", agentCard.provider().organization()); + assertEquals("https://www.examplegeoservices.com", agentCard.provider().url()); + assertEquals("1.2.0", agentCard.version()); + assertEquals("https://docs.examplegeoservices.com/georoute-agent/api", agentCard.documentationUrl()); + assertTrue(agentCard.capabilities().streaming()); + assertTrue(agentCard.capabilities().pushNotifications()); + assertFalse(agentCard.capabilities().stateTransitionHistory()); + Map securitySchemes = agentCard.securitySchemes(); + assertNotNull(securitySchemes); + OpenIdConnectSecurityScheme_v0_3 google = (OpenIdConnectSecurityScheme_v0_3) securitySchemes.get("google"); + assertEquals("openIdConnect", google.getType()); + assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.getOpenIdConnectUrl()); + List>> security = agentCard.security(); + assertEquals(1, security.size()); + Map> securityMap = security.get(0); + List scopes = securityMap.get("google"); + List expectedScopes = List.of("openid", "profile", "email"); + assertEquals(expectedScopes, scopes); + List defaultInputModes = List.of("application/json", "text/plain"); + assertEquals(defaultInputModes, agentCard.defaultInputModes()); + List defaultOutputModes = List.of("application/json", "image/png"); + assertEquals(defaultOutputModes, agentCard.defaultOutputModes()); + List skills = agentCard.skills(); + assertEquals("route-optimizer-traffic", skills.get(0).id()); + assertEquals("Traffic-Aware Route Optimizer", skills.get(0).name()); + assertEquals("Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", skills.get(0).description()); + List tags = List.of("maps", "routing", "navigation", "directions", "traffic"); + assertEquals(tags, skills.get(0).tags()); + List examples = List.of("Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}"); + assertEquals(examples, skills.get(0).examples()); + assertEquals(defaultInputModes, skills.get(0).inputModes()); + List outputModes = List.of("application/json", "application/vnd.geo+json", "text/html"); + assertEquals(outputModes, skills.get(0).outputModes()); + assertEquals("custom-map-generator", skills.get(1).id()); + assertEquals("Personalized Map Generator", skills.get(1).name()); + assertEquals("Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", skills.get(1).description()); + tags = List.of("maps", "customization", "visualization", "cartography"); + assertEquals(tags, skills.get(1).tags()); + examples = List.of("Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location."); + assertEquals(examples, skills.get(1).examples()); + List inputModes = List.of("application/json"); + assertEquals(inputModes, skills.get(1).inputModes()); + outputModes = List.of("image/png", "image/jpeg", "application/json", "text/html"); + assertEquals(outputModes, skills.get(1).outputModes()); + assertEquals("skill-extended", skills.get(2).id()); + assertEquals("Extended Skill", skills.get(2).name()); + assertEquals("This is an extended skill.", skills.get(2).description()); + assertEquals(List.of("extended"), skills.get(2).tags()); + assertTrue(agentCard.supportsAuthenticatedExtendedCard()); + assertEquals("https://georoute-agent.example.com/icon.png", agentCard.iconUrl()); + assertEquals("0.2.5", agentCard.protocolVersion()); + } + + @Test + public void testA2AClientSendMessageWithFilePart() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(List.of( + new TextPart_v0_3("analyze this image"), + new FilePart_v0_3(new FileWithUri_v0_3("image/jpeg", null, "file:///path/to/image.jpg")) + )) + .contextId("context-1234") + .messageId("message-1234-with-file") + .build(); + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(true) + .build(); + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + + EventKind_v0_3 result = client.sendMessage(params, null); + assertInstanceOf(Task_v0_3.class, result); + Task_v0_3 task = (Task_v0_3) result; + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); + assertNotNull(task.getContextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + assertEquals(1, task.getArtifacts().size()); + Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("artifact-1", artifact.artifactId()); + assertEquals("image-analysis", artifact.name()); + assertEquals(1, artifact.parts().size()); + Part_v0_3 part = artifact.parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("This is an image of a cat sitting on a windowsill.", ((TextPart_v0_3) part).getText()); + assertTrue(task.getMetadata().isEmpty()); + } + + @Test + public void testA2AClientSendMessageWithDataPart() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + + Map data = new HashMap<>(); + data.put("temperature", 25.5); + data.put("humidity", 60.2); + data.put("location", "San Francisco"); + data.put("timestamp", "2024-01-15T10:30:00Z"); + + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(List.of( + new TextPart_v0_3("process this data"), + new DataPart_v0_3(data) + )) + .contextId("context-1234") + .messageId("message-1234-with-data") + .build(); + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(true) + .build(); + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + + EventKind_v0_3 result = client.sendMessage(params, null); + assertInstanceOf(Task_v0_3.class, result); + Task_v0_3 task = (Task_v0_3) result; + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); + assertNotNull(task.getContextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + assertEquals(1, task.getArtifacts().size()); + Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("artifact-1", artifact.artifactId()); + assertEquals("data-analysis", artifact.name()); + assertEquals(1, artifact.parts().size()); + Part_v0_3 part = artifact.parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("Processed weather data: Temperature is 25.5°C, humidity is 60.2% in San Francisco.", ((TextPart_v0_3) part).getText()); + assertTrue(task.getMetadata().isEmpty()); + } + + @Test + public void testA2AClientSendMessageWithMixedParts() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/") + .withBody(JsonBody.json(SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + + ) + .respond( + response() + .withStatusCode(200) + .withBody(SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE) + ); + + JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); + + Map data = new HashMap<>(); + data.put("chartType", "bar"); + data.put("dataPoints", List.of(10, 20, 30, 40)); + data.put("labels", List.of("Q1", "Q2", "Q3", "Q4")); + + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(List.of( + new TextPart_v0_3("analyze this data and image"), + new FilePart_v0_3(new FileWithBytes_v0_3("image/png", "chart.png", "aGVsbG8=")), + new DataPart_v0_3(data) + )) + .contextId("context-1234") + .messageId("message-1234-with-mixed") + .build(); + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(true) + .build(); + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + + EventKind_v0_3 result = client.sendMessage(params, null); + assertInstanceOf(Task_v0_3.class, result); + Task_v0_3 task = (Task_v0_3) result; + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); + assertNotNull(task.getContextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + assertEquals(1, task.getArtifacts().size()); + Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("artifact-1", artifact.artifactId()); + assertEquals("mixed-analysis", artifact.name()); + assertEquals(1, artifact.parts().size()); + Part_v0_3 part = artifact.parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("Analyzed chart image and data: Bar chart showing quarterly data with values [10, 20, 30, 40].", ((TextPart_v0_3) part).getText()); + assertTrue(task.getMetadata().isEmpty()); + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JsonMessages_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JsonMessages_v0_3.java new file mode 100644 index 000000000..a23a4b5e6 --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JsonMessages_v0_3.java @@ -0,0 +1,769 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc; + +/** + * Request and response messages used by the tests. These have been created following examples from + * the A2A sample messages. + */ +public class JsonMessages_v0_3 { + + static final String AGENT_CARD = """ + { + "protocolVersion": "0.2.9", + "name": "GeoSpatial Route Planner Agent", + "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", + "url": "https://georoute-agent.example.com/a2a/v1", + "preferredTransport": "JSONRPC", + "additionalInterfaces" : [ + {"url": "https://georoute-agent.example.com/a2a/v1", "transport": "JSONRPC"}, + {"url": "https://georoute-agent.example.com/a2a/grpc", "transport": "GRPC"}, + {"url": "https://georoute-agent.example.com/a2a/json", "transport": "HTTP+JSON"} + ], + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + } + ], + "supportsAuthenticatedExtendedCard": false, + "signatures": [ + { + "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", + "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" + } + ] + }"""; + + static final String AUTHENTICATION_EXTENDED_AGENT_CARD = """ + { + "name": "GeoSpatial Route Planner Agent Extended", + "description": "Extended description", + "url": "https://georoute-agent.example.com/a2a/v1", + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + }, + { + "id": "skill-extended", + "name": "Extended Skill", + "description": "This is an extended skill.", + "tags": ["extended"] + } + ], + "supportsAuthenticatedExtendedCard": true, + "protocolVersion": "0.2.9", + "signatures": [ + { + "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", + "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" + } + ] + }"""; + + static final String SEND_MESSAGE_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + } + ], + "messageId": "message-1234", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + }, + } + }"""; + + static final String SEND_MESSAGE_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "name": "joke", + "parts": [ + { + "kind": "text", + "text": "Why did the chicken cross the road? To get to the other side!" + } + ] + } + ], + "metadata": {}, + "kind": "task" + } + }"""; + + static final String SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + } + ], + "messageId": "message-1234", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + }, + } + }"""; + + + static final String SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE = """ + { + "jsonrpc": "2.0", + "id": 1, + "result": { + "role": "agent", + "parts": [ + { + "kind": "text", + "text": "Why did the chicken cross the road? To get to the other side!" + } + ], + "messageId": "msg-456", + "kind": "message" + } + }"""; + + static final String SEND_MESSAGE_WITH_ERROR_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + } + ], + "messageId": "message-1234", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + }, + } + }"""; + + static final String SEND_MESSAGE_ERROR_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "error": { + "code": -32702, + "message": "Invalid parameters", + "data": "Hello world" + } + }"""; + + static final String GET_TASK_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "tasks/get", + "params": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "historyLength": 10 + } + } + """; + + static final String GET_TASK_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "parts": [ + { + "kind": "text", + "text": "Why did the chicken cross the road? To get to the other side!" + } + ] + } + ], + "history": [ + { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + }, + { + "kind": "file", + "file": { + "uri": "file:///path/to/file.txt", + "mimeType": "text/plain" + } + }, + { + "kind": "file", + "file": { + "bytes": "aGVsbG8=", + "name": "hello.txt" + } + } + ], + "messageId": "message-123", + "kind": "message" + } + ], + "metadata": {}, + "kind": "task" + } + } + """; + + static final String CANCEL_TASK_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "tasks/cancel", + "params": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "metadata": {} + } + } + """; + + static final String CANCEL_TASK_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "canceled" + }, + "metadata": {}, + "kind" : "task" + } + } + """; + + static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "tasks/pushNotificationConfig/get", + "params": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "metadata": {}, + } + } + """; + + static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": ["jwt"] + } + } + } + } + """; + + static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "tasks/pushNotificationConfig/set", + "params": { + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": ["jwt"] + } + } + } + }"""; + + static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": ["jwt"] + } + } + } + } + """; + + static final String SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "analyze this image" + }, + { + "kind": "file", + "file": { + "uri": "file:///path/to/image.jpg", + "mimeType": "image/jpeg" + } + } + ], + "messageId": "message-1234-with-file", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + } + } + }"""; + + static final String SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "name": "image-analysis", + "parts": [ + { + "kind": "text", + "text": "This is an image of a cat sitting on a windowsill." + } + ] + } + ], + "metadata": {}, + "kind": "task" + } + }"""; + + static final String SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "process this data" + }, + { + "kind": "data", + "data": { + "temperature": 25.5, + "humidity": 60.2, + "location": "San Francisco", + "timestamp": "2024-01-15T10:30:00Z" + } + } + ], + "messageId": "message-1234-with-data", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + } + } + }"""; + + static final String SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "name": "data-analysis", + "parts": [ + { + "kind": "text", + "text": "Processed weather data: Temperature is 25.5°C, humidity is 60.2% in San Francisco." + } + ] + } + ], + "metadata": {}, + "kind": "task" + } + }"""; + + static final String SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "analyze this data and image" + }, + { + "kind": "file", + "file": { + "bytes": "aGVsbG8=", + "name": "chart.png", + "mimeType": "image/png" + } + }, + { + "kind": "data", + "data": { + "chartType": "bar", + "dataPoints": [10, 20, 30, 40], + "labels": ["Q1", "Q2", "Q3", "Q4"] + } + } + ], + "messageId": "message-1234-with-mixed", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + } + } + }"""; + + static final String SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "name": "mixed-analysis", + "parts": [ + { + "kind": "text", + "text": "Analyzed chart image and data: Bar chart showing quarterly data with values [10, 20, 30, 40]." + } + ] + } + ], + "metadata": {}, + "kind": "task" + } + }"""; + + static final String GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "agent/getAuthenticatedExtendedCard" + } + """; + + static final String GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE = """ + { + "jsonrpc": "2.0", + "id": "1", + "result": { + "name": "GeoSpatial Route Planner Agent Extended", + "description": "Extended description", + "url": "https://georoute-agent.example.com/a2a/v1", + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + }, + { + "id": "skill-extended", + "name": "Extended Skill", + "description": "This is an extended skill.", + "tags": ["extended"] + } + ], + "supportsAuthenticatedExtendedCard": true, + "protocolVersion": "0.2.5", + "signatures": [ + { + "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdUI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", + "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" + } + ] + } + }"""; + + static final String AGENT_CARD_SUPPORTS_EXTENDED = """ + { + "name": "GeoSpatial Route Planner Agent", + "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", + "url": "https://georoute-agent.example.com/a2a/v1", + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + } + ], + "supportsAuthenticatedExtendedCard": true, + "protocolVersion": "0.2.5" + }"""; +} diff --git a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JsonStreamingMessages_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JsonStreamingMessages_v0_3.java new file mode 100644 index 000000000..feb12572a --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JsonStreamingMessages_v0_3.java @@ -0,0 +1,145 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc; + +/** + * Contains JSON strings for testing SSE streaming. + */ +public class JsonStreamingMessages_v0_3 { + + public static final String STREAMING_TASK_EVENT = """ + data: { + "jsonrpc": "2.0", + "id": "1234", + "result": { + "kind": "task", + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "working" + } + } + } + """; + + + public static final String STREAMING_MESSAGE_EVENT = """ + data: { + "jsonrpc": "2.0", + "id": "1234", + "result": { + "kind": "message", + "role": "agent", + "messageId": "msg-123", + "contextId": "context-456", + "parts": [ + { + "kind": "text", + "text": "Hello, world!" + } + ] + } + }"""; + + public static final String STREAMING_STATUS_UPDATE_EVENT = """ + data: { + "jsonrpc": "2.0", + "id": "1234", + "result": { + "taskId": "1", + "contextId": "2", + "status": { + "state": "submitted" + }, + "final": false, + "kind": "status-update" + } + }"""; + + public static final String STREAMING_STATUS_UPDATE_EVENT_FINAL = """ + data: { + "jsonrpc": "2.0", + "id": "1234", + "result": { + "taskId": "1", + "contextId": "2", + "status": { + "state": "completed" + }, + "final": true, + "kind": "status-update" + } + }"""; + + public static final String STREAMING_ARTIFACT_UPDATE_EVENT = """ + data: { + "jsonrpc": "2.0", + "id": "1234", + "result": { + "kind": "artifact-update", + "taskId": "1", + "contextId": "2", + "append": false, + "lastChunk": true, + "artifact": { + "artifactId": "artifact-1", + "parts": [ + { + "kind": "text", + "text": "Why did the chicken cross the road? To get to the other side!" + } + ] + } + } + }"""; + + public static final String STREAMING_ERROR_EVENT = """ + data: { + "jsonrpc": "2.0", + "id": "1234", + "error": { + "code": -32602, + "message": "Invalid parameters", + "data": "Missing required field" + } + }"""; + + public static final String SEND_MESSAGE_STREAMING_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/stream", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me some jokes" + } + ], + "messageId": "message-1234", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": false + }, + } + }"""; + + static final String SEND_MESSAGE_STREAMING_TEST_RESPONSE = + "event: message\n" + + "data: {\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"id\":\"2\",\"contextId\":\"context-1234\",\"status\":{\"state\":\"completed\"},\"artifacts\":[{\"artifactId\":\"artifact-1\",\"name\":\"joke\",\"parts\":[{\"kind\":\"text\",\"text\":\"Why did the chicken cross the road? To get to the other side!\"}]}],\"metadata\":{},\"kind\":\"task\"}}\n\n"; + + static final String TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE = + "event: message\n" + + "data: {\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"id\":\"2\",\"contextId\":\"context-1234\",\"status\":{\"state\":\"completed\"},\"artifacts\":[{\"artifactId\":\"artifact-1\",\"name\":\"joke\",\"parts\":[{\"kind\":\"text\",\"text\":\"Why did the chicken cross the road? To get to the other side!\"}]}],\"metadata\":{},\"kind\":\"task\"}}\n\n"; + + public static final String TASK_RESUBSCRIPTION_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "tasks/resubscribe", + "params": { + "id": "task-1234" + } + }"""; +} \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3_Test.java b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3_Test.java new file mode 100644 index 000000000..b968c59ee --- /dev/null +++ b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3_Test.java @@ -0,0 +1,267 @@ +package org.a2aproject.sdk.compat03.client.transport.jsonrpc.sse; + +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 java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JsonStreamingMessages_v0_3; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.junit.jupiter.api.Test; + +public class SSEEventListener_v0_3_Test { + + @Test + public void testOnEventWithTaskResult() throws Exception { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener_v0_3 listener = new SSEEventListener_v0_3( + event -> receivedEvent.set(event), + error -> {} + ); + + // Parse the task event JSON + String eventData = JsonStreamingMessages_v0_3.STREAMING_TASK_EVENT.substring( + JsonStreamingMessages_v0_3.STREAMING_TASK_EVENT.indexOf("{")); + + // Call the onEvent method directly + listener.onMessage(eventData, null); + + // Verify the event was processed correctly + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof Task_v0_3); + Task_v0_3 task = (Task_v0_3) receivedEvent.get(); + assertEquals("task-123", task.getId()); + assertEquals("context-456", task.getContextId()); + assertEquals(TaskState_v0_3.WORKING, task.getStatus().state()); + } + + @Test + public void testOnEventWithMessageResult() throws Exception { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener_v0_3 listener = new SSEEventListener_v0_3( + event -> receivedEvent.set(event), + error -> {} + ); + + // Parse the message event JSON + String eventData = JsonStreamingMessages_v0_3.STREAMING_MESSAGE_EVENT.substring( + JsonStreamingMessages_v0_3.STREAMING_MESSAGE_EVENT.indexOf("{")); + + // Call onEvent method + listener.onMessage(eventData, null); + + // Verify the event was processed correctly + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof Message_v0_3); + Message_v0_3 message = (Message_v0_3) receivedEvent.get(); + assertEquals(Message_v0_3.Role.AGENT, message.getRole()); + assertEquals("msg-123", message.getMessageId()); + assertEquals("context-456", message.getContextId()); + assertEquals(1, message.getParts().size()); + assertTrue(message.getParts().get(0) instanceof TextPart_v0_3); + assertEquals("Hello, world!", ((TextPart_v0_3) message.getParts().get(0)).getText()); + } + + @Test + public void testOnEventWithTaskStatusUpdateEventEvent() throws Exception { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener_v0_3 listener = new SSEEventListener_v0_3( + event -> receivedEvent.set(event), + error -> {} + ); + + // Parse the message event JSON + String eventData = JsonStreamingMessages_v0_3.STREAMING_STATUS_UPDATE_EVENT.substring( + JsonStreamingMessages_v0_3.STREAMING_STATUS_UPDATE_EVENT.indexOf("{")); + + // Call onEvent method + listener.onMessage(eventData, null); + + // Verify the event was processed correctly + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent_v0_3); + TaskStatusUpdateEvent_v0_3 taskStatusUpdateEvent = (TaskStatusUpdateEvent_v0_3) receivedEvent.get(); + assertEquals("1", taskStatusUpdateEvent.getTaskId()); + assertEquals("2", taskStatusUpdateEvent.getContextId()); + assertFalse(taskStatusUpdateEvent.isFinal()); + assertEquals(TaskState_v0_3.SUBMITTED, taskStatusUpdateEvent.getStatus().state()); + } + + @Test + public void testOnEventWithTaskArtifactUpdateEventEvent() throws Exception { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener_v0_3 listener = new SSEEventListener_v0_3( + event -> receivedEvent.set(event), + error -> {} + ); + + // Parse the message event JSON + String eventData = JsonStreamingMessages_v0_3.STREAMING_ARTIFACT_UPDATE_EVENT.substring( + JsonStreamingMessages_v0_3.STREAMING_ARTIFACT_UPDATE_EVENT.indexOf("{")); + + // Call onEvent method + listener.onMessage(eventData, null); + + // Verify the event was processed correctly + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof TaskArtifactUpdateEvent_v0_3); + + TaskArtifactUpdateEvent_v0_3 taskArtifactUpdateEvent = (TaskArtifactUpdateEvent_v0_3) receivedEvent.get(); + assertEquals("1", taskArtifactUpdateEvent.getTaskId()); + assertEquals("2", taskArtifactUpdateEvent.getContextId()); + assertFalse(taskArtifactUpdateEvent.isAppend()); + assertTrue(taskArtifactUpdateEvent.isLastChunk()); + Artifact_v0_3 artifact = taskArtifactUpdateEvent.getArtifact(); + assertEquals("artifact-1", artifact.artifactId()); + assertEquals(1, artifact.parts().size()); + assertEquals(Part_v0_3.Kind.TEXT, artifact.parts().get(0).getKind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) artifact.parts().get(0)).getText()); + } + + @Test + public void testOnEventWithError() throws Exception { + // Set up event handler + AtomicReference receivedError = new AtomicReference<>(); + SSEEventListener_v0_3 listener = new SSEEventListener_v0_3( + event -> {}, + error -> receivedError.set(error) + ); + + // Parse the error event JSON + String eventData = JsonStreamingMessages_v0_3.STREAMING_ERROR_EVENT.substring( + JsonStreamingMessages_v0_3.STREAMING_ERROR_EVENT.indexOf("{")); + + // Call onEvent method + listener.onMessage(eventData, null); + + // Verify the error was processed correctly + assertNotNull(receivedError.get()); + assertInstanceOf(JSONRPCError_v0_3.class, receivedError.get()); + JSONRPCError_v0_3 jsonrpcError = (JSONRPCError_v0_3) receivedError.get(); + assertEquals(-32602, jsonrpcError.getCode()); + assertEquals("Invalid parameters", jsonrpcError.getMessage()); + assertEquals("Missing required field", jsonrpcError.getData()); + } + + @Test + public void testOnFailure() { + AtomicBoolean failureHandlerCalled = new AtomicBoolean(false); + SSEEventListener_v0_3 listener = new SSEEventListener_v0_3( + event -> {}, + error -> failureHandlerCalled.set(true) + ); + + // Simulate a failure + CancelCapturingFuture future = new CancelCapturingFuture(); + listener.onError(new RuntimeException("Test exception"), future); + + // Verify the failure handler was called + assertTrue(failureHandlerCalled.get()); + // Verify it got cancelled + assertTrue(future.cancelHandlerCalled); + } + + @Test + public void testFinalTaskStatusUpdateEventCancels() { + TaskStatusUpdateEvent_v0_3 tsue = new TaskStatusUpdateEvent_v0_3.Builder() + .taskId("1234") + .contextId("xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .isFinal(true) + .build(); + + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener_v0_3 listener = new SSEEventListener_v0_3( + event -> receivedEvent.set(event), + error -> {} + ); + + + } + + @Test + public void testOnEventWithFinalTaskStatusUpdateEventEventCancels() throws Exception { + // Set up event handler + AtomicReference receivedEvent = new AtomicReference<>(); + SSEEventListener_v0_3 listener = new SSEEventListener_v0_3( + event -> receivedEvent.set(event), + error -> {} + ); + + // Parse the message event JSON + String eventData = JsonStreamingMessages_v0_3.STREAMING_STATUS_UPDATE_EVENT_FINAL.substring( + JsonStreamingMessages_v0_3.STREAMING_STATUS_UPDATE_EVENT_FINAL.indexOf("{")); + + // Call onEvent method + CancelCapturingFuture future = new CancelCapturingFuture(); + listener.onMessage(eventData, future); + + // Verify the event was processed correctly + assertNotNull(receivedEvent.get()); + assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent_v0_3); + TaskStatusUpdateEvent_v0_3 taskStatusUpdateEvent = (TaskStatusUpdateEvent_v0_3) receivedEvent.get(); + assertEquals("1", taskStatusUpdateEvent.getTaskId()); + assertEquals("2", taskStatusUpdateEvent.getContextId()); + assertTrue(taskStatusUpdateEvent.isFinal()); + assertEquals(TaskState_v0_3.COMPLETED, taskStatusUpdateEvent.getStatus().state()); + + assertTrue(future.cancelHandlerCalled); + } + + + private static class CancelCapturingFuture implements Future { + private boolean cancelHandlerCalled; + + public CancelCapturingFuture() { + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + cancelHandlerCalled = true; + return true; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return false; + } + + @Override + public Void get() throws InterruptedException, ExecutionException { + return null; + } + + @Override + public Void get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return null; + } + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/rest/pom.xml b/compat-0.3/client/transport/rest/pom.xml new file mode 100644 index 000000000..2539152af --- /dev/null +++ b/compat-0.3/client/transport/rest/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../../.. + + a2a-java-sdk-compat-0.3-client-transport-rest + jar + + Java SDK A2A Compat 0.3 Client Transport: JSON+HTTP/REST + Java SDK for the Agent2Agent Protocol (A2A) - JSON+HTTP/REST Client Transport + + + + ${project.groupId} + a2a-java-sdk-common + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec-grpc + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-spi + + + ${project.groupId} + a2a-java-sdk-compat-0.3-http-client + + + com.google.protobuf + protobuf-java-util + + + org.junit.jupiter + junit-jupiter-api + test + + + + org.mock-server + mockserver-netty + test + + + org.slf4j + slf4j-jdk14 + test + + + + \ No newline at end of file diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java new file mode 100644 index 000000000..8e77af39f --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java @@ -0,0 +1,64 @@ +package org.a2aproject.sdk.compat03.client.transport.rest; + +import com.google.gson.JsonObject; +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AuthenticatedExtendedCardNotConfiguredError_v0_3; +import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Utility class to A2AHttpResponse to appropriate A2A error types + */ +public class RestErrorMapper_v0_3 { + + public static A2AClientException_v0_3 mapRestError(A2AHttpResponse_v0_3 response) { + return RestErrorMapper_v0_3.mapRestError(response.body(), response.status()); + } + + public static A2AClientException_v0_3 mapRestError(String body, int code) { + try { + if (body != null && !body.isBlank()) { + JsonObject node = JsonUtil_v0_3.fromJson(body, JsonObject.class); + String className = node.has("error") ? node.get("error").getAsString() : ""; + String errorMessage = node.has("message") ? node.get("message").getAsString() : ""; + return mapRestError(className, errorMessage, code); + } + return mapRestError("", "", code); + } catch (JsonProcessingException_v0_3 ex) { + Logger.getLogger(RestErrorMapper_v0_3.class.getName()).log(Level.SEVERE, null, ex); + return new A2AClientException_v0_3("Failed to parse error response: " + ex.getMessage()); + } + } + + public static A2AClientException_v0_3 mapRestError(String className, String errorMessage, int code) { + return switch (className) { + case "org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3" -> new A2AClientException_v0_3(errorMessage, new TaskNotFoundError_v0_3()); + case "org.a2aproject.sdk.compat03.spec.AuthenticatedExtendedCardNotConfiguredError_v0_3" -> new A2AClientException_v0_3(errorMessage, new AuthenticatedExtendedCardNotConfiguredError_v0_3(null, errorMessage, null)); + case "org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3" -> new A2AClientException_v0_3(errorMessage, new ContentTypeNotSupportedError_v0_3(null, null, errorMessage)); + case "org.a2aproject.sdk.compat03.spec.InternalError_v0_3" -> new A2AClientException_v0_3(errorMessage, new InternalError_v0_3(errorMessage)); + case "org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3" -> new A2AClientException_v0_3(errorMessage, new InvalidAgentResponseError_v0_3(null, null, errorMessage)); + case "org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3" -> new A2AClientException_v0_3(errorMessage, new InvalidParamsError_v0_3()); + case "org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3" -> new A2AClientException_v0_3(errorMessage, new InvalidRequestError_v0_3()); + case "org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3" -> new A2AClientException_v0_3(errorMessage, new JSONParseError_v0_3()); + case "org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3" -> new A2AClientException_v0_3(errorMessage, new MethodNotFoundError_v0_3()); + case "org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3" -> new A2AClientException_v0_3(errorMessage, new PushNotificationNotSupportedError_v0_3()); + case "org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3" -> new A2AClientException_v0_3(errorMessage, new TaskNotCancelableError_v0_3()); + case "org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3" -> new A2AClientException_v0_3(errorMessage, new UnsupportedOperationError_v0_3()); + default -> new A2AClientException_v0_3(errorMessage); + }; + } +} diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfigBuilder_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfigBuilder_v0_3.java new file mode 100644 index 000000000..13794ee3f --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfigBuilder_v0_3.java @@ -0,0 +1,28 @@ +package org.a2aproject.sdk.compat03.client.transport.rest; + +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfigBuilder_v0_3; +import org.jspecify.annotations.Nullable; + +public class RestTransportConfigBuilder_v0_3 extends ClientTransportConfigBuilder_v0_3 { + + private @Nullable A2AHttpClient_v0_3 httpClient; + + public RestTransportConfigBuilder_v0_3 httpClient(A2AHttpClient_v0_3 httpClient) { + this.httpClient = httpClient; + return this; + } + + @Override + public RestTransportConfig_v0_3 build() { + // No HTTP client provided, fallback to the default one (JDK-based implementation) + if (httpClient == null) { + httpClient = new JdkA2AHttpClient_v0_3(); + } + + RestTransportConfig_v0_3 config = new RestTransportConfig_v0_3(httpClient); + config.setInterceptors(this.interceptors); + return config; + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfig_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfig_v0_3.java new file mode 100644 index 000000000..0d6b1f859 --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfig_v0_3.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.client.transport.rest; + +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfig_v0_3; +import org.jspecify.annotations.Nullable; + +public class RestTransportConfig_v0_3 extends ClientTransportConfig_v0_3 { + + private final @Nullable A2AHttpClient_v0_3 httpClient; + + public RestTransportConfig_v0_3() { + this.httpClient = null; + } + + public RestTransportConfig_v0_3(A2AHttpClient_v0_3 httpClient) { + this.httpClient = httpClient; + } + + public @Nullable A2AHttpClient_v0_3 getHttpClient() { + return httpClient; + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportProvider_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportProvider_v0_3.java new file mode 100644 index 000000000..87dcdf5ce --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportProvider_v0_3.java @@ -0,0 +1,29 @@ +package org.a2aproject.sdk.compat03.client.transport.rest; + +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; + +public class RestTransportProvider_v0_3 implements ClientTransportProvider_v0_3 { + + @Override + public String getTransportProtocol() { + return TransportProtocol_v0_3.HTTP_JSON.asString(); + } + + @Override + public RestTransport_v0_3 create(RestTransportConfig_v0_3 clientTransportConfig, AgentCard_v0_3 agentCard, String agentUrl) throws A2AClientException_v0_3 { + RestTransportConfig_v0_3 transportConfig = clientTransportConfig; + if (transportConfig == null) { + transportConfig = new RestTransportConfig_v0_3(new JdkA2AHttpClient_v0_3()); + } + return new RestTransport_v0_3(clientTransportConfig.getHttpClient(), agentCard, agentUrl, transportConfig.getInterceptors()); + } + + @Override + public Class getTransportProtocolClass() { + return RestTransport_v0_3.class; + } +} diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java new file mode 100644 index 000000000..656da61ee --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java @@ -0,0 +1,401 @@ +package org.a2aproject.sdk.compat03.client.transport.rest; + +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.MessageOrBuilder; +import com.google.protobuf.util.JsonFormat; +import org.a2aproject.sdk.compat03.client.http.A2ACardResolver_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.sse.RestSSEEventListener_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallInterceptor_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.PayloadAndHeaders_v0_3; +import org.a2aproject.sdk.compat03.grpc.CancelTaskRequest; +import org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.compat03.grpc.GetTaskRequest; +import org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest; +import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetAuthenticatedExtendedCardRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskResubscriptionRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.grpc.utils.ProtoUtils_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import org.jspecify.annotations.Nullable; + +public class RestTransport_v0_3 implements ClientTransport_v0_3 { + + private static final Logger log = Logger.getLogger(RestTransport_v0_3.class.getName()); + private final A2AHttpClient_v0_3 httpClient; + private final String agentUrl; + private @Nullable final List interceptors; + private AgentCard_v0_3 agentCard; + private boolean needsExtendedCard = false; + + public RestTransport_v0_3(AgentCard_v0_3 agentCard) { + this(null, agentCard, agentCard.url(), null); + } + + public RestTransport_v0_3(@Nullable A2AHttpClient_v0_3 httpClient, AgentCard_v0_3 agentCard, + String agentUrl, @Nullable List interceptors) { + this.httpClient = httpClient == null ? new JdkA2AHttpClient_v0_3() : httpClient; + this.agentCard = agentCard; + this.agentUrl = agentUrl.endsWith("/") ? agentUrl.substring(0, agentUrl.length() - 1) : agentUrl; + this.interceptors = interceptors; + } + + @Override + public EventKind_v0_3 sendMessage(MessageSendParams_v0_3 messageSendParams, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("messageSendParams", messageSendParams); + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.Builder builder = org.a2aproject.sdk.compat03.grpc.SendMessageRequest.newBuilder(ProtoUtils_v0_3.ToProto.sendMessageRequest(messageSendParams)); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SendMessageRequest_v0_3.METHOD, builder, agentCard, context); + try { + String httpResponseBody = sendPostRequest(agentUrl + "/v1/message:send", payloadAndHeaders); + org.a2aproject.sdk.compat03.grpc.SendMessageResponse.Builder responseBuilder = org.a2aproject.sdk.compat03.grpc.SendMessageResponse.newBuilder(); + JsonFormat.parser().merge(httpResponseBody, responseBuilder); + if (responseBuilder.hasMsg()) { + return ProtoUtils_v0_3.FromProto.message(responseBuilder.getMsg()); + } + if (responseBuilder.hasTask()) { + return ProtoUtils_v0_3.FromProto.task(responseBuilder.getTask()); + } + throw new A2AClientException_v0_3("Failed to send message, wrong response:" + httpResponseBody); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to send message: " + e, e); + } + } + + @Override + public void sendMessageStreaming(MessageSendParams_v0_3 messageSendParams, Consumer eventConsumer, Consumer errorConsumer, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", messageSendParams); + checkNotNullParam("eventConsumer", eventConsumer); + checkNotNullParam("messageSendParams", messageSendParams); + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.Builder builder = org.a2aproject.sdk.compat03.grpc.SendMessageRequest.newBuilder(ProtoUtils_v0_3.ToProto.sendMessageRequest(messageSendParams)); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SendStreamingMessageRequest_v0_3.METHOD, + builder, agentCard, context); + AtomicReference> ref = new AtomicReference<>(); + RestSSEEventListener_v0_3 sseEventListener = new RestSSEEventListener_v0_3(eventConsumer, errorConsumer); + try { + A2AHttpClient_v0_3.PostBuilder postBuilder = createPostBuilder(agentUrl + "/v1/message:stream", payloadAndHeaders); + ref.set(postBuilder.postAsyncSSE( + msg -> sseEventListener.onMessage(msg, ref.get()), + throwable -> sseEventListener.onError(throwable, ref.get()), + () -> { + // We don't need to do anything special on completion + })); + } catch (IOException e) { + throw new A2AClientException_v0_3("Failed to send streaming message request: " + e, e); + } catch (InterruptedException e) { + throw new A2AClientException_v0_3("Send streaming message request timed out: " + e, e); + } catch (JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to process JSON for streaming message request: " + e, e); + } + } + + @Override + public Task_v0_3 getTask(TaskQueryParams_v0_3 taskQueryParams, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("taskQueryParams", taskQueryParams); + GetTaskRequest.Builder builder = GetTaskRequest.newBuilder(); + builder.setName("tasks/" + taskQueryParams.id()); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetTaskRequest_v0_3.METHOD, builder, + agentCard, context); + try { + String url; + if (taskQueryParams.historyLength() > 0) { + url = agentUrl + String.format("/v1/tasks/%1s?historyLength=%2d", taskQueryParams.id(), taskQueryParams.historyLength()); + } else { + url = agentUrl + String.format("/v1/tasks/%1s", taskQueryParams.id()); + } + A2AHttpClient_v0_3.GetBuilder getBuilder = httpClient.createGet().url(url); + if (payloadAndHeaders.getHeaders() != null) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + getBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + A2AHttpResponse_v0_3 response = getBuilder.get(); + if (!response.success()) { + throw RestErrorMapper_v0_3.mapRestError(response); + } + String httpResponseBody = response.body(); + org.a2aproject.sdk.compat03.grpc.Task.Builder responseBuilder = org.a2aproject.sdk.compat03.grpc.Task.newBuilder(); + JsonFormat.parser().merge(httpResponseBody, responseBuilder); + return ProtoUtils_v0_3.FromProto.task(responseBuilder); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException e) { + throw new A2AClientException_v0_3("Failed to get task: " + e, e); + } + } + + @Override + public Task_v0_3 cancelTask(TaskIdParams_v0_3 taskIdParams, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("taskIdParams", taskIdParams); + CancelTaskRequest.Builder builder = CancelTaskRequest.newBuilder(); + builder.setName("tasks/" + taskIdParams.id()); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(CancelTaskRequest_v0_3.METHOD, builder, + agentCard, context); + try { + String httpResponseBody = sendPostRequest(agentUrl + String.format("/v1/tasks/%1s:cancel", taskIdParams.id()), payloadAndHeaders); + org.a2aproject.sdk.compat03.grpc.Task.Builder responseBuilder = org.a2aproject.sdk.compat03.grpc.Task.newBuilder(); + JsonFormat.parser().merge(httpResponseBody, responseBuilder); + return ProtoUtils_v0_3.FromProto.task(responseBuilder); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to cancel task: " + e, e); + } + } + + @Override + public TaskPushNotificationConfig_v0_3 setTaskPushNotificationConfiguration(TaskPushNotificationConfig_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + CreateTaskPushNotificationConfigRequest.Builder builder = CreateTaskPushNotificationConfigRequest.newBuilder(); + builder.setConfig(ProtoUtils_v0_3.ToProto.taskPushNotificationConfig(request)) + .setParent("tasks/" + request.taskId()); + if (request.pushNotificationConfig().id() != null) { + builder.setConfigId(request.pushNotificationConfig().id()); + } + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(SetTaskPushNotificationConfigRequest_v0_3.METHOD, builder, agentCard, context); + try { + String httpResponseBody = sendPostRequest(agentUrl + String.format("/v1/tasks/%1s/pushNotificationConfigs", request.taskId()), payloadAndHeaders); + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder responseBuilder = org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.newBuilder(); + JsonFormat.parser().merge(httpResponseBody, responseBuilder); + return ProtoUtils_v0_3.FromProto.taskPushNotificationConfig(responseBuilder); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to set task push notification config: " + e, e); + } + } + + @Override + public TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + // When configId is not specified, use taskId as the default configId + String configId = request.pushNotificationConfigId() != null ? request.pushNotificationConfigId() : request.id(); + GetTaskPushNotificationConfigRequest.Builder builder = GetTaskPushNotificationConfigRequest.newBuilder(); + builder.setName(String.format("/tasks/%1s/pushNotificationConfigs/%2s", request.id(), configId)); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetTaskPushNotificationConfigRequest_v0_3.METHOD, builder, + agentCard, context); + try { + String url = agentUrl + String.format("/v1/tasks/%1s/pushNotificationConfigs/%2s", request.id(), configId); + A2AHttpClient_v0_3.GetBuilder getBuilder = httpClient.createGet().url(url); + if (payloadAndHeaders.getHeaders() != null) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + getBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + A2AHttpResponse_v0_3 response = getBuilder.get(); + if (!response.success()) { + throw RestErrorMapper_v0_3.mapRestError(response); + } + String httpResponseBody = response.body(); + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder responseBuilder = org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.newBuilder(); + JsonFormat.parser().merge(httpResponseBody, responseBuilder); + return ProtoUtils_v0_3.FromProto.taskPushNotificationConfig(responseBuilder); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException e) { + throw new A2AClientException_v0_3("Failed to get push notifications: " + e, e); + } + } + + @Override + public List listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + ListTaskPushNotificationConfigRequest.Builder builder = ListTaskPushNotificationConfigRequest.newBuilder(); + builder.setParent(String.format("/tasks/%1s/pushNotificationConfigs", request.id())); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(ListTaskPushNotificationConfigRequest_v0_3.METHOD, builder, + agentCard, context); + try { + String url = agentUrl + String.format("/v1/tasks/%1s/pushNotificationConfigs", request.id()); + A2AHttpClient_v0_3.GetBuilder getBuilder = httpClient.createGet().url(url); + if (payloadAndHeaders.getHeaders() != null) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + getBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + A2AHttpResponse_v0_3 response = getBuilder.get(); + if (!response.success()) { + throw RestErrorMapper_v0_3.mapRestError(response); + } + String httpResponseBody = response.body(); + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.Builder responseBuilder = org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.newBuilder(); + JsonFormat.parser().merge(httpResponseBody, responseBuilder); + return ProtoUtils_v0_3.FromProto.listTaskPushNotificationConfigParams(responseBuilder); + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException e) { + throw new A2AClientException_v0_3("Failed to list push notifications: " + e, e); + } + } + + @Override + public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder builder = org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(DeleteTaskPushNotificationConfigRequest_v0_3.METHOD, builder, + agentCard, context); + try { + String url = agentUrl + String.format("/v1/tasks/%1s/pushNotificationConfigs/%2s", request.id(), request.pushNotificationConfigId()); + A2AHttpClient_v0_3.DeleteBuilder deleteBuilder = httpClient.createDelete().url(url); + if (payloadAndHeaders.getHeaders() != null) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + deleteBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + A2AHttpResponse_v0_3 response = deleteBuilder.delete(); + if (!response.success()) { + throw RestErrorMapper_v0_3.mapRestError(response); + } + } catch (A2AClientException_v0_3 e) { + throw e; + } catch (IOException | InterruptedException e) { + throw new A2AClientException_v0_3("Failed to delete push notification config: " + e, e); + } + } + + @Override + public void resubscribe(TaskIdParams_v0_3 request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + checkNotNullParam("request", request); + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.Builder builder = org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.newBuilder(); + builder.setName("tasks/" + request.id()); + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(TaskResubscriptionRequest_v0_3.METHOD, builder, + agentCard, context); + AtomicReference> ref = new AtomicReference<>(); + RestSSEEventListener_v0_3 sseEventListener = new RestSSEEventListener_v0_3(eventConsumer, errorConsumer); + try { + String url = agentUrl + String.format("/v1/tasks/%1s:subscribe", request.id()); + A2AHttpClient_v0_3.PostBuilder postBuilder = createPostBuilder(url, payloadAndHeaders); + ref.set(postBuilder.postAsyncSSE( + msg -> sseEventListener.onMessage(msg, ref.get()), + throwable -> sseEventListener.onError(throwable, ref.get()), + () -> { + // We don't need to do anything special on completion + })); + } catch (IOException e) { + throw new A2AClientException_v0_3("Failed to send streaming message request: " + e, e); + } catch (InterruptedException e) { + throw new A2AClientException_v0_3("Send streaming message request timed out: " + e, e); + } catch (JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to process JSON for streaming message request: " + e, e); + } + } + + @Override + public AgentCard_v0_3 getAgentCard(@Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { + A2ACardResolver_v0_3 resolver; + try { + if (agentCard == null) { + resolver = new A2ACardResolver_v0_3(httpClient, agentUrl, null, getHttpHeaders(context)); + agentCard = resolver.getAgentCard(); + needsExtendedCard = agentCard.supportsAuthenticatedExtendedCard(); + } + if (!needsExtendedCard) { + return agentCard; + } + PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetAuthenticatedExtendedCardRequest_v0_3.METHOD, null, + agentCard, context); + String url = agentUrl + String.format("/v1/card"); + A2AHttpClient_v0_3.GetBuilder getBuilder = httpClient.createGet().url(url); + if (payloadAndHeaders.getHeaders() != null) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + getBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + A2AHttpResponse_v0_3 response = getBuilder.get(); + if (!response.success()) { + throw RestErrorMapper_v0_3.mapRestError(response); + } + String httpResponseBody = response.body(); + agentCard = JsonUtil_v0_3.fromJson(httpResponseBody, AgentCard_v0_3.class); + needsExtendedCard = false; + return agentCard; + } catch (IOException | InterruptedException | JsonProcessingException_v0_3 e) { + throw new A2AClientException_v0_3("Failed to get authenticated extended agent card: " + e, e); + } catch (A2AClientError_v0_3 e) { + throw new A2AClientException_v0_3("Failed to get agent card: " + e, e); + } + } + + @Override + public void close() { + // no-op + } + + private PayloadAndHeaders_v0_3 applyInterceptors(String methodName, @Nullable MessageOrBuilder payload, + AgentCard_v0_3 agentCard, @Nullable ClientCallContext_v0_3 clientCallContext) { + PayloadAndHeaders_v0_3 payloadAndHeaders = new PayloadAndHeaders_v0_3(payload, getHttpHeaders(clientCallContext)); + if (interceptors != null && !interceptors.isEmpty()) { + for (ClientCallInterceptor_v0_3 interceptor : interceptors) { + payloadAndHeaders = interceptor.intercept(methodName, payloadAndHeaders.getPayload(), + payloadAndHeaders.getHeaders(), agentCard, clientCallContext); + } + } + return payloadAndHeaders; + } + + private String sendPostRequest(String url, PayloadAndHeaders_v0_3 payloadAndHeaders) throws IOException, InterruptedException, JsonProcessingException_v0_3 { + A2AHttpClient_v0_3.PostBuilder builder = createPostBuilder(url, payloadAndHeaders); + A2AHttpResponse_v0_3 response = builder.post(); + if (!response.success()) { + log.fine("Error on POST processing " + JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); + throw RestErrorMapper_v0_3.mapRestError(response); + } + return response.body(); + } + + private A2AHttpClient_v0_3.PostBuilder createPostBuilder(String url, PayloadAndHeaders_v0_3 payloadAndHeaders) throws JsonProcessingException_v0_3, InvalidProtocolBufferException { + log.fine(JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); + A2AHttpClient_v0_3.PostBuilder postBuilder = httpClient.createPost() + .url(url) + .addHeader("Content-Type", "application/json") + .body(JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); + + if (payloadAndHeaders.getHeaders() != null) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + postBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + return postBuilder; + } + + private Map getHttpHeaders(@Nullable ClientCallContext_v0_3 context) { + return context != null ? context.getHeaders() : Collections.emptyMap(); + } +} diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/package-info.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/package-info.java new file mode 100644 index 000000000..746922520 --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client.transport.rest; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/sse/RestSSEEventListener_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/sse/RestSSEEventListener_v0_3.java new file mode 100644 index 000000000..e7f96c539 --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/sse/RestSSEEventListener_v0_3.java @@ -0,0 +1,67 @@ +package org.a2aproject.sdk.compat03.client.transport.rest.sse; + +import java.util.concurrent.Future; +import java.util.function.Consumer; +import java.util.logging.Logger; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; +import org.a2aproject.sdk.compat03.client.transport.rest.RestErrorMapper_v0_3; +import org.a2aproject.sdk.compat03.grpc.StreamResponse; +import org.a2aproject.sdk.compat03.grpc.utils.ProtoUtils_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.jspecify.annotations.Nullable; + +public class RestSSEEventListener_v0_3 { + + private static final Logger log = Logger.getLogger(RestSSEEventListener_v0_3.class.getName()); + private final Consumer eventHandler; + private final Consumer errorHandler; + + public RestSSEEventListener_v0_3(Consumer eventHandler, + Consumer errorHandler) { + this.eventHandler = eventHandler; + this.errorHandler = errorHandler; + } + + public void onMessage(String message, @Nullable Future completableFuture) { + try { + log.fine("Streaming message received: " + message); + org.a2aproject.sdk.compat03.grpc.StreamResponse.Builder builder = org.a2aproject.sdk.compat03.grpc.StreamResponse.newBuilder(); + JsonFormat.parser().merge(message, builder); + handleMessage(builder.build()); + } catch (InvalidProtocolBufferException e) { + errorHandler.accept(RestErrorMapper_v0_3.mapRestError(message, 500)); + } + } + + public void onError(Throwable throwable, @Nullable Future future) { + if (errorHandler != null) { + errorHandler.accept(throwable); + } + if (future != null) { + future.cancel(true); // close SSE channel + } + } + + private void handleMessage(StreamResponse response) { + StreamingEventKind_v0_3 event; + switch (response.getPayloadCase()) { + case MSG -> + event = ProtoUtils_v0_3.FromProto.message(response.getMsg()); + case TASK -> + event = ProtoUtils_v0_3.FromProto.task(response.getTask()); + case STATUS_UPDATE -> + event = ProtoUtils_v0_3.FromProto.taskStatusUpdateEvent(response.getStatusUpdate()); + case ARTIFACT_UPDATE -> + event = ProtoUtils_v0_3.FromProto.taskArtifactUpdateEvent(response.getArtifactUpdate()); + default -> { + log.warning("Invalid stream response " + response.getPayloadCase()); + errorHandler.accept(new IllegalStateException("Invalid stream response from server: " + response.getPayloadCase())); + return; + } + } + eventHandler.accept(event); + } + +} diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/sse/package-info.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/sse/package-info.java new file mode 100644 index 000000000..38dfbf147 --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/sse/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client.transport.rest.sse; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/client/transport/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 b/compat-0.3/client/transport/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 new file mode 100644 index 000000000..53dac6e73 --- /dev/null +++ b/compat-0.3/client/transport/rest/src/main/resources/META-INF/services/org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3 @@ -0,0 +1 @@ +org.a2aproject.sdk.compat03.client.transport.rest.RestTransportProvider_v0_3 \ No newline at end of file diff --git a/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/JsonRestMessages_v0_3.java b/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/JsonRestMessages_v0_3.java new file mode 100644 index 000000000..5fec20d23 --- /dev/null +++ b/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/JsonRestMessages_v0_3.java @@ -0,0 +1,654 @@ +package org.a2aproject.sdk.compat03.client.transport.rest; + +/** + * Request and response messages used by the tests. These have been created following examples from + * the A2A sample messages. + */ +public class JsonRestMessages_v0_3 { + + static final String SEND_MESSAGE_TEST_REQUEST = """ + { + "message": + { + "messageId": "message-1234", + "contextId": "context-1234", + "role": "ROLE_USER", + "content": [{ + "text": "tell me a joke" + }], + "metadata": { + } + } + }"""; + + static final String SEND_MESSAGE_TEST_RESPONSE = """ + { + "task": { + "id": "9b511af4-b27c-47fa-aecf-2a93c08a44f8", + "contextId": "context-1234", + "status": { + "state": "TASK_STATE_SUBMITTED" + }, + "history": [ + { + "messageId": "message-1234", + "contextId": "context-1234", + "taskId": "9b511af4-b27c-47fa-aecf-2a93c08a44f8", + "role": "ROLE_USER", + "content": [ + { + "text": "tell me a joke" + } + ], + "metadata": {} + } + ] + } + }"""; + + static final String CANCEL_TASK_TEST_REQUEST = """ + { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64" + }"""; + + static final String CANCEL_TASK_TEST_RESPONSE = """ + { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "TASK_STATE_CANCELLED" + }, + "metadata": {} + }"""; + + static final String GET_TASK_TEST_RESPONSE = """ + { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "TASK_STATE_COMPLETED" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "parts": [ + { + "text": "Why did the chicken cross the road? To get to the other side!" + } + ] + } + ], + "history": [ + { + "role": "ROLE_USER", + "content": [ + { + "text": "tell me a joke" + }, + { + "file": { + "file_with_uri": "file:///path/to/file.txt", + "mimeType": "text/plain" + } + }, + { + "file": { + "file_with_bytes": "aGVsbG8=", + "mimeType": "text/plain" + } + } + ], + "messageId": "message-123" + } + ], + "metadata": {} + } + """; + + static final String AGENT_CARD = """ + { + "name": "GeoSpatial Route Planner Agent", + "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", + "url": "https://georoute-agent.example.com/a2a/v1", + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + } + ], + "supportsAuthenticatedExtendedCard": false, + "protocolVersion": "0.2.5" + }"""; + + static final String AGENT_CARD_SUPPORTS_EXTENDED = """ + { + "name": "GeoSpatial Route Planner Agent", + "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", + "url": "https://georoute-agent.example.com/a2a/v1", + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + } + ], + "supportsAuthenticatedExtendedCard": true, + "protocolVersion": "0.2.5" + }"""; + + static final String AUTHENTICATION_EXTENDED_AGENT_CARD = """ + { + "name": "GeoSpatial Route Planner Agent Extended", + "description": "Extended description", + "url": "https://georoute-agent.example.com/a2a/v1", + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + }, + { + "id": "skill-extended", + "name": "Extended Skill", + "description": "This is an extended skill.", + "tags": ["extended"] + } + ], + "supportsAuthenticatedExtendedCard": true, + "protocolVersion": "0.2.5" + }"""; + + static final String SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + } + ], + "messageId": "message-1234", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + }, + } + }"""; + + static final String SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE = """ + { + "jsonrpc": "2.0", + "id": 1, + "result": { + "role": "agent", + "parts": [ + { + "kind": "text", + "text": "Why did the chicken cross the road? To get to the other side!" + } + ], + "messageId": "msg-456", + "kind": "message" + } + }"""; + + static final String SEND_MESSAGE_WITH_ERROR_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + } + ], + "messageId": "message-1234", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + }, + } + }"""; + + static final String SEND_MESSAGE_ERROR_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "error": { + "code": -32702, + "message": "Invalid parameters", + "data": "Hello world" + } + }"""; + + static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ + { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": ["jwt"] + } + } + }"""; + static final String LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ + { + "configs":[ + { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": ["jwt"] + } + } + }, + { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/5", + "pushNotificationConfig": { + "url": "https://test.com/callback" + } + } + ] + }"""; + + + static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ + { + "parent": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64", + "config": { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": [ "jwt" ] + } + } + } + }"""; + + static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ + { + "name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": ["jwt"] + } + } + }"""; + + static final String SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "analyze this image" + }, + { + "kind": "file", + "file": { + "uri": "file:///path/to/image.jpg", + "mimeType": "image/jpeg" + } + } + ], + "messageId": "message-1234-with-file", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + } + } + }"""; + + static final String SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "name": "image-analysis", + "parts": [ + { + "kind": "text", + "text": "This is an image of a cat sitting on a windowsill." + } + ] + } + ], + "metadata": {}, + "kind": "task" + } + }"""; + + static final String SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "process this data" + }, + { + "kind": "data", + "data": { + "temperature": 25.5, + "humidity": 60.2, + "location": "San Francisco", + "timestamp": "2024-01-15T10:30:00Z" + } + } + ], + "messageId": "message-1234-with-data", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + } + } + }"""; + + static final String SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "name": "data-analysis", + "parts": [ + { + "kind": "text", + "text": "Processed weather data: Temperature is 25.5°C, humidity is 60.2% in San Francisco." + } + ] + } + ], + "metadata": {}, + "kind": "task" + } + }"""; + + static final String SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "analyze this data and image" + }, + { + "kind": "file", + "file": { + "bytes": "aGVsbG8=", + "name": "chart.png", + "mimeType": "image/png" + } + }, + { + "kind": "data", + "data": { + "chartType": "bar", + "dataPoints": [10, 20, 30, 40], + "labels": ["Q1", "Q2", "Q3", "Q4"] + } + } + ], + "messageId": "message-1234-with-mixed", + "contextId": "context-1234", + "kind": "message" + }, + "configuration": { + "acceptedOutputModes": ["text"], + "blocking": true + } + } + }"""; + + static final String SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE = """ + { + "jsonrpc": "2.0", + "result": { + "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "name": "mixed-analysis", + "parts": [ + { + "kind": "text", + "text": "Analyzed chart image and data: Bar chart showing quarterly data with values [10, 20, 30, 40]." + } + ] + } + ], + "metadata": {}, + "kind": "task" + } + }"""; + + public static final String SEND_MESSAGE_STREAMING_TEST_REQUEST = """ + { + "message": { + "role": "ROLE_USER", + "content": [ + { + "text": "tell me some jokes" + } + ], + "messageId": "message-1234", + "contextId": "context-1234" + }, + "configuration": { + "acceptedOutputModes": ["text"] + } + }"""; + static final String SEND_MESSAGE_STREAMING_TEST_RESPONSE + = "event: message\n" + + "data: {\"task\":{\"id\":\"2\",\"contextId\":\"context-1234\",\"status\":{\"state\":\"TASK_STATE_SUBMITTED\"},\"artifacts\":[{\"artifactId\":\"artifact-1\",\"name\":\"joke\",\"parts\":[{\"text\":\"Why did the chicken cross the road? To get to the other side!\"}]}],\"metadata\":{}}}\n\n"; + + static final String TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE + = "event: message\n" + + "data: {\"task\":{\"id\":\"2\",\"contextId\":\"context-1234\",\"status\":{\"state\":\"TASK_STATE_COMPLETED\"},\"artifacts\":[{\"artifactId\":\"artifact-1\",\"name\":\"joke\",\"parts\":[{\"text\":\"Why did the chicken cross the road? To get to the other side!\"}]}],\"metadata\":{}}}\n\n"; + public static final String TASK_RESUBSCRIPTION_TEST_REQUEST = """ + { + "jsonrpc": "2.0", + "method": "tasks/resubscribe", + "params": { + "id": "task-1234" + } + }"""; +} diff --git a/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3_Test.java b/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3_Test.java new file mode 100644 index 000000000..4d6b3b5c2 --- /dev/null +++ b/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3_Test.java @@ -0,0 +1,452 @@ +package org.a2aproject.sdk.compat03.client.transport.rest; + + +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.CANCEL_TASK_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.CANCEL_TASK_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.GET_TASK_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.SEND_MESSAGE_STREAMING_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.SEND_MESSAGE_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.SEND_MESSAGE_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.SEND_MESSAGE_STREAMING_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; +import static org.a2aproject.sdk.compat03.client.transport.rest.JsonRestMessages_v0_3.TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE; +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.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.FilePart_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithBytes_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithUri_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendConfiguration_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3.Kind; +import org.a2aproject.sdk.compat03.spec.PushNotificationAuthenticationInfo_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.logging.Logger; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.matchers.MatchType; +import org.mockserver.model.JsonBody; + +public class RestTransport_v0_3_Test { + + private static final Logger log = Logger.getLogger(RestTransport_v0_3_Test.class.getName()); + private ClientAndServer server; + private static final AgentCard_v0_3 CARD = new AgentCard_v0_3.Builder() + .name("Hello World Agent") + .description("Just a hello world agent") + .url("http://localhost:4001") + .version("1.0.0") + .documentationUrl("http://example.com/docs") + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(true) + .pushNotifications(true) + .stateTransitionHistory(true) + .build()) + .defaultInputModes(Collections.singletonList("text")) + .defaultOutputModes(Collections.singletonList("text")) + .skills(Collections.singletonList(new AgentSkill_v0_3.Builder() + .id("hello_world") + .name("Returns hello world") + .description("just returns hello world") + .tags(Collections.singletonList("hello world")) + .examples(List.of("hi", "hello world")) + .build())) + .protocolVersion("0.3.0") + .build(); + + @BeforeEach + public void setUp() throws IOException { + server = new ClientAndServer(4001); + } + + @AfterEach + public void tearDown() { + server.stop(); + } + + public RestTransport_v0_3_Test() { + } + + /** + * Test of sendMessage method, of class JSONRestTransport. + */ + @Test + public void testSendMessage() throws Exception { + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("tell me a joke"))) + .contextId("context-1234") + .messageId("message-1234") + .taskId("") + .build(); + this.server.when( + request() + .withMethod("POST") + .withPath("/v1/message:send") + .withBody(JsonBody.json(SEND_MESSAGE_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + ) + .respond( + response() + .withStatusCode(200) + .withBody(SEND_MESSAGE_TEST_RESPONSE) + ); + MessageSendParams_v0_3 messageSendParams = new MessageSendParams_v0_3(message, null, null); + ClientCallContext_v0_3 context = null; + + RestTransport_v0_3 instance = new RestTransport_v0_3(CARD); + EventKind_v0_3 result = instance.sendMessage(messageSendParams, context); + assertEquals("task", result.getKind()); + Task_v0_3 task = (Task_v0_3) result; + assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", task.getId()); + assertEquals("context-1234", task.getContextId()); + assertEquals(TaskState_v0_3.SUBMITTED, task.getStatus().state()); + assertNull(task.getStatus().message()); + assertNull(task.getMetadata()); + assertEquals(true, task.getArtifacts().isEmpty()); + assertEquals(1, task.getHistory().size()); + Message_v0_3 history = task.getHistory().get(0); + assertEquals("message", history.getKind()); + assertEquals(Message_v0_3.Role.USER, history.getRole()); + assertEquals("context-1234", history.getContextId()); + assertEquals("message-1234", history.getMessageId()); + assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", history.getTaskId()); + assertEquals(1, history.getParts().size()); + assertEquals(Kind.TEXT, history.getParts().get(0).getKind()); + assertEquals("tell me a joke", ((TextPart_v0_3) history.getParts().get(0)).getText()); + assertNull(history.getMetadata()); + assertNull(history.getReferenceTaskIds()); + } + + /** + * Test of cancelTask method, of class JSONRestTransport. + */ + @Test + public void testCancelTask() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/v1/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64:cancel") + .withBody(JsonBody.json(CANCEL_TASK_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + ) + .respond( + response() + .withStatusCode(200) + .withBody(CANCEL_TASK_TEST_RESPONSE) + ); + ClientCallContext_v0_3 context = null; + RestTransport_v0_3 instance = new RestTransport_v0_3(CARD); + Task_v0_3 task = instance.cancelTask(new TaskIdParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", + new HashMap<>()), context); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); + assertEquals(TaskState_v0_3.CANCELED, task.getStatus().state()); + assertNull(task.getStatus().message()); + assertNull(task.getMetadata()); + } + + /** + * Test of getTask method, of class JSONRestTransport. + */ + @Test + public void testGetTask() throws Exception { + this.server.when( + request() + .withMethod("GET") + .withPath("/v1/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64") + ) + .respond( + response() + .withStatusCode(200) + .withBody(GET_TASK_TEST_RESPONSE) + ); + ClientCallContext_v0_3 context = null; + TaskQueryParams_v0_3 request = new TaskQueryParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", 10); + RestTransport_v0_3 instance = new RestTransport_v0_3(CARD); + Task_v0_3 task = instance.getTask(request, context); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + assertNull(task.getStatus().message()); + assertNull(task.getMetadata()); + assertEquals(false, task.getArtifacts().isEmpty()); + assertEquals(1, task.getArtifacts().size()); + Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("artifact-1", artifact.artifactId()); + assertEquals("", artifact.name()); + assertEquals(false, artifact.parts().isEmpty()); + assertEquals(Kind.TEXT, artifact.parts().get(0).getKind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) artifact.parts().get(0)).getText()); + assertEquals(1, task.getHistory().size()); + Message_v0_3 history = task.getHistory().get(0); + assertEquals("message", history.getKind()); + assertEquals(Message_v0_3.Role.USER, history.getRole()); + assertEquals("message-123", history.getMessageId()); + assertEquals(3, history.getParts().size()); + assertEquals(Kind.TEXT, history.getParts().get(0).getKind()); + assertEquals("tell me a joke", ((TextPart_v0_3) history.getParts().get(0)).getText()); + assertEquals(Kind.FILE, history.getParts().get(1).getKind()); + FilePart_v0_3 part = (FilePart_v0_3) history.getParts().get(1); + assertEquals("text/plain", part.getFile().mimeType()); + assertEquals("file:///path/to/file.txt", ((FileWithUri_v0_3) part.getFile()).uri()); + part = (FilePart_v0_3) history.getParts().get(2); + assertEquals(Kind.FILE, part.getKind()); + assertEquals("text/plain", part.getFile().mimeType()); + assertEquals("hello", ((FileWithBytes_v0_3) part.getFile()).bytes()); + assertNull(history.getMetadata()); + assertNull(history.getReferenceTaskIds()); + } + + /** + * Test of sendMessageStreaming method, of class JSONRestTransport. + */ + @Test + public void testSendMessageStreaming() throws Exception { + this.server.when( + request() + .withMethod("POST") + .withPath("/v1/message:stream") + .withBody(JsonBody.json(SEND_MESSAGE_STREAMING_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + ) + .respond( + response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody(SEND_MESSAGE_STREAMING_TEST_RESPONSE) + ); + + RestTransport_v0_3 client = new RestTransport_v0_3(CARD); + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("tell me some jokes"))) + .contextId("context-1234") + .messageId("message-1234") + .build(); + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(false) + .build(); + MessageSendParams_v0_3 params = new MessageSendParams_v0_3.Builder() + .message(message) + .configuration(configuration) + .build(); + AtomicReference receivedEvent = new AtomicReference<>(); + CountDownLatch latch = new CountDownLatch(1); + Consumer eventHandler = event -> { + receivedEvent.set(event); + latch.countDown(); + }; + Consumer errorHandler = error -> { + }; + client.sendMessageStreaming(params, eventHandler, errorHandler, null); + + boolean eventReceived = latch.await(10, TimeUnit.SECONDS); + assertTrue(eventReceived); + assertNotNull(receivedEvent.get()); + assertEquals("task", receivedEvent.get().getKind()); + Task_v0_3 task = (Task_v0_3) receivedEvent.get(); + assertEquals("2", task.getId()); + } + + /** + * Test of setTaskPushNotificationConfiguration method, of class JSONRestTransport. + */ + @Test + public void testSetTaskPushNotificationConfiguration() throws Exception { + log.info("Testing setTaskPushNotificationConfiguration"); + this.server.when( + request() + .withMethod("POST") + .withPath("/v1/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs") + .withBody(JsonBody.json(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) + ) + .respond( + response() + .withStatusCode(200) + .withBody(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) + ); + RestTransport_v0_3 client = new RestTransport_v0_3(CARD); + TaskPushNotificationConfig_v0_3 pushedConfig = new TaskPushNotificationConfig_v0_3( + "de38c76d-d54c-436c-8b9f-4c2703648d64", + new PushNotificationConfig_v0_3.Builder() + .url("https://example.com/callback") + .authenticationInfo( + new PushNotificationAuthenticationInfo_v0_3(Collections.singletonList("jwt"), null)) + .build()); + TaskPushNotificationConfig_v0_3 taskPushNotificationConfig = client.setTaskPushNotificationConfiguration(pushedConfig, null); + PushNotificationConfig_v0_3 pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); + assertNotNull(pushNotificationConfig); + assertEquals("https://example.com/callback", pushNotificationConfig.url()); + PushNotificationAuthenticationInfo_v0_3 authenticationInfo = pushNotificationConfig.authentication(); + assertEquals(1, authenticationInfo.schemes().size()); + assertEquals("jwt", authenticationInfo.schemes().get(0)); + } + + /** + * Test of getTaskPushNotificationConfiguration method, of class JSONRestTransport. + */ + @Test + public void testGetTaskPushNotificationConfiguration() throws Exception { + this.server.when( + request() + .withMethod("GET") + .withPath("/v1/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10") + ) + .respond( + response() + .withStatusCode(200) + .withBody(GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) + ); + + RestTransport_v0_3 client = new RestTransport_v0_3(CARD); + TaskPushNotificationConfig_v0_3 taskPushNotificationConfig = client.getTaskPushNotificationConfiguration( + new GetTaskPushNotificationConfigParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", "10", + new HashMap<>()), null); + PushNotificationConfig_v0_3 pushNotificationConfig = taskPushNotificationConfig.pushNotificationConfig(); + assertNotNull(pushNotificationConfig); + assertEquals("https://example.com/callback", pushNotificationConfig.url()); + PushNotificationAuthenticationInfo_v0_3 authenticationInfo = pushNotificationConfig.authentication(); + assertTrue(authenticationInfo.schemes().size() == 1); + assertEquals("jwt", authenticationInfo.schemes().get(0)); + } + + /** + * Test of listTaskPushNotificationConfigurations method, of class JSONRestTransport. + */ + @Test + public void testListTaskPushNotificationConfigurations() throws Exception { + this.server.when( + request() + .withMethod("GET") + .withPath("/v1/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs") + ) + .respond( + response() + .withStatusCode(200) + .withBody(LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) + ); + + RestTransport_v0_3 client = new RestTransport_v0_3(CARD); + List taskPushNotificationConfigs = client.listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", new HashMap<>()), null); + assertEquals(2, taskPushNotificationConfigs.size()); + PushNotificationConfig_v0_3 pushNotificationConfig = taskPushNotificationConfigs.get(0).pushNotificationConfig(); + assertNotNull(pushNotificationConfig); + assertEquals("https://example.com/callback", pushNotificationConfig.url()); + assertEquals("10", pushNotificationConfig.id()); + PushNotificationAuthenticationInfo_v0_3 authenticationInfo = pushNotificationConfig.authentication(); + assertTrue(authenticationInfo.schemes().size() == 1); + assertEquals("jwt", authenticationInfo.schemes().get(0)); + assertEquals("", authenticationInfo.credentials()); + pushNotificationConfig = taskPushNotificationConfigs.get(1).pushNotificationConfig(); + assertNotNull(pushNotificationConfig); + assertEquals("https://test.com/callback", pushNotificationConfig.url()); + assertEquals("5", pushNotificationConfig.id()); + authenticationInfo = pushNotificationConfig.authentication(); + assertNull(authenticationInfo); + } + + /** + * Test of deleteTaskPushNotificationConfigurations method, of class JSONRestTransport. + */ + @Test + public void testDeleteTaskPushNotificationConfigurations() throws Exception { + log.info("Testing deleteTaskPushNotificationConfigurations"); + this.server.when( + request() + .withMethod("DELETE") + .withPath("/v1/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10") + ) + .respond( + response() + .withStatusCode(200) + ); + ClientCallContext_v0_3 context = null; + RestTransport_v0_3 instance = new RestTransport_v0_3(CARD); + instance.deleteTaskPushNotificationConfigurations(new DeleteTaskPushNotificationConfigParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", "10"), context); + } + + /** + * Test of resubscribe method, of class JSONRestTransport. + */ + @Test + public void testResubscribe() throws Exception { + log.info("Testing resubscribe"); + + this.server.when( + request() + .withMethod("POST") + .withPath("/v1/tasks/task-1234:subscribe") + ) + .respond( + response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody(TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE) + ); + + RestTransport_v0_3 client = new RestTransport_v0_3(CARD); + TaskIdParams_v0_3 taskIdParams = new TaskIdParams_v0_3("task-1234"); + + AtomicReference receivedEvent = new AtomicReference<>(); + CountDownLatch latch = new CountDownLatch(1); + Consumer eventHandler = event -> { + receivedEvent.set(event); + latch.countDown(); + }; + Consumer errorHandler = error -> {}; + client.resubscribe(taskIdParams, eventHandler, errorHandler, null); + + boolean eventReceived = latch.await(10, TimeUnit.SECONDS); + assertTrue(eventReceived); + + StreamingEventKind_v0_3 eventKind = receivedEvent.get();; + assertNotNull(eventKind); + assertInstanceOf(Task_v0_3.class, eventKind); + Task_v0_3 task = (Task_v0_3) eventKind; + assertEquals("2", task.getId()); + assertEquals("context-1234", task.getContextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + List artifacts = task.getArtifacts(); + assertEquals(1, artifacts.size()); + Artifact_v0_3 artifact = artifacts.get(0); + assertEquals("artifact-1", artifact.artifactId()); + assertEquals("joke", artifact.name()); + Part_v0_3 part = artifact.parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); + } +} diff --git a/compat-0.3/client/transport/spi/pom.xml b/compat-0.3/client/transport/spi/pom.xml new file mode 100644 index 000000000..b8e8d1730 --- /dev/null +++ b/compat-0.3/client/transport/spi/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../../.. + + a2a-java-sdk-compat-0.3-client-transport-spi + jar + + Java SDK A2A Compat 0.3 Client Transport: SPI + Java SDK for the Agent2Agent Protocol (A2A) - Client Transport SPI + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + + diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportConfigBuilder_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportConfigBuilder_v0_3.java new file mode 100644 index 000000000..645d2f209 --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportConfigBuilder_v0_3.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.client.transport.spi; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallInterceptor_v0_3; + +import java.util.ArrayList; +import java.util.List; + +public abstract class ClientTransportConfigBuilder_v0_3, + B extends ClientTransportConfigBuilder_v0_3> { + + protected List interceptors = new ArrayList<>(); + + public B addInterceptor(ClientCallInterceptor_v0_3 interceptor) { + if (interceptor != null) { + this.interceptors.add(interceptor); + } + + return (B) this; + } + + public abstract T build(); +} diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportConfig_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportConfig_v0_3.java new file mode 100644 index 000000000..f81011d1c --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportConfig_v0_3.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.client.transport.spi; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallInterceptor_v0_3; +import java.util.ArrayList; + +import java.util.List; + +/** + * Configuration for an A2A client transport. + */ +public abstract class ClientTransportConfig_v0_3 { + + protected List interceptors = new ArrayList<>(); + + public void setInterceptors(List interceptors) { + this.interceptors = new ArrayList<>(interceptors); + } + + public List getInterceptors() { + return interceptors; + } +} \ No newline at end of file diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportProvider_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportProvider_v0_3.java new file mode 100644 index 000000000..962825f40 --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransportProvider_v0_3.java @@ -0,0 +1,30 @@ +package org.a2aproject.sdk.compat03.client.transport.spi; + +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; + +/** + * Client transport provider interface. + */ +public interface ClientTransportProvider_v0_3> { + + /** + * Create a client transport. + * + * @param clientTransportConfig the client transport config to use + * @param agentCard the remote agent's agent card + * @param agentUrl the remote agent's URL + * @return the client transport + * @throws A2AClientException_v0_3 if an error occurs trying to create the client + */ + T create(C clientTransportConfig, AgentCard_v0_3 agentCard, + String agentUrl) throws A2AClientException_v0_3; + + /** + * Get the name of the client transport. + */ + String getTransportProtocol(); + + Class getTransportProtocolClass(); +} + diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransport_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransport_v0_3.java new file mode 100644 index 000000000..ddc0b920f --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/ClientTransport_v0_3.java @@ -0,0 +1,141 @@ +package org.a2aproject.sdk.compat03.client.transport.spi; + +import java.util.List; +import java.util.function.Consumer; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.jspecify.annotations.Nullable; + +/** + * Interface for a client transport. + */ +public interface ClientTransport_v0_3 { + + /** + * Send a non-streaming message request to the agent. + * + * @param request the message send parameters + * @param context optional client call context for the request (may be {@code null}) + * @return the response, either a Task or Message + * @throws A2AClientException_v0_3 if sending the message fails for any reason + */ + EventKind_v0_3 sendMessage(MessageSendParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) + throws A2AClientException_v0_3; + + /** + * Send a streaming message request to the agent and receive responses as they arrive. + * + * @param request the message send parameters + * @param eventConsumer consumer that will receive streaming events as they arrive + * @param errorConsumer consumer that will be called if an error occurs during streaming + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if setting up the streaming connection fails + */ + void sendMessageStreaming(MessageSendParams_v0_3 request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Retrieve the current state and history of a specific task. + * + * @param request the task query parameters specifying which task to retrieve + * @param context optional client call context for the request (may be {@code null}) + * @return the task + * @throws A2AClientException_v0_3 if retrieving the task fails for any reason + */ + Task_v0_3 getTask(TaskQueryParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Request the agent to cancel a specific task. + * + * @param request the task ID parameters specifying which task to cancel + * @param context optional client call context for the request (may be {@code null}) + * @return the cancelled task + * @throws A2AClientException_v0_3 if cancelling the task fails for any reason + */ + Task_v0_3 cancelTask(TaskIdParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Set or update the push notification configuration for a specific task. + * + * @param request the push notification configuration to set for the task + * @param context optional client call context for the request (may be {@code null}) + * @return the configured TaskPushNotificationConfig + * @throws A2AClientException_v0_3 if setting the task push notification configuration fails for any reason + */ + TaskPushNotificationConfig_v0_3 setTaskPushNotificationConfiguration(TaskPushNotificationConfig_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Retrieve the push notification configuration for a specific task. + * + * @param request the parameters specifying which task's notification config to retrieve + * @param context optional client call context for the request (may be {@code null}) + * @return the task push notification config + * @throws A2AClientException_v0_3 if getting the task push notification config fails for any reason + */ + TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration( + GetTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Retrieve the list of push notification configurations for a specific task. + * + * @param request the parameters specifying which task's notification configs to retrieve + * @param context optional client call context for the request (may be {@code null}) + * @return the list of task push notification configs + * @throws A2AClientException_v0_3 if getting the task push notification configs fails for any reason + */ + List listTaskPushNotificationConfigurations( + ListTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Delete the list of push notification configurations for a specific task. + * + * @param request the parameters specifying which task's notification configs to delete + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if deleting the task push notification configs fails for any reason + */ + void deleteTaskPushNotificationConfigurations( + DeleteTaskPushNotificationConfigParams_v0_3 request, + @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Reconnect to get task updates for an existing task. + * + * @param request the task ID parameters specifying which task to resubscribe to + * @param eventConsumer consumer that will receive streaming events as they arrive + * @param errorConsumer consumer that will be called if an error occurs during streaming + * @param context optional client call context for the request (may be {@code null}) + * @throws A2AClientException_v0_3 if resubscribing to the task fails for any reason + */ + void resubscribe(TaskIdParams_v0_3 request, Consumer eventConsumer, + Consumer errorConsumer, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Retrieve the AgentCard. + * + * @param context optional client call context for the request (may be {@code null}) + * @return the AgentCard + * @throws A2AClientException_v0_3 if retrieving the agent card fails for any reason + */ + AgentCard_v0_3 getAgentCard(@Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3; + + /** + * Close the transport and release any associated resources. + */ + void close(); + +} diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/ClientCallContext_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/ClientCallContext_v0_3.java new file mode 100644 index 000000000..c6cbbcdc3 --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/ClientCallContext_v0_3.java @@ -0,0 +1,27 @@ +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors; + +import java.util.Map; + +/** + * A context passed with each client call, allowing for call-specific. + * configuration and data passing. Such as authentication details or + * request deadlines. + */ +public class ClientCallContext_v0_3 { + + private final Map state; + private final Map headers; + + public ClientCallContext_v0_3(Map state, Map headers) { + this.state = state; + this.headers = headers; + } + + public Map getState() { + return state; + } + + public Map getHeaders() { + return headers; + } +} diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/ClientCallInterceptor_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/ClientCallInterceptor_v0_3.java new file mode 100644 index 000000000..fc0e76584 --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/ClientCallInterceptor_v0_3.java @@ -0,0 +1,27 @@ +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors; + +import java.util.Map; + +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.jspecify.annotations.Nullable; + +/** + * An abstract base class for client-side call interceptors. + * Interceptors can inspect and modify requests before they are sent, + * which is ideal for concerns like authentication, logging, or tracing. + */ +public abstract class ClientCallInterceptor_v0_3 { + + /** + * Intercept a client call before the request is sent. + * + * @param methodName the name of the protocol method (e.g., 'message/send') + * @param payload the request payload + * @param headers the headers to use + * @param agentCard the agent card (may be {@code null}) + * @param clientCallContext the {@code ClientCallContext} for this call (may be {@code null}) + * @return the potentially modified payload and headers + */ + public abstract PayloadAndHeaders_v0_3 intercept(String methodName, @Nullable Object payload, Map headers, + AgentCard_v0_3 agentCard, @Nullable ClientCallContext_v0_3 clientCallContext); +} diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/PayloadAndHeaders_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/PayloadAndHeaders_v0_3.java new file mode 100644 index 000000000..bc08d174c --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/PayloadAndHeaders_v0_3.java @@ -0,0 +1,25 @@ +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.jspecify.annotations.Nullable; + +public class PayloadAndHeaders_v0_3 { + + private final @Nullable Object payload; + private final Map headers; + + public PayloadAndHeaders_v0_3(@Nullable Object payload, @Nullable Map headers) { + this.payload = payload; + this.headers = headers == null ? Collections.emptyMap() : new HashMap<>(headers); + } + + public @Nullable Object getPayload() { + return payload; + } + + public Map getHeaders() { + return headers; + } +} diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java new file mode 100644 index 000000000..82d1f0739 --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java @@ -0,0 +1,71 @@ +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallInterceptor_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.PayloadAndHeaders_v0_3; +import org.a2aproject.sdk.compat03.spec.APIKeySecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.OAuth2SecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.OpenIdConnectSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.SecurityScheme_v0_3; +import org.jspecify.annotations.Nullable; + +/** + * An interceptor that automatically adds authentication details to requests + * based on the agent's security schemes and the credentials available. + */ +public class AuthInterceptor_v0_3 extends ClientCallInterceptor_v0_3 { + + private static final String BEARER_SCHEME = "bearer"; + public static final String AUTHORIZATION = "Authorization"; + private static final String BEARER = "Bearer "; + private final CredentialService_v0_3 credentialService; + + public AuthInterceptor_v0_3(final CredentialService_v0_3 credentialService) { + this.credentialService = credentialService; + } + + @Override + public PayloadAndHeaders_v0_3 intercept(String methodName, @Nullable Object payload, Map headers, + AgentCard_v0_3 agentCard, @Nullable ClientCallContext_v0_3 clientCallContext) { + Map updatedHeaders = new HashMap<>(headers == null ? new HashMap<>() : headers); + if (agentCard == null || agentCard.security() == null || agentCard.securitySchemes() == null) { + return new PayloadAndHeaders_v0_3(payload, updatedHeaders); + } + for (Map> requirement : agentCard.security()) { + for (String securitySchemeName : requirement.keySet()) { + String credential = credentialService.getCredential(securitySchemeName, clientCallContext); + if (credential != null && agentCard.securitySchemes().containsKey(securitySchemeName)) { + SecurityScheme_v0_3 securityScheme = agentCard.securitySchemes().get(securitySchemeName); + if (securityScheme == null) { + continue; + } + if (securityScheme instanceof HTTPAuthSecurityScheme_v0_3 httpAuthSecurityScheme) { + if (httpAuthSecurityScheme.getScheme().toLowerCase(Locale.ROOT).equals(BEARER_SCHEME)) { + updatedHeaders.put(AUTHORIZATION, getBearerValue(credential)); + return new PayloadAndHeaders_v0_3(payload, updatedHeaders); + } + } else if (securityScheme instanceof OAuth2SecurityScheme_v0_3 + || securityScheme instanceof OpenIdConnectSecurityScheme_v0_3) { + updatedHeaders.put(AUTHORIZATION, getBearerValue(credential)); + return new PayloadAndHeaders_v0_3(payload, updatedHeaders); + } else if (securityScheme instanceof APIKeySecurityScheme_v0_3 apiKeySecurityScheme) { + updatedHeaders.put(apiKeySecurityScheme.getName(), credential); + return new PayloadAndHeaders_v0_3(payload, updatedHeaders); + } + } + } + } + return new PayloadAndHeaders_v0_3(payload, updatedHeaders); + } + + private static String getBearerValue(String credential) { + return BEARER + credential; + } +} diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/CredentialService_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/CredentialService_v0_3.java new file mode 100644 index 000000000..05a320eb4 --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/CredentialService_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.jspecify.annotations.Nullable; + +/** + * Used to retrieve credentials. + */ +public interface CredentialService_v0_3 { + + /** + * Retrieves a credential (e.g., token) for a security scheme. + * + * @param securitySchemeName the name of the security scheme + * @param clientCallContext the client call context, which may be {@code null}. + * @return the credential or {@code null} if the credential could not be retrieved + */ + @Nullable String getCredential(String securitySchemeName, @Nullable ClientCallContext_v0_3 clientCallContext); +} diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/InMemoryContextCredentialService_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/InMemoryContextCredentialService_v0_3.java new file mode 100644 index 000000000..21f77dcc8 --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/InMemoryContextCredentialService_v0_3.java @@ -0,0 +1,55 @@ +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.jspecify.annotations.Nullable; + +/** + * A simple in-memory store for session-keyed credentials. + * This class uses the 'sessionId' from the {@code ClientCallContext} state to + * store and retrieve credentials + */ +public class InMemoryContextCredentialService_v0_3 implements CredentialService_v0_3 { + + private static final String SESSION_ID = "sessionId"; + + // maps a sessionId to a map of security scheme names to credentials + private final ConcurrentMap> credentialStore; + + public InMemoryContextCredentialService_v0_3() { + credentialStore = new ConcurrentHashMap<>(); + } + + @Override + public @Nullable String getCredential(String securitySchemeName, + @Nullable ClientCallContext_v0_3 clientCallContext) { + if (clientCallContext == null || !clientCallContext.getState().containsKey(SESSION_ID)) { + // no credential to retrieve + return null; + } + + Object sessionIdObj = clientCallContext.getState().get(SESSION_ID); + if (! (sessionIdObj instanceof String sessionId)) { + return null; + } + Map sessionCredentials = credentialStore.get(sessionId); + if (sessionCredentials == null) { + return null; + } + return sessionCredentials.get(securitySchemeName); + } + + /** + * Method to populate the in-memory credential service. + * + * @param sessionId the session ID + * @param securitySchemeName the name of the security scheme + * @param credential the credential string + */ + public void setCredential(String sessionId, String securitySchemeName, String credential) { + credentialStore.computeIfAbsent(sessionId, k -> new ConcurrentHashMap<>()).put(securitySchemeName, credential); + } +} diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/package-info.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/package-info.java new file mode 100644 index 000000000..d9805799c --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/package-info.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/package-info.java new file mode 100644 index 000000000..bda43ec7b --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/package-info.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/package-info.java new file mode 100644 index 000000000..850736146 --- /dev/null +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client.transport.spi; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3_Test.java b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3_Test.java new file mode 100644 index 000000000..fda90973d --- /dev/null +++ b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3_Test.java @@ -0,0 +1,328 @@ +package org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallInterceptor_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.PayloadAndHeaders_v0_3; +import org.a2aproject.sdk.compat03.spec.APIKeySecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.OAuth2SecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.OAuthFlows_v0_3; +import org.a2aproject.sdk.compat03.spec.OpenIdConnectSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.SecurityScheme_v0_3; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class AuthInterceptor_v0_3_Test { + + private InMemoryContextCredentialService_v0_3 credentialStore; + private AuthInterceptor_v0_3 authInterceptor; + + @BeforeEach + void setUp() { + credentialStore = new InMemoryContextCredentialService_v0_3(); + authInterceptor = new AuthInterceptor_v0_3(credentialStore); + } + + private static class HeaderInterceptor extends ClientCallInterceptor_v0_3 { + private final String headerName; + private final String headerValue; + + public HeaderInterceptor(String headerName, String headerValue) { + this.headerName = headerName; + this.headerValue = headerValue; + } + + @Override + public PayloadAndHeaders_v0_3 intercept(String methodName, Object payload, Map headers, + AgentCard_v0_3 agentCard, ClientCallContext_v0_3 clientCallContext) { + Map updatedHeaders = new HashMap<>(headers); + updatedHeaders.put(headerName, headerValue); + return new PayloadAndHeaders_v0_3(payload, updatedHeaders); + } + } + + private static class AuthTestCase { + final String url; + final String sessionId; + final String schemeName; + final String credential; + final SecurityScheme_v0_3 securityScheme; + final String expectedHeaderKey; + final String expectedHeaderValue; + + AuthTestCase(String url, String sessionId, String schemeName, String credential, + SecurityScheme_v0_3 securityScheme, String expectedHeaderKey, String expectedHeaderValue) { + this.url = url; + this.sessionId = sessionId; + this.schemeName = schemeName; + this.credential = credential; + this.securityScheme = securityScheme; + this.expectedHeaderKey = expectedHeaderKey; + this.expectedHeaderValue = expectedHeaderValue; + } + } + + @Test + public void testAPIKeySecurityScheme() { + AuthTestCase authTestCase = new AuthTestCase( + "http://agent.com/rpc", + "session-id", + APIKeySecurityScheme_v0_3.API_KEY, + "secret-api-key", + new APIKeySecurityScheme_v0_3("header", "x-api-key", "API Key authentication"), + "x-api-key", + "secret-api-key" + ); + testSecurityScheme(authTestCase); + } + + @Test + public void testOAuth2SecurityScheme() { + AuthTestCase authTestCase = new AuthTestCase( + "http://agent.com/rpc", + "session-id", + OAuth2SecurityScheme_v0_3.OAUTH2, + "secret-oauth-access-token", + new OAuth2SecurityScheme_v0_3(new OAuthFlows_v0_3.Builder().build(), "OAuth2 authentication", null), + "Authorization", + "Bearer secret-oauth-access-token" + ); + testSecurityScheme(authTestCase); + } + + @Test + public void testOidcSecurityScheme() { + AuthTestCase authTestCase = new AuthTestCase( + "http://agent.com/rpc", + "session-id", + OpenIdConnectSecurityScheme_v0_3.OPENID_CONNECT, + "secret-oidc-id-token", + new OpenIdConnectSecurityScheme_v0_3("http://provider.com/.well-known/openid-configuration", "OIDC authentication"), + "Authorization", + "Bearer secret-oidc-id-token" + ); + testSecurityScheme(authTestCase); + } + + @Test + public void testBearerSecurityScheme() { + AuthTestCase authTestCase = new AuthTestCase( + "http://agent.com/rpc", + "session-id", + "bearer", + "bearer-token-123", + new HTTPAuthSecurityScheme_v0_3(null, "bearer", "Bearer token authentication"), + "Authorization", + "Bearer bearer-token-123" + ); + testSecurityScheme(authTestCase); + } + + private void testSecurityScheme(AuthTestCase authTestCase) { + credentialStore.setCredential(authTestCase.sessionId, authTestCase.schemeName, authTestCase.credential); + + AgentCard_v0_3 agentCard = createAgentCard(authTestCase.schemeName, authTestCase.securityScheme); + Map requestPayload = Map.of("test", "payload"); + Map headers = Map.of(); + ClientCallContext_v0_3 context = new ClientCallContext_v0_3(Map.of("sessionId", authTestCase.sessionId), Map.of()); + + PayloadAndHeaders_v0_3 result = authInterceptor.intercept( + "message/send", + requestPayload, + headers, + agentCard, + context + ); + + assertEquals(requestPayload, result.getPayload()); + assertEquals(authTestCase.expectedHeaderValue, result.getHeaders().get(authTestCase.expectedHeaderKey)); + } + + @Test + void testAuthInterceptorWithoutAgentCard() { + Map requestPayload = Map.of("foo", "bar"); + Map headers = Map.of("foo", "bar"); + + PayloadAndHeaders_v0_3 result = authInterceptor.intercept( + "message/send", + requestPayload, + headers, + null, // no agent card + new ClientCallContext_v0_3(Map.of(), Map.of()) + ); + + // should be unchanged + assertEquals(requestPayload, result.getPayload()); + assertEquals(headers, result.getHeaders()); + } + + @Test + void testInMemoryContextCredentialStore() { + String sessionId = "session-id"; + String schemeName = "test-scheme"; + String credential = "test-token"; + + credentialStore.setCredential(sessionId, schemeName, credential); + ClientCallContext_v0_3 context = new ClientCallContext_v0_3(Map.of("sessionId", sessionId), Map.of()); + String retrievedCredential = credentialStore.getCredential(schemeName, context); + assertEquals(credential, retrievedCredential); + + // wrong session ID + ClientCallContext_v0_3 wrongContext = new ClientCallContext_v0_3(Map.of("sessionId", "wrong-session"), Map.of()); + retrievedCredential = credentialStore.getCredential(schemeName, wrongContext); + assertNull(retrievedCredential); + + retrievedCredential = credentialStore.getCredential(schemeName, null); + assertNull(retrievedCredential); + + // no session ID in context + ClientCallContext_v0_3 emptyContext = new ClientCallContext_v0_3(Map.of(), Map.of()); + retrievedCredential = credentialStore.getCredential(schemeName, emptyContext); + assertNull(retrievedCredential); + + String newCredential = "new-token"; + credentialStore.setCredential(sessionId, schemeName, newCredential); + retrievedCredential = credentialStore.getCredential(schemeName, context); + assertEquals(newCredential, retrievedCredential); + } + + @Test + void testCustomInterceptor() { + String headerName = "X-Test-Header"; + String headerValue = "Test-Value-123"; + HeaderInterceptor interceptor = new HeaderInterceptor(headerName, headerValue); + + Map payload = Map.of("test", "payload"); + Map headers = Map.of(); + + PayloadAndHeaders_v0_3 result = interceptor.intercept( + "message/send", + payload, + headers, + null, + null + ); + + assertEquals(payload, result.getPayload()); + assertEquals(headerValue, result.getHeaders().get(headerName)); + } + + @Test + void testAvailableSecuritySchemeNotInAgentCardSecuritySchemes() { + String schemeName = "missing"; + String sessionId = "session-id"; + String credential = "dummy-token"; + + credentialStore.setCredential(sessionId, schemeName, credential); + + // Create agent card with security requirement but no scheme definition + AgentCard_v0_3 agentCard = new AgentCard_v0_3.Builder() + .name("missing") + .description("Uses missing scheme definition") + .url("http://agent.com/rpc") + .version("1.0") + .capabilities(new AgentCapabilities_v0_3.Builder().build()) + .defaultInputModes(List.of("text")) + .defaultOutputModes(List.of("text")) + .skills(List.of()) + .security(List.of(Map.of(schemeName, List.of()))) + .securitySchemes(Map.of()) // no security schemes + .build(); + + Map requestPayload = Map.of("foo", "bar"); + Map headers = Map.of("fizz", "buzz"); + ClientCallContext_v0_3 context = new ClientCallContext_v0_3(Map.of("sessionId", sessionId), Map.of()); + + PayloadAndHeaders_v0_3 result = authInterceptor.intercept( + "message/send", + requestPayload, + headers, + agentCard, + context + ); + + assertEquals(requestPayload, result.getPayload()); + assertEquals(headers, result.getHeaders()); + } + + @Test + void testNoCredentialAvailable() { + String schemeName = "apikey"; + SecurityScheme_v0_3 securityScheme = new APIKeySecurityScheme_v0_3("header", "X-API-Key", "API Key authentication"); + AgentCard_v0_3 agentCard = createAgentCard(schemeName, securityScheme); + + Map requestPayload = Map.of("test", "payload"); + Map headers = Map.of(); + ClientCallContext_v0_3 context = new ClientCallContext_v0_3(Map.of("sessionId", "session-id"), Map.of()); + + PayloadAndHeaders_v0_3 result = authInterceptor.intercept( + "message/send", + requestPayload, + headers, + agentCard, + context + ); + + assertEquals(requestPayload, result.getPayload()); + assertEquals(headers, result.getHeaders()); // headers should be unchanged + } + + @Test + void testNoAgentCardSecuritySpecified() { + // Arrange + AgentCard_v0_3 agentCard = new AgentCard_v0_3.Builder() + .name("nosecuritybot") + .description("A bot with no security requirements") + .url("http://agent.com/rpc") + .version("1.0") + .capabilities(new AgentCapabilities_v0_3.Builder().build()) + .defaultInputModes(List.of("text")) + .defaultOutputModes(List.of("text")) + .skills(List.of()) + .security(null) // no security info + .build(); + + Map requestPayload = Map.of("test", "payload"); + Map headers = Map.of(); + ClientCallContext_v0_3 context = new ClientCallContext_v0_3(Map.of("sessionId", "session-id"), Map.of()); + + PayloadAndHeaders_v0_3 result = authInterceptor.intercept( + "message/send", + requestPayload, + headers, + agentCard, + context + ); + + assertEquals(requestPayload, result.getPayload()); + assertEquals(headers, result.getHeaders()); + } + + /** + * Helper method to create an AgentCard with specified security scheme. + */ + private AgentCard_v0_3 createAgentCard(String schemeName, SecurityScheme_v0_3 securityScheme) { + return new AgentCard_v0_3.Builder() + .name(schemeName + "bot") + .description("A bot that uses " + schemeName) + .url("http://agent.com/rpc") + .version("1.0") + .capabilities(new AgentCapabilities_v0_3.Builder().build()) + .defaultInputModes(List.of("text")) + .defaultOutputModes(List.of("text")) + .skills(List.of()) + .security(List.of(Map.of(schemeName, List.of()))) + .securitySchemes(Map.of(schemeName, securityScheme)) + .build(); + } +} diff --git a/compat-0.3/http-client/pom.xml b/compat-0.3/http-client/pom.xml new file mode 100644 index 000000000..61fb8bd3a --- /dev/null +++ b/compat-0.3/http-client/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + .. + + a2a-java-sdk-compat-0.3-http-client + + jar + + Java SDK A2A Compat 0.3 HTTP Client + Java SDK for the Agent2Agent Protocol (A2A) - HTTP Client (0.3 compat) + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + + org.junit.jupiter + junit-jupiter-api + test + + + + org.mock-server + mockserver-netty + test + + + + diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java new file mode 100644 index 000000000..af554f978 --- /dev/null +++ b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java @@ -0,0 +1,113 @@ +package org.a2aproject.sdk.compat03.client.http; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; + +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientJSONError_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.jspecify.annotations.Nullable; + +public class A2ACardResolver_v0_3 { + private final A2AHttpClient_v0_3 httpClient; + private final String url; + private final @Nullable Map authHeaders; + + private static final String DEFAULT_AGENT_CARD_PATH = "/.well-known/agent-card.json"; + + /** + * Get the agent card for an A2A agent. + * The {@code JdkA2AHttpClient} will be used to fetch the agent card. + * + * @param baseUrl the base URL for the agent whose agent card we want to retrieve + * @throws A2AClientError_v0_3 if the URL for the agent is invalid + */ + public A2ACardResolver_v0_3(String baseUrl) throws A2AClientError_v0_3 { + this(new JdkA2AHttpClient_v0_3(), baseUrl, null, null); + } + + /** + * Constructs an A2ACardResolver with a specific HTTP client and base URL. + * + * @param httpClient the http client to use + * @param baseUrl the base URL for the agent whose agent card we want to retrieve + * @throws A2AClientError_v0_3 if the URL for the agent is invalid + */ + public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl) throws A2AClientError_v0_3 { + this(httpClient, baseUrl, null, null); + } + + /** + * @param httpClient the http client to use + * @param baseUrl the base URL for the agent whose agent card we want to retrieve + * @param agentCardPath optional path to the agent card endpoint relative to the base + * agent URL, defaults to ".well-known/agent-card.json" + * @throws A2AClientError_v0_3 if the URL for the agent is invalid + */ + public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl, String agentCardPath) throws A2AClientError_v0_3 { + this(httpClient, baseUrl, agentCardPath, null); + } + + /** + * @param httpClient the http client to use + * @param baseUrl the base URL for the agent whose agent card we want to retrieve + * @param agentCardPath optional path to the agent card endpoint relative to the base + * agent URL, defaults to ".well-known/agent-card.json" + * @param authHeaders the HTTP authentication headers to use. May be {@code null} + * @throws A2AClientError_v0_3 if the URL for the agent is invalid + */ + public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl, @Nullable String agentCardPath, + @Nullable Map authHeaders) throws A2AClientError_v0_3 { + this.httpClient = httpClient; + String effectiveAgentCardPath = agentCardPath == null || agentCardPath.isEmpty() ? DEFAULT_AGENT_CARD_PATH : agentCardPath; + try { + this.url = new URI(baseUrl).resolve(effectiveAgentCardPath).toString(); + } catch (URISyntaxException e) { + throw new A2AClientError_v0_3("Invalid agent URL", e); + } + this.authHeaders = authHeaders; + } + + /** + * Get the agent card for the configured A2A agent. + * + * @return the agent card + * @throws A2AClientError_v0_3 If an HTTP error occurs fetching the card + * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema + */ + public AgentCard_v0_3 getAgentCard() throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { + A2AHttpClient_v0_3.GetBuilder builder = httpClient.createGet() + .url(url) + .addHeader("Content-Type", "application/json"); + + if (authHeaders != null) { + for (Map.Entry entry : authHeaders.entrySet()) { + builder.addHeader(entry.getKey(), entry.getValue()); + } + } + + String body; + try { + A2AHttpResponse_v0_3 response = builder.get(); + if (!response.success()) { + throw new A2AClientError_v0_3("Failed to obtain agent card: " + response.status()); + } + body = response.body(); + } catch (IOException | InterruptedException e) { + throw new A2AClientError_v0_3("Failed to obtain agent card", e); + } + + try { + return JsonUtil_v0_3.fromJson(body, AgentCard_v0_3.class); + } catch (JsonProcessingException_v0_3 e) { + throw new A2AClientJSONError_v0_3("Could not unmarshal agent card response", e); + } + + } + + +} diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpClient_v0_3.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpClient_v0_3.java new file mode 100644 index 000000000..2387e725e --- /dev/null +++ b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpClient_v0_3.java @@ -0,0 +1,42 @@ +package org.a2aproject.sdk.compat03.client.http; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +public interface A2AHttpClient_v0_3 { + + GetBuilder createGet(); + + PostBuilder createPost(); + + DeleteBuilder createDelete(); + + interface Builder> { + T url(String s); + T addHeaders(Map headers); + T addHeader(String name, String value); + } + + interface GetBuilder extends Builder { + A2AHttpResponse_v0_3 get() throws IOException, InterruptedException; + CompletableFuture getAsyncSSE( + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) throws IOException, InterruptedException; + } + + interface PostBuilder extends Builder { + PostBuilder body(String body); + A2AHttpResponse_v0_3 post() throws IOException, InterruptedException; + CompletableFuture postAsyncSSE( + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) throws IOException, InterruptedException; + } + + interface DeleteBuilder extends Builder { + A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException; + } +} diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpResponse_v0_3.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpResponse_v0_3.java new file mode 100644 index 000000000..fe082648d --- /dev/null +++ b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpResponse_v0_3.java @@ -0,0 +1,9 @@ +package org.a2aproject.sdk.compat03.client.http; + +public interface A2AHttpResponse_v0_3 { + int status(); + + boolean success(); + + String body(); +} diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java new file mode 100644 index 000000000..1a968059b --- /dev/null +++ b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java @@ -0,0 +1,316 @@ +package org.a2aproject.sdk.compat03.client.http; + +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; +import static java.net.HttpURLConnection.HTTP_MULT_CHOICE; +import static java.net.HttpURLConnection.HTTP_OK; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandler; +import java.net.http.HttpResponse.BodyHandlers; +import java.net.http.HttpResponse.BodySubscribers; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Flow; +import java.util.function.Consumer; +import org.jspecify.annotations.Nullable; + +import org.a2aproject.sdk.common.A2AErrorMessages; + +public class JdkA2AHttpClient_v0_3 implements A2AHttpClient_v0_3 { + + private final HttpClient httpClient; + + public JdkA2AHttpClient_v0_3() { + httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .followRedirects(HttpClient.Redirect.NORMAL) + .build(); + } + + @Override + public GetBuilder createGet() { + return new JdkGetBuilder(); + } + + @Override + public PostBuilder createPost() { + return new JdkPostBuilder(); + } + + @Override + public DeleteBuilder createDelete() { + return new JdkDeleteBuilder(); + } + + private abstract class JdkBuilder> implements Builder { + private String url = ""; + private Map headers = new HashMap<>(); + + @Override + public T url(String url) { + this.url = url; + return self(); + } + + @Override + public T addHeader(String name, String value) { + headers.put(name, value); + return self(); + } + + @Override + public T addHeaders(Map headers) { + if(headers != null && ! headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + addHeader(entry.getKey(), entry.getValue()); + } + } + return self(); + } + + @SuppressWarnings("unchecked") + T self() { + return (T) this; + } + + protected HttpRequest.Builder createRequestBuilder() throws IOException { + HttpRequest.Builder builder = HttpRequest.newBuilder() + .uri(URI.create(url)); + for (Map.Entry headerEntry : headers.entrySet()) { + builder.header(headerEntry.getKey(), headerEntry.getValue()); + } + return builder; + } + + protected CompletableFuture asyncRequest( + HttpRequest request, + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable + ) { + Flow.Subscriber subscriber = new Flow.Subscriber() { + private Flow.@Nullable Subscription subscription; + private volatile boolean errorRaised = false; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + this.subscription.request(1); + } + + @Override + public void onNext(String item) { + // SSE messages sometimes start with "data:". Strip that off + if (item != null && item.startsWith("data:")) { + item = item.substring(5).trim(); + if (!item.isEmpty()) { + messageConsumer.accept(item); + } + } + if (subscription != null) { + subscription.request(1); + } + } + + @Override + public void onError(Throwable throwable) { + if (!errorRaised) { + errorRaised = true; + errorConsumer.accept(throwable); + } + if (subscription != null) { + subscription.cancel(); + } + } + + @Override + public void onComplete() { + if (!errorRaised) { + completeRunnable.run(); + } + if (subscription != null) { + subscription.cancel(); + } + } + }; + + // Create a custom body handler that checks status before processing body + BodyHandler bodyHandler = responseInfo -> { + // Check for authentication/authorization errors only + if (responseInfo.statusCode() == HTTP_UNAUTHORIZED || responseInfo.statusCode() == HTTP_FORBIDDEN) { + final String errorMessage; + if (responseInfo.statusCode() == HTTP_UNAUTHORIZED) { + errorMessage = A2AErrorMessages.AUTHENTICATION_FAILED; + } else { + errorMessage = A2AErrorMessages.AUTHORIZATION_FAILED; + } + // Return a body subscriber that immediately signals error + return BodySubscribers.fromSubscriber(new Flow.Subscriber>() { + @Override + public void onSubscribe(Flow.Subscription subscription) { + subscriber.onError(new IOException(errorMessage)); + } + + @Override + public void onNext(List item) { + // Should not be called + } + + @Override + public void onError(Throwable throwable) { + // Should not be called + } + + @Override + public void onComplete() { + // Should not be called + } + }); + } else { + // For all other status codes (including other errors), proceed with normal line subscriber + return BodyHandlers.fromLineSubscriber(subscriber).apply(responseInfo); + } + }; + + // Send the response async, and let the subscriber handle the lines. + return httpClient.sendAsync(request, bodyHandler) + .thenAccept(response -> { + // Handle non-authentication/non-authorization errors here + if (!isSuccessStatus(response.statusCode()) && + response.statusCode() != HTTP_UNAUTHORIZED && + response.statusCode() != HTTP_FORBIDDEN) { + subscriber.onError(new IOException("Request failed with status " + response.statusCode() + ":" + response.body())); + } + }) + .exceptionally(throwable -> { + // Handle network errors (timeouts, connection failures, etc.) + subscriber.onError(throwable); + return null; + }); + } + } + + private class JdkGetBuilder extends JdkBuilder implements A2AHttpClient_v0_3.GetBuilder { + + private HttpRequest.Builder createRequestBuilder(boolean SSE) throws IOException { + HttpRequest.Builder builder = super.createRequestBuilder().GET(); + if (SSE) { + builder.header("Accept", "text/event-stream"); + } + return builder; + } + + @Override + public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { + HttpRequest request = createRequestBuilder(false) + .build(); + HttpResponse response = + httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); + return new JdkHttpResponse(response); + } + + @Override + public CompletableFuture getAsyncSSE( + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) throws IOException, InterruptedException { + HttpRequest request = createRequestBuilder(true) + .build(); + return super.asyncRequest(request, messageConsumer, errorConsumer, completeRunnable); + } + + } + + private class JdkDeleteBuilder extends JdkBuilder implements A2AHttpClient_v0_3.DeleteBuilder { + + @Override + public A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException { + HttpRequest request = super.createRequestBuilder().DELETE().build(); + HttpResponse response = + httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); + return new JdkHttpResponse(response); + } + + } + + private class JdkPostBuilder extends JdkBuilder implements A2AHttpClient_v0_3.PostBuilder { + String body = ""; + + @Override + public PostBuilder body(String body) { + this.body = body; + return self(); + } + + private HttpRequest.Builder createRequestBuilder(boolean SSE) throws IOException { + HttpRequest.Builder builder = super.createRequestBuilder() + .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)); + if (SSE) { + builder.header("Accept", "text/event-stream"); + } + return builder; + } + + @Override + public A2AHttpResponse_v0_3 post() throws IOException, InterruptedException { + HttpRequest request = createRequestBuilder(false) + .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)) + .build(); + HttpResponse response = + httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); + + if (response.statusCode() == HTTP_UNAUTHORIZED) { + throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); + } else if (response.statusCode() == HTTP_FORBIDDEN) { + throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); + } + + return new JdkHttpResponse(response); + } + + @Override + public CompletableFuture postAsyncSSE( + Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) throws IOException, InterruptedException { + HttpRequest request = createRequestBuilder(true) + .build(); + return super.asyncRequest(request, messageConsumer, errorConsumer, completeRunnable); + } + } + + private record JdkHttpResponse(HttpResponse response) implements A2AHttpResponse_v0_3 { + + @Override + public int status() { + return response.statusCode(); + } + + @Override + public boolean success() {// Send the request and get the response + return success(response); + } + + static boolean success(HttpResponse response) { + return response.statusCode() >= HTTP_OK && response.statusCode() < HTTP_MULT_CHOICE; + } + + @Override + public String body() { + return response.body(); + } + } + + private static boolean isSuccessStatus(int statusCode) { + return statusCode >= HTTP_OK && statusCode < HTTP_MULT_CHOICE; + } +} diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/package-info.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/package-info.java new file mode 100644 index 000000000..035bf5a62 --- /dev/null +++ b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.client.http; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java b/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java new file mode 100644 index 000000000..f632d3e22 --- /dev/null +++ b/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java @@ -0,0 +1,177 @@ +package org.a2aproject.sdk.compat03.client.http; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientJSONError_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import java.util.Map; +import org.junit.jupiter.api.Test; + +public class A2ACardResolver_v0_3_Test { + + private static final String AGENT_CARD_PATH = "/.well-known/agent-card.json"; + + @Test + public void testConstructorStripsSlashes() throws Exception { + TestHttpClient client = new TestHttpClient(); + client.body = JsonMessages_v0_3.AGENT_CARD; + + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(client, "http://example.com/"); + AgentCard_v0_3 card = resolver.getAgentCard(); + + assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); + + + resolver = new A2ACardResolver_v0_3(client, "http://example.com"); + card = resolver.getAgentCard(); + + assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); + + // baseUrl with trailing slash, agentCardParth with leading slash + resolver = new A2ACardResolver_v0_3(client, "http://example.com/", AGENT_CARD_PATH); + card = resolver.getAgentCard(); + + assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); + + // baseUrl without trailing slash, agentCardPath with leading slash + resolver = new A2ACardResolver_v0_3(client, "http://example.com", AGENT_CARD_PATH); + card = resolver.getAgentCard(); + + assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); + + // baseUrl with trailing slash, agentCardPath without leading slash + resolver = new A2ACardResolver_v0_3(client, "http://example.com/", AGENT_CARD_PATH.substring(1)); + card = resolver.getAgentCard(); + + assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); + + // baseUrl without trailing slash, agentCardPath without leading slash + resolver = new A2ACardResolver_v0_3(client, "http://example.com", AGENT_CARD_PATH.substring(1)); + card = resolver.getAgentCard(); + + assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); + } + + + @Test + public void testGetAgentCardSuccess() throws Exception { + TestHttpClient client = new TestHttpClient(); + client.body = JsonMessages_v0_3.AGENT_CARD; + + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(client, "http://example.com/"); + AgentCard_v0_3 card = resolver.getAgentCard(); + + AgentCard_v0_3 expectedCard = JsonUtil_v0_3.fromJson(JsonMessages_v0_3.AGENT_CARD, AgentCard_v0_3.class); + String expected = JsonUtil_v0_3.toJson(expectedCard); + + String requestCardString = JsonUtil_v0_3.toJson(card); + assertEquals(expected, requestCardString); + } + + @Test + public void testGetAgentCardJsonDecodeError() throws Exception { + TestHttpClient client = new TestHttpClient(); + client.body = "X" + JsonMessages_v0_3.AGENT_CARD; + + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(client, "http://example.com/"); + + boolean success = false; + try { + AgentCard_v0_3 card = resolver.getAgentCard(); + success = true; + } catch (A2AClientJSONError_v0_3 expected) { + } + assertFalse(success); + } + + + @Test + public void testGetAgentCardRequestError() throws Exception { + TestHttpClient client = new TestHttpClient(); + client.status = 503; + + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(client, "http://example.com/"); + + String msg = null; + try { + AgentCard_v0_3 card = resolver.getAgentCard(); + } catch (A2AClientError_v0_3 expected) { + msg = expected.getMessage(); + } + assertTrue(msg.contains("503")); + } + + private static class TestHttpClient implements A2AHttpClient_v0_3 { + int status = 200; + String body; + String url; + + @Override + public GetBuilder createGet() { + return new TestGetBuilder(); + } + + @Override + public PostBuilder createPost() { + return null; + } + + @Override + public DeleteBuilder createDelete() { + return null; + } + + class TestGetBuilder implements A2AHttpClient_v0_3.GetBuilder { + + @Override + public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { + return new A2AHttpResponse_v0_3() { + @Override + public int status() { + return status; + } + + @Override + public boolean success() { + return status == 200; + } + + @Override + public String body() { + return body; + } + }; + } + + @Override + public CompletableFuture getAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { + return null; + } + + @Override + public GetBuilder url(String s) { + url = s; + return this; + } + + @Override + public GetBuilder addHeader(String name, String value) { + return this; + } + + @Override + public GetBuilder addHeaders(Map headers) { + return this; + } + } + } + +} diff --git a/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java b/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java new file mode 100644 index 000000000..751dadf6c --- /dev/null +++ b/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java @@ -0,0 +1,164 @@ +package org.a2aproject.sdk.compat03.client.http; + +/** + * Request and response messages used by the tests. These have been created following examples from + * the A2A sample messages. + */ +public class JsonMessages_v0_3 { + + static final String AGENT_CARD = """ + { + "protocolVersion": "0.2.9", + "name": "GeoSpatial Route Planner Agent", + "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", + "url": "https://georoute-agent.example.com/a2a/v1", + "preferredTransport": "JSONRPC", + "additionalInterfaces" : [ + {"url": "https://georoute-agent.example.com/a2a/v1", "transport": "JSONRPC"}, + {"url": "https://georoute-agent.example.com/a2a/grpc", "transport": "GRPC"}, + {"url": "https://georoute-agent.example.com/a2a/json", "transport": "HTTP+JSON"} + ], + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + } + ], + "supportsAuthenticatedExtendedCard": true, + "signatures": [ + { + "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", + "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" + } + ] + }"""; + + static final String AUTHENTICATION_EXTENDED_AGENT_CARD = """ + { + "name": "GeoSpatial Route Planner Agent Extended", + "description": "Extended description", + "url": "https://georoute-agent.example.com/a2a/v1", + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + }, + { + "id": "skill-extended", + "name": "Extended Skill", + "description": "This is an extended skill.", + "tags": ["extended"] + } + ], + "supportsAuthenticatedExtendedCard": true, + "protocolVersion": "0.2.9", + "signatures": [ + { + "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", + "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" + } + ] + }"""; + + +} \ No newline at end of file diff --git a/compat-0.3/pom.xml b/compat-0.3/pom.xml new file mode 100644 index 000000000..9e7af13ae --- /dev/null +++ b/compat-0.3/pom.xml @@ -0,0 +1,148 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.0.Beta2-SNAPSHOT + + + a2a-java-sdk-compat-0.3-parent + pom + + Java SDK A2A Compat 0.3 Parent + A2A Protocol v0.3 backward compatibility layer for v1.0 SDK + + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec-grpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-http-client + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-spi + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-grpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-rest + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-grpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-rest + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-common + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-grpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-rest + ${project.version} + + + ${project.groupId} + a2a-compat-0.3-tck-server + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + test-jar + ${project.version} + + + + + + + spec + spec-grpc + + + http-client + + + server-conversion + + + client/base + client/transport/spi + client/transport/jsonrpc + client/transport/grpc + client/transport/rest + + + transport/jsonrpc + transport/grpc + transport/rest + + + reference/jsonrpc + reference/grpc + reference/rest + + + tck + + + diff --git a/compat-0.3/reference/grpc/pom.xml b/compat-0.3/reference/grpc/pom.xml new file mode 100644 index 000000000..356a1f0f8 --- /dev/null +++ b/compat-0.3/reference/grpc/pom.xml @@ -0,0 +1,114 @@ + + + 4.0.0 + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../../pom.xml + + + a2a-java-sdk-compat-0.3-reference-grpc + Java A2A Compat 0.3 Reference Server: gRPC + Java SDK for the Agent2Agent Protocol (A2A) - A2A gRPC Reference Server (based on Quarkus) + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec-grpc + + + ${project.groupId} + a2a-java-sdk-common + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-grpc + + + ${project.groupId} + a2a-java-sdk-server-common + + + ${project.groupId} + a2a-java-sdk-spec-grpc + + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + test-jar + test + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-grpc + test + + + + io.quarkus + quarkus-grpc + + + io.quarkus + quarkus-rest + test + + + io.quarkus + quarkus-junit5 + test + + + org.assertj + assertj-core + 3.25.3 + test + + + com.google.api.grpc + proto-google-common-protos + + + com.google.protobuf + protobuf-java + + + io.grpc + grpc-protobuf + + + io.grpc + grpc-stub + + + io.rest-assured + rest-assured + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + \ No newline at end of file diff --git a/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/A2AExtensionsInterceptor_v0_3.java b/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/A2AExtensionsInterceptor_v0_3.java new file mode 100644 index 000000000..5d3ae805c --- /dev/null +++ b/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/A2AExtensionsInterceptor_v0_3.java @@ -0,0 +1,70 @@ +package org.a2aproject.sdk.compat03.server.grpc.quarkus; + +import jakarta.enterprise.context.ApplicationScoped; +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 org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3; +import org.a2aproject.sdk.compat03.transport.grpc.context.GrpcContextKeys_v0_3; + +/** + * gRPC server interceptor that captures request metadata and context information, + * providing equivalent functionality to Python's grpc.aio.ServicerContext. + * + * This interceptor: + * - Extracts A2A extension headers from incoming requests + * - Captures ServerCall and Metadata for rich context access + * - Stores context information in gRPC Context for service method access + * - Provides proper equivalence to Python's ServicerContext + */ +@ApplicationScoped +public class A2AExtensionsInterceptor_v0_3 implements ServerInterceptor { + + + @Override + public ServerCall.Listener interceptCall( + ServerCall serverCall, + Metadata metadata, + ServerCallHandler serverCallHandler) { + + // Extract A2A extensions header + Metadata.Key extensionsKey = + Metadata.Key.of(A2AHeaders_v0_3.X_A2A_EXTENSIONS, Metadata.ASCII_STRING_MARSHALLER); + String extensions = metadata.get(extensionsKey); + + // Create enhanced context with rich information (equivalent to Python's ServicerContext) + Context context = Context.current() + // Store complete metadata for full header access + .withValue(GrpcContextKeys_v0_3.METADATA_KEY, metadata) + // Store method name (equivalent to Python's context.method()) + .withValue(GrpcContextKeys_v0_3.METHOD_NAME_KEY, serverCall.getMethodDescriptor().getFullMethodName()) + // Store peer information for client connection details + .withValue(GrpcContextKeys_v0_3.PEER_INFO_KEY, getPeerInfo(serverCall)); + + // Store A2A extensions if present + if (extensions != null) { + context = context.withValue(GrpcContextKeys_v0_3.EXTENSIONS_HEADER_KEY, extensions); + } + + // Proceed with the call in the enhanced context + return Contexts.interceptCall(context, serverCall, metadata, serverCallHandler); + } + + /** + * Safely extracts peer information from the ServerCall. + * + * @param serverCall the gRPC ServerCall + * @return peer information string, or "unknown" if not available + */ + private String getPeerInfo(ServerCall serverCall) { + try { + Object remoteAddr = serverCall.getAttributes().get(io.grpc.Grpc.TRANSPORT_ATTR_REMOTE_ADDR); + return remoteAddr != null ? remoteAddr.toString() : "unknown"; + } catch (Exception e) { + return "unknown"; + } + } +} diff --git a/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcHandler_v0_3.java b/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcHandler_v0_3.java new file mode 100644 index 000000000..bd9c7b890 --- /dev/null +++ b/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcHandler_v0_3.java @@ -0,0 +1,52 @@ +package org.a2aproject.sdk.compat03.server.grpc.quarkus; + +import java.util.concurrent.Executor; + +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import io.quarkus.grpc.GrpcService; +import io.quarkus.grpc.RegisterInterceptor; +import io.quarkus.security.Authenticated; +import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.transport.grpc.handler.CallContextFactory_v0_3; +import org.a2aproject.sdk.compat03.transport.grpc.handler.GrpcHandler_v0_3; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.util.async.Internal; + +@GrpcService +@RegisterInterceptor(A2AExtensionsInterceptor_v0_3.class) +@Authenticated +public class QuarkusGrpcHandler_v0_3 extends GrpcHandler_v0_3 { + + private final AgentCard_v0_3 agentCard; + private final Instance callContextFactoryInstance; + private final Executor executor; + + @Inject + public QuarkusGrpcHandler_v0_3(@PublicAgentCard AgentCard_v0_3 agentCard, + Convert_v0_3_To10RequestHandler requestHandler, + Instance callContextFactoryInstance, + @Internal Executor executor) { + this.agentCard = agentCard; + this.callContextFactoryInstance = callContextFactoryInstance; + this.executor = executor; + setRequestHandler(requestHandler); + } + + @Override + protected AgentCard_v0_3 getAgentCard() { + return agentCard; + } + + @Override + protected CallContextFactory_v0_3 getCallContextFactory() { + return callContextFactoryInstance.isUnsatisfied() ? null : callContextFactoryInstance.get(); + } + + @Override + protected Executor getExecutor() { + return executor; + } +} diff --git a/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcTransportMetadata_v0_3.java b/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcTransportMetadata_v0_3.java new file mode 100644 index 000000000..5cb9d813a --- /dev/null +++ b/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcTransportMetadata_v0_3.java @@ -0,0 +1,11 @@ +package org.a2aproject.sdk.compat03.server.grpc.quarkus; + +import org.a2aproject.sdk.server.TransportMetadata; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; + +public class QuarkusGrpcTransportMetadata_v0_3 implements TransportMetadata { + @Override + public String getTransportProtocol() { + return TransportProtocol_v0_3.GRPC.asString(); + } +} diff --git a/compat-0.3/reference/grpc/src/main/resources/META-INF/beans.xml b/compat-0.3/reference/grpc/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..e69de29bb diff --git a/compat-0.3/reference/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata b/compat-0.3/reference/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata new file mode 100644 index 000000000..751bdcfdb --- /dev/null +++ b/compat-0.3/reference/grpc/src/main/resources/META-INF/services/org.a2aproject.sdk.server.TransportMetadata @@ -0,0 +1 @@ +org.a2aproject.sdk.compat03.server.grpc.quarkus.QuarkusGrpcTransportMetadata_v0_3 diff --git a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/A2ATestResource_v0_3.java b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/A2ATestResource_v0_3.java new file mode 100644 index 000000000..971d09afe --- /dev/null +++ b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/A2ATestResource_v0_3.java @@ -0,0 +1,144 @@ +package org.a2aproject.sdk.compat03.server.grpc.quarkus; + +import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; + +import java.util.concurrent.atomic.AtomicInteger; + +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import org.a2aproject.sdk.compat03.conversion.TestUtilsBean_v0_3; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.compat03.transport.grpc.handler.GrpcHandler_v0_3; + +/** + * Exposes the {@link TestUtilsBean_v0_3} via JAX-RS REST endpoints for testing the gRPC server. + * Uses JAX-RS instead of Reactive Routes because gRPC servers typically expose REST test utilities separately. + */ +@Path("/test") +@ApplicationScoped +public class A2ATestResource_v0_3 { + @Inject + TestUtilsBean_v0_3 testUtilsBean; + + private final AtomicInteger streamingSubscribedCount = new AtomicInteger(0); + + @PostConstruct + public void init() { + GrpcHandler_v0_3.setStreamingSubscribedRunnable(streamingSubscribedCount::incrementAndGet); + } + + + @POST + @Path("/task") + @Consumes(MediaType.APPLICATION_JSON) + public Response saveTask(String body) throws Exception { + Task task = JsonUtil.fromJson(body, Task.class); + testUtilsBean.saveTask(task); + return Response.ok().build(); + } + + @GET + @Path("/task/{taskId}") + public Response getTask(@PathParam("taskId") String taskId) throws Exception { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + return Response.status(404).build(); + } + return Response.ok() + .entity(JsonUtil.toJson(task)) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .build(); + } + + @DELETE + @Path("/task/{taskId}") + public Response deleteTask(@PathParam("taskId") String taskId) { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + return Response.status(404).build(); + } + testUtilsBean.deleteTask(taskId); + return Response.ok() + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .build(); + } + + @POST + @Path("/queue/ensure/{taskId}") + public Response ensureQueue(@PathParam("taskId") String taskId) { + testUtilsBean.ensureQueue(taskId); + return Response.ok().build(); + } + + @POST + @Path("/queue/enqueueTaskStatusUpdateEvent/{taskId}") + public Response enqueueTaskStatusUpdateEvent(@PathParam("taskId") String taskId, String body) throws Exception { + TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + return Response.ok().build(); + } + + @POST + @Path("/queue/enqueueTaskArtifactUpdateEvent/{taskId}") + public Response enqueueTaskArtifactUpdateEvent(@PathParam("taskId") String taskId, String body) throws Exception { + TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + return Response.ok().build(); + } + + @GET + @Path("/streamingSubscribedCount") + @Produces(TEXT_PLAIN) + public Response getStreamingSubscribedCount() { + return Response.ok(String.valueOf(streamingSubscribedCount.get()), TEXT_PLAIN).build(); + } + + @GET + @Path("/queue/childCount/{taskId}") + @Produces(TEXT_PLAIN) + public Response getChildQueueCount(@PathParam("taskId") String taskId) { + int count = testUtilsBean.getChildQueueCount(taskId); + return Response.ok(String.valueOf(count), TEXT_PLAIN).build(); + } + + @DELETE + @Path("/task/{taskId}/config/{configId}") + public Response deleteTaskPushNotificationConfig(@PathParam("taskId") String taskId, @PathParam("configId") String configId) { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + return Response.status(404).build(); + } + testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); + return Response.ok() + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .build(); + } + + @POST + @Path("/task/{taskId}") + @Consumes(MediaType.APPLICATION_JSON) + public Response savePushNotificationConfigInStore(@PathParam("taskId") String taskId, String body) throws Exception { + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); + if (notificationConfig == null) { + return Response.status(404).build(); + } + testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); + return Response.ok().build(); + } +} diff --git a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_Test.java b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_Test.java new file mode 100644 index 000000000..c5e362c6b --- /dev/null +++ b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_Test.java @@ -0,0 +1,55 @@ +package org.a2aproject.sdk.compat03.server.grpc.quarkus; + +import java.util.concurrent.TimeUnit; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.quarkus.test.junit.QuarkusTest; + +import org.junit.jupiter.api.AfterAll; + +@QuarkusTest +public class QuarkusA2AGrpc_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { + + private static ManagedChannel channel; + + public QuarkusA2AGrpc_v0_3_Test() { + super(8081); // HTTP server port for utility endpoints + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.GRPC.asString(); + } + + @Override + protected String getTransportUrl() { + // gRPC server runs on port 8081, which is the same port as the main web server. + return "localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(GrpcTransport_v0_3.class, new GrpcTransportConfigBuilder_v0_3().channelFactory(target -> { + channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build(); + return channel; + })); + } + + @AfterAll + public static void closeChannel() { + if (channel != null) { + channel.shutdownNow(); + try { + channel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } +} diff --git a/compat-0.3/reference/grpc/src/test/resources/application.properties b/compat-0.3/reference/grpc/src/test/resources/application.properties new file mode 100644 index 000000000..8ec9e2967 --- /dev/null +++ b/compat-0.3/reference/grpc/src/test/resources/application.properties @@ -0,0 +1,27 @@ +# gRPC server configuration - use main HTTP port (not separate port) +quarkus.grpc.server.use-separate-server=false + +# HTTP server port for tests +quarkus.http.port=8081 +quarkus.http.test-port=8081 + +# Index dependencies for CDI bean discovery +quarkus.index-dependency.server-conversion.group-id=org.a2aproject.sdk +quarkus.index-dependency.server-conversion.artifact-id=a2a-java-sdk-compat-0.3-server-conversion +quarkus.index-dependency.server-conversion.classifier=tests + +# Index v1.0 server-common for InMemoryTaskStore, DefaultRequestHandler, etc. +quarkus.index-dependency.server-common.group-id=org.a2aproject.sdk +quarkus.index-dependency.server-common.artifact-id=a2a-java-sdk-server-common + +# Index compat-0.3 transport-grpc for GrpcHandler +quarkus.index-dependency.transport-grpc.group-id=org.a2aproject.sdk +quarkus.index-dependency.transport-grpc.artifact-id=a2a-java-sdk-compat-0.3-transport-grpc + +# Use test HTTP client from v0.3 compat test infrastructure +quarkus.arc.selected-alternatives=org.a2aproject.sdk.compat03.conversion.TestHttpClient_v0_3 + +# Debug logging for event processing and request handling +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG diff --git a/compat-0.3/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties b/compat-0.3/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties new file mode 100644 index 000000000..941770fb9 --- /dev/null +++ b/compat-0.3/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=grpc diff --git a/compat-0.3/reference/jsonrpc/pom.xml b/compat-0.3/reference/jsonrpc/pom.xml new file mode 100644 index 000000000..4bbd63ef4 --- /dev/null +++ b/compat-0.3/reference/jsonrpc/pom.xml @@ -0,0 +1,107 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../../pom.xml + + a2a-java-sdk-compat-0.3-reference-jsonrpc + + jar + + Java A2A Compat 0.3 Reference Server: JSONRPC + Java SDK for the Agent2Agent Protocol (A2A) - A2A JSONRPC Reference Server (based on Quarkus) + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-jsonrpc + + + ${project.groupId} + a2a-java-sdk-server-common + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + test-jar + test + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + test + + + io.quarkus + quarkus-reactive-routes + + + jakarta.enterprise + jakarta.enterprise.cdi-api + + + jakarta.inject + jakarta.inject-api + + + org.slf4j + slf4j-api + + + io.quarkus + quarkus-junit5 + test + + + io.quarkus + quarkus-rest-client-jackson + test + + + org.junit.jupiter + junit-jupiter-api + test + + + io.rest-assured + rest-assured + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java new file mode 100644 index 000000000..e7fff4e8e --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -0,0 +1,390 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +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 static org.a2aproject.sdk.compat03.transport.jsonrpc.context.JSONRPCContextKeys_v0_3.HEADERS_KEY; +import static org.a2aproject.sdk.compat03.transport.jsonrpc.context.JSONRPCContextKeys_v0_3.METHOD_NAME_KEY; + +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; +import java.util.function.Function; + +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import io.quarkus.security.Authenticated; +import io.quarkus.vertx.web.Body; +import io.quarkus.vertx.web.ReactiveRoutes; +import io.quarkus.vertx.web.Route; +import io.smallrye.mutiny.Multi; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.RoutingContext; +import org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3; +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetAuthenticatedExtendedCardRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCErrorResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCMessage_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.NonStreamingJSONRPCRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingJSONRPCRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskResubscriptionRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +import org.a2aproject.sdk.compat03.transport.jsonrpc.handler.JSONRPCHandler_v0_3; +import org.a2aproject.sdk.compat03.util.Utils_v0_3; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.server.util.async.Internal; + +@Singleton +public class A2AServerRoutes_v0_3 { + + @Inject + JSONRPCHandler_v0_3 jsonRpcHandler; + + // Hook so testing can wait until the MultiSseSupport is subscribed. + // Without this we get intermittent failures + private static volatile Runnable streamingMultiSseSupportSubscribedRunnable; + + @Inject + @Internal + Executor executor; + + @Inject + Instance callContextFactory; + + @Route(path = "/", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + @Authenticated + public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { + boolean streaming = false; + ServerCallContext context = createCallContext(rc); + JSONRPCResponse_v0_3 nonStreamingResponse = null; + Multi> streamingResponse = null; + JSONRPCErrorResponse_v0_3 error = null; + Object requestId = null; + try { + com.google.gson.JsonObject node; + try { + node = JsonParser.parseString(body).getAsJsonObject(); + } catch (Exception e) { + throw new JSONParseError_v0_3(e.getMessage()); + } + + // Extract id field early so error responses can include it + com.google.gson.JsonElement idElement = node.get("id"); + if (idElement != null && !idElement.isJsonNull() && !idElement.isJsonPrimitive()) { + throw new InvalidRequestError_v0_3("Invalid JSON-RPC request: 'id' must be a string, number, or null"); + } + if (idElement != null && !idElement.isJsonNull() && idElement.isJsonPrimitive()) { + com.google.gson.JsonPrimitive idPrimitive = idElement.getAsJsonPrimitive(); + requestId = idPrimitive.isNumber() ? idPrimitive.getAsLong() : idPrimitive.getAsString(); + } + + // Validate jsonrpc field + com.google.gson.JsonElement jsonrpcElement = node.get("jsonrpc"); + if (jsonrpcElement == null || !jsonrpcElement.isJsonPrimitive() + || !JSONRPCMessage_v0_3.JSONRPC_VERSION.equals(jsonrpcElement.getAsString())) { + throw new InvalidRequestError_v0_3("Invalid JSON-RPC request: missing or invalid 'jsonrpc' field"); + } + + // Validate method field + com.google.gson.JsonElement methodElement = node.get("method"); + if (methodElement == null || !methodElement.isJsonPrimitive()) { + throw new InvalidRequestError_v0_3("Invalid JSON-RPC request: missing or invalid 'method' field"); + } + + String methodName = methodElement.getAsString(); + context.getState().put(METHOD_NAME_KEY, methodName); + + streaming = SendStreamingMessageRequest_v0_3.METHOD.equals(methodName) + || TaskResubscriptionRequest_v0_3.METHOD.equals(methodName); + + if (streaming) { + StreamingJSONRPCRequest_v0_3 request = deserializeStreamingRequest(body, methodName); + streamingResponse = processStreamingRequest(request, context); + } else { + NonStreamingJSONRPCRequest_v0_3 request = deserializeNonStreamingRequest(body, methodName); + nonStreamingResponse = processNonStreamingRequest(request, context); + } + } catch (JSONRPCError_v0_3 e) { + error = new JSONRPCErrorResponse_v0_3(requestId, e); + } catch (JsonSyntaxException e) { + error = new JSONRPCErrorResponse_v0_3(requestId, new JSONParseError_v0_3(e.getMessage())); + } catch (Throwable t) { + error = new JSONRPCErrorResponse_v0_3(requestId, new InternalError_v0_3(t.getMessage())); + } finally { + if (error != null) { + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(Utils_v0_3.toJsonString(error)); + } else if (streaming) { + final Multi> finalStreamingResponse = streamingResponse; + executor.execute(() -> { + MultiSseSupport.subscribeObject( + finalStreamingResponse.map(i -> (Object) i), rc); + }); + + } else { + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(Utils_v0_3.toJsonString(nonStreamingResponse)); + } + } + } + + /** + * /** + * Handles incoming GET requests to the agent card endpoint. + * Returns the agent card in JSON format. + * + * @return the agent card + * @throws JsonProcessingException_v0_3 if serialization fails + */ + @Route(path = "/.well-known/agent-card.json", methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) + public String getAgentCard() throws JsonProcessingException_v0_3 { + return JsonUtil_v0_3.toJson(jsonRpcHandler.getAgentCard()); + } + + private NonStreamingJSONRPCRequest_v0_3 deserializeNonStreamingRequest(String body, String methodName) { + try { + return switch (methodName) { + case GetTaskRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, GetTaskRequest_v0_3.class); + case CancelTaskRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, CancelTaskRequest_v0_3.class); + case SendMessageRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, SendMessageRequest_v0_3.class); + case SetTaskPushNotificationConfigRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, SetTaskPushNotificationConfigRequest_v0_3.class); + case GetTaskPushNotificationConfigRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, GetTaskPushNotificationConfigRequest_v0_3.class); + case ListTaskPushNotificationConfigRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, ListTaskPushNotificationConfigRequest_v0_3.class); + case DeleteTaskPushNotificationConfigRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, DeleteTaskPushNotificationConfigRequest_v0_3.class); + case GetAuthenticatedExtendedCardRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, GetAuthenticatedExtendedCardRequest_v0_3.class); + default -> throw new MethodNotFoundError_v0_3(); + }; + } catch (JSONRPCError_v0_3 e) { + throw e; + } catch (Exception e) { + throw new InvalidParamsError_v0_3(e.getMessage()); + } + } + + private StreamingJSONRPCRequest_v0_3 deserializeStreamingRequest(String body, String methodName) { + try { + return switch (methodName) { + case SendStreamingMessageRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, SendStreamingMessageRequest_v0_3.class); + case TaskResubscriptionRequest_v0_3.METHOD -> JsonUtil_v0_3.fromJson(body, TaskResubscriptionRequest_v0_3.class); + default -> throw new MethodNotFoundError_v0_3(); + }; + } catch (JSONRPCError_v0_3 e) { + throw e; + } catch (Exception e) { + throw new InvalidParamsError_v0_3(e.getMessage()); + } + } + + private JSONRPCResponse_v0_3 processNonStreamingRequest( + NonStreamingJSONRPCRequest_v0_3 request, ServerCallContext context) { + if (request instanceof GetTaskRequest_v0_3 req) { + return jsonRpcHandler.onGetTask(req, context); + } else if (request instanceof CancelTaskRequest_v0_3 req) { + return jsonRpcHandler.onCancelTask(req, context); + } else if (request instanceof SetTaskPushNotificationConfigRequest_v0_3 req) { + return jsonRpcHandler.setPushNotificationConfig(req, context); + } else if (request instanceof GetTaskPushNotificationConfigRequest_v0_3 req) { + return jsonRpcHandler.getPushNotificationConfig(req, context); + } else if (request instanceof SendMessageRequest_v0_3 req) { + return jsonRpcHandler.onMessageSend(req, context); + } else if (request instanceof ListTaskPushNotificationConfigRequest_v0_3 req) { + return jsonRpcHandler.listPushNotificationConfig(req, context); + } else if (request instanceof DeleteTaskPushNotificationConfigRequest_v0_3 req) { + return jsonRpcHandler.deletePushNotificationConfig(req, context); + } else if (request instanceof GetAuthenticatedExtendedCardRequest_v0_3 req) { + return jsonRpcHandler.onGetAuthenticatedExtendedCardRequest(req, context); + } else { + return generateErrorResponse(request, new UnsupportedOperationError_v0_3()); + } + } + + private Multi> processStreamingRequest( + JSONRPCRequest_v0_3 request, ServerCallContext context) { + Flow.Publisher> publisher; + if (request instanceof SendStreamingMessageRequest_v0_3 req) { + publisher = jsonRpcHandler.onMessageSendStream(req, context); + } else if (request instanceof TaskResubscriptionRequest_v0_3 req) { + publisher = jsonRpcHandler.onResubscribeToTask(req, context); + } else { + return Multi.createFrom().item(generateErrorResponse(request, new UnsupportedOperationError_v0_3())); + } + return Multi.createFrom().publisher(publisher); + } + + private JSONRPCResponse_v0_3 generateErrorResponse(JSONRPCRequest_v0_3 request, JSONRPCError_v0_3 error) { + return new JSONRPCErrorResponse_v0_3(request.getId(), error); + } + + static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { + streamingMultiSseSupportSubscribedRunnable = runnable; + } + + private ServerCallContext createCallContext(RoutingContext rc) { + + if (callContextFactory.isUnsatisfied()) { + User user; + if (rc.user() == null) { + user = UnauthenticatedUser.INSTANCE; + } else { + user = new User() { + @Override + public boolean isAuthenticated() { + return rc.userContext().authenticated(); + } + + @Override + public String getUsername() { + return rc.user().subject(); + } + }; + } + Map state = new HashMap<>(); + // TODO Python's impl has + // state['auth'] = request.auth + // in jsonrpc_app.py. Figure out what this maps to in what Vert.X gives us + + Map headers = new HashMap<>(); + Set headerNames = rc.request().headers().names(); + headerNames.forEach(name -> headers.put(name, rc.request().getHeader(name))); + state.put(HEADERS_KEY, headers); + + // Extract requested extensions from X-A2A-Extensions header + List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders_v0_3.X_A2A_EXTENSIONS); + Set requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues); + + return new ServerCallContext(user, state, requestedExtensions); + } else { + CallContextFactory_v0_3 builder = callContextFactory.get(); + return builder.build(rc); + } + } + + // Port of import io.quarkus.vertx.web.runtime.MultiSseSupport, which is considered internal API + private static class MultiSseSupport { + + private MultiSseSupport() { + // Avoid direct instantiation. + } + + private static void initialize(HttpServerResponse response) { + if (response.bytesWritten() == 0) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + response.setChunked(true); + } + } + + private static void onWriteDone(Flow.Subscription subscription, AsyncResult ar, RoutingContext rc) { + if (ar.failed()) { + rc.fail(ar.cause()); + } else { + subscription.request(1); + } + } + + public static void write(Multi multi, RoutingContext rc) { + HttpServerResponse response = rc.response(); + multi.subscribe().withSubscriber(new Flow.Subscriber() { + Flow.Subscription upstream; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.upstream = subscription; + this.upstream.request(1); + + // Notify tests that we are subscribed + Runnable runnable = streamingMultiSseSupportSubscribedRunnable; + if (runnable != null) { + runnable.run(); + } + } + + @Override + public void onNext(Buffer item) { + initialize(response); + response.write(item, new Handler>() { + @Override + public void handle(AsyncResult ar) { + onWriteDone(upstream, ar, rc); + } + }); + } + + @Override + public void onError(Throwable throwable) { + rc.fail(throwable); + } + + @Override + public void onComplete() { + endOfStream(response); + } + }); + } + + public static void subscribeObject(Multi multi, RoutingContext rc) { + AtomicLong count = new AtomicLong(); + write(multi.map(new Function() { + @Override + public Buffer apply(Object o) { + if (o instanceof ReactiveRoutes.ServerSentEvent) { + ReactiveRoutes.ServerSentEvent ev = (ReactiveRoutes.ServerSentEvent) o; + long id = ev.id() != -1 ? ev.id() : count.getAndIncrement(); + String e = ev.event() == null ? "" : "event: " + ev.event() + "\n"; + return Buffer.buffer(e + "data: " + Utils_v0_3.toJsonString(ev.data()) + "\nid: " + id + "\n\n"); + } + return Buffer.buffer("data: " + Utils_v0_3.toJsonString(o) + "\nid: " + count.getAndIncrement() + "\n\n"); + } + }), rc); + } + + private static void endOfStream(HttpServerResponse response) { + if (response.bytesWritten() == 0) { // No item + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + } + response.end(); + } + } +} diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java new file mode 100644 index 000000000..f00bce4db --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java @@ -0,0 +1,8 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.server.ServerCallContext; +import io.vertx.ext.web.RoutingContext; + +public interface CallContextFactory_v0_3 { + ServerCallContext build(RoutingContext rc); +} diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusJSONRPCTransportMetadata_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusJSONRPCTransportMetadata_v0_3.java new file mode 100644 index 000000000..6b98db4b2 --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusJSONRPCTransportMetadata_v0_3.java @@ -0,0 +1,12 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.server.TransportMetadata; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; + +public class QuarkusJSONRPCTransportMetadata_v0_3 implements TransportMetadata { + + @Override + public String getTransportProtocol() { + return TransportProtocol_v0_3.JSONRPC.asString(); + } +} diff --git a/compat-0.3/reference/jsonrpc/src/main/resources/META-INF/beans.xml b/compat-0.3/reference/jsonrpc/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..548d44b72 --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/main/resources/META-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2ATestRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2ATestRoutes_v0_3.java new file mode 100644 index 000000000..96b30d362 --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2ATestRoutes_v0_3.java @@ -0,0 +1,196 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +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; + +import java.util.concurrent.atomic.AtomicInteger; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import org.a2aproject.sdk.compat03.conversion.TestUtilsBean_v0_3; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import io.quarkus.vertx.web.Body; +import io.quarkus.vertx.web.Param; +import io.quarkus.vertx.web.Route; +import io.vertx.ext.web.RoutingContext; + +/** + * Exposes the {@link TestUtilsBean_v0_3} via REST using Quarkus Reactive Routes + */ +@Singleton +public class A2ATestRoutes_v0_3 { + @Inject + TestUtilsBean_v0_3 testUtilsBean; + + @Inject + A2AServerRoutes_v0_3 a2AServerRoutes; + + AtomicInteger streamingSubscribedCount = new AtomicInteger(0); + + @PostConstruct + public void init() { + A2AServerRoutes_v0_3.setStreamingMultiSseSupportSubscribedRunnable(() -> streamingSubscribedCount.incrementAndGet()); + } + + + @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + public void saveTask(@Body String body, RoutingContext rc) { + try { + Task task = JsonUtil.fromJson(body, Task.class); + testUtilsBean.saveTask(task); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + public void getTask(@Param String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(JsonUtil.toJson(task)); + + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) + public void deleteTask(@Param String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.deleteTask(taskId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) + public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { + try { + testUtilsBean.ensureQueue(taskId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) + public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + + try { + TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) + public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + + try { + TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/streamingSubscribedCount", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) + public void getStreamingSubscribedCount(RoutingContext rc) { + rc.response() + .setStatusCode(200) + .end(String.valueOf(streamingSubscribedCount.get())); + } + + @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) + public void getChildQueueCount(@Param String taskId, RoutingContext rc) { + int count = testUtilsBean.getChildQueueCount(taskId); + rc.response() + .setStatusCode(200) + .end(String.valueOf(count)); + } + + @Route(path = "/test/task/:taskId/config/:configId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) + public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String configId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) + public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { + try { + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); + if (notificationConfig == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + private void errorResponse(Throwable t, RoutingContext rc) { + t.printStackTrace(); + rc.response() + .setStatusCode(500) + .putHeader(CONTENT_TYPE, TEXT_PLAIN) + .end(); + } + +} diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_Test.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_Test.java new file mode 100644 index 000000000..65683ce9a --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_Test.java @@ -0,0 +1,31 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusA2AJSONRPC_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { + + public QuarkusA2AJSONRPC_v0_3_Test() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); + } +} diff --git a/compat-0.3/reference/jsonrpc/src/test/resources/application.properties b/compat-0.3/reference/jsonrpc/src/test/resources/application.properties new file mode 100644 index 000000000..f7b5a7d9f --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/resources/application.properties @@ -0,0 +1,12 @@ +# Index dependencies for CDI bean discovery +quarkus.index-dependency.server-conversion.group-id=org.a2aproject.sdk +quarkus.index-dependency.server-conversion.artifact-id=a2a-java-sdk-compat-0.3-server-conversion +quarkus.index-dependency.server-conversion.classifier=tests + +# Use test HTTP client from v0.3 compat test infrastructure +quarkus.arc.selected-alternatives=org.a2aproject.sdk.compat03.conversion.TestHttpClient_v0_3 + +# Debug logging for event processing and request handling +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG diff --git a/compat-0.3/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties b/compat-0.3/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties new file mode 100644 index 000000000..2d94ad8ab --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=jsonrpc diff --git a/compat-0.3/reference/rest/pom.xml b/compat-0.3/reference/rest/pom.xml new file mode 100644 index 000000000..3677c6a51 --- /dev/null +++ b/compat-0.3/reference/rest/pom.xml @@ -0,0 +1,107 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../../pom.xml + + a2a-java-sdk-compat-0.3-reference-rest + + jar + + Java A2A Compat 0.3 Reference Server: JSON+HTTP/REST + Java SDK for the Agent2Agent Protocol (A2A) - A2A JSON+HTTP/REST Reference Server (based on Quarkus) + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-compat-0.3-transport-rest + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + test-jar + test + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-rest + test + + + com.google.protobuf + protobuf-java-util + test + + + io.quarkus + quarkus-reactive-routes + + + jakarta.enterprise + jakarta.enterprise.cdi-api + + + jakarta.inject + jakarta.inject-api + + + org.slf4j + slf4j-api + + + io.quarkus + quarkus-junit5 + test + + + io.quarkus + quarkus-rest-client-jackson + test + + + org.junit.jupiter + junit-jupiter-api + test + + + io.rest-assured + rest-assured + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java new file mode 100644 index 000000000..7e424dcfa --- /dev/null +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -0,0 +1,453 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import static org.a2aproject.sdk.compat03.transport.rest.context.RestContextKeys_v0_3.HEADERS_KEY; +import static org.a2aproject.sdk.compat03.transport.rest.context.RestContextKeys_v0_3.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.concurrent.Executor; +import java.util.concurrent.Flow; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Function; + +import jakarta.annotation.security.PermitAll; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskResubscriptionRequest_v0_3; +import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3; +import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3.HTTPRestResponse; +import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3.HTTPRestStreamingResponse; +import io.quarkus.security.Authenticated; +import io.quarkus.vertx.web.Body; +import io.quarkus.vertx.web.ReactiveRoutes; +import io.quarkus.vertx.web.Route; +import io.smallrye.mutiny.Multi; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +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 org.jspecify.annotations.Nullable; + +@Singleton +@Authenticated +public class A2AServerRoutes_v0_3 { + + @Inject + RestHandler_v0_3 jsonRestHandler; + + // Hook so testing can wait until the MultiSseSupport is subscribed. + // Without this we get intermittent failures + private static volatile @Nullable Runnable streamingMultiSseSupportSubscribedRunnable; + + @Inject + @Internal + Executor executor; + + @Inject + Instance callContextFactory; + + @Route(regex = "^/v1/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_v0_3.METHOD); + HTTPRestResponse response = null; + try { + response = jsonRestHandler.sendMessage(body, context); + } catch (Throwable t) { + response = jsonRestHandler.createErrorResponse(new InternalError_v0_3(t.getMessage())); + } finally { + sendResponse(rc, response); + } + } + + @Route(regex = "^/v1/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_v0_3.METHOD); + HTTPRestStreamingResponse streamingResponse = null; + HTTPRestResponse error = null; + try { + HTTPRestResponse response = jsonRestHandler.sendStreamingMessage(body, context); + if (response instanceof HTTPRestStreamingResponse hTTPRestStreamingResponse) { + streamingResponse = hTTPRestStreamingResponse; + } else { + error = response; + } + } finally { + if (error != null) { + sendResponse(rc, error); + } else if (streamingResponse != null) { + Multi events = Multi.createFrom().publisher(streamingResponse.getPublisher()); + executor.execute(() -> { + MultiSseSupport.subscribeObject( + events.map(i -> (Object) i), rc); + }); + } + } + } + + @Route(path = "/v1/tasks/:id", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) + public void getTask(RoutingContext rc) { + String taskId = rc.pathParam("id"); + ServerCallContext context = createCallContext(rc, GetTaskRequest_v0_3.METHOD); + HTTPRestResponse response = null; + try { + if (taskId == null || taskId.isEmpty()) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad task id")); + } else { + int historyLength = 0; + boolean hasHistoryLength = rc.request().params().contains("history_length"); + boolean hasHistoryLengthCamel = rc.request().params().contains("historyLength"); + + if (hasHistoryLength && hasHistoryLengthCamel) { + response = jsonRestHandler.createErrorResponse( + new InvalidParamsError_v0_3("Only one of 'history_length' or 'historyLength' may be specified")); + } else if (hasHistoryLength) { + historyLength = Integer.parseInt(rc.request().params().get("history_length")); + } else if (hasHistoryLengthCamel) { + historyLength = Integer.parseInt(rc.request().params().get("historyLength")); + } + + if (response == null) { + response = jsonRestHandler.getTask(taskId, historyLength, context); + } + } + } catch (NumberFormatException e) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad history_length or historyLength")); + } catch (Throwable t) { + response = jsonRestHandler.createErrorResponse(new InternalError_v0_3(t.getMessage())); + } finally { + sendResponse(rc, response); + } + } + + @Route(regex = "^/v1/tasks/([^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) + public void cancelTask(RoutingContext rc) { + String taskId = rc.pathParam("param0"); + ServerCallContext context = createCallContext(rc, CancelTaskRequest_v0_3.METHOD); + HTTPRestResponse response = null; + try { + if (taskId == null || taskId.isEmpty()) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad task id")); + } else { + response = jsonRestHandler.cancelTask(taskId, context); + } + } catch (Throwable t) { + if (t instanceof JSONRPCError_v0_3 error) { + response = jsonRestHandler.createErrorResponse(error); + } else { + response = jsonRestHandler.createErrorResponse(new InternalError_v0_3(t.getMessage())); + } + } finally { + sendResponse(rc, response); + } + } + + private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response) { + if (response != null) { + rc.response() + .setStatusCode(response.getStatusCode()) + .putHeader(CONTENT_TYPE, response.getContentType()) + .end(response.getBody()); + } else { + rc.response().end(); + } + } + + @Route(regex = "^/v1/tasks/([^/]+):subscribe$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) + public void resubscribeTask(RoutingContext rc) { + String taskId = rc.pathParam("param0"); + ServerCallContext context = createCallContext(rc, TaskResubscriptionRequest_v0_3.METHOD); + HTTPRestStreamingResponse streamingResponse = null; + HTTPRestResponse error = null; + try { + if (taskId == null || taskId.isEmpty()) { + error = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad task id")); + } else { + HTTPRestResponse response = jsonRestHandler.resubscribeTask(taskId, context); + if (response instanceof HTTPRestStreamingResponse hTTPRestStreamingResponse) { + streamingResponse = hTTPRestStreamingResponse; + } else { + error = response; + } + } + } finally { + if (error != null) { + sendResponse(rc, error); + } else if (streamingResponse != null) { + Multi events = Multi.createFrom().publisher(streamingResponse.getPublisher()); + executor.execute(() -> { + MultiSseSupport.subscribeObject( + events.map(i -> (Object) i), rc); + }); + } + } + } + + @Route(path = "/v1/tasks/:id/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("id"); + ServerCallContext context = createCallContext(rc, SetTaskPushNotificationConfigRequest_v0_3.METHOD); + HTTPRestResponse response = null; + try { + if (taskId == null || taskId.isEmpty()) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad task id")); + } else { + response = jsonRestHandler.setTaskPushNotificationConfiguration(taskId, body, context); + } + } catch (Throwable t) { + response = jsonRestHandler.createErrorResponse(new InternalError_v0_3(t.getMessage())); + } finally { + sendResponse(rc, response); + } + } + + @Route(path = "/v1/tasks/:id/pushNotificationConfigs/:configId", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) + public void getTaskPushNotificationConfiguration(RoutingContext rc) { + String taskId = rc.pathParam("id"); + String configId = rc.pathParam("configId"); + ServerCallContext context = createCallContext(rc, GetTaskPushNotificationConfigRequest_v0_3.METHOD); + HTTPRestResponse response = null; + try { + if (taskId == null || taskId.isEmpty()) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad task id")); + } else { + response = jsonRestHandler.getTaskPushNotificationConfiguration(taskId, configId, context); + } + } catch (Throwable t) { + response = jsonRestHandler.createErrorResponse(new InternalError_v0_3(t.getMessage())); + } finally { + sendResponse(rc, response); + } + } + + @Route(path = "/v1/tasks/:id/pushNotificationConfigs", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) + public void listTaskPushNotificationConfigurations(RoutingContext rc) { + String taskId = rc.pathParam("id"); + ServerCallContext context = createCallContext(rc, ListTaskPushNotificationConfigRequest_v0_3.METHOD); + HTTPRestResponse response = null; + try { + if (taskId == null || taskId.isEmpty()) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad task id")); + } else { + response = jsonRestHandler.listTaskPushNotificationConfigurations(taskId, context); + } + } catch (Throwable t) { + response = jsonRestHandler.createErrorResponse(new InternalError_v0_3(t.getMessage())); + } finally { + sendResponse(rc, response); + } + } + + @Route(path = "/v1/tasks/:id/pushNotificationConfigs/:configId", order = 1, methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) + public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { + String taskId = rc.pathParam("id"); + String configId = rc.pathParam("configId"); + ServerCallContext context = createCallContext(rc, DeleteTaskPushNotificationConfigRequest_v0_3.METHOD); + HTTPRestResponse response = null; + try { + if (taskId == null || taskId.isEmpty()) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad task id")); + } else if (configId == null || configId.isEmpty()) { + response = jsonRestHandler.createErrorResponse(new InvalidParamsError_v0_3("bad config id")); + } else { + response = jsonRestHandler.deleteTaskPushNotificationConfiguration(taskId, configId, context); + } + } catch (Throwable t) { + response = jsonRestHandler.createErrorResponse(new InternalError_v0_3(t.getMessage())); + } finally { + sendResponse(rc, response); + } + } + + /** + * Handles incoming GET requests to the agent card endpoint. + * Returns the agent card in JSON format. + * + * @param rc the routing context + */ + @Route(path = "/.well-known/agent-card.json", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) + @PermitAll + public void getAgentCard(RoutingContext rc) { + HTTPRestResponse response = jsonRestHandler.getAgentCard(); + sendResponse(rc, response); + } + + @Route(path = "/v1/card", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) + public void getAuthenticatedExtendedCard(RoutingContext rc) { + HTTPRestResponse response = jsonRestHandler.getAuthenticatedExtendedCard(); + sendResponse(rc, response); + } + + @Route(path = "^/v1/.*", order = 100, methods = {Route.HttpMethod.DELETE, Route.HttpMethod.GET, Route.HttpMethod.HEAD, Route.HttpMethod.OPTIONS, Route.HttpMethod.POST, Route.HttpMethod.PUT}, produces = APPLICATION_JSON) + public void methodNotFoundMessage(RoutingContext rc) { + HTTPRestResponse response = jsonRestHandler.createErrorResponse(new MethodNotFoundError_v0_3()); + sendResponse(rc, response); + } + + static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { + streamingMultiSseSupportSubscribedRunnable = runnable; + } + + private ServerCallContext createCallContext(RoutingContext rc, String jsonRpcMethodName) { + if (callContextFactory.isUnsatisfied()) { + User user; + if (rc.user() == null) { + user = UnauthenticatedUser.INSTANCE; + } else { + user = new User() { + @Override + public boolean isAuthenticated() { + if (rc.userContext() != null) { + return rc.userContext().authenticated(); + } + return false; + } + + @Override + public String getUsername() { + if (rc.user() != null) { + String subject = rc.user().subject(); + return subject != null ? subject : ""; + } + return ""; + } + }; + } + Map state = new HashMap<>(); + + Map headers = new HashMap<>(); + Set headerNames = rc.request().headers().names(); + headerNames.forEach(name -> headers.put(name, rc.request().getHeader(name))); + state.put(HEADERS_KEY, headers); + state.put(METHOD_NAME_KEY, jsonRpcMethodName); + + // Extract requested extensions from X-A2A-Extensions header (v0.3 header) + List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders_v0_3.X_A2A_EXTENSIONS); + Set requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues); + + return new ServerCallContext(user, state, requestedExtensions); + } else { + CallContextFactory_v0_3 builder = callContextFactory.get(); + return builder.build(rc); + } + } + + // Port of import io.quarkus.vertx.web.runtime.MultiSseSupport, which is considered internal API + private static class MultiSseSupport { + + private MultiSseSupport() { + // Avoid direct instantiation. + } + + private static void initialize(HttpServerResponse response) { + if (response.bytesWritten() == 0) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + response.setChunked(true); + } + } + + private static void onWriteDone(Flow.@Nullable Subscription subscription, AsyncResult ar, RoutingContext rc) { + if (ar.failed()) { + rc.fail(ar.cause()); + } else if (subscription != null) { + subscription.request(1); + } + } + + private static void write(Multi multi, RoutingContext rc) { + HttpServerResponse response = rc.response(); + multi.subscribe().withSubscriber(new Flow.Subscriber() { + Flow.@Nullable Subscription upstream; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.upstream = subscription; + this.upstream.request(1); + + // Notify tests that we are subscribed + Runnable runnable = streamingMultiSseSupportSubscribedRunnable; + if (runnable != null) { + runnable.run(); + } + } + + @Override + public void onNext(Buffer item) { + initialize(response); + response.write(item, new Handler>() { + @Override + public void handle(AsyncResult ar) { + onWriteDone(upstream, ar, rc); + } + }); + } + + @Override + public void onError(Throwable throwable) { + rc.fail(throwable); + } + + @Override + public void onComplete() { + endOfStream(response); + } + }); + } + + private static void subscribeObject(Multi multi, RoutingContext rc) { + AtomicLong count = new AtomicLong(); + write(multi.map(new Function() { + @Override + public Buffer apply(Object o) { + if (o instanceof ReactiveRoutes.ServerSentEvent) { + ReactiveRoutes.ServerSentEvent ev = (ReactiveRoutes.ServerSentEvent) o; + long id = ev.id() != -1 ? ev.id() : count.getAndIncrement(); + String e = ev.event() == null ? "" : "event: " + ev.event() + "\n"; + return Buffer.buffer(e + "data: " + ev.data() + "\nid: " + id + "\n\n"); + } else { + return Buffer.buffer("data: " + o + "\nid: " + count.getAndIncrement() + "\n\n"); + } + } + }), rc); + } + + private static void endOfStream(HttpServerResponse response) { + if (response.bytesWritten() == 0) { // No item + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + } + response.end(); + } + } +} diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java new file mode 100644 index 000000000..a1f3922c2 --- /dev/null +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java @@ -0,0 +1,8 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import org.a2aproject.sdk.server.ServerCallContext; +import io.vertx.ext.web.RoutingContext; + +public interface CallContextFactory_v0_3 { + ServerCallContext build(RoutingContext rc); +} diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusRestTransportMetadata_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusRestTransportMetadata_v0_3.java new file mode 100644 index 000000000..ea463eba9 --- /dev/null +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusRestTransportMetadata_v0_3.java @@ -0,0 +1,10 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +// TODO: Uncomment when server-common is ported +// See: /Users/kabir/sourcecontrol/AI/a2a-java-0.3.x/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java + +/** + * Placeholder stub - awaiting server-common port. + */ +public class QuarkusRestTransportMetadata_v0_3 { +} diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/package-info.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/package-info.java new file mode 100644 index 000000000..c662c2471 --- /dev/null +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import org.jspecify.annotations.NullMarked; diff --git a/compat-0.3/reference/rest/src/main/resources/META-INF/beans.xml b/compat-0.3/reference/rest/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..548d44b72 --- /dev/null +++ b/compat-0.3/reference/rest/src/main/resources/META-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2ATestRoutes_v0_3.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2ATestRoutes_v0_3.java new file mode 100644 index 000000000..33f0586aa --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2ATestRoutes_v0_3.java @@ -0,0 +1,196 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +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; + +import java.util.concurrent.atomic.AtomicInteger; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import org.a2aproject.sdk.compat03.conversion.TestUtilsBean_v0_3; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import io.quarkus.vertx.web.Body; +import io.quarkus.vertx.web.Param; +import io.quarkus.vertx.web.Route; +import io.vertx.ext.web.RoutingContext; + +/** + * Exposes the {@link TestUtilsBean_v0_3} via REST using Quarkus Reactive Routes + */ +@Singleton +public class A2ATestRoutes_v0_3 { + @Inject + TestUtilsBean_v0_3 testUtilsBean; + + @Inject + A2AServerRoutes_v0_3 a2AServerRoutes; + + AtomicInteger streamingSubscribedCount = new AtomicInteger(0); + + @PostConstruct + public void init() { + A2AServerRoutes_v0_3.setStreamingMultiSseSupportSubscribedRunnable(() -> streamingSubscribedCount.incrementAndGet()); + } + + + @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + public void saveTask(@Body String body, RoutingContext rc) { + try { + Task task = JsonUtil.fromJson(body, Task.class); + testUtilsBean.saveTask(task); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) + public void getTask(@Param String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(JsonUtil.toJson(task)); + + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) + public void deleteTask(@Param String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.deleteTask(taskId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) + public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { + try { + testUtilsBean.ensureQueue(taskId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) + public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + + try { + TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) + public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + + try { + TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/streamingSubscribedCount", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) + public void getStreamingSubscribedCount(RoutingContext rc) { + rc.response() + .setStatusCode(200) + .end(String.valueOf(streamingSubscribedCount.get())); + } + + @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) + public void getChildQueueCount(@Param String taskId, RoutingContext rc) { + int count = testUtilsBean.getChildQueueCount(taskId); + rc.response() + .setStatusCode(200) + .end(String.valueOf(count)); + } + + @Route(path = "/test/task/:taskId/config/:configId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) + public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String configId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) + public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { + try { + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); + if (notificationConfig == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + private void errorResponse(Throwable t, RoutingContext rc) { + t.printStackTrace(); + rc.response() + .setStatusCode(500) + .putHeader(CONTENT_TYPE, TEXT_PLAIN) + .end(); + } + +} diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_Test.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_Test.java new file mode 100644 index 000000000..c371eb538 --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_Test.java @@ -0,0 +1,60 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@QuarkusTest +public class QuarkusA2ARest_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { + + public QuarkusA2ARest_v0_3_Test() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); + } + + @Test + public void testMethodNotFound() throws Exception { + // Create the client + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + // Create the request + HttpRequest.Builder builder = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/v1/message:send")) + .PUT(HttpRequest.BodyPublishers.ofString("test")) + .header("Content-Type", APPLICATION_JSON); + HttpResponse response = client.send(builder.build(), HttpResponse.BodyHandlers.ofString()); + assertEquals(405, response.statusCode()); + builder = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/v1/message:send")) + .DELETE() + .header("Content-Type", APPLICATION_JSON); + response = client.send(builder.build(), HttpResponse.BodyHandlers.ofString()); + assertEquals(405, response.statusCode()); + } +} diff --git a/compat-0.3/reference/rest/src/test/resources/application.properties b/compat-0.3/reference/rest/src/test/resources/application.properties new file mode 100644 index 000000000..3412ec5de --- /dev/null +++ b/compat-0.3/reference/rest/src/test/resources/application.properties @@ -0,0 +1,20 @@ +# HTTP server port for tests +quarkus.http.port=8081 +quarkus.http.test-port=8081 + +# Index dependencies for CDI bean discovery +quarkus.index-dependency.server-conversion.group-id=org.a2aproject.sdk +quarkus.index-dependency.server-conversion.artifact-id=a2a-java-sdk-compat-0.3-server-conversion +quarkus.index-dependency.server-conversion.classifier=tests + +# Index v1.0 server-common for InMemoryTaskStore, DefaultRequestHandler, etc. +quarkus.index-dependency.server-common.group-id=org.a2aproject.sdk +quarkus.index-dependency.server-common.artifact-id=a2a-java-sdk-server-common + +# Use test HTTP client from v0.3 compat test infrastructure +quarkus.arc.selected-alternatives=org.a2aproject.sdk.compat03.conversion.TestHttpClient_v0_3 + +# Debug logging for event processing and request handling +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG diff --git a/compat-0.3/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties b/compat-0.3/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties new file mode 100644 index 000000000..5d8801bfe --- /dev/null +++ b/compat-0.3/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=rest diff --git a/compat-0.3/server-conversion/pom.xml b/compat-0.3/server-conversion/pom.xml new file mode 100644 index 000000000..9f5f3c174 --- /dev/null +++ b/compat-0.3/server-conversion/pom.xml @@ -0,0 +1,140 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + .. + + a2a-java-sdk-compat-0.3-server-conversion + + jar + + Java SDK A2A Compat 0.3 Server Conversion + Java SDK for the Agent2Agent Protocol (A2A) - 0.3 to 1.0 Type Conversion Layer + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + + + ${project.groupId} + a2a-java-sdk-spec + + + + + ${project.groupId} + a2a-java-sdk-server-common + + + + + org.mapstruct + mapstruct + + + + + jakarta.enterprise + jakarta.enterprise.cdi-api + + + jakarta.inject + jakarta.inject-api + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + + + ${project.groupId} + a2a-java-sdk-http-client + test + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + test + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + test + + + + + ${project.groupId} + a2a-java-sdk-server-common + test-jar + test + + + + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + test + + + + + io.quarkus + quarkus-arc + test + + + + + io.rest-assured + rest-assured + test + + + + + jakarta.ws.rs + jakarta.ws.rs-api + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + + diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java new file mode 100644 index 000000000..39773edbb --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java @@ -0,0 +1,385 @@ +package org.a2aproject.sdk.compat03.conversion; + +import java.util.List; +import java.util.concurrent.Flow; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.a2aproject.sdk.compat03.conversion.mappers.domain.EventKindMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.StreamingEventKindMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskPushNotificationConfigMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.params.CancelTaskParamsMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.params.MessageSendParamsMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.params.TaskIdParamsMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.params.TaskQueryParamsMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.result.ListTaskPushNotificationConfigsResultMapper_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.requesthandlers.RequestHandler; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.GetTaskPushNotificationConfigParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskQueryParams; + +/** + * Request handler that converts v0.3 protocol requests to v1.0 and delegates to the v1.0 {@link RequestHandler}. + *

            + * This class acts as an adapter layer between the v0.3 transport handlers and the v1.0 core request handler. + * It accepts v0.3 spec types, converts them to v1.0 types, delegates to the v1.0 DefaultRequestHandler, + * and converts the results back to v0.3 types. + *

            + * Key responsibilities: + *

              + *
            • Convert v0.3 params to v1.0 params using mappers
            • + *
            • Delegate to v1.0 RequestHandler
            • + *
            • Convert v1.0 results back to v0.3 results
            • + *
            • Handle streaming publishers with element-by-element conversion
            • + *
            + *

            + * Method naming differences between v0.3 and v1.0: + *

              + *
            • {@code onSetTaskPushNotificationConfig} (v0.3) → {@code onCreateTaskPushNotificationConfig} (v1.0)
            • + *
            • {@code onResubscribeToTask} (v0.3) → {@code onSubscribeToTask} (v1.0)
            • + *
            • {@code onListTaskPushNotificationConfig} (v0.3) → {@code onListTaskPushNotificationConfigs} (v1.0)
            • + *
            + */ +@ApplicationScoped +public class Convert_v0_3_To10RequestHandler { + + /** + * The v1.0 {@link RequestHandler} to which all converted requests are delegated. + */ + @Inject + public RequestHandler v10Handler; + + /** + * Gets a task by ID. + *

            + * v0.3 → v1.0: Converts TaskQueryParams and Task + * + * @param v03Params the v0.3 task query params + * @param context the server call context + * @return the v0.3 task + * @throws A2AError if an error occurs + */ + public Task_v0_3 onGetTask( + TaskQueryParams_v0_3 v03Params, + ServerCallContext context) throws A2AError { + + // Convert v0.3 params → v1.0 params + TaskQueryParams v10Params = TaskQueryParamsMapper_v0_3.INSTANCE.toV10(v03Params); + + // Call v1.0 handler + Task v10Result = v10Handler.onGetTask(v10Params, context); + + // Convert v1.0 result → v0.3 result + return TaskMapper_v0_3.INSTANCE.fromV10(v10Result); + } + + /** + * Cancels a task. + *

            + * v0.3 → v1.0: Converts TaskIdParams to CancelTaskParams and Task + * + * @param v03Params the v0.3 task ID params + * @param context the server call context + * @return the v0.3 task + * @throws A2AError if an error occurs + */ + public Task_v0_3 onCancelTask( + TaskIdParams_v0_3 v03Params, + ServerCallContext context) throws A2AError { + + // Convert v0.3 TaskIdParams → v1.0 CancelTaskParams + CancelTaskParams v10Params = CancelTaskParamsMapper_v0_3.INSTANCE.toV10(v03Params); + + // Call v1.0 handler + Task v10Result = v10Handler.onCancelTask(v10Params, context); + + // Convert v1.0 result → v0.3 result + return TaskMapper_v0_3.INSTANCE.fromV10(v10Result); + } + + /** + * Sends a message (blocking). + *

            + * v0.3 → v1.0: Converts MessageSendParams and EventKind + * + * @param v03Params the v0.3 message send params + * @param context the server call context + * @return the v0.3 event kind (Task or Message) + * @throws A2AError if an error occurs + */ + public EventKind_v0_3 onMessageSend( + MessageSendParams_v0_3 v03Params, + ServerCallContext context) throws A2AError { + + // Convert v0.3 params → v1.0 params + MessageSendParams v10Params = MessageSendParamsMapper_v0_3.INSTANCE.toV10(v03Params); + + // Enable v0.3 compatibility mode: disable strict context ID validation + // v0.3 allowed messages with both taskId and contextId even if they didn't match + context.getState().put(ServerCallContext.STRICT_CONTEXT_VALIDATION_KEY, false); + + // Call v1.0 handler + EventKind v10Result = v10Handler.onMessageSend(v10Params, context); + + // Convert v1.0 result → v0.3 result + return EventKindMapper_v0_3.INSTANCE.fromV10(v10Result); + } + + /** + * Sends a message (streaming). + *

            + * v0.3 → v1.0: Converts MessageSendParams and streams StreamingEventKind + * + * @param v03Params the v0.3 message send params + * @param context the server call context + * @return publisher of v0.3 streaming event kinds + * @throws A2AError if an error occurs + */ + public Flow.Publisher onMessageSendStream( + MessageSendParams_v0_3 v03Params, + ServerCallContext context) throws A2AError { + + // Convert v0.3 params → v1.0 params + MessageSendParams v10Params = MessageSendParamsMapper_v0_3.INSTANCE.toV10(v03Params); + + // Enable v0.3 compatibility mode: disable strict context ID validation + // v0.3 allowed messages with both taskId and contextId even if they didn't match + context.getState().put(ServerCallContext.STRICT_CONTEXT_VALIDATION_KEY, false); + + // Get v1.0 publisher + Flow.Publisher v10Publisher = + v10Handler.onMessageSendStream(v10Params, context); + + // Convert each event using a mapping processor + return convertPublisher(v10Publisher, StreamingEventKindMapper_v0_3.INSTANCE::fromV10); + } + + /** + * Sets (creates) a task push notification configuration. + *

            + * v0.3 method name: {@code onSetTaskPushNotificationConfig} + * v1.0 method name: {@code onCreateTaskPushNotificationConfig} + * + * @param v03Config the v0.3 task push notification config + * @param context the server call context + * @return the v0.3 task push notification config + * @throws A2AError if an error occurs + */ + public TaskPushNotificationConfig_v0_3 onSetTaskPushNotificationConfig( + TaskPushNotificationConfig_v0_3 v03Config, + ServerCallContext context) throws A2AError { + + // Convert v0.3 config → v1.0 config + TaskPushNotificationConfig v10Config = + TaskPushNotificationConfigMapper_v0_3.INSTANCE.toV10(v03Config); + + // Call v1.0 handler + TaskPushNotificationConfig v10Result = + v10Handler.onCreateTaskPushNotificationConfig(v10Config, context); + + // Convert v1.0 result → v0.3 result + return TaskPushNotificationConfigMapper_v0_3.INSTANCE.fromV10(v10Result); + } + + /** + * Gets a task push notification configuration. + *

            + * v0.3 → v1.0: Converts GetTaskPushNotificationConfigParams and TaskPushNotificationConfig + *

            + * v0.3 semantics: If a specific pushNotificationConfigId is provided but not found, + * fall back to returning the first config (lenient behavior). + * + * @param v03Params the v0.3 get params + * @param context the server call context + * @return the v0.3 task push notification config + * @throws A2AError if an error occurs + */ + public TaskPushNotificationConfig_v0_3 onGetTaskPushNotificationConfig( + GetTaskPushNotificationConfigParams_v0_3 v03Params, + ServerCallContext context) throws A2AError { + + // Convert v0.3 params → v1.0 params + // v0.3: id = taskId, pushNotificationConfigId = optional config id + // v1.0: taskId = taskId, id = config id (defaults to taskId if not specified) + String configId = v03Params.pushNotificationConfigId() != null + ? v03Params.pushNotificationConfigId() + : v03Params.id(); // Default to taskId when config id not specified + + GetTaskPushNotificationConfigParams v10Params = + new GetTaskPushNotificationConfigParams(v03Params.id(), configId); + + TaskPushNotificationConfig v10Result; + try { + // Call v1.0 handler + v10Result = v10Handler.onGetTaskPushNotificationConfig(v10Params, context); + } catch (TaskNotFoundError e) { + // v0.3 fallback behavior: if specific config ID not found, return first config + // This matches v0.3 DefaultRequestHandler.getPushNotificationConfig() behavior + if (v03Params.pushNotificationConfigId() != null) { + ListTaskPushNotificationConfigsParams listParams = + new ListTaskPushNotificationConfigsParams(v03Params.id()); + ListTaskPushNotificationConfigsResult listResult = + v10Handler.onListTaskPushNotificationConfigs(listParams, context); + + if (listResult.configs().isEmpty()) { + throw e; // Re-throw if no configs exist at all + } + // Return first config as fallback + v10Result = listResult.configs().get(0); + } else { + throw e; // Re-throw if no fallback is applicable + } + } + + // Convert v1.0 result → v0.3 result + return TaskPushNotificationConfigMapper_v0_3.INSTANCE.fromV10(v10Result); + } + + /** + * Resubscribes to task updates (streaming). + *

            + * v0.3 method name: {@code onResubscribeToTask} + * v1.0 method name: {@code onSubscribeToTask} + * + * @param v03Params the v0.3 task ID params + * @param context the server call context + * @return publisher of v0.3 streaming event kinds + * @throws A2AError if an error occurs + */ + public Flow.Publisher onResubscribeToTask( + TaskIdParams_v0_3 v03Params, + ServerCallContext context) throws A2AError { + + // Convert v0.3 params → v1.0 params + TaskIdParams v10Params = TaskIdParamsMapper_v0_3.INSTANCE.toV10(v03Params); + + // Get v1.0 publisher + Flow.Publisher v10Publisher = + v10Handler.onSubscribeToTask(v10Params, context); + + // Convert each event using a mapping processor + return convertPublisher(v10Publisher, StreamingEventKindMapper_v0_3.INSTANCE::fromV10); + } + + /** + * Lists task push notification configurations. + *

            + * v0.3 → v1.0: Converts params and result (List → ListTaskPushNotificationConfigsResult) + * + * @param v03Params the v0.3 list params + * @param context the server call context + * @return list of v0.3 task push notification configs + * @throws A2AError if an error occurs + */ + public List onListTaskPushNotificationConfig( + ListTaskPushNotificationConfigParams_v0_3 v03Params, + ServerCallContext context) throws A2AError { + + // Convert v0.3 params → v1.0 params + // ListTaskPushNotificationConfigParams has different structure - v0.3 has id, v1.0 has more fields + ListTaskPushNotificationConfigsParams v10Params = + new ListTaskPushNotificationConfigsParams( + v03Params.id(), + 0, // No pageSize in v0.3 - use 0 (will use default) + "", // No pageToken in v0.3 - use empty string + "" // Default tenant + ); + + // Call v1.0 handler + ListTaskPushNotificationConfigsResult v10Result = + v10Handler.onListTaskPushNotificationConfigs(v10Params, context); + + // Convert v1.0 result → v0.3 result (extract list from result wrapper) + return ListTaskPushNotificationConfigsResultMapper_v0_3.INSTANCE.fromV10(v10Result); + } + + /** + * Deletes a task push notification configuration. + *

            + * v0.3 → v1.0: Converts DeleteTaskPushNotificationConfigParams (adds tenant field) + * + * @param v03Params the v0.3 delete params + * @param context the server call context + * @throws A2AError if an error occurs + */ + public void onDeleteTaskPushNotificationConfig( + DeleteTaskPushNotificationConfigParams_v0_3 v03Params, + ServerCallContext context) throws A2AError { + + // Convert v0.3 params → v1.0 params (add tenant field) + DeleteTaskPushNotificationConfigParams v10Params = + new DeleteTaskPushNotificationConfigParams( + v03Params.id(), + v03Params.pushNotificationConfigId(), + "" // Default tenant + ); + + // Call v1.0 handler + v10Handler.onDeleteTaskPushNotificationConfig(v10Params, context); + } + + /** + * Converts a v1.0 publisher to a v0.3 publisher by applying a mapper to each element. + * + * @param v10Publisher the v1.0 publisher + * @param mapper function to convert each v1.0 element to v0.3 + * @param the v1.0 element type + * @param the v0.3 element type + * @return publisher of v0.3 elements + */ + private Flow.Publisher convertPublisher( + Flow.Publisher v10Publisher, + java.util.function.Function mapper) { + + return subscriber -> v10Publisher.subscribe(new Flow.Subscriber() { + @Override + public void onSubscribe(Flow.Subscription subscription) { + subscriber.onSubscribe(subscription); + } + + @Override + public void onNext(V10 v10Item) { + try { + V03 v03Item = mapper.apply(v10Item); + subscriber.onNext(v03Item); + } catch (Exception e) { + subscriber.onError(e); + } + } + + @Override + public void onError(Throwable throwable) { + subscriber.onError(throwable); + } + + @Override + public void onComplete() { + subscriber.onComplete(); + } + }); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/ErrorConverter_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/ErrorConverter_v0_3.java new file mode 100644 index 000000000..4e5c51a2c --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/ErrorConverter_v0_3.java @@ -0,0 +1,91 @@ +package org.a2aproject.sdk.compat03.conversion; + +import org.a2aproject.sdk.compat03.spec.AuthenticatedExtendedCardNotConfiguredError_v0_3; +import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.ContentTypeNotSupportedError; +import org.a2aproject.sdk.spec.ExtendedAgentCardNotConfiguredError; +import org.a2aproject.sdk.spec.InternalError; +import org.a2aproject.sdk.spec.InvalidAgentResponseError; +import org.a2aproject.sdk.spec.InvalidParamsError; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.JSONParseError; +import org.a2aproject.sdk.spec.MethodNotFoundError; +import org.a2aproject.sdk.spec.PushNotificationNotSupportedError; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.UnsupportedOperationError; + +/** + * Utility for converting v1.0 A2AError instances to v0.3 JSONRPCError instances. + *

            + * This converter preserves specific error types to ensure proper status code mapping + * in transport handlers (REST HTTP status codes, gRPC status codes, etc.). + *

            + */ +public final class ErrorConverter_v0_3 { + + private ErrorConverter_v0_3() { + // Utility class + } + + /** + * Converts a v1.0 A2AError to a v0.3 JSONRPCError. + *

            + * Since A2AError in v0.3 is an interface and JSONRPCError is the concrete implementation, + * we need to convert the v1.0 A2AError to the v0.3 JSONRPCError type. + * This method preserves specific error types by using instanceof checks to map + * v1.0 errors to their v0.3 equivalents. + *

            + * + * @param v10Error the v1.0 A2AError to convert + * @return the equivalent v0.3 JSONRPCError, preserving the specific error type + */ + public static JSONRPCError_v0_3 convertA2AError(A2AError v10Error) { + // A2AError from v1.0 has: code, message (via getMessage()), details + // JSONRPCError from v0.3 has: code, message (via getMessage()), data + // Preserve exact error code, message, and details from v1.0 error + + // Preserve specific error types by mapping v1.0 errors to v0.3 equivalents + if (v10Error instanceof TaskNotFoundError) { + return new TaskNotFoundError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof UnsupportedOperationError) { + return new UnsupportedOperationError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof TaskNotCancelableError) { + return new TaskNotCancelableError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof InvalidParamsError) { + return new InvalidParamsError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof InvalidRequestError) { + return new InvalidRequestError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof InternalError) { + return new InternalError_v0_3(v10Error.getMessage()); + } else if (v10Error instanceof InvalidAgentResponseError) { + return new InvalidAgentResponseError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof ContentTypeNotSupportedError) { + return new ContentTypeNotSupportedError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof PushNotificationNotSupportedError) { + return new PushNotificationNotSupportedError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof MethodNotFoundError) { + return new MethodNotFoundError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof JSONParseError) { + return new JSONParseError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } else if (v10Error instanceof ExtendedAgentCardNotConfiguredError) { + return new AuthenticatedExtendedCardNotConfiguredError_v0_3( + v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } + + // Fallback to generic JSONRPCError for unmapped types + return new JSONRPCError_v0_3(v10Error.getCode(), v10Error.getMessage(), v10Error.getDetails()); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/config/A03ToV10MapperConfig.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/config/A03ToV10MapperConfig.java new file mode 100644 index 000000000..4067ef9f2 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/config/A03ToV10MapperConfig.java @@ -0,0 +1,42 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.config; + +import org.mapstruct.MapperConfig; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.mapstruct.ReportingPolicy; + +/** + * Global MapStruct configuration for converting between A2A Protocol v0.3 and v1.0 types. + *

            + * This configuration interface provides shared settings and default conversion methods + * used by all mappers in the compat-0.3 conversion layer. It ensures consistent handling + * of unmapped fields, null values, and component instantiation across the codebase. + *

            + * Key Configuration: + *

              + *
            • unmappedTargetPolicy = ERROR: Compile-time validation ensures no fields are missed
            • + *
            • componentModel = "default": Uses singleton pattern via {@link A2AMappers_v0_3} factory
            • + *
            • nullValuePropertyMappingStrategy = IGNORE: Skip null source properties during mapping
            • + *
            + * + * @see A2AMappers_v0_3 + */ +@MapperConfig( + unmappedTargetPolicy = ReportingPolicy.ERROR, + componentModel = "default", + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE +) +public interface A03ToV10MapperConfig { + + /** + * Default tenant value for conversions from 0.3 to 1.0. + *

            + * The 1.0 protocol adds a tenant field that doesn't exist in 0.3. + * When converting from 0.3 to 1.0, we use an empty string as the default tenant, + * matching the 1.0 MessageSendParams convenience constructor default. + * + * @return empty string as default tenant + */ + default String tenantDefault() { + return ""; + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/config/A2AMappers_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/config/A2AMappers_v0_3.java new file mode 100644 index 000000000..2bdb85967 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/config/A2AMappers_v0_3.java @@ -0,0 +1,69 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.config; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Singleton factory for MapStruct mapper instances in the v0.3 to v1.0 conversion layer. + *

            + * This factory provides centralized access to mapper implementations, ensuring that + * each mapper interface has exactly one instance (singleton pattern). MapStruct + * generates implementation classes with an "Impl" suffix at compile time, and this + * factory uses reflection to instantiate and cache them. + *

            + * Example usage: + *

            {@code
            + * public interface TaskStateMapper {
            + *     TaskStateMapper INSTANCE = A03Mappers.getMapper(TaskStateMapper.class);
            + *
            + *     org.a2aproject.sdk.spec.TaskState toV10(
            + *         org.a2aproject.sdk.compat03.spec.TaskState v03);
            + * }
            + * }
            + * + * Thread Safety: This factory uses {@link ConcurrentHashMap} to ensure thread-safe + * lazy initialization of mapper instances. + * + * @see A03ToV10MapperConfig + */ +public final class A2AMappers_v0_3 { + + /** + * Cache of instantiated mapper instances. + * Key: Mapper interface class, Value: Singleton mapper instance + */ + private static final Map, Object> MAPPERS = new ConcurrentHashMap<>(); + + /** + * Private constructor to prevent instantiation. + */ + private A2AMappers_v0_3() { + throw new UnsupportedOperationException("Utility class cannot be instantiated"); + } + + /** + * Returns the singleton instance of the specified mapper interface. + *

            + * This method uses reflection to load the MapStruct-generated implementation class + * (interface name + "Impl" suffix) and caches it for future use. If the implementation + * class cannot be loaded or instantiated, a {@link RuntimeException} is thrown. + * + * @param mapperInterface the mapper interface class (e.g., {@code TaskStateMapper.class}) + * @param the mapper type + * @return the singleton instance of the mapper + * @throws RuntimeException if the mapper implementation cannot be loaded or instantiated + */ + @SuppressWarnings("unchecked") + public static T getMapper(Class mapperInterface) { + return (T) MAPPERS.computeIfAbsent(mapperInterface, clazz -> { + try { + // MapStruct generates implementation with "Impl" suffix + String implName = clazz.getName() + "Impl"; + Class implClass = Class.forName(implName); + return implClass.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Failed to load mapper: " + clazz.getName(), e); + } + }); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/ArtifactMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/ArtifactMapper_v0_3.java new file mode 100644 index 000000000..166842cbb --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/ArtifactMapper_v0_3.java @@ -0,0 +1,83 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import java.util.List; +import java.util.stream.Collectors; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Part; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting Artifact between A2A Protocol v0.3 and v1.0. + *

            + * Both versions are records with the same structure: + * {@code Artifact(artifactId, name, description, parts, metadata, extensions)}. + *

            + * The conversion primarily involves converting the nested {@link Part} list using {@link PartMapper_v0_3}. + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {PartMapper_v0_3.class}) +public interface ArtifactMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + ArtifactMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(ArtifactMapper_v0_3.class); + + /** + * Converts v0.3 Artifact to v1.0 Artifact. + *

            + * Converts all Part instances in the parts list using PartMapper. + * + * @param v03 the v0.3 artifact + * @return the equivalent v1.0 artifact + */ + default Artifact toV10(Artifact_v0_3 v03) { + if (v03 == null) { + return null; + } + + List> parts = v03.parts().stream() + .map(PartMapper_v0_3.INSTANCE::toV10) + .collect(Collectors.toList()); + + return new Artifact( + v03.artifactId(), + v03.name(), + v03.description(), + parts, + v03.metadata(), + v03.extensions() + ); + } + + /** + * Converts v1.0 Artifact to v0.3 Artifact. + *

            + * Converts all Part instances in the parts list using PartMapper. + * + * @param v10 the v1.0 artifact + * @return the equivalent v0.3 artifact + */ + default Artifact_v0_3 fromV10(Artifact v10) { + if (v10 == null) { + return null; + } + + List> parts = v10.parts().stream() + .map(PartMapper_v0_3.INSTANCE::fromV10) + .collect(Collectors.toList()); + + return new Artifact_v0_3( + v10.artifactId(), + v10.name(), + v10.description(), + parts, + v10.metadata(), + v10.extensions() + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/AuthenticationInfoMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/AuthenticationInfoMapper_v0_3.java new file mode 100644 index 000000000..f0c1106a3 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/AuthenticationInfoMapper_v0_3.java @@ -0,0 +1,119 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import java.util.List; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.AuthenticationInfo_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationAuthenticationInfo_v0_3; +import org.a2aproject.sdk.spec.AuthenticationInfo; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting AuthenticationInfo between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: {@code AuthenticationInfo(List schemes, String credentials)} - supports multiple schemes
            • + *
            • v1.0: {@code AuthenticationInfo(String scheme, String credentials)} - single scheme only
            • + *
            + *

            + * Conversion strategy: + *

              + *
            • v0.3 → v1.0: Takes the first scheme from the list (or empty string if list is empty)
            • + *
            • v1.0 → v0.3: Wraps the single scheme in a list
            • + *
            + *

            + * Note: v0.3 also has {@code PushNotificationAuthenticationInfo} which has the same structure + * as v0.3 {@code AuthenticationInfo}, so this mapper handles both. + */ +@Mapper(config = A03ToV10MapperConfig.class) +public interface AuthenticationInfoMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + AuthenticationInfoMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(AuthenticationInfoMapper_v0_3.class); + + /** + * Converts v0.3 AuthenticationInfo to v1.0 AuthenticationInfo. + *

            + * Takes the first scheme from the v0.3 schemes list. If the list is empty or null, + * uses an empty string for the v1.0 scheme. + * + * @param v03 the v0.3 authentication info + * @return the equivalent v1.0 authentication info + */ + default AuthenticationInfo toV10(AuthenticationInfo_v0_3 v03) { + if (v03 == null) { + return null; + } + + String scheme = (v03.schemes() != null && !v03.schemes().isEmpty()) + ? v03.schemes().get(0) + : ""; + + return new AuthenticationInfo(scheme, v03.credentials()); + } + + /** + * Converts v0.3 PushNotificationAuthenticationInfo to v1.0 AuthenticationInfo. + *

            + * Takes the first scheme from the v0.3 schemes list. If the list is empty or null, + * uses an empty string for the v1.0 scheme. + * + * @param v03 the v0.3 push notification authentication info + * @return the equivalent v1.0 authentication info + */ + default AuthenticationInfo toV10FromPushNotification( + PushNotificationAuthenticationInfo_v0_3 v03) { + if (v03 == null) { + return null; + } + + String scheme = (v03.schemes() != null && !v03.schemes().isEmpty()) + ? v03.schemes().get(0) + : ""; + + return new AuthenticationInfo(scheme, v03.credentials()); + } + + /** + * Converts v1.0 AuthenticationInfo to v0.3 AuthenticationInfo. + *

            + * Wraps the v1.0 single scheme in a list for v0.3. + * + * @param v10 the v1.0 authentication info + * @return the equivalent v0.3 authentication info + */ + default AuthenticationInfo_v0_3 fromV10(AuthenticationInfo v10) { + if (v10 == null) { + return null; + } + + return new AuthenticationInfo_v0_3( + List.of(v10.scheme()), + v10.credentials() + ); + } + + /** + * Converts v1.0 AuthenticationInfo to v0.3 PushNotificationAuthenticationInfo. + *

            + * Wraps the v1.0 single scheme in a list for v0.3. + * + * @param v10 the v1.0 authentication info + * @return the equivalent v0.3 push notification authentication info + */ + default PushNotificationAuthenticationInfo_v0_3 fromV10ToPushNotification( + AuthenticationInfo v10) { + if (v10 == null) { + return null; + } + + return new PushNotificationAuthenticationInfo_v0_3( + List.of(v10.scheme()), + v10.credentials() + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/EventKindMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/EventKindMapper_v0_3.java new file mode 100644 index 000000000..e8fffde04 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/EventKindMapper_v0_3.java @@ -0,0 +1,97 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.spec.EventKind; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.mapstruct.Mapper; + +/** + * Bidirectional polymorphic mapper for converting EventKind between A2A Protocol v0.3 and v1.0. + *

            + * Handles conversion for all EventKind implementers: + *

              + *
            • {@link Task}
            • + *
            • {@link Message}
            • + *
            • {@link TaskStatusUpdateEvent}
            • + *
            • {@link TaskArtifactUpdateEvent}
            • + *
            + *

            + * Uses instanceof dispatch to determine the concrete type and delegates to the appropriate mapper. + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = { + TaskMapper_v0_3.class, + MessageMapper_v0_3.class, + TaskStatusUpdateEventMapper_v0_3.class, + TaskArtifactUpdateEventMapper_v0_3.class +}) +public interface EventKindMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + EventKindMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(EventKindMapper_v0_3.class); + + /** + * Converts v0.3 EventKind to v1.0 EventKind. + *

            + * Uses instanceof dispatch to determine the concrete type and delegates to the appropriate mapper. + * + * @param v03 the v0.3 event kind + * @return the equivalent v1.0 event kind + * @throws InvalidRequestError if the event kind type is unrecognized + */ + default EventKind toV10(EventKind_v0_3 v03) { + if (v03 == null) { + return null; + } + + if (v03 instanceof Task_v0_3 v03Task) { + return TaskMapper_v0_3.INSTANCE.toV10(v03Task); + } else if (v03 instanceof Message_v0_3 v03Message) { + return MessageMapper_v0_3.INSTANCE.toV10(v03Message); + } else if (v03 instanceof TaskStatusUpdateEvent_v0_3 v03StatusUpdate) { + return TaskStatusUpdateEventMapper_v0_3.INSTANCE.toV10(v03StatusUpdate); + } else if (v03 instanceof TaskArtifactUpdateEvent_v0_3 v03ArtifactUpdate) { + return TaskArtifactUpdateEventMapper_v0_3.INSTANCE.toV10(v03ArtifactUpdate); + } + + throw new InvalidRequestError(null, "Unrecognized EventKind type: " + v03.getClass().getName(), null); + } + + /** + * Converts v1.0 EventKind to v0.3 EventKind. + *

            + * Uses instanceof dispatch to determine the concrete type and delegates to the appropriate mapper. + * + * @param v10 the v1.0 event kind + * @return the equivalent v0.3 event kind + * @throws InvalidRequestError if the event kind type is unrecognized + */ + default EventKind_v0_3 fromV10(EventKind v10) { + if (v10 == null) { + return null; + } + + if (v10 instanceof Task v10Task) { + return TaskMapper_v0_3.INSTANCE.fromV10(v10Task); + } else if (v10 instanceof Message v10Message) { + return MessageMapper_v0_3.INSTANCE.fromV10(v10Message); + } else if (v10 instanceof TaskStatusUpdateEvent v10StatusUpdate) { + return TaskStatusUpdateEventMapper_v0_3.INSTANCE.fromV10(v10StatusUpdate); + } else if (v10 instanceof TaskArtifactUpdateEvent v10ArtifactUpdate) { + return TaskArtifactUpdateEventMapper_v0_3.INSTANCE.fromV10(v10ArtifactUpdate); + } + + throw new InvalidRequestError(null, "Unrecognized EventKind type: " + v10.getClass().getName(), null); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/FileContentMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/FileContentMapper_v0_3.java new file mode 100644 index 000000000..c77998042 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/FileContentMapper_v0_3.java @@ -0,0 +1,92 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.FileContent_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithBytes_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithUri_v0_3; +import org.a2aproject.sdk.spec.FileContent; +import org.a2aproject.sdk.spec.FileWithBytes; +import org.a2aproject.sdk.spec.FileWithUri; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting FileContent types between A2A Protocol v0.3 and v1.0. + *

            + * Handles polymorphic FileContent conversion for: + *

              + *
            • {@link FileWithBytes_v0_3} ↔ {@link FileWithBytes}
            • + *
            • {@link FileWithUri_v0_3} ↔ {@link FileWithUri}
            • + *
            + *

            + * Key differences: + *

              + *
            • v0.3: FileWithBytes and FileWithUri are simple records
            • + *
            • v1.0: FileWithBytes is a complex class with lazy loading; FileWithUri is a simple record
            • + *
            + *

            + * The conversion preserves the mimeType, name, and content (bytes or uri) fields across both versions. + */ +@Mapper(config = A03ToV10MapperConfig.class) +public interface FileContentMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + FileContentMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(FileContentMapper_v0_3.class); + + /** + * Converts v0.3 FileContent to v1.0 FileContent. + *

            + * Handles FileWithBytes and FileWithUri polymorphism using instanceof dispatch. + * + * @param v03 the v0.3 file content + * @return the equivalent v1.0 file content + * @throws InvalidRequestError if the file content type is unrecognized + */ + default FileContent toV10(FileContent_v0_3 v03) { + if (v03 == null) { + return null; + } + + if (v03 instanceof FileWithBytes_v0_3 v03Bytes) { + return new FileWithBytes(v03Bytes.mimeType(), v03Bytes.name(), v03Bytes.bytes()); + } else if (v03 instanceof FileWithUri_v0_3 v03Uri) { + return new FileWithUri(v03Uri.mimeType(), v03Uri.name(), v03Uri.uri()); + } + + throw new InvalidRequestError(null, "Unrecognized FileContent type: " + v03.getClass().getName(), null); + } + + /** + * Converts v1.0 FileContent to v0.3 FileContent. + *

            + * Handles FileWithBytes and FileWithUri polymorphism using instanceof dispatch. + * + * @param v10 the v1.0 file content + * @return the equivalent v0.3 file content + * @throws InvalidRequestError if the file content type is unrecognized + */ + default FileContent_v0_3 fromV10(FileContent v10) { + if (v10 == null) { + return null; + } + + if (v10 instanceof FileWithBytes v10Bytes) { + return new FileWithBytes_v0_3( + v10Bytes.mimeType(), + v10Bytes.name(), + v10Bytes.bytes() + ); + } else if (v10 instanceof FileWithUri v10Uri) { + return new FileWithUri_v0_3( + v10Uri.mimeType(), + v10Uri.name(), + v10Uri.uri() + ); + } + + throw new InvalidRequestError(null, "Unrecognized FileContent type: " + v10.getClass().getName(), null); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/MessageMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/MessageMapper_v0_3.java new file mode 100644 index 000000000..2c5a71528 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/MessageMapper_v0_3.java @@ -0,0 +1,96 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import java.util.List; +import java.util.stream.Collectors; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Part; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting Message between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: Message is a class with getter methods (e.g., {@code getRole()}, {@code getParts()})
            • + *
            • v1.0: Message is a record with accessor methods (e.g., {@code role()}, {@code parts()})
            • + *
            • Role enum values have "ROLE_" prefix in v1.0
            • + *
            • Part types (TextPart, FilePart, DataPart) changed from classes to records in v1.0
            • + *
            + *

            + * Uses {@link RoleMapper_v0_3} and {@link PartMapper_v0_3} for nested conversions. + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {RoleMapper_v0_3.class, PartMapper_v0_3.class}) +public interface MessageMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + MessageMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(MessageMapper_v0_3.class); + + /** + * Converts v0.3 Message to v1.0 Message. + *

            + * Converts all fields including role, parts, messageId, contextId, taskId, + * referenceTaskIds, metadata, and extensions. + * + * @param v03 the v0.3 message + * @return the equivalent v1.0 message + */ + default Message toV10(Message_v0_3 v03) { + if (v03 == null) { + return null; + } + + Message.Role role = RoleMapper_v0_3.INSTANCE.toV10(v03.getRole()); + List> parts = v03.getParts().stream() + .map(PartMapper_v0_3.INSTANCE::toV10) + .collect(Collectors.toList()); + + return new Message( + role, + parts, + v03.getMessageId(), + v03.getContextId(), + v03.getTaskId(), + v03.getReferenceTaskIds(), + v03.getMetadata(), + v03.getExtensions() + ); + } + + /** + * Converts v1.0 Message to v0.3 Message. + *

            + * Converts all fields including role, parts, messageId, contextId, taskId, + * referenceTaskIds, metadata, and extensions. + * + * @param v10 the v1.0 message + * @return the equivalent v0.3 message + */ + default Message_v0_3 fromV10(Message v10) { + if (v10 == null) { + return null; + } + + Message_v0_3.Role role = RoleMapper_v0_3.INSTANCE.fromV10(v10.role()); + List> parts = v10.parts().stream() + .map(PartMapper_v0_3.INSTANCE::fromV10) + .collect(Collectors.toList()); + + return new Message_v0_3( + role, + parts, + v10.messageId(), + v10.contextId(), + v10.taskId(), + v10.referenceTaskIds(), + v10.metadata(), + v10.extensions() + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/PartMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/PartMapper_v0_3.java new file mode 100644 index 000000000..5da63952e --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/PartMapper_v0_3.java @@ -0,0 +1,104 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.DataPart_v0_3; +import org.a2aproject.sdk.compat03.spec.FilePart_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.FilePart; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.Part; +import org.a2aproject.sdk.spec.TextPart; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting Part types between A2A Protocol v0.3 and v1.0. + *

            + * Handles polymorphic Part conversion for: + *

              + *
            • {@link TextPart_v0_3} ↔ {@link TextPart}
            • + *
            • {@link FilePart_v0_3} ↔ {@link FilePart}
            • + *
            • {@link DataPart_v0_3} ↔ {@link DataPart}
            • + *
            + *

            + * Key differences: + *

              + *
            • v0.3: Part types are classes with getter methods (e.g., {@code getText()}, {@code getMetadata()})
            • + *
            • v1.0: Part types are records with accessor methods (e.g., {@code text()}, {@code metadata()})
            • + *
            + *

            + * Uses manual instanceof dispatch to handle polymorphic conversion. + */ +@Mapper(config = A03ToV10MapperConfig.class) +public interface PartMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + PartMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(PartMapper_v0_3.class); + + /** + * Converts v0.3 Part to v1.0 Part. + *

            + * Handles TextPart, FilePart, and DataPart polymorphism using instanceof dispatch. + * + * @param v03 the v0.3 part + * @return the equivalent v1.0 part + * @throws InvalidRequestError if the part type is unrecognized + */ + default Part toV10(Part_v0_3 v03) { + if (v03 == null) { + return null; + } + + if (v03 instanceof TextPart_v0_3 v03Text) { + return new TextPart(v03Text.getText(), v03Text.getMetadata()); + } else if (v03 instanceof FilePart_v0_3 v03File) { + return new FilePart( + FileContentMapper_v0_3.INSTANCE.toV10(v03File.getFile()), + v03File.getMetadata() + ); + } else if (v03 instanceof DataPart_v0_3 v03Data) { + return new DataPart(v03Data.getData(), v03Data.getMetadata()); + } + + throw new InvalidRequestError(null, "Unrecognized Part type: " + v03.getClass().getName(), null); + } + + /** + * Converts v1.0 Part to v0.3 Part. + *

            + * Handles TextPart, FilePart, and DataPart polymorphism using instanceof dispatch. + * + * @param v10 the v1.0 part + * @return the equivalent v0.3 part + * @throws InvalidRequestError if the part type is unrecognized + */ + default Part_v0_3 fromV10(Part v10) { + if (v10 == null) { + return null; + } + + if (v10 instanceof TextPart v10Text) { + return new TextPart_v0_3(v10Text.text(), v10Text.metadata()); + } else if (v10 instanceof FilePart v10File) { + return new FilePart_v0_3( + FileContentMapper_v0_3.INSTANCE.fromV10(v10File.file()), + v10File.metadata() + ); + } else if (v10 instanceof DataPart v10Data) { + // v1.0 DataPart.data() returns Object, but v0.3 expects Map + Object data = v10Data.data(); + if (!(data instanceof java.util.Map)) { + throw new InvalidRequestError(null, "DataPart data must be a Map for v0.3 compatibility", null); + } + @SuppressWarnings("unchecked") + java.util.Map dataMap = (java.util.Map) data; + return new DataPart_v0_3(dataMap, v10Data.metadata()); + } + + throw new InvalidRequestError(null, "Unrecognized Part type: " + v10.getClass().getName(), null); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/RoleMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/RoleMapper_v0_3.java new file mode 100644 index 000000000..2ae2dc733 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/RoleMapper_v0_3.java @@ -0,0 +1,60 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.spec.Message; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting Message.Role enum between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: {@code USER}, {@code AGENT}
            • + *
            • v1.0: {@code ROLE_USER}, {@code ROLE_AGENT}
            • + *
            + *

            + * The v1.0 enum adds a "ROLE_" prefix to align with protocol buffer conventions. + */ +@Mapper(config = A03ToV10MapperConfig.class) +public interface RoleMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + RoleMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(RoleMapper_v0_3.class); + + /** + * Converts v0.3 Role to v1.0 Role. + * + * @param v03 the v0.3 role + * @return the equivalent v1.0 role + */ + default Message.Role toV10(Message_v0_3.Role v03) { + if (v03 == null) { + return null; + } + return switch (v03) { + case USER -> Message.Role.ROLE_USER; + case AGENT -> Message.Role.ROLE_AGENT; + }; + } + + /** + * Converts v1.0 Role to v0.3 Role. + * + * @param v10 the v1.0 role + * @return the equivalent v0.3 role + */ + default Message_v0_3.Role fromV10(Message.Role v10) { + if (v10 == null) { + return null; + } + return switch (v10) { + case ROLE_USER -> Message_v0_3.Role.USER; + case ROLE_AGENT -> Message_v0_3.Role.AGENT; + default -> throw new IllegalArgumentException("Unrecognized Role: " + v10); + }; + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/StreamingEventKindMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/StreamingEventKindMapper_v0_3.java new file mode 100644 index 000000000..8a3fe90df --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/StreamingEventKindMapper_v0_3.java @@ -0,0 +1,100 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.spec.InvalidRequestError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.mapstruct.Mapper; + +/** + * Bidirectional polymorphic mapper for converting StreamingEventKind between A2A Protocol v0.3 and v1.0. + *

            + * Handles conversion for all StreamingEventKind implementers: + *

              + *
            • {@link Task}
            • + *
            • {@link Message}
            • + *
            • {@link TaskStatusUpdateEvent}
            • + *
            • {@link TaskArtifactUpdateEvent}
            • + *
            + *

            + * Uses instanceof dispatch to determine the concrete type and delegates to the appropriate mapper. + *

            + * Note: The same types implement both {@link org.a2aproject.sdk.spec.EventKind} and + * {@link StreamingEventKind}, so this mapper uses the same delegation logic as {@link EventKindMapper_v0_3}. + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = { + TaskMapper_v0_3.class, + MessageMapper_v0_3.class, + TaskStatusUpdateEventMapper_v0_3.class, + TaskArtifactUpdateEventMapper_v0_3.class +}) +public interface StreamingEventKindMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + StreamingEventKindMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(StreamingEventKindMapper_v0_3.class); + + /** + * Converts v0.3 StreamingEventKind to v1.0 StreamingEventKind. + *

            + * Uses instanceof dispatch to determine the concrete type and delegates to the appropriate mapper. + * + * @param v03 the v0.3 streaming event kind + * @return the equivalent v1.0 streaming event kind + * @throws InvalidRequestError if the streaming event kind type is unrecognized + */ + default StreamingEventKind toV10(StreamingEventKind_v0_3 v03) { + if (v03 == null) { + return null; + } + + if (v03 instanceof Task_v0_3 v03Task) { + return TaskMapper_v0_3.INSTANCE.toV10(v03Task); + } else if (v03 instanceof Message_v0_3 v03Message) { + return MessageMapper_v0_3.INSTANCE.toV10(v03Message); + } else if (v03 instanceof TaskStatusUpdateEvent_v0_3 v03StatusUpdate) { + return TaskStatusUpdateEventMapper_v0_3.INSTANCE.toV10(v03StatusUpdate); + } else if (v03 instanceof TaskArtifactUpdateEvent_v0_3 v03ArtifactUpdate) { + return TaskArtifactUpdateEventMapper_v0_3.INSTANCE.toV10(v03ArtifactUpdate); + } + + throw new InvalidRequestError(null, "Unrecognized StreamingEventKind type: " + v03.getClass().getName(), null); + } + + /** + * Converts v1.0 StreamingEventKind to v0.3 StreamingEventKind. + *

            + * Uses instanceof dispatch to determine the concrete type and delegates to the appropriate mapper. + * + * @param v10 the v1.0 streaming event kind + * @return the equivalent v0.3 streaming event kind + * @throws InvalidRequestError if the streaming event kind type is unrecognized + */ + default StreamingEventKind_v0_3 fromV10(StreamingEventKind v10) { + if (v10 == null) { + return null; + } + + if (v10 instanceof Task v10Task) { + return TaskMapper_v0_3.INSTANCE.fromV10(v10Task); + } else if (v10 instanceof Message v10Message) { + return MessageMapper_v0_3.INSTANCE.fromV10(v10Message); + } else if (v10 instanceof TaskStatusUpdateEvent v10StatusUpdate) { + return TaskStatusUpdateEventMapper_v0_3.INSTANCE.fromV10(v10StatusUpdate); + } else if (v10 instanceof TaskArtifactUpdateEvent v10ArtifactUpdate) { + return TaskArtifactUpdateEventMapper_v0_3.INSTANCE.fromV10(v10ArtifactUpdate); + } + + throw new InvalidRequestError(null, "Unrecognized StreamingEventKind type: " + v10.getClass().getName(), null); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskArtifactUpdateEventMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskArtifactUpdateEventMapper_v0_3.java new file mode 100644 index 000000000..defde82ac --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskArtifactUpdateEventMapper_v0_3.java @@ -0,0 +1,74 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting TaskArtifactUpdateEvent between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: TaskArtifactUpdateEvent is a class with getter methods (e.g., {@code getTaskId()}, {@code isAppend()})
            • + *
            • v1.0: TaskArtifactUpdateEvent is a record with accessor methods (e.g., {@code taskId()}, {@code append()})
            • + *
            + *

            + * Both versions have the same structure: + * {@code TaskArtifactUpdateEvent(taskId, artifact, contextId, append, lastChunk, metadata)}. + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {ArtifactMapper_v0_3.class}) +public interface TaskArtifactUpdateEventMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + TaskArtifactUpdateEventMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(TaskArtifactUpdateEventMapper_v0_3.class); + + /** + * Converts v0.3 TaskArtifactUpdateEvent to v1.0 TaskArtifactUpdateEvent. + *

            + * Converts the nested Artifact using ArtifactMapper. + * + * @param v03 the v0.3 task artifact update event + * @return the equivalent v1.0 task artifact update event + */ + default TaskArtifactUpdateEvent toV10(TaskArtifactUpdateEvent_v0_3 v03) { + if (v03 == null) { + return null; + } + + return new TaskArtifactUpdateEvent( + v03.getTaskId(), + ArtifactMapper_v0_3.INSTANCE.toV10(v03.getArtifact()), + v03.getContextId(), + v03.isAppend(), + v03.isLastChunk(), + v03.getMetadata() + ); + } + + /** + * Converts v1.0 TaskArtifactUpdateEvent to v0.3 TaskArtifactUpdateEvent. + *

            + * Converts the nested Artifact using ArtifactMapper. + * + * @param v10 the v1.0 task artifact update event + * @return the equivalent v0.3 task artifact update event + */ + default TaskArtifactUpdateEvent_v0_3 fromV10(TaskArtifactUpdateEvent v10) { + if (v10 == null) { + return null; + } + + return new TaskArtifactUpdateEvent_v0_3( + v10.taskId(), + ArtifactMapper_v0_3.INSTANCE.fromV10(v10.artifact()), + v10.contextId(), + v10.append(), + v10.lastChunk(), + v10.metadata() + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3.java new file mode 100644 index 000000000..47d6a4e3c --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3.java @@ -0,0 +1,111 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import java.util.List; +import java.util.stream.Collectors; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.spec.Artifact; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting Task between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: Task is a class with getter methods (e.g., {@code getId()}, {@code getStatus()})
            • + *
            • v1.0: Task is a record with accessor methods (e.g., {@code id()}, {@code status()})
            • + *
            • v0.3 has a {@code kind} field with {@code getKind()} method
            • + *
            • v1.0 has a {@code kind()} method from the {@link org.a2aproject.sdk.spec.StreamingEventKind} interface
            • + *
            + *

            + * The conversion involves mapping nested types: + *

              + *
            • {@link org.a2aproject.sdk.spec.TaskStatus} via {@link TaskStatusMapper_v0_3}
            • + *
            • {@link Artifact} list via {@link ArtifactMapper_v0_3}
            • + *
            • {@link Message} history list via {@link MessageMapper_v0_3}
            • + *
            + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {TaskStatusMapper_v0_3.class, ArtifactMapper_v0_3.class, MessageMapper_v0_3.class}) +public interface TaskMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + TaskMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(TaskMapper_v0_3.class); + + /** + * Converts v0.3 Task to v1.0 Task. + *

            + * Converts all nested objects including status, artifacts, and history using their respective mappers. + * + * @param v03 the v0.3 task + * @return the equivalent v1.0 task + */ + default Task toV10(Task_v0_3 v03) { + if (v03 == null) { + return null; + } + + List artifacts = v03.getArtifacts() != null + ? v03.getArtifacts().stream() + .map(ArtifactMapper_v0_3.INSTANCE::toV10) + .collect(Collectors.toList()) + : null; + + List history = v03.getHistory() != null + ? v03.getHistory().stream() + .map(MessageMapper_v0_3.INSTANCE::toV10) + .collect(Collectors.toList()) + : null; + + return new Task( + v03.getId(), + v03.getContextId(), + TaskStatusMapper_v0_3.INSTANCE.toV10(v03.getStatus()), + artifacts, + history, + v03.getMetadata() + ); + } + + /** + * Converts v1.0 Task to v0.3 Task. + *

            + * Converts all nested objects including status, artifacts, and history using their respective mappers. + * + * @param v10 the v1.0 task + * @return the equivalent v0.3 task + */ + default Task_v0_3 fromV10(Task v10) { + if (v10 == null) { + return null; + } + + List artifacts = v10.artifacts() != null + ? v10.artifacts().stream() + .map(ArtifactMapper_v0_3.INSTANCE::fromV10) + .collect(Collectors.toList()) + : null; + + List history = v10.history() != null + ? v10.history().stream() + .map(MessageMapper_v0_3.INSTANCE::fromV10) + .collect(Collectors.toList()) + : null; + + return new Task_v0_3( + v10.id(), + v10.contextId(), + TaskStatusMapper_v0_3.INSTANCE.fromV10(v10.status()), + artifacts, + history, + v10.metadata() + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskPushNotificationConfigMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskPushNotificationConfigMapper_v0_3.java new file mode 100644 index 000000000..0b9534a30 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskPushNotificationConfigMapper_v0_3.java @@ -0,0 +1,89 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting TaskPushNotificationConfig between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: Nested structure with {@code TaskPushNotificationConfig(taskId, PushNotificationConfig)}
            • + *
            • v1.0: Flattened structure with {@code TaskPushNotificationConfig(id, taskId, url, token, authentication, tenant)}
            • + *
            + *

            + * Conversion strategy: + *

              + *
            • v0.3 → v1.0: Extract fields from nested {@code PushNotificationConfig}, add tenant field (default "")
            • + *
            • v1.0 → v0.3: Nest url/token/authentication/id into {@code PushNotificationConfig}, drop tenant field
            • + *
            + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {AuthenticationInfoMapper_v0_3.class}) +public interface TaskPushNotificationConfigMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + TaskPushNotificationConfigMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(TaskPushNotificationConfigMapper_v0_3.class); + + /** + * Converts v0.3 TaskPushNotificationConfig to v1.0 TaskPushNotificationConfig. + *

            + * Flattens the nested {@code PushNotificationConfig} structure and adds the tenant field (default ""). + * + * @param v03 the v0.3 task push notification config + * @return the equivalent v1.0 task push notification config + */ + default TaskPushNotificationConfig toV10( + TaskPushNotificationConfig_v0_3 v03) { + if (v03 == null) { + return null; + } + + PushNotificationConfig_v0_3 pushConfig = v03.pushNotificationConfig(); + + // v0.3 id can be null; v1.0 requires non-null id but stores use empty string to auto-assign + String id = pushConfig.id() != null ? pushConfig.id() : ""; + + return new TaskPushNotificationConfig( + id, + v03.taskId(), + pushConfig.url(), + pushConfig.token(), + AuthenticationInfoMapper_v0_3.INSTANCE.toV10FromPushNotification(pushConfig.authentication()), + "" // Default tenant + ); + } + + /** + * Converts v1.0 TaskPushNotificationConfig to v0.3 TaskPushNotificationConfig. + *

            + * Nests the url/token/authentication/id fields into a {@code PushNotificationConfig} and drops the tenant field. + * + * @param v10 the v1.0 task push notification config + * @return the equivalent v0.3 task push notification config + */ + default TaskPushNotificationConfig_v0_3 fromV10( + TaskPushNotificationConfig v10) { + if (v10 == null) { + return null; + } + + PushNotificationConfig_v0_3 pushConfig = + new PushNotificationConfig_v0_3( + v10.url(), + v10.token(), + AuthenticationInfoMapper_v0_3.INSTANCE.fromV10ToPushNotification(v10.authentication()), + v10.id() + ); + + return new TaskPushNotificationConfig_v0_3( + v10.taskId(), + pushConfig + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStateMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStateMapper_v0_3.java new file mode 100644 index 000000000..05f8b464d --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStateMapper_v0_3.java @@ -0,0 +1,115 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.spec.TaskState; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting {@code TaskState} enum between A2A Protocol v0.3 and v1.0. + *

            + * This is a critical mapper because v1.0 adds the {@code TASK_STATE_} prefix to all enum constants: + *

              + *
            • v0.3: {@code SUBMITTED, WORKING, ...}
            • + *
            • v1.0: {@code TASK_STATE_SUBMITTED, TASK_STATE_WORKING, ...}
            • + *
            + *

            + * Additionally, the {@code UNKNOWN} state in v0.3 maps to {@code UNRECOGNIZED} in v1.0. + *

            + * This mapper uses manual switch statements instead of {@code @ValueMapping} to: + *

              + *
            • Avoid mapstruct-spi-protobuf enum strategy initialization issues
            • + *
            • Handle explicit null mapping (null → UNRECOGNIZED/UNKNOWN)
            • + *
            • Provide clear, compile-time-safe enum conversions
            • + *
            + * + * @see TaskState_v0_3 + * @see TaskState + */ +@Mapper(config = A03ToV10MapperConfig.class) +public interface TaskStateMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + TaskStateMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(TaskStateMapper_v0_3.class); + + /** + * Converts a v0.3 {@code TaskState} to v1.0 {@code TaskState}. + *

            + * Mapping: + *

            +     * 0.3                    → 1.0
            +     * ─────────────────────────────────────────────
            +     * SUBMITTED              → TASK_STATE_SUBMITTED
            +     * WORKING                → TASK_STATE_WORKING
            +     * INPUT_REQUIRED         → TASK_STATE_INPUT_REQUIRED
            +     * AUTH_REQUIRED          → TASK_STATE_AUTH_REQUIRED
            +     * COMPLETED              → TASK_STATE_COMPLETED
            +     * CANCELED               → TASK_STATE_CANCELED
            +     * FAILED                 → TASK_STATE_FAILED
            +     * REJECTED               → TASK_STATE_REJECTED
            +     * UNKNOWN                → UNRECOGNIZED
            +     * null                   → UNRECOGNIZED
            +     * 
            + * + * @param v03 the v0.3 task state (may be null) + * @return the equivalent v1.0 task state (never null) + */ + default TaskState toV10(TaskState_v0_3 v03) { + if (v03 == null) { + return TaskState.UNRECOGNIZED; + } + return switch (v03) { + case SUBMITTED -> TaskState.TASK_STATE_SUBMITTED; + case WORKING -> TaskState.TASK_STATE_WORKING; + case INPUT_REQUIRED -> TaskState.TASK_STATE_INPUT_REQUIRED; + case AUTH_REQUIRED -> TaskState.TASK_STATE_AUTH_REQUIRED; + case COMPLETED -> TaskState.TASK_STATE_COMPLETED; + case CANCELED -> TaskState.TASK_STATE_CANCELED; + case FAILED -> TaskState.TASK_STATE_FAILED; + case REJECTED -> TaskState.TASK_STATE_REJECTED; + case UNKNOWN -> TaskState.UNRECOGNIZED; + }; + } + + /** + * Converts a v1.0 {@code TaskState} to v0.3 {@code TaskState}. + *

            + * Reverse mapping: + *

            +     * 1.0                          → 0.3
            +     * ───────────────────────────────────────────────────
            +     * TASK_STATE_SUBMITTED         → SUBMITTED
            +     * TASK_STATE_WORKING           → WORKING
            +     * TASK_STATE_INPUT_REQUIRED    → INPUT_REQUIRED
            +     * TASK_STATE_AUTH_REQUIRED     → AUTH_REQUIRED
            +     * TASK_STATE_COMPLETED         → COMPLETED
            +     * TASK_STATE_CANCELED          → CANCELED
            +     * TASK_STATE_FAILED            → FAILED
            +     * TASK_STATE_REJECTED          → REJECTED
            +     * UNRECOGNIZED                 → UNKNOWN
            +     * null                         → UNKNOWN
            +     * 
            + * + * @param v10 the v1.0 task state (may be null) + * @return the equivalent v0.3 task state (never null) + */ + default TaskState_v0_3 fromV10(TaskState v10) { + if (v10 == null) { + return TaskState_v0_3.UNKNOWN; + } + return switch (v10) { + case TASK_STATE_SUBMITTED -> TaskState_v0_3.SUBMITTED; + case TASK_STATE_WORKING -> TaskState_v0_3.WORKING; + case TASK_STATE_INPUT_REQUIRED -> TaskState_v0_3.INPUT_REQUIRED; + case TASK_STATE_AUTH_REQUIRED -> TaskState_v0_3.AUTH_REQUIRED; + case TASK_STATE_COMPLETED -> TaskState_v0_3.COMPLETED; + case TASK_STATE_CANCELED -> TaskState_v0_3.CANCELED; + case TASK_STATE_FAILED -> TaskState_v0_3.FAILED; + case TASK_STATE_REJECTED -> TaskState_v0_3.REJECTED; + case UNRECOGNIZED -> TaskState_v0_3.UNKNOWN; + }; + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusMapper_v0_3.java new file mode 100644 index 000000000..f72aafcf7 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusMapper_v0_3.java @@ -0,0 +1,71 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.spec.TaskStatus; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting TaskStatus between A2A Protocol v0.3 and v1.0. + *

            + * Both versions are records with the same structure: + * {@code TaskStatus(TaskState state, Message message, OffsetDateTime timestamp)}. + *

            + * The conversion involves: + *

              + *
            • Converting {@link TaskState_v0_3} to {@link org.a2aproject.sdk.spec.TaskState} (enum prefix mapping)
            • + *
            • Converting {@link Message_v0_3} to {@link org.a2aproject.sdk.spec.Message} (class ↔ record)
            • + *
            • Preserving the timestamp field (same type in both versions)
            • + *
            + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {TaskStateMapper_v0_3.class, MessageMapper_v0_3.class}) +public interface TaskStatusMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + TaskStatusMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(TaskStatusMapper_v0_3.class); + + /** + * Converts v0.3 TaskStatus to v1.0 TaskStatus. + *

            + * Converts the state enum and message object using their respective mappers. + * + * @param v03 the v0.3 task status + * @return the equivalent v1.0 task status + */ + default TaskStatus toV10(TaskStatus_v0_3 v03) { + if (v03 == null) { + return null; + } + + return new TaskStatus( + TaskStateMapper_v0_3.INSTANCE.toV10(v03.state()), + MessageMapper_v0_3.INSTANCE.toV10(v03.message()), + v03.timestamp() + ); + } + + /** + * Converts v1.0 TaskStatus to v0.3 TaskStatus. + *

            + * Converts the state enum and message object using their respective mappers. + * + * @param v10 the v1.0 task status + * @return the equivalent v0.3 task status + */ + default TaskStatus_v0_3 fromV10(TaskStatus v10) { + if (v10 == null) { + return null; + } + + return new TaskStatus_v0_3( + TaskStateMapper_v0_3.INSTANCE.fromV10(v10.state()), + MessageMapper_v0_3.INSTANCE.fromV10(v10.message()), + v10.timestamp() + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusUpdateEventMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusUpdateEventMapper_v0_3.java new file mode 100644 index 000000000..8b90af2c0 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusUpdateEventMapper_v0_3.java @@ -0,0 +1,71 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting TaskStatusUpdateEvent between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: TaskStatusUpdateEvent is a class with getter methods
            • + *
            • v1.0: TaskStatusUpdateEvent is a record with accessor methods
            • + *
            + *

            + * Both versions have the same structure: + * {@code TaskStatusUpdateEvent(taskId, status, contextId, isFinal, metadata)}. + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {TaskStatusMapper_v0_3.class}) +public interface TaskStatusUpdateEventMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + TaskStatusUpdateEventMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(TaskStatusUpdateEventMapper_v0_3.class); + + /** + * Converts v0.3 TaskStatusUpdateEvent to v1.0 TaskStatusUpdateEvent. + *

            + * Converts the nested TaskStatus using TaskStatusMapper. + * + * @param v03 the v0.3 task status update event + * @return the equivalent v1.0 task status update event + */ + default TaskStatusUpdateEvent toV10(TaskStatusUpdateEvent_v0_3 v03) { + if (v03 == null) { + return null; + } + + return new TaskStatusUpdateEvent( + v03.getTaskId(), + TaskStatusMapper_v0_3.INSTANCE.toV10(v03.getStatus()), + v03.getContextId(), + v03.getMetadata() + ); + } + + /** + * Converts v1.0 TaskStatusUpdateEvent to v0.3 TaskStatusUpdateEvent. + *

            + * Converts the nested TaskStatus using TaskStatusMapper. + * + * @param v10 the v1.0 task status update event + * @return the equivalent v0.3 task status update event + */ + default TaskStatusUpdateEvent_v0_3 fromV10(TaskStatusUpdateEvent v10) { + if (v10 == null) { + return null; + } + + return new TaskStatusUpdateEvent_v0_3( + v10.taskId(), + TaskStatusMapper_v0_3.INSTANCE.fromV10(v10.status()), + v10.contextId(), + v10.isFinal(), + v10.metadata() + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/CancelTaskParamsMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/CancelTaskParamsMapper_v0_3.java new file mode 100644 index 000000000..67ee7a597 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/CancelTaskParamsMapper_v0_3.java @@ -0,0 +1,72 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.params; + +import java.util.Collections; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.spec.CancelTaskParams; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting cancel task parameters between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: Uses {@code TaskIdParams(String id, Map metadata)}
            • + *
            • v1.0: Uses {@code CancelTaskParams(String id, String tenant, Map metadata)}
            • + *
            + *

            + * Conversion strategy: + *

              + *
            • 0.3 → 1.0: Convert {@code TaskIdParams} to {@code CancelTaskParams} (add {@code tenant} field = "", preserve {@code metadata})
            • + *
            • 1.0 → 0.3: Convert {@code CancelTaskParams} to {@code TaskIdParams} (drop {@code tenant} field, preserve {@code metadata})
            • + *
            + * + * @see TaskIdParams_v0_3 + * @see CancelTaskParams + */ +@Mapper(config = A03ToV10MapperConfig.class) +public interface CancelTaskParamsMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + CancelTaskParamsMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(CancelTaskParamsMapper_v0_3.class); + + /** + * Converts v0.3 {@code TaskIdParams} to v1.0 {@code CancelTaskParams}. + *

            + * The v0.3 {@code metadata} field is preserved in the v1.0 type, and the v1.0 + * {@code tenant} field is set to the empty string default. + * + * @param v03 the v0.3 task ID params used for cancel operations + * @return the equivalent v1.0 cancel task params + */ + default CancelTaskParams toV10(TaskIdParams_v0_3 v03) { + if (v03 == null) { + return null; + } + return new CancelTaskParams( + v03.id(), + "", // Default tenant + v03.metadata() != null ? v03.metadata() : Collections.emptyMap() + ); + } + + /** + * Converts v1.0 {@code CancelTaskParams} to v0.3 {@code TaskIdParams}. + *

            + * The v1.0 {@code tenant} field is dropped, and the v1.0 {@code metadata} field + * is preserved in the v0.3 type. + * + * @param v10 the v1.0 cancel task params + * @return the equivalent v0.3 task ID params + */ + default TaskIdParams_v0_3 fromV10(CancelTaskParams v10) { + if (v10 == null) { + return null; + } + return new TaskIdParams_v0_3(v10.id(), v10.metadata()); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/MessageSendConfigurationMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/MessageSendConfigurationMapper_v0_3.java new file mode 100644 index 000000000..c1228087e --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/MessageSendConfigurationMapper_v0_3.java @@ -0,0 +1,107 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.params; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskPushNotificationConfigMapper_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendConfiguration_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.spec.MessageSendConfiguration; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting MessageSendConfiguration between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: {@code PushNotificationConfig pushNotificationConfig, Boolean blocking}
            • + *
            • v1.0: {@code TaskPushNotificationConfig taskPushNotificationConfig, Boolean returnImmediately}
            • + *
            + *

            + * Conversion strategy: + *

              + *
            • {@code blocking} (v0.3) ↔ {@code returnImmediately} (v1.0): Inverse semantics - {@code returnImmediately = !blocking}
            • + *
            • {@code PushNotificationConfig} wraps to {@code TaskPushNotificationConfig} with empty taskId
            • + *
            + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {TaskPushNotificationConfigMapper_v0_3.class}) +public interface MessageSendConfigurationMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + MessageSendConfigurationMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(MessageSendConfigurationMapper_v0_3.class); + + /** + * Converts v0.3 MessageSendConfiguration to v1.0 MessageSendConfiguration. + *

            + * Converts {@code blocking} to {@code returnImmediately} with inverse semantics, + * and wraps {@code PushNotificationConfig} into {@code TaskPushNotificationConfig}. + * + * @param v03 the v0.3 message send configuration + * @return the equivalent v1.0 message send configuration + */ + default MessageSendConfiguration toV10( + MessageSendConfiguration_v0_3 v03) { + if (v03 == null) { + return null; + } + + // Convert PushNotificationConfig to TaskPushNotificationConfig if present + TaskPushNotificationConfig taskPushConfig = null; + if (v03.pushNotificationConfig() != null) { + // Wrap the push notification config with an empty taskId (will be set by the server) + TaskPushNotificationConfig_v0_3 v03TaskConfig = + new TaskPushNotificationConfig_v0_3( + "", // Empty taskId - will be populated by server + v03.pushNotificationConfig() + ); + taskPushConfig = TaskPushNotificationConfigMapper_v0_3.INSTANCE.toV10(v03TaskConfig); + } + + // Convert blocking to returnImmediately (inverse semantics) + Boolean returnImmediately = v03.blocking() != null ? !v03.blocking() : null; + + return new MessageSendConfiguration( + v03.acceptedOutputModes(), + v03.historyLength(), + taskPushConfig, + returnImmediately + ); + } + + /** + * Converts v1.0 MessageSendConfiguration to v0.3 MessageSendConfiguration. + *

            + * Converts {@code returnImmediately} to {@code blocking} with inverse semantics, + * and extracts {@code PushNotificationConfig} from {@code TaskPushNotificationConfig}. + * + * @param v10 the v1.0 message send configuration + * @return the equivalent v0.3 message send configuration + */ + default MessageSendConfiguration_v0_3 fromV10( + MessageSendConfiguration v10) { + if (v10 == null) { + return null; + } + + // Extract PushNotificationConfig from TaskPushNotificationConfig if present + PushNotificationConfig_v0_3 pushConfig = null; + if (v10.taskPushNotificationConfig() != null) { + TaskPushNotificationConfig_v0_3 v03TaskConfig = + TaskPushNotificationConfigMapper_v0_3.INSTANCE.fromV10(v10.taskPushNotificationConfig()); + pushConfig = v03TaskConfig.pushNotificationConfig(); + } + + // Convert returnImmediately to blocking (inverse semantics) + Boolean blocking = v10.returnImmediately() != null ? !v10.returnImmediately() : null; + + return new MessageSendConfiguration_v0_3( + v10.acceptedOutputModes(), + v10.historyLength(), + pushConfig, + blocking + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/MessageSendParamsMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/MessageSendParamsMapper_v0_3.java new file mode 100644 index 000000000..862b4e0c8 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/MessageSendParamsMapper_v0_3.java @@ -0,0 +1,75 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.params; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.MessageMapper_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.spec.MessageSendParams; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting MessageSendParams between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: {@code MessageSendParams(message, configuration, metadata)} - no tenant field
            • + *
            • v1.0: {@code MessageSendParams(message, configuration, metadata, tenant)} - adds tenant field
            • + *
            + *

            + * Conversion strategy: + *

              + *
            • v0.3 → v1.0: Add tenant field with default value ""
            • + *
            • v1.0 → v0.3: Drop tenant field
            • + *
            + *

            + * Uses {@link MessageMapper_v0_3} and {@link MessageSendConfigurationMapper_v0_3} for nested conversions. + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {MessageMapper_v0_3.class, MessageSendConfigurationMapper_v0_3.class}) +public interface MessageSendParamsMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + MessageSendParamsMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(MessageSendParamsMapper_v0_3.class); + + /** + * Converts v0.3 MessageSendParams to v1.0 MessageSendParams. + *

            + * Adds the tenant field with default value "". + * + * @param v03 the v0.3 message send params + * @return the equivalent v1.0 message send params + */ + default MessageSendParams toV10(MessageSendParams_v0_3 v03) { + if (v03 == null) { + return null; + } + + return new MessageSendParams( + MessageMapper_v0_3.INSTANCE.toV10(v03.message()), + MessageSendConfigurationMapper_v0_3.INSTANCE.toV10(v03.configuration()), + v03.metadata(), + "" // Default tenant + ); + } + + /** + * Converts v1.0 MessageSendParams to v0.3 MessageSendParams. + *

            + * Drops the tenant field. + * + * @param v10 the v1.0 message send params + * @return the equivalent v0.3 message send params + */ + default MessageSendParams_v0_3 fromV10(MessageSendParams v10) { + if (v10 == null) { + return null; + } + + return new MessageSendParams_v0_3( + MessageMapper_v0_3.INSTANCE.fromV10(v10.message()), + MessageSendConfigurationMapper_v0_3.INSTANCE.fromV10(v10.configuration()), + v10.metadata() + ); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/TaskIdParamsMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/TaskIdParamsMapper_v0_3.java new file mode 100644 index 000000000..b8ae86dec --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/TaskIdParamsMapper_v0_3.java @@ -0,0 +1,66 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.params; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.spec.TaskIdParams; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting {@code TaskIdParams} between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: {@code TaskIdParams(String id, Map metadata)}
            • + *
            • v1.0: {@code TaskIdParams(String id, String tenant)}
            • + *
            + *

            + * Conversion strategy: + *

              + *
            • 0.3 → 1.0: Drop {@code metadata} field, add {@code tenant} field (default to "")
            • + *
            • 1.0 → 0.3: Drop {@code tenant} field, add {@code metadata} field (set to null)
            • + *
            + * + * @see TaskIdParams_v0_3 + * @see TaskIdParams + */ +@Mapper(config = A03ToV10MapperConfig.class) +public interface TaskIdParamsMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + TaskIdParamsMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(TaskIdParamsMapper_v0_3.class); + + /** + * Converts v0.3 {@code TaskIdParams} to v1.0 {@code TaskIdParams}. + *

            + * The {@code metadata} field from v0.3 is dropped, and the v1.0 {@code tenant} field + * is set to the empty string default. + * + * @param v03 the v0.3 task ID params + * @return the equivalent v1.0 task ID params + */ + default TaskIdParams toV10(TaskIdParams_v0_3 v03) { + if (v03 == null) { + return null; + } + return new TaskIdParams(v03.id(), ""); + } + + /** + * Converts v1.0 {@code TaskIdParams} to v0.3 {@code TaskIdParams}. + *

            + * The {@code tenant} field from v1.0 is dropped, and the v0.3 {@code metadata} field + * is set to null. + * + * @param v10 the v1.0 task ID params + * @return the equivalent v0.3 task ID params + */ + default TaskIdParams_v0_3 fromV10(TaskIdParams v10) { + if (v10 == null) { + return null; + } + return new TaskIdParams_v0_3(v10.id(), null); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/TaskQueryParamsMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/TaskQueryParamsMapper_v0_3.java new file mode 100644 index 000000000..31357b42e --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/params/TaskQueryParamsMapper_v0_3.java @@ -0,0 +1,84 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.params; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.spec.TaskQueryParams; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting {@code TaskQueryParams} between A2A Protocol v0.3 and v1.0. + *

            + * Key differences: + *

              + *
            • v0.3: {@code TaskQueryParams(String id, int historyLength, Map metadata)}
            • + *
            • v1.0: {@code TaskQueryParams(String id, Integer historyLength, String tenant)}
            • + *
            + *

            + * Conversion strategy: + *

              + *
            • 0.3 → 1.0: + *
                + *
              • {@code historyLength}: primitive int → nullable Integer (0 → null)
              • + *
              • {@code metadata}: dropped
              • + *
              • {@code tenant}: added as ""
              • + *
              + *
            • + *
            • 1.0 → 0.3: + *
                + *
              • {@code historyLength}: nullable Integer → primitive int (null → 0)
              • + *
              • {@code metadata}: added as null
              • + *
              • {@code tenant}: dropped
              • + *
              + *
            • + *
            + * + * @see TaskQueryParams_v0_3 + * @see TaskQueryParams + */ +@Mapper(config = A03ToV10MapperConfig.class) +public interface TaskQueryParamsMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + TaskQueryParamsMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(TaskQueryParamsMapper_v0_3.class); + + /** + * Converts v0.3 {@code TaskQueryParams} to v1.0 {@code TaskQueryParams}. + *

            + * The {@code metadata} field from v0.3 is dropped, the {@code historyLength} is converted + * from primitive int to nullable Integer (0 becomes null), and the v1.0 {@code tenant} + * field is set to the empty string default. + * + * @param v03 the v0.3 task query params + * @return the equivalent v1.0 task query params + */ + default TaskQueryParams toV10(TaskQueryParams_v0_3 v03) { + if (v03 == null) { + return null; + } + // Convert historyLength: 0 (default) → null, non-zero → Integer + Integer historyLength = v03.historyLength() == 0 ? null : v03.historyLength(); + return new TaskQueryParams(v03.id(), historyLength, ""); + } + + /** + * Converts v1.0 {@code TaskQueryParams} to v0.3 {@code TaskQueryParams}. + *

            + * The {@code tenant} field from v1.0 is dropped, the {@code historyLength} is converted + * from nullable Integer to primitive int (null becomes 0), and the v0.3 {@code metadata} + * field is set to null. + * + * @param v10 the v1.0 task query params + * @return the equivalent v0.3 task query params + */ + default TaskQueryParams_v0_3 fromV10(TaskQueryParams v10) { + if (v10 == null) { + return null; + } + // Convert historyLength: null → 0 (default), Integer → int + int historyLength = v10.historyLength() == null ? 0 : v10.historyLength(); + return new TaskQueryParams_v0_3(v10.id(), historyLength, null); + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/result/ListTaskPushNotificationConfigsResultMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/result/ListTaskPushNotificationConfigsResultMapper_v0_3.java new file mode 100644 index 000000000..95320f8c8 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/result/ListTaskPushNotificationConfigsResultMapper_v0_3.java @@ -0,0 +1,79 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.result; + +import java.util.List; +import java.util.stream.Collectors; + +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A03ToV10MapperConfig; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskPushNotificationConfigMapper_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.mapstruct.Mapper; + +/** + * Bidirectional mapper for converting between v0.3 {@code List} + * and v1.0 {@link ListTaskPushNotificationConfigsResult}. + *

            + * Key differences: + *

              + *
            • v0.3: Returns a plain {@code List} (no pagination support)
            • + *
            • v1.0: Returns {@link ListTaskPushNotificationConfigsResult} with pagination support (nextPageToken)
            • + *
            + *

            + * Conversion strategy: + *

              + *
            • v0.3 → v1.0: Wrap the list in {@code ListTaskPushNotificationConfigsResult} with no nextPageToken
            • + *
            • v1.0 → v0.3: Extract the configs list (discard nextPageToken as 0.3 doesn't support pagination)
            • + *
            + */ +@Mapper(config = A03ToV10MapperConfig.class, uses = {TaskPushNotificationConfigMapper_v0_3.class}) +public interface ListTaskPushNotificationConfigsResultMapper_v0_3 { + + /** + * Singleton instance accessed via {@link A2AMappers_v0_3} factory. + */ + ListTaskPushNotificationConfigsResultMapper_v0_3 INSTANCE = A2AMappers_v0_3.getMapper(ListTaskPushNotificationConfigsResultMapper_v0_3.class); + + /** + * Converts v0.3 {@code List} to v1.0 {@link ListTaskPushNotificationConfigsResult}. + *

            + * Wraps the list in a result object with no nextPageToken (pagination not supported in 0.3). + * Converts each TaskPushNotificationConfig using TaskPushNotificationConfigMapper. + * + * @param v03List the v0.3 list of task push notification configs + * @return the equivalent v1.0 result object + */ + default ListTaskPushNotificationConfigsResult toV10( + List v03List) { + if (v03List == null) { + return null; + } + + List v10Configs = v03List.stream() + .map(TaskPushNotificationConfigMapper_v0_3.INSTANCE::toV10) + .collect(Collectors.toList()); + + return new ListTaskPushNotificationConfigsResult(v10Configs, null); + } + + /** + * Converts v1.0 {@link ListTaskPushNotificationConfigsResult} to v0.3 {@code List}. + *

            + * Extracts the configs list and discards the nextPageToken (pagination not supported in 0.3). + * Converts each TaskPushNotificationConfig using TaskPushNotificationConfigMapper. + * + * @param v10Result the v1.0 result object + * @return the equivalent v0.3 list + */ + default List fromV10( + ListTaskPushNotificationConfigsResult v10Result) { + if (v10Result == null) { + return null; + } + + return v10Result.configs().stream() + .map(TaskPushNotificationConfigMapper_v0_3.INSTANCE::fromV10) + .collect(Collectors.toList()); + } +} diff --git a/compat-0.3/server-conversion/src/main/resources/META-INF/beans.xml b/compat-0.3/server-conversion/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..548d44b72 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/resources/META-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java new file mode 100644 index 000000000..701e2ea63 --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java @@ -0,0 +1,287 @@ +package org.a2aproject.sdk.compat03.conversion; + +import java.io.IOException; +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.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.function.Consumer; + +import jakarta.enterprise.context.Dependent; + +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.events.EventQueueUtil; +import org.a2aproject.sdk.server.events.InMemoryQueueManager; +import org.a2aproject.sdk.server.events.MainEventBus; +import org.a2aproject.sdk.server.events.MainEventBusProcessor; +import org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.server.tasks.BasePushNotificationSender; +import org.a2aproject.sdk.server.tasks.InMemoryPushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.InMemoryTaskStore; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.PushNotificationSender; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import io.quarkus.arc.profile.IfBuildProfile; + +// V0.3 imports for test fixtures +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; + +/** + * Base test class for v0.3 transport handler tests. + *

            + * This class sets up the test infrastructure that bridges v0.3 transport handlers + * to the v1.0 backend via the {@link Convert_v0_3_To10RequestHandler} conversion layer. + *

            + * + *

            Architecture:

            + *
            + * Test (v0.3 types) → Handler (v0.3) → Convert03To10RequestHandler → v1.0 Backend
            + * 
            + * + *

            Test fixtures:

            + * All test fixtures use v0.3 types ({@code org.a2aproject.sdk.compat03.spec.*}) + * to match the client perspective. + * + *

            Backend:

            + * The backend uses v1.0 components ({@code org.a2aproject.sdk.server.*}) with + * the conversion happening transparently in {@link Convert_v0_3_To10RequestHandler}. + */ +public abstract class AbstractA2ARequestHandlerTest_v0_3 { + + // V0.3 test fixtures (client perspective) + protected static final AgentCard_v0_3 CARD = createAgentCard(true, true, true); + + protected static final Task_v0_3 MINIMAL_TASK = new Task_v0_3.Builder() + .id("task-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + + protected static final Message_v0_3 MESSAGE = new Message_v0_3.Builder() + .messageId("111") + .role(Message_v0_3.Role.AGENT) + .parts(new TextPart_v0_3("test message")) + .build(); + + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + + // V1.0 backend infrastructure + protected AgentExecutor agentExecutor; + protected TaskStore taskStore; + protected InMemoryQueueManager queueManager; + protected TestHttpClient httpClient; + protected MainEventBus mainEventBus; + protected MainEventBusProcessor mainEventBusProcessor; + + // V0.3 conversion layer (what transport handlers use) + protected Convert_v0_3_To10RequestHandler convert03To10Handler; + + // Lambda injection for AgentExecutor behavior (v0.3.x pattern) + protected AgentExecutorMethod agentExecutorExecute; + protected AgentExecutorMethod agentExecutorCancel; + + protected final Executor internalExecutor = Executors.newCachedThreadPool(); + + @BeforeEach + public void init() { + // Create AgentExecutor with lambda injection (v1.0 interface) + agentExecutor = new AgentExecutor() { + @Override + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + if (agentExecutorExecute != null) { + agentExecutorExecute.invoke(context, agentEmitter); + } + } + + @Override + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + if (agentExecutorCancel != null) { + agentExecutorCancel.invoke(context, agentEmitter); + } + } + }; + + // Set up v1.0 backend components + InMemoryTaskStore inMemoryTaskStore = new InMemoryTaskStore(); + taskStore = inMemoryTaskStore; + + // Create push notification components BEFORE MainEventBusProcessor + httpClient = new TestHttpClient(); + PushNotificationConfigStore pushConfigStore = new InMemoryPushNotificationConfigStore(); + PushNotificationSender pushSender = new BasePushNotificationSender(pushConfigStore, httpClient); + + // Create MainEventBus and MainEventBusProcessor (production code path) + mainEventBus = new MainEventBus(); + queueManager = new InMemoryQueueManager(inMemoryTaskStore, mainEventBus); + mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, pushSender, queueManager); + EventQueueUtil.start(mainEventBusProcessor); + + // Create v1.0 DefaultRequestHandler + org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler v10Handler = + DefaultRequestHandler.create( + agentExecutor, taskStore, queueManager, pushConfigStore, + mainEventBusProcessor, internalExecutor, internalExecutor); + + // Wrap in v0.3 conversion handler + convert03To10Handler = new Convert_v0_3_To10RequestHandler(); + convert03To10Handler.v10Handler = v10Handler; + } + + @AfterEach + public void cleanup() { + agentExecutorExecute = null; + agentExecutorCancel = null; + + // Stop MainEventBusProcessor background thread + if (mainEventBusProcessor != null) { + EventQueueUtil.stop(mainEventBusProcessor); + } + } + + /** + * Creates a v0.3 AgentCard with specified capabilities. + * + * @param streaming whether streaming is supported + * @param pushNotifications whether push notifications are supported + * @param stateTransitionHistory whether state transition history is supported + * @return configured AgentCard + */ + protected static AgentCard_v0_3 createAgentCard(boolean streaming, boolean pushNotifications, + boolean stateTransitionHistory) { + return new AgentCard_v0_3.Builder() + .name("test-card") + .description("A test agent card") + .url("http://example.com") + .version("1.0") + .documentationUrl("http://example.com/docs") + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(streaming) + .pushNotifications(pushNotifications) + .stateTransitionHistory(stateTransitionHistory) + .build()) + .defaultInputModes(new ArrayList<>()) + .defaultOutputModes(new ArrayList<>()) + .preferredTransport("jsonrpc") + .skills(new ArrayList<>()) + .protocolVersion("0.3") + .build(); + } + + /** + * Lambda interface for AgentExecutor method injection in tests. + */ + protected interface AgentExecutorMethod { + void invoke(RequestContext context, AgentEmitter agentEmitter) throws A2AError; + } + + /** + * Test HTTP client for push notification testing. + * Captures posted events for verification. + */ + @Dependent + @IfBuildProfile("test") + protected static class TestHttpClient implements A2AHttpClient { + public final List events = Collections.synchronizedList(new ArrayList<>()); + public volatile CountDownLatch latch; + + @Override + public GetBuilder createGet() { + return null; + } + + @Override + public PostBuilder createPost() { + return new TestHttpClient.TestPostBuilder(); + } + + @Override + public DeleteBuilder createDelete() { + return null; + } + + class TestPostBuilder implements A2AHttpClient.PostBuilder { + private volatile String body; + + @Override + public PostBuilder body(String body) { + this.body = body; + return this; + } + + @Override + public A2AHttpResponse post() throws IOException, InterruptedException { + try { + // Parse StreamResponse format to extract the streaming event + // The body contains a wrapper with one of: task, message, statusUpdate, artifactUpdate + StreamingEventKind event = JsonUtil.fromJson(body, StreamingEventKind.class); + events.add(event); + return new A2AHttpResponse() { + @Override + public int status() { + return 200; + } + + @Override + public boolean success() { + return true; + } + + @Override + public String body() { + return ""; + } + }; + } catch (JsonProcessingException e) { + throw new IOException("Failed to parse StreamingEventKind JSON", e); + } finally { + if (latch != null) { + latch.countDown(); + } + } + } + + @Override + public CompletableFuture postAsyncSSE(Consumer messageConsumer, + Consumer errorConsumer, + Runnable completeRunnable) + throws IOException, InterruptedException { + return null; + } + + @Override + public PostBuilder url(String s) { + return this; + } + + @Override + public PostBuilder addHeader(String name, String value) { + return this; + } + + @Override + public PostBuilder addHeaders(Map headers) { + return this; + } + } + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java new file mode 100644 index 000000000..b881c0cc0 --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java @@ -0,0 +1,2038 @@ +package org.a2aproject.sdk.compat03.conversion; + +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.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import java.io.EOFException; +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import jakarta.ws.rs.core.MediaType; + +import io.restassured.RestAssured; +import io.restassured.config.ObjectMapperConfig; +import io.restassured.specification.RequestSpecification; +import org.a2aproject.sdk.compat03.client.Client_v0_3; +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.ClientEvent_v0_3; +import org.a2aproject.sdk.compat03.client.MessageEvent_v0_3; +import org.a2aproject.sdk.compat03.client.TaskEvent_v0_3; +import org.a2aproject.sdk.compat03.client.TaskUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.client.config.ClientConfig_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.config.A2AMappers_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskArtifactUpdateEventMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskPushNotificationConfigMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskStatusUpdateEventMapper_v0_3; +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentInterface_v0_3; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Event_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCErrorResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingJSONRPCRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +import org.a2aproject.sdk.compat03.spec.UpdateEvent_v0_3; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +/** + * Abstract test class for v0.3 to v1.0 compatibility layer integration tests. + *

            + * This test requires server-side test utilities (TestUtilsBean) exposed via REST endpoints + * to add/get/delete tasks and enqueue events. + *

            + * Type conversion strategy: + *

              + *
            • Test code uses v0.3 client types ({@link org.a2aproject.sdk.compat03.spec.*})
            • + *
            • Server test utilities expect v1.0 types ({@link org.a2aproject.sdk.spec.*})
            • + *
            • Conversion at boundaries using mappers from {@link A2AMappers_v0_3}
            • + *
            • REST-Assured configured with {@link V10GsonObjectMapper_v0_3} for server communication
            • + *
            + */ +public abstract class AbstractA2AServerServerTest_v0_3 { + + protected static final Task_v0_3 MINIMAL_TASK = new Task_v0_3.Builder() + .id("task-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + + private static final Task_v0_3 CANCEL_TASK = new Task_v0_3.Builder() + .id("cancel-task-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + + private static final Task_v0_3 CANCEL_TASK_NOT_SUPPORTED = new Task_v0_3.Builder() + .id("cancel-task-not-supported-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + + private static final Task_v0_3 SEND_MESSAGE_NOT_SUPPORTED = new Task_v0_3.Builder() + .id("task-not-supported-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + + protected static final Message_v0_3 MESSAGE = new Message_v0_3.Builder() + .messageId("111") + .role(Message_v0_3.Role.AGENT) + .parts(new TextPart_v0_3("test message")) + .build(); + + public static final String APPLICATION_JSON = "application/json"; + + /** + * REST-Assured configuration using v1.0 JSON mapper. + * Server test endpoints expect v1.0 JSON format. + */ + public static RequestSpecification given() { + return RestAssured.given() + .config(RestAssured.config() + .objectMapperConfig(new ObjectMapperConfig(V10GsonObjectMapper_v0_3.INSTANCE))); + } + + /** + * REST-Assured configuration using v0.3 JSON mapper. + * Use for deserializing v0.3 JSONRPC server responses (errors, etc.). + */ + public static RequestSpecification givenV03() { + return RestAssured.given() + .config(RestAssured.config() + .objectMapperConfig(new ObjectMapperConfig(GsonObjectMapper_v0_3.INSTANCE))); + } + + protected final int serverPort; + private Client_v0_3 client; + private Client_v0_3 nonStreamingClient; + private Client_v0_3 pollingClient; + + protected AbstractA2AServerServerTest_v0_3(int serverPort) { + this.serverPort = serverPort; + } + + /** + * Get the transport protocol to use for this test (e.g., "JSONRPC", "GRPC"). + */ + protected abstract String getTransportProtocol(); + + /** + * Get the transport URL for this test. + */ + protected abstract String getTransportUrl(); + + /** + * Configure transport-specific settings for the client builder. + */ + protected abstract void configureTransport(ClientBuilder_v0_3 builder); + + @Test + public void testTaskStoreMethodsSanityTest() throws Exception { + Task_v0_3 task = new Task_v0_3.Builder(MINIMAL_TASK).id("abcde").build(); + saveTaskInTaskStore(task); + Task_v0_3 saved = getTaskFromTaskStore(task.getId()); + assertEquals(task.getId(), saved.getId()); + assertEquals(task.getContextId(), saved.getContextId()); + assertEquals(task.getStatus().state(), saved.getStatus().state()); + + deleteTaskInTaskStore(task.getId()); + Task_v0_3 saved2 = getTaskFromTaskStore(task.getId()); + assertNull(saved2); + } + + @Test + public void testGetTaskSuccess() throws Exception { + testGetTask(); + } + + private void testGetTask() throws Exception { + testGetTask(null); + } + + private void testGetTask(String mediaType) throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { + Task_v0_3 response = getClient().getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + assertEquals("task-123", response.getId()); + assertEquals("session-xyz", response.getContextId()); + assertEquals(TaskState_v0_3.SUBMITTED, response.getStatus().state()); + } catch (A2AClientException_v0_3 e) { + fail("Unexpected exception during getTask: " + e.getMessage(), e); + } finally { + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testGetTaskNotFound() throws Exception { + assertTrue(getTaskFromTaskStore("non-existent-task") == null); + try { + getClient().getTask(new TaskQueryParams_v0_3("non-existent-task")); + fail("Expected A2AClientException for non-existent task"); + } catch (A2AClientException_v0_3 e) { + // Expected - the client should throw an exception for non-existent tasks + assertInstanceOf(TaskNotFoundError_v0_3.class, e.getCause()); + } + } + + @Test + public void testCancelTaskSuccess() throws Exception { + saveTaskInTaskStore(CANCEL_TASK); + try { + Task_v0_3 task = getClient().cancelTask(new TaskIdParams_v0_3(CANCEL_TASK.getId())); + assertEquals(CANCEL_TASK.getId(), task.getId()); + assertEquals(CANCEL_TASK.getContextId(), task.getContextId()); + assertEquals(TaskState_v0_3.CANCELED, task.getStatus().state()); + } catch (A2AClientException_v0_3 e) { + fail("Unexpected exception during cancel task: " + e.getMessage(), e); + } finally { + deleteTaskInTaskStore(CANCEL_TASK.getId()); + } + } + + @Test + public void testCancelTaskNotSupported() throws Exception { + saveTaskInTaskStore(CANCEL_TASK_NOT_SUPPORTED); + try { + getClient().cancelTask(new TaskIdParams_v0_3(CANCEL_TASK_NOT_SUPPORTED.getId())); + fail("Expected A2AClientException for unsupported cancel operation"); + } catch (A2AClientException_v0_3 e) { + // Expected - the client should throw an exception for unsupported operations + assertInstanceOf(UnsupportedOperationError_v0_3.class, e.getCause()); + } finally { + deleteTaskInTaskStore(CANCEL_TASK_NOT_SUPPORTED.getId()); + } + } + + @Test + public void testCancelTaskNotFound() { + try { + getClient().cancelTask(new TaskIdParams_v0_3("non-existent-task")); + fail("Expected A2AClientException for non-existent task"); + } catch (A2AClientException_v0_3 e) { + // Expected - the client should throw an exception for non-existent tasks + assertInstanceOf(TaskNotFoundError_v0_3.class, e.getCause()); + } + } + + @Test + public void testSendMessageNewMessageSuccess() throws Exception { + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .build(); + + CountDownLatch latch = new CountDownLatch(1); + AtomicReference receivedMessage = new AtomicReference<>(); + AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); + BiConsumer consumer = (event, agentCard) -> { + if (event instanceof MessageEvent_v0_3 messageEvent) { + if (latch.getCount() > 0) { + receivedMessage.set(messageEvent.getMessage()); + latch.countDown(); + } else { + wasUnexpectedEvent.set(true); + } + } else { + wasUnexpectedEvent.set(true); + } + }; + + // testing the non-streaming send message + getNonStreamingClient().sendMessage(message, List.of(consumer), null); + + assertTrue(latch.await(10, TimeUnit.SECONDS)); + assertFalse(wasUnexpectedEvent.get()); + Message_v0_3 messageResponse = receivedMessage.get(); + assertNotNull(messageResponse); + assertEquals(MESSAGE.getMessageId(), messageResponse.getMessageId()); + assertEquals(MESSAGE.getRole(), messageResponse.getRole()); + Part_v0_3 part = messageResponse.getParts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("test message", ((TextPart_v0_3) part).getText()); + } + + @Test + public void testSendMessageExistingTaskSuccess() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .build(); + + CountDownLatch latch = new CountDownLatch(1); + AtomicReference receivedMessage = new AtomicReference<>(); + AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); + BiConsumer consumer = (event, agentCard) -> { + if (event instanceof MessageEvent_v0_3 messageEvent) { + if (latch.getCount() > 0) { + receivedMessage.set(messageEvent.getMessage()); + latch.countDown(); + } else { + wasUnexpectedEvent.set(true); + } + } else { + wasUnexpectedEvent.set(true); + } + }; + + // testing the non-streaming send message + getNonStreamingClient().sendMessage(message, List.of(consumer), null); + assertFalse(wasUnexpectedEvent.get()); + assertTrue(latch.await(10, TimeUnit.SECONDS)); + Message_v0_3 messageResponse = receivedMessage.get(); + assertNotNull(messageResponse); + assertEquals(MESSAGE.getMessageId(), messageResponse.getMessageId()); + assertEquals(MESSAGE.getRole(), messageResponse.getRole()); + Part_v0_3 part = messageResponse.getParts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("test message", ((TextPart_v0_3) part).getText()); + } catch (A2AClientException_v0_3 e) { + fail("Unexpected exception during sendMessage: " + e.getMessage(), e); + } finally { + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testSetPushNotificationSuccess() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { + TaskPushNotificationConfig_v0_3 taskPushConfig = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), new PushNotificationConfig_v0_3.Builder().url("http://example.com").build()); + TaskPushNotificationConfig_v0_3 config = getClient().setTaskPushNotificationConfiguration(taskPushConfig); + assertEquals(MINIMAL_TASK.getId(), config.taskId()); + assertEquals("http://example.com", config.pushNotificationConfig().url()); + } catch (A2AClientException_v0_3 e) { + fail("Unexpected exception during set push notification test: " + e.getMessage(), e); + } finally { + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testGetPushNotificationSuccess() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { + TaskPushNotificationConfig_v0_3 taskPushConfig = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), new PushNotificationConfig_v0_3.Builder().url("http://example.com").build()); + + TaskPushNotificationConfig_v0_3 setResult = getClient().setTaskPushNotificationConfiguration(taskPushConfig); + assertNotNull(setResult); + + TaskPushNotificationConfig_v0_3 config = getClient().getTaskPushNotificationConfiguration( + new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + assertEquals(MINIMAL_TASK.getId(), config.taskId()); + assertEquals("http://example.com", config.pushNotificationConfig().url()); + } catch (A2AClientException_v0_3 e) { + fail("Unexpected exception during get push notification test: " + e.getMessage(), e); + } finally { + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testError() throws Exception { + saveTaskInTaskStore(SEND_MESSAGE_NOT_SUPPORTED); + try { + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(SEND_MESSAGE_NOT_SUPPORTED.getId()) + .contextId(SEND_MESSAGE_NOT_SUPPORTED.getContextId()) + .build(); + + try { + getNonStreamingClient().sendMessage(message); + + // For non-streaming clients, the error should still be thrown as an exception + fail("Expected A2AClientException for unsupported send message operation"); + } catch (A2AClientException_v0_3 e) { + // Expected - the client should throw an exception for unsupported operations + assertInstanceOf(UnsupportedOperationError_v0_3.class, e.getCause()); + } + } finally { + deleteTaskInTaskStore(SEND_MESSAGE_NOT_SUPPORTED.getId()); + } + } + + @Test + public void testGetAgentCard() throws A2AClientException_v0_3 { + AgentCard_v0_3 agentCard = getClient().getAgentCard(); + assertNotNull(agentCard); + assertEquals("test-card", agentCard.name()); + assertEquals("A test agent card", agentCard.description()); + assertEquals(getTransportUrl(), agentCard.url()); + assertEquals("1.0", agentCard.version()); + assertEquals("http://example.com/docs", agentCard.documentationUrl()); + assertTrue(agentCard.capabilities().pushNotifications()); + assertTrue(agentCard.capabilities().streaming()); + assertTrue(agentCard.capabilities().stateTransitionHistory()); + assertTrue(agentCard.skills().isEmpty()); + assertFalse(agentCard.supportsAuthenticatedExtendedCard()); + } + + @Test + public void testSendMessageStreamNewMessageSuccess() throws Exception { + testSendStreamingMessage(false); + } + + @Test + public void testSendMessageStreamExistingTaskSuccess() throws Exception { + testSendStreamingMessage(true); + } + + @Test + @Timeout(value = 3, unit = TimeUnit.MINUTES) + public void testResubscribeExistingTaskSuccess() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { + // attempting to send a streaming message instead of explicitly calling queueManager#createOrTap + // does not work because after the message is sent, the queue becomes null but task resubscription + // requires the queue to still be active + ensureQueueForTask(MINIMAL_TASK.getId()); + + CountDownLatch eventLatch = new CountDownLatch(2); + AtomicReference artifactUpdateEvent = new AtomicReference<>(); + AtomicReference statusUpdateEvent = new AtomicReference<>(); + AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); + AtomicReference errorRef = new AtomicReference<>(); + AtomicBoolean receivedInitialSnapshot = new AtomicBoolean(false); + + // Create consumer to handle resubscribed events + BiConsumer consumer = (event, agentCard) -> { + if (event instanceof TaskUpdateEvent_v0_3 taskUpdateEvent) { + if (taskUpdateEvent.getUpdateEvent() instanceof TaskArtifactUpdateEvent_v0_3 artifactEvent) { + artifactUpdateEvent.set(artifactEvent); + eventLatch.countDown(); + } else if (taskUpdateEvent.getUpdateEvent() instanceof TaskStatusUpdateEvent_v0_3 statusEvent) { + statusUpdateEvent.set(statusEvent); + eventLatch.countDown(); + } else { + wasUnexpectedEvent.set(true); + } + } else if (event instanceof TaskEvent_v0_3) { + // v0.3 spec confirms task snapshot as first event on resubscribe is valid behavior + // See: https://a2a-protocol.org/v0.3.0/specification/#721-sendstreamingmessageresponse-object + if (!receivedInitialSnapshot.compareAndSet(false, true)) { + wasUnexpectedEvent.set(true); // TaskEvent received after first event + } + } else { + wasUnexpectedEvent.set(true); + } + }; + + // Create error handler + Consumer errorHandler = error -> { + if (!isStreamClosedError(error)) { + errorRef.set(error); + } + eventLatch.countDown(); + }; + + // Count down when the streaming subscription is established + CountDownLatch subscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); + + // Resubscribe to the task with specific consumer and error handler + getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.getId()), List.of(consumer), errorHandler); + + // Wait for subscription to be established + assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); + + // Enqueue events on the server + List events = List.of( + new TaskArtifactUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .artifact(new Artifact_v0_3.Builder() + .artifactId("11") + .parts(new TextPart_v0_3("text")) + .build()) + .build(), + new TaskStatusUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .isFinal(true) + .build()); + + for (Event_v0_3 event : events) { + enqueueEventOnServer(event); + } + + // Wait for events to be received + assertTrue(eventLatch.await(30, TimeUnit.SECONDS)); + assertFalse(wasUnexpectedEvent.get()); + assertNull(errorRef.get()); + + // Verify artifact update event + TaskArtifactUpdateEvent_v0_3 receivedArtifactEvent = artifactUpdateEvent.get(); + assertNotNull(receivedArtifactEvent); + assertEquals(MINIMAL_TASK.getId(), receivedArtifactEvent.getTaskId()); + assertEquals(MINIMAL_TASK.getContextId(), receivedArtifactEvent.getContextId()); + Part_v0_3 part = receivedArtifactEvent.getArtifact().parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("text", ((TextPart_v0_3) part).getText()); + + // Verify status update event + TaskStatusUpdateEvent_v0_3 receivedStatusEvent = statusUpdateEvent.get(); + assertNotNull(receivedStatusEvent); + assertEquals(MINIMAL_TASK.getId(), receivedStatusEvent.getTaskId()); + assertEquals(MINIMAL_TASK.getContextId(), receivedStatusEvent.getContextId()); + assertEquals(TaskState_v0_3.COMPLETED, receivedStatusEvent.getStatus().state()); + assertNotNull(receivedStatusEvent.getStatus().timestamp()); + } finally { + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testResubscribeNoExistingTaskError() throws Exception { + CountDownLatch errorLatch = new CountDownLatch(1); + AtomicReference errorRef = new AtomicReference<>(); + + // Create error handler to capture the TaskNotFoundError + Consumer errorHandler = error -> { + if (error == null) { + // Stream completed successfully - ignore, we're waiting for an error + return; + } + if (!isStreamClosedError(error)) { + errorRef.set(error); + } + errorLatch.countDown(); + }; + + try { + getClient().resubscribe(new TaskIdParams_v0_3("non-existent-task"), List.of(), errorHandler); + + // Wait for error to be captured (may come via error handler for streaming) + boolean errorReceived = errorLatch.await(10, TimeUnit.SECONDS); + + if (errorReceived) { + // Error came via error handler + Throwable error = errorRef.get(); + assertNotNull(error); + if (error instanceof A2AClientException_v0_3) { + assertInstanceOf(TaskNotFoundError_v0_3.class, ((A2AClientException_v0_3) error).getCause()); + } else { + // Check if it's directly a TaskNotFoundError or walk the cause chain + Throwable cause = error; + boolean foundTaskNotFound = false; + while (cause != null && !foundTaskNotFound) { + if (cause instanceof TaskNotFoundError_v0_3) { + foundTaskNotFound = true; + } + cause = cause.getCause(); + } + if (!foundTaskNotFound) { + fail("Expected TaskNotFoundError in error chain"); + } + } + } else { + fail("Expected error for non-existent task resubscription"); + } + } catch (A2AClientException_v0_3 e) { + fail("Expected error for non-existent task resubscription"); + } + } + + /** + * Regression test for race condition where MainQueue closed when first ChildQueue closed, + * preventing resubscription. With reference counting, MainQueue stays alive while any + * ChildQueue exists, allowing successful concurrent operations. + * + * This test verifies that: + * 1. Multiple consumers can be active simultaneously + * 2. All consumers receive events while the MainQueue is alive + * 3. MainQueue doesn't close prematurely when earlier operations complete + */ + @Test + @Timeout(value = 1, unit = TimeUnit.MINUTES) + public void testMainQueueReferenceCountingWithMultipleConsumers() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { + // 1. Ensure queue exists for the task + ensureQueueForTask(MINIMAL_TASK.getId()); + + // 2. First consumer subscribes and receives initial event + CountDownLatch firstConsumerLatch = new CountDownLatch(1); + AtomicReference firstConsumerEvent = new AtomicReference<>(); + AtomicBoolean firstUnexpectedEvent = new AtomicBoolean(false); + AtomicReference firstErrorRef = new AtomicReference<>(); + AtomicBoolean firstReceivedInitialSnapshot = new AtomicBoolean(false); + + BiConsumer firstConsumer = (event, agentCard) -> { + if (event instanceof TaskUpdateEvent_v0_3 tue && tue.getUpdateEvent() instanceof TaskArtifactUpdateEvent_v0_3 artifact) { + firstConsumerEvent.set(artifact); + firstConsumerLatch.countDown(); + } else if (event instanceof TaskEvent_v0_3) { + // v0.3 spec confirms task snapshot as first event on resubscribe is valid behavior + // See: https://a2a-protocol.org/v0.3.0/specification/#721-sendstreamingmessageresponse-object + if (!firstReceivedInitialSnapshot.compareAndSet(false, true)) { + firstUnexpectedEvent.set(true); // TaskEvent received after first event + } + } else if (!(event instanceof TaskUpdateEvent_v0_3)) { + firstUnexpectedEvent.set(true); + } + }; + + Consumer firstErrorHandler = error -> { + if (!isStreamClosedError(error)) { + firstErrorRef.set(error); + } + firstConsumerLatch.countDown(); + }; + + // Wait for first subscription to be established + CountDownLatch firstSubscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> firstSubscriptionLatch.countDown()); + + getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.getId()), + List.of(firstConsumer), + firstErrorHandler); + + assertTrue(firstSubscriptionLatch.await(15, TimeUnit.SECONDS), "First subscription should be established"); + + // Enqueue first event + TaskArtifactUpdateEvent_v0_3 event1 = new TaskArtifactUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .artifact(new Artifact_v0_3.Builder() + .artifactId("artifact-1") + .parts(new TextPart_v0_3("First artifact")) + .build()) + .build(); + enqueueEventOnServer(event1); + + // Wait for first consumer to receive event + assertTrue(firstConsumerLatch.await(15, TimeUnit.SECONDS), "First consumer should receive event"); + assertFalse(firstUnexpectedEvent.get()); + assertNull(firstErrorRef.get()); + assertNotNull(firstConsumerEvent.get()); + + // Verify we have multiple child queues (ensureQueue + first resubscribe) + int childCountBeforeSecond = getChildQueueCount(MINIMAL_TASK.getId()); + assertTrue(childCountBeforeSecond >= 2, "Should have at least 2 child queues"); + + // 3. Second consumer resubscribes while first is still active + // This simulates the Kafka replication race condition where resubscription happens + // while other consumers are still active. Without reference counting, the MainQueue + // might close when the ensureQueue ChildQueue closes, preventing this resubscription. + CountDownLatch secondConsumerLatch = new CountDownLatch(1); + AtomicReference secondConsumerEvent = new AtomicReference<>(); + AtomicBoolean secondUnexpectedEvent = new AtomicBoolean(false); + AtomicReference secondErrorRef = new AtomicReference<>(); + AtomicBoolean secondReceivedInitialSnapshot = new AtomicBoolean(false); + + BiConsumer secondConsumer = (event, agentCard) -> { + if (event instanceof TaskUpdateEvent_v0_3 tue && tue.getUpdateEvent() instanceof TaskArtifactUpdateEvent_v0_3 artifact) { + secondConsumerEvent.set(artifact); + secondConsumerLatch.countDown(); + } else if (event instanceof TaskEvent_v0_3) { + // v0.3 spec confirms task snapshot as first event on resubscribe is valid behavior + // See: https://a2a-protocol.org/v0.3.0/specification/#721-sendstreamingmessageresponse-object + if (!secondReceivedInitialSnapshot.compareAndSet(false, true)) { + secondUnexpectedEvent.set(true); // TaskEvent received after first event + } + } else if (!(event instanceof TaskUpdateEvent_v0_3)) { + secondUnexpectedEvent.set(true); + } + }; + + Consumer secondErrorHandler = error -> { + if (!isStreamClosedError(error)) { + secondErrorRef.set(error); + } + secondConsumerLatch.countDown(); + }; + + // Wait for second subscription to be established + CountDownLatch secondSubscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> secondSubscriptionLatch.countDown()); + + // This should succeed with reference counting because MainQueue stays alive + // while first consumer's ChildQueue exists + getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.getId()), + List.of(secondConsumer), + secondErrorHandler); + + assertTrue(secondSubscriptionLatch.await(15, TimeUnit.SECONDS), "Second subscription should be established"); + + // Verify child queue count increased (now ensureQueue + first + second) + int childCountAfterSecond = getChildQueueCount(MINIMAL_TASK.getId()); + assertTrue(childCountAfterSecond > childCountBeforeSecond, + "Child queue count should increase after second resubscription"); + + // 4. Enqueue second event - both consumers should receive it + TaskArtifactUpdateEvent_v0_3 event2 = new TaskArtifactUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .artifact(new Artifact_v0_3.Builder() + .artifactId("artifact-2") + .parts(new TextPart_v0_3("Second artifact")) + .build()) + .build(); + enqueueEventOnServer(event2); + + // Both consumers should receive the event + assertTrue(secondConsumerLatch.await(15, TimeUnit.SECONDS), "Second consumer should receive event"); + assertFalse(secondUnexpectedEvent.get()); + assertNull(secondErrorRef.get(), + "Resubscription should succeed with reference counting (MainQueue stays alive)"); + + TaskArtifactUpdateEvent_v0_3 receivedEvent = secondConsumerEvent.get(); + assertNotNull(receivedEvent); + assertEquals("artifact-2", receivedEvent.getArtifact().artifactId()); + assertEquals("Second artifact", ((TextPart_v0_3) receivedEvent.getArtifact().parts().get(0)).getText()); + + } finally { + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + /** + * Wait for the child queue count to reach a specific value. + * Uses polling with sleep intervals, similar to awaitStreamingSubscription(). + * + * @param taskId The task ID + * @param expectedCount The expected child queue count + * @param timeoutMs Timeout in milliseconds + * @return true if count reached expected value within timeout, false otherwise + */ + private boolean waitForChildQueueCountToBe(String taskId, int expectedCount, long timeoutMs) { + long endTime = System.currentTimeMillis() + timeoutMs; + while (System.currentTimeMillis() < endTime) { + if (getChildQueueCount(taskId) == expectedCount) { + return true; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + } + return false; + } + + @Test + public void testListPushNotificationConfigWithConfigId() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + PushNotificationConfig_v0_3 notificationConfig1 = + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id("config1") + .build(); + PushNotificationConfig_v0_3 notificationConfig2 = + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id("config2") + .build(); + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + + try { + List result = getClient().listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + assertEquals(2, result.size()); + assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.getId(), notificationConfig1), result.get(0)); + assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.getId(), notificationConfig2), result.get(1)); + } catch (Exception e) { + fail(); + } finally { + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config1"); + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config2"); + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testListPushNotificationConfigWithoutConfigId() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + PushNotificationConfig_v0_3 notificationConfig1 = + new PushNotificationConfig_v0_3.Builder() + .url("http://1.example.com") + .build(); + PushNotificationConfig_v0_3 notificationConfig2 = + new PushNotificationConfig_v0_3.Builder() + .url("http://2.example.com") + .build(); + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); + + // will overwrite the previous one + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + try { + List result = getClient().listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + assertEquals(1, result.size()); + + PushNotificationConfig_v0_3 expectedNotificationConfig = new PushNotificationConfig_v0_3.Builder() + .url("http://2.example.com") + .id(MINIMAL_TASK.getId()) + .build(); + assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.getId(), expectedNotificationConfig), + result.get(0)); + } catch (Exception e) { + fail(); + } finally { + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testListPushNotificationConfigTaskNotFound() { + try { + List result = getClient().listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3("non-existent-task")); + fail(); + } catch (A2AClientException_v0_3 e) { + assertInstanceOf(TaskNotFoundError_v0_3.class, e.getCause()); + } + } + + @Test + public void testListPushNotificationConfigEmptyList() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { + List result = getClient().listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + assertEquals(0, result.size()); + } catch (Exception e) { + fail(e.getMessage()); + } finally { + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testDeletePushNotificationConfigWithValidConfigId() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + saveTaskInTaskStore(new Task_v0_3.Builder() + .id("task-456") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build()); + + PushNotificationConfig_v0_3 notificationConfig1 = + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id("config1") + .build(); + PushNotificationConfig_v0_3 notificationConfig2 = + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id("config2") + .build(); + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + savePushNotificationConfigInStore("task-456", notificationConfig1); + + try { + // specify the config ID to delete + getClient().deleteTaskPushNotificationConfigurations( + new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), "config1")); + + // should now be 1 left + List result = getClient().listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + assertEquals(1, result.size()); + + // should remain unchanged, this is a different task + result = getClient().listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3("task-456")); + assertEquals(1, result.size()); + } catch (Exception e) { + fail(e.getMessage()); + } finally { + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config1"); + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config2"); + deletePushNotificationConfigInStore("task-456", "config1"); + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore("task-456"); + } + } + + @Test + public void testDeletePushNotificationConfigWithNonExistingConfigId() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + PushNotificationConfig_v0_3 notificationConfig1 = + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id("config1") + .build(); + PushNotificationConfig_v0_3 notificationConfig2 = + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id("config2") + .build(); + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + + try { + getClient().deleteTaskPushNotificationConfigurations( + new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), "non-existent-config-id")); + + // should remain unchanged + List result = getClient().listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + assertEquals(2, result.size()); + } catch (Exception e) { + fail(); + } finally { + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config1"); + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config2"); + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + public void testDeletePushNotificationConfigTaskNotFound() { + try { + getClient().deleteTaskPushNotificationConfigurations( + new DeleteTaskPushNotificationConfigParams_v0_3("non-existent-task", + "non-existent-config-id")); + fail(); + } catch (A2AClientException_v0_3 e) { + assertInstanceOf(TaskNotFoundError_v0_3.class, e.getCause()); + } + } + + @Test + public void testDeletePushNotificationConfigSetWithoutConfigId() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + PushNotificationConfig_v0_3 notificationConfig1 = + new PushNotificationConfig_v0_3.Builder() + .url("http://1.example.com") + .build(); + PushNotificationConfig_v0_3 notificationConfig2 = + new PushNotificationConfig_v0_3.Builder() + .url("http://2.example.com") + .build(); + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); + + // this one will overwrite the previous one + savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + + try { + getClient().deleteTaskPushNotificationConfigurations( + new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), MINIMAL_TASK.getId())); + + // should now be 0 + List result = getClient().listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId()), null); + assertEquals(0, result.size()); + } catch (Exception e) { + fail(); + } finally { + deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + @Test + @Timeout(value = 1, unit = TimeUnit.MINUTES) + public void testNonBlockingWithMultipleMessages() throws Exception { + AtomicReference generatedTaskIdRef = new AtomicReference<>(); + try { + // 1. Send first non-blocking message without taskId - server generates one + // Routing is by message content prefix "multi-event:first" + Message_v0_3 message1 = new Message_v0_3.Builder(MESSAGE) + .parts(new TextPart_v0_3("multi-event:first")) + .build(); + + AtomicReference taskIdRef = new AtomicReference<>(); + CountDownLatch firstTaskLatch = new CountDownLatch(1); + + BiConsumer firstMessageConsumer = (event, agentCard) -> { + if (event instanceof TaskEvent_v0_3 te) { + taskIdRef.set(te.getTask().getId()); + firstTaskLatch.countDown(); + } else if (event instanceof TaskUpdateEvent_v0_3 tue && tue.getUpdateEvent() instanceof TaskStatusUpdateEvent_v0_3 status) { + taskIdRef.set(status.getTaskId()); + firstTaskLatch.countDown(); + } + }; + + // Non-blocking message creates task in WORKING state and returns immediately + // Queue stays open because task is not in final state + getPollingClient().sendMessage(message1, List.of(firstMessageConsumer), null); + + assertTrue(firstTaskLatch.await(10, TimeUnit.SECONDS)); + String taskId = taskIdRef.get(); + assertNotNull(taskId); + generatedTaskIdRef.set(taskId); + + // 2. Resubscribe to task (queue should still be open) + CountDownLatch resubEventLatch = new CountDownLatch(2); // artifact-2 + completion + List resubReceivedEvents = new CopyOnWriteArrayList<>(); + AtomicBoolean resubUnexpectedEvent = new AtomicBoolean(false); + AtomicReference resubErrorRef = new AtomicReference<>(); + AtomicBoolean resubReceivedInitialSnapshot = new AtomicBoolean(false); + + BiConsumer resubConsumer = (event, agentCard) -> { + if (event instanceof TaskUpdateEvent_v0_3 tue) { + resubReceivedEvents.add(tue.getUpdateEvent()); + resubEventLatch.countDown(); + } else if (event instanceof TaskEvent_v0_3) { + // v0.3 spec confirms task snapshot as first event on resubscribe is valid behavior + // See: https://a2a-protocol.org/v0.3.0/specification/#721-sendstreamingmessageresponse-object + if (!resubReceivedInitialSnapshot.compareAndSet(false, true)) { + System.err.println("testNonBlockingWithMultipleMessages: TaskEvent received after first event"); + resubUnexpectedEvent.set(true); // TaskEvent received after first event + } + } else { + System.err.println("testNonBlockingWithMultipleMessages: Unexpected event type in resubConsumer: " + event.getClass().getName()); + resubUnexpectedEvent.set(true); + } + }; + + Consumer resubErrorHandler = error -> { + if (!isStreamClosedError(error)) { + resubErrorRef.set(error); + } + }; + + // Wait for subscription to be active + CountDownLatch subscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); + + getClient().resubscribe(new TaskIdParams_v0_3(taskId), + List.of(resubConsumer), + resubErrorHandler); + + assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); + + // 3. Send second streaming message to same taskId + Message_v0_3 message2 = new Message_v0_3.Builder(MESSAGE) + .taskId(taskId) + .parts(new TextPart_v0_3("multi-event:second")) + .build(); + + CountDownLatch streamEventLatch = new CountDownLatch(2); // artifact-2 + completion + List streamReceivedEvents = new CopyOnWriteArrayList<>(); + AtomicBoolean streamUnexpectedEvent = new AtomicBoolean(false); + + BiConsumer streamConsumer = (event, agentCard) -> { + if (event instanceof TaskUpdateEvent_v0_3 tue) { + streamReceivedEvents.add(tue.getUpdateEvent()); + streamEventLatch.countDown(); + } else { + streamUnexpectedEvent.set(true); + } + }; + + // Streaming message adds artifact-2 and completes task + getClient().sendMessage(message2, List.of(streamConsumer), null); + + // 4. Verify both consumers received artifact-2 and completion + assertTrue(resubEventLatch.await(10, TimeUnit.SECONDS)); + assertTrue(streamEventLatch.await(10, TimeUnit.SECONDS)); + + assertFalse(resubUnexpectedEvent.get()); + assertFalse(streamUnexpectedEvent.get()); + assertNull(resubErrorRef.get()); + + // Both should have received 2 events: artifact-2 and completion + assertEquals(2, resubReceivedEvents.size()); + assertEquals(2, streamReceivedEvents.size()); + + // Verify resubscription events + long resubArtifactCount = resubReceivedEvents.stream() + .filter(e -> e instanceof TaskArtifactUpdateEvent_v0_3) + .count(); + assertEquals(1, resubArtifactCount); + + long resubCompletionCount = resubReceivedEvents.stream() + .filter(e -> e instanceof TaskStatusUpdateEvent_v0_3) + .filter(e -> ((TaskStatusUpdateEvent_v0_3) e).isFinal()) + .count(); + assertEquals(1, resubCompletionCount); + + // Verify streaming events + long streamArtifactCount = streamReceivedEvents.stream() + .filter(e -> e instanceof TaskArtifactUpdateEvent_v0_3) + .count(); + assertEquals(1, streamArtifactCount); + + long streamCompletionCount = streamReceivedEvents.stream() + .filter(e -> e instanceof TaskStatusUpdateEvent_v0_3) + .filter(e -> ((TaskStatusUpdateEvent_v0_3) e).isFinal()) + .count(); + assertEquals(1, streamCompletionCount); + + // Verify artifact-2 details from resubscription + TaskArtifactUpdateEvent_v0_3 resubArtifact = (TaskArtifactUpdateEvent_v0_3) resubReceivedEvents.stream() + .filter(e -> e instanceof TaskArtifactUpdateEvent_v0_3) + .findFirst() + .orElseThrow(); + assertEquals("artifact-2", resubArtifact.getArtifact().artifactId()); + assertEquals("Second message artifact", + ((TextPart_v0_3) resubArtifact.getArtifact().parts().get(0)).getText()); + + // Verify artifact-2 details from streaming + TaskArtifactUpdateEvent_v0_3 streamArtifact = (TaskArtifactUpdateEvent_v0_3) streamReceivedEvents.stream() + .filter(e -> e instanceof TaskArtifactUpdateEvent_v0_3) + .findFirst() + .orElseThrow(); + assertEquals("artifact-2", streamArtifact.getArtifact().artifactId()); + assertEquals("Second message artifact", + ((TextPart_v0_3) streamArtifact.getArtifact().parts().get(0)).getText()); + } finally { + String taskId = generatedTaskIdRef.get(); + if (taskId != null) { + deleteTaskInTaskStore(taskId); + } + } + } + + @Test + public void testMalformedJSONRPCRequest() { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + + // missing closing bracket + String malformedRequest = "{\"jsonrpc\": \"2.0\", \"method\": \"message/send\", \"params\": {\"foo\": \"bar\"}"; + JSONRPCErrorResponse_v0_3 response = givenV03() + .contentType(MediaType.APPLICATION_JSON) + .body(malformedRequest) + .when() + .post("/") + .then() + .statusCode(200) + .extract() + .as(JSONRPCErrorResponse_v0_3.class); + assertNotNull(response.getError()); + assertEquals(new JSONParseError_v0_3().getCode(), response.getError().getCode()); + } + + @Test + public void testInvalidParamsJSONRPCRequest() { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + + String invalidParamsRequest = """ + {"jsonrpc": "2.0", "method": "message/send", "params": "not_a_dict", "id": "1"} + """; + testInvalidParams(invalidParamsRequest); + + invalidParamsRequest = """ + {"jsonrpc": "2.0", "method": "message/send", "params": {"message": {"parts": "invalid"}}, "id": "1"} + """; + testInvalidParams(invalidParamsRequest); + } + + private void testInvalidParams(String invalidParamsRequest) { + JSONRPCErrorResponse_v0_3 response = givenV03() + .contentType(MediaType.APPLICATION_JSON) + .body(invalidParamsRequest) + .when() + .post("/") + .then() + .statusCode(200) + .extract() + .as(JSONRPCErrorResponse_v0_3.class); + assertNotNull(response.getError()); + assertEquals(new InvalidParamsError_v0_3().getCode(), response.getError().getCode()); + assertEquals("1", response.getId()); + } + + @Test + public void testInvalidJSONRPCRequestMissingJsonrpc() { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + + String invalidRequest = """ + { + "method": "message/send", + "params": {} + } + """; + JSONRPCErrorResponse_v0_3 response = givenV03() + .contentType(MediaType.APPLICATION_JSON) + .body(invalidRequest) + .when() + .post("/") + .then() + .statusCode(200) + .extract() + .as(JSONRPCErrorResponse_v0_3.class); + assertNotNull(response.getError()); + assertEquals(new InvalidRequestError_v0_3().getCode(), response.getError().getCode()); + } + + @Test + public void testInvalidJSONRPCRequestMissingMethod() { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + + String invalidRequest = """ + {"jsonrpc": "2.0", "params": {}} + """; + JSONRPCErrorResponse_v0_3 response = givenV03() + .contentType(MediaType.APPLICATION_JSON) + .body(invalidRequest) + .when() + .post("/") + .then() + .statusCode(200) + .extract() + .as(JSONRPCErrorResponse_v0_3.class); + assertNotNull(response.getError()); + assertEquals(new InvalidRequestError_v0_3().getCode(), response.getError().getCode()); + } + + @Test + public void testInvalidJSONRPCRequestInvalidId() { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + + String invalidRequest = """ + {"jsonrpc": "2.0", "method": "message/send", "params": {}, "id": {"bad": "type"}} + """; + JSONRPCErrorResponse_v0_3 response = givenV03() + .contentType(MediaType.APPLICATION_JSON) + .body(invalidRequest) + .when() + .post("/") + .then() + .statusCode(200) + .extract() + .as(JSONRPCErrorResponse_v0_3.class); + assertNotNull(response.getError()); + assertEquals(new InvalidRequestError_v0_3().getCode(), response.getError().getCode()); + } + + @Test + public void testInvalidJSONRPCRequestNonExistentMethod() { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + + String invalidRequest = """ + {"jsonrpc": "2.0", "method" : "nonexistent/method", "params": {}} + """; + JSONRPCErrorResponse_v0_3 response = givenV03() + .contentType(MediaType.APPLICATION_JSON) + .body(invalidRequest) + .when() + .post("/") + .then() + .statusCode(200) + .extract() + .as(JSONRPCErrorResponse_v0_3.class); + assertNotNull(response.getError()); + assertEquals(new MethodNotFoundError_v0_3().getCode(), response.getError().getCode()); + } + + @Test + public void testNonStreamingMethodWithAcceptHeader() throws Exception { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + testGetTask(MediaType.APPLICATION_JSON); + } + + @Test + public void testStreamingMethodWithAcceptHeader() throws Exception { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + + testSendStreamingMessageWithHttpClient(MediaType.SERVER_SENT_EVENTS); + } + + @Test + public void testStreamingMethodWithoutAcceptHeader() throws Exception { + // skip this test for non-JSONRPC transports + assumeTrue(TransportProtocol_v0_3.JSONRPC.asString().equals(getTransportProtocol()), + "JSONRPC-specific test"); + + testSendStreamingMessageWithHttpClient(null); + } + + private void testSendStreamingMessageWithHttpClient(String mediaType) throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + try { + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .build(); + SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( + "1", new MessageSendParams_v0_3(message, null, null)); + + CompletableFuture>> responseFuture = initialiseStreamingRequest(request, mediaType); + + CountDownLatch latch = new CountDownLatch(1); + AtomicReference errorRef = new AtomicReference<>(); + + responseFuture.thenAccept(response -> { + if (response.statusCode() != 200) { + throw new IllegalStateException("Status code was " + response.statusCode()); + } + response.body().forEach(line -> { + try { + SendStreamingMessageResponse_v0_3 jsonResponse = extractJsonResponseFromSseLine(line); + if (jsonResponse != null) { + assertNull(jsonResponse.getError()); + Message_v0_3 messageResponse = (Message_v0_3) jsonResponse.getResult(); + assertEquals(MESSAGE.getMessageId(), messageResponse.getMessageId()); + assertEquals(MESSAGE.getRole(), messageResponse.getRole()); + Part_v0_3 part = messageResponse.getParts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("test message", ((TextPart_v0_3) part).getText()); + latch.countDown(); + } + } catch (JsonProcessingException_v0_3 e) { + throw new RuntimeException(e); + } + }); + }).exceptionally(t -> { + if (!isStreamClosedError(t)) { + errorRef.set(t); + } + latch.countDown(); + return null; + }); + + boolean dataRead = latch.await(20, TimeUnit.SECONDS); + Assertions.assertTrue(dataRead); + Assertions.assertNull(errorRef.get()); + + } finally { + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + + public void testSendStreamingMessage(boolean createTask) throws Exception { + if (createTask) { + saveTaskInTaskStore(MINIMAL_TASK); + } + try { + Message_v0_3.Builder messageBuilder = new Message_v0_3.Builder(MESSAGE); + if (createTask) { + messageBuilder.taskId(MINIMAL_TASK.getId()).contextId(MINIMAL_TASK.getContextId()); + } + Message_v0_3 message = messageBuilder.build(); + + CountDownLatch latch = new CountDownLatch(1); + AtomicReference receivedMessage = new AtomicReference<>(); + AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); + AtomicReference errorRef = new AtomicReference<>(); + + BiConsumer consumer = (event, agentCard) -> { + if (event instanceof MessageEvent_v0_3 messageEvent) { + if (latch.getCount() > 0) { + receivedMessage.set(messageEvent.getMessage()); + latch.countDown(); + } else { + wasUnexpectedEvent.set(true); + } + } else { + wasUnexpectedEvent.set(true); + } + }; + + Consumer errorHandler = error -> { + errorRef.set(error); + latch.countDown(); + }; + + // testing the streaming send message + getClient().sendMessage(message, List.of(consumer), errorHandler); + + assertTrue(latch.await(10, TimeUnit.SECONDS)); + assertFalse(wasUnexpectedEvent.get()); + assertNull(errorRef.get()); + + Message_v0_3 messageResponse = receivedMessage.get(); + assertNotNull(messageResponse); + assertEquals(MESSAGE.getMessageId(), messageResponse.getMessageId()); + assertEquals(MESSAGE.getRole(), messageResponse.getRole()); + Part_v0_3 part = messageResponse.getParts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("test message", ((TextPart_v0_3) part).getText()); + } catch (A2AClientException_v0_3 e) { + fail("Unexpected exception during sendMessage: " + e.getMessage(), e); + } finally { + if (createTask) { + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + } + } + + private CompletableFuture>> initialiseStreamingRequest( + StreamingJSONRPCRequest_v0_3 request, String mediaType) throws Exception { + + // Create the client + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + + // Create the request + HttpRequest.Builder builder = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/")) + .POST(HttpRequest.BodyPublishers.ofString(JsonUtil_v0_3.toJson(request))) + .header("Content-Type", APPLICATION_JSON); + if (mediaType != null) { + builder.header("Accept", mediaType); + } + HttpRequest httpRequest = builder.build(); + + // Send request async and return the CompletableFuture + return client.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofLines()); + } + + private SendStreamingMessageResponse_v0_3 extractJsonResponseFromSseLine(String line) throws JsonProcessingException_v0_3 { + line = extractSseData(line); + if (line != null) { + return JsonUtil_v0_3.fromJson(line, SendStreamingMessageResponse_v0_3.class); + } + return null; + } + + private static String extractSseData(String line) { + if (line.startsWith("data:")) { + line = line.substring(5).trim(); + return line; + } + return null; + } + + protected boolean isStreamClosedError(Throwable throwable) { + // Unwrap the CompletionException + Throwable cause = throwable; + + while (cause != null) { + if (cause instanceof EOFException) { + return true; + } + if (cause instanceof IOException && cause.getMessage() != null + && cause.getMessage().contains("cancelled")) { + // stream is closed upon cancellation + return true; + } + cause = cause.getCause(); + } + return false; + } + + /** + * Save a v0.3 task to the v1.0 task store via HTTP. + * Converts v0.3 → v1.0 using TaskMapper. + */ + protected void saveTaskInTaskStore(Task_v0_3 task) throws Exception { + // Convert v0.3 → v1.0 + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(task); + + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task")) + .POST(HttpRequest.BodyPublishers.ofString(org.a2aproject.sdk.jsonrpc.common.json.JsonUtil.toJson(v10Task))) + .header("Content-Type", APPLICATION_JSON) + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(String.format("Saving task failed! Status: %d, Body: %s", response.statusCode(), response.body())); + } + } + + /** + * Get a v0.3 task from the v1.0 task store via HTTP. + * Converts v1.0 → v0.3 using TaskMapper. + */ + protected Task_v0_3 getTaskFromTaskStore(String taskId) throws Exception { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task/" + taskId)) + .GET() + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() == 404) { + return null; + } + if (response.statusCode() != 200) { + throw new RuntimeException(String.format("Getting task failed! Status: %d, Body: %s", response.statusCode(), response.body())); + } + + // Convert v1.0 → v0.3 + org.a2aproject.sdk.spec.Task v10Task = org.a2aproject.sdk.jsonrpc.common.json.JsonUtil.fromJson( + response.body(), org.a2aproject.sdk.spec.Task.class); + return TaskMapper_v0_3.INSTANCE.fromV10(v10Task); + } + + protected void deleteTaskInTaskStore(String taskId) throws Exception { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(("http://localhost:" + serverPort + "/test/task/" + taskId))) + .DELETE() + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(response.statusCode() + ": Deleting task failed!" + response.body()); + } + } + + protected void ensureQueueForTask(String taskId) throws Exception { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/queue/ensure/" + taskId)) + .POST(HttpRequest.BodyPublishers.noBody()) + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(String.format("Ensuring queue failed! Status: %d, Body: %s", response.statusCode(), response.body())); + } + } + + /** + * Enqueue a v0.3 event on the server. + * Converts v0.3 → v1.0 using event-specific mappers. + */ + protected void enqueueEventOnServer(Event_v0_3 event) throws Exception { + String path; + Object v10Event; + + if (event instanceof TaskArtifactUpdateEvent_v0_3 e) { + path = "test/queue/enqueueTaskArtifactUpdateEvent/" + e.getTaskId(); + v10Event = TaskArtifactUpdateEventMapper_v0_3.INSTANCE.toV10(e); + } else if (event instanceof TaskStatusUpdateEvent_v0_3 e) { + path = "test/queue/enqueueTaskStatusUpdateEvent/" + e.getTaskId(); + v10Event = TaskStatusUpdateEventMapper_v0_3.INSTANCE.toV10(e); + } else { + throw new RuntimeException("Unknown event type " + event.getClass() + ". If you need the ability to" + + " handle more types, please add the REST endpoints."); + } + + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/" + path)) + .header("Content-Type", APPLICATION_JSON) + .POST(HttpRequest.BodyPublishers.ofString(org.a2aproject.sdk.jsonrpc.common.json.JsonUtil.toJson(v10Event))) + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(response.statusCode() + ": Queueing event failed!" + response.body()); + } + } + + private CompletableFuture awaitStreamingSubscription() { + int cnt = getStreamingSubscribedCount(); + AtomicInteger initialCount = new AtomicInteger(cnt); + + return CompletableFuture.runAsync(() -> { + try { + boolean done = false; + long end = System.currentTimeMillis() + 15000; + while (System.currentTimeMillis() < end) { + int count = getStreamingSubscribedCount(); + if (count > initialCount.get()) { + done = true; + break; + } + Thread.sleep(500); + } + if (!done) { + throw new RuntimeException("Timed out waiting for subscription"); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted"); + } + }); + } + + private int getStreamingSubscribedCount() { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/streamingSubscribedCount")) + .GET() + .build(); + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + String body = response.body().trim(); + return Integer.parseInt(body); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + protected int getChildQueueCount(String taskId) { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/queue/childCount/" + taskId)) + .GET() + .build(); + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + String body = response.body().trim(); + return Integer.parseInt(body); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + /** + * Delete a push notification config from the v1.0 store. + */ + protected void deletePushNotificationConfigInStore(String taskId, String configId) throws Exception { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(("http://localhost:" + serverPort + "/test/task/" + taskId + "/config/" + configId))) + .DELETE() + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(response.statusCode() + ": Deleting task failed!" + response.body()); + } + } + + /** + * Save a v0.3 push notification config to the v1.0 store. + * Converts v0.3 → v1.0 using mappers. + */ + protected void savePushNotificationConfigInStore(String taskId, PushNotificationConfig_v0_3 notificationConfig) throws Exception { + // Create v0.3 TaskPushNotificationConfig wrapper + TaskPushNotificationConfig_v0_3 v03Config = + new TaskPushNotificationConfig_v0_3(taskId, notificationConfig); + + // Convert v0.3 → v1.0 + org.a2aproject.sdk.spec.TaskPushNotificationConfig v10Config = + TaskPushNotificationConfigMapper_v0_3.INSTANCE.toV10(v03Config); + + // Send to v1.0 server using v1.0 JSON serialization + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task/" + taskId)) + .POST(HttpRequest.BodyPublishers.ofString(org.a2aproject.sdk.jsonrpc.common.json.JsonUtil.toJson(v10Config))) + .header("Content-Type", APPLICATION_JSON) + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200) { + throw new RuntimeException(response.statusCode() + ": Creating task push notification config failed! " + response.body()); + } + } + + /** + * Get a client instance. + */ + protected Client_v0_3 getClient() throws A2AClientException_v0_3 { + if (client == null) { + client = createClient(true); + } + return client; + } + + /** + * Get a client configured for non-streaming operations. + */ + protected Client_v0_3 getNonStreamingClient() throws A2AClientException_v0_3 { + if (nonStreamingClient == null) { + nonStreamingClient = createClient(false); + } + return nonStreamingClient; + } + + /** + * Get a client configured for polling (non-blocking) operations. + */ + protected Client_v0_3 getPollingClient() throws A2AClientException_v0_3 { + if (pollingClient == null) { + pollingClient = createPollingClient(); + } + return pollingClient; + } + + /** + * Create a client with the specified streaming configuration. + */ + private Client_v0_3 createClient(boolean streaming) throws A2AClientException_v0_3 { + AgentCard_v0_3 agentCard = createTestAgentCard(); + ClientConfig_v0_3 clientConfig = createClientConfig(streaming); + + ClientBuilder_v0_3 clientBuilder = Client_v0_3 + .builder(agentCard) + .clientConfig(clientConfig); + + configureTransport(clientBuilder); + + return clientBuilder.build(); + } + + /** + * Create a test agent card with the appropriate transport configuration. + */ + private AgentCard_v0_3 createTestAgentCard() { + return new AgentCard_v0_3.Builder() + .name("test-card") + .description("A test agent card") + .url(getTransportUrl()) + .version("1.0") + .documentationUrl("http://example.com/docs") + .preferredTransport(getTransportProtocol()) + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(true) + .pushNotifications(true) + .stateTransitionHistory(true) + .build()) + .defaultInputModes(List.of("text")) + .defaultOutputModes(List.of("text")) + .skills(List.of()) + .additionalInterfaces(List.of(new AgentInterface_v0_3(getTransportProtocol(), getTransportUrl()))) + .protocolVersion("0.2.5") + .build(); + } + + /** + * Create client configuration with transport-specific settings. + */ + private ClientConfig_v0_3 createClientConfig(boolean streaming) { + return new ClientConfig_v0_3.Builder() + .setStreaming(streaming) + .build(); + } + + /** + * Create a client configured for polling (non-blocking) operations. + */ + private Client_v0_3 createPollingClient() throws A2AClientException_v0_3 { + AgentCard_v0_3 agentCard = createTestAgentCard(); + ClientConfig_v0_3 clientConfig = new ClientConfig_v0_3.Builder() + .setStreaming(false) // Non-streaming + .setPolling(true) // Polling mode (translates to blocking=false on server) + .build(); + + ClientBuilder_v0_3 clientBuilder = Client_v0_3 + .builder(agentCard) + .clientConfig(clientConfig); + + configureTransport(clientBuilder); + + return clientBuilder.build(); + } + + /** + * Integration test for THE BIG IDEA: MainQueue stays open for non-final tasks, + * enabling fire-and-forget patterns and late resubscription. + * + * Flow: + * 1. Agent emits WORKING state (non-final) and finishes without completing + * 2. Client disconnects (ChildQueue closes) + * 3. MainQueue should stay OPEN because task is non-final + * 4. Late resubscription should succeed + */ + @Test + @Timeout(value = 2, unit = TimeUnit.MINUTES) + public void testMainQueueStaysOpenForNonFinalTasks() throws Exception { + String taskId = "fire-and-forget-task-integration"; + String contextId = "fire-ctx"; + + // Create task in WORKING state (non-final) + Task_v0_3 workingTask = new Task_v0_3.Builder() + .id(taskId) + .contextId(contextId) + .status(new TaskStatus_v0_3(TaskState_v0_3.WORKING)) + .build(); + saveTaskInTaskStore(workingTask); + + try { + // Ensure queue exists for the task + ensureQueueForTask(taskId); + + // Send a message that will leave task in WORKING state (fire-and-forget pattern) + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(taskId) + .contextId(contextId) + .parts(new TextPart_v0_3("fire and forget")) + .build(); + + CountDownLatch firstEventLatch = new CountDownLatch(1); + AtomicReference errorRef = new AtomicReference<>(); + + BiConsumer consumer = (event, agentCard) -> { + // Receive any event (Message) to know agent processed the request + if (event instanceof MessageEvent_v0_3) { + firstEventLatch.countDown(); + } + }; + + Consumer errorHandler = error -> { + if (!isStreamClosedError(error)) { + errorRef.set(error); + } + firstEventLatch.countDown(); + }; + + // Start streaming subscription + CountDownLatch subscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); + + getClient().sendMessage(message, List.of(consumer), errorHandler); + + // Wait for subscription to be established + assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS), + "Subscription should be established"); + + // Wait for agent to respond (test agent sends Message, not WORKING status) + assertTrue(firstEventLatch.await(15, TimeUnit.SECONDS), + "Should receive agent response"); + assertNull(errorRef.get()); + + // Give agent time to finish (task remains in WORKING state - non-final) + Thread.sleep(2000); + + // THE BIG IDEA TEST: Resubscribe to the task + // Even though the agent finished and original ChildQueue closed, + // MainQueue should still be open because task is in non-final WORKING state + + CountDownLatch resubLatch = new CountDownLatch(1); + AtomicReference resubErrorRef = new AtomicReference<>(); + + BiConsumer resubConsumer = (event, agentCard) -> { + // We might not receive events immediately, but subscription should succeed + resubLatch.countDown(); + }; + + Consumer resubErrorHandler = error -> { + if (!isStreamClosedError(error)) { + resubErrorRef.set(error); + } + resubLatch.countDown(); + }; + + // This should succeed - MainQueue is still open for non-final task + CountDownLatch resubSubscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> resubSubscriptionLatch.countDown()); + + getClient().resubscribe(new TaskIdParams_v0_3(taskId), + List.of(resubConsumer), + resubErrorHandler); + + // Wait for resubscription to be established + assertTrue(resubSubscriptionLatch.await(15, TimeUnit.SECONDS), + "Resubscription should succeed - MainQueue stayed open for non-final task"); + + // Verify no errors during resubscription + assertNull(resubErrorRef.get(), + "Resubscription should not error - validates THE BIG IDEA works end-to-end"); + + } finally { + deleteTaskInTaskStore(taskId); + } + } + + /** + * Integration test verifying MainQueue DOES close when task is finalized. + * This ensures Level 2 protection doesn't prevent cleanup of completed tasks. + * + * Flow: + * 1. Send message to new task (creates task in WORKING, then completes it) + * 2. Task reaches COMPLETED state (final) + * 3. ChildQueue closes after receiving final event + * 4. MainQueue should close because task is finalized + * 5. Resubscription should fail with TaskNotFoundError + */ + @Test + @Timeout(value = 2, unit = TimeUnit.MINUTES) + public void testMainQueueClosesForFinalizedTasks() throws Exception { + // Send a message without taskId - server generates one + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .parts(new TextPart_v0_3("complete task")) + .build(); + + CountDownLatch completionLatch = new CountDownLatch(1); + AtomicReference errorRef = new AtomicReference<>(); + AtomicReference generatedTaskId = new AtomicReference<>(); + + BiConsumer consumer = (event, agentCard) -> { + if (event instanceof TaskEvent_v0_3 te) { + generatedTaskId.compareAndSet(null, te.getTask().getId()); + // Might get Task with final state + if (te.getTask().getStatus().state().isFinal()) { + completionLatch.countDown(); + } + } else if (event instanceof MessageEvent_v0_3 me) { + // Message is considered a final event - capture taskId from the message + generatedTaskId.compareAndSet(null, me.getMessage().getTaskId()); + completionLatch.countDown(); + } else if (event instanceof TaskUpdateEvent_v0_3 tue && + tue.getUpdateEvent() instanceof TaskStatusUpdateEvent_v0_3 status) { + generatedTaskId.compareAndSet(null, status.getTaskId()); + if (status.isFinal()) { + completionLatch.countDown(); + } + } + }; + + Consumer errorHandler = error -> { + if (!isStreamClosedError(error)) { + errorRef.set(error); + } + completionLatch.countDown(); + }; + + try { + // Send message and wait for completion + getClient().sendMessage(message, List.of(consumer), errorHandler); + + assertTrue(completionLatch.await(15, TimeUnit.SECONDS), + "Should receive final event"); + assertNull(errorRef.get(), "Should not have errors during message send"); + + String taskId = generatedTaskId.get(); + assertNotNull(taskId, "Should have captured server-generated taskId"); + + // Give cleanup time to run after final event + Thread.sleep(2000); + + // Try to resubscribe to finalized task - should fail + CountDownLatch errorLatch = new CountDownLatch(1); + AtomicReference resubErrorRef = new AtomicReference<>(); + + Consumer resubErrorHandler = error -> { + if (error == null) { + // Stream completed successfully - ignore, we're waiting for an error + return; + } + if (!isStreamClosedError(error)) { + resubErrorRef.set(error); + } + errorLatch.countDown(); + }; + + // Attempt resubscription + try { + getClient().resubscribe(new TaskIdParams_v0_3(taskId), + List.of(), + resubErrorHandler); + + // Wait for error + assertTrue(errorLatch.await(15, TimeUnit.SECONDS), + "Should receive error for finalized task"); + + Throwable error = resubErrorRef.get(); + assertNotNull(error, "Resubscription should fail for finalized task"); + + // Verify it's a TaskNotFoundError + Throwable cause = error; + boolean foundTaskNotFound = false; + while (cause != null && !foundTaskNotFound) { + if (cause instanceof TaskNotFoundError_v0_3 || + (cause instanceof A2AClientException_v0_3 && + ((A2AClientException_v0_3) cause).getCause() instanceof TaskNotFoundError_v0_3)) { + foundTaskNotFound = true; + } + cause = cause.getCause(); + } + assertTrue(foundTaskNotFound, + "Should receive TaskNotFoundError - MainQueue closed for finalized task"); + + } catch (A2AClientException_v0_3 e) { + // Exception might be thrown immediately instead of via error handler + assertInstanceOf(TaskNotFoundError_v0_3.class, e.getCause(), + "Should fail with TaskNotFoundError - MainQueue cleaned up for finalized task"); + } + + } finally { + // Task might not exist in store if created via message send + String taskId = generatedTaskId.get(); + if (taskId != null) { + try { + Task_v0_3 task = getTaskFromTaskStore(taskId); + if (task != null) { + deleteTaskInTaskStore(taskId); + } + } catch (Exception e) { + // Ignore cleanup errors + } + } + } + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentCardProducer_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentCardProducer_v0_3.java new file mode 100644 index 000000000..130ace31c --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentCardProducer_v0_3.java @@ -0,0 +1,73 @@ +package org.a2aproject.sdk.compat03.conversion; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.server.PublicAgentCard; + +import io.quarkus.arc.DefaultBean; +import io.quarkus.arc.profile.IfBuildProfile; + +/** + * Produces v0.3 AgentCard for compat layer tests. + * Duplicated from v1.0 tests/server-common to avoid dependency on v1.0 test infrastructure. + */ +@ApplicationScoped +@IfBuildProfile("test") +public class AgentCardProducer_v0_3 { + + private static final String PREFERRED_TRANSPORT = "preferred-transport"; + private static final String PROPERTIES_FILE = "/compat-0.3-requesthandler-test.properties"; + + @Produces + @PublicAgentCard + @DefaultBean + public AgentCard_v0_3 createTestAgentCard() { + String port = System.getProperty("test.agent.card.port", "8081"); + String preferredTransport = loadPreferredTransportFromProperties(); + + // v0.3 uses 'url' field for primary endpoint + String url = "grpc".equalsIgnoreCase(preferredTransport) + ? "localhost:" + port + : "http://localhost:" + port; + + return new AgentCard_v0_3.Builder() + .name("compat-0.3-test-agent") + .description("Test agent for v0.3 compatibility layer") + .url(url) + .version("1.0.0") + .preferredTransport(preferredTransport) + .capabilities(new AgentCapabilities_v0_3(true, true, true, List.of())) + .defaultInputModes(List.of("text")) + .defaultOutputModes(List.of("text")) + .skills(List.of()) + .additionalInterfaces(new ArrayList<>()) + .build(); + } + + private static String loadPreferredTransportFromProperties() { + URL url = AgentCardProducer_v0_3.class.getResource(PROPERTIES_FILE); + if (url == null) { + // Default to jsonrpc if no config found + return "jsonrpc"; + } + Properties properties = new Properties(); + try { + try (InputStream in = url.openStream()) { + properties.load(in); + } + } catch (IOException e) { + throw new RuntimeException("Failed to load test properties", e); + } + return properties.getProperty(PREFERRED_TRANSPORT, "jsonrpc"); + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java new file mode 100644 index 000000000..2a684f391 --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java @@ -0,0 +1,106 @@ +package org.a2aproject.sdk.compat03.conversion; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.TextPart; +import org.a2aproject.sdk.spec.UnsupportedOperationError; +import io.quarkus.arc.profile.IfBuildProfile; + +@ApplicationScoped +@IfBuildProfile("test") +public class AgentExecutorProducer_v0_3 { + + @Produces + public AgentExecutor agentExecutor() { + return new AgentExecutor() { + @Override + public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + String taskId = context.getTaskId(); + String input = context.getMessage() != null ? extractTextFromMessage(context.getMessage()) : ""; + + // Special handling for multi-event test (routed by message content) + if (input.startsWith("multi-event:first")) { + agentEmitter.startWork(); + // Return immediately - queue stays open because task is in WORKING state + return; + } + if (input.startsWith("multi-event:second")) { + agentEmitter.addArtifact( + List.of(new TextPart("Second message artifact")), + "artifact-2", "Second Artifact", null); + agentEmitter.complete(); + return; + } + + // Special handling for input-required test (routed by message content) + if (input.startsWith("input-required:")) { + String payload = input.substring("input-required:".length()); + // Second call: user provided the required input - complete the task + if ("User input".equals(payload)) { + agentEmitter.complete(); + return; + } + // First call: emit INPUT_REQUIRED + agentEmitter.requiresInput(agentEmitter.newAgentMessage( + List.of(new TextPart("Please provide additional information")), + context.getMessage().metadata())); + return; + } + + // Special handling for auth-required test (routed by message content) + if (input.startsWith("auth-required:")) { + agentEmitter.requiresAuth(agentEmitter.newAgentMessage( + List.of(new TextPart("Please authenticate with OAuth provider")), + context.getMessage().metadata())); + + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new org.a2aproject.sdk.spec.InternalError("Auth simulation interrupted: " + e.getMessage()); + } + + agentEmitter.complete(); + return; + } + + if ("task-not-supported-123".equals(taskId)) { + throw new UnsupportedOperationError(); + } + + if (context.getMessage() != null) { + agentEmitter.sendMessage(context.getMessage()); + } else { + agentEmitter.addTask(context.getTask()); + } + } + + private String extractTextFromMessage(org.a2aproject.sdk.spec.Message message) { + if (message.parts() == null || message.parts().isEmpty()) { + return ""; + } + return message.parts().stream() + .filter(part -> part instanceof TextPart) + .map(part -> ((TextPart) part).text()) + .findFirst() + .orElse(""); + } + + @Override + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { + if (context.getTask().id().equals("cancel-task-123")) { + agentEmitter.cancel(); + } else if (context.getTask().id().equals("cancel-task-not-supported-123")) { + throw new UnsupportedOperationError(); + } + } + }; + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/GsonObjectMapper_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/GsonObjectMapper_v0_3.java new file mode 100644 index 000000000..bc1c6cfbf --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/GsonObjectMapper_v0_3.java @@ -0,0 +1,39 @@ +package org.a2aproject.sdk.compat03.conversion; + +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperDeserializationContext; +import io.restassured.mapper.ObjectMapperSerializationContext; +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; + +/** + * REST-Assured ObjectMapper adapter for v0.3 JSON serialization. + *

            + * Used to deserialize v0.3 server JSONRPC responses that contain v0.3 types + * (JSONRPCError, JSONRPCErrorResponse, etc.). Complements {@link V10GsonObjectMapper_v0_3} + * which is used for test utility endpoints that expect v1.0 types. + */ +public class GsonObjectMapper_v0_3 implements ObjectMapper { + public static final GsonObjectMapper_v0_3 INSTANCE = new GsonObjectMapper_v0_3(); + + private GsonObjectMapper_v0_3() { + } + + @Override + public Object deserialize(ObjectMapperDeserializationContext context) { + try { + return JsonUtil_v0_3.fromJson(context.getDataToDeserialize().asString(), context.getType()); + } catch (JsonProcessingException_v0_3 ex) { + throw new RuntimeException(ex); + } + } + + @Override + public Object serialize(ObjectMapperSerializationContext context) { + try { + return JsonUtil_v0_3.toJson(context.getObjectToSerialize()); + } catch (JsonProcessingException_v0_3 ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestHttpClient_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestHttpClient_v0_3.java new file mode 100644 index 000000000..f95fb723d --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestHttpClient_v0_3.java @@ -0,0 +1,106 @@ +package org.a2aproject.sdk.compat03.conversion; + +import java.io.IOException; +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; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Alternative; + +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.spec.Task; + +import io.quarkus.arc.profile.IfBuildProfile; + +/** + * Test implementation of A2AHttpClient for push notification testing. + * Duplicated from v1.0 tests/server-common to avoid dependency on v1.0 test infrastructure. + */ +@Dependent +@Alternative +@IfBuildProfile("test") +public class TestHttpClient_v0_3 implements A2AHttpClient { + final List tasks = Collections.synchronizedList(new ArrayList<>()); + volatile CountDownLatch latch; + + @Override + public GetBuilder createGet() { + return null; + } + + @Override + public PostBuilder createPost() { + return new TestPostBuilder(); + } + + @Override + public DeleteBuilder createDelete() { + return null; + } + + class TestPostBuilder implements A2AHttpClient.PostBuilder { + private volatile String body; + @Override + public PostBuilder body(String body) { + this.body = body; + return this; + } + + @Override + public A2AHttpResponse post() throws IOException, InterruptedException { + try { + tasks.add(JsonUtil.fromJson(body, Task.class)); + } catch (JsonProcessingException e) { + throw new IOException("Failed to parse task JSON", e); + } + try { + return new A2AHttpResponse() { + @Override + public int status() { + return 200; + } + + @Override + public boolean success() { + return true; + } + + @Override + public String body() { + return ""; + } + }; + } finally { + latch.countDown(); + } + } + + @Override + public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { + return null; + } + + @Override + public PostBuilder url(String s) { + return this; + } + + @Override + public PostBuilder addHeader(String name, String value) { + return this; + } + + @Override + public PostBuilder addHeaders(Map headers) { + return this; + } + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestUtilsBean_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestUtilsBean_v0_3.java new file mode 100644 index 000000000..6a43e444c --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestUtilsBean_v0_3.java @@ -0,0 +1,118 @@ +package org.a2aproject.sdk.compat03.conversion; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.a2aproject.sdk.server.events.QueueManager; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; +import org.a2aproject.sdk.server.tasks.TaskStore; +import org.a2aproject.sdk.spec.Event; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.Task; + +import io.quarkus.arc.profile.IfBuildProfile; + +/** + * Contains utilities to interact with the server side for the v0.3 compat tests. + * Duplicated from v1.0 tests/server-common to avoid dependency on v1.0 test infrastructure. + * + *

            The intent for this bean is to be exposed via REST. + * + *

            There is a Quarkus implementation in {@code A2ATestRoutes} which shows the contract for how to + * expose it via REST. For other REST frameworks, you will need to provide an implementation that works in a similar + * way to {@code A2ATestRoutes}.

            + */ +@ApplicationScoped +@IfBuildProfile("test") +public class TestUtilsBean_v0_3 { + + @Inject + TaskStore taskStore; + + @Inject + QueueManager queueManager; + + @Inject + PushNotificationConfigStore pushNotificationConfigStore; + + public void saveTask(Task task) { + taskStore.save(task, false); + } + + public Task getTask(String taskId) { + return taskStore.get(taskId); + } + + public void deleteTask(String taskId) { + taskStore.delete(taskId); + } + + public void ensureQueue(String taskId) { + queueManager.createOrTap(taskId); + } + + public void enqueueEvent(String taskId, Event event) { + queueManager.get(taskId).enqueueEvent(event); + } + + public int getChildQueueCount(String taskId) { + return queueManager.getActiveChildQueueCount(taskId); + } + + public void deleteTaskPushNotificationConfig(String taskId, String configId) { + pushNotificationConfigStore.deleteInfo(taskId, configId); + } + + public void saveTaskPushNotificationConfig(String taskId, TaskPushNotificationConfig notificationConfig) { + pushNotificationConfigStore.setInfo(TaskPushNotificationConfig.builder(notificationConfig).taskId(taskId).build()); + } + + /** + * Waits for the EventConsumer polling loop to start for the specified task's queue. + * This ensures the queue is ready to receive and process events. + * + * @param taskId the task ID whose queue poller to wait for + * @throws InterruptedException if interrupted while waiting + */ + public void awaitQueuePollerStart(String taskId) throws InterruptedException { + queueManager.awaitQueuePollerStart(queueManager.get(taskId)); + } + + /** + * Waits for the child queue count to stabilize at the expected value. + *

            + * This method addresses a race condition where EventConsumer polling loops may not have started + * yet when events are emitted. It waits for the child queue count to match the expected value + * for 3 consecutive checks (150ms total), ensuring EventConsumers are actively polling and + * won't miss events. + *

            + * Use this after operations that create child queues (e.g., subscribeToTask, sendMessage) to + * ensure their EventConsumer polling loops have started before the agent emits events. + * + * @param taskId the task ID whose child queues to monitor + * @param expectedCount the expected number of active child queues + * @param timeoutMs maximum time to wait in milliseconds + * @return true if the count stabilized at the expected value, false if timeout occurred + * @throws InterruptedException if interrupted while waiting + */ + public boolean awaitChildQueueCountStable(String taskId, int expectedCount, long timeoutMs) throws InterruptedException { + long endTime = System.currentTimeMillis() + timeoutMs; + int consecutiveMatches = 0; + final int requiredMatches = 3; // Count must match 3 times in a row (150ms) to be considered stable + + while (System.currentTimeMillis() < endTime) { + int count = queueManager.getActiveChildQueueCount(taskId); + if (count == expectedCount) { + consecutiveMatches++; + if (consecutiveMatches >= requiredMatches) { + // Count is stable - all child queues exist and haven't closed + return true; + } + } else { + consecutiveMatches = 0; // Reset if count changes + } + Thread.sleep(50); + } + return false; + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/V10GsonObjectMapper_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/V10GsonObjectMapper_v0_3.java new file mode 100644 index 000000000..04439ab28 --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/V10GsonObjectMapper_v0_3.java @@ -0,0 +1,39 @@ +package org.a2aproject.sdk.compat03.conversion; + +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperDeserializationContext; +import io.restassured.mapper.ObjectMapperSerializationContext; +import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; + +/** + * REST-Assured ObjectMapper adapter for v1.0 JSON serialization. + *

            + * Used by test utilities to communicate with server test endpoints that expect v1.0 JSON format. + * The v0.3 compatibility tests use v0.3 client types, but the server test infrastructure + * (TestUtilsBean endpoints) operates on v1.0 types. + */ +public class V10GsonObjectMapper_v0_3 implements ObjectMapper { + public static final V10GsonObjectMapper_v0_3 INSTANCE = new V10GsonObjectMapper_v0_3(); + + private V10GsonObjectMapper_v0_3() { + } + + @Override + public Object deserialize(ObjectMapperDeserializationContext context) { + try { + return JsonUtil.fromJson(context.getDataToDeserialize().asString(), context.getType()); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public Object serialize(ObjectMapperSerializationContext context) { + try { + return JsonUtil.toJson(context.getObjectToSerialize()); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3_Test.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3_Test.java new file mode 100644 index 000000000..be1695469 --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3_Test.java @@ -0,0 +1,186 @@ +package org.a2aproject.sdk.compat03.conversion.mappers.domain; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.DataPart_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.a2aproject.sdk.spec.Task; +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; + +/** + * Test for {@link TaskMapper_v0_3} to verify conversion of fully populated Task objects + * between v0.3 and v1.0 protocol versions. + */ +class TaskMapper_v0_3_Test { + + @Test + void testFullyPopulatedTaskConversion() { + // Create a fully populated v0.3 Task + OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); + + Message_v0_3 v03Message = new Message_v0_3( + Message_v0_3.Role.USER, + List.of(new TextPart_v0_3("Hello, agent!")), + "msg-001", + "ctx-001", + "task-001", + List.of("ref-task-001"), + Map.of("key", "value"), + List.of("ext1") + ); + + TaskStatus_v0_3 v03Status = new TaskStatus_v0_3( + TaskState_v0_3.WORKING, + v03Message, + now + ); + + Artifact_v0_3 v03Artifact = new Artifact_v0_3( + "artifact-001", + "Test Artifact", + "A test artifact", + List.of( + new TextPart_v0_3("Response text"), + new DataPart_v0_3(Map.of("result", "success")) + ), + Map.of("artifactMeta", "value"), + List.of("artifactExt") + ); + + Message_v0_3 v03HistoryMessage = new Message_v0_3( + Message_v0_3.Role.AGENT, + List.of(new TextPart_v0_3("Agent response")), + "msg-002", + "ctx-001", + "task-001", + null, + null, + null + ); + + Task_v0_3 v03Task = new Task_v0_3( + "task-001", + "ctx-001", + v03Status, + List.of(v03Artifact), + List.of(v03HistoryMessage), + Map.of("taskMeta", "taskValue") + ); + + // Convert v0.3 → v1.0 + Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(v03Task); + + // Verify v1.0 Task + assertNotNull(v10Task); + assertEquals("task-001", v10Task.id()); + assertEquals("ctx-001", v10Task.contextId()); + assertEquals(Map.of("taskMeta", "taskValue"), v10Task.metadata()); + + // Verify status conversion + assertNotNull(v10Task.status()); + assertEquals(org.a2aproject.sdk.spec.TaskState.TASK_STATE_WORKING, v10Task.status().state()); + assertEquals(now, v10Task.status().timestamp()); + + // Verify status message conversion + assertNotNull(v10Task.status().message()); + assertEquals(org.a2aproject.sdk.spec.Message.Role.ROLE_USER, v10Task.status().message().role()); + assertEquals("msg-001", v10Task.status().message().messageId()); + assertEquals("ctx-001", v10Task.status().message().contextId()); + assertEquals("task-001", v10Task.status().message().taskId()); + assertEquals(1, v10Task.status().message().parts().size()); + assertEquals("Hello, agent!", ((org.a2aproject.sdk.spec.TextPart) v10Task.status().message().parts().get(0)).text()); + + // Verify artifacts conversion + assertNotNull(v10Task.artifacts()); + assertEquals(1, v10Task.artifacts().size()); + org.a2aproject.sdk.spec.Artifact v10Artifact = v10Task.artifacts().get(0); + assertEquals("artifact-001", v10Artifact.artifactId()); + assertEquals("Test Artifact", v10Artifact.name()); + assertEquals("A test artifact", v10Artifact.description()); + assertEquals(2, v10Artifact.parts().size()); + assertEquals("Response text", ((org.a2aproject.sdk.spec.TextPart) v10Artifact.parts().get(0)).text()); + + // Verify history conversion + assertNotNull(v10Task.history()); + assertEquals(1, v10Task.history().size()); + org.a2aproject.sdk.spec.Message v10HistoryMsg = v10Task.history().get(0); + assertEquals(org.a2aproject.sdk.spec.Message.Role.ROLE_AGENT, v10HistoryMsg.role()); + assertEquals("msg-002", v10HistoryMsg.messageId()); + assertEquals("Agent response", ((org.a2aproject.sdk.spec.TextPart) v10HistoryMsg.parts().get(0)).text()); + + // Convert v1.0 → v0.3 (round trip) + Task_v0_3 v03TaskRoundTrip = TaskMapper_v0_3.INSTANCE.fromV10(v10Task); + + // Verify round-trip conversion + assertNotNull(v03TaskRoundTrip); + assertEquals("task-001", v03TaskRoundTrip.getId()); + assertEquals("ctx-001", v03TaskRoundTrip.getContextId()); + assertEquals(TaskState_v0_3.WORKING, v03TaskRoundTrip.getStatus().state()); + assertEquals("msg-001", v03TaskRoundTrip.getStatus().message().getMessageId()); + assertEquals(1, v03TaskRoundTrip.getArtifacts().size()); + assertEquals("artifact-001", v03TaskRoundTrip.getArtifacts().get(0).artifactId()); + assertEquals(1, v03TaskRoundTrip.getHistory().size()); + assertEquals("msg-002", v03TaskRoundTrip.getHistory().get(0).getMessageId()); + } + + @Test + void testMinimalTaskConversion() { + // Test with minimal Task (no artifacts, no history, no metadata) + OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); + + TaskStatus_v0_3 v03Status = new TaskStatus_v0_3( + TaskState_v0_3.SUBMITTED + ); + + Task_v0_3 v03Task = new Task_v0_3( + "task-minimal", + "ctx-minimal", + v03Status, + null, + null, + null + ); + + // Convert v0.3 → v1.0 + Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(v03Task); + + // Verify minimal conversion + assertNotNull(v10Task); + assertEquals("task-minimal", v10Task.id()); + assertEquals("ctx-minimal", v10Task.contextId()); + assertEquals(org.a2aproject.sdk.spec.TaskState.TASK_STATE_SUBMITTED, v10Task.status().state()); + assertNull(v10Task.status().message()); + + // v1.0 Task compact constructor converts null to empty list + assertNotNull(v10Task.artifacts()); + assertEquals(0, v10Task.artifacts().size()); + assertNotNull(v10Task.history()); + assertEquals(0, v10Task.history().size()); + assertNull(v10Task.metadata()); + + // Round trip + Task_v0_3 v03TaskRoundTrip = TaskMapper_v0_3.INSTANCE.fromV10(v10Task); + assertNotNull(v03TaskRoundTrip); + assertEquals("task-minimal", v03TaskRoundTrip.getId()); + assertEquals(TaskState_v0_3.SUBMITTED, v03TaskRoundTrip.getStatus().state()); + } + + @Test + void testNullTaskConversion() { + // Null safety + assertNull(TaskMapper_v0_3.INSTANCE.toV10(null)); + assertNull(TaskMapper_v0_3.INSTANCE.fromV10(null)); + } +} diff --git a/compat-0.3/server-conversion/src/test/resources/META-INF/beans.xml b/compat-0.3/server-conversion/src/test/resources/META-INF/beans.xml new file mode 100644 index 000000000..b708636eb --- /dev/null +++ b/compat-0.3/server-conversion/src/test/resources/META-INF/beans.xml @@ -0,0 +1,7 @@ + + + diff --git a/compat-0.3/spec-grpc/pom.xml b/compat-0.3/spec-grpc/pom.xml new file mode 100644 index 000000000..6021f6820 --- /dev/null +++ b/compat-0.3/spec-grpc/pom.xml @@ -0,0 +1,147 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + .. + + a2a-java-sdk-compat-0.3-spec-grpc + + jar + + Java SDK A2A Compat 0.3 Spec: gRPC + Java SDK for the Agent2Agent Protocol (A2A) - Spec: gRPC + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + com.google.protobuf + protobuf-java + + + io.grpc + grpc-protobuf + provided + + + io.grpc + grpc-stub + provided + + + jakarta.enterprise + jakarta.enterprise.cdi-api + + + jakarta.inject + jakarta.inject-api + + + com.google.api.grpc + proto-google-common-protos + + + + + javax.annotation + javax.annotation-api + provided + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + + + + + proto-compile + + + + + org.apache.maven.plugins + maven-clean-plugin + ${maven-clean-plugin.version} + + + remove-generated-files + initialize + + clean + + + true + + + ${project.basedir}/src/main/java/io/a2a/grpc + false + + *.java + + + + + + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + ${protobuf-maven-plugin.version} + + com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier} + grpc-java + io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} + src/main/java + false + + + + + compile + compile-custom + + + + + + + + + + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/A2A.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/A2A.java new file mode 100644 index 000000000..cbed7cc2c --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/A2A.java @@ -0,0 +1,827 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public final class A2A extends com.google.protobuf.GeneratedFile { + private A2A() {} + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "A2A"); + } + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_SendMessageConfiguration_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_Task_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_Task_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_TaskStatus_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_TaskStatus_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_Part_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_Part_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_FilePart_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_FilePart_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_DataPart_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_DataPart_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_Message_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_Message_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_Artifact_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_Artifact_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_PushNotificationConfig_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AuthenticationInfo_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AgentInterface_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AgentInterface_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AgentCard_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AgentCard_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AgentProvider_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AgentProvider_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AgentCapabilities_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AgentExtension_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AgentExtension_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AgentSkill_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AgentSkill_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AgentCardSignature_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_StringList_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_StringList_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_Security_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_Security_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_Security_SchemesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_Security_SchemesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_SecurityScheme_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_SecurityScheme_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_APIKeySecurityScheme_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_OAuthFlows_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_OAuthFlows_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_SendMessageRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_GetTaskRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_CancelTaskRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_TaskSubscriptionRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_TaskSubscriptionRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_GetAgentCardRequest_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_GetAgentCardRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_SendMessageResponse_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_StreamResponse_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_StreamResponse_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\ta2a.proto\022\006a2a.v1\032\034google/api/annotati" + + "ons.proto\032\027google/api/client.proto\032\037goog" + + "le/api/field_behavior.proto\032\033google/prot" + + "obuf/empty.proto\032\034google/protobuf/struct" + + ".proto\032\037google/protobuf/timestamp.proto\"" + + "\236\001\n\030SendMessageConfiguration\022\035\n\025accepted" + + "_output_modes\030\001 \003(\t\0229\n\021push_notification" + + "\030\002 \001(\0132\036.a2a.v1.PushNotificationConfig\022\026" + + "\n\016history_length\030\003 \001(\005\022\020\n\010blocking\030\004 \001(\010" + + "\"\274\001\n\004Task\022\n\n\002id\030\001 \001(\t\022\022\n\ncontext_id\030\002 \001(" + + "\t\022\"\n\006status\030\003 \001(\0132\022.a2a.v1.TaskStatus\022#\n" + + "\tartifacts\030\004 \003(\0132\020.a2a.v1.Artifact\022 \n\007hi" + + "story\030\005 \003(\0132\017.a2a.v1.Message\022)\n\010metadata" + + "\030\006 \001(\0132\027.google.protobuf.Struct\"\207\001\n\nTask" + + "Status\022 \n\005state\030\001 \001(\0162\021.a2a.v1.TaskState" + + "\022(\n\006update\030\002 \001(\0132\017.a2a.v1.MessageR\007messa" + + "ge\022-\n\ttimestamp\030\003 \001(\0132\032.google.protobuf." + + "Timestamp\"b\n\004Part\022\016\n\004text\030\001 \001(\tH\000\022 \n\004fil" + + "e\030\002 \001(\0132\020.a2a.v1.FilePartH\000\022 \n\004data\030\003 \001(" + + "\0132\020.a2a.v1.DataPartH\000B\006\n\004part\"Y\n\010FilePar" + + "t\022\027\n\rfile_with_uri\030\001 \001(\tH\000\022\031\n\017file_with_" + + "bytes\030\002 \001(\014H\000\022\021\n\tmime_type\030\003 \001(\tB\006\n\004file" + + "\"1\n\010DataPart\022%\n\004data\030\001 \001(\0132\027.google.prot" + + "obuf.Struct\"\274\001\n\007Message\022\022\n\nmessage_id\030\001 " + + "\001(\t\022\022\n\ncontext_id\030\002 \001(\t\022\017\n\007task_id\030\003 \001(\t" + + "\022\032\n\004role\030\004 \001(\0162\014.a2a.v1.Role\022\035\n\007content\030" + + "\005 \003(\0132\014.a2a.v1.Part\022)\n\010metadata\030\006 \001(\0132\027." + + "google.protobuf.Struct\022\022\n\nextensions\030\007 \003" + + "(\t\"\236\001\n\010Artifact\022\023\n\013artifact_id\030\001 \001(\t\022\014\n\004" + + "name\030\003 \001(\t\022\023\n\013description\030\004 \001(\t\022\033\n\005parts" + + "\030\005 \003(\0132\014.a2a.v1.Part\022)\n\010metadata\030\006 \001(\0132\027" + + ".google.protobuf.Struct\022\022\n\nextensions\030\007 " + + "\003(\t\"\232\001\n\025TaskStatusUpdateEvent\022\017\n\007task_id" + + "\030\001 \001(\t\022\022\n\ncontext_id\030\002 \001(\t\022\"\n\006status\030\003 \001" + + "(\0132\022.a2a.v1.TaskStatus\022\r\n\005final\030\004 \001(\010\022)\n" + + "\010metadata\030\005 \001(\0132\027.google.protobuf.Struct" + + "\"\261\001\n\027TaskArtifactUpdateEvent\022\017\n\007task_id\030" + + "\001 \001(\t\022\022\n\ncontext_id\030\002 \001(\t\022\"\n\010artifact\030\003 " + + "\001(\0132\020.a2a.v1.Artifact\022\016\n\006append\030\004 \001(\010\022\022\n" + + "\nlast_chunk\030\005 \001(\010\022)\n\010metadata\030\006 \001(\0132\027.go" + + "ogle.protobuf.Struct\"t\n\026PushNotification" + + "Config\022\n\n\002id\030\001 \001(\t\022\013\n\003url\030\002 \001(\t\022\r\n\005token" + + "\030\003 \001(\t\0222\n\016authentication\030\004 \001(\0132\032.a2a.v1." + + "AuthenticationInfo\":\n\022AuthenticationInfo" + + "\022\017\n\007schemes\030\001 \003(\t\022\023\n\013credentials\030\002 \001(\t\"0" + + "\n\016AgentInterface\022\013\n\003url\030\001 \001(\t\022\021\n\ttranspo" + + "rt\030\002 \001(\t\"\242\005\n\tAgentCard\022\030\n\020protocol_versi" + + "on\030\020 \001(\t\022\014\n\004name\030\001 \001(\t\022\023\n\013description\030\002 " + + "\001(\t\022\013\n\003url\030\003 \001(\t\022\033\n\023preferred_transport\030" + + "\016 \001(\t\0225\n\025additional_interfaces\030\017 \003(\0132\026.a" + + "2a.v1.AgentInterface\022\'\n\010provider\030\004 \001(\0132\025" + + ".a2a.v1.AgentProvider\022\017\n\007version\030\005 \001(\t\022\031" + + "\n\021documentation_url\030\006 \001(\t\022/\n\014capabilitie" + + "s\030\007 \001(\0132\031.a2a.v1.AgentCapabilities\022@\n\020se" + + "curity_schemes\030\010 \003(\0132&.a2a.v1.AgentCard." + + "SecuritySchemesEntry\022\"\n\010security\030\t \003(\0132\020" + + ".a2a.v1.Security\022\033\n\023default_input_modes\030" + + "\n \003(\t\022\034\n\024default_output_modes\030\013 \003(\t\022\"\n\006s" + + "kills\030\014 \003(\0132\022.a2a.v1.AgentSkill\022,\n$suppo" + + "rts_authenticated_extended_card\030\r \001(\010\022.\n" + + "\nsignatures\030\021 \003(\0132\032.a2a.v1.AgentCardSign" + + "ature\032N\n\024SecuritySchemesEntry\022\013\n\003key\030\001 \001" + + "(\t\022%\n\005value\030\002 \001(\0132\026.a2a.v1.SecuritySchem" + + "e:\0028\001\"2\n\rAgentProvider\022\013\n\003url\030\001 \001(\t\022\024\n\014o" + + "rganization\030\002 \001(\t\"n\n\021AgentCapabilities\022\021" + + "\n\tstreaming\030\001 \001(\010\022\032\n\022push_notifications\030" + + "\002 \001(\010\022*\n\nextensions\030\003 \003(\0132\026.a2a.v1.Agent" + + "Extension\"m\n\016AgentExtension\022\013\n\003uri\030\001 \001(\t" + + "\022\023\n\013description\030\002 \001(\t\022\020\n\010required\030\003 \001(\010\022" + + "\'\n\006params\030\004 \001(\0132\027.google.protobuf.Struct" + + "\"\252\001\n\nAgentSkill\022\n\n\002id\030\001 \001(\t\022\014\n\004name\030\002 \001(" + + "\t\022\023\n\013description\030\003 \001(\t\022\014\n\004tags\030\004 \003(\t\022\020\n\010" + + "examples\030\005 \003(\t\022\023\n\013input_modes\030\006 \003(\t\022\024\n\014o" + + "utput_modes\030\007 \003(\t\022\"\n\010security\030\010 \003(\0132\020.a2" + + "a.v1.Security\"m\n\022AgentCardSignature\022\026\n\tp" + + "rotected\030\001 \001(\tB\003\340A\002\022\026\n\tsignature\030\002 \001(\tB\003" + + "\340A\002\022\'\n\006header\030\003 \001(\0132\027.google.protobuf.St" + + "ruct\"l\n\032TaskPushNotificationConfig\022\014\n\004na" + + "me\030\001 \001(\t\022@\n\030push_notification_config\030\002 \001" + + "(\0132\036.a2a.v1.PushNotificationConfig\"\032\n\nSt" + + "ringList\022\014\n\004list\030\001 \003(\t\"~\n\010Security\022.\n\007sc" + + "hemes\030\001 \003(\0132\035.a2a.v1.Security.SchemesEnt" + + "ry\032B\n\014SchemesEntry\022\013\n\003key\030\001 \001(\t\022!\n\005value" + + "\030\002 \001(\0132\022.a2a.v1.StringList:\0028\001\"\361\002\n\016Secur" + + "ityScheme\022?\n\027api_key_security_scheme\030\001 \001" + + "(\0132\034.a2a.v1.APIKeySecuritySchemeH\000\022C\n\031ht" + + "tp_auth_security_scheme\030\002 \001(\0132\036.a2a.v1.H" + + "TTPAuthSecuritySchemeH\000\022>\n\026oauth2_securi" + + "ty_scheme\030\003 \001(\0132\034.a2a.v1.OAuth2SecurityS" + + "chemeH\000\022N\n\037open_id_connect_security_sche" + + "me\030\004 \001(\0132#.a2a.v1.OpenIdConnectSecurityS" + + "chemeH\000\022?\n\024mtls_security_scheme\030\005 \001(\0132\037." + + "a2a.v1.MutualTlsSecuritySchemeH\000B\010\n\006sche" + + "me\"K\n\024APIKeySecurityScheme\022\023\n\013descriptio" + + "n\030\001 \001(\t\022\020\n\010location\030\002 \001(\t\022\014\n\004name\030\003 \001(\t\"" + + "T\n\026HTTPAuthSecurityScheme\022\023\n\013description" + + "\030\001 \001(\t\022\016\n\006scheme\030\002 \001(\t\022\025\n\rbearer_format\030" + + "\003 \001(\t\"k\n\024OAuth2SecurityScheme\022\023\n\013descrip" + + "tion\030\001 \001(\t\022!\n\005flows\030\002 \001(\0132\022.a2a.v1.OAuth" + + "Flows\022\033\n\023oauth2_metadata_url\030\003 \001(\t\"O\n\033Op" + + "enIdConnectSecurityScheme\022\023\n\013description" + + "\030\001 \001(\t\022\033\n\023open_id_connect_url\030\002 \001(\t\".\n\027M" + + "utualTlsSecurityScheme\022\023\n\013description\030\001 " + + "\001(\t\"\366\001\n\nOAuthFlows\022@\n\022authorization_code" + + "\030\001 \001(\0132\".a2a.v1.AuthorizationCodeOAuthFl" + + "owH\000\022@\n\022client_credentials\030\002 \001(\0132\".a2a.v" + + "1.ClientCredentialsOAuthFlowH\000\022-\n\010implic" + + "it\030\003 \001(\0132\031.a2a.v1.ImplicitOAuthFlowH\000\022-\n" + + "\010password\030\004 \001(\0132\031.a2a.v1.PasswordOAuthFl" + + "owH\000B\006\n\004flow\"\316\001\n\032AuthorizationCodeOAuthF" + + "low\022\031\n\021authorization_url\030\001 \001(\t\022\021\n\ttoken_" + + "url\030\002 \001(\t\022\023\n\013refresh_url\030\003 \001(\t\022>\n\006scopes" + + "\030\004 \003(\0132..a2a.v1.AuthorizationCodeOAuthFl" + + "ow.ScopesEntry\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001" + + "(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\263\001\n\032ClientCredenti" + + "alsOAuthFlow\022\021\n\ttoken_url\030\001 \001(\t\022\023\n\013refre" + + "sh_url\030\002 \001(\t\022>\n\006scopes\030\003 \003(\0132..a2a.v1.Cl" + + "ientCredentialsOAuthFlow.ScopesEntry\032-\n\013" + + "ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:" + + "\0028\001\"\251\001\n\021ImplicitOAuthFlow\022\031\n\021authorizati" + + "on_url\030\001 \001(\t\022\023\n\013refresh_url\030\002 \001(\t\0225\n\006sco" + + "pes\030\003 \003(\0132%.a2a.v1.ImplicitOAuthFlow.Sco" + + "pesEntry\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005" + + "value\030\002 \001(\t:\0028\001\"\241\001\n\021PasswordOAuthFlow\022\021\n" + + "\ttoken_url\030\001 \001(\t\022\023\n\013refresh_url\030\002 \001(\t\0225\n" + + "\006scopes\030\003 \003(\0132%.a2a.v1.PasswordOAuthFlow" + + ".ScopesEntry\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(\t" + + "\022\r\n\005value\030\002 \001(\t:\0028\001\"\250\001\n\022SendMessageReque" + + "st\022.\n\007request\030\001 \001(\0132\017.a2a.v1.MessageB\003\340A" + + "\002R\007message\0227\n\rconfiguration\030\002 \001(\0132 .a2a." + + "v1.SendMessageConfiguration\022)\n\010metadata\030" + + "\003 \001(\0132\027.google.protobuf.Struct\";\n\016GetTas" + + "kRequest\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\026\n\016history_l" + + "ength\030\002 \001(\005\"!\n\021CancelTaskRequest\022\014\n\004name" + + "\030\001 \001(\t\"4\n$GetTaskPushNotificationConfigR" + + "equest\022\014\n\004name\030\001 \001(\t\"7\n\'DeleteTaskPushNo" + + "tificationConfigRequest\022\014\n\004name\030\001 \001(\t\"\217\001" + + "\n\'CreateTaskPushNotificationConfigReques" + + "t\022\023\n\006parent\030\001 \001(\tB\003\340A\002\022\026\n\tconfig_id\030\002 \001(" + + "\tB\003\340A\002\0227\n\006config\030\003 \001(\0132\".a2a.v1.TaskPush" + + "NotificationConfigB\003\340A\002\"\'\n\027TaskSubscript" + + "ionRequest\022\014\n\004name\030\001 \001(\t\"^\n%ListTaskPush" + + "NotificationConfigRequest\022\016\n\006parent\030\001 \001(" + + "\t\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t" + + "\"\025\n\023GetAgentCardRequest\"g\n\023SendMessageRe" + + "sponse\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022\'\n\003" + + "msg\030\002 \001(\0132\017.a2a.v1.MessageH\000R\007messageB\t\n" + + "\007payload\"\326\001\n\016StreamResponse\022\034\n\004task\030\001 \001(" + + "\0132\014.a2a.v1.TaskH\000\022\'\n\003msg\030\002 \001(\0132\017.a2a.v1." + + "MessageH\000R\007message\0226\n\rstatus_update\030\003 \001(" + + "\0132\035.a2a.v1.TaskStatusUpdateEventH\000\022:\n\017ar" + + "tifact_update\030\004 \001(\0132\037.a2a.v1.TaskArtifac" + + "tUpdateEventH\000B\t\n\007payload\"v\n&ListTaskPus" + + "hNotificationConfigResponse\0223\n\007configs\030\001" + + " \003(\0132\".a2a.v1.TaskPushNotificationConfig" + + "\022\027\n\017next_page_token\030\002 \001(\t*\372\001\n\tTaskState\022" + + "\032\n\026TASK_STATE_UNSPECIFIED\020\000\022\030\n\024TASK_STAT" + + "E_SUBMITTED\020\001\022\026\n\022TASK_STATE_WORKING\020\002\022\030\n" + + "\024TASK_STATE_COMPLETED\020\003\022\025\n\021TASK_STATE_FA" + + "ILED\020\004\022\030\n\024TASK_STATE_CANCELLED\020\005\022\035\n\031TASK" + + "_STATE_INPUT_REQUIRED\020\006\022\027\n\023TASK_STATE_RE" + + "JECTED\020\007\022\034\n\030TASK_STATE_AUTH_REQUIRED\020\010*;" + + "\n\004Role\022\024\n\020ROLE_UNSPECIFIED\020\000\022\r\n\tROLE_USE" + + "R\020\001\022\016\n\nROLE_AGENT\020\0022\272\n\n\nA2AService\022c\n\013Se" + + "ndMessage\022\032.a2a.v1.SendMessageRequest\032\033." + + "a2a.v1.SendMessageResponse\"\033\202\323\344\223\002\025\"\020/v1/" + + "message:send:\001*\022k\n\024SendStreamingMessage\022" + + "\032.a2a.v1.SendMessageRequest\032\026.a2a.v1.Str" + + "eamResponse\"\035\202\323\344\223\002\027\"\022/v1/message:stream:" + + "\001*0\001\022R\n\007GetTask\022\026.a2a.v1.GetTaskRequest\032" + + "\014.a2a.v1.Task\"!\332A\004name\202\323\344\223\002\024\022\022/v1/{name=" + + "tasks/*}\022[\n\nCancelTask\022\031.a2a.v1.CancelTa" + + "skRequest\032\014.a2a.v1.Task\"$\202\323\344\223\002\036\"\031/v1/{na" + + "me=tasks/*}:cancel:\001*\022s\n\020TaskSubscriptio" + + "n\022\037.a2a.v1.TaskSubscriptionRequest\032\026.a2a" + + ".v1.StreamResponse\"$\202\323\344\223\002\036\022\034/v1/{name=ta" + + "sks/*}:subscribe0\001\022\304\001\n CreateTaskPushNot" + + "ificationConfig\022/.a2a.v1.CreateTaskPushN" + + "otificationConfigRequest\032\".a2a.v1.TaskPu" + + "shNotificationConfig\"K\332A\rparent,config\202\323" + + "\344\223\0025\"+/v1/{parent=task/*/pushNotificatio" + + "nConfigs}:\006config\022\256\001\n\035GetTaskPushNotific" + + "ationConfig\022,.a2a.v1.GetTaskPushNotifica" + + "tionConfigRequest\032\".a2a.v1.TaskPushNotif" + + "icationConfig\";\332A\004name\202\323\344\223\002.\022,/v1/{name=" + + "tasks/*/pushNotificationConfigs/*}\022\276\001\n\036L" + + "istTaskPushNotificationConfig\022-.a2a.v1.L" + + "istTaskPushNotificationConfigRequest\032..a" + + "2a.v1.ListTaskPushNotificationConfigResp" + + "onse\"=\332A\006parent\202\323\344\223\002.\022,/v1/{parent=tasks" + + "/*}/pushNotificationConfigs\022P\n\014GetAgentC" + + "ard\022\033.a2a.v1.GetAgentCardRequest\032\021.a2a.v" + + "1.AgentCard\"\020\202\323\344\223\002\n\022\010/v1/card\022\250\001\n Delete" + + "TaskPushNotificationConfig\022/.a2a.v1.Dele" + + "teTaskPushNotificationConfigRequest\032\026.go" + + "ogle.protobuf.Empty\";\332A\004name\202\323\344\223\002.*,/v1/" + + "{name=tasks/*/pushNotificationConfigs/*}" + + "BL\n org.a2aproject.sdk.compat03.grpcB\003A2" + + "AP\001Z\030google.golang.org/a2a/v1\252\002\006A2a.V1b\006" + + "proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + com.google.api.AnnotationsProto.getDescriptor(), + com.google.api.ClientProto.getDescriptor(), + com.google.api.FieldBehaviorProto.getDescriptor(), + com.google.protobuf.EmptyProto.getDescriptor(), + com.google.protobuf.StructProto.getDescriptor(), + com.google.protobuf.TimestampProto.getDescriptor(), + }); + internal_static_a2a_v1_SendMessageConfiguration_descriptor = + getDescriptor().getMessageType(0); + internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_SendMessageConfiguration_descriptor, + new java.lang.String[] { "AcceptedOutputModes", "PushNotification", "HistoryLength", "Blocking", }); + internal_static_a2a_v1_Task_descriptor = + getDescriptor().getMessageType(1); + internal_static_a2a_v1_Task_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_Task_descriptor, + new java.lang.String[] { "Id", "ContextId", "Status", "Artifacts", "History", "Metadata", }); + internal_static_a2a_v1_TaskStatus_descriptor = + getDescriptor().getMessageType(2); + internal_static_a2a_v1_TaskStatus_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_TaskStatus_descriptor, + new java.lang.String[] { "State", "Update", "Timestamp", }); + internal_static_a2a_v1_Part_descriptor = + getDescriptor().getMessageType(3); + internal_static_a2a_v1_Part_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_Part_descriptor, + new java.lang.String[] { "Text", "File", "Data", "Part", }); + internal_static_a2a_v1_FilePart_descriptor = + getDescriptor().getMessageType(4); + internal_static_a2a_v1_FilePart_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_FilePart_descriptor, + new java.lang.String[] { "FileWithUri", "FileWithBytes", "MimeType", "File", }); + internal_static_a2a_v1_DataPart_descriptor = + getDescriptor().getMessageType(5); + internal_static_a2a_v1_DataPart_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_DataPart_descriptor, + new java.lang.String[] { "Data", }); + internal_static_a2a_v1_Message_descriptor = + getDescriptor().getMessageType(6); + internal_static_a2a_v1_Message_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_Message_descriptor, + new java.lang.String[] { "MessageId", "ContextId", "TaskId", "Role", "Content", "Metadata", "Extensions", }); + internal_static_a2a_v1_Artifact_descriptor = + getDescriptor().getMessageType(7); + internal_static_a2a_v1_Artifact_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_Artifact_descriptor, + new java.lang.String[] { "ArtifactId", "Name", "Description", "Parts", "Metadata", "Extensions", }); + internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor = + getDescriptor().getMessageType(8); + internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor, + new java.lang.String[] { "TaskId", "ContextId", "Status", "Final", "Metadata", }); + internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor = + getDescriptor().getMessageType(9); + internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor, + new java.lang.String[] { "TaskId", "ContextId", "Artifact", "Append", "LastChunk", "Metadata", }); + internal_static_a2a_v1_PushNotificationConfig_descriptor = + getDescriptor().getMessageType(10); + internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_PushNotificationConfig_descriptor, + new java.lang.String[] { "Id", "Url", "Token", "Authentication", }); + internal_static_a2a_v1_AuthenticationInfo_descriptor = + getDescriptor().getMessageType(11); + internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AuthenticationInfo_descriptor, + new java.lang.String[] { "Schemes", "Credentials", }); + internal_static_a2a_v1_AgentInterface_descriptor = + getDescriptor().getMessageType(12); + internal_static_a2a_v1_AgentInterface_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AgentInterface_descriptor, + new java.lang.String[] { "Url", "Transport", }); + internal_static_a2a_v1_AgentCard_descriptor = + getDescriptor().getMessageType(13); + internal_static_a2a_v1_AgentCard_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AgentCard_descriptor, + new java.lang.String[] { "ProtocolVersion", "Name", "Description", "Url", "PreferredTransport", "AdditionalInterfaces", "Provider", "Version", "DocumentationUrl", "Capabilities", "SecuritySchemes", "Security", "DefaultInputModes", "DefaultOutputModes", "Skills", "SupportsAuthenticatedExtendedCard", "Signatures", }); + internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor = + internal_static_a2a_v1_AgentCard_descriptor.getNestedType(0); + internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + internal_static_a2a_v1_AgentProvider_descriptor = + getDescriptor().getMessageType(14); + internal_static_a2a_v1_AgentProvider_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AgentProvider_descriptor, + new java.lang.String[] { "Url", "Organization", }); + internal_static_a2a_v1_AgentCapabilities_descriptor = + getDescriptor().getMessageType(15); + internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AgentCapabilities_descriptor, + new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", }); + internal_static_a2a_v1_AgentExtension_descriptor = + getDescriptor().getMessageType(16); + internal_static_a2a_v1_AgentExtension_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AgentExtension_descriptor, + new java.lang.String[] { "Uri", "Description", "Required", "Params", }); + internal_static_a2a_v1_AgentSkill_descriptor = + getDescriptor().getMessageType(17); + internal_static_a2a_v1_AgentSkill_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AgentSkill_descriptor, + new java.lang.String[] { "Id", "Name", "Description", "Tags", "Examples", "InputModes", "OutputModes", "Security", }); + internal_static_a2a_v1_AgentCardSignature_descriptor = + getDescriptor().getMessageType(18); + internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AgentCardSignature_descriptor, + new java.lang.String[] { "Protected", "Signature", "Header", }); + internal_static_a2a_v1_TaskPushNotificationConfig_descriptor = + getDescriptor().getMessageType(19); + internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_TaskPushNotificationConfig_descriptor, + new java.lang.String[] { "Name", "PushNotificationConfig", }); + internal_static_a2a_v1_StringList_descriptor = + getDescriptor().getMessageType(20); + internal_static_a2a_v1_StringList_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_StringList_descriptor, + new java.lang.String[] { "List", }); + internal_static_a2a_v1_Security_descriptor = + getDescriptor().getMessageType(21); + internal_static_a2a_v1_Security_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_Security_descriptor, + new java.lang.String[] { "Schemes", }); + internal_static_a2a_v1_Security_SchemesEntry_descriptor = + internal_static_a2a_v1_Security_descriptor.getNestedType(0); + internal_static_a2a_v1_Security_SchemesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_Security_SchemesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + internal_static_a2a_v1_SecurityScheme_descriptor = + getDescriptor().getMessageType(22); + internal_static_a2a_v1_SecurityScheme_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_SecurityScheme_descriptor, + new java.lang.String[] { "ApiKeySecurityScheme", "HttpAuthSecurityScheme", "Oauth2SecurityScheme", "OpenIdConnectSecurityScheme", "MtlsSecurityScheme", "Scheme", }); + internal_static_a2a_v1_APIKeySecurityScheme_descriptor = + getDescriptor().getMessageType(23); + internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_APIKeySecurityScheme_descriptor, + new java.lang.String[] { "Description", "Location", "Name", }); + internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor = + getDescriptor().getMessageType(24); + internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor, + new java.lang.String[] { "Description", "Scheme", "BearerFormat", }); + internal_static_a2a_v1_OAuth2SecurityScheme_descriptor = + getDescriptor().getMessageType(25); + internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_OAuth2SecurityScheme_descriptor, + new java.lang.String[] { "Description", "Flows", "Oauth2MetadataUrl", }); + internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor = + getDescriptor().getMessageType(26); + internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor, + new java.lang.String[] { "Description", "OpenIdConnectUrl", }); + internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor = + getDescriptor().getMessageType(27); + internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor, + new java.lang.String[] { "Description", }); + internal_static_a2a_v1_OAuthFlows_descriptor = + getDescriptor().getMessageType(28); + internal_static_a2a_v1_OAuthFlows_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_OAuthFlows_descriptor, + new java.lang.String[] { "AuthorizationCode", "ClientCredentials", "Implicit", "Password", "Flow", }); + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor = + getDescriptor().getMessageType(29); + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor, + new java.lang.String[] { "AuthorizationUrl", "TokenUrl", "RefreshUrl", "Scopes", }); + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor = + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor.getNestedType(0); + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor = + getDescriptor().getMessageType(30); + internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor, + new java.lang.String[] { "TokenUrl", "RefreshUrl", "Scopes", }); + internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor = + internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor.getNestedType(0); + internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + internal_static_a2a_v1_ImplicitOAuthFlow_descriptor = + getDescriptor().getMessageType(31); + internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_ImplicitOAuthFlow_descriptor, + new java.lang.String[] { "AuthorizationUrl", "RefreshUrl", "Scopes", }); + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor = + internal_static_a2a_v1_ImplicitOAuthFlow_descriptor.getNestedType(0); + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + internal_static_a2a_v1_PasswordOAuthFlow_descriptor = + getDescriptor().getMessageType(32); + internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_PasswordOAuthFlow_descriptor, + new java.lang.String[] { "TokenUrl", "RefreshUrl", "Scopes", }); + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor = + internal_static_a2a_v1_PasswordOAuthFlow_descriptor.getNestedType(0); + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + internal_static_a2a_v1_SendMessageRequest_descriptor = + getDescriptor().getMessageType(33); + internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_SendMessageRequest_descriptor, + new java.lang.String[] { "Request", "Configuration", "Metadata", }); + internal_static_a2a_v1_GetTaskRequest_descriptor = + getDescriptor().getMessageType(34); + internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_GetTaskRequest_descriptor, + new java.lang.String[] { "Name", "HistoryLength", }); + internal_static_a2a_v1_CancelTaskRequest_descriptor = + getDescriptor().getMessageType(35); + internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_CancelTaskRequest_descriptor, + new java.lang.String[] { "Name", }); + internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor = + getDescriptor().getMessageType(36); + internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor, + new java.lang.String[] { "Name", }); + internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor = + getDescriptor().getMessageType(37); + internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor, + new java.lang.String[] { "Name", }); + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor = + getDescriptor().getMessageType(38); + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor, + new java.lang.String[] { "Parent", "ConfigId", "Config", }); + internal_static_a2a_v1_TaskSubscriptionRequest_descriptor = + getDescriptor().getMessageType(39); + internal_static_a2a_v1_TaskSubscriptionRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_TaskSubscriptionRequest_descriptor, + new java.lang.String[] { "Name", }); + internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor = + getDescriptor().getMessageType(40); + internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor, + new java.lang.String[] { "Parent", "PageSize", "PageToken", }); + internal_static_a2a_v1_GetAgentCardRequest_descriptor = + getDescriptor().getMessageType(41); + internal_static_a2a_v1_GetAgentCardRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_GetAgentCardRequest_descriptor, + new java.lang.String[] { }); + internal_static_a2a_v1_SendMessageResponse_descriptor = + getDescriptor().getMessageType(42); + internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_SendMessageResponse_descriptor, + new java.lang.String[] { "Task", "Msg", "Payload", }); + internal_static_a2a_v1_StreamResponse_descriptor = + getDescriptor().getMessageType(43); + internal_static_a2a_v1_StreamResponse_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_StreamResponse_descriptor, + new java.lang.String[] { "Task", "Msg", "StatusUpdate", "ArtifactUpdate", "Payload", }); + internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor = + getDescriptor().getMessageType(44); + internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor, + new java.lang.String[] { "Configs", "NextPageToken", }); + descriptor.resolveAllFeaturesImmutable(); + com.google.api.AnnotationsProto.getDescriptor(); + com.google.api.ClientProto.getDescriptor(); + com.google.api.FieldBehaviorProto.getDescriptor(); + com.google.protobuf.EmptyProto.getDescriptor(); + com.google.protobuf.StructProto.getDescriptor(); + com.google.protobuf.TimestampProto.getDescriptor(); + com.google.protobuf.ExtensionRegistry registry = + com.google.protobuf.ExtensionRegistry.newInstance(); + registry.add(com.google.api.FieldBehaviorProto.fieldBehavior); + registry.add(com.google.api.AnnotationsProto.http); + registry.add(com.google.api.ClientProto.methodSignature); + com.google.protobuf.Descriptors.FileDescriptor + .internalUpdateFileDescriptor(descriptor, registry); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/A2AServiceGrpc.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/A2AServiceGrpc.java new file mode 100644 index 000000000..f169371e2 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/A2AServiceGrpc.java @@ -0,0 +1,1323 @@ +package org.a2aproject.sdk.compat03.grpc; + +import static io.grpc.MethodDescriptor.generateFullMethodName; + +/** + *

            + * A2AService defines the gRPC version of the A2A protocol. This has a slightly
            + * different shape than the JSONRPC version to better conform to AIP-127,
            + * where appropriate. The nouns are AgentCard, Message, Task and
            + * TaskPushNotificationConfig.
            + * - Messages are not a standard resource so there is no get/delete/update/list
            + *   interface, only a send and stream custom methods.
            + * - Tasks have a get interface and custom cancel and subscribe methods.
            + * - TaskPushNotificationConfig are a resource whose parent is a task.
            + *   They have get, list and create methods.
            + * - AgentCard is a static resource with only a get method.
            + * fields are not present as they don't comply with AIP rules, and the
            + * optional history_length on the get task method is not present as it also
            + * violates AIP-127 and AIP-131.
            + * 
            + */ +@io.grpc.stub.annotations.GrpcGenerated +public final class A2AServiceGrpc { + + private A2AServiceGrpc() {} + + public static final java.lang.String SERVICE_NAME = "a2a.v1.A2AService"; + + // Static method descriptors that strictly reflect the proto. + private static volatile io.grpc.MethodDescriptor getSendMessageMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "SendMessage", + requestType = org.a2aproject.sdk.compat03.grpc.SendMessageRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.SendMessageResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getSendMessageMethod() { + io.grpc.MethodDescriptor getSendMessageMethod; + if ((getSendMessageMethod = A2AServiceGrpc.getSendMessageMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getSendMessageMethod = A2AServiceGrpc.getSendMessageMethod) == null) { + A2AServiceGrpc.getSendMessageMethod = getSendMessageMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SendMessage")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.SendMessageResponse.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SendMessage")) + .build(); + } + } + } + return getSendMessageMethod; + } + + private static volatile io.grpc.MethodDescriptor getSendStreamingMessageMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "SendStreamingMessage", + requestType = org.a2aproject.sdk.compat03.grpc.SendMessageRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.StreamResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) + public static io.grpc.MethodDescriptor getSendStreamingMessageMethod() { + io.grpc.MethodDescriptor getSendStreamingMessageMethod; + if ((getSendStreamingMessageMethod = A2AServiceGrpc.getSendStreamingMessageMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getSendStreamingMessageMethod = A2AServiceGrpc.getSendStreamingMessageMethod) == null) { + A2AServiceGrpc.getSendStreamingMessageMethod = getSendStreamingMessageMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SendStreamingMessage")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.StreamResponse.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SendStreamingMessage")) + .build(); + } + } + } + return getSendStreamingMessageMethod; + } + + private static volatile io.grpc.MethodDescriptor getGetTaskMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "GetTask", + requestType = org.a2aproject.sdk.compat03.grpc.GetTaskRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.Task.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getGetTaskMethod() { + io.grpc.MethodDescriptor getGetTaskMethod; + if ((getGetTaskMethod = A2AServiceGrpc.getGetTaskMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getGetTaskMethod = A2AServiceGrpc.getGetTaskMethod) == null) { + A2AServiceGrpc.getGetTaskMethod = getGetTaskMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetTask")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.GetTaskRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetTask")) + .build(); + } + } + } + return getGetTaskMethod; + } + + private static volatile io.grpc.MethodDescriptor getCancelTaskMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "CancelTask", + requestType = org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.Task.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getCancelTaskMethod() { + io.grpc.MethodDescriptor getCancelTaskMethod; + if ((getCancelTaskMethod = A2AServiceGrpc.getCancelTaskMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getCancelTaskMethod = A2AServiceGrpc.getCancelTaskMethod) == null) { + A2AServiceGrpc.getCancelTaskMethod = getCancelTaskMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "CancelTask")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("CancelTask")) + .build(); + } + } + } + return getCancelTaskMethod; + } + + private static volatile io.grpc.MethodDescriptor getTaskSubscriptionMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "TaskSubscription", + requestType = org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.StreamResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) + public static io.grpc.MethodDescriptor getTaskSubscriptionMethod() { + io.grpc.MethodDescriptor getTaskSubscriptionMethod; + if ((getTaskSubscriptionMethod = A2AServiceGrpc.getTaskSubscriptionMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getTaskSubscriptionMethod = A2AServiceGrpc.getTaskSubscriptionMethod) == null) { + A2AServiceGrpc.getTaskSubscriptionMethod = getTaskSubscriptionMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "TaskSubscription")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.StreamResponse.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("TaskSubscription")) + .build(); + } + } + } + return getTaskSubscriptionMethod; + } + + private static volatile io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "CreateTaskPushNotificationConfig", + requestType = org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod() { + io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; + if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { + A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod = getCreateTaskPushNotificationConfigMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "CreateTaskPushNotificationConfig")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("CreateTaskPushNotificationConfig")) + .build(); + } + } + } + return getCreateTaskPushNotificationConfigMethod; + } + + private static volatile io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "GetTaskPushNotificationConfig", + requestType = org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod() { + io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod; + if ((getGetTaskPushNotificationConfigMethod = A2AServiceGrpc.getGetTaskPushNotificationConfigMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getGetTaskPushNotificationConfigMethod = A2AServiceGrpc.getGetTaskPushNotificationConfigMethod) == null) { + A2AServiceGrpc.getGetTaskPushNotificationConfigMethod = getGetTaskPushNotificationConfigMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetTaskPushNotificationConfig")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetTaskPushNotificationConfig")) + .build(); + } + } + } + return getGetTaskPushNotificationConfigMethod; + } + + private static volatile io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "ListTaskPushNotificationConfig", + requestType = org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod() { + io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod; + if ((getListTaskPushNotificationConfigMethod = A2AServiceGrpc.getListTaskPushNotificationConfigMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getListTaskPushNotificationConfigMethod = A2AServiceGrpc.getListTaskPushNotificationConfigMethod) == null) { + A2AServiceGrpc.getListTaskPushNotificationConfigMethod = getListTaskPushNotificationConfigMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListTaskPushNotificationConfig")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("ListTaskPushNotificationConfig")) + .build(); + } + } + } + return getListTaskPushNotificationConfigMethod; + } + + private static volatile io.grpc.MethodDescriptor getGetAgentCardMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "GetAgentCard", + requestType = org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.class, + responseType = org.a2aproject.sdk.compat03.grpc.AgentCard.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getGetAgentCardMethod() { + io.grpc.MethodDescriptor getGetAgentCardMethod; + if ((getGetAgentCardMethod = A2AServiceGrpc.getGetAgentCardMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getGetAgentCardMethod = A2AServiceGrpc.getGetAgentCardMethod) == null) { + A2AServiceGrpc.getGetAgentCardMethod = getGetAgentCardMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetAgentCard")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.AgentCard.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetAgentCard")) + .build(); + } + } + } + return getGetAgentCardMethod; + } + + private static volatile io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "DeleteTaskPushNotificationConfig", + requestType = org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.class, + responseType = com.google.protobuf.Empty.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod() { + io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod; + if ((getDeleteTaskPushNotificationConfigMethod = A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod) == null) { + synchronized (A2AServiceGrpc.class) { + if ((getDeleteTaskPushNotificationConfigMethod = A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod) == null) { + A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod = getDeleteTaskPushNotificationConfigMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "DeleteTaskPushNotificationConfig")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + com.google.protobuf.Empty.getDefaultInstance())) + .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("DeleteTaskPushNotificationConfig")) + .build(); + } + } + } + return getDeleteTaskPushNotificationConfigMethod; + } + + /** + * Creates a new async stub that supports all call types for the service + */ + public static A2AServiceStub newStub(io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public A2AServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new A2AServiceStub(channel, callOptions); + } + }; + return A2AServiceStub.newStub(factory, channel); + } + + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static A2AServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public A2AServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new A2AServiceBlockingV2Stub(channel, callOptions); + } + }; + return A2AServiceBlockingV2Stub.newStub(factory, channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static A2AServiceBlockingStub newBlockingStub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public A2AServiceBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new A2AServiceBlockingStub(channel, callOptions); + } + }; + return A2AServiceBlockingStub.newStub(factory, channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary calls on the service + */ + public static A2AServiceFutureStub newFutureStub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public A2AServiceFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new A2AServiceFutureStub(channel, callOptions); + } + }; + return A2AServiceFutureStub.newStub(factory, channel); + } + + /** + *
            +   * A2AService defines the gRPC version of the A2A protocol. This has a slightly
            +   * different shape than the JSONRPC version to better conform to AIP-127,
            +   * where appropriate. The nouns are AgentCard, Message, Task and
            +   * TaskPushNotificationConfig.
            +   * - Messages are not a standard resource so there is no get/delete/update/list
            +   *   interface, only a send and stream custom methods.
            +   * - Tasks have a get interface and custom cancel and subscribe methods.
            +   * - TaskPushNotificationConfig are a resource whose parent is a task.
            +   *   They have get, list and create methods.
            +   * - AgentCard is a static resource with only a get method.
            +   * fields are not present as they don't comply with AIP rules, and the
            +   * optional history_length on the get task method is not present as it also
            +   * violates AIP-127 and AIP-131.
            +   * 
            + */ + public interface AsyncService { + + /** + *
            +     * Send a message to the agent. This is a blocking call that will return the
            +     * task once it is completed, or a LRO if requested.
            +     * 
            + */ + default void sendMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSendMessageMethod(), responseObserver); + } + + /** + *
            +     * SendStreamingMessage is a streaming call that will return a stream of
            +     * task update events until the Task is in an interrupted or terminal state.
            +     * 
            + */ + default void sendStreamingMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSendStreamingMessageMethod(), responseObserver); + } + + /** + *
            +     * Get the current state of a task from the agent.
            +     * 
            + */ + default void getTask(org.a2aproject.sdk.compat03.grpc.GetTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetTaskMethod(), responseObserver); + } + + /** + *
            +     * Cancel a task from the agent. If supported one should expect no
            +     * more task updates for the task.
            +     * 
            + */ + default void cancelTask(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCancelTaskMethod(), responseObserver); + } + + /** + *
            +     * TaskSubscription is a streaming call that will return a stream of task
            +     * update events. This attaches the stream to an existing in process task.
            +     * If the task is complete the stream will return the completed task (like
            +     * GetTask) and close the stream.
            +     * 
            + */ + default void taskSubscription(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getTaskSubscriptionMethod(), responseObserver); + } + + /** + *
            +     * Set a push notification config for a task.
            +     * 
            + */ + default void createTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCreateTaskPushNotificationConfigMethod(), responseObserver); + } + + /** + *
            +     * Get a push notification config for a task.
            +     * 
            + */ + default void getTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetTaskPushNotificationConfigMethod(), responseObserver); + } + + /** + *
            +     * Get a list of push notifications configured for a task.
            +     * 
            + */ + default void listTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListTaskPushNotificationConfigMethod(), responseObserver); + } + + /** + *
            +     * GetAgentCard returns the agent card for the agent.
            +     * 
            + */ + default void getAgentCard(org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetAgentCardMethod(), responseObserver); + } + + /** + *
            +     * Delete a push notification config for a task.
            +     * 
            + */ + default void deleteTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getDeleteTaskPushNotificationConfigMethod(), responseObserver); + } + } + + /** + * Base class for the server implementation of the service A2AService. + *
            +   * A2AService defines the gRPC version of the A2A protocol. This has a slightly
            +   * different shape than the JSONRPC version to better conform to AIP-127,
            +   * where appropriate. The nouns are AgentCard, Message, Task and
            +   * TaskPushNotificationConfig.
            +   * - Messages are not a standard resource so there is no get/delete/update/list
            +   *   interface, only a send and stream custom methods.
            +   * - Tasks have a get interface and custom cancel and subscribe methods.
            +   * - TaskPushNotificationConfig are a resource whose parent is a task.
            +   *   They have get, list and create methods.
            +   * - AgentCard is a static resource with only a get method.
            +   * fields are not present as they don't comply with AIP rules, and the
            +   * optional history_length on the get task method is not present as it also
            +   * violates AIP-127 and AIP-131.
            +   * 
            + */ + public static abstract class A2AServiceImplBase + implements io.grpc.BindableService, AsyncService { + + @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() { + return A2AServiceGrpc.bindService(this); + } + } + + /** + * A stub to allow clients to do asynchronous rpc calls to service A2AService. + *
            +   * A2AService defines the gRPC version of the A2A protocol. This has a slightly
            +   * different shape than the JSONRPC version to better conform to AIP-127,
            +   * where appropriate. The nouns are AgentCard, Message, Task and
            +   * TaskPushNotificationConfig.
            +   * - Messages are not a standard resource so there is no get/delete/update/list
            +   *   interface, only a send and stream custom methods.
            +   * - Tasks have a get interface and custom cancel and subscribe methods.
            +   * - TaskPushNotificationConfig are a resource whose parent is a task.
            +   *   They have get, list and create methods.
            +   * - AgentCard is a static resource with only a get method.
            +   * fields are not present as they don't comply with AIP rules, and the
            +   * optional history_length on the get task method is not present as it also
            +   * violates AIP-127 and AIP-131.
            +   * 
            + */ + public static final class A2AServiceStub + extends io.grpc.stub.AbstractAsyncStub { + private A2AServiceStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected A2AServiceStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new A2AServiceStub(channel, callOptions); + } + + /** + *
            +     * Send a message to the agent. This is a blocking call that will return the
            +     * task once it is completed, or a LRO if requested.
            +     * 
            + */ + public void sendMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getSendMessageMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * SendStreamingMessage is a streaming call that will return a stream of
            +     * task update events until the Task is in an interrupted or terminal state.
            +     * 
            + */ + public void sendStreamingMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncServerStreamingCall( + getChannel().newCall(getSendStreamingMessageMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * Get the current state of a task from the agent.
            +     * 
            + */ + public void getTask(org.a2aproject.sdk.compat03.grpc.GetTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getGetTaskMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * Cancel a task from the agent. If supported one should expect no
            +     * more task updates for the task.
            +     * 
            + */ + public void cancelTask(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getCancelTaskMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * TaskSubscription is a streaming call that will return a stream of task
            +     * update events. This attaches the stream to an existing in process task.
            +     * If the task is complete the stream will return the completed task (like
            +     * GetTask) and close the stream.
            +     * 
            + */ + public void taskSubscription(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncServerStreamingCall( + getChannel().newCall(getTaskSubscriptionMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * Set a push notification config for a task.
            +     * 
            + */ + public void createTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * Get a push notification config for a task.
            +     * 
            + */ + public void getTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getGetTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * Get a list of push notifications configured for a task.
            +     * 
            + */ + public void listTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getListTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * GetAgentCard returns the agent card for the agent.
            +     * 
            + */ + public void getAgentCard(org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getGetAgentCardMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
            +     * Delete a push notification config for a task.
            +     * 
            + */ + public void deleteTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getDeleteTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); + } + } + + /** + * A stub to allow clients to do synchronous rpc calls to service A2AService. + *
            +   * A2AService defines the gRPC version of the A2A protocol. This has a slightly
            +   * different shape than the JSONRPC version to better conform to AIP-127,
            +   * where appropriate. The nouns are AgentCard, Message, Task and
            +   * TaskPushNotificationConfig.
            +   * - Messages are not a standard resource so there is no get/delete/update/list
            +   *   interface, only a send and stream custom methods.
            +   * - Tasks have a get interface and custom cancel and subscribe methods.
            +   * - TaskPushNotificationConfig are a resource whose parent is a task.
            +   *   They have get, list and create methods.
            +   * - AgentCard is a static resource with only a get method.
            +   * fields are not present as they don't comply with AIP rules, and the
            +   * optional history_length on the get task method is not present as it also
            +   * violates AIP-127 and AIP-131.
            +   * 
            + */ + public static final class A2AServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private A2AServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected A2AServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new A2AServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
            +     * Send a message to the agent. This is a blocking call that will return the
            +     * task once it is completed, or a LRO if requested.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.SendMessageResponse sendMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getSendMessageMethod(), getCallOptions(), request); + } + + /** + *
            +     * SendStreamingMessage is a streaming call that will return a stream of
            +     * task update events until the Task is in an interrupted or terminal state.
            +     * 
            + */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + sendStreamingMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getSendStreamingMessageMethod(), getCallOptions(), request); + } + + /** + *
            +     * Get the current state of a task from the agent.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.Task getTask(org.a2aproject.sdk.compat03.grpc.GetTaskRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getGetTaskMethod(), getCallOptions(), request); + } + + /** + *
            +     * Cancel a task from the agent. If supported one should expect no
            +     * more task updates for the task.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.Task cancelTask(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getCancelTaskMethod(), getCallOptions(), request); + } + + /** + *
            +     * TaskSubscription is a streaming call that will return a stream of task
            +     * update events. This attaches the stream to an existing in process task.
            +     * If the task is complete the stream will return the completed task (like
            +     * GetTask) and close the stream.
            +     * 
            + */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + taskSubscription(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getTaskSubscriptionMethod(), getCallOptions(), request); + } + + /** + *
            +     * Set a push notification config for a task.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); + } + + /** + *
            +     * Get a push notification config for a task.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getGetTaskPushNotificationConfigMethod(), getCallOptions(), request); + } + + /** + *
            +     * Get a list of push notifications configured for a task.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getListTaskPushNotificationConfigMethod(), getCallOptions(), request); + } + + /** + *
            +     * GetAgentCard returns the agent card for the agent.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.AgentCard getAgentCard(org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getGetAgentCardMethod(), getCallOptions(), request); + } + + /** + *
            +     * Delete a push notification config for a task.
            +     * 
            + */ + public com.google.protobuf.Empty deleteTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getDeleteTaskPushNotificationConfigMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service A2AService. + *
            +   * A2AService defines the gRPC version of the A2A protocol. This has a slightly
            +   * different shape than the JSONRPC version to better conform to AIP-127,
            +   * where appropriate. The nouns are AgentCard, Message, Task and
            +   * TaskPushNotificationConfig.
            +   * - Messages are not a standard resource so there is no get/delete/update/list
            +   *   interface, only a send and stream custom methods.
            +   * - Tasks have a get interface and custom cancel and subscribe methods.
            +   * - TaskPushNotificationConfig are a resource whose parent is a task.
            +   *   They have get, list and create methods.
            +   * - AgentCard is a static resource with only a get method.
            +   * fields are not present as they don't comply with AIP rules, and the
            +   * optional history_length on the get task method is not present as it also
            +   * violates AIP-127 and AIP-131.
            +   * 
            + */ + public static final class A2AServiceBlockingStub + extends io.grpc.stub.AbstractBlockingStub { + private A2AServiceBlockingStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected A2AServiceBlockingStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new A2AServiceBlockingStub(channel, callOptions); + } + + /** + *
            +     * Send a message to the agent. This is a blocking call that will return the
            +     * task once it is completed, or a LRO if requested.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.SendMessageResponse sendMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSendMessageMethod(), getCallOptions(), request); + } + + /** + *
            +     * SendStreamingMessage is a streaming call that will return a stream of
            +     * task update events until the Task is in an interrupted or terminal state.
            +     * 
            + */ + public java.util.Iterator sendStreamingMessage( + org.a2aproject.sdk.compat03.grpc.SendMessageRequest request) { + return io.grpc.stub.ClientCalls.blockingServerStreamingCall( + getChannel(), getSendStreamingMessageMethod(), getCallOptions(), request); + } + + /** + *
            +     * Get the current state of a task from the agent.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.Task getTask(org.a2aproject.sdk.compat03.grpc.GetTaskRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetTaskMethod(), getCallOptions(), request); + } + + /** + *
            +     * Cancel a task from the agent. If supported one should expect no
            +     * more task updates for the task.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.Task cancelTask(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getCancelTaskMethod(), getCallOptions(), request); + } + + /** + *
            +     * TaskSubscription is a streaming call that will return a stream of task
            +     * update events. This attaches the stream to an existing in process task.
            +     * If the task is complete the stream will return the completed task (like
            +     * GetTask) and close the stream.
            +     * 
            + */ + public java.util.Iterator taskSubscription( + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest request) { + return io.grpc.stub.ClientCalls.blockingServerStreamingCall( + getChannel(), getTaskSubscriptionMethod(), getCallOptions(), request); + } + + /** + *
            +     * Set a push notification config for a task.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); + } + + /** + *
            +     * Get a push notification config for a task.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetTaskPushNotificationConfigMethod(), getCallOptions(), request); + } + + /** + *
            +     * Get a list of push notifications configured for a task.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getListTaskPushNotificationConfigMethod(), getCallOptions(), request); + } + + /** + *
            +     * GetAgentCard returns the agent card for the agent.
            +     * 
            + */ + public org.a2aproject.sdk.compat03.grpc.AgentCard getAgentCard(org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetAgentCardMethod(), getCallOptions(), request); + } + + /** + *
            +     * Delete a push notification config for a task.
            +     * 
            + */ + public com.google.protobuf.Empty deleteTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getDeleteTaskPushNotificationConfigMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do ListenableFuture-style rpc calls to service A2AService. + *
            +   * A2AService defines the gRPC version of the A2A protocol. This has a slightly
            +   * different shape than the JSONRPC version to better conform to AIP-127,
            +   * where appropriate. The nouns are AgentCard, Message, Task and
            +   * TaskPushNotificationConfig.
            +   * - Messages are not a standard resource so there is no get/delete/update/list
            +   *   interface, only a send and stream custom methods.
            +   * - Tasks have a get interface and custom cancel and subscribe methods.
            +   * - TaskPushNotificationConfig are a resource whose parent is a task.
            +   *   They have get, list and create methods.
            +   * - AgentCard is a static resource with only a get method.
            +   * fields are not present as they don't comply with AIP rules, and the
            +   * optional history_length on the get task method is not present as it also
            +   * violates AIP-127 and AIP-131.
            +   * 
            + */ + public static final class A2AServiceFutureStub + extends io.grpc.stub.AbstractFutureStub { + private A2AServiceFutureStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected A2AServiceFutureStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new A2AServiceFutureStub(channel, callOptions); + } + + /** + *
            +     * Send a message to the agent. This is a blocking call that will return the
            +     * task once it is completed, or a LRO if requested.
            +     * 
            + */ + public com.google.common.util.concurrent.ListenableFuture sendMessage( + org.a2aproject.sdk.compat03.grpc.SendMessageRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getSendMessageMethod(), getCallOptions()), request); + } + + /** + *
            +     * Get the current state of a task from the agent.
            +     * 
            + */ + public com.google.common.util.concurrent.ListenableFuture getTask( + org.a2aproject.sdk.compat03.grpc.GetTaskRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getGetTaskMethod(), getCallOptions()), request); + } + + /** + *
            +     * Cancel a task from the agent. If supported one should expect no
            +     * more task updates for the task.
            +     * 
            + */ + public com.google.common.util.concurrent.ListenableFuture cancelTask( + org.a2aproject.sdk.compat03.grpc.CancelTaskRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getCancelTaskMethod(), getCallOptions()), request); + } + + /** + *
            +     * Set a push notification config for a task.
            +     * 
            + */ + public com.google.common.util.concurrent.ListenableFuture createTaskPushNotificationConfig( + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request); + } + + /** + *
            +     * Get a push notification config for a task.
            +     * 
            + */ + public com.google.common.util.concurrent.ListenableFuture getTaskPushNotificationConfig( + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getGetTaskPushNotificationConfigMethod(), getCallOptions()), request); + } + + /** + *
            +     * Get a list of push notifications configured for a task.
            +     * 
            + */ + public com.google.common.util.concurrent.ListenableFuture listTaskPushNotificationConfig( + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getListTaskPushNotificationConfigMethod(), getCallOptions()), request); + } + + /** + *
            +     * GetAgentCard returns the agent card for the agent.
            +     * 
            + */ + public com.google.common.util.concurrent.ListenableFuture getAgentCard( + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getGetAgentCardMethod(), getCallOptions()), request); + } + + /** + *
            +     * Delete a push notification config for a task.
            +     * 
            + */ + public com.google.common.util.concurrent.ListenableFuture deleteTaskPushNotificationConfig( + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getDeleteTaskPushNotificationConfigMethod(), getCallOptions()), request); + } + } + + private static final int METHODID_SEND_MESSAGE = 0; + private static final int METHODID_SEND_STREAMING_MESSAGE = 1; + private static final int METHODID_GET_TASK = 2; + private static final int METHODID_CANCEL_TASK = 3; + private static final int METHODID_TASK_SUBSCRIPTION = 4; + private static final int METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG = 5; + private static final int METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG = 6; + private static final int METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIG = 7; + private static final int METHODID_GET_AGENT_CARD = 8; + private static final int METHODID_DELETE_TASK_PUSH_NOTIFICATION_CONFIG = 9; + + private static final class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final AsyncService serviceImpl; + private final int methodId; + + MethodHandlers(AsyncService serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_SEND_MESSAGE: + serviceImpl.sendMessage((org.a2aproject.sdk.compat03.grpc.SendMessageRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_SEND_STREAMING_MESSAGE: + serviceImpl.sendStreamingMessage((org.a2aproject.sdk.compat03.grpc.SendMessageRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_GET_TASK: + serviceImpl.getTask((org.a2aproject.sdk.compat03.grpc.GetTaskRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_CANCEL_TASK: + serviceImpl.cancelTask((org.a2aproject.sdk.compat03.grpc.CancelTaskRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_TASK_SUBSCRIPTION: + serviceImpl.taskSubscription((org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG: + serviceImpl.createTaskPushNotificationConfig((org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG: + serviceImpl.getTaskPushNotificationConfig((org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIG: + serviceImpl.listTaskPushNotificationConfig((org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_GET_AGENT_CARD: + serviceImpl.getAgentCard((org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_DELETE_TASK_PUSH_NOTIFICATION_CONFIG: + serviceImpl.deleteTaskPushNotificationConfig((org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + } + + public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + getSendMessageMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.SendMessageRequest, + org.a2aproject.sdk.compat03.grpc.SendMessageResponse>( + service, METHODID_SEND_MESSAGE))) + .addMethod( + getSendStreamingMessageMethod(), + io.grpc.stub.ServerCalls.asyncServerStreamingCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.SendMessageRequest, + org.a2aproject.sdk.compat03.grpc.StreamResponse>( + service, METHODID_SEND_STREAMING_MESSAGE))) + .addMethod( + getGetTaskMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.GetTaskRequest, + org.a2aproject.sdk.compat03.grpc.Task>( + service, METHODID_GET_TASK))) + .addMethod( + getCancelTaskMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.CancelTaskRequest, + org.a2aproject.sdk.compat03.grpc.Task>( + service, METHODID_CANCEL_TASK))) + .addMethod( + getTaskSubscriptionMethod(), + io.grpc.stub.ServerCalls.asyncServerStreamingCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest, + org.a2aproject.sdk.compat03.grpc.StreamResponse>( + service, METHODID_TASK_SUBSCRIPTION))) + .addMethod( + getCreateTaskPushNotificationConfigMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest, + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig>( + service, METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG))) + .addMethod( + getGetTaskPushNotificationConfigMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest, + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig>( + service, METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG))) + .addMethod( + getListTaskPushNotificationConfigMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest, + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse>( + service, METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIG))) + .addMethod( + getGetAgentCardMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest, + org.a2aproject.sdk.compat03.grpc.AgentCard>( + service, METHODID_GET_AGENT_CARD))) + .addMethod( + getDeleteTaskPushNotificationConfigMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest, + com.google.protobuf.Empty>( + service, METHODID_DELETE_TASK_PUSH_NOTIFICATION_CONFIG))) + .build(); + } + + private static abstract class A2AServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { + A2AServiceBaseDescriptorSupplier() {} + + @java.lang.Override + public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { + return A2A.getDescriptor(); + } + + @java.lang.Override + public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { + return getFileDescriptor().findServiceByName("A2AService"); + } + } + + private static final class A2AServiceFileDescriptorSupplier + extends A2AServiceBaseDescriptorSupplier { + A2AServiceFileDescriptorSupplier() {} + } + + private static final class A2AServiceMethodDescriptorSupplier + extends A2AServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { + private final java.lang.String methodName; + + A2AServiceMethodDescriptorSupplier(java.lang.String methodName) { + this.methodName = methodName; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { + return getServiceDescriptor().findMethodByName(methodName); + } + } + + private static volatile io.grpc.ServiceDescriptor serviceDescriptor; + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + io.grpc.ServiceDescriptor result = serviceDescriptor; + if (result == null) { + synchronized (A2AServiceGrpc.class) { + result = serviceDescriptor; + if (result == null) { + serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) + .setSchemaDescriptor(new A2AServiceFileDescriptorSupplier()) + .addMethod(getSendMessageMethod()) + .addMethod(getSendStreamingMessageMethod()) + .addMethod(getGetTaskMethod()) + .addMethod(getCancelTaskMethod()) + .addMethod(getTaskSubscriptionMethod()) + .addMethod(getCreateTaskPushNotificationConfigMethod()) + .addMethod(getGetTaskPushNotificationConfigMethod()) + .addMethod(getListTaskPushNotificationConfigMethod()) + .addMethod(getGetAgentCardMethod()) + .addMethod(getDeleteTaskPushNotificationConfigMethod()) + .build(); + } + } + } + return result; + } +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/APIKeySecurityScheme.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/APIKeySecurityScheme.java new file mode 100644 index 000000000..f26fa1f1a --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/APIKeySecurityScheme.java @@ -0,0 +1,858 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.APIKeySecurityScheme} + */ +@com.google.protobuf.Generated +public final class APIKeySecurityScheme extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.APIKeySecurityScheme) + APIKeySecuritySchemeOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "APIKeySecurityScheme"); + } + // Use APIKeySecurityScheme.newBuilder() to construct. + private APIKeySecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private APIKeySecurityScheme() { + description_ = ""; + location_ = ""; + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.class, org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder.class); + } + + public static final int DESCRIPTION_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int LOCATION_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object location_ = ""; + /** + *
            +   * Location of the API key, valid values are "query", "header", or "cookie"
            +   * 
            + * + * string location = 2; + * @return The location. + */ + @java.lang.Override + public java.lang.String getLocation() { + java.lang.Object ref = location_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + location_ = s; + return s; + } + } + /** + *
            +   * Location of the API key, valid values are "query", "header", or "cookie"
            +   * 
            + * + * string location = 2; + * @return The bytes for location. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getLocationBytes() { + java.lang.Object ref = location_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + location_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int NAME_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * Name of the header, query or cookie parameter to be used.
            +   * 
            + * + * string name = 3; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * Name of the header, query or cookie parameter to be used.
            +   * 
            + * + * string name = 3; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(location_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, location_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, name_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(location_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, location_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, name_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme other = (org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) obj; + + if (!getDescription() + .equals(other.getDescription())) return false; + if (!getLocation() + .equals(other.getLocation())) return false; + if (!getName() + .equals(other.getName())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + hash = (37 * hash) + LOCATION_FIELD_NUMBER; + hash = (53 * hash) + getLocation().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.APIKeySecurityScheme} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.APIKeySecurityScheme) + org.a2aproject.sdk.compat03.grpc.APIKeySecuritySchemeOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.class, org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + description_ = ""; + location_ = ""; + name_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme build() { + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme buildPartial() { + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme result = new org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.description_ = description_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.location_ = location_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.name_ = name_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme other) { + if (other == org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance()) return this; + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getLocation().isEmpty()) { + location_ = other.location_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000004; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + location_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object description_ = ""; + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object location_ = ""; + /** + *
            +     * Location of the API key, valid values are "query", "header", or "cookie"
            +     * 
            + * + * string location = 2; + * @return The location. + */ + public java.lang.String getLocation() { + java.lang.Object ref = location_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + location_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Location of the API key, valid values are "query", "header", or "cookie"
            +     * 
            + * + * string location = 2; + * @return The bytes for location. + */ + public com.google.protobuf.ByteString + getLocationBytes() { + java.lang.Object ref = location_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + location_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Location of the API key, valid values are "query", "header", or "cookie"
            +     * 
            + * + * string location = 2; + * @param value The location to set. + * @return This builder for chaining. + */ + public Builder setLocation( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + location_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * Location of the API key, valid values are "query", "header", or "cookie"
            +     * 
            + * + * string location = 2; + * @return This builder for chaining. + */ + public Builder clearLocation() { + location_ = getDefaultInstance().getLocation(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * Location of the API key, valid values are "query", "header", or "cookie"
            +     * 
            + * + * string location = 2; + * @param value The bytes for location to set. + * @return This builder for chaining. + */ + public Builder setLocationBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + location_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object name_ = ""; + /** + *
            +     * Name of the header, query or cookie parameter to be used.
            +     * 
            + * + * string name = 3; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Name of the header, query or cookie parameter to be used.
            +     * 
            + * + * string name = 3; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Name of the header, query or cookie parameter to be used.
            +     * 
            + * + * string name = 3; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * Name of the header, query or cookie parameter to be used.
            +     * 
            + * + * string name = 3; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * Name of the header, query or cookie parameter to be used.
            +     * 
            + * + * string name = 3; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.APIKeySecurityScheme) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.APIKeySecurityScheme) + private static final org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme(); + } + + public static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public APIKeySecurityScheme parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/APIKeySecuritySchemeOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/APIKeySecuritySchemeOrBuilder.java new file mode 100644 index 000000000..7c5b8258e --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/APIKeySecuritySchemeOrBuilder.java @@ -0,0 +1,72 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface APIKeySecuritySchemeOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.APIKeySecurityScheme) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + *
            +   * Location of the API key, valid values are "query", "header", or "cookie"
            +   * 
            + * + * string location = 2; + * @return The location. + */ + java.lang.String getLocation(); + /** + *
            +   * Location of the API key, valid values are "query", "header", or "cookie"
            +   * 
            + * + * string location = 2; + * @return The bytes for location. + */ + com.google.protobuf.ByteString + getLocationBytes(); + + /** + *
            +   * Name of the header, query or cookie parameter to be used.
            +   * 
            + * + * string name = 3; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * Name of the header, query or cookie parameter to be used.
            +   * 
            + * + * string name = 3; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCapabilities.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCapabilities.java new file mode 100644 index 000000000..37b323b72 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCapabilities.java @@ -0,0 +1,986 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Defines the A2A feature set supported by the agent
            + * 
            + * + * Protobuf type {@code a2a.v1.AgentCapabilities} + */ +@com.google.protobuf.Generated +public final class AgentCapabilities extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AgentCapabilities) + AgentCapabilitiesOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AgentCapabilities"); + } + // Use AgentCapabilities.newBuilder() to construct. + private AgentCapabilities(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AgentCapabilities() { + extensions_ = java.util.Collections.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentCapabilities.class, org.a2aproject.sdk.compat03.grpc.AgentCapabilities.Builder.class); + } + + public static final int STREAMING_FIELD_NUMBER = 1; + private boolean streaming_ = false; + /** + *
            +   * If the agent will support streaming responses
            +   * 
            + * + * bool streaming = 1; + * @return The streaming. + */ + @java.lang.Override + public boolean getStreaming() { + return streaming_; + } + + public static final int PUSH_NOTIFICATIONS_FIELD_NUMBER = 2; + private boolean pushNotifications_ = false; + /** + *
            +   * If the agent can send push notifications to the clients webhook
            +   * 
            + * + * bool push_notifications = 2; + * @return The pushNotifications. + */ + @java.lang.Override + public boolean getPushNotifications() { + return pushNotifications_; + } + + public static final int EXTENSIONS_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private java.util.List extensions_; + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + @java.lang.Override + public java.util.List getExtensionsList() { + return extensions_; + } + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + @java.lang.Override + public java.util.List + getExtensionsOrBuilderList() { + return extensions_; + } + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + @java.lang.Override + public int getExtensionsCount() { + return extensions_.size(); + } + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentExtension getExtensions(int index) { + return extensions_.get(index); + } + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( + int index) { + return extensions_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (streaming_ != false) { + output.writeBool(1, streaming_); + } + if (pushNotifications_ != false) { + output.writeBool(2, pushNotifications_); + } + for (int i = 0; i < extensions_.size(); i++) { + output.writeMessage(3, extensions_.get(i)); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (streaming_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(1, streaming_); + } + if (pushNotifications_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(2, pushNotifications_); + } + for (int i = 0; i < extensions_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, extensions_.get(i)); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AgentCapabilities)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AgentCapabilities other = (org.a2aproject.sdk.compat03.grpc.AgentCapabilities) obj; + + if (getStreaming() + != other.getStreaming()) return false; + if (getPushNotifications() + != other.getPushNotifications()) return false; + if (!getExtensionsList() + .equals(other.getExtensionsList())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + STREAMING_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getStreaming()); + hash = (37 * hash) + PUSH_NOTIFICATIONS_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getPushNotifications()); + if (getExtensionsCount() > 0) { + hash = (37 * hash) + EXTENSIONS_FIELD_NUMBER; + hash = (53 * hash) + getExtensionsList().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AgentCapabilities prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Defines the A2A feature set supported by the agent
            +   * 
            + * + * Protobuf type {@code a2a.v1.AgentCapabilities} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCapabilities) + org.a2aproject.sdk.compat03.grpc.AgentCapabilitiesOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentCapabilities.class, org.a2aproject.sdk.compat03.grpc.AgentCapabilities.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AgentCapabilities.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + streaming_ = false; + pushNotifications_ = false; + if (extensionsBuilder_ == null) { + extensions_ = java.util.Collections.emptyList(); + } else { + extensions_ = null; + extensionsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCapabilities getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AgentCapabilities.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCapabilities build() { + org.a2aproject.sdk.compat03.grpc.AgentCapabilities result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCapabilities buildPartial() { + org.a2aproject.sdk.compat03.grpc.AgentCapabilities result = new org.a2aproject.sdk.compat03.grpc.AgentCapabilities(this); + buildPartialRepeatedFields(result); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartialRepeatedFields(org.a2aproject.sdk.compat03.grpc.AgentCapabilities result) { + if (extensionsBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0)) { + extensions_ = java.util.Collections.unmodifiableList(extensions_); + bitField0_ = (bitField0_ & ~0x00000004); + } + result.extensions_ = extensions_; + } else { + result.extensions_ = extensionsBuilder_.build(); + } + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AgentCapabilities result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.streaming_ = streaming_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.pushNotifications_ = pushNotifications_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AgentCapabilities) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AgentCapabilities)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AgentCapabilities other) { + if (other == org.a2aproject.sdk.compat03.grpc.AgentCapabilities.getDefaultInstance()) return this; + if (other.getStreaming() != false) { + setStreaming(other.getStreaming()); + } + if (other.getPushNotifications() != false) { + setPushNotifications(other.getPushNotifications()); + } + if (extensionsBuilder_ == null) { + if (!other.extensions_.isEmpty()) { + if (extensions_.isEmpty()) { + extensions_ = other.extensions_; + bitField0_ = (bitField0_ & ~0x00000004); + } else { + ensureExtensionsIsMutable(); + extensions_.addAll(other.extensions_); + } + onChanged(); + } + } else { + if (!other.extensions_.isEmpty()) { + if (extensionsBuilder_.isEmpty()) { + extensionsBuilder_.dispose(); + extensionsBuilder_ = null; + extensions_ = other.extensions_; + bitField0_ = (bitField0_ & ~0x00000004); + extensionsBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetExtensionsFieldBuilder() : null; + } else { + extensionsBuilder_.addAllMessages(other.extensions_); + } + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + streaming_ = input.readBool(); + bitField0_ |= 0x00000001; + break; + } // case 8 + case 16: { + pushNotifications_ = input.readBool(); + bitField0_ |= 0x00000002; + break; + } // case 16 + case 26: { + org.a2aproject.sdk.compat03.grpc.AgentExtension m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.AgentExtension.parser(), + extensionRegistry); + if (extensionsBuilder_ == null) { + ensureExtensionsIsMutable(); + extensions_.add(m); + } else { + extensionsBuilder_.addMessage(m); + } + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private boolean streaming_ ; + /** + *
            +     * If the agent will support streaming responses
            +     * 
            + * + * bool streaming = 1; + * @return The streaming. + */ + @java.lang.Override + public boolean getStreaming() { + return streaming_; + } + /** + *
            +     * If the agent will support streaming responses
            +     * 
            + * + * bool streaming = 1; + * @param value The streaming to set. + * @return This builder for chaining. + */ + public Builder setStreaming(boolean value) { + + streaming_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * If the agent will support streaming responses
            +     * 
            + * + * bool streaming = 1; + * @return This builder for chaining. + */ + public Builder clearStreaming() { + bitField0_ = (bitField0_ & ~0x00000001); + streaming_ = false; + onChanged(); + return this; + } + + private boolean pushNotifications_ ; + /** + *
            +     * If the agent can send push notifications to the clients webhook
            +     * 
            + * + * bool push_notifications = 2; + * @return The pushNotifications. + */ + @java.lang.Override + public boolean getPushNotifications() { + return pushNotifications_; + } + /** + *
            +     * If the agent can send push notifications to the clients webhook
            +     * 
            + * + * bool push_notifications = 2; + * @param value The pushNotifications to set. + * @return This builder for chaining. + */ + public Builder setPushNotifications(boolean value) { + + pushNotifications_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * If the agent can send push notifications to the clients webhook
            +     * 
            + * + * bool push_notifications = 2; + * @return This builder for chaining. + */ + public Builder clearPushNotifications() { + bitField0_ = (bitField0_ & ~0x00000002); + pushNotifications_ = false; + onChanged(); + return this; + } + + private java.util.List extensions_ = + java.util.Collections.emptyList(); + private void ensureExtensionsIsMutable() { + if (!((bitField0_ & 0x00000004) != 0)) { + extensions_ = new java.util.ArrayList(extensions_); + bitField0_ |= 0x00000004; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentExtension, org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder, org.a2aproject.sdk.compat03.grpc.AgentExtensionOrBuilder> extensionsBuilder_; + + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public java.util.List getExtensionsList() { + if (extensionsBuilder_ == null) { + return java.util.Collections.unmodifiableList(extensions_); + } else { + return extensionsBuilder_.getMessageList(); + } + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public int getExtensionsCount() { + if (extensionsBuilder_ == null) { + return extensions_.size(); + } else { + return extensionsBuilder_.getCount(); + } + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public org.a2aproject.sdk.compat03.grpc.AgentExtension getExtensions(int index) { + if (extensionsBuilder_ == null) { + return extensions_.get(index); + } else { + return extensionsBuilder_.getMessage(index); + } + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder setExtensions( + int index, org.a2aproject.sdk.compat03.grpc.AgentExtension value) { + if (extensionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionsIsMutable(); + extensions_.set(index, value); + onChanged(); + } else { + extensionsBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder setExtensions( + int index, org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder builderForValue) { + if (extensionsBuilder_ == null) { + ensureExtensionsIsMutable(); + extensions_.set(index, builderForValue.build()); + onChanged(); + } else { + extensionsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder addExtensions(org.a2aproject.sdk.compat03.grpc.AgentExtension value) { + if (extensionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionsIsMutable(); + extensions_.add(value); + onChanged(); + } else { + extensionsBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder addExtensions( + int index, org.a2aproject.sdk.compat03.grpc.AgentExtension value) { + if (extensionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureExtensionsIsMutable(); + extensions_.add(index, value); + onChanged(); + } else { + extensionsBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder addExtensions( + org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder builderForValue) { + if (extensionsBuilder_ == null) { + ensureExtensionsIsMutable(); + extensions_.add(builderForValue.build()); + onChanged(); + } else { + extensionsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder addExtensions( + int index, org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder builderForValue) { + if (extensionsBuilder_ == null) { + ensureExtensionsIsMutable(); + extensions_.add(index, builderForValue.build()); + onChanged(); + } else { + extensionsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder addAllExtensions( + java.lang.Iterable values) { + if (extensionsBuilder_ == null) { + ensureExtensionsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, extensions_); + onChanged(); + } else { + extensionsBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder clearExtensions() { + if (extensionsBuilder_ == null) { + extensions_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + } else { + extensionsBuilder_.clear(); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public Builder removeExtensions(int index) { + if (extensionsBuilder_ == null) { + ensureExtensionsIsMutable(); + extensions_.remove(index); + onChanged(); + } else { + extensionsBuilder_.remove(index); + } + return this; + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder getExtensionsBuilder( + int index) { + return internalGetExtensionsFieldBuilder().getBuilder(index); + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public org.a2aproject.sdk.compat03.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( + int index) { + if (extensionsBuilder_ == null) { + return extensions_.get(index); } else { + return extensionsBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public java.util.List + getExtensionsOrBuilderList() { + if (extensionsBuilder_ != null) { + return extensionsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(extensions_); + } + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder addExtensionsBuilder() { + return internalGetExtensionsFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.AgentExtension.getDefaultInstance()); + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder addExtensionsBuilder( + int index) { + return internalGetExtensionsFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.AgentExtension.getDefaultInstance()); + } + /** + *
            +     * Extensions supported by this agent.
            +     * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + public java.util.List + getExtensionsBuilderList() { + return internalGetExtensionsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentExtension, org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder, org.a2aproject.sdk.compat03.grpc.AgentExtensionOrBuilder> + internalGetExtensionsFieldBuilder() { + if (extensionsBuilder_ == null) { + extensionsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentExtension, org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder, org.a2aproject.sdk.compat03.grpc.AgentExtensionOrBuilder>( + extensions_, + ((bitField0_ & 0x00000004) != 0), + getParentForChildren(), + isClean()); + extensions_ = null; + } + return extensionsBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCapabilities) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AgentCapabilities) + private static final org.a2aproject.sdk.compat03.grpc.AgentCapabilities DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AgentCapabilities(); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCapabilities getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AgentCapabilities parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCapabilities getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCapabilitiesOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCapabilitiesOrBuilder.java new file mode 100644 index 000000000..47b710f89 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCapabilitiesOrBuilder.java @@ -0,0 +1,76 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AgentCapabilitiesOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCapabilities) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * If the agent will support streaming responses
            +   * 
            + * + * bool streaming = 1; + * @return The streaming. + */ + boolean getStreaming(); + + /** + *
            +   * If the agent can send push notifications to the clients webhook
            +   * 
            + * + * bool push_notifications = 2; + * @return The pushNotifications. + */ + boolean getPushNotifications(); + + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + java.util.List + getExtensionsList(); + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + org.a2aproject.sdk.compat03.grpc.AgentExtension getExtensions(int index); + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + int getExtensionsCount(); + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + java.util.List + getExtensionsOrBuilderList(); + /** + *
            +   * Extensions supported by this agent.
            +   * 
            + * + * repeated .a2a.v1.AgentExtension extensions = 3; + */ + org.a2aproject.sdk.compat03.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( + int index); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCard.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCard.java new file mode 100644 index 000000000..6e0eeeba1 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCard.java @@ -0,0 +1,5131 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * AgentCard conveys key information:
            + * - Overall details (version, name, description, uses)
            + * - Skills; a set of actions/solutions the agent can perform
            + * - Default modalities/content types supported by the agent.
            + * - Authentication requirements
            + * Next ID: 18
            + * 
            + * + * Protobuf type {@code a2a.v1.AgentCard} + */ +@com.google.protobuf.Generated +public final class AgentCard extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AgentCard) + AgentCardOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AgentCard"); + } + // Use AgentCard.newBuilder() to construct. + private AgentCard(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AgentCard() { + protocolVersion_ = ""; + name_ = ""; + description_ = ""; + url_ = ""; + preferredTransport_ = ""; + additionalInterfaces_ = java.util.Collections.emptyList(); + version_ = ""; + documentationUrl_ = ""; + security_ = java.util.Collections.emptyList(); + defaultInputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + defaultOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + skills_ = java.util.Collections.emptyList(); + signatures_ = java.util.Collections.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentCard_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 8: + return internalGetSecuritySchemes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentCard_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentCard.class, org.a2aproject.sdk.compat03.grpc.AgentCard.Builder.class); + } + + private int bitField0_; + public static final int PROTOCOL_VERSION_FIELD_NUMBER = 16; + @SuppressWarnings("serial") + private volatile java.lang.Object protocolVersion_ = ""; + /** + *
            +   * The version of the A2A protocol this agent supports.
            +   * 
            + * + * string protocol_version = 16; + * @return The protocolVersion. + */ + @java.lang.Override + public java.lang.String getProtocolVersion() { + java.lang.Object ref = protocolVersion_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + protocolVersion_ = s; + return s; + } + } + /** + *
            +   * The version of the A2A protocol this agent supports.
            +   * 
            + * + * string protocol_version = 16; + * @return The bytes for protocolVersion. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getProtocolVersionBytes() { + java.lang.Object ref = protocolVersion_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + protocolVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int NAME_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * A human readable name for the agent.
            +   * Example: "Recipe Agent"
            +   * 
            + * + * string name = 1; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * A human readable name for the agent.
            +   * Example: "Recipe Agent"
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DESCRIPTION_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * A description of the agent's domain of action/solution space.
            +   * Example: "Agent that helps users with recipes and cooking."
            +   * 
            + * + * string description = 2; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * A description of the agent's domain of action/solution space.
            +   * Example: "Agent that helps users with recipes and cooking."
            +   * 
            + * + * string description = 2; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int URL_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object url_ = ""; + /** + *
            +   * A URL to the address the agent is hosted at. This represents the
            +   * preferred endpoint as declared by the agent.
            +   * 
            + * + * string url = 3; + * @return The url. + */ + @java.lang.Override + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } + } + /** + *
            +   * A URL to the address the agent is hosted at. This represents the
            +   * preferred endpoint as declared by the agent.
            +   * 
            + * + * string url = 3; + * @return The bytes for url. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PREFERRED_TRANSPORT_FIELD_NUMBER = 14; + @SuppressWarnings("serial") + private volatile java.lang.Object preferredTransport_ = ""; + /** + *
            +   * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +   * 
            + * + * string preferred_transport = 14; + * @return The preferredTransport. + */ + @java.lang.Override + public java.lang.String getPreferredTransport() { + java.lang.Object ref = preferredTransport_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + preferredTransport_ = s; + return s; + } + } + /** + *
            +   * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +   * 
            + * + * string preferred_transport = 14; + * @return The bytes for preferredTransport. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getPreferredTransportBytes() { + java.lang.Object ref = preferredTransport_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + preferredTransport_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int ADDITIONAL_INTERFACES_FIELD_NUMBER = 15; + @SuppressWarnings("serial") + private java.util.List additionalInterfaces_; + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + @java.lang.Override + public java.util.List getAdditionalInterfacesList() { + return additionalInterfaces_; + } + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + @java.lang.Override + public java.util.List + getAdditionalInterfacesOrBuilderList() { + return additionalInterfaces_; + } + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + @java.lang.Override + public int getAdditionalInterfacesCount() { + return additionalInterfaces_.size(); + } + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentInterface getAdditionalInterfaces(int index) { + return additionalInterfaces_.get(index); + } + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentInterfaceOrBuilder getAdditionalInterfacesOrBuilder( + int index) { + return additionalInterfaces_.get(index); + } + + public static final int PROVIDER_FIELD_NUMBER = 4; + private org.a2aproject.sdk.compat03.grpc.AgentProvider provider_; + /** + *
            +   * The service provider of the agent.
            +   * 
            + * + * .a2a.v1.AgentProvider provider = 4; + * @return Whether the provider field is set. + */ + @java.lang.Override + public boolean hasProvider() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * The service provider of the agent.
            +   * 
            + * + * .a2a.v1.AgentProvider provider = 4; + * @return The provider. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentProvider getProvider() { + return provider_ == null ? org.a2aproject.sdk.compat03.grpc.AgentProvider.getDefaultInstance() : provider_; + } + /** + *
            +   * The service provider of the agent.
            +   * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentProviderOrBuilder getProviderOrBuilder() { + return provider_ == null ? org.a2aproject.sdk.compat03.grpc.AgentProvider.getDefaultInstance() : provider_; + } + + public static final int VERSION_FIELD_NUMBER = 5; + @SuppressWarnings("serial") + private volatile java.lang.Object version_ = ""; + /** + *
            +   * The version of the agent.
            +   * Example: "1.0.0"
            +   * 
            + * + * string version = 5; + * @return The version. + */ + @java.lang.Override + public java.lang.String getVersion() { + java.lang.Object ref = version_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + version_ = s; + return s; + } + } + /** + *
            +   * The version of the agent.
            +   * Example: "1.0.0"
            +   * 
            + * + * string version = 5; + * @return The bytes for version. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getVersionBytes() { + java.lang.Object ref = version_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + version_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DOCUMENTATION_URL_FIELD_NUMBER = 6; + @SuppressWarnings("serial") + private volatile java.lang.Object documentationUrl_ = ""; + /** + *
            +   * A url to provide additional documentation about the agent.
            +   * 
            + * + * string documentation_url = 6; + * @return The documentationUrl. + */ + @java.lang.Override + public java.lang.String getDocumentationUrl() { + java.lang.Object ref = documentationUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + documentationUrl_ = s; + return s; + } + } + /** + *
            +   * A url to provide additional documentation about the agent.
            +   * 
            + * + * string documentation_url = 6; + * @return The bytes for documentationUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDocumentationUrlBytes() { + java.lang.Object ref = documentationUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + documentationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CAPABILITIES_FIELD_NUMBER = 7; + private org.a2aproject.sdk.compat03.grpc.AgentCapabilities capabilities_; + /** + *
            +   * A2A Capability set supported by the agent.
            +   * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + * @return Whether the capabilities field is set. + */ + @java.lang.Override + public boolean hasCapabilities() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
            +   * A2A Capability set supported by the agent.
            +   * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + * @return The capabilities. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCapabilities getCapabilities() { + return capabilities_ == null ? org.a2aproject.sdk.compat03.grpc.AgentCapabilities.getDefaultInstance() : capabilities_; + } + /** + *
            +   * A2A Capability set supported by the agent.
            +   * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() { + return capabilities_ == null ? org.a2aproject.sdk.compat03.grpc.AgentCapabilities.getDefaultInstance() : capabilities_; + } + + public static final int SECURITY_SCHEMES_FIELD_NUMBER = 8; + private static final class SecuritySchemesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, org.a2aproject.sdk.compat03.grpc.SecurityScheme> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + A2A.internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.MESSAGE, + org.a2aproject.sdk.compat03.grpc.SecurityScheme.getDefaultInstance()); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, org.a2aproject.sdk.compat03.grpc.SecurityScheme> securitySchemes_; + private com.google.protobuf.MapField + internalGetSecuritySchemes() { + if (securitySchemes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + SecuritySchemesDefaultEntryHolder.defaultEntry); + } + return securitySchemes_; + } + public int getSecuritySchemesCount() { + return internalGetSecuritySchemes().getMap().size(); + } + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + @java.lang.Override + public boolean containsSecuritySchemes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetSecuritySchemes().getMap().containsKey(key); + } + /** + * Use {@link #getSecuritySchemesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getSecuritySchemes() { + return getSecuritySchemesMap(); + } + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + @java.lang.Override + public java.util.Map getSecuritySchemesMap() { + return internalGetSecuritySchemes().getMap(); + } + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + @java.lang.Override + public /* nullable */ +org.a2aproject.sdk.compat03.grpc.SecurityScheme getSecuritySchemesOrDefault( + java.lang.String key, + /* nullable */ +org.a2aproject.sdk.compat03.grpc.SecurityScheme defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetSecuritySchemes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityScheme getSecuritySchemesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetSecuritySchemes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + public static final int SECURITY_FIELD_NUMBER = 9; + @SuppressWarnings("serial") + private java.util.List security_; + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + @java.lang.Override + public java.util.List getSecurityList() { + return security_; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + @java.lang.Override + public java.util.List + getSecurityOrBuilderList() { + return security_; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + @java.lang.Override + public int getSecurityCount() { + return security_.size(); + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Security getSecurity(int index) { + return security_.get(index); + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder getSecurityOrBuilder( + int index) { + return security_.get(index); + } + + public static final int DEFAULT_INPUT_MODES_FIELD_NUMBER = 10; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList defaultInputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The set of interaction modes that the agent supports across all skills.
            +   * This can be overridden per skill. Defined as mime types.
            +   * 
            + * + * repeated string default_input_modes = 10; + * @return A list containing the defaultInputModes. + */ + public com.google.protobuf.ProtocolStringList + getDefaultInputModesList() { + return defaultInputModes_; + } + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The set of interaction modes that the agent supports across all skills.
            +   * This can be overridden per skill. Defined as mime types.
            +   * 
            + * + * repeated string default_input_modes = 10; + * @return The count of defaultInputModes. + */ + public int getDefaultInputModesCount() { + return defaultInputModes_.size(); + } + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The set of interaction modes that the agent supports across all skills.
            +   * This can be overridden per skill. Defined as mime types.
            +   * 
            + * + * repeated string default_input_modes = 10; + * @param index The index of the element to return. + * @return The defaultInputModes at the given index. + */ + public java.lang.String getDefaultInputModes(int index) { + return defaultInputModes_.get(index); + } + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The set of interaction modes that the agent supports across all skills.
            +   * This can be overridden per skill. Defined as mime types.
            +   * 
            + * + * repeated string default_input_modes = 10; + * @param index The index of the value to return. + * @return The bytes of the defaultInputModes at the given index. + */ + public com.google.protobuf.ByteString + getDefaultInputModesBytes(int index) { + return defaultInputModes_.getByteString(index); + } + + public static final int DEFAULT_OUTPUT_MODES_FIELD_NUMBER = 11; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList defaultOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * The mime types supported as outputs from this agent.
            +   * 
            + * + * repeated string default_output_modes = 11; + * @return A list containing the defaultOutputModes. + */ + public com.google.protobuf.ProtocolStringList + getDefaultOutputModesList() { + return defaultOutputModes_; + } + /** + *
            +   * The mime types supported as outputs from this agent.
            +   * 
            + * + * repeated string default_output_modes = 11; + * @return The count of defaultOutputModes. + */ + public int getDefaultOutputModesCount() { + return defaultOutputModes_.size(); + } + /** + *
            +   * The mime types supported as outputs from this agent.
            +   * 
            + * + * repeated string default_output_modes = 11; + * @param index The index of the element to return. + * @return The defaultOutputModes at the given index. + */ + public java.lang.String getDefaultOutputModes(int index) { + return defaultOutputModes_.get(index); + } + /** + *
            +   * The mime types supported as outputs from this agent.
            +   * 
            + * + * repeated string default_output_modes = 11; + * @param index The index of the value to return. + * @return The bytes of the defaultOutputModes at the given index. + */ + public com.google.protobuf.ByteString + getDefaultOutputModesBytes(int index) { + return defaultOutputModes_.getByteString(index); + } + + public static final int SKILLS_FIELD_NUMBER = 12; + @SuppressWarnings("serial") + private java.util.List skills_; + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + @java.lang.Override + public java.util.List getSkillsList() { + return skills_; + } + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + @java.lang.Override + public java.util.List + getSkillsOrBuilderList() { + return skills_; + } + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + @java.lang.Override + public int getSkillsCount() { + return skills_.size(); + } + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentSkill getSkills(int index) { + return skills_.get(index); + } + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentSkillOrBuilder getSkillsOrBuilder( + int index) { + return skills_.get(index); + } + + public static final int SUPPORTS_AUTHENTICATED_EXTENDED_CARD_FIELD_NUMBER = 13; + private boolean supportsAuthenticatedExtendedCard_ = false; + /** + *
            +   * Whether the agent supports providing an extended agent card when
            +   * the user is authenticated, i.e. is the card from .well-known
            +   * different than the card from GetAgentCard.
            +   * 
            + * + * bool supports_authenticated_extended_card = 13; + * @return The supportsAuthenticatedExtendedCard. + */ + @java.lang.Override + public boolean getSupportsAuthenticatedExtendedCard() { + return supportsAuthenticatedExtendedCard_; + } + + public static final int SIGNATURES_FIELD_NUMBER = 17; + @SuppressWarnings("serial") + private java.util.List signatures_; + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + @java.lang.Override + public java.util.List getSignaturesList() { + return signatures_; + } + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + @java.lang.Override + public java.util.List + getSignaturesOrBuilderList() { + return signatures_; + } + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + @java.lang.Override + public int getSignaturesCount() { + return signatures_.size(); + } + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature getSignatures(int index) { + return signatures_.get(index); + } + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( + int index) { + return signatures_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, description_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, url_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(4, getProvider()); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(version_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 5, version_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(documentationUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 6, documentationUrl_); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(7, getCapabilities()); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetSecuritySchemes(), + SecuritySchemesDefaultEntryHolder.defaultEntry, + 8); + for (int i = 0; i < security_.size(); i++) { + output.writeMessage(9, security_.get(i)); + } + for (int i = 0; i < defaultInputModes_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 10, defaultInputModes_.getRaw(i)); + } + for (int i = 0; i < defaultOutputModes_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 11, defaultOutputModes_.getRaw(i)); + } + for (int i = 0; i < skills_.size(); i++) { + output.writeMessage(12, skills_.get(i)); + } + if (supportsAuthenticatedExtendedCard_ != false) { + output.writeBool(13, supportsAuthenticatedExtendedCard_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(preferredTransport_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 14, preferredTransport_); + } + for (int i = 0; i < additionalInterfaces_.size(); i++) { + output.writeMessage(15, additionalInterfaces_.get(i)); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protocolVersion_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 16, protocolVersion_); + } + for (int i = 0; i < signatures_.size(); i++) { + output.writeMessage(17, signatures_.get(i)); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, description_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, url_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getProvider()); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(version_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(5, version_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(documentationUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(6, documentationUrl_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, getCapabilities()); + } + for (java.util.Map.Entry entry + : internalGetSecuritySchemes().getMap().entrySet()) { + com.google.protobuf.MapEntry + securitySchemes__ = SecuritySchemesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, securitySchemes__); + } + for (int i = 0; i < security_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, security_.get(i)); + } + { + int dataSize = 0; + for (int i = 0; i < defaultInputModes_.size(); i++) { + dataSize += computeStringSizeNoTag(defaultInputModes_.getRaw(i)); + } + size += dataSize; + size += 1 * getDefaultInputModesList().size(); + } + { + int dataSize = 0; + for (int i = 0; i < defaultOutputModes_.size(); i++) { + dataSize += computeStringSizeNoTag(defaultOutputModes_.getRaw(i)); + } + size += dataSize; + size += 1 * getDefaultOutputModesList().size(); + } + for (int i = 0; i < skills_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(12, skills_.get(i)); + } + if (supportsAuthenticatedExtendedCard_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(13, supportsAuthenticatedExtendedCard_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(preferredTransport_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(14, preferredTransport_); + } + for (int i = 0; i < additionalInterfaces_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(15, additionalInterfaces_.get(i)); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protocolVersion_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(16, protocolVersion_); + } + for (int i = 0; i < signatures_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(17, signatures_.get(i)); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AgentCard)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AgentCard other = (org.a2aproject.sdk.compat03.grpc.AgentCard) obj; + + if (!getProtocolVersion() + .equals(other.getProtocolVersion())) return false; + if (!getName() + .equals(other.getName())) return false; + if (!getDescription() + .equals(other.getDescription())) return false; + if (!getUrl() + .equals(other.getUrl())) return false; + if (!getPreferredTransport() + .equals(other.getPreferredTransport())) return false; + if (!getAdditionalInterfacesList() + .equals(other.getAdditionalInterfacesList())) return false; + if (hasProvider() != other.hasProvider()) return false; + if (hasProvider()) { + if (!getProvider() + .equals(other.getProvider())) return false; + } + if (!getVersion() + .equals(other.getVersion())) return false; + if (!getDocumentationUrl() + .equals(other.getDocumentationUrl())) return false; + if (hasCapabilities() != other.hasCapabilities()) return false; + if (hasCapabilities()) { + if (!getCapabilities() + .equals(other.getCapabilities())) return false; + } + if (!internalGetSecuritySchemes().equals( + other.internalGetSecuritySchemes())) return false; + if (!getSecurityList() + .equals(other.getSecurityList())) return false; + if (!getDefaultInputModesList() + .equals(other.getDefaultInputModesList())) return false; + if (!getDefaultOutputModesList() + .equals(other.getDefaultOutputModesList())) return false; + if (!getSkillsList() + .equals(other.getSkillsList())) return false; + if (getSupportsAuthenticatedExtendedCard() + != other.getSupportsAuthenticatedExtendedCard()) return false; + if (!getSignaturesList() + .equals(other.getSignaturesList())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + PROTOCOL_VERSION_FIELD_NUMBER; + hash = (53 * hash) + getProtocolVersion().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + hash = (37 * hash) + URL_FIELD_NUMBER; + hash = (53 * hash) + getUrl().hashCode(); + hash = (37 * hash) + PREFERRED_TRANSPORT_FIELD_NUMBER; + hash = (53 * hash) + getPreferredTransport().hashCode(); + if (getAdditionalInterfacesCount() > 0) { + hash = (37 * hash) + ADDITIONAL_INTERFACES_FIELD_NUMBER; + hash = (53 * hash) + getAdditionalInterfacesList().hashCode(); + } + if (hasProvider()) { + hash = (37 * hash) + PROVIDER_FIELD_NUMBER; + hash = (53 * hash) + getProvider().hashCode(); + } + hash = (37 * hash) + VERSION_FIELD_NUMBER; + hash = (53 * hash) + getVersion().hashCode(); + hash = (37 * hash) + DOCUMENTATION_URL_FIELD_NUMBER; + hash = (53 * hash) + getDocumentationUrl().hashCode(); + if (hasCapabilities()) { + hash = (37 * hash) + CAPABILITIES_FIELD_NUMBER; + hash = (53 * hash) + getCapabilities().hashCode(); + } + if (!internalGetSecuritySchemes().getMap().isEmpty()) { + hash = (37 * hash) + SECURITY_SCHEMES_FIELD_NUMBER; + hash = (53 * hash) + internalGetSecuritySchemes().hashCode(); + } + if (getSecurityCount() > 0) { + hash = (37 * hash) + SECURITY_FIELD_NUMBER; + hash = (53 * hash) + getSecurityList().hashCode(); + } + if (getDefaultInputModesCount() > 0) { + hash = (37 * hash) + DEFAULT_INPUT_MODES_FIELD_NUMBER; + hash = (53 * hash) + getDefaultInputModesList().hashCode(); + } + if (getDefaultOutputModesCount() > 0) { + hash = (37 * hash) + DEFAULT_OUTPUT_MODES_FIELD_NUMBER; + hash = (53 * hash) + getDefaultOutputModesList().hashCode(); + } + if (getSkillsCount() > 0) { + hash = (37 * hash) + SKILLS_FIELD_NUMBER; + hash = (53 * hash) + getSkillsList().hashCode(); + } + hash = (37 * hash) + SUPPORTS_AUTHENTICATED_EXTENDED_CARD_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getSupportsAuthenticatedExtendedCard()); + if (getSignaturesCount() > 0) { + hash = (37 * hash) + SIGNATURES_FIELD_NUMBER; + hash = (53 * hash) + getSignaturesList().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCard parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AgentCard prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * AgentCard conveys key information:
            +   * - Overall details (version, name, description, uses)
            +   * - Skills; a set of actions/solutions the agent can perform
            +   * - Default modalities/content types supported by the agent.
            +   * - Authentication requirements
            +   * Next ID: 18
            +   * 
            + * + * Protobuf type {@code a2a.v1.AgentCard} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCard) + org.a2aproject.sdk.compat03.grpc.AgentCardOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentCard_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 8: + return internalGetSecuritySchemes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 8: + return internalGetMutableSecuritySchemes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentCard_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentCard.class, org.a2aproject.sdk.compat03.grpc.AgentCard.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AgentCard.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetAdditionalInterfacesFieldBuilder(); + internalGetProviderFieldBuilder(); + internalGetCapabilitiesFieldBuilder(); + internalGetSecurityFieldBuilder(); + internalGetSkillsFieldBuilder(); + internalGetSignaturesFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + protocolVersion_ = ""; + name_ = ""; + description_ = ""; + url_ = ""; + preferredTransport_ = ""; + if (additionalInterfacesBuilder_ == null) { + additionalInterfaces_ = java.util.Collections.emptyList(); + } else { + additionalInterfaces_ = null; + additionalInterfacesBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000020); + provider_ = null; + if (providerBuilder_ != null) { + providerBuilder_.dispose(); + providerBuilder_ = null; + } + version_ = ""; + documentationUrl_ = ""; + capabilities_ = null; + if (capabilitiesBuilder_ != null) { + capabilitiesBuilder_.dispose(); + capabilitiesBuilder_ = null; + } + internalGetMutableSecuritySchemes().clear(); + if (securityBuilder_ == null) { + security_ = java.util.Collections.emptyList(); + } else { + security_ = null; + securityBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000800); + defaultInputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + defaultOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + if (skillsBuilder_ == null) { + skills_ = java.util.Collections.emptyList(); + } else { + skills_ = null; + skillsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00004000); + supportsAuthenticatedExtendedCard_ = false; + if (signaturesBuilder_ == null) { + signatures_ = java.util.Collections.emptyList(); + } else { + signatures_ = null; + signaturesBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00010000); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AgentCard_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCard getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AgentCard.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCard build() { + org.a2aproject.sdk.compat03.grpc.AgentCard result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCard buildPartial() { + org.a2aproject.sdk.compat03.grpc.AgentCard result = new org.a2aproject.sdk.compat03.grpc.AgentCard(this); + buildPartialRepeatedFields(result); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartialRepeatedFields(org.a2aproject.sdk.compat03.grpc.AgentCard result) { + if (additionalInterfacesBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0)) { + additionalInterfaces_ = java.util.Collections.unmodifiableList(additionalInterfaces_); + bitField0_ = (bitField0_ & ~0x00000020); + } + result.additionalInterfaces_ = additionalInterfaces_; + } else { + result.additionalInterfaces_ = additionalInterfacesBuilder_.build(); + } + if (securityBuilder_ == null) { + if (((bitField0_ & 0x00000800) != 0)) { + security_ = java.util.Collections.unmodifiableList(security_); + bitField0_ = (bitField0_ & ~0x00000800); + } + result.security_ = security_; + } else { + result.security_ = securityBuilder_.build(); + } + if (skillsBuilder_ == null) { + if (((bitField0_ & 0x00004000) != 0)) { + skills_ = java.util.Collections.unmodifiableList(skills_); + bitField0_ = (bitField0_ & ~0x00004000); + } + result.skills_ = skills_; + } else { + result.skills_ = skillsBuilder_.build(); + } + if (signaturesBuilder_ == null) { + if (((bitField0_ & 0x00010000) != 0)) { + signatures_ = java.util.Collections.unmodifiableList(signatures_); + bitField0_ = (bitField0_ & ~0x00010000); + } + result.signatures_ = signatures_; + } else { + result.signatures_ = signaturesBuilder_.build(); + } + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AgentCard result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.protocolVersion_ = protocolVersion_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.name_ = name_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.description_ = description_; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.url_ = url_; + } + if (((from_bitField0_ & 0x00000010) != 0)) { + result.preferredTransport_ = preferredTransport_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000040) != 0)) { + result.provider_ = providerBuilder_ == null + ? provider_ + : providerBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000080) != 0)) { + result.version_ = version_; + } + if (((from_bitField0_ & 0x00000100) != 0)) { + result.documentationUrl_ = documentationUrl_; + } + if (((from_bitField0_ & 0x00000200) != 0)) { + result.capabilities_ = capabilitiesBuilder_ == null + ? capabilities_ + : capabilitiesBuilder_.build(); + to_bitField0_ |= 0x00000002; + } + if (((from_bitField0_ & 0x00000400) != 0)) { + result.securitySchemes_ = internalGetSecuritySchemes().build(SecuritySchemesDefaultEntryHolder.defaultEntry); + } + if (((from_bitField0_ & 0x00001000) != 0)) { + defaultInputModes_.makeImmutable(); + result.defaultInputModes_ = defaultInputModes_; + } + if (((from_bitField0_ & 0x00002000) != 0)) { + defaultOutputModes_.makeImmutable(); + result.defaultOutputModes_ = defaultOutputModes_; + } + if (((from_bitField0_ & 0x00008000) != 0)) { + result.supportsAuthenticatedExtendedCard_ = supportsAuthenticatedExtendedCard_; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AgentCard) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AgentCard)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AgentCard other) { + if (other == org.a2aproject.sdk.compat03.grpc.AgentCard.getDefaultInstance()) return this; + if (!other.getProtocolVersion().isEmpty()) { + protocolVersion_ = other.protocolVersion_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000004; + onChanged(); + } + if (!other.getUrl().isEmpty()) { + url_ = other.url_; + bitField0_ |= 0x00000008; + onChanged(); + } + if (!other.getPreferredTransport().isEmpty()) { + preferredTransport_ = other.preferredTransport_; + bitField0_ |= 0x00000010; + onChanged(); + } + if (additionalInterfacesBuilder_ == null) { + if (!other.additionalInterfaces_.isEmpty()) { + if (additionalInterfaces_.isEmpty()) { + additionalInterfaces_ = other.additionalInterfaces_; + bitField0_ = (bitField0_ & ~0x00000020); + } else { + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.addAll(other.additionalInterfaces_); + } + onChanged(); + } + } else { + if (!other.additionalInterfaces_.isEmpty()) { + if (additionalInterfacesBuilder_.isEmpty()) { + additionalInterfacesBuilder_.dispose(); + additionalInterfacesBuilder_ = null; + additionalInterfaces_ = other.additionalInterfaces_; + bitField0_ = (bitField0_ & ~0x00000020); + additionalInterfacesBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetAdditionalInterfacesFieldBuilder() : null; + } else { + additionalInterfacesBuilder_.addAllMessages(other.additionalInterfaces_); + } + } + } + if (other.hasProvider()) { + mergeProvider(other.getProvider()); + } + if (!other.getVersion().isEmpty()) { + version_ = other.version_; + bitField0_ |= 0x00000080; + onChanged(); + } + if (!other.getDocumentationUrl().isEmpty()) { + documentationUrl_ = other.documentationUrl_; + bitField0_ |= 0x00000100; + onChanged(); + } + if (other.hasCapabilities()) { + mergeCapabilities(other.getCapabilities()); + } + internalGetMutableSecuritySchemes().mergeFrom( + other.internalGetSecuritySchemes()); + bitField0_ |= 0x00000400; + if (securityBuilder_ == null) { + if (!other.security_.isEmpty()) { + if (security_.isEmpty()) { + security_ = other.security_; + bitField0_ = (bitField0_ & ~0x00000800); + } else { + ensureSecurityIsMutable(); + security_.addAll(other.security_); + } + onChanged(); + } + } else { + if (!other.security_.isEmpty()) { + if (securityBuilder_.isEmpty()) { + securityBuilder_.dispose(); + securityBuilder_ = null; + security_ = other.security_; + bitField0_ = (bitField0_ & ~0x00000800); + securityBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetSecurityFieldBuilder() : null; + } else { + securityBuilder_.addAllMessages(other.security_); + } + } + } + if (!other.defaultInputModes_.isEmpty()) { + if (defaultInputModes_.isEmpty()) { + defaultInputModes_ = other.defaultInputModes_; + bitField0_ |= 0x00001000; + } else { + ensureDefaultInputModesIsMutable(); + defaultInputModes_.addAll(other.defaultInputModes_); + } + onChanged(); + } + if (!other.defaultOutputModes_.isEmpty()) { + if (defaultOutputModes_.isEmpty()) { + defaultOutputModes_ = other.defaultOutputModes_; + bitField0_ |= 0x00002000; + } else { + ensureDefaultOutputModesIsMutable(); + defaultOutputModes_.addAll(other.defaultOutputModes_); + } + onChanged(); + } + if (skillsBuilder_ == null) { + if (!other.skills_.isEmpty()) { + if (skills_.isEmpty()) { + skills_ = other.skills_; + bitField0_ = (bitField0_ & ~0x00004000); + } else { + ensureSkillsIsMutable(); + skills_.addAll(other.skills_); + } + onChanged(); + } + } else { + if (!other.skills_.isEmpty()) { + if (skillsBuilder_.isEmpty()) { + skillsBuilder_.dispose(); + skillsBuilder_ = null; + skills_ = other.skills_; + bitField0_ = (bitField0_ & ~0x00004000); + skillsBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetSkillsFieldBuilder() : null; + } else { + skillsBuilder_.addAllMessages(other.skills_); + } + } + } + if (other.getSupportsAuthenticatedExtendedCard() != false) { + setSupportsAuthenticatedExtendedCard(other.getSupportsAuthenticatedExtendedCard()); + } + if (signaturesBuilder_ == null) { + if (!other.signatures_.isEmpty()) { + if (signatures_.isEmpty()) { + signatures_ = other.signatures_; + bitField0_ = (bitField0_ & ~0x00010000); + } else { + ensureSignaturesIsMutable(); + signatures_.addAll(other.signatures_); + } + onChanged(); + } + } else { + if (!other.signatures_.isEmpty()) { + if (signaturesBuilder_.isEmpty()) { + signaturesBuilder_.dispose(); + signaturesBuilder_ = null; + signatures_ = other.signatures_; + bitField0_ = (bitField0_ & ~0x00010000); + signaturesBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetSignaturesFieldBuilder() : null; + } else { + signaturesBuilder_.addAllMessages(other.signatures_); + } + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 10 + case 18: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 18 + case 26: { + url_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000008; + break; + } // case 26 + case 34: { + input.readMessage( + internalGetProviderFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000040; + break; + } // case 34 + case 42: { + version_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000080; + break; + } // case 42 + case 50: { + documentationUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000100; + break; + } // case 50 + case 58: { + input.readMessage( + internalGetCapabilitiesFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000200; + break; + } // case 58 + case 66: { + com.google.protobuf.MapEntry + securitySchemes__ = input.readMessage( + SecuritySchemesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableSecuritySchemes().ensureBuilderMap().put( + securitySchemes__.getKey(), securitySchemes__.getValue()); + bitField0_ |= 0x00000400; + break; + } // case 66 + case 74: { + org.a2aproject.sdk.compat03.grpc.Security m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.Security.parser(), + extensionRegistry); + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.add(m); + } else { + securityBuilder_.addMessage(m); + } + break; + } // case 74 + case 82: { + java.lang.String s = input.readStringRequireUtf8(); + ensureDefaultInputModesIsMutable(); + defaultInputModes_.add(s); + break; + } // case 82 + case 90: { + java.lang.String s = input.readStringRequireUtf8(); + ensureDefaultOutputModesIsMutable(); + defaultOutputModes_.add(s); + break; + } // case 90 + case 98: { + org.a2aproject.sdk.compat03.grpc.AgentSkill m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.AgentSkill.parser(), + extensionRegistry); + if (skillsBuilder_ == null) { + ensureSkillsIsMutable(); + skills_.add(m); + } else { + skillsBuilder_.addMessage(m); + } + break; + } // case 98 + case 104: { + supportsAuthenticatedExtendedCard_ = input.readBool(); + bitField0_ |= 0x00008000; + break; + } // case 104 + case 114: { + preferredTransport_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000010; + break; + } // case 114 + case 122: { + org.a2aproject.sdk.compat03.grpc.AgentInterface m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.AgentInterface.parser(), + extensionRegistry); + if (additionalInterfacesBuilder_ == null) { + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.add(m); + } else { + additionalInterfacesBuilder_.addMessage(m); + } + break; + } // case 122 + case 130: { + protocolVersion_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 130 + case 138: { + org.a2aproject.sdk.compat03.grpc.AgentCardSignature m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.AgentCardSignature.parser(), + extensionRegistry); + if (signaturesBuilder_ == null) { + ensureSignaturesIsMutable(); + signatures_.add(m); + } else { + signaturesBuilder_.addMessage(m); + } + break; + } // case 138 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object protocolVersion_ = ""; + /** + *
            +     * The version of the A2A protocol this agent supports.
            +     * 
            + * + * string protocol_version = 16; + * @return The protocolVersion. + */ + public java.lang.String getProtocolVersion() { + java.lang.Object ref = protocolVersion_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + protocolVersion_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The version of the A2A protocol this agent supports.
            +     * 
            + * + * string protocol_version = 16; + * @return The bytes for protocolVersion. + */ + public com.google.protobuf.ByteString + getProtocolVersionBytes() { + java.lang.Object ref = protocolVersion_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + protocolVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The version of the A2A protocol this agent supports.
            +     * 
            + * + * string protocol_version = 16; + * @param value The protocolVersion to set. + * @return This builder for chaining. + */ + public Builder setProtocolVersion( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + protocolVersion_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The version of the A2A protocol this agent supports.
            +     * 
            + * + * string protocol_version = 16; + * @return This builder for chaining. + */ + public Builder clearProtocolVersion() { + protocolVersion_ = getDefaultInstance().getProtocolVersion(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The version of the A2A protocol this agent supports.
            +     * 
            + * + * string protocol_version = 16; + * @param value The bytes for protocolVersion to set. + * @return This builder for chaining. + */ + public Builder setProtocolVersionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + protocolVersion_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object name_ = ""; + /** + *
            +     * A human readable name for the agent.
            +     * Example: "Recipe Agent"
            +     * 
            + * + * string name = 1; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A human readable name for the agent.
            +     * Example: "Recipe Agent"
            +     * 
            + * + * string name = 1; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A human readable name for the agent.
            +     * Example: "Recipe Agent"
            +     * 
            + * + * string name = 1; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A human readable name for the agent.
            +     * Example: "Recipe Agent"
            +     * 
            + * + * string name = 1; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * A human readable name for the agent.
            +     * Example: "Recipe Agent"
            +     * 
            + * + * string name = 1; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object description_ = ""; + /** + *
            +     * A description of the agent's domain of action/solution space.
            +     * Example: "Agent that helps users with recipes and cooking."
            +     * 
            + * + * string description = 2; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A description of the agent's domain of action/solution space.
            +     * Example: "Agent that helps users with recipes and cooking."
            +     * 
            + * + * string description = 2; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A description of the agent's domain of action/solution space.
            +     * Example: "Agent that helps users with recipes and cooking."
            +     * 
            + * + * string description = 2; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * A description of the agent's domain of action/solution space.
            +     * Example: "Agent that helps users with recipes and cooking."
            +     * 
            + * + * string description = 2; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * A description of the agent's domain of action/solution space.
            +     * Example: "Agent that helps users with recipes and cooking."
            +     * 
            + * + * string description = 2; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private java.lang.Object url_ = ""; + /** + *
            +     * A URL to the address the agent is hosted at. This represents the
            +     * preferred endpoint as declared by the agent.
            +     * 
            + * + * string url = 3; + * @return The url. + */ + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A URL to the address the agent is hosted at. This represents the
            +     * preferred endpoint as declared by the agent.
            +     * 
            + * + * string url = 3; + * @return The bytes for url. + */ + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A URL to the address the agent is hosted at. This represents the
            +     * preferred endpoint as declared by the agent.
            +     * 
            + * + * string url = 3; + * @param value The url to set. + * @return This builder for chaining. + */ + public Builder setUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + url_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * A URL to the address the agent is hosted at. This represents the
            +     * preferred endpoint as declared by the agent.
            +     * 
            + * + * string url = 3; + * @return This builder for chaining. + */ + public Builder clearUrl() { + url_ = getDefaultInstance().getUrl(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + return this; + } + /** + *
            +     * A URL to the address the agent is hosted at. This represents the
            +     * preferred endpoint as declared by the agent.
            +     * 
            + * + * string url = 3; + * @param value The bytes for url to set. + * @return This builder for chaining. + */ + public Builder setUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + url_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + + private java.lang.Object preferredTransport_ = ""; + /** + *
            +     * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +     * 
            + * + * string preferred_transport = 14; + * @return The preferredTransport. + */ + public java.lang.String getPreferredTransport() { + java.lang.Object ref = preferredTransport_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + preferredTransport_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +     * 
            + * + * string preferred_transport = 14; + * @return The bytes for preferredTransport. + */ + public com.google.protobuf.ByteString + getPreferredTransportBytes() { + java.lang.Object ref = preferredTransport_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + preferredTransport_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +     * 
            + * + * string preferred_transport = 14; + * @param value The preferredTransport to set. + * @return This builder for chaining. + */ + public Builder setPreferredTransport( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + preferredTransport_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +     * 
            + * + * string preferred_transport = 14; + * @return This builder for chaining. + */ + public Builder clearPreferredTransport() { + preferredTransport_ = getDefaultInstance().getPreferredTransport(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + return this; + } + /** + *
            +     * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +     * 
            + * + * string preferred_transport = 14; + * @param value The bytes for preferredTransport to set. + * @return This builder for chaining. + */ + public Builder setPreferredTransportBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + preferredTransport_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + + private java.util.List additionalInterfaces_ = + java.util.Collections.emptyList(); + private void ensureAdditionalInterfacesIsMutable() { + if (!((bitField0_ & 0x00000020) != 0)) { + additionalInterfaces_ = new java.util.ArrayList(additionalInterfaces_); + bitField0_ |= 0x00000020; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentInterface, org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder, org.a2aproject.sdk.compat03.grpc.AgentInterfaceOrBuilder> additionalInterfacesBuilder_; + + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public java.util.List getAdditionalInterfacesList() { + if (additionalInterfacesBuilder_ == null) { + return java.util.Collections.unmodifiableList(additionalInterfaces_); + } else { + return additionalInterfacesBuilder_.getMessageList(); + } + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public int getAdditionalInterfacesCount() { + if (additionalInterfacesBuilder_ == null) { + return additionalInterfaces_.size(); + } else { + return additionalInterfacesBuilder_.getCount(); + } + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public org.a2aproject.sdk.compat03.grpc.AgentInterface getAdditionalInterfaces(int index) { + if (additionalInterfacesBuilder_ == null) { + return additionalInterfaces_.get(index); + } else { + return additionalInterfacesBuilder_.getMessage(index); + } + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder setAdditionalInterfaces( + int index, org.a2aproject.sdk.compat03.grpc.AgentInterface value) { + if (additionalInterfacesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.set(index, value); + onChanged(); + } else { + additionalInterfacesBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder setAdditionalInterfaces( + int index, org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder builderForValue) { + if (additionalInterfacesBuilder_ == null) { + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.set(index, builderForValue.build()); + onChanged(); + } else { + additionalInterfacesBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder addAdditionalInterfaces(org.a2aproject.sdk.compat03.grpc.AgentInterface value) { + if (additionalInterfacesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.add(value); + onChanged(); + } else { + additionalInterfacesBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder addAdditionalInterfaces( + int index, org.a2aproject.sdk.compat03.grpc.AgentInterface value) { + if (additionalInterfacesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.add(index, value); + onChanged(); + } else { + additionalInterfacesBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder addAdditionalInterfaces( + org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder builderForValue) { + if (additionalInterfacesBuilder_ == null) { + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.add(builderForValue.build()); + onChanged(); + } else { + additionalInterfacesBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder addAdditionalInterfaces( + int index, org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder builderForValue) { + if (additionalInterfacesBuilder_ == null) { + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.add(index, builderForValue.build()); + onChanged(); + } else { + additionalInterfacesBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder addAllAdditionalInterfaces( + java.lang.Iterable values) { + if (additionalInterfacesBuilder_ == null) { + ensureAdditionalInterfacesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, additionalInterfaces_); + onChanged(); + } else { + additionalInterfacesBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder clearAdditionalInterfaces() { + if (additionalInterfacesBuilder_ == null) { + additionalInterfaces_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); + onChanged(); + } else { + additionalInterfacesBuilder_.clear(); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public Builder removeAdditionalInterfaces(int index) { + if (additionalInterfacesBuilder_ == null) { + ensureAdditionalInterfacesIsMutable(); + additionalInterfaces_.remove(index); + onChanged(); + } else { + additionalInterfacesBuilder_.remove(index); + } + return this; + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder getAdditionalInterfacesBuilder( + int index) { + return internalGetAdditionalInterfacesFieldBuilder().getBuilder(index); + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public org.a2aproject.sdk.compat03.grpc.AgentInterfaceOrBuilder getAdditionalInterfacesOrBuilder( + int index) { + if (additionalInterfacesBuilder_ == null) { + return additionalInterfaces_.get(index); } else { + return additionalInterfacesBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public java.util.List + getAdditionalInterfacesOrBuilderList() { + if (additionalInterfacesBuilder_ != null) { + return additionalInterfacesBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(additionalInterfaces_); + } + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder addAdditionalInterfacesBuilder() { + return internalGetAdditionalInterfacesFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.AgentInterface.getDefaultInstance()); + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder addAdditionalInterfacesBuilder( + int index) { + return internalGetAdditionalInterfacesFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.AgentInterface.getDefaultInstance()); + } + /** + *
            +     * Announcement of additional supported transports. Client can use any of
            +     * the supported transports.
            +     * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + public java.util.List + getAdditionalInterfacesBuilderList() { + return internalGetAdditionalInterfacesFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentInterface, org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder, org.a2aproject.sdk.compat03.grpc.AgentInterfaceOrBuilder> + internalGetAdditionalInterfacesFieldBuilder() { + if (additionalInterfacesBuilder_ == null) { + additionalInterfacesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentInterface, org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder, org.a2aproject.sdk.compat03.grpc.AgentInterfaceOrBuilder>( + additionalInterfaces_, + ((bitField0_ & 0x00000020) != 0), + getParentForChildren(), + isClean()); + additionalInterfaces_ = null; + } + return additionalInterfacesBuilder_; + } + + private org.a2aproject.sdk.compat03.grpc.AgentProvider provider_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentProvider, org.a2aproject.sdk.compat03.grpc.AgentProvider.Builder, org.a2aproject.sdk.compat03.grpc.AgentProviderOrBuilder> providerBuilder_; + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + * @return Whether the provider field is set. + */ + public boolean hasProvider() { + return ((bitField0_ & 0x00000040) != 0); + } + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + * @return The provider. + */ + public org.a2aproject.sdk.compat03.grpc.AgentProvider getProvider() { + if (providerBuilder_ == null) { + return provider_ == null ? org.a2aproject.sdk.compat03.grpc.AgentProvider.getDefaultInstance() : provider_; + } else { + return providerBuilder_.getMessage(); + } + } + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + public Builder setProvider(org.a2aproject.sdk.compat03.grpc.AgentProvider value) { + if (providerBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + provider_ = value; + } else { + providerBuilder_.setMessage(value); + } + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + public Builder setProvider( + org.a2aproject.sdk.compat03.grpc.AgentProvider.Builder builderForValue) { + if (providerBuilder_ == null) { + provider_ = builderForValue.build(); + } else { + providerBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + public Builder mergeProvider(org.a2aproject.sdk.compat03.grpc.AgentProvider value) { + if (providerBuilder_ == null) { + if (((bitField0_ & 0x00000040) != 0) && + provider_ != null && + provider_ != org.a2aproject.sdk.compat03.grpc.AgentProvider.getDefaultInstance()) { + getProviderBuilder().mergeFrom(value); + } else { + provider_ = value; + } + } else { + providerBuilder_.mergeFrom(value); + } + if (provider_ != null) { + bitField0_ |= 0x00000040; + onChanged(); + } + return this; + } + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + public Builder clearProvider() { + bitField0_ = (bitField0_ & ~0x00000040); + provider_ = null; + if (providerBuilder_ != null) { + providerBuilder_.dispose(); + providerBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + public org.a2aproject.sdk.compat03.grpc.AgentProvider.Builder getProviderBuilder() { + bitField0_ |= 0x00000040; + onChanged(); + return internalGetProviderFieldBuilder().getBuilder(); + } + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + public org.a2aproject.sdk.compat03.grpc.AgentProviderOrBuilder getProviderOrBuilder() { + if (providerBuilder_ != null) { + return providerBuilder_.getMessageOrBuilder(); + } else { + return provider_ == null ? + org.a2aproject.sdk.compat03.grpc.AgentProvider.getDefaultInstance() : provider_; + } + } + /** + *
            +     * The service provider of the agent.
            +     * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentProvider, org.a2aproject.sdk.compat03.grpc.AgentProvider.Builder, org.a2aproject.sdk.compat03.grpc.AgentProviderOrBuilder> + internalGetProviderFieldBuilder() { + if (providerBuilder_ == null) { + providerBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentProvider, org.a2aproject.sdk.compat03.grpc.AgentProvider.Builder, org.a2aproject.sdk.compat03.grpc.AgentProviderOrBuilder>( + getProvider(), + getParentForChildren(), + isClean()); + provider_ = null; + } + return providerBuilder_; + } + + private java.lang.Object version_ = ""; + /** + *
            +     * The version of the agent.
            +     * Example: "1.0.0"
            +     * 
            + * + * string version = 5; + * @return The version. + */ + public java.lang.String getVersion() { + java.lang.Object ref = version_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + version_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The version of the agent.
            +     * Example: "1.0.0"
            +     * 
            + * + * string version = 5; + * @return The bytes for version. + */ + public com.google.protobuf.ByteString + getVersionBytes() { + java.lang.Object ref = version_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + version_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The version of the agent.
            +     * Example: "1.0.0"
            +     * 
            + * + * string version = 5; + * @param value The version to set. + * @return This builder for chaining. + */ + public Builder setVersion( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + version_ = value; + bitField0_ |= 0x00000080; + onChanged(); + return this; + } + /** + *
            +     * The version of the agent.
            +     * Example: "1.0.0"
            +     * 
            + * + * string version = 5; + * @return This builder for chaining. + */ + public Builder clearVersion() { + version_ = getDefaultInstance().getVersion(); + bitField0_ = (bitField0_ & ~0x00000080); + onChanged(); + return this; + } + /** + *
            +     * The version of the agent.
            +     * Example: "1.0.0"
            +     * 
            + * + * string version = 5; + * @param value The bytes for version to set. + * @return This builder for chaining. + */ + public Builder setVersionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + version_ = value; + bitField0_ |= 0x00000080; + onChanged(); + return this; + } + + private java.lang.Object documentationUrl_ = ""; + /** + *
            +     * A url to provide additional documentation about the agent.
            +     * 
            + * + * string documentation_url = 6; + * @return The documentationUrl. + */ + public java.lang.String getDocumentationUrl() { + java.lang.Object ref = documentationUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + documentationUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A url to provide additional documentation about the agent.
            +     * 
            + * + * string documentation_url = 6; + * @return The bytes for documentationUrl. + */ + public com.google.protobuf.ByteString + getDocumentationUrlBytes() { + java.lang.Object ref = documentationUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + documentationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A url to provide additional documentation about the agent.
            +     * 
            + * + * string documentation_url = 6; + * @param value The documentationUrl to set. + * @return This builder for chaining. + */ + public Builder setDocumentationUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + documentationUrl_ = value; + bitField0_ |= 0x00000100; + onChanged(); + return this; + } + /** + *
            +     * A url to provide additional documentation about the agent.
            +     * 
            + * + * string documentation_url = 6; + * @return This builder for chaining. + */ + public Builder clearDocumentationUrl() { + documentationUrl_ = getDefaultInstance().getDocumentationUrl(); + bitField0_ = (bitField0_ & ~0x00000100); + onChanged(); + return this; + } + /** + *
            +     * A url to provide additional documentation about the agent.
            +     * 
            + * + * string documentation_url = 6; + * @param value The bytes for documentationUrl to set. + * @return This builder for chaining. + */ + public Builder setDocumentationUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + documentationUrl_ = value; + bitField0_ |= 0x00000100; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.AgentCapabilities capabilities_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentCapabilities, org.a2aproject.sdk.compat03.grpc.AgentCapabilities.Builder, org.a2aproject.sdk.compat03.grpc.AgentCapabilitiesOrBuilder> capabilitiesBuilder_; + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + * @return Whether the capabilities field is set. + */ + public boolean hasCapabilities() { + return ((bitField0_ & 0x00000200) != 0); + } + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + * @return The capabilities. + */ + public org.a2aproject.sdk.compat03.grpc.AgentCapabilities getCapabilities() { + if (capabilitiesBuilder_ == null) { + return capabilities_ == null ? org.a2aproject.sdk.compat03.grpc.AgentCapabilities.getDefaultInstance() : capabilities_; + } else { + return capabilitiesBuilder_.getMessage(); + } + } + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + public Builder setCapabilities(org.a2aproject.sdk.compat03.grpc.AgentCapabilities value) { + if (capabilitiesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + capabilities_ = value; + } else { + capabilitiesBuilder_.setMessage(value); + } + bitField0_ |= 0x00000200; + onChanged(); + return this; + } + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + public Builder setCapabilities( + org.a2aproject.sdk.compat03.grpc.AgentCapabilities.Builder builderForValue) { + if (capabilitiesBuilder_ == null) { + capabilities_ = builderForValue.build(); + } else { + capabilitiesBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000200; + onChanged(); + return this; + } + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + public Builder mergeCapabilities(org.a2aproject.sdk.compat03.grpc.AgentCapabilities value) { + if (capabilitiesBuilder_ == null) { + if (((bitField0_ & 0x00000200) != 0) && + capabilities_ != null && + capabilities_ != org.a2aproject.sdk.compat03.grpc.AgentCapabilities.getDefaultInstance()) { + getCapabilitiesBuilder().mergeFrom(value); + } else { + capabilities_ = value; + } + } else { + capabilitiesBuilder_.mergeFrom(value); + } + if (capabilities_ != null) { + bitField0_ |= 0x00000200; + onChanged(); + } + return this; + } + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + public Builder clearCapabilities() { + bitField0_ = (bitField0_ & ~0x00000200); + capabilities_ = null; + if (capabilitiesBuilder_ != null) { + capabilitiesBuilder_.dispose(); + capabilitiesBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + public org.a2aproject.sdk.compat03.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() { + bitField0_ |= 0x00000200; + onChanged(); + return internalGetCapabilitiesFieldBuilder().getBuilder(); + } + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + public org.a2aproject.sdk.compat03.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() { + if (capabilitiesBuilder_ != null) { + return capabilitiesBuilder_.getMessageOrBuilder(); + } else { + return capabilities_ == null ? + org.a2aproject.sdk.compat03.grpc.AgentCapabilities.getDefaultInstance() : capabilities_; + } + } + /** + *
            +     * A2A Capability set supported by the agent.
            +     * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentCapabilities, org.a2aproject.sdk.compat03.grpc.AgentCapabilities.Builder, org.a2aproject.sdk.compat03.grpc.AgentCapabilitiesOrBuilder> + internalGetCapabilitiesFieldBuilder() { + if (capabilitiesBuilder_ == null) { + capabilitiesBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentCapabilities, org.a2aproject.sdk.compat03.grpc.AgentCapabilities.Builder, org.a2aproject.sdk.compat03.grpc.AgentCapabilitiesOrBuilder>( + getCapabilities(), + getParentForChildren(), + isClean()); + capabilities_ = null; + } + return capabilitiesBuilder_; + } + + private static final class SecuritySchemesConverter implements com.google.protobuf.MapFieldBuilder.Converter { + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityScheme build(org.a2aproject.sdk.compat03.grpc.SecuritySchemeOrBuilder val) { + if (val instanceof org.a2aproject.sdk.compat03.grpc.SecurityScheme) { return (org.a2aproject.sdk.compat03.grpc.SecurityScheme) val; } + return ((org.a2aproject.sdk.compat03.grpc.SecurityScheme.Builder) val).build(); + } + + @java.lang.Override + public com.google.protobuf.MapEntry defaultEntry() { + return SecuritySchemesDefaultEntryHolder.defaultEntry; + } + }; + private static final SecuritySchemesConverter securitySchemesConverter = new SecuritySchemesConverter(); + + private com.google.protobuf.MapFieldBuilder< + java.lang.String, org.a2aproject.sdk.compat03.grpc.SecuritySchemeOrBuilder, org.a2aproject.sdk.compat03.grpc.SecurityScheme, org.a2aproject.sdk.compat03.grpc.SecurityScheme.Builder> securitySchemes_; + private com.google.protobuf.MapFieldBuilder + internalGetSecuritySchemes() { + if (securitySchemes_ == null) { + return new com.google.protobuf.MapFieldBuilder<>(securitySchemesConverter); + } + return securitySchemes_; + } + private com.google.protobuf.MapFieldBuilder + internalGetMutableSecuritySchemes() { + if (securitySchemes_ == null) { + securitySchemes_ = new com.google.protobuf.MapFieldBuilder<>(securitySchemesConverter); + } + bitField0_ |= 0x00000400; + onChanged(); + return securitySchemes_; + } + public int getSecuritySchemesCount() { + return internalGetSecuritySchemes().ensureBuilderMap().size(); + } + /** + *
            +     * The security scheme details used for authenticating with this agent.
            +     * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + @java.lang.Override + public boolean containsSecuritySchemes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetSecuritySchemes().ensureBuilderMap().containsKey(key); + } + /** + * Use {@link #getSecuritySchemesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getSecuritySchemes() { + return getSecuritySchemesMap(); + } + /** + *
            +     * The security scheme details used for authenticating with this agent.
            +     * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + @java.lang.Override + public java.util.Map getSecuritySchemesMap() { + return internalGetSecuritySchemes().getImmutableMap(); + } + /** + *
            +     * The security scheme details used for authenticating with this agent.
            +     * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + @java.lang.Override + public /* nullable */ +org.a2aproject.sdk.compat03.grpc.SecurityScheme getSecuritySchemesOrDefault( + java.lang.String key, + /* nullable */ +org.a2aproject.sdk.compat03.grpc.SecurityScheme defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = internalGetMutableSecuritySchemes().ensureBuilderMap(); + return map.containsKey(key) ? securitySchemesConverter.build(map.get(key)) : defaultValue; + } + /** + *
            +     * The security scheme details used for authenticating with this agent.
            +     * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityScheme getSecuritySchemesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = internalGetMutableSecuritySchemes().ensureBuilderMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return securitySchemesConverter.build(map.get(key)); + } + public Builder clearSecuritySchemes() { + bitField0_ = (bitField0_ & ~0x00000400); + internalGetMutableSecuritySchemes().clear(); + return this; + } + /** + *
            +     * The security scheme details used for authenticating with this agent.
            +     * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + public Builder removeSecuritySchemes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableSecuritySchemes().ensureBuilderMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableSecuritySchemes() { + bitField0_ |= 0x00000400; + return internalGetMutableSecuritySchemes().ensureMessageMap(); + } + /** + *
            +     * The security scheme details used for authenticating with this agent.
            +     * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + public Builder putSecuritySchemes( + java.lang.String key, + org.a2aproject.sdk.compat03.grpc.SecurityScheme value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableSecuritySchemes().ensureBuilderMap() + .put(key, value); + bitField0_ |= 0x00000400; + return this; + } + /** + *
            +     * The security scheme details used for authenticating with this agent.
            +     * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + public Builder putAllSecuritySchemes( + java.util.Map values) { + for (java.util.Map.Entry e : values.entrySet()) { + if (e.getKey() == null || e.getValue() == null) { + throw new NullPointerException(); + } + } + internalGetMutableSecuritySchemes().ensureBuilderMap() + .putAll(values); + bitField0_ |= 0x00000400; + return this; + } + /** + *
            +     * The security scheme details used for authenticating with this agent.
            +     * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + public org.a2aproject.sdk.compat03.grpc.SecurityScheme.Builder putSecuritySchemesBuilderIfAbsent( + java.lang.String key) { + java.util.Map builderMap = internalGetMutableSecuritySchemes().ensureBuilderMap(); + org.a2aproject.sdk.compat03.grpc.SecuritySchemeOrBuilder entry = builderMap.get(key); + if (entry == null) { + entry = org.a2aproject.sdk.compat03.grpc.SecurityScheme.newBuilder(); + builderMap.put(key, entry); + } + if (entry instanceof org.a2aproject.sdk.compat03.grpc.SecurityScheme) { + entry = ((org.a2aproject.sdk.compat03.grpc.SecurityScheme) entry).toBuilder(); + builderMap.put(key, entry); + } + return (org.a2aproject.sdk.compat03.grpc.SecurityScheme.Builder) entry; + } + + private java.util.List security_ = + java.util.Collections.emptyList(); + private void ensureSecurityIsMutable() { + if (!((bitField0_ & 0x00000800) != 0)) { + security_ = new java.util.ArrayList(security_); + bitField0_ |= 0x00000800; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Security, org.a2aproject.sdk.compat03.grpc.Security.Builder, org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder> securityBuilder_; + + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public java.util.List getSecurityList() { + if (securityBuilder_ == null) { + return java.util.Collections.unmodifiableList(security_); + } else { + return securityBuilder_.getMessageList(); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public int getSecurityCount() { + if (securityBuilder_ == null) { + return security_.size(); + } else { + return securityBuilder_.getCount(); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public org.a2aproject.sdk.compat03.grpc.Security getSecurity(int index) { + if (securityBuilder_ == null) { + return security_.get(index); + } else { + return securityBuilder_.getMessage(index); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder setSecurity( + int index, org.a2aproject.sdk.compat03.grpc.Security value) { + if (securityBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSecurityIsMutable(); + security_.set(index, value); + onChanged(); + } else { + securityBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder setSecurity( + int index, org.a2aproject.sdk.compat03.grpc.Security.Builder builderForValue) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.set(index, builderForValue.build()); + onChanged(); + } else { + securityBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder addSecurity(org.a2aproject.sdk.compat03.grpc.Security value) { + if (securityBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSecurityIsMutable(); + security_.add(value); + onChanged(); + } else { + securityBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder addSecurity( + int index, org.a2aproject.sdk.compat03.grpc.Security value) { + if (securityBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSecurityIsMutable(); + security_.add(index, value); + onChanged(); + } else { + securityBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder addSecurity( + org.a2aproject.sdk.compat03.grpc.Security.Builder builderForValue) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.add(builderForValue.build()); + onChanged(); + } else { + securityBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder addSecurity( + int index, org.a2aproject.sdk.compat03.grpc.Security.Builder builderForValue) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.add(index, builderForValue.build()); + onChanged(); + } else { + securityBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder addAllSecurity( + java.lang.Iterable values) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, security_); + onChanged(); + } else { + securityBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder clearSecurity() { + if (securityBuilder_ == null) { + security_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000800); + onChanged(); + } else { + securityBuilder_.clear(); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public Builder removeSecurity(int index) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.remove(index); + onChanged(); + } else { + securityBuilder_.remove(index); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public org.a2aproject.sdk.compat03.grpc.Security.Builder getSecurityBuilder( + int index) { + return internalGetSecurityFieldBuilder().getBuilder(index); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder getSecurityOrBuilder( + int index) { + if (securityBuilder_ == null) { + return security_.get(index); } else { + return securityBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public java.util.List + getSecurityOrBuilderList() { + if (securityBuilder_ != null) { + return securityBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(security_); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public org.a2aproject.sdk.compat03.grpc.Security.Builder addSecurityBuilder() { + return internalGetSecurityFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.Security.getDefaultInstance()); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public org.a2aproject.sdk.compat03.grpc.Security.Builder addSecurityBuilder( + int index) { + return internalGetSecurityFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.Security.getDefaultInstance()); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security requirements for contacting the agent.
            +     * This list can be seen as an OR of ANDs. Each object in the list describes
            +     * one possible set of security requirements that must be present on a
            +     * request. This allows specifying, for example, "callers must either use
            +     * OAuth OR an API Key AND mTLS."
            +     * Example:
            +     * security {
            +     * schemes { key: "oauth" value { list: ["read"] } }
            +     * }
            +     * security {
            +     * schemes { key: "api-key" }
            +     * schemes { key: "mtls" }
            +     * }
            +     * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + public java.util.List + getSecurityBuilderList() { + return internalGetSecurityFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Security, org.a2aproject.sdk.compat03.grpc.Security.Builder, org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder> + internalGetSecurityFieldBuilder() { + if (securityBuilder_ == null) { + securityBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Security, org.a2aproject.sdk.compat03.grpc.Security.Builder, org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder>( + security_, + ((bitField0_ & 0x00000800) != 0), + getParentForChildren(), + isClean()); + security_ = null; + } + return securityBuilder_; + } + + private com.google.protobuf.LazyStringArrayList defaultInputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureDefaultInputModesIsMutable() { + if (!defaultInputModes_.isModifiable()) { + defaultInputModes_ = new com.google.protobuf.LazyStringArrayList(defaultInputModes_); + } + bitField0_ |= 0x00001000; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @return A list containing the defaultInputModes. + */ + public com.google.protobuf.ProtocolStringList + getDefaultInputModesList() { + defaultInputModes_.makeImmutable(); + return defaultInputModes_; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @return The count of defaultInputModes. + */ + public int getDefaultInputModesCount() { + return defaultInputModes_.size(); + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @param index The index of the element to return. + * @return The defaultInputModes at the given index. + */ + public java.lang.String getDefaultInputModes(int index) { + return defaultInputModes_.get(index); + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @param index The index of the value to return. + * @return The bytes of the defaultInputModes at the given index. + */ + public com.google.protobuf.ByteString + getDefaultInputModesBytes(int index) { + return defaultInputModes_.getByteString(index); + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @param index The index to set the value at. + * @param value The defaultInputModes to set. + * @return This builder for chaining. + */ + public Builder setDefaultInputModes( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureDefaultInputModesIsMutable(); + defaultInputModes_.set(index, value); + bitField0_ |= 0x00001000; + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @param value The defaultInputModes to add. + * @return This builder for chaining. + */ + public Builder addDefaultInputModes( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureDefaultInputModesIsMutable(); + defaultInputModes_.add(value); + bitField0_ |= 0x00001000; + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @param values The defaultInputModes to add. + * @return This builder for chaining. + */ + public Builder addAllDefaultInputModes( + java.lang.Iterable values) { + ensureDefaultInputModesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, defaultInputModes_); + bitField0_ |= 0x00001000; + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @return This builder for chaining. + */ + public Builder clearDefaultInputModes() { + defaultInputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00001000);; + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The set of interaction modes that the agent supports across all skills.
            +     * This can be overridden per skill. Defined as mime types.
            +     * 
            + * + * repeated string default_input_modes = 10; + * @param value The bytes of the defaultInputModes to add. + * @return This builder for chaining. + */ + public Builder addDefaultInputModesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureDefaultInputModesIsMutable(); + defaultInputModes_.add(value); + bitField0_ |= 0x00001000; + onChanged(); + return this; + } + + private com.google.protobuf.LazyStringArrayList defaultOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureDefaultOutputModesIsMutable() { + if (!defaultOutputModes_.isModifiable()) { + defaultOutputModes_ = new com.google.protobuf.LazyStringArrayList(defaultOutputModes_); + } + bitField0_ |= 0x00002000; + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @return A list containing the defaultOutputModes. + */ + public com.google.protobuf.ProtocolStringList + getDefaultOutputModesList() { + defaultOutputModes_.makeImmutable(); + return defaultOutputModes_; + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @return The count of defaultOutputModes. + */ + public int getDefaultOutputModesCount() { + return defaultOutputModes_.size(); + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @param index The index of the element to return. + * @return The defaultOutputModes at the given index. + */ + public java.lang.String getDefaultOutputModes(int index) { + return defaultOutputModes_.get(index); + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @param index The index of the value to return. + * @return The bytes of the defaultOutputModes at the given index. + */ + public com.google.protobuf.ByteString + getDefaultOutputModesBytes(int index) { + return defaultOutputModes_.getByteString(index); + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @param index The index to set the value at. + * @param value The defaultOutputModes to set. + * @return This builder for chaining. + */ + public Builder setDefaultOutputModes( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureDefaultOutputModesIsMutable(); + defaultOutputModes_.set(index, value); + bitField0_ |= 0x00002000; + onChanged(); + return this; + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @param value The defaultOutputModes to add. + * @return This builder for chaining. + */ + public Builder addDefaultOutputModes( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureDefaultOutputModesIsMutable(); + defaultOutputModes_.add(value); + bitField0_ |= 0x00002000; + onChanged(); + return this; + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @param values The defaultOutputModes to add. + * @return This builder for chaining. + */ + public Builder addAllDefaultOutputModes( + java.lang.Iterable values) { + ensureDefaultOutputModesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, defaultOutputModes_); + bitField0_ |= 0x00002000; + onChanged(); + return this; + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @return This builder for chaining. + */ + public Builder clearDefaultOutputModes() { + defaultOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00002000);; + onChanged(); + return this; + } + /** + *
            +     * The mime types supported as outputs from this agent.
            +     * 
            + * + * repeated string default_output_modes = 11; + * @param value The bytes of the defaultOutputModes to add. + * @return This builder for chaining. + */ + public Builder addDefaultOutputModesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureDefaultOutputModesIsMutable(); + defaultOutputModes_.add(value); + bitField0_ |= 0x00002000; + onChanged(); + return this; + } + + private java.util.List skills_ = + java.util.Collections.emptyList(); + private void ensureSkillsIsMutable() { + if (!((bitField0_ & 0x00004000) != 0)) { + skills_ = new java.util.ArrayList(skills_); + bitField0_ |= 0x00004000; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentSkill, org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder, org.a2aproject.sdk.compat03.grpc.AgentSkillOrBuilder> skillsBuilder_; + + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public java.util.List getSkillsList() { + if (skillsBuilder_ == null) { + return java.util.Collections.unmodifiableList(skills_); + } else { + return skillsBuilder_.getMessageList(); + } + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public int getSkillsCount() { + if (skillsBuilder_ == null) { + return skills_.size(); + } else { + return skillsBuilder_.getCount(); + } + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public org.a2aproject.sdk.compat03.grpc.AgentSkill getSkills(int index) { + if (skillsBuilder_ == null) { + return skills_.get(index); + } else { + return skillsBuilder_.getMessage(index); + } + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder setSkills( + int index, org.a2aproject.sdk.compat03.grpc.AgentSkill value) { + if (skillsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSkillsIsMutable(); + skills_.set(index, value); + onChanged(); + } else { + skillsBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder setSkills( + int index, org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder builderForValue) { + if (skillsBuilder_ == null) { + ensureSkillsIsMutable(); + skills_.set(index, builderForValue.build()); + onChanged(); + } else { + skillsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder addSkills(org.a2aproject.sdk.compat03.grpc.AgentSkill value) { + if (skillsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSkillsIsMutable(); + skills_.add(value); + onChanged(); + } else { + skillsBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder addSkills( + int index, org.a2aproject.sdk.compat03.grpc.AgentSkill value) { + if (skillsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSkillsIsMutable(); + skills_.add(index, value); + onChanged(); + } else { + skillsBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder addSkills( + org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder builderForValue) { + if (skillsBuilder_ == null) { + ensureSkillsIsMutable(); + skills_.add(builderForValue.build()); + onChanged(); + } else { + skillsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder addSkills( + int index, org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder builderForValue) { + if (skillsBuilder_ == null) { + ensureSkillsIsMutable(); + skills_.add(index, builderForValue.build()); + onChanged(); + } else { + skillsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder addAllSkills( + java.lang.Iterable values) { + if (skillsBuilder_ == null) { + ensureSkillsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, skills_); + onChanged(); + } else { + skillsBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder clearSkills() { + if (skillsBuilder_ == null) { + skills_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00004000); + onChanged(); + } else { + skillsBuilder_.clear(); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public Builder removeSkills(int index) { + if (skillsBuilder_ == null) { + ensureSkillsIsMutable(); + skills_.remove(index); + onChanged(); + } else { + skillsBuilder_.remove(index); + } + return this; + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder getSkillsBuilder( + int index) { + return internalGetSkillsFieldBuilder().getBuilder(index); + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public org.a2aproject.sdk.compat03.grpc.AgentSkillOrBuilder getSkillsOrBuilder( + int index) { + if (skillsBuilder_ == null) { + return skills_.get(index); } else { + return skillsBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public java.util.List + getSkillsOrBuilderList() { + if (skillsBuilder_ != null) { + return skillsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(skills_); + } + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder addSkillsBuilder() { + return internalGetSkillsFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.AgentSkill.getDefaultInstance()); + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder addSkillsBuilder( + int index) { + return internalGetSkillsFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.AgentSkill.getDefaultInstance()); + } + /** + *
            +     * Skills represent a unit of ability an agent can perform. This may
            +     * somewhat abstract but represents a more focused set of actions that the
            +     * agent is highly likely to succeed at.
            +     * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + public java.util.List + getSkillsBuilderList() { + return internalGetSkillsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentSkill, org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder, org.a2aproject.sdk.compat03.grpc.AgentSkillOrBuilder> + internalGetSkillsFieldBuilder() { + if (skillsBuilder_ == null) { + skillsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentSkill, org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder, org.a2aproject.sdk.compat03.grpc.AgentSkillOrBuilder>( + skills_, + ((bitField0_ & 0x00004000) != 0), + getParentForChildren(), + isClean()); + skills_ = null; + } + return skillsBuilder_; + } + + private boolean supportsAuthenticatedExtendedCard_ ; + /** + *
            +     * Whether the agent supports providing an extended agent card when
            +     * the user is authenticated, i.e. is the card from .well-known
            +     * different than the card from GetAgentCard.
            +     * 
            + * + * bool supports_authenticated_extended_card = 13; + * @return The supportsAuthenticatedExtendedCard. + */ + @java.lang.Override + public boolean getSupportsAuthenticatedExtendedCard() { + return supportsAuthenticatedExtendedCard_; + } + /** + *
            +     * Whether the agent supports providing an extended agent card when
            +     * the user is authenticated, i.e. is the card from .well-known
            +     * different than the card from GetAgentCard.
            +     * 
            + * + * bool supports_authenticated_extended_card = 13; + * @param value The supportsAuthenticatedExtendedCard to set. + * @return This builder for chaining. + */ + public Builder setSupportsAuthenticatedExtendedCard(boolean value) { + + supportsAuthenticatedExtendedCard_ = value; + bitField0_ |= 0x00008000; + onChanged(); + return this; + } + /** + *
            +     * Whether the agent supports providing an extended agent card when
            +     * the user is authenticated, i.e. is the card from .well-known
            +     * different than the card from GetAgentCard.
            +     * 
            + * + * bool supports_authenticated_extended_card = 13; + * @return This builder for chaining. + */ + public Builder clearSupportsAuthenticatedExtendedCard() { + bitField0_ = (bitField0_ & ~0x00008000); + supportsAuthenticatedExtendedCard_ = false; + onChanged(); + return this; + } + + private java.util.List signatures_ = + java.util.Collections.emptyList(); + private void ensureSignaturesIsMutable() { + if (!((bitField0_ & 0x00010000) != 0)) { + signatures_ = new java.util.ArrayList(signatures_); + bitField0_ |= 0x00010000; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentCardSignature, org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder, org.a2aproject.sdk.compat03.grpc.AgentCardSignatureOrBuilder> signaturesBuilder_; + + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public java.util.List getSignaturesList() { + if (signaturesBuilder_ == null) { + return java.util.Collections.unmodifiableList(signatures_); + } else { + return signaturesBuilder_.getMessageList(); + } + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public int getSignaturesCount() { + if (signaturesBuilder_ == null) { + return signatures_.size(); + } else { + return signaturesBuilder_.getCount(); + } + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature getSignatures(int index) { + if (signaturesBuilder_ == null) { + return signatures_.get(index); + } else { + return signaturesBuilder_.getMessage(index); + } + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder setSignatures( + int index, org.a2aproject.sdk.compat03.grpc.AgentCardSignature value) { + if (signaturesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSignaturesIsMutable(); + signatures_.set(index, value); + onChanged(); + } else { + signaturesBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder setSignatures( + int index, org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder builderForValue) { + if (signaturesBuilder_ == null) { + ensureSignaturesIsMutable(); + signatures_.set(index, builderForValue.build()); + onChanged(); + } else { + signaturesBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder addSignatures(org.a2aproject.sdk.compat03.grpc.AgentCardSignature value) { + if (signaturesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSignaturesIsMutable(); + signatures_.add(value); + onChanged(); + } else { + signaturesBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder addSignatures( + int index, org.a2aproject.sdk.compat03.grpc.AgentCardSignature value) { + if (signaturesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSignaturesIsMutable(); + signatures_.add(index, value); + onChanged(); + } else { + signaturesBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder addSignatures( + org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder builderForValue) { + if (signaturesBuilder_ == null) { + ensureSignaturesIsMutable(); + signatures_.add(builderForValue.build()); + onChanged(); + } else { + signaturesBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder addSignatures( + int index, org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder builderForValue) { + if (signaturesBuilder_ == null) { + ensureSignaturesIsMutable(); + signatures_.add(index, builderForValue.build()); + onChanged(); + } else { + signaturesBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder addAllSignatures( + java.lang.Iterable values) { + if (signaturesBuilder_ == null) { + ensureSignaturesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, signatures_); + onChanged(); + } else { + signaturesBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder clearSignatures() { + if (signaturesBuilder_ == null) { + signatures_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00010000); + onChanged(); + } else { + signaturesBuilder_.clear(); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public Builder removeSignatures(int index) { + if (signaturesBuilder_ == null) { + ensureSignaturesIsMutable(); + signatures_.remove(index); + onChanged(); + } else { + signaturesBuilder_.remove(index); + } + return this; + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder getSignaturesBuilder( + int index) { + return internalGetSignaturesFieldBuilder().getBuilder(index); + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public org.a2aproject.sdk.compat03.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( + int index) { + if (signaturesBuilder_ == null) { + return signatures_.get(index); } else { + return signaturesBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public java.util.List + getSignaturesOrBuilderList() { + if (signaturesBuilder_ != null) { + return signaturesBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(signatures_); + } + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder addSignaturesBuilder() { + return internalGetSignaturesFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.AgentCardSignature.getDefaultInstance()); + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder addSignaturesBuilder( + int index) { + return internalGetSignaturesFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.AgentCardSignature.getDefaultInstance()); + } + /** + *
            +     * JSON Web Signatures computed for this AgentCard.
            +     * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + public java.util.List + getSignaturesBuilderList() { + return internalGetSignaturesFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentCardSignature, org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder, org.a2aproject.sdk.compat03.grpc.AgentCardSignatureOrBuilder> + internalGetSignaturesFieldBuilder() { + if (signaturesBuilder_ == null) { + signaturesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AgentCardSignature, org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder, org.a2aproject.sdk.compat03.grpc.AgentCardSignatureOrBuilder>( + signatures_, + ((bitField0_ & 0x00010000) != 0), + getParentForChildren(), + isClean()); + signatures_ = null; + } + return signaturesBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCard) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AgentCard) + private static final org.a2aproject.sdk.compat03.grpc.AgentCard DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AgentCard(); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCard getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AgentCard parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCard getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardOrBuilder.java new file mode 100644 index 000000000..43a03abd3 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardOrBuilder.java @@ -0,0 +1,626 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AgentCardOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCard) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The version of the A2A protocol this agent supports.
            +   * 
            + * + * string protocol_version = 16; + * @return The protocolVersion. + */ + java.lang.String getProtocolVersion(); + /** + *
            +   * The version of the A2A protocol this agent supports.
            +   * 
            + * + * string protocol_version = 16; + * @return The bytes for protocolVersion. + */ + com.google.protobuf.ByteString + getProtocolVersionBytes(); + + /** + *
            +   * A human readable name for the agent.
            +   * Example: "Recipe Agent"
            +   * 
            + * + * string name = 1; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * A human readable name for the agent.
            +   * Example: "Recipe Agent"
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + *
            +   * A description of the agent's domain of action/solution space.
            +   * Example: "Agent that helps users with recipes and cooking."
            +   * 
            + * + * string description = 2; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * A description of the agent's domain of action/solution space.
            +   * Example: "Agent that helps users with recipes and cooking."
            +   * 
            + * + * string description = 2; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + *
            +   * A URL to the address the agent is hosted at. This represents the
            +   * preferred endpoint as declared by the agent.
            +   * 
            + * + * string url = 3; + * @return The url. + */ + java.lang.String getUrl(); + /** + *
            +   * A URL to the address the agent is hosted at. This represents the
            +   * preferred endpoint as declared by the agent.
            +   * 
            + * + * string url = 3; + * @return The bytes for url. + */ + com.google.protobuf.ByteString + getUrlBytes(); + + /** + *
            +   * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +   * 
            + * + * string preferred_transport = 14; + * @return The preferredTransport. + */ + java.lang.String getPreferredTransport(); + /** + *
            +   * The transport of the preferred endpoint. If empty, defaults to JSONRPC.
            +   * 
            + * + * string preferred_transport = 14; + * @return The bytes for preferredTransport. + */ + com.google.protobuf.ByteString + getPreferredTransportBytes(); + + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + java.util.List + getAdditionalInterfacesList(); + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + org.a2aproject.sdk.compat03.grpc.AgentInterface getAdditionalInterfaces(int index); + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + int getAdditionalInterfacesCount(); + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + java.util.List + getAdditionalInterfacesOrBuilderList(); + /** + *
            +   * Announcement of additional supported transports. Client can use any of
            +   * the supported transports.
            +   * 
            + * + * repeated .a2a.v1.AgentInterface additional_interfaces = 15; + */ + org.a2aproject.sdk.compat03.grpc.AgentInterfaceOrBuilder getAdditionalInterfacesOrBuilder( + int index); + + /** + *
            +   * The service provider of the agent.
            +   * 
            + * + * .a2a.v1.AgentProvider provider = 4; + * @return Whether the provider field is set. + */ + boolean hasProvider(); + /** + *
            +   * The service provider of the agent.
            +   * 
            + * + * .a2a.v1.AgentProvider provider = 4; + * @return The provider. + */ + org.a2aproject.sdk.compat03.grpc.AgentProvider getProvider(); + /** + *
            +   * The service provider of the agent.
            +   * 
            + * + * .a2a.v1.AgentProvider provider = 4; + */ + org.a2aproject.sdk.compat03.grpc.AgentProviderOrBuilder getProviderOrBuilder(); + + /** + *
            +   * The version of the agent.
            +   * Example: "1.0.0"
            +   * 
            + * + * string version = 5; + * @return The version. + */ + java.lang.String getVersion(); + /** + *
            +   * The version of the agent.
            +   * Example: "1.0.0"
            +   * 
            + * + * string version = 5; + * @return The bytes for version. + */ + com.google.protobuf.ByteString + getVersionBytes(); + + /** + *
            +   * A url to provide additional documentation about the agent.
            +   * 
            + * + * string documentation_url = 6; + * @return The documentationUrl. + */ + java.lang.String getDocumentationUrl(); + /** + *
            +   * A url to provide additional documentation about the agent.
            +   * 
            + * + * string documentation_url = 6; + * @return The bytes for documentationUrl. + */ + com.google.protobuf.ByteString + getDocumentationUrlBytes(); + + /** + *
            +   * A2A Capability set supported by the agent.
            +   * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + * @return Whether the capabilities field is set. + */ + boolean hasCapabilities(); + /** + *
            +   * A2A Capability set supported by the agent.
            +   * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + * @return The capabilities. + */ + org.a2aproject.sdk.compat03.grpc.AgentCapabilities getCapabilities(); + /** + *
            +   * A2A Capability set supported by the agent.
            +   * 
            + * + * .a2a.v1.AgentCapabilities capabilities = 7; + */ + org.a2aproject.sdk.compat03.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder(); + + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + int getSecuritySchemesCount(); + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + boolean containsSecuritySchemes( + java.lang.String key); + /** + * Use {@link #getSecuritySchemesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getSecuritySchemes(); + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + java.util.Map + getSecuritySchemesMap(); + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + /* nullable */ +org.a2aproject.sdk.compat03.grpc.SecurityScheme getSecuritySchemesOrDefault( + java.lang.String key, + /* nullable */ +org.a2aproject.sdk.compat03.grpc.SecurityScheme defaultValue); + /** + *
            +   * The security scheme details used for authenticating with this agent.
            +   * 
            + * + * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; + */ + org.a2aproject.sdk.compat03.grpc.SecurityScheme getSecuritySchemesOrThrow( + java.lang.String key); + + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + java.util.List + getSecurityList(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + org.a2aproject.sdk.compat03.grpc.Security getSecurity(int index); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + int getSecurityCount(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + java.util.List + getSecurityOrBuilderList(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security requirements for contacting the agent.
            +   * This list can be seen as an OR of ANDs. Each object in the list describes
            +   * one possible set of security requirements that must be present on a
            +   * request. This allows specifying, for example, "callers must either use
            +   * OAuth OR an API Key AND mTLS."
            +   * Example:
            +   * security {
            +   * schemes { key: "oauth" value { list: ["read"] } }
            +   * }
            +   * security {
            +   * schemes { key: "api-key" }
            +   * schemes { key: "mtls" }
            +   * }
            +   * 
            + * + * repeated .a2a.v1.Security security = 9; + */ + org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder getSecurityOrBuilder( + int index); + + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The set of interaction modes that the agent supports across all skills.
            +   * This can be overridden per skill. Defined as mime types.
            +   * 
            + * + * repeated string default_input_modes = 10; + * @return A list containing the defaultInputModes. + */ + java.util.List + getDefaultInputModesList(); + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The set of interaction modes that the agent supports across all skills.
            +   * This can be overridden per skill. Defined as mime types.
            +   * 
            + * + * repeated string default_input_modes = 10; + * @return The count of defaultInputModes. + */ + int getDefaultInputModesCount(); + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The set of interaction modes that the agent supports across all skills.
            +   * This can be overridden per skill. Defined as mime types.
            +   * 
            + * + * repeated string default_input_modes = 10; + * @param index The index of the element to return. + * @return The defaultInputModes at the given index. + */ + java.lang.String getDefaultInputModes(int index); + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The set of interaction modes that the agent supports across all skills.
            +   * This can be overridden per skill. Defined as mime types.
            +   * 
            + * + * repeated string default_input_modes = 10; + * @param index The index of the value to return. + * @return The bytes of the defaultInputModes at the given index. + */ + com.google.protobuf.ByteString + getDefaultInputModesBytes(int index); + + /** + *
            +   * The mime types supported as outputs from this agent.
            +   * 
            + * + * repeated string default_output_modes = 11; + * @return A list containing the defaultOutputModes. + */ + java.util.List + getDefaultOutputModesList(); + /** + *
            +   * The mime types supported as outputs from this agent.
            +   * 
            + * + * repeated string default_output_modes = 11; + * @return The count of defaultOutputModes. + */ + int getDefaultOutputModesCount(); + /** + *
            +   * The mime types supported as outputs from this agent.
            +   * 
            + * + * repeated string default_output_modes = 11; + * @param index The index of the element to return. + * @return The defaultOutputModes at the given index. + */ + java.lang.String getDefaultOutputModes(int index); + /** + *
            +   * The mime types supported as outputs from this agent.
            +   * 
            + * + * repeated string default_output_modes = 11; + * @param index The index of the value to return. + * @return The bytes of the defaultOutputModes at the given index. + */ + com.google.protobuf.ByteString + getDefaultOutputModesBytes(int index); + + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + java.util.List + getSkillsList(); + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + org.a2aproject.sdk.compat03.grpc.AgentSkill getSkills(int index); + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + int getSkillsCount(); + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + java.util.List + getSkillsOrBuilderList(); + /** + *
            +   * Skills represent a unit of ability an agent can perform. This may
            +   * somewhat abstract but represents a more focused set of actions that the
            +   * agent is highly likely to succeed at.
            +   * 
            + * + * repeated .a2a.v1.AgentSkill skills = 12; + */ + org.a2aproject.sdk.compat03.grpc.AgentSkillOrBuilder getSkillsOrBuilder( + int index); + + /** + *
            +   * Whether the agent supports providing an extended agent card when
            +   * the user is authenticated, i.e. is the card from .well-known
            +   * different than the card from GetAgentCard.
            +   * 
            + * + * bool supports_authenticated_extended_card = 13; + * @return The supportsAuthenticatedExtendedCard. + */ + boolean getSupportsAuthenticatedExtendedCard(); + + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + java.util.List + getSignaturesList(); + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + org.a2aproject.sdk.compat03.grpc.AgentCardSignature getSignatures(int index); + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + int getSignaturesCount(); + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + java.util.List + getSignaturesOrBuilderList(); + /** + *
            +   * JSON Web Signatures computed for this AgentCard.
            +   * 
            + * + * repeated .a2a.v1.AgentCardSignature signatures = 17; + */ + org.a2aproject.sdk.compat03.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( + int index); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardSignature.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardSignature.java new file mode 100644 index 000000000..8fa5c42dc --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardSignature.java @@ -0,0 +1,952 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * AgentCardSignature represents a JWS signature of an AgentCard.
            + * This follows the JSON format of an RFC 7515 JSON Web Signature (JWS).
            + * 
            + * + * Protobuf type {@code a2a.v1.AgentCardSignature} + */ +@com.google.protobuf.Generated +public final class AgentCardSignature extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AgentCardSignature) + AgentCardSignatureOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AgentCardSignature"); + } + // Use AgentCardSignature.newBuilder() to construct. + private AgentCardSignature(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AgentCardSignature() { + protected_ = ""; + signature_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentCardSignature.class, org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder.class); + } + + private int bitField0_; + public static final int PROTECTED_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object protected_ = ""; + /** + *
            +   * The protected JWS header for the signature. This is always a
            +   * base64url-encoded JSON object. Required.
            +   * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The protected. + */ + @java.lang.Override + public java.lang.String getProtected() { + java.lang.Object ref = protected_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + protected_ = s; + return s; + } + } + /** + *
            +   * The protected JWS header for the signature. This is always a
            +   * base64url-encoded JSON object. Required.
            +   * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for protected. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getProtectedBytes() { + java.lang.Object ref = protected_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + protected_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SIGNATURE_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object signature_ = ""; + /** + *
            +   * The computed signature, base64url-encoded. Required.
            +   * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The signature. + */ + @java.lang.Override + public java.lang.String getSignature() { + java.lang.Object ref = signature_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + signature_ = s; + return s; + } + } + /** + *
            +   * The computed signature, base64url-encoded. Required.
            +   * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for signature. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getSignatureBytes() { + java.lang.Object ref = signature_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + signature_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int HEADER_FIELD_NUMBER = 3; + private com.google.protobuf.Struct header_; + /** + *
            +   * The unprotected JWS header values.
            +   * 
            + * + * .google.protobuf.Struct header = 3; + * @return Whether the header field is set. + */ + @java.lang.Override + public boolean hasHeader() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * The unprotected JWS header values.
            +   * 
            + * + * .google.protobuf.Struct header = 3; + * @return The header. + */ + @java.lang.Override + public com.google.protobuf.Struct getHeader() { + return header_ == null ? com.google.protobuf.Struct.getDefaultInstance() : header_; + } + /** + *
            +   * The unprotected JWS header values.
            +   * 
            + * + * .google.protobuf.Struct header = 3; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getHeaderOrBuilder() { + return header_ == null ? com.google.protobuf.Struct.getDefaultInstance() : header_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protected_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, protected_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(signature_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, signature_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(3, getHeader()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protected_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, protected_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(signature_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, signature_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getHeader()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AgentCardSignature)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AgentCardSignature other = (org.a2aproject.sdk.compat03.grpc.AgentCardSignature) obj; + + if (!getProtected() + .equals(other.getProtected())) return false; + if (!getSignature() + .equals(other.getSignature())) return false; + if (hasHeader() != other.hasHeader()) return false; + if (hasHeader()) { + if (!getHeader() + .equals(other.getHeader())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + PROTECTED_FIELD_NUMBER; + hash = (53 * hash) + getProtected().hashCode(); + hash = (37 * hash) + SIGNATURE_FIELD_NUMBER; + hash = (53 * hash) + getSignature().hashCode(); + if (hasHeader()) { + hash = (37 * hash) + HEADER_FIELD_NUMBER; + hash = (53 * hash) + getHeader().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AgentCardSignature prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * AgentCardSignature represents a JWS signature of an AgentCard.
            +   * This follows the JSON format of an RFC 7515 JSON Web Signature (JWS).
            +   * 
            + * + * Protobuf type {@code a2a.v1.AgentCardSignature} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCardSignature) + org.a2aproject.sdk.compat03.grpc.AgentCardSignatureOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentCardSignature.class, org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AgentCardSignature.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetHeaderFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + protected_ = ""; + signature_ = ""; + header_ = null; + if (headerBuilder_ != null) { + headerBuilder_.dispose(); + headerBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AgentCardSignature.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature build() { + org.a2aproject.sdk.compat03.grpc.AgentCardSignature result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature buildPartial() { + org.a2aproject.sdk.compat03.grpc.AgentCardSignature result = new org.a2aproject.sdk.compat03.grpc.AgentCardSignature(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AgentCardSignature result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.protected_ = protected_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.signature_ = signature_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000004) != 0)) { + result.header_ = headerBuilder_ == null + ? header_ + : headerBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AgentCardSignature) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AgentCardSignature)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AgentCardSignature other) { + if (other == org.a2aproject.sdk.compat03.grpc.AgentCardSignature.getDefaultInstance()) return this; + if (!other.getProtected().isEmpty()) { + protected_ = other.protected_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getSignature().isEmpty()) { + signature_ = other.signature_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (other.hasHeader()) { + mergeHeader(other.getHeader()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + protected_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + signature_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetHeaderFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object protected_ = ""; + /** + *
            +     * The protected JWS header for the signature. This is always a
            +     * base64url-encoded JSON object. Required.
            +     * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The protected. + */ + public java.lang.String getProtected() { + java.lang.Object ref = protected_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + protected_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The protected JWS header for the signature. This is always a
            +     * base64url-encoded JSON object. Required.
            +     * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for protected. + */ + public com.google.protobuf.ByteString + getProtectedBytes() { + java.lang.Object ref = protected_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + protected_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The protected JWS header for the signature. This is always a
            +     * base64url-encoded JSON object. Required.
            +     * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The protected to set. + * @return This builder for chaining. + */ + public Builder setProtected( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + protected_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The protected JWS header for the signature. This is always a
            +     * base64url-encoded JSON object. Required.
            +     * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearProtected() { + protected_ = getDefaultInstance().getProtected(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The protected JWS header for the signature. This is always a
            +     * base64url-encoded JSON object. Required.
            +     * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for protected to set. + * @return This builder for chaining. + */ + public Builder setProtectedBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + protected_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object signature_ = ""; + /** + *
            +     * The computed signature, base64url-encoded. Required.
            +     * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The signature. + */ + public java.lang.String getSignature() { + java.lang.Object ref = signature_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + signature_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The computed signature, base64url-encoded. Required.
            +     * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for signature. + */ + public com.google.protobuf.ByteString + getSignatureBytes() { + java.lang.Object ref = signature_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + signature_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The computed signature, base64url-encoded. Required.
            +     * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @param value The signature to set. + * @return This builder for chaining. + */ + public Builder setSignature( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + signature_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The computed signature, base64url-encoded. Required.
            +     * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearSignature() { + signature_ = getDefaultInstance().getSignature(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The computed signature, base64url-encoded. Required.
            +     * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for signature to set. + * @return This builder for chaining. + */ + public Builder setSignatureBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + signature_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private com.google.protobuf.Struct header_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> headerBuilder_; + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + * @return Whether the header field is set. + */ + public boolean hasHeader() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + * @return The header. + */ + public com.google.protobuf.Struct getHeader() { + if (headerBuilder_ == null) { + return header_ == null ? com.google.protobuf.Struct.getDefaultInstance() : header_; + } else { + return headerBuilder_.getMessage(); + } + } + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + */ + public Builder setHeader(com.google.protobuf.Struct value) { + if (headerBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + header_ = value; + } else { + headerBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + */ + public Builder setHeader( + com.google.protobuf.Struct.Builder builderForValue) { + if (headerBuilder_ == null) { + header_ = builderForValue.build(); + } else { + headerBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + */ + public Builder mergeHeader(com.google.protobuf.Struct value) { + if (headerBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + header_ != null && + header_ != com.google.protobuf.Struct.getDefaultInstance()) { + getHeaderBuilder().mergeFrom(value); + } else { + header_ = value; + } + } else { + headerBuilder_.mergeFrom(value); + } + if (header_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + */ + public Builder clearHeader() { + bitField0_ = (bitField0_ & ~0x00000004); + header_ = null; + if (headerBuilder_ != null) { + headerBuilder_.dispose(); + headerBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + */ + public com.google.protobuf.Struct.Builder getHeaderBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return internalGetHeaderFieldBuilder().getBuilder(); + } + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + */ + public com.google.protobuf.StructOrBuilder getHeaderOrBuilder() { + if (headerBuilder_ != null) { + return headerBuilder_.getMessageOrBuilder(); + } else { + return header_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : header_; + } + } + /** + *
            +     * The unprotected JWS header values.
            +     * 
            + * + * .google.protobuf.Struct header = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetHeaderFieldBuilder() { + if (headerBuilder_ == null) { + headerBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getHeader(), + getParentForChildren(), + isClean()); + header_ = null; + } + return headerBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCardSignature) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AgentCardSignature) + private static final org.a2aproject.sdk.compat03.grpc.AgentCardSignature DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AgentCardSignature(); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentCardSignature getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AgentCardSignature parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentCardSignature getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardSignatureOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardSignatureOrBuilder.java new file mode 100644 index 000000000..eb40168b0 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentCardSignatureOrBuilder.java @@ -0,0 +1,81 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AgentCardSignatureOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCardSignature) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The protected JWS header for the signature. This is always a
            +   * base64url-encoded JSON object. Required.
            +   * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The protected. + */ + java.lang.String getProtected(); + /** + *
            +   * The protected JWS header for the signature. This is always a
            +   * base64url-encoded JSON object. Required.
            +   * 
            + * + * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for protected. + */ + com.google.protobuf.ByteString + getProtectedBytes(); + + /** + *
            +   * The computed signature, base64url-encoded. Required.
            +   * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The signature. + */ + java.lang.String getSignature(); + /** + *
            +   * The computed signature, base64url-encoded. Required.
            +   * 
            + * + * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for signature. + */ + com.google.protobuf.ByteString + getSignatureBytes(); + + /** + *
            +   * The unprotected JWS header values.
            +   * 
            + * + * .google.protobuf.Struct header = 3; + * @return Whether the header field is set. + */ + boolean hasHeader(); + /** + *
            +   * The unprotected JWS header values.
            +   * 
            + * + * .google.protobuf.Struct header = 3; + * @return The header. + */ + com.google.protobuf.Struct getHeader(); + /** + *
            +   * The unprotected JWS header values.
            +   * 
            + * + * .google.protobuf.Struct header = 3; + */ + com.google.protobuf.StructOrBuilder getHeaderOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentExtension.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentExtension.java new file mode 100644 index 000000000..a378d85b9 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentExtension.java @@ -0,0 +1,1044 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * A declaration of an extension supported by an Agent.
            + * 
            + * + * Protobuf type {@code a2a.v1.AgentExtension} + */ +@com.google.protobuf.Generated +public final class AgentExtension extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AgentExtension) + AgentExtensionOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AgentExtension"); + } + // Use AgentExtension.newBuilder() to construct. + private AgentExtension(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AgentExtension() { + uri_ = ""; + description_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentExtension_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentExtension_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentExtension.class, org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder.class); + } + + private int bitField0_; + public static final int URI_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object uri_ = ""; + /** + *
            +   * The URI of the extension.
            +   * Example: "https://developers.google.com/identity/protocols/oauth2"
            +   * 
            + * + * string uri = 1; + * @return The uri. + */ + @java.lang.Override + public java.lang.String getUri() { + java.lang.Object ref = uri_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + uri_ = s; + return s; + } + } + /** + *
            +   * The URI of the extension.
            +   * Example: "https://developers.google.com/identity/protocols/oauth2"
            +   * 
            + * + * string uri = 1; + * @return The bytes for uri. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getUriBytes() { + java.lang.Object ref = uri_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + uri_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DESCRIPTION_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * A description of how this agent uses this extension.
            +   * Example: "Google OAuth 2.0 authentication"
            +   * 
            + * + * string description = 2; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * A description of how this agent uses this extension.
            +   * Example: "Google OAuth 2.0 authentication"
            +   * 
            + * + * string description = 2; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REQUIRED_FIELD_NUMBER = 3; + private boolean required_ = false; + /** + *
            +   * Whether the client must follow specific requirements of the extension.
            +   * Example: false
            +   * 
            + * + * bool required = 3; + * @return The required. + */ + @java.lang.Override + public boolean getRequired() { + return required_; + } + + public static final int PARAMS_FIELD_NUMBER = 4; + private com.google.protobuf.Struct params_; + /** + *
            +   * Optional configuration for the extension.
            +   * 
            + * + * .google.protobuf.Struct params = 4; + * @return Whether the params field is set. + */ + @java.lang.Override + public boolean hasParams() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * Optional configuration for the extension.
            +   * 
            + * + * .google.protobuf.Struct params = 4; + * @return The params. + */ + @java.lang.Override + public com.google.protobuf.Struct getParams() { + return params_ == null ? com.google.protobuf.Struct.getDefaultInstance() : params_; + } + /** + *
            +   * Optional configuration for the extension.
            +   * 
            + * + * .google.protobuf.Struct params = 4; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getParamsOrBuilder() { + return params_ == null ? com.google.protobuf.Struct.getDefaultInstance() : params_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(uri_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, uri_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, description_); + } + if (required_ != false) { + output.writeBool(3, required_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(4, getParams()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(uri_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, uri_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, description_); + } + if (required_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(3, required_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getParams()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AgentExtension)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AgentExtension other = (org.a2aproject.sdk.compat03.grpc.AgentExtension) obj; + + if (!getUri() + .equals(other.getUri())) return false; + if (!getDescription() + .equals(other.getDescription())) return false; + if (getRequired() + != other.getRequired()) return false; + if (hasParams() != other.hasParams()) return false; + if (hasParams()) { + if (!getParams() + .equals(other.getParams())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + URI_FIELD_NUMBER; + hash = (53 * hash) + getUri().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + hash = (37 * hash) + REQUIRED_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getRequired()); + if (hasParams()) { + hash = (37 * hash) + PARAMS_FIELD_NUMBER; + hash = (53 * hash) + getParams().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentExtension parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AgentExtension prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * A declaration of an extension supported by an Agent.
            +   * 
            + * + * Protobuf type {@code a2a.v1.AgentExtension} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AgentExtension) + org.a2aproject.sdk.compat03.grpc.AgentExtensionOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentExtension_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentExtension_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentExtension.class, org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AgentExtension.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetParamsFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + uri_ = ""; + description_ = ""; + required_ = false; + params_ = null; + if (paramsBuilder_ != null) { + paramsBuilder_.dispose(); + paramsBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AgentExtension_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentExtension getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AgentExtension.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentExtension build() { + org.a2aproject.sdk.compat03.grpc.AgentExtension result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentExtension buildPartial() { + org.a2aproject.sdk.compat03.grpc.AgentExtension result = new org.a2aproject.sdk.compat03.grpc.AgentExtension(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AgentExtension result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.uri_ = uri_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.description_ = description_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.required_ = required_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000008) != 0)) { + result.params_ = paramsBuilder_ == null + ? params_ + : paramsBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AgentExtension) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AgentExtension)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AgentExtension other) { + if (other == org.a2aproject.sdk.compat03.grpc.AgentExtension.getDefaultInstance()) return this; + if (!other.getUri().isEmpty()) { + uri_ = other.uri_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (other.getRequired() != false) { + setRequired(other.getRequired()); + } + if (other.hasParams()) { + mergeParams(other.getParams()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + uri_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 24: { + required_ = input.readBool(); + bitField0_ |= 0x00000004; + break; + } // case 24 + case 34: { + input.readMessage( + internalGetParamsFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000008; + break; + } // case 34 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object uri_ = ""; + /** + *
            +     * The URI of the extension.
            +     * Example: "https://developers.google.com/identity/protocols/oauth2"
            +     * 
            + * + * string uri = 1; + * @return The uri. + */ + public java.lang.String getUri() { + java.lang.Object ref = uri_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + uri_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The URI of the extension.
            +     * Example: "https://developers.google.com/identity/protocols/oauth2"
            +     * 
            + * + * string uri = 1; + * @return The bytes for uri. + */ + public com.google.protobuf.ByteString + getUriBytes() { + java.lang.Object ref = uri_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + uri_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The URI of the extension.
            +     * Example: "https://developers.google.com/identity/protocols/oauth2"
            +     * 
            + * + * string uri = 1; + * @param value The uri to set. + * @return This builder for chaining. + */ + public Builder setUri( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + uri_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The URI of the extension.
            +     * Example: "https://developers.google.com/identity/protocols/oauth2"
            +     * 
            + * + * string uri = 1; + * @return This builder for chaining. + */ + public Builder clearUri() { + uri_ = getDefaultInstance().getUri(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The URI of the extension.
            +     * Example: "https://developers.google.com/identity/protocols/oauth2"
            +     * 
            + * + * string uri = 1; + * @param value The bytes for uri to set. + * @return This builder for chaining. + */ + public Builder setUriBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + uri_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object description_ = ""; + /** + *
            +     * A description of how this agent uses this extension.
            +     * Example: "Google OAuth 2.0 authentication"
            +     * 
            + * + * string description = 2; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A description of how this agent uses this extension.
            +     * Example: "Google OAuth 2.0 authentication"
            +     * 
            + * + * string description = 2; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A description of how this agent uses this extension.
            +     * Example: "Google OAuth 2.0 authentication"
            +     * 
            + * + * string description = 2; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A description of how this agent uses this extension.
            +     * Example: "Google OAuth 2.0 authentication"
            +     * 
            + * + * string description = 2; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * A description of how this agent uses this extension.
            +     * Example: "Google OAuth 2.0 authentication"
            +     * 
            + * + * string description = 2; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private boolean required_ ; + /** + *
            +     * Whether the client must follow specific requirements of the extension.
            +     * Example: false
            +     * 
            + * + * bool required = 3; + * @return The required. + */ + @java.lang.Override + public boolean getRequired() { + return required_; + } + /** + *
            +     * Whether the client must follow specific requirements of the extension.
            +     * Example: false
            +     * 
            + * + * bool required = 3; + * @param value The required to set. + * @return This builder for chaining. + */ + public Builder setRequired(boolean value) { + + required_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * Whether the client must follow specific requirements of the extension.
            +     * Example: false
            +     * 
            + * + * bool required = 3; + * @return This builder for chaining. + */ + public Builder clearRequired() { + bitField0_ = (bitField0_ & ~0x00000004); + required_ = false; + onChanged(); + return this; + } + + private com.google.protobuf.Struct params_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> paramsBuilder_; + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + * @return Whether the params field is set. + */ + public boolean hasParams() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + * @return The params. + */ + public com.google.protobuf.Struct getParams() { + if (paramsBuilder_ == null) { + return params_ == null ? com.google.protobuf.Struct.getDefaultInstance() : params_; + } else { + return paramsBuilder_.getMessage(); + } + } + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + */ + public Builder setParams(com.google.protobuf.Struct value) { + if (paramsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + params_ = value; + } else { + paramsBuilder_.setMessage(value); + } + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + */ + public Builder setParams( + com.google.protobuf.Struct.Builder builderForValue) { + if (paramsBuilder_ == null) { + params_ = builderForValue.build(); + } else { + paramsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + */ + public Builder mergeParams(com.google.protobuf.Struct value) { + if (paramsBuilder_ == null) { + if (((bitField0_ & 0x00000008) != 0) && + params_ != null && + params_ != com.google.protobuf.Struct.getDefaultInstance()) { + getParamsBuilder().mergeFrom(value); + } else { + params_ = value; + } + } else { + paramsBuilder_.mergeFrom(value); + } + if (params_ != null) { + bitField0_ |= 0x00000008; + onChanged(); + } + return this; + } + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + */ + public Builder clearParams() { + bitField0_ = (bitField0_ & ~0x00000008); + params_ = null; + if (paramsBuilder_ != null) { + paramsBuilder_.dispose(); + paramsBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + */ + public com.google.protobuf.Struct.Builder getParamsBuilder() { + bitField0_ |= 0x00000008; + onChanged(); + return internalGetParamsFieldBuilder().getBuilder(); + } + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + */ + public com.google.protobuf.StructOrBuilder getParamsOrBuilder() { + if (paramsBuilder_ != null) { + return paramsBuilder_.getMessageOrBuilder(); + } else { + return params_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : params_; + } + } + /** + *
            +     * Optional configuration for the extension.
            +     * 
            + * + * .google.protobuf.Struct params = 4; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetParamsFieldBuilder() { + if (paramsBuilder_ == null) { + paramsBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getParams(), + getParentForChildren(), + isClean()); + params_ = null; + } + return paramsBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentExtension) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AgentExtension) + private static final org.a2aproject.sdk.compat03.grpc.AgentExtension DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AgentExtension(); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentExtension getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AgentExtension parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentExtension getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentExtensionOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentExtensionOrBuilder.java new file mode 100644 index 000000000..bbd435191 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentExtensionOrBuilder.java @@ -0,0 +1,94 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AgentExtensionOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AgentExtension) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The URI of the extension.
            +   * Example: "https://developers.google.com/identity/protocols/oauth2"
            +   * 
            + * + * string uri = 1; + * @return The uri. + */ + java.lang.String getUri(); + /** + *
            +   * The URI of the extension.
            +   * Example: "https://developers.google.com/identity/protocols/oauth2"
            +   * 
            + * + * string uri = 1; + * @return The bytes for uri. + */ + com.google.protobuf.ByteString + getUriBytes(); + + /** + *
            +   * A description of how this agent uses this extension.
            +   * Example: "Google OAuth 2.0 authentication"
            +   * 
            + * + * string description = 2; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * A description of how this agent uses this extension.
            +   * Example: "Google OAuth 2.0 authentication"
            +   * 
            + * + * string description = 2; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + *
            +   * Whether the client must follow specific requirements of the extension.
            +   * Example: false
            +   * 
            + * + * bool required = 3; + * @return The required. + */ + boolean getRequired(); + + /** + *
            +   * Optional configuration for the extension.
            +   * 
            + * + * .google.protobuf.Struct params = 4; + * @return Whether the params field is set. + */ + boolean hasParams(); + /** + *
            +   * Optional configuration for the extension.
            +   * 
            + * + * .google.protobuf.Struct params = 4; + * @return The params. + */ + com.google.protobuf.Struct getParams(); + /** + *
            +   * Optional configuration for the extension.
            +   * 
            + * + * .google.protobuf.Struct params = 4; + */ + com.google.protobuf.StructOrBuilder getParamsOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentInterface.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentInterface.java new file mode 100644 index 000000000..cb918a27e --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentInterface.java @@ -0,0 +1,716 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Defines additional transport information for the agent.
            + * 
            + * + * Protobuf type {@code a2a.v1.AgentInterface} + */ +@com.google.protobuf.Generated +public final class AgentInterface extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AgentInterface) + AgentInterfaceOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AgentInterface"); + } + // Use AgentInterface.newBuilder() to construct. + private AgentInterface(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AgentInterface() { + url_ = ""; + transport_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentInterface_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentInterface_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentInterface.class, org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder.class); + } + + public static final int URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object url_ = ""; + /** + *
            +   * The url this interface is found at.
            +   * 
            + * + * string url = 1; + * @return The url. + */ + @java.lang.Override + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } + } + /** + *
            +   * The url this interface is found at.
            +   * 
            + * + * string url = 1; + * @return The bytes for url. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TRANSPORT_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object transport_ = ""; + /** + *
            +   * The transport supported this url. This is an open form string, to be
            +   * easily extended for many transport protocols. The core ones officially
            +   * supported are JSONRPC, GRPC and HTTP+JSON.
            +   * 
            + * + * string transport = 2; + * @return The transport. + */ + @java.lang.Override + public java.lang.String getTransport() { + java.lang.Object ref = transport_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + transport_ = s; + return s; + } + } + /** + *
            +   * The transport supported this url. This is an open form string, to be
            +   * easily extended for many transport protocols. The core ones officially
            +   * supported are JSONRPC, GRPC and HTTP+JSON.
            +   * 
            + * + * string transport = 2; + * @return The bytes for transport. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTransportBytes() { + java.lang.Object ref = transport_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + transport_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, url_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(transport_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, transport_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, url_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(transport_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, transport_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AgentInterface)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AgentInterface other = (org.a2aproject.sdk.compat03.grpc.AgentInterface) obj; + + if (!getUrl() + .equals(other.getUrl())) return false; + if (!getTransport() + .equals(other.getTransport())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + URL_FIELD_NUMBER; + hash = (53 * hash) + getUrl().hashCode(); + hash = (37 * hash) + TRANSPORT_FIELD_NUMBER; + hash = (53 * hash) + getTransport().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentInterface parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AgentInterface prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Defines additional transport information for the agent.
            +   * 
            + * + * Protobuf type {@code a2a.v1.AgentInterface} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AgentInterface) + org.a2aproject.sdk.compat03.grpc.AgentInterfaceOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentInterface_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentInterface_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentInterface.class, org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AgentInterface.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + url_ = ""; + transport_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AgentInterface_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentInterface getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AgentInterface.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentInterface build() { + org.a2aproject.sdk.compat03.grpc.AgentInterface result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentInterface buildPartial() { + org.a2aproject.sdk.compat03.grpc.AgentInterface result = new org.a2aproject.sdk.compat03.grpc.AgentInterface(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AgentInterface result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.url_ = url_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.transport_ = transport_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AgentInterface) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AgentInterface)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AgentInterface other) { + if (other == org.a2aproject.sdk.compat03.grpc.AgentInterface.getDefaultInstance()) return this; + if (!other.getUrl().isEmpty()) { + url_ = other.url_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getTransport().isEmpty()) { + transport_ = other.transport_; + bitField0_ |= 0x00000002; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + url_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + transport_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object url_ = ""; + /** + *
            +     * The url this interface is found at.
            +     * 
            + * + * string url = 1; + * @return The url. + */ + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The url this interface is found at.
            +     * 
            + * + * string url = 1; + * @return The bytes for url. + */ + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The url this interface is found at.
            +     * 
            + * + * string url = 1; + * @param value The url to set. + * @return This builder for chaining. + */ + public Builder setUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + url_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The url this interface is found at.
            +     * 
            + * + * string url = 1; + * @return This builder for chaining. + */ + public Builder clearUrl() { + url_ = getDefaultInstance().getUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The url this interface is found at.
            +     * 
            + * + * string url = 1; + * @param value The bytes for url to set. + * @return This builder for chaining. + */ + public Builder setUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + url_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object transport_ = ""; + /** + *
            +     * The transport supported this url. This is an open form string, to be
            +     * easily extended for many transport protocols. The core ones officially
            +     * supported are JSONRPC, GRPC and HTTP+JSON.
            +     * 
            + * + * string transport = 2; + * @return The transport. + */ + public java.lang.String getTransport() { + java.lang.Object ref = transport_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + transport_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The transport supported this url. This is an open form string, to be
            +     * easily extended for many transport protocols. The core ones officially
            +     * supported are JSONRPC, GRPC and HTTP+JSON.
            +     * 
            + * + * string transport = 2; + * @return The bytes for transport. + */ + public com.google.protobuf.ByteString + getTransportBytes() { + java.lang.Object ref = transport_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + transport_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The transport supported this url. This is an open form string, to be
            +     * easily extended for many transport protocols. The core ones officially
            +     * supported are JSONRPC, GRPC and HTTP+JSON.
            +     * 
            + * + * string transport = 2; + * @param value The transport to set. + * @return This builder for chaining. + */ + public Builder setTransport( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + transport_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The transport supported this url. This is an open form string, to be
            +     * easily extended for many transport protocols. The core ones officially
            +     * supported are JSONRPC, GRPC and HTTP+JSON.
            +     * 
            + * + * string transport = 2; + * @return This builder for chaining. + */ + public Builder clearTransport() { + transport_ = getDefaultInstance().getTransport(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The transport supported this url. This is an open form string, to be
            +     * easily extended for many transport protocols. The core ones officially
            +     * supported are JSONRPC, GRPC and HTTP+JSON.
            +     * 
            + * + * string transport = 2; + * @param value The bytes for transport to set. + * @return This builder for chaining. + */ + public Builder setTransportBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + transport_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentInterface) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AgentInterface) + private static final org.a2aproject.sdk.compat03.grpc.AgentInterface DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AgentInterface(); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentInterface getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AgentInterface parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentInterface getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentInterfaceOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentInterfaceOrBuilder.java new file mode 100644 index 000000000..261794711 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentInterfaceOrBuilder.java @@ -0,0 +1,56 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AgentInterfaceOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AgentInterface) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The url this interface is found at.
            +   * 
            + * + * string url = 1; + * @return The url. + */ + java.lang.String getUrl(); + /** + *
            +   * The url this interface is found at.
            +   * 
            + * + * string url = 1; + * @return The bytes for url. + */ + com.google.protobuf.ByteString + getUrlBytes(); + + /** + *
            +   * The transport supported this url. This is an open form string, to be
            +   * easily extended for many transport protocols. The core ones officially
            +   * supported are JSONRPC, GRPC and HTTP+JSON.
            +   * 
            + * + * string transport = 2; + * @return The transport. + */ + java.lang.String getTransport(); + /** + *
            +   * The transport supported this url. This is an open form string, to be
            +   * easily extended for many transport protocols. The core ones officially
            +   * supported are JSONRPC, GRPC and HTTP+JSON.
            +   * 
            + * + * string transport = 2; + * @return The bytes for transport. + */ + com.google.protobuf.ByteString + getTransportBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentProvider.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentProvider.java new file mode 100644 index 000000000..c77d6fdd2 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentProvider.java @@ -0,0 +1,716 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Represents information about the service provider of an agent.
            + * 
            + * + * Protobuf type {@code a2a.v1.AgentProvider} + */ +@com.google.protobuf.Generated +public final class AgentProvider extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AgentProvider) + AgentProviderOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AgentProvider"); + } + // Use AgentProvider.newBuilder() to construct. + private AgentProvider(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AgentProvider() { + url_ = ""; + organization_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentProvider_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentProvider_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentProvider.class, org.a2aproject.sdk.compat03.grpc.AgentProvider.Builder.class); + } + + public static final int URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object url_ = ""; + /** + *
            +   * The providers reference url
            +   * Example: "https://ai.google.dev"
            +   * 
            + * + * string url = 1; + * @return The url. + */ + @java.lang.Override + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } + } + /** + *
            +   * The providers reference url
            +   * Example: "https://ai.google.dev"
            +   * 
            + * + * string url = 1; + * @return The bytes for url. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int ORGANIZATION_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object organization_ = ""; + /** + *
            +   * The providers organization name
            +   * Example: "Google"
            +   * 
            + * + * string organization = 2; + * @return The organization. + */ + @java.lang.Override + public java.lang.String getOrganization() { + java.lang.Object ref = organization_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + organization_ = s; + return s; + } + } + /** + *
            +   * The providers organization name
            +   * Example: "Google"
            +   * 
            + * + * string organization = 2; + * @return The bytes for organization. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getOrganizationBytes() { + java.lang.Object ref = organization_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + organization_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, url_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(organization_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, organization_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, url_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(organization_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, organization_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AgentProvider)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AgentProvider other = (org.a2aproject.sdk.compat03.grpc.AgentProvider) obj; + + if (!getUrl() + .equals(other.getUrl())) return false; + if (!getOrganization() + .equals(other.getOrganization())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + URL_FIELD_NUMBER; + hash = (53 * hash) + getUrl().hashCode(); + hash = (37 * hash) + ORGANIZATION_FIELD_NUMBER; + hash = (53 * hash) + getOrganization().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentProvider parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AgentProvider prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Represents information about the service provider of an agent.
            +   * 
            + * + * Protobuf type {@code a2a.v1.AgentProvider} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AgentProvider) + org.a2aproject.sdk.compat03.grpc.AgentProviderOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentProvider_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentProvider_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentProvider.class, org.a2aproject.sdk.compat03.grpc.AgentProvider.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AgentProvider.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + url_ = ""; + organization_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AgentProvider_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentProvider getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AgentProvider.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentProvider build() { + org.a2aproject.sdk.compat03.grpc.AgentProvider result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentProvider buildPartial() { + org.a2aproject.sdk.compat03.grpc.AgentProvider result = new org.a2aproject.sdk.compat03.grpc.AgentProvider(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AgentProvider result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.url_ = url_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.organization_ = organization_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AgentProvider) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AgentProvider)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AgentProvider other) { + if (other == org.a2aproject.sdk.compat03.grpc.AgentProvider.getDefaultInstance()) return this; + if (!other.getUrl().isEmpty()) { + url_ = other.url_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getOrganization().isEmpty()) { + organization_ = other.organization_; + bitField0_ |= 0x00000002; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + url_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + organization_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object url_ = ""; + /** + *
            +     * The providers reference url
            +     * Example: "https://ai.google.dev"
            +     * 
            + * + * string url = 1; + * @return The url. + */ + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The providers reference url
            +     * Example: "https://ai.google.dev"
            +     * 
            + * + * string url = 1; + * @return The bytes for url. + */ + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The providers reference url
            +     * Example: "https://ai.google.dev"
            +     * 
            + * + * string url = 1; + * @param value The url to set. + * @return This builder for chaining. + */ + public Builder setUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + url_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The providers reference url
            +     * Example: "https://ai.google.dev"
            +     * 
            + * + * string url = 1; + * @return This builder for chaining. + */ + public Builder clearUrl() { + url_ = getDefaultInstance().getUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The providers reference url
            +     * Example: "https://ai.google.dev"
            +     * 
            + * + * string url = 1; + * @param value The bytes for url to set. + * @return This builder for chaining. + */ + public Builder setUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + url_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object organization_ = ""; + /** + *
            +     * The providers organization name
            +     * Example: "Google"
            +     * 
            + * + * string organization = 2; + * @return The organization. + */ + public java.lang.String getOrganization() { + java.lang.Object ref = organization_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + organization_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The providers organization name
            +     * Example: "Google"
            +     * 
            + * + * string organization = 2; + * @return The bytes for organization. + */ + public com.google.protobuf.ByteString + getOrganizationBytes() { + java.lang.Object ref = organization_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + organization_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The providers organization name
            +     * Example: "Google"
            +     * 
            + * + * string organization = 2; + * @param value The organization to set. + * @return This builder for chaining. + */ + public Builder setOrganization( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + organization_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The providers organization name
            +     * Example: "Google"
            +     * 
            + * + * string organization = 2; + * @return This builder for chaining. + */ + public Builder clearOrganization() { + organization_ = getDefaultInstance().getOrganization(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The providers organization name
            +     * Example: "Google"
            +     * 
            + * + * string organization = 2; + * @param value The bytes for organization to set. + * @return This builder for chaining. + */ + public Builder setOrganizationBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + organization_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentProvider) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AgentProvider) + private static final org.a2aproject.sdk.compat03.grpc.AgentProvider DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AgentProvider(); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentProvider getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AgentProvider parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentProvider getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentProviderOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentProviderOrBuilder.java new file mode 100644 index 000000000..7335191a6 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentProviderOrBuilder.java @@ -0,0 +1,56 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AgentProviderOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AgentProvider) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The providers reference url
            +   * Example: "https://ai.google.dev"
            +   * 
            + * + * string url = 1; + * @return The url. + */ + java.lang.String getUrl(); + /** + *
            +   * The providers reference url
            +   * Example: "https://ai.google.dev"
            +   * 
            + * + * string url = 1; + * @return The bytes for url. + */ + com.google.protobuf.ByteString + getUrlBytes(); + + /** + *
            +   * The providers organization name
            +   * Example: "Google"
            +   * 
            + * + * string organization = 2; + * @return The organization. + */ + java.lang.String getOrganization(); + /** + *
            +   * The providers organization name
            +   * Example: "Google"
            +   * 
            + * + * string organization = 2; + * @return The bytes for organization. + */ + com.google.protobuf.ByteString + getOrganizationBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentSkill.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentSkill.java new file mode 100644 index 000000000..58832f364 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentSkill.java @@ -0,0 +1,2435 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * AgentSkill represents a unit of action/solution that the agent can perform.
            + * One can think of this as a type of highly reliable solution that an agent
            + * can be tasked to provide. Agents have the autonomy to choose how and when
            + * to use specific skills, but clients should have confidence that if the
            + * skill is defined that unit of action can be reliably performed.
            + * 
            + * + * Protobuf type {@code a2a.v1.AgentSkill} + */ +@com.google.protobuf.Generated +public final class AgentSkill extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AgentSkill) + AgentSkillOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AgentSkill"); + } + // Use AgentSkill.newBuilder() to construct. + private AgentSkill(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AgentSkill() { + id_ = ""; + name_ = ""; + description_ = ""; + tags_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + examples_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + inputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + outputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + security_ = java.util.Collections.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentSkill_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentSkill_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentSkill.class, org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder.class); + } + + public static final int ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object id_ = ""; + /** + *
            +   * Unique id of the skill within this agent.
            +   * 
            + * + * string id = 1; + * @return The id. + */ + @java.lang.Override + public java.lang.String getId() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + *
            +   * Unique id of the skill within this agent.
            +   * 
            + * + * string id = 1; + * @return The bytes for id. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int NAME_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * A human readable name for the skill.
            +   * 
            + * + * string name = 2; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * A human readable name for the skill.
            +   * 
            + * + * string name = 2; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DESCRIPTION_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * A human (or llm) readable description of the skill
            +   * details and behaviors.
            +   * 
            + * + * string description = 3; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * A human (or llm) readable description of the skill
            +   * details and behaviors.
            +   * 
            + * + * string description = 3; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TAGS_FIELD_NUMBER = 4; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList tags_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * A set of tags for the skill to enhance categorization/utilization.
            +   * Example: ["cooking", "customer support", "billing"]
            +   * 
            + * + * repeated string tags = 4; + * @return A list containing the tags. + */ + public com.google.protobuf.ProtocolStringList + getTagsList() { + return tags_; + } + /** + *
            +   * A set of tags for the skill to enhance categorization/utilization.
            +   * Example: ["cooking", "customer support", "billing"]
            +   * 
            + * + * repeated string tags = 4; + * @return The count of tags. + */ + public int getTagsCount() { + return tags_.size(); + } + /** + *
            +   * A set of tags for the skill to enhance categorization/utilization.
            +   * Example: ["cooking", "customer support", "billing"]
            +   * 
            + * + * repeated string tags = 4; + * @param index The index of the element to return. + * @return The tags at the given index. + */ + public java.lang.String getTags(int index) { + return tags_.get(index); + } + /** + *
            +   * A set of tags for the skill to enhance categorization/utilization.
            +   * Example: ["cooking", "customer support", "billing"]
            +   * 
            + * + * repeated string tags = 4; + * @param index The index of the value to return. + * @return The bytes of the tags at the given index. + */ + public com.google.protobuf.ByteString + getTagsBytes(int index) { + return tags_.getByteString(index); + } + + public static final int EXAMPLES_FIELD_NUMBER = 5; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList examples_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * A set of example queries that this skill is designed to address.
            +   * These examples should help the caller to understand how to craft requests
            +   * to the agent to achieve specific goals.
            +   * Example: ["I need a recipe for bread"]
            +   * 
            + * + * repeated string examples = 5; + * @return A list containing the examples. + */ + public com.google.protobuf.ProtocolStringList + getExamplesList() { + return examples_; + } + /** + *
            +   * A set of example queries that this skill is designed to address.
            +   * These examples should help the caller to understand how to craft requests
            +   * to the agent to achieve specific goals.
            +   * Example: ["I need a recipe for bread"]
            +   * 
            + * + * repeated string examples = 5; + * @return The count of examples. + */ + public int getExamplesCount() { + return examples_.size(); + } + /** + *
            +   * A set of example queries that this skill is designed to address.
            +   * These examples should help the caller to understand how to craft requests
            +   * to the agent to achieve specific goals.
            +   * Example: ["I need a recipe for bread"]
            +   * 
            + * + * repeated string examples = 5; + * @param index The index of the element to return. + * @return The examples at the given index. + */ + public java.lang.String getExamples(int index) { + return examples_.get(index); + } + /** + *
            +   * A set of example queries that this skill is designed to address.
            +   * These examples should help the caller to understand how to craft requests
            +   * to the agent to achieve specific goals.
            +   * Example: ["I need a recipe for bread"]
            +   * 
            + * + * repeated string examples = 5; + * @param index The index of the value to return. + * @return The bytes of the examples at the given index. + */ + public com.google.protobuf.ByteString + getExamplesBytes(int index) { + return examples_.getByteString(index); + } + + public static final int INPUT_MODES_FIELD_NUMBER = 6; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList inputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * Possible input modalities supported.
            +   * 
            + * + * repeated string input_modes = 6; + * @return A list containing the inputModes. + */ + public com.google.protobuf.ProtocolStringList + getInputModesList() { + return inputModes_; + } + /** + *
            +   * Possible input modalities supported.
            +   * 
            + * + * repeated string input_modes = 6; + * @return The count of inputModes. + */ + public int getInputModesCount() { + return inputModes_.size(); + } + /** + *
            +   * Possible input modalities supported.
            +   * 
            + * + * repeated string input_modes = 6; + * @param index The index of the element to return. + * @return The inputModes at the given index. + */ + public java.lang.String getInputModes(int index) { + return inputModes_.get(index); + } + /** + *
            +   * Possible input modalities supported.
            +   * 
            + * + * repeated string input_modes = 6; + * @param index The index of the value to return. + * @return The bytes of the inputModes at the given index. + */ + public com.google.protobuf.ByteString + getInputModesBytes(int index) { + return inputModes_.getByteString(index); + } + + public static final int OUTPUT_MODES_FIELD_NUMBER = 7; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList outputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * Possible output modalities produced
            +   * 
            + * + * repeated string output_modes = 7; + * @return A list containing the outputModes. + */ + public com.google.protobuf.ProtocolStringList + getOutputModesList() { + return outputModes_; + } + /** + *
            +   * Possible output modalities produced
            +   * 
            + * + * repeated string output_modes = 7; + * @return The count of outputModes. + */ + public int getOutputModesCount() { + return outputModes_.size(); + } + /** + *
            +   * Possible output modalities produced
            +   * 
            + * + * repeated string output_modes = 7; + * @param index The index of the element to return. + * @return The outputModes at the given index. + */ + public java.lang.String getOutputModes(int index) { + return outputModes_.get(index); + } + /** + *
            +   * Possible output modalities produced
            +   * 
            + * + * repeated string output_modes = 7; + * @param index The index of the value to return. + * @return The bytes of the outputModes at the given index. + */ + public com.google.protobuf.ByteString + getOutputModesBytes(int index) { + return outputModes_.getByteString(index); + } + + public static final int SECURITY_FIELD_NUMBER = 8; + @SuppressWarnings("serial") + private java.util.List security_; + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + @java.lang.Override + public java.util.List getSecurityList() { + return security_; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + @java.lang.Override + public java.util.List + getSecurityOrBuilderList() { + return security_; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + @java.lang.Override + public int getSecurityCount() { + return security_.size(); + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Security getSecurity(int index) { + return security_.get(index); + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder getSecurityOrBuilder( + int index) { + return security_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, name_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, description_); + } + for (int i = 0; i < tags_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 4, tags_.getRaw(i)); + } + for (int i = 0; i < examples_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 5, examples_.getRaw(i)); + } + for (int i = 0; i < inputModes_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 6, inputModes_.getRaw(i)); + } + for (int i = 0; i < outputModes_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 7, outputModes_.getRaw(i)); + } + for (int i = 0; i < security_.size(); i++) { + output.writeMessage(8, security_.get(i)); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, name_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, description_); + } + { + int dataSize = 0; + for (int i = 0; i < tags_.size(); i++) { + dataSize += computeStringSizeNoTag(tags_.getRaw(i)); + } + size += dataSize; + size += 1 * getTagsList().size(); + } + { + int dataSize = 0; + for (int i = 0; i < examples_.size(); i++) { + dataSize += computeStringSizeNoTag(examples_.getRaw(i)); + } + size += dataSize; + size += 1 * getExamplesList().size(); + } + { + int dataSize = 0; + for (int i = 0; i < inputModes_.size(); i++) { + dataSize += computeStringSizeNoTag(inputModes_.getRaw(i)); + } + size += dataSize; + size += 1 * getInputModesList().size(); + } + { + int dataSize = 0; + for (int i = 0; i < outputModes_.size(); i++) { + dataSize += computeStringSizeNoTag(outputModes_.getRaw(i)); + } + size += dataSize; + size += 1 * getOutputModesList().size(); + } + for (int i = 0; i < security_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, security_.get(i)); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AgentSkill)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AgentSkill other = (org.a2aproject.sdk.compat03.grpc.AgentSkill) obj; + + if (!getId() + .equals(other.getId())) return false; + if (!getName() + .equals(other.getName())) return false; + if (!getDescription() + .equals(other.getDescription())) return false; + if (!getTagsList() + .equals(other.getTagsList())) return false; + if (!getExamplesList() + .equals(other.getExamplesList())) return false; + if (!getInputModesList() + .equals(other.getInputModesList())) return false; + if (!getOutputModesList() + .equals(other.getOutputModesList())) return false; + if (!getSecurityList() + .equals(other.getSecurityList())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + if (getTagsCount() > 0) { + hash = (37 * hash) + TAGS_FIELD_NUMBER; + hash = (53 * hash) + getTagsList().hashCode(); + } + if (getExamplesCount() > 0) { + hash = (37 * hash) + EXAMPLES_FIELD_NUMBER; + hash = (53 * hash) + getExamplesList().hashCode(); + } + if (getInputModesCount() > 0) { + hash = (37 * hash) + INPUT_MODES_FIELD_NUMBER; + hash = (53 * hash) + getInputModesList().hashCode(); + } + if (getOutputModesCount() > 0) { + hash = (37 * hash) + OUTPUT_MODES_FIELD_NUMBER; + hash = (53 * hash) + getOutputModesList().hashCode(); + } + if (getSecurityCount() > 0) { + hash = (37 * hash) + SECURITY_FIELD_NUMBER; + hash = (53 * hash) + getSecurityList().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AgentSkill parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AgentSkill prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * AgentSkill represents a unit of action/solution that the agent can perform.
            +   * One can think of this as a type of highly reliable solution that an agent
            +   * can be tasked to provide. Agents have the autonomy to choose how and when
            +   * to use specific skills, but clients should have confidence that if the
            +   * skill is defined that unit of action can be reliably performed.
            +   * 
            + * + * Protobuf type {@code a2a.v1.AgentSkill} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AgentSkill) + org.a2aproject.sdk.compat03.grpc.AgentSkillOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AgentSkill_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AgentSkill_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AgentSkill.class, org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AgentSkill.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + id_ = ""; + name_ = ""; + description_ = ""; + tags_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + examples_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + inputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + outputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + if (securityBuilder_ == null) { + security_ = java.util.Collections.emptyList(); + } else { + security_ = null; + securityBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000080); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AgentSkill_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentSkill getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AgentSkill.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentSkill build() { + org.a2aproject.sdk.compat03.grpc.AgentSkill result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentSkill buildPartial() { + org.a2aproject.sdk.compat03.grpc.AgentSkill result = new org.a2aproject.sdk.compat03.grpc.AgentSkill(this); + buildPartialRepeatedFields(result); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartialRepeatedFields(org.a2aproject.sdk.compat03.grpc.AgentSkill result) { + if (securityBuilder_ == null) { + if (((bitField0_ & 0x00000080) != 0)) { + security_ = java.util.Collections.unmodifiableList(security_); + bitField0_ = (bitField0_ & ~0x00000080); + } + result.security_ = security_; + } else { + result.security_ = securityBuilder_.build(); + } + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AgentSkill result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.id_ = id_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.name_ = name_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.description_ = description_; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + tags_.makeImmutable(); + result.tags_ = tags_; + } + if (((from_bitField0_ & 0x00000010) != 0)) { + examples_.makeImmutable(); + result.examples_ = examples_; + } + if (((from_bitField0_ & 0x00000020) != 0)) { + inputModes_.makeImmutable(); + result.inputModes_ = inputModes_; + } + if (((from_bitField0_ & 0x00000040) != 0)) { + outputModes_.makeImmutable(); + result.outputModes_ = outputModes_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AgentSkill) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AgentSkill)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AgentSkill other) { + if (other == org.a2aproject.sdk.compat03.grpc.AgentSkill.getDefaultInstance()) return this; + if (!other.getId().isEmpty()) { + id_ = other.id_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000004; + onChanged(); + } + if (!other.tags_.isEmpty()) { + if (tags_.isEmpty()) { + tags_ = other.tags_; + bitField0_ |= 0x00000008; + } else { + ensureTagsIsMutable(); + tags_.addAll(other.tags_); + } + onChanged(); + } + if (!other.examples_.isEmpty()) { + if (examples_.isEmpty()) { + examples_ = other.examples_; + bitField0_ |= 0x00000010; + } else { + ensureExamplesIsMutable(); + examples_.addAll(other.examples_); + } + onChanged(); + } + if (!other.inputModes_.isEmpty()) { + if (inputModes_.isEmpty()) { + inputModes_ = other.inputModes_; + bitField0_ |= 0x00000020; + } else { + ensureInputModesIsMutable(); + inputModes_.addAll(other.inputModes_); + } + onChanged(); + } + if (!other.outputModes_.isEmpty()) { + if (outputModes_.isEmpty()) { + outputModes_ = other.outputModes_; + bitField0_ |= 0x00000040; + } else { + ensureOutputModesIsMutable(); + outputModes_.addAll(other.outputModes_); + } + onChanged(); + } + if (securityBuilder_ == null) { + if (!other.security_.isEmpty()) { + if (security_.isEmpty()) { + security_ = other.security_; + bitField0_ = (bitField0_ & ~0x00000080); + } else { + ensureSecurityIsMutable(); + security_.addAll(other.security_); + } + onChanged(); + } + } else { + if (!other.security_.isEmpty()) { + if (securityBuilder_.isEmpty()) { + securityBuilder_.dispose(); + securityBuilder_ = null; + security_ = other.security_; + bitField0_ = (bitField0_ & ~0x00000080); + securityBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetSecurityFieldBuilder() : null; + } else { + securityBuilder_.addAllMessages(other.security_); + } + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 34: { + java.lang.String s = input.readStringRequireUtf8(); + ensureTagsIsMutable(); + tags_.add(s); + break; + } // case 34 + case 42: { + java.lang.String s = input.readStringRequireUtf8(); + ensureExamplesIsMutable(); + examples_.add(s); + break; + } // case 42 + case 50: { + java.lang.String s = input.readStringRequireUtf8(); + ensureInputModesIsMutable(); + inputModes_.add(s); + break; + } // case 50 + case 58: { + java.lang.String s = input.readStringRequireUtf8(); + ensureOutputModesIsMutable(); + outputModes_.add(s); + break; + } // case 58 + case 66: { + org.a2aproject.sdk.compat03.grpc.Security m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.Security.parser(), + extensionRegistry); + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.add(m); + } else { + securityBuilder_.addMessage(m); + } + break; + } // case 66 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object id_ = ""; + /** + *
            +     * Unique id of the skill within this agent.
            +     * 
            + * + * string id = 1; + * @return The id. + */ + public java.lang.String getId() { + java.lang.Object ref = id_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Unique id of the skill within this agent.
            +     * 
            + * + * string id = 1; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Unique id of the skill within this agent.
            +     * 
            + * + * string id = 1; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Unique id of the skill within this agent.
            +     * 
            + * + * string id = 1; + * @return This builder for chaining. + */ + public Builder clearId() { + id_ = getDefaultInstance().getId(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * Unique id of the skill within this agent.
            +     * 
            + * + * string id = 1; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object name_ = ""; + /** + *
            +     * A human readable name for the skill.
            +     * 
            + * + * string name = 2; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A human readable name for the skill.
            +     * 
            + * + * string name = 2; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A human readable name for the skill.
            +     * 
            + * + * string name = 2; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A human readable name for the skill.
            +     * 
            + * + * string name = 2; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * A human readable name for the skill.
            +     * 
            + * + * string name = 2; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object description_ = ""; + /** + *
            +     * A human (or llm) readable description of the skill
            +     * details and behaviors.
            +     * 
            + * + * string description = 3; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A human (or llm) readable description of the skill
            +     * details and behaviors.
            +     * 
            + * + * string description = 3; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A human (or llm) readable description of the skill
            +     * details and behaviors.
            +     * 
            + * + * string description = 3; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * A human (or llm) readable description of the skill
            +     * details and behaviors.
            +     * 
            + * + * string description = 3; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * A human (or llm) readable description of the skill
            +     * details and behaviors.
            +     * 
            + * + * string description = 3; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private com.google.protobuf.LazyStringArrayList tags_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureTagsIsMutable() { + if (!tags_.isModifiable()) { + tags_ = new com.google.protobuf.LazyStringArrayList(tags_); + } + bitField0_ |= 0x00000008; + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @return A list containing the tags. + */ + public com.google.protobuf.ProtocolStringList + getTagsList() { + tags_.makeImmutable(); + return tags_; + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @return The count of tags. + */ + public int getTagsCount() { + return tags_.size(); + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @param index The index of the element to return. + * @return The tags at the given index. + */ + public java.lang.String getTags(int index) { + return tags_.get(index); + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @param index The index of the value to return. + * @return The bytes of the tags at the given index. + */ + public com.google.protobuf.ByteString + getTagsBytes(int index) { + return tags_.getByteString(index); + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @param index The index to set the value at. + * @param value The tags to set. + * @return This builder for chaining. + */ + public Builder setTags( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureTagsIsMutable(); + tags_.set(index, value); + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @param value The tags to add. + * @return This builder for chaining. + */ + public Builder addTags( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureTagsIsMutable(); + tags_.add(value); + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @param values The tags to add. + * @return This builder for chaining. + */ + public Builder addAllTags( + java.lang.Iterable values) { + ensureTagsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, tags_); + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @return This builder for chaining. + */ + public Builder clearTags() { + tags_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008);; + onChanged(); + return this; + } + /** + *
            +     * A set of tags for the skill to enhance categorization/utilization.
            +     * Example: ["cooking", "customer support", "billing"]
            +     * 
            + * + * repeated string tags = 4; + * @param value The bytes of the tags to add. + * @return This builder for chaining. + */ + public Builder addTagsBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureTagsIsMutable(); + tags_.add(value); + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + + private com.google.protobuf.LazyStringArrayList examples_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureExamplesIsMutable() { + if (!examples_.isModifiable()) { + examples_ = new com.google.protobuf.LazyStringArrayList(examples_); + } + bitField0_ |= 0x00000010; + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @return A list containing the examples. + */ + public com.google.protobuf.ProtocolStringList + getExamplesList() { + examples_.makeImmutable(); + return examples_; + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @return The count of examples. + */ + public int getExamplesCount() { + return examples_.size(); + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @param index The index of the element to return. + * @return The examples at the given index. + */ + public java.lang.String getExamples(int index) { + return examples_.get(index); + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @param index The index of the value to return. + * @return The bytes of the examples at the given index. + */ + public com.google.protobuf.ByteString + getExamplesBytes(int index) { + return examples_.getByteString(index); + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @param index The index to set the value at. + * @param value The examples to set. + * @return This builder for chaining. + */ + public Builder setExamples( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureExamplesIsMutable(); + examples_.set(index, value); + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @param value The examples to add. + * @return This builder for chaining. + */ + public Builder addExamples( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureExamplesIsMutable(); + examples_.add(value); + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @param values The examples to add. + * @return This builder for chaining. + */ + public Builder addAllExamples( + java.lang.Iterable values) { + ensureExamplesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, examples_); + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @return This builder for chaining. + */ + public Builder clearExamples() { + examples_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010);; + onChanged(); + return this; + } + /** + *
            +     * A set of example queries that this skill is designed to address.
            +     * These examples should help the caller to understand how to craft requests
            +     * to the agent to achieve specific goals.
            +     * Example: ["I need a recipe for bread"]
            +     * 
            + * + * repeated string examples = 5; + * @param value The bytes of the examples to add. + * @return This builder for chaining. + */ + public Builder addExamplesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureExamplesIsMutable(); + examples_.add(value); + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + + private com.google.protobuf.LazyStringArrayList inputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureInputModesIsMutable() { + if (!inputModes_.isModifiable()) { + inputModes_ = new com.google.protobuf.LazyStringArrayList(inputModes_); + } + bitField0_ |= 0x00000020; + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @return A list containing the inputModes. + */ + public com.google.protobuf.ProtocolStringList + getInputModesList() { + inputModes_.makeImmutable(); + return inputModes_; + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @return The count of inputModes. + */ + public int getInputModesCount() { + return inputModes_.size(); + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @param index The index of the element to return. + * @return The inputModes at the given index. + */ + public java.lang.String getInputModes(int index) { + return inputModes_.get(index); + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @param index The index of the value to return. + * @return The bytes of the inputModes at the given index. + */ + public com.google.protobuf.ByteString + getInputModesBytes(int index) { + return inputModes_.getByteString(index); + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @param index The index to set the value at. + * @param value The inputModes to set. + * @return This builder for chaining. + */ + public Builder setInputModes( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureInputModesIsMutable(); + inputModes_.set(index, value); + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @param value The inputModes to add. + * @return This builder for chaining. + */ + public Builder addInputModes( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureInputModesIsMutable(); + inputModes_.add(value); + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @param values The inputModes to add. + * @return This builder for chaining. + */ + public Builder addAllInputModes( + java.lang.Iterable values) { + ensureInputModesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, inputModes_); + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @return This builder for chaining. + */ + public Builder clearInputModes() { + inputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020);; + onChanged(); + return this; + } + /** + *
            +     * Possible input modalities supported.
            +     * 
            + * + * repeated string input_modes = 6; + * @param value The bytes of the inputModes to add. + * @return This builder for chaining. + */ + public Builder addInputModesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureInputModesIsMutable(); + inputModes_.add(value); + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + + private com.google.protobuf.LazyStringArrayList outputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureOutputModesIsMutable() { + if (!outputModes_.isModifiable()) { + outputModes_ = new com.google.protobuf.LazyStringArrayList(outputModes_); + } + bitField0_ |= 0x00000040; + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @return A list containing the outputModes. + */ + public com.google.protobuf.ProtocolStringList + getOutputModesList() { + outputModes_.makeImmutable(); + return outputModes_; + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @return The count of outputModes. + */ + public int getOutputModesCount() { + return outputModes_.size(); + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @param index The index of the element to return. + * @return The outputModes at the given index. + */ + public java.lang.String getOutputModes(int index) { + return outputModes_.get(index); + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @param index The index of the value to return. + * @return The bytes of the outputModes at the given index. + */ + public com.google.protobuf.ByteString + getOutputModesBytes(int index) { + return outputModes_.getByteString(index); + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @param index The index to set the value at. + * @param value The outputModes to set. + * @return This builder for chaining. + */ + public Builder setOutputModes( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureOutputModesIsMutable(); + outputModes_.set(index, value); + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @param value The outputModes to add. + * @return This builder for chaining. + */ + public Builder addOutputModes( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureOutputModesIsMutable(); + outputModes_.add(value); + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @param values The outputModes to add. + * @return This builder for chaining. + */ + public Builder addAllOutputModes( + java.lang.Iterable values) { + ensureOutputModesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, outputModes_); + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @return This builder for chaining. + */ + public Builder clearOutputModes() { + outputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000040);; + onChanged(); + return this; + } + /** + *
            +     * Possible output modalities produced
            +     * 
            + * + * repeated string output_modes = 7; + * @param value The bytes of the outputModes to add. + * @return This builder for chaining. + */ + public Builder addOutputModesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureOutputModesIsMutable(); + outputModes_.add(value); + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + + private java.util.List security_ = + java.util.Collections.emptyList(); + private void ensureSecurityIsMutable() { + if (!((bitField0_ & 0x00000080) != 0)) { + security_ = new java.util.ArrayList(security_); + bitField0_ |= 0x00000080; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Security, org.a2aproject.sdk.compat03.grpc.Security.Builder, org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder> securityBuilder_; + + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public java.util.List getSecurityList() { + if (securityBuilder_ == null) { + return java.util.Collections.unmodifiableList(security_); + } else { + return securityBuilder_.getMessageList(); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public int getSecurityCount() { + if (securityBuilder_ == null) { + return security_.size(); + } else { + return securityBuilder_.getCount(); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public org.a2aproject.sdk.compat03.grpc.Security getSecurity(int index) { + if (securityBuilder_ == null) { + return security_.get(index); + } else { + return securityBuilder_.getMessage(index); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder setSecurity( + int index, org.a2aproject.sdk.compat03.grpc.Security value) { + if (securityBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSecurityIsMutable(); + security_.set(index, value); + onChanged(); + } else { + securityBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder setSecurity( + int index, org.a2aproject.sdk.compat03.grpc.Security.Builder builderForValue) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.set(index, builderForValue.build()); + onChanged(); + } else { + securityBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder addSecurity(org.a2aproject.sdk.compat03.grpc.Security value) { + if (securityBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSecurityIsMutable(); + security_.add(value); + onChanged(); + } else { + securityBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder addSecurity( + int index, org.a2aproject.sdk.compat03.grpc.Security value) { + if (securityBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSecurityIsMutable(); + security_.add(index, value); + onChanged(); + } else { + securityBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder addSecurity( + org.a2aproject.sdk.compat03.grpc.Security.Builder builderForValue) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.add(builderForValue.build()); + onChanged(); + } else { + securityBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder addSecurity( + int index, org.a2aproject.sdk.compat03.grpc.Security.Builder builderForValue) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.add(index, builderForValue.build()); + onChanged(); + } else { + securityBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder addAllSecurity( + java.lang.Iterable values) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, security_); + onChanged(); + } else { + securityBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder clearSecurity() { + if (securityBuilder_ == null) { + security_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000080); + onChanged(); + } else { + securityBuilder_.clear(); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public Builder removeSecurity(int index) { + if (securityBuilder_ == null) { + ensureSecurityIsMutable(); + security_.remove(index); + onChanged(); + } else { + securityBuilder_.remove(index); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public org.a2aproject.sdk.compat03.grpc.Security.Builder getSecurityBuilder( + int index) { + return internalGetSecurityFieldBuilder().getBuilder(index); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder getSecurityOrBuilder( + int index) { + if (securityBuilder_ == null) { + return security_.get(index); } else { + return securityBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public java.util.List + getSecurityOrBuilderList() { + if (securityBuilder_ != null) { + return securityBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(security_); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public org.a2aproject.sdk.compat03.grpc.Security.Builder addSecurityBuilder() { + return internalGetSecurityFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.Security.getDefaultInstance()); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public org.a2aproject.sdk.compat03.grpc.Security.Builder addSecurityBuilder( + int index) { + return internalGetSecurityFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.Security.getDefaultInstance()); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Security schemes necessary for the agent to leverage this skill.
            +     * As in the overall AgentCard.security, this list represents a logical OR of
            +     * security requirement objects. Each object is a set of security schemes
            +     * that must be used together (a logical AND).
            +     * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + public java.util.List + getSecurityBuilderList() { + return internalGetSecurityFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Security, org.a2aproject.sdk.compat03.grpc.Security.Builder, org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder> + internalGetSecurityFieldBuilder() { + if (securityBuilder_ == null) { + securityBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Security, org.a2aproject.sdk.compat03.grpc.Security.Builder, org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder>( + security_, + ((bitField0_ & 0x00000080) != 0), + getParentForChildren(), + isClean()); + security_ = null; + } + return securityBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AgentSkill) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AgentSkill) + private static final org.a2aproject.sdk.compat03.grpc.AgentSkill DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AgentSkill(); + } + + public static org.a2aproject.sdk.compat03.grpc.AgentSkill getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AgentSkill parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AgentSkill getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentSkillOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentSkillOrBuilder.java new file mode 100644 index 000000000..0a61179db --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AgentSkillOrBuilder.java @@ -0,0 +1,318 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AgentSkillOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AgentSkill) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Unique id of the skill within this agent.
            +   * 
            + * + * string id = 1; + * @return The id. + */ + java.lang.String getId(); + /** + *
            +   * Unique id of the skill within this agent.
            +   * 
            + * + * string id = 1; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); + + /** + *
            +   * A human readable name for the skill.
            +   * 
            + * + * string name = 2; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * A human readable name for the skill.
            +   * 
            + * + * string name = 2; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + *
            +   * A human (or llm) readable description of the skill
            +   * details and behaviors.
            +   * 
            + * + * string description = 3; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * A human (or llm) readable description of the skill
            +   * details and behaviors.
            +   * 
            + * + * string description = 3; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + *
            +   * A set of tags for the skill to enhance categorization/utilization.
            +   * Example: ["cooking", "customer support", "billing"]
            +   * 
            + * + * repeated string tags = 4; + * @return A list containing the tags. + */ + java.util.List + getTagsList(); + /** + *
            +   * A set of tags for the skill to enhance categorization/utilization.
            +   * Example: ["cooking", "customer support", "billing"]
            +   * 
            + * + * repeated string tags = 4; + * @return The count of tags. + */ + int getTagsCount(); + /** + *
            +   * A set of tags for the skill to enhance categorization/utilization.
            +   * Example: ["cooking", "customer support", "billing"]
            +   * 
            + * + * repeated string tags = 4; + * @param index The index of the element to return. + * @return The tags at the given index. + */ + java.lang.String getTags(int index); + /** + *
            +   * A set of tags for the skill to enhance categorization/utilization.
            +   * Example: ["cooking", "customer support", "billing"]
            +   * 
            + * + * repeated string tags = 4; + * @param index The index of the value to return. + * @return The bytes of the tags at the given index. + */ + com.google.protobuf.ByteString + getTagsBytes(int index); + + /** + *
            +   * A set of example queries that this skill is designed to address.
            +   * These examples should help the caller to understand how to craft requests
            +   * to the agent to achieve specific goals.
            +   * Example: ["I need a recipe for bread"]
            +   * 
            + * + * repeated string examples = 5; + * @return A list containing the examples. + */ + java.util.List + getExamplesList(); + /** + *
            +   * A set of example queries that this skill is designed to address.
            +   * These examples should help the caller to understand how to craft requests
            +   * to the agent to achieve specific goals.
            +   * Example: ["I need a recipe for bread"]
            +   * 
            + * + * repeated string examples = 5; + * @return The count of examples. + */ + int getExamplesCount(); + /** + *
            +   * A set of example queries that this skill is designed to address.
            +   * These examples should help the caller to understand how to craft requests
            +   * to the agent to achieve specific goals.
            +   * Example: ["I need a recipe for bread"]
            +   * 
            + * + * repeated string examples = 5; + * @param index The index of the element to return. + * @return The examples at the given index. + */ + java.lang.String getExamples(int index); + /** + *
            +   * A set of example queries that this skill is designed to address.
            +   * These examples should help the caller to understand how to craft requests
            +   * to the agent to achieve specific goals.
            +   * Example: ["I need a recipe for bread"]
            +   * 
            + * + * repeated string examples = 5; + * @param index The index of the value to return. + * @return The bytes of the examples at the given index. + */ + com.google.protobuf.ByteString + getExamplesBytes(int index); + + /** + *
            +   * Possible input modalities supported.
            +   * 
            + * + * repeated string input_modes = 6; + * @return A list containing the inputModes. + */ + java.util.List + getInputModesList(); + /** + *
            +   * Possible input modalities supported.
            +   * 
            + * + * repeated string input_modes = 6; + * @return The count of inputModes. + */ + int getInputModesCount(); + /** + *
            +   * Possible input modalities supported.
            +   * 
            + * + * repeated string input_modes = 6; + * @param index The index of the element to return. + * @return The inputModes at the given index. + */ + java.lang.String getInputModes(int index); + /** + *
            +   * Possible input modalities supported.
            +   * 
            + * + * repeated string input_modes = 6; + * @param index The index of the value to return. + * @return The bytes of the inputModes at the given index. + */ + com.google.protobuf.ByteString + getInputModesBytes(int index); + + /** + *
            +   * Possible output modalities produced
            +   * 
            + * + * repeated string output_modes = 7; + * @return A list containing the outputModes. + */ + java.util.List + getOutputModesList(); + /** + *
            +   * Possible output modalities produced
            +   * 
            + * + * repeated string output_modes = 7; + * @return The count of outputModes. + */ + int getOutputModesCount(); + /** + *
            +   * Possible output modalities produced
            +   * 
            + * + * repeated string output_modes = 7; + * @param index The index of the element to return. + * @return The outputModes at the given index. + */ + java.lang.String getOutputModes(int index); + /** + *
            +   * Possible output modalities produced
            +   * 
            + * + * repeated string output_modes = 7; + * @param index The index of the value to return. + * @return The bytes of the outputModes at the given index. + */ + com.google.protobuf.ByteString + getOutputModesBytes(int index); + + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + java.util.List + getSecurityList(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + org.a2aproject.sdk.compat03.grpc.Security getSecurity(int index); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + int getSecurityCount(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + java.util.List + getSecurityOrBuilderList(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Security schemes necessary for the agent to leverage this skill.
            +   * As in the overall AgentCard.security, this list represents a logical OR of
            +   * security requirement objects. Each object is a set of security schemes
            +   * that must be used together (a logical AND).
            +   * 
            + * + * repeated .a2a.v1.Security security = 8; + */ + org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder getSecurityOrBuilder( + int index); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Artifact.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Artifact.java new file mode 100644 index 000000000..e45a33300 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Artifact.java @@ -0,0 +1,1799 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Artifacts are the container for task completed results. These are similar
            + * to Messages but are intended to be the product of a task, as opposed to
            + * point-to-point communication.
            + * 
            + * + * Protobuf type {@code a2a.v1.Artifact} + */ +@com.google.protobuf.Generated +public final class Artifact extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.Artifact) + ArtifactOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "Artifact"); + } + // Use Artifact.newBuilder() to construct. + private Artifact(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Artifact() { + artifactId_ = ""; + name_ = ""; + description_ = ""; + parts_ = java.util.Collections.emptyList(); + extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Artifact_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Artifact_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Artifact.class, org.a2aproject.sdk.compat03.grpc.Artifact.Builder.class); + } + + private int bitField0_; + public static final int ARTIFACT_ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object artifactId_ = ""; + /** + *
            +   * Unique id for the artifact. It must be at least unique within a task.
            +   * 
            + * + * string artifact_id = 1; + * @return The artifactId. + */ + @java.lang.Override + public java.lang.String getArtifactId() { + java.lang.Object ref = artifactId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + artifactId_ = s; + return s; + } + } + /** + *
            +   * Unique id for the artifact. It must be at least unique within a task.
            +   * 
            + * + * string artifact_id = 1; + * @return The bytes for artifactId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getArtifactIdBytes() { + java.lang.Object ref = artifactId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + artifactId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int NAME_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * A human readable name for the artifact.
            +   * 
            + * + * string name = 3; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * A human readable name for the artifact.
            +   * 
            + * + * string name = 3; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DESCRIPTION_FIELD_NUMBER = 4; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * A human readable description of the artifact, optional.
            +   * 
            + * + * string description = 4; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * A human readable description of the artifact, optional.
            +   * 
            + * + * string description = 4; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PARTS_FIELD_NUMBER = 5; + @SuppressWarnings("serial") + private java.util.List parts_; + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + @java.lang.Override + public java.util.List getPartsList() { + return parts_; + } + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + @java.lang.Override + public java.util.List + getPartsOrBuilderList() { + return parts_; + } + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + @java.lang.Override + public int getPartsCount() { + return parts_.size(); + } + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Part getParts(int index) { + return parts_.get(index); + } + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PartOrBuilder getPartsOrBuilder( + int index) { + return parts_.get(index); + } + + public static final int METADATA_FIELD_NUMBER = 6; + private com.google.protobuf.Struct metadata_; + /** + *
            +   * Optional metadata included with the artifact.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + @java.lang.Override + public boolean hasMetadata() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * Optional metadata included with the artifact.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + @java.lang.Override + public com.google.protobuf.Struct getMetadata() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + /** + *
            +   * Optional metadata included with the artifact.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + + public static final int EXTENSIONS_FIELD_NUMBER = 7; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * The URIs of extensions that are present or contributed to this Artifact.
            +   * 
            + * + * repeated string extensions = 7; + * @return A list containing the extensions. + */ + public com.google.protobuf.ProtocolStringList + getExtensionsList() { + return extensions_; + } + /** + *
            +   * The URIs of extensions that are present or contributed to this Artifact.
            +   * 
            + * + * repeated string extensions = 7; + * @return The count of extensions. + */ + public int getExtensionsCount() { + return extensions_.size(); + } + /** + *
            +   * The URIs of extensions that are present or contributed to this Artifact.
            +   * 
            + * + * repeated string extensions = 7; + * @param index The index of the element to return. + * @return The extensions at the given index. + */ + public java.lang.String getExtensions(int index) { + return extensions_.get(index); + } + /** + *
            +   * The URIs of extensions that are present or contributed to this Artifact.
            +   * 
            + * + * repeated string extensions = 7; + * @param index The index of the value to return. + * @return The bytes of the extensions at the given index. + */ + public com.google.protobuf.ByteString + getExtensionsBytes(int index) { + return extensions_.getByteString(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(artifactId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, artifactId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, name_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 4, description_); + } + for (int i = 0; i < parts_.size(); i++) { + output.writeMessage(5, parts_.get(i)); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(6, getMetadata()); + } + for (int i = 0; i < extensions_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 7, extensions_.getRaw(i)); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(artifactId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, artifactId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, name_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(4, description_); + } + for (int i = 0; i < parts_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, parts_.get(i)); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, getMetadata()); + } + { + int dataSize = 0; + for (int i = 0; i < extensions_.size(); i++) { + dataSize += computeStringSizeNoTag(extensions_.getRaw(i)); + } + size += dataSize; + size += 1 * getExtensionsList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.Artifact)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.Artifact other = (org.a2aproject.sdk.compat03.grpc.Artifact) obj; + + if (!getArtifactId() + .equals(other.getArtifactId())) return false; + if (!getName() + .equals(other.getName())) return false; + if (!getDescription() + .equals(other.getDescription())) return false; + if (!getPartsList() + .equals(other.getPartsList())) return false; + if (hasMetadata() != other.hasMetadata()) return false; + if (hasMetadata()) { + if (!getMetadata() + .equals(other.getMetadata())) return false; + } + if (!getExtensionsList() + .equals(other.getExtensionsList())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ARTIFACT_ID_FIELD_NUMBER; + hash = (53 * hash) + getArtifactId().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + if (getPartsCount() > 0) { + hash = (37 * hash) + PARTS_FIELD_NUMBER; + hash = (53 * hash) + getPartsList().hashCode(); + } + if (hasMetadata()) { + hash = (37 * hash) + METADATA_FIELD_NUMBER; + hash = (53 * hash) + getMetadata().hashCode(); + } + if (getExtensionsCount() > 0) { + hash = (37 * hash) + EXTENSIONS_FIELD_NUMBER; + hash = (53 * hash) + getExtensionsList().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.Artifact parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.Artifact parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Artifact parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.Artifact prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Artifacts are the container for task completed results. These are similar
            +   * to Messages but are intended to be the product of a task, as opposed to
            +   * point-to-point communication.
            +   * 
            + * + * Protobuf type {@code a2a.v1.Artifact} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.Artifact) + org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Artifact_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Artifact_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Artifact.class, org.a2aproject.sdk.compat03.grpc.Artifact.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.Artifact.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetPartsFieldBuilder(); + internalGetMetadataFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + artifactId_ = ""; + name_ = ""; + description_ = ""; + if (partsBuilder_ == null) { + parts_ = java.util.Collections.emptyList(); + } else { + parts_ = null; + partsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_Artifact_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Artifact getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Artifact build() { + org.a2aproject.sdk.compat03.grpc.Artifact result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Artifact buildPartial() { + org.a2aproject.sdk.compat03.grpc.Artifact result = new org.a2aproject.sdk.compat03.grpc.Artifact(this); + buildPartialRepeatedFields(result); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartialRepeatedFields(org.a2aproject.sdk.compat03.grpc.Artifact result) { + if (partsBuilder_ == null) { + if (((bitField0_ & 0x00000008) != 0)) { + parts_ = java.util.Collections.unmodifiableList(parts_); + bitField0_ = (bitField0_ & ~0x00000008); + } + result.parts_ = parts_; + } else { + result.parts_ = partsBuilder_.build(); + } + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.Artifact result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.artifactId_ = artifactId_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.name_ = name_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.description_ = description_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000010) != 0)) { + result.metadata_ = metadataBuilder_ == null + ? metadata_ + : metadataBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000020) != 0)) { + extensions_.makeImmutable(); + result.extensions_ = extensions_; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.Artifact) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.Artifact)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.Artifact other) { + if (other == org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance()) return this; + if (!other.getArtifactId().isEmpty()) { + artifactId_ = other.artifactId_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000004; + onChanged(); + } + if (partsBuilder_ == null) { + if (!other.parts_.isEmpty()) { + if (parts_.isEmpty()) { + parts_ = other.parts_; + bitField0_ = (bitField0_ & ~0x00000008); + } else { + ensurePartsIsMutable(); + parts_.addAll(other.parts_); + } + onChanged(); + } + } else { + if (!other.parts_.isEmpty()) { + if (partsBuilder_.isEmpty()) { + partsBuilder_.dispose(); + partsBuilder_ = null; + parts_ = other.parts_; + bitField0_ = (bitField0_ & ~0x00000008); + partsBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetPartsFieldBuilder() : null; + } else { + partsBuilder_.addAllMessages(other.parts_); + } + } + } + if (other.hasMetadata()) { + mergeMetadata(other.getMetadata()); + } + if (!other.extensions_.isEmpty()) { + if (extensions_.isEmpty()) { + extensions_ = other.extensions_; + bitField0_ |= 0x00000020; + } else { + ensureExtensionsIsMutable(); + extensions_.addAll(other.extensions_); + } + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + artifactId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 26: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 26 + case 34: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 34 + case 42: { + org.a2aproject.sdk.compat03.grpc.Part m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.Part.parser(), + extensionRegistry); + if (partsBuilder_ == null) { + ensurePartsIsMutable(); + parts_.add(m); + } else { + partsBuilder_.addMessage(m); + } + break; + } // case 42 + case 50: { + input.readMessage( + internalGetMetadataFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000010; + break; + } // case 50 + case 58: { + java.lang.String s = input.readStringRequireUtf8(); + ensureExtensionsIsMutable(); + extensions_.add(s); + break; + } // case 58 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object artifactId_ = ""; + /** + *
            +     * Unique id for the artifact. It must be at least unique within a task.
            +     * 
            + * + * string artifact_id = 1; + * @return The artifactId. + */ + public java.lang.String getArtifactId() { + java.lang.Object ref = artifactId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + artifactId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Unique id for the artifact. It must be at least unique within a task.
            +     * 
            + * + * string artifact_id = 1; + * @return The bytes for artifactId. + */ + public com.google.protobuf.ByteString + getArtifactIdBytes() { + java.lang.Object ref = artifactId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + artifactId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Unique id for the artifact. It must be at least unique within a task.
            +     * 
            + * + * string artifact_id = 1; + * @param value The artifactId to set. + * @return This builder for chaining. + */ + public Builder setArtifactId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + artifactId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Unique id for the artifact. It must be at least unique within a task.
            +     * 
            + * + * string artifact_id = 1; + * @return This builder for chaining. + */ + public Builder clearArtifactId() { + artifactId_ = getDefaultInstance().getArtifactId(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * Unique id for the artifact. It must be at least unique within a task.
            +     * 
            + * + * string artifact_id = 1; + * @param value The bytes for artifactId to set. + * @return This builder for chaining. + */ + public Builder setArtifactIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + artifactId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object name_ = ""; + /** + *
            +     * A human readable name for the artifact.
            +     * 
            + * + * string name = 3; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A human readable name for the artifact.
            +     * 
            + * + * string name = 3; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A human readable name for the artifact.
            +     * 
            + * + * string name = 3; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A human readable name for the artifact.
            +     * 
            + * + * string name = 3; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * A human readable name for the artifact.
            +     * 
            + * + * string name = 3; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object description_ = ""; + /** + *
            +     * A human readable description of the artifact, optional.
            +     * 
            + * + * string description = 4; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A human readable description of the artifact, optional.
            +     * 
            + * + * string description = 4; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A human readable description of the artifact, optional.
            +     * 
            + * + * string description = 4; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * A human readable description of the artifact, optional.
            +     * 
            + * + * string description = 4; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * A human readable description of the artifact, optional.
            +     * 
            + * + * string description = 4; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private java.util.List parts_ = + java.util.Collections.emptyList(); + private void ensurePartsIsMutable() { + if (!((bitField0_ & 0x00000008) != 0)) { + parts_ = new java.util.ArrayList(parts_); + bitField0_ |= 0x00000008; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Part, org.a2aproject.sdk.compat03.grpc.Part.Builder, org.a2aproject.sdk.compat03.grpc.PartOrBuilder> partsBuilder_; + + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public java.util.List getPartsList() { + if (partsBuilder_ == null) { + return java.util.Collections.unmodifiableList(parts_); + } else { + return partsBuilder_.getMessageList(); + } + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public int getPartsCount() { + if (partsBuilder_ == null) { + return parts_.size(); + } else { + return partsBuilder_.getCount(); + } + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Part getParts(int index) { + if (partsBuilder_ == null) { + return parts_.get(index); + } else { + return partsBuilder_.getMessage(index); + } + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder setParts( + int index, org.a2aproject.sdk.compat03.grpc.Part value) { + if (partsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensurePartsIsMutable(); + parts_.set(index, value); + onChanged(); + } else { + partsBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder setParts( + int index, org.a2aproject.sdk.compat03.grpc.Part.Builder builderForValue) { + if (partsBuilder_ == null) { + ensurePartsIsMutable(); + parts_.set(index, builderForValue.build()); + onChanged(); + } else { + partsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder addParts(org.a2aproject.sdk.compat03.grpc.Part value) { + if (partsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensurePartsIsMutable(); + parts_.add(value); + onChanged(); + } else { + partsBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder addParts( + int index, org.a2aproject.sdk.compat03.grpc.Part value) { + if (partsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensurePartsIsMutable(); + parts_.add(index, value); + onChanged(); + } else { + partsBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder addParts( + org.a2aproject.sdk.compat03.grpc.Part.Builder builderForValue) { + if (partsBuilder_ == null) { + ensurePartsIsMutable(); + parts_.add(builderForValue.build()); + onChanged(); + } else { + partsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder addParts( + int index, org.a2aproject.sdk.compat03.grpc.Part.Builder builderForValue) { + if (partsBuilder_ == null) { + ensurePartsIsMutable(); + parts_.add(index, builderForValue.build()); + onChanged(); + } else { + partsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder addAllParts( + java.lang.Iterable values) { + if (partsBuilder_ == null) { + ensurePartsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, parts_); + onChanged(); + } else { + partsBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder clearParts() { + if (partsBuilder_ == null) { + parts_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + } else { + partsBuilder_.clear(); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public Builder removeParts(int index) { + if (partsBuilder_ == null) { + ensurePartsIsMutable(); + parts_.remove(index); + onChanged(); + } else { + partsBuilder_.remove(index); + } + return this; + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Part.Builder getPartsBuilder( + int index) { + return internalGetPartsFieldBuilder().getBuilder(index); + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public org.a2aproject.sdk.compat03.grpc.PartOrBuilder getPartsOrBuilder( + int index) { + if (partsBuilder_ == null) { + return parts_.get(index); } else { + return partsBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public java.util.List + getPartsOrBuilderList() { + if (partsBuilder_ != null) { + return partsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(parts_); + } + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Part.Builder addPartsBuilder() { + return internalGetPartsFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.Part.getDefaultInstance()); + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Part.Builder addPartsBuilder( + int index) { + return internalGetPartsFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.Part.getDefaultInstance()); + } + /** + *
            +     * The content of the artifact.
            +     * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + public java.util.List + getPartsBuilderList() { + return internalGetPartsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Part, org.a2aproject.sdk.compat03.grpc.Part.Builder, org.a2aproject.sdk.compat03.grpc.PartOrBuilder> + internalGetPartsFieldBuilder() { + if (partsBuilder_ == null) { + partsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Part, org.a2aproject.sdk.compat03.grpc.Part.Builder, org.a2aproject.sdk.compat03.grpc.PartOrBuilder>( + parts_, + ((bitField0_ & 0x00000008) != 0), + getParentForChildren(), + isClean()); + parts_ = null; + } + return partsBuilder_; + } + + private com.google.protobuf.Struct metadata_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + public boolean hasMetadata() { + return ((bitField0_ & 0x00000010) != 0); + } + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + public com.google.protobuf.Struct getMetadata() { + if (metadataBuilder_ == null) { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } else { + return metadataBuilder_.getMessage(); + } + } + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder setMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + metadata_ = value; + } else { + metadataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder setMetadata( + com.google.protobuf.Struct.Builder builderForValue) { + if (metadataBuilder_ == null) { + metadata_ = builderForValue.build(); + } else { + metadataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder mergeMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (((bitField0_ & 0x00000010) != 0) && + metadata_ != null && + metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { + getMetadataBuilder().mergeFrom(value); + } else { + metadata_ = value; + } + } else { + metadataBuilder_.mergeFrom(value); + } + if (metadata_ != null) { + bitField0_ |= 0x00000010; + onChanged(); + } + return this; + } + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder clearMetadata() { + bitField0_ = (bitField0_ & ~0x00000010); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public com.google.protobuf.Struct.Builder getMetadataBuilder() { + bitField0_ |= 0x00000010; + onChanged(); + return internalGetMetadataFieldBuilder().getBuilder(); + } + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + if (metadataBuilder_ != null) { + return metadataBuilder_.getMessageOrBuilder(); + } else { + return metadata_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + } + /** + *
            +     * Optional metadata included with the artifact.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetMetadataFieldBuilder() { + if (metadataBuilder_ == null) { + metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getMetadata(), + getParentForChildren(), + isClean()); + metadata_ = null; + } + return metadataBuilder_; + } + + private com.google.protobuf.LazyStringArrayList extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureExtensionsIsMutable() { + if (!extensions_.isModifiable()) { + extensions_ = new com.google.protobuf.LazyStringArrayList(extensions_); + } + bitField0_ |= 0x00000020; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @return A list containing the extensions. + */ + public com.google.protobuf.ProtocolStringList + getExtensionsList() { + extensions_.makeImmutable(); + return extensions_; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @return The count of extensions. + */ + public int getExtensionsCount() { + return extensions_.size(); + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @param index The index of the element to return. + * @return The extensions at the given index. + */ + public java.lang.String getExtensions(int index) { + return extensions_.get(index); + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @param index The index of the value to return. + * @return The bytes of the extensions at the given index. + */ + public com.google.protobuf.ByteString + getExtensionsBytes(int index) { + return extensions_.getByteString(index); + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @param index The index to set the value at. + * @param value The extensions to set. + * @return This builder for chaining. + */ + public Builder setExtensions( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureExtensionsIsMutable(); + extensions_.set(index, value); + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @param value The extensions to add. + * @return This builder for chaining. + */ + public Builder addExtensions( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureExtensionsIsMutable(); + extensions_.add(value); + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @param values The extensions to add. + * @return This builder for chaining. + */ + public Builder addAllExtensions( + java.lang.Iterable values) { + ensureExtensionsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, extensions_); + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @return This builder for chaining. + */ + public Builder clearExtensions() { + extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020);; + onChanged(); + return this; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Artifact.
            +     * 
            + * + * repeated string extensions = 7; + * @param value The bytes of the extensions to add. + * @return This builder for chaining. + */ + public Builder addExtensionsBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureExtensionsIsMutable(); + extensions_.add(value); + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.Artifact) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.Artifact) + private static final org.a2aproject.sdk.compat03.grpc.Artifact DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.Artifact(); + } + + public static org.a2aproject.sdk.compat03.grpc.Artifact getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Artifact parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Artifact getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ArtifactOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ArtifactOrBuilder.java new file mode 100644 index 000000000..eeedc6acd --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ArtifactOrBuilder.java @@ -0,0 +1,184 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface ArtifactOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.Artifact) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Unique id for the artifact. It must be at least unique within a task.
            +   * 
            + * + * string artifact_id = 1; + * @return The artifactId. + */ + java.lang.String getArtifactId(); + /** + *
            +   * Unique id for the artifact. It must be at least unique within a task.
            +   * 
            + * + * string artifact_id = 1; + * @return The bytes for artifactId. + */ + com.google.protobuf.ByteString + getArtifactIdBytes(); + + /** + *
            +   * A human readable name for the artifact.
            +   * 
            + * + * string name = 3; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * A human readable name for the artifact.
            +   * 
            + * + * string name = 3; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + *
            +   * A human readable description of the artifact, optional.
            +   * 
            + * + * string description = 4; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * A human readable description of the artifact, optional.
            +   * 
            + * + * string description = 4; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + java.util.List + getPartsList(); + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + org.a2aproject.sdk.compat03.grpc.Part getParts(int index); + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + int getPartsCount(); + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + java.util.List + getPartsOrBuilderList(); + /** + *
            +   * The content of the artifact.
            +   * 
            + * + * repeated .a2a.v1.Part parts = 5; + */ + org.a2aproject.sdk.compat03.grpc.PartOrBuilder getPartsOrBuilder( + int index); + + /** + *
            +   * Optional metadata included with the artifact.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + boolean hasMetadata(); + /** + *
            +   * Optional metadata included with the artifact.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + com.google.protobuf.Struct getMetadata(); + /** + *
            +   * Optional metadata included with the artifact.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); + + /** + *
            +   * The URIs of extensions that are present or contributed to this Artifact.
            +   * 
            + * + * repeated string extensions = 7; + * @return A list containing the extensions. + */ + java.util.List + getExtensionsList(); + /** + *
            +   * The URIs of extensions that are present or contributed to this Artifact.
            +   * 
            + * + * repeated string extensions = 7; + * @return The count of extensions. + */ + int getExtensionsCount(); + /** + *
            +   * The URIs of extensions that are present or contributed to this Artifact.
            +   * 
            + * + * repeated string extensions = 7; + * @param index The index of the element to return. + * @return The extensions at the given index. + */ + java.lang.String getExtensions(int index); + /** + *
            +   * The URIs of extensions that are present or contributed to this Artifact.
            +   * 
            + * + * repeated string extensions = 7; + * @param index The index of the value to return. + * @return The bytes of the extensions at the given index. + */ + com.google.protobuf.ByteString + getExtensionsBytes(int index); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthenticationInfo.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthenticationInfo.java new file mode 100644 index 000000000..d2b3d4f1a --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthenticationInfo.java @@ -0,0 +1,779 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Defines authentication details, used for push notifications.
            + * 
            + * + * Protobuf type {@code a2a.v1.AuthenticationInfo} + */ +@com.google.protobuf.Generated +public final class AuthenticationInfo extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AuthenticationInfo) + AuthenticationInfoOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AuthenticationInfo"); + } + // Use AuthenticationInfo.newBuilder() to construct. + private AuthenticationInfo(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AuthenticationInfo() { + schemes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + credentials_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.class, org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.Builder.class); + } + + public static final int SCHEMES_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList schemes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * Supported authentication schemes - e.g. Basic, Bearer, etc
            +   * 
            + * + * repeated string schemes = 1; + * @return A list containing the schemes. + */ + public com.google.protobuf.ProtocolStringList + getSchemesList() { + return schemes_; + } + /** + *
            +   * Supported authentication schemes - e.g. Basic, Bearer, etc
            +   * 
            + * + * repeated string schemes = 1; + * @return The count of schemes. + */ + public int getSchemesCount() { + return schemes_.size(); + } + /** + *
            +   * Supported authentication schemes - e.g. Basic, Bearer, etc
            +   * 
            + * + * repeated string schemes = 1; + * @param index The index of the element to return. + * @return The schemes at the given index. + */ + public java.lang.String getSchemes(int index) { + return schemes_.get(index); + } + /** + *
            +   * Supported authentication schemes - e.g. Basic, Bearer, etc
            +   * 
            + * + * repeated string schemes = 1; + * @param index The index of the value to return. + * @return The bytes of the schemes at the given index. + */ + public com.google.protobuf.ByteString + getSchemesBytes(int index) { + return schemes_.getByteString(index); + } + + public static final int CREDENTIALS_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object credentials_ = ""; + /** + *
            +   * Optional credentials
            +   * 
            + * + * string credentials = 2; + * @return The credentials. + */ + @java.lang.Override + public java.lang.String getCredentials() { + java.lang.Object ref = credentials_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + credentials_ = s; + return s; + } + } + /** + *
            +   * Optional credentials
            +   * 
            + * + * string credentials = 2; + * @return The bytes for credentials. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getCredentialsBytes() { + java.lang.Object ref = credentials_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + credentials_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < schemes_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, schemes_.getRaw(i)); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(credentials_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, credentials_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + { + int dataSize = 0; + for (int i = 0; i < schemes_.size(); i++) { + dataSize += computeStringSizeNoTag(schemes_.getRaw(i)); + } + size += dataSize; + size += 1 * getSchemesList().size(); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(credentials_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, credentials_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AuthenticationInfo)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo other = (org.a2aproject.sdk.compat03.grpc.AuthenticationInfo) obj; + + if (!getSchemesList() + .equals(other.getSchemesList())) return false; + if (!getCredentials() + .equals(other.getCredentials())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getSchemesCount() > 0) { + hash = (37 * hash) + SCHEMES_FIELD_NUMBER; + hash = (53 * hash) + getSchemesList().hashCode(); + } + hash = (37 * hash) + CREDENTIALS_FIELD_NUMBER; + hash = (53 * hash) + getCredentials().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AuthenticationInfo prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Defines authentication details, used for push notifications.
            +   * 
            + * + * Protobuf type {@code a2a.v1.AuthenticationInfo} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AuthenticationInfo) + org.a2aproject.sdk.compat03.grpc.AuthenticationInfoOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.class, org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + schemes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + credentials_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfo getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfo build() { + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfo buildPartial() { + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo result = new org.a2aproject.sdk.compat03.grpc.AuthenticationInfo(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AuthenticationInfo result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + schemes_.makeImmutable(); + result.schemes_ = schemes_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.credentials_ = credentials_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AuthenticationInfo) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AuthenticationInfo)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AuthenticationInfo other) { + if (other == org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.getDefaultInstance()) return this; + if (!other.schemes_.isEmpty()) { + if (schemes_.isEmpty()) { + schemes_ = other.schemes_; + bitField0_ |= 0x00000001; + } else { + ensureSchemesIsMutable(); + schemes_.addAll(other.schemes_); + } + onChanged(); + } + if (!other.getCredentials().isEmpty()) { + credentials_ = other.credentials_; + bitField0_ |= 0x00000002; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + ensureSchemesIsMutable(); + schemes_.add(s); + break; + } // case 10 + case 18: { + credentials_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private com.google.protobuf.LazyStringArrayList schemes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureSchemesIsMutable() { + if (!schemes_.isModifiable()) { + schemes_ = new com.google.protobuf.LazyStringArrayList(schemes_); + } + bitField0_ |= 0x00000001; + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @return A list containing the schemes. + */ + public com.google.protobuf.ProtocolStringList + getSchemesList() { + schemes_.makeImmutable(); + return schemes_; + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @return The count of schemes. + */ + public int getSchemesCount() { + return schemes_.size(); + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @param index The index of the element to return. + * @return The schemes at the given index. + */ + public java.lang.String getSchemes(int index) { + return schemes_.get(index); + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @param index The index of the value to return. + * @return The bytes of the schemes at the given index. + */ + public com.google.protobuf.ByteString + getSchemesBytes(int index) { + return schemes_.getByteString(index); + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @param index The index to set the value at. + * @param value The schemes to set. + * @return This builder for chaining. + */ + public Builder setSchemes( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureSchemesIsMutable(); + schemes_.set(index, value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @param value The schemes to add. + * @return This builder for chaining. + */ + public Builder addSchemes( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureSchemesIsMutable(); + schemes_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @param values The schemes to add. + * @return This builder for chaining. + */ + public Builder addAllSchemes( + java.lang.Iterable values) { + ensureSchemesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, schemes_); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @return This builder for chaining. + */ + public Builder clearSchemes() { + schemes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001);; + onChanged(); + return this; + } + /** + *
            +     * Supported authentication schemes - e.g. Basic, Bearer, etc
            +     * 
            + * + * repeated string schemes = 1; + * @param value The bytes of the schemes to add. + * @return This builder for chaining. + */ + public Builder addSchemesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureSchemesIsMutable(); + schemes_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object credentials_ = ""; + /** + *
            +     * Optional credentials
            +     * 
            + * + * string credentials = 2; + * @return The credentials. + */ + public java.lang.String getCredentials() { + java.lang.Object ref = credentials_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + credentials_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Optional credentials
            +     * 
            + * + * string credentials = 2; + * @return The bytes for credentials. + */ + public com.google.protobuf.ByteString + getCredentialsBytes() { + java.lang.Object ref = credentials_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + credentials_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Optional credentials
            +     * 
            + * + * string credentials = 2; + * @param value The credentials to set. + * @return This builder for chaining. + */ + public Builder setCredentials( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + credentials_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * Optional credentials
            +     * 
            + * + * string credentials = 2; + * @return This builder for chaining. + */ + public Builder clearCredentials() { + credentials_ = getDefaultInstance().getCredentials(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * Optional credentials
            +     * 
            + * + * string credentials = 2; + * @param value The bytes for credentials to set. + * @return This builder for chaining. + */ + public Builder setCredentialsBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + credentials_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AuthenticationInfo) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AuthenticationInfo) + private static final org.a2aproject.sdk.compat03.grpc.AuthenticationInfo DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AuthenticationInfo(); + } + + public static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AuthenticationInfo parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfo getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthenticationInfoOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthenticationInfoOrBuilder.java new file mode 100644 index 000000000..6b25b7358 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthenticationInfoOrBuilder.java @@ -0,0 +1,73 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AuthenticationInfoOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AuthenticationInfo) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Supported authentication schemes - e.g. Basic, Bearer, etc
            +   * 
            + * + * repeated string schemes = 1; + * @return A list containing the schemes. + */ + java.util.List + getSchemesList(); + /** + *
            +   * Supported authentication schemes - e.g. Basic, Bearer, etc
            +   * 
            + * + * repeated string schemes = 1; + * @return The count of schemes. + */ + int getSchemesCount(); + /** + *
            +   * Supported authentication schemes - e.g. Basic, Bearer, etc
            +   * 
            + * + * repeated string schemes = 1; + * @param index The index of the element to return. + * @return The schemes at the given index. + */ + java.lang.String getSchemes(int index); + /** + *
            +   * Supported authentication schemes - e.g. Basic, Bearer, etc
            +   * 
            + * + * repeated string schemes = 1; + * @param index The index of the value to return. + * @return The bytes of the schemes at the given index. + */ + com.google.protobuf.ByteString + getSchemesBytes(int index); + + /** + *
            +   * Optional credentials
            +   * 
            + * + * string credentials = 2; + * @return The credentials. + */ + java.lang.String getCredentials(); + /** + *
            +   * Optional credentials
            +   * 
            + * + * string credentials = 2; + * @return The bytes for credentials. + */ + com.google.protobuf.ByteString + getCredentialsBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthorizationCodeOAuthFlow.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthorizationCodeOAuthFlow.java new file mode 100644 index 000000000..4c971f31e --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthorizationCodeOAuthFlow.java @@ -0,0 +1,1213 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.AuthorizationCodeOAuthFlow} + */ +@com.google.protobuf.Generated +public final class AuthorizationCodeOAuthFlow extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.AuthorizationCodeOAuthFlow) + AuthorizationCodeOAuthFlowOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "AuthorizationCodeOAuthFlow"); + } + // Use AuthorizationCodeOAuthFlow.newBuilder() to construct. + private AuthorizationCodeOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private AuthorizationCodeOAuthFlow() { + authorizationUrl_ = ""; + tokenUrl_ = ""; + refreshUrl_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 4: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.class, org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.Builder.class); + } + + public static final int AUTHORIZATION_URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object authorizationUrl_ = ""; + /** + *
            +   * The authorization URL to be used for this flow. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS
            +   * 
            + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + @java.lang.Override + public java.lang.String getAuthorizationUrl() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + authorizationUrl_ = s; + return s; + } + } + /** + *
            +   * The authorization URL to be used for this flow. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS
            +   * 
            + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getAuthorizationUrlBytes() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + authorizationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TOKEN_URL_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object tokenUrl_ = ""; + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 2; + * @return The tokenUrl. + */ + @java.lang.Override + public java.lang.String getTokenUrl() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + tokenUrl_ = s; + return s; + } + } + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 2; + * @return The bytes for tokenUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTokenUrlBytes() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tokenUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REFRESH_URL_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object refreshUrl_ = ""; + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 3; + * @return The refreshUrl. + */ + @java.lang.Override + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } + } + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 3; + * @return The bytes for refreshUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCOPES_FIELD_NUMBER = 4; + private static final class ScopesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, java.lang.String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, authorizationUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, tokenUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, refreshUrl_); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetScopes(), + ScopesDefaultEntryHolder.defaultEntry, + 4); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, authorizationUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tokenUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, refreshUrl_); + } + for (java.util.Map.Entry entry + : internalGetScopes().getMap().entrySet()) { + com.google.protobuf.MapEntry + scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, scopes__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow other = (org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) obj; + + if (!getAuthorizationUrl() + .equals(other.getAuthorizationUrl())) return false; + if (!getTokenUrl() + .equals(other.getTokenUrl())) return false; + if (!getRefreshUrl() + .equals(other.getRefreshUrl())) return false; + if (!internalGetScopes().equals( + other.internalGetScopes())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + AUTHORIZATION_URL_FIELD_NUMBER; + hash = (53 * hash) + getAuthorizationUrl().hashCode(); + hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; + hash = (53 * hash) + getTokenUrl().hashCode(); + hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; + hash = (53 * hash) + getRefreshUrl().hashCode(); + if (!internalGetScopes().getMap().isEmpty()) { + hash = (37 * hash) + SCOPES_FIELD_NUMBER; + hash = (53 * hash) + internalGetScopes().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.AuthorizationCodeOAuthFlow} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.AuthorizationCodeOAuthFlow) + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlowOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 4: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 4: + return internalGetMutableScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.class, org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + authorizationUrl_ = ""; + tokenUrl_ = ""; + refreshUrl_ = ""; + internalGetMutableScopes().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow build() { + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow buildPartial() { + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow result = new org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.authorizationUrl_ = authorizationUrl_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.tokenUrl_ = tokenUrl_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.refreshUrl_ = refreshUrl_; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.scopes_ = internalGetScopes(); + result.scopes_.makeImmutable(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow other) { + if (other == org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance()) return this; + if (!other.getAuthorizationUrl().isEmpty()) { + authorizationUrl_ = other.authorizationUrl_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getTokenUrl().isEmpty()) { + tokenUrl_ = other.tokenUrl_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getRefreshUrl().isEmpty()) { + refreshUrl_ = other.refreshUrl_; + bitField0_ |= 0x00000004; + onChanged(); + } + internalGetMutableScopes().mergeFrom( + other.internalGetScopes()); + bitField0_ |= 0x00000008; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + authorizationUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + tokenUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + refreshUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 34: { + com.google.protobuf.MapEntry + scopes__ = input.readMessage( + ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableScopes().getMutableMap().put( + scopes__.getKey(), scopes__.getValue()); + bitField0_ |= 0x00000008; + break; + } // case 34 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object authorizationUrl_ = ""; + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + public java.lang.String getAuthorizationUrl() { + java.lang.Object ref = authorizationUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + authorizationUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + public com.google.protobuf.ByteString + getAuthorizationUrlBytes() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + authorizationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @param value The authorizationUrl to set. + * @return This builder for chaining. + */ + public Builder setAuthorizationUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + authorizationUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @return This builder for chaining. + */ + public Builder clearAuthorizationUrl() { + authorizationUrl_ = getDefaultInstance().getAuthorizationUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @param value The bytes for authorizationUrl to set. + * @return This builder for chaining. + */ + public Builder setAuthorizationUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + authorizationUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object tokenUrl_ = ""; + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 2; + * @return The tokenUrl. + */ + public java.lang.String getTokenUrl() { + java.lang.Object ref = tokenUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + tokenUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 2; + * @return The bytes for tokenUrl. + */ + public com.google.protobuf.ByteString + getTokenUrlBytes() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tokenUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 2; + * @param value The tokenUrl to set. + * @return This builder for chaining. + */ + public Builder setTokenUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + tokenUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 2; + * @return This builder for chaining. + */ + public Builder clearTokenUrl() { + tokenUrl_ = getDefaultInstance().getTokenUrl(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 2; + * @param value The bytes for tokenUrl to set. + * @return This builder for chaining. + */ + public Builder setTokenUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + tokenUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object refreshUrl_ = ""; + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 3; + * @return The refreshUrl. + */ + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 3; + * @return The bytes for refreshUrl. + */ + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 3; + * @param value The refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + refreshUrl_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 3; + * @return This builder for chaining. + */ + public Builder clearRefreshUrl() { + refreshUrl_ = getDefaultInstance().getRefreshUrl(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 3; + * @param value The bytes for refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + refreshUrl_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + private com.google.protobuf.MapField + internalGetMutableScopes() { + if (scopes_ == null) { + scopes_ = com.google.protobuf.MapField.newMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + if (!scopes_.isMutable()) { + scopes_ = scopes_.copy(); + } + bitField0_ |= 0x00000008; + onChanged(); + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 4; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 4; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 4; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 4; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + public Builder clearScopes() { + bitField0_ = (bitField0_ & ~0x00000008); + internalGetMutableScopes().getMutableMap() + .clear(); + return this; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 4; + */ + public Builder removeScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableScopes().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableScopes() { + bitField0_ |= 0x00000008; + return internalGetMutableScopes().getMutableMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 4; + */ + public Builder putScopes( + java.lang.String key, + java.lang.String value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableScopes().getMutableMap() + .put(key, value); + bitField0_ |= 0x00000008; + return this; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 4; + */ + public Builder putAllScopes( + java.util.Map values) { + internalGetMutableScopes().getMutableMap() + .putAll(values); + bitField0_ |= 0x00000008; + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.AuthorizationCodeOAuthFlow) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.AuthorizationCodeOAuthFlow) + private static final org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow(); + } + + public static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public AuthorizationCodeOAuthFlow parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthorizationCodeOAuthFlowOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthorizationCodeOAuthFlowOrBuilder.java new file mode 100644 index 000000000..399a78bcb --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/AuthorizationCodeOAuthFlowOrBuilder.java @@ -0,0 +1,137 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface AuthorizationCodeOAuthFlowOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.AuthorizationCodeOAuthFlow) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The authorization URL to be used for this flow. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS
            +   * 
            + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + java.lang.String getAuthorizationUrl(); + /** + *
            +   * The authorization URL to be used for this flow. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS
            +   * 
            + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + com.google.protobuf.ByteString + getAuthorizationUrlBytes(); + + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 2; + * @return The tokenUrl. + */ + java.lang.String getTokenUrl(); + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 2; + * @return The bytes for tokenUrl. + */ + com.google.protobuf.ByteString + getTokenUrlBytes(); + + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 3; + * @return The refreshUrl. + */ + java.lang.String getRefreshUrl(); + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 3; + * @return The bytes for refreshUrl. + */ + com.google.protobuf.ByteString + getRefreshUrlBytes(); + + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + int getScopesCount(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + boolean containsScopes( + java.lang.String key); + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getScopes(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + java.util.Map + getScopesMap(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 4; + */ + java.lang.String getScopesOrThrow( + java.lang.String key); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CancelTaskRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CancelTaskRequest.java new file mode 100644 index 000000000..397dd9977 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CancelTaskRequest.java @@ -0,0 +1,530 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.CancelTaskRequest} + */ +@com.google.protobuf.Generated +public final class CancelTaskRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.CancelTaskRequest) + CancelTaskRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "CancelTaskRequest"); + } + // Use CancelTaskRequest.newBuilder() to construct. + private CancelTaskRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private CancelTaskRequest() { + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.class, org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.Builder.class); + } + + public static final int NAME_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.CancelTaskRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.CancelTaskRequest other = (org.a2aproject.sdk.compat03.grpc.CancelTaskRequest) obj; + + if (!getName() + .equals(other.getName())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.CancelTaskRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.CancelTaskRequest) + org.a2aproject.sdk.compat03.grpc.CancelTaskRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.class, org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + name_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.CancelTaskRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.CancelTaskRequest build() { + org.a2aproject.sdk.compat03.grpc.CancelTaskRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.CancelTaskRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.CancelTaskRequest result = new org.a2aproject.sdk.compat03.grpc.CancelTaskRequest(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.name_ = name_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.CancelTaskRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.CancelTaskRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.CancelTaskRequest.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000001; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.CancelTaskRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.CancelTaskRequest) + private static final org.a2aproject.sdk.compat03.grpc.CancelTaskRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.CancelTaskRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.CancelTaskRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public CancelTaskRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.CancelTaskRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CancelTaskRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CancelTaskRequestOrBuilder.java new file mode 100644 index 000000000..f46dc46c2 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CancelTaskRequestOrBuilder.java @@ -0,0 +1,32 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface CancelTaskRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.CancelTaskRequest) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ClientCredentialsOAuthFlow.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ClientCredentialsOAuthFlow.java new file mode 100644 index 000000000..79000ab25 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ClientCredentialsOAuthFlow.java @@ -0,0 +1,1042 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.ClientCredentialsOAuthFlow} + */ +@com.google.protobuf.Generated +public final class ClientCredentialsOAuthFlow extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.ClientCredentialsOAuthFlow) + ClientCredentialsOAuthFlowOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "ClientCredentialsOAuthFlow"); + } + // Use ClientCredentialsOAuthFlow.newBuilder() to construct. + private ClientCredentialsOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private ClientCredentialsOAuthFlow() { + tokenUrl_ = ""; + refreshUrl_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.class, org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.Builder.class); + } + + public static final int TOKEN_URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object tokenUrl_ = ""; + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 1; + * @return The tokenUrl. + */ + @java.lang.Override + public java.lang.String getTokenUrl() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + tokenUrl_ = s; + return s; + } + } + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTokenUrlBytes() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tokenUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REFRESH_URL_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object refreshUrl_ = ""; + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + @java.lang.Override + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } + } + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCOPES_FIELD_NUMBER = 3; + private static final class ScopesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, java.lang.String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, tokenUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetScopes(), + ScopesDefaultEntryHolder.defaultEntry, + 3); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tokenUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); + } + for (java.util.Map.Entry entry + : internalGetScopes().getMap().entrySet()) { + com.google.protobuf.MapEntry + scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, scopes__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow other = (org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) obj; + + if (!getTokenUrl() + .equals(other.getTokenUrl())) return false; + if (!getRefreshUrl() + .equals(other.getRefreshUrl())) return false; + if (!internalGetScopes().equals( + other.internalGetScopes())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; + hash = (53 * hash) + getTokenUrl().hashCode(); + hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; + hash = (53 * hash) + getRefreshUrl().hashCode(); + if (!internalGetScopes().getMap().isEmpty()) { + hash = (37 * hash) + SCOPES_FIELD_NUMBER; + hash = (53 * hash) + internalGetScopes().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.ClientCredentialsOAuthFlow} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.ClientCredentialsOAuthFlow) + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlowOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetMutableScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.class, org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + tokenUrl_ = ""; + refreshUrl_ = ""; + internalGetMutableScopes().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow build() { + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow buildPartial() { + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow result = new org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.tokenUrl_ = tokenUrl_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.refreshUrl_ = refreshUrl_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.scopes_ = internalGetScopes(); + result.scopes_.makeImmutable(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow other) { + if (other == org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance()) return this; + if (!other.getTokenUrl().isEmpty()) { + tokenUrl_ = other.tokenUrl_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getRefreshUrl().isEmpty()) { + refreshUrl_ = other.refreshUrl_; + bitField0_ |= 0x00000002; + onChanged(); + } + internalGetMutableScopes().mergeFrom( + other.internalGetScopes()); + bitField0_ |= 0x00000004; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + tokenUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + refreshUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + com.google.protobuf.MapEntry + scopes__ = input.readMessage( + ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableScopes().getMutableMap().put( + scopes__.getKey(), scopes__.getValue()); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object tokenUrl_ = ""; + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @return The tokenUrl. + */ + public java.lang.String getTokenUrl() { + java.lang.Object ref = tokenUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + tokenUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + public com.google.protobuf.ByteString + getTokenUrlBytes() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tokenUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @param value The tokenUrl to set. + * @return This builder for chaining. + */ + public Builder setTokenUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + tokenUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @return This builder for chaining. + */ + public Builder clearTokenUrl() { + tokenUrl_ = getDefaultInstance().getTokenUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @param value The bytes for tokenUrl to set. + * @return This builder for chaining. + */ + public Builder setTokenUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + tokenUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object refreshUrl_ = ""; + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @param value The refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return This builder for chaining. + */ + public Builder clearRefreshUrl() { + refreshUrl_ = getDefaultInstance().getRefreshUrl(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @param value The bytes for refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + private com.google.protobuf.MapField + internalGetMutableScopes() { + if (scopes_ == null) { + scopes_ = com.google.protobuf.MapField.newMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + if (!scopes_.isMutable()) { + scopes_ = scopes_.copy(); + } + bitField0_ |= 0x00000004; + onChanged(); + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + public Builder clearScopes() { + bitField0_ = (bitField0_ & ~0x00000004); + internalGetMutableScopes().getMutableMap() + .clear(); + return this; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder removeScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableScopes().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableScopes() { + bitField0_ |= 0x00000004; + return internalGetMutableScopes().getMutableMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder putScopes( + java.lang.String key, + java.lang.String value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableScopes().getMutableMap() + .put(key, value); + bitField0_ |= 0x00000004; + return this; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder putAllScopes( + java.util.Map values) { + internalGetMutableScopes().getMutableMap() + .putAll(values); + bitField0_ |= 0x00000004; + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.ClientCredentialsOAuthFlow) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.ClientCredentialsOAuthFlow) + private static final org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow(); + } + + public static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ClientCredentialsOAuthFlow parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ClientCredentialsOAuthFlowOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ClientCredentialsOAuthFlowOrBuilder.java new file mode 100644 index 000000000..11ce5b1e2 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ClientCredentialsOAuthFlowOrBuilder.java @@ -0,0 +1,115 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface ClientCredentialsOAuthFlowOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.ClientCredentialsOAuthFlow) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 1; + * @return The tokenUrl. + */ + java.lang.String getTokenUrl(); + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + com.google.protobuf.ByteString + getTokenUrlBytes(); + + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + java.lang.String getRefreshUrl(); + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + com.google.protobuf.ByteString + getRefreshUrlBytes(); + + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + int getScopesCount(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + boolean containsScopes( + java.lang.String key); + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getScopes(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + java.util.Map + getScopesMap(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + java.lang.String getScopesOrThrow( + java.lang.String key); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CreateTaskPushNotificationConfigRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CreateTaskPushNotificationConfigRequest.java new file mode 100644 index 000000000..ff6d73815 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CreateTaskPushNotificationConfigRequest.java @@ -0,0 +1,866 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.CreateTaskPushNotificationConfigRequest} + */ +@com.google.protobuf.Generated +public final class CreateTaskPushNotificationConfigRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.CreateTaskPushNotificationConfigRequest) + CreateTaskPushNotificationConfigRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "CreateTaskPushNotificationConfigRequest"); + } + // Use CreateTaskPushNotificationConfigRequest.newBuilder() to construct. + private CreateTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private CreateTaskPushNotificationConfigRequest() { + parent_ = ""; + configId_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); + } + + private int bitField0_; + public static final int PARENT_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object parent_ = ""; + /** + *
            +   * The task resource for this config.
            +   * Format: tasks/{id}
            +   * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The parent. + */ + @java.lang.Override + public java.lang.String getParent() { + java.lang.Object ref = parent_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + parent_ = s; + return s; + } + } + /** + *
            +   * The task resource for this config.
            +   * Format: tasks/{id}
            +   * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for parent. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getParentBytes() { + java.lang.Object ref = parent_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + parent_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CONFIG_ID_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object configId_ = ""; + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The configId. + */ + @java.lang.Override + public java.lang.String getConfigId() { + java.lang.Object ref = configId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + configId_ = s; + return s; + } + } + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for configId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getConfigIdBytes() { + java.lang.Object ref = configId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + configId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CONFIG_FIELD_NUMBER = 3; + private org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig config_; + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return Whether the config field is set. + */ + @java.lang.Override + public boolean hasConfig() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The config. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getConfig() { + return config_ == null ? org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance() : config_; + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder getConfigOrBuilder() { + return config_ == null ? org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance() : config_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(parent_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, parent_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(configId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, configId_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(3, getConfig()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(parent_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, parent_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(configId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, configId_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getConfig()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest other = (org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest) obj; + + if (!getParent() + .equals(other.getParent())) return false; + if (!getConfigId() + .equals(other.getConfigId())) return false; + if (hasConfig() != other.hasConfig()) return false; + if (hasConfig()) { + if (!getConfig() + .equals(other.getConfig())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + PARENT_FIELD_NUMBER; + hash = (53 * hash) + getParent().hashCode(); + hash = (37 * hash) + CONFIG_ID_FIELD_NUMBER; + hash = (53 * hash) + getConfigId().hashCode(); + if (hasConfig()) { + hash = (37 * hash) + CONFIG_FIELD_NUMBER; + hash = (53 * hash) + getConfig().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.CreateTaskPushNotificationConfigRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.CreateTaskPushNotificationConfigRequest) + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetConfigFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + parent_ = ""; + configId_ = ""; + config_ = null; + if (configBuilder_ != null) { + configBuilder_.dispose(); + configBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest build() { + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest result = new org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.parent_ = parent_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.configId_ = configId_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000004) != 0)) { + result.config_ = configBuilder_ == null + ? config_ + : configBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance()) return this; + if (!other.getParent().isEmpty()) { + parent_ = other.parent_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getConfigId().isEmpty()) { + configId_ = other.configId_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (other.hasConfig()) { + mergeConfig(other.getConfig()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + parent_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + configId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetConfigFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object parent_ = ""; + /** + *
            +     * The task resource for this config.
            +     * Format: tasks/{id}
            +     * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The parent. + */ + public java.lang.String getParent() { + java.lang.Object ref = parent_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + parent_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The task resource for this config.
            +     * Format: tasks/{id}
            +     * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for parent. + */ + public com.google.protobuf.ByteString + getParentBytes() { + java.lang.Object ref = parent_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + parent_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The task resource for this config.
            +     * Format: tasks/{id}
            +     * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The parent to set. + * @return This builder for chaining. + */ + public Builder setParent( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + parent_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The task resource for this config.
            +     * Format: tasks/{id}
            +     * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearParent() { + parent_ = getDefaultInstance().getParent(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The task resource for this config.
            +     * Format: tasks/{id}
            +     * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for parent to set. + * @return This builder for chaining. + */ + public Builder setParentBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + parent_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object configId_ = ""; + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The configId. + */ + public java.lang.String getConfigId() { + java.lang.Object ref = configId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + configId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for configId. + */ + public com.google.protobuf.ByteString + getConfigIdBytes() { + java.lang.Object ref = configId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + configId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @param value The configId to set. + * @return This builder for chaining. + */ + public Builder setConfigId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + configId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearConfigId() { + configId_ = getDefaultInstance().getConfigId(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for configId to set. + * @return This builder for chaining. + */ + public Builder setConfigIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + configId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig config_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder> configBuilder_; + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return Whether the config field is set. + */ + public boolean hasConfig() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The config. + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getConfig() { + if (configBuilder_ == null) { + return config_ == null ? org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance() : config_; + } else { + return configBuilder_.getMessage(); + } + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + public Builder setConfig(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig value) { + if (configBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + config_ = value; + } else { + configBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + public Builder setConfig( + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder builderForValue) { + if (configBuilder_ == null) { + config_ = builderForValue.build(); + } else { + configBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + public Builder mergeConfig(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig value) { + if (configBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + config_ != null && + config_ != org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance()) { + getConfigBuilder().mergeFrom(value); + } else { + config_ = value; + } + } else { + configBuilder_.mergeFrom(value); + } + if (config_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + public Builder clearConfig() { + bitField0_ = (bitField0_ & ~0x00000004); + config_ = null; + if (configBuilder_ != null) { + configBuilder_.dispose(); + configBuilder_ = null; + } + onChanged(); + return this; + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder getConfigBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return internalGetConfigFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder getConfigOrBuilder() { + if (configBuilder_ != null) { + return configBuilder_.getMessageOrBuilder(); + } else { + return config_ == null ? + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance() : config_; + } + } + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder> + internalGetConfigFieldBuilder() { + if (configBuilder_ == null) { + configBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder>( + getConfig(), + getParentForChildren(), + isClean()); + config_ = null; + } + return configBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.CreateTaskPushNotificationConfigRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.CreateTaskPushNotificationConfigRequest) + private static final org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public CreateTaskPushNotificationConfigRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java new file mode 100644 index 000000000..ce25ef2c4 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java @@ -0,0 +1,61 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface CreateTaskPushNotificationConfigRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.CreateTaskPushNotificationConfigRequest) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The task resource for this config.
            +   * Format: tasks/{id}
            +   * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The parent. + */ + java.lang.String getParent(); + /** + *
            +   * The task resource for this config.
            +   * Format: tasks/{id}
            +   * 
            + * + * string parent = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for parent. + */ + com.google.protobuf.ByteString + getParentBytes(); + + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The configId. + */ + java.lang.String getConfigId(); + /** + * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for configId. + */ + com.google.protobuf.ByteString + getConfigIdBytes(); + + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return Whether the config field is set. + */ + boolean hasConfig(); + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + * @return The config. + */ + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getConfig(); + /** + * .a2a.v1.TaskPushNotificationConfig config = 3 [(.google.api.field_behavior) = REQUIRED]; + */ + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder getConfigOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DataPart.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DataPart.java new file mode 100644 index 000000000..7aefff18a --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DataPart.java @@ -0,0 +1,567 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * DataPart represents a structured blob. This is most commonly a JSON payload.
            + * 
            + * + * Protobuf type {@code a2a.v1.DataPart} + */ +@com.google.protobuf.Generated +public final class DataPart extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.DataPart) + DataPartOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "DataPart"); + } + // Use DataPart.newBuilder() to construct. + private DataPart(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private DataPart() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_DataPart_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_DataPart_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.DataPart.class, org.a2aproject.sdk.compat03.grpc.DataPart.Builder.class); + } + + private int bitField0_; + public static final int DATA_FIELD_NUMBER = 1; + private com.google.protobuf.Struct data_; + /** + * .google.protobuf.Struct data = 1; + * @return Whether the data field is set. + */ + @java.lang.Override + public boolean hasData() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * .google.protobuf.Struct data = 1; + * @return The data. + */ + @java.lang.Override + public com.google.protobuf.Struct getData() { + return data_ == null ? com.google.protobuf.Struct.getDefaultInstance() : data_; + } + /** + * .google.protobuf.Struct data = 1; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getDataOrBuilder() { + return data_ == null ? com.google.protobuf.Struct.getDefaultInstance() : data_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(1, getData()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getData()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.DataPart)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.DataPart other = (org.a2aproject.sdk.compat03.grpc.DataPart) obj; + + if (hasData() != other.hasData()) return false; + if (hasData()) { + if (!getData() + .equals(other.getData())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasData()) { + hash = (37 * hash) + DATA_FIELD_NUMBER; + hash = (53 * hash) + getData().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.DataPart parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.DataPart parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.DataPart parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.DataPart prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * DataPart represents a structured blob. This is most commonly a JSON payload.
            +   * 
            + * + * Protobuf type {@code a2a.v1.DataPart} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.DataPart) + org.a2aproject.sdk.compat03.grpc.DataPartOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_DataPart_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_DataPart_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.DataPart.class, org.a2aproject.sdk.compat03.grpc.DataPart.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.DataPart.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetDataFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + data_ = null; + if (dataBuilder_ != null) { + dataBuilder_.dispose(); + dataBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_DataPart_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DataPart getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DataPart build() { + org.a2aproject.sdk.compat03.grpc.DataPart result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DataPart buildPartial() { + org.a2aproject.sdk.compat03.grpc.DataPart result = new org.a2aproject.sdk.compat03.grpc.DataPart(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.DataPart result) { + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.data_ = dataBuilder_ == null + ? data_ + : dataBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.DataPart) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.DataPart)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.DataPart other) { + if (other == org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance()) return this; + if (other.hasData()) { + mergeData(other.getData()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + input.readMessage( + internalGetDataFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private com.google.protobuf.Struct data_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> dataBuilder_; + /** + * .google.protobuf.Struct data = 1; + * @return Whether the data field is set. + */ + public boolean hasData() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * .google.protobuf.Struct data = 1; + * @return The data. + */ + public com.google.protobuf.Struct getData() { + if (dataBuilder_ == null) { + return data_ == null ? com.google.protobuf.Struct.getDefaultInstance() : data_; + } else { + return dataBuilder_.getMessage(); + } + } + /** + * .google.protobuf.Struct data = 1; + */ + public Builder setData(com.google.protobuf.Struct value) { + if (dataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + data_ = value; + } else { + dataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * .google.protobuf.Struct data = 1; + */ + public Builder setData( + com.google.protobuf.Struct.Builder builderForValue) { + if (dataBuilder_ == null) { + data_ = builderForValue.build(); + } else { + dataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * .google.protobuf.Struct data = 1; + */ + public Builder mergeData(com.google.protobuf.Struct value) { + if (dataBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0) && + data_ != null && + data_ != com.google.protobuf.Struct.getDefaultInstance()) { + getDataBuilder().mergeFrom(value); + } else { + data_ = value; + } + } else { + dataBuilder_.mergeFrom(value); + } + if (data_ != null) { + bitField0_ |= 0x00000001; + onChanged(); + } + return this; + } + /** + * .google.protobuf.Struct data = 1; + */ + public Builder clearData() { + bitField0_ = (bitField0_ & ~0x00000001); + data_ = null; + if (dataBuilder_ != null) { + dataBuilder_.dispose(); + dataBuilder_ = null; + } + onChanged(); + return this; + } + /** + * .google.protobuf.Struct data = 1; + */ + public com.google.protobuf.Struct.Builder getDataBuilder() { + bitField0_ |= 0x00000001; + onChanged(); + return internalGetDataFieldBuilder().getBuilder(); + } + /** + * .google.protobuf.Struct data = 1; + */ + public com.google.protobuf.StructOrBuilder getDataOrBuilder() { + if (dataBuilder_ != null) { + return dataBuilder_.getMessageOrBuilder(); + } else { + return data_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : data_; + } + } + /** + * .google.protobuf.Struct data = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetDataFieldBuilder() { + if (dataBuilder_ == null) { + dataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getData(), + getParentForChildren(), + isClean()); + data_ = null; + } + return dataBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.DataPart) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.DataPart) + private static final org.a2aproject.sdk.compat03.grpc.DataPart DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.DataPart(); + } + + public static org.a2aproject.sdk.compat03.grpc.DataPart getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public DataPart parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DataPart getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DataPartOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DataPartOrBuilder.java new file mode 100644 index 000000000..cf387c020 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DataPartOrBuilder.java @@ -0,0 +1,27 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface DataPartOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.DataPart) + com.google.protobuf.MessageOrBuilder { + + /** + * .google.protobuf.Struct data = 1; + * @return Whether the data field is set. + */ + boolean hasData(); + /** + * .google.protobuf.Struct data = 1; + * @return The data. + */ + com.google.protobuf.Struct getData(); + /** + * .google.protobuf.Struct data = 1; + */ + com.google.protobuf.StructOrBuilder getDataOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DeleteTaskPushNotificationConfigRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DeleteTaskPushNotificationConfigRequest.java new file mode 100644 index 000000000..369c55560 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DeleteTaskPushNotificationConfigRequest.java @@ -0,0 +1,530 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.DeleteTaskPushNotificationConfigRequest} + */ +@com.google.protobuf.Generated +public final class DeleteTaskPushNotificationConfigRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.DeleteTaskPushNotificationConfigRequest) + DeleteTaskPushNotificationConfigRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "DeleteTaskPushNotificationConfigRequest"); + } + // Use DeleteTaskPushNotificationConfigRequest.newBuilder() to construct. + private DeleteTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private DeleteTaskPushNotificationConfigRequest() { + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class); + } + + public static final int NAME_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest other = (org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest) obj; + + if (!getName() + .equals(other.getName())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.DeleteTaskPushNotificationConfigRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.DeleteTaskPushNotificationConfigRequest) + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + name_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest build() { + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest result = new org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.name_ = name_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000001; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.DeleteTaskPushNotificationConfigRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.DeleteTaskPushNotificationConfigRequest) + private static final org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public DeleteTaskPushNotificationConfigRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java new file mode 100644 index 000000000..574779a54 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java @@ -0,0 +1,32 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface DeleteTaskPushNotificationConfigRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.DeleteTaskPushNotificationConfigRequest) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/FilePart.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/FilePart.java new file mode 100644 index 000000000..ca9369dbb --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/FilePart.java @@ -0,0 +1,855 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * FilePart represents the different ways files can be provided. If files are
            + * small, directly feeding the bytes is supported via file_with_bytes. If the
            + * file is large, the agent should read the content as appropriate directly
            + * from the file_with_uri source.
            + * 
            + * + * Protobuf type {@code a2a.v1.FilePart} + */ +@com.google.protobuf.Generated +public final class FilePart extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.FilePart) + FilePartOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "FilePart"); + } + // Use FilePart.newBuilder() to construct. + private FilePart(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private FilePart() { + mimeType_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_FilePart_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_FilePart_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.FilePart.class, org.a2aproject.sdk.compat03.grpc.FilePart.Builder.class); + } + + private int fileCase_ = 0; + @SuppressWarnings("serial") + private java.lang.Object file_; + public enum FileCase + implements com.google.protobuf.Internal.EnumLite, + com.google.protobuf.AbstractMessage.InternalOneOfEnum { + FILE_WITH_URI(1), + FILE_WITH_BYTES(2), + FILE_NOT_SET(0); + private final int value; + private FileCase(int value) { + this.value = value; + } + /** + * @param value The number of the enum to look for. + * @return The enum associated with the given number. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static FileCase valueOf(int value) { + return forNumber(value); + } + + public static FileCase forNumber(int value) { + switch (value) { + case 1: return FILE_WITH_URI; + case 2: return FILE_WITH_BYTES; + case 0: return FILE_NOT_SET; + default: return null; + } + } + public int getNumber() { + return this.value; + } + }; + + public FileCase + getFileCase() { + return FileCase.forNumber( + fileCase_); + } + + public static final int FILE_WITH_URI_FIELD_NUMBER = 1; + /** + * string file_with_uri = 1; + * @return Whether the fileWithUri field is set. + */ + public boolean hasFileWithUri() { + return fileCase_ == 1; + } + /** + * string file_with_uri = 1; + * @return The fileWithUri. + */ + public java.lang.String getFileWithUri() { + java.lang.Object ref = ""; + if (fileCase_ == 1) { + ref = file_; + } + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (fileCase_ == 1) { + file_ = s; + } + return s; + } + } + /** + * string file_with_uri = 1; + * @return The bytes for fileWithUri. + */ + public com.google.protobuf.ByteString + getFileWithUriBytes() { + java.lang.Object ref = ""; + if (fileCase_ == 1) { + ref = file_; + } + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + if (fileCase_ == 1) { + file_ = b; + } + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int FILE_WITH_BYTES_FIELD_NUMBER = 2; + /** + * bytes file_with_bytes = 2; + * @return Whether the fileWithBytes field is set. + */ + @java.lang.Override + public boolean hasFileWithBytes() { + return fileCase_ == 2; + } + /** + * bytes file_with_bytes = 2; + * @return The fileWithBytes. + */ + @java.lang.Override + public com.google.protobuf.ByteString getFileWithBytes() { + if (fileCase_ == 2) { + return (com.google.protobuf.ByteString) file_; + } + return com.google.protobuf.ByteString.EMPTY; + } + + public static final int MIME_TYPE_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object mimeType_ = ""; + /** + * string mime_type = 3; + * @return The mimeType. + */ + @java.lang.Override + public java.lang.String getMimeType() { + java.lang.Object ref = mimeType_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + mimeType_ = s; + return s; + } + } + /** + * string mime_type = 3; + * @return The bytes for mimeType. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getMimeTypeBytes() { + java.lang.Object ref = mimeType_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + mimeType_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (fileCase_ == 1) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, file_); + } + if (fileCase_ == 2) { + output.writeBytes( + 2, (com.google.protobuf.ByteString) file_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(mimeType_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, mimeType_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (fileCase_ == 1) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, file_); + } + if (fileCase_ == 2) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize( + 2, (com.google.protobuf.ByteString) file_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(mimeType_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, mimeType_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.FilePart)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.FilePart other = (org.a2aproject.sdk.compat03.grpc.FilePart) obj; + + if (!getMimeType() + .equals(other.getMimeType())) return false; + if (!getFileCase().equals(other.getFileCase())) return false; + switch (fileCase_) { + case 1: + if (!getFileWithUri() + .equals(other.getFileWithUri())) return false; + break; + case 2: + if (!getFileWithBytes() + .equals(other.getFileWithBytes())) return false; + break; + case 0: + default: + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + MIME_TYPE_FIELD_NUMBER; + hash = (53 * hash) + getMimeType().hashCode(); + switch (fileCase_) { + case 1: + hash = (37 * hash) + FILE_WITH_URI_FIELD_NUMBER; + hash = (53 * hash) + getFileWithUri().hashCode(); + break; + case 2: + hash = (37 * hash) + FILE_WITH_BYTES_FIELD_NUMBER; + hash = (53 * hash) + getFileWithBytes().hashCode(); + break; + case 0: + default: + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.FilePart parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.FilePart parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.FilePart parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.FilePart prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * FilePart represents the different ways files can be provided. If files are
            +   * small, directly feeding the bytes is supported via file_with_bytes. If the
            +   * file is large, the agent should read the content as appropriate directly
            +   * from the file_with_uri source.
            +   * 
            + * + * Protobuf type {@code a2a.v1.FilePart} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.FilePart) + org.a2aproject.sdk.compat03.grpc.FilePartOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_FilePart_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_FilePart_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.FilePart.class, org.a2aproject.sdk.compat03.grpc.FilePart.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.FilePart.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + mimeType_ = ""; + fileCase_ = 0; + file_ = null; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_FilePart_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.FilePart getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.FilePart build() { + org.a2aproject.sdk.compat03.grpc.FilePart result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.FilePart buildPartial() { + org.a2aproject.sdk.compat03.grpc.FilePart result = new org.a2aproject.sdk.compat03.grpc.FilePart(this); + if (bitField0_ != 0) { buildPartial0(result); } + buildPartialOneofs(result); + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.FilePart result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000004) != 0)) { + result.mimeType_ = mimeType_; + } + } + + private void buildPartialOneofs(org.a2aproject.sdk.compat03.grpc.FilePart result) { + result.fileCase_ = fileCase_; + result.file_ = this.file_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.FilePart) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.FilePart)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.FilePart other) { + if (other == org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance()) return this; + if (!other.getMimeType().isEmpty()) { + mimeType_ = other.mimeType_; + bitField0_ |= 0x00000004; + onChanged(); + } + switch (other.getFileCase()) { + case FILE_WITH_URI: { + fileCase_ = 1; + file_ = other.file_; + onChanged(); + break; + } + case FILE_WITH_BYTES: { + setFileWithBytes(other.getFileWithBytes()); + break; + } + case FILE_NOT_SET: { + break; + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + fileCase_ = 1; + file_ = s; + break; + } // case 10 + case 18: { + file_ = input.readBytes(); + fileCase_ = 2; + break; + } // case 18 + case 26: { + mimeType_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int fileCase_ = 0; + private java.lang.Object file_; + public FileCase + getFileCase() { + return FileCase.forNumber( + fileCase_); + } + + public Builder clearFile() { + fileCase_ = 0; + file_ = null; + onChanged(); + return this; + } + + private int bitField0_; + + /** + * string file_with_uri = 1; + * @return Whether the fileWithUri field is set. + */ + @java.lang.Override + public boolean hasFileWithUri() { + return fileCase_ == 1; + } + /** + * string file_with_uri = 1; + * @return The fileWithUri. + */ + @java.lang.Override + public java.lang.String getFileWithUri() { + java.lang.Object ref = ""; + if (fileCase_ == 1) { + ref = file_; + } + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (fileCase_ == 1) { + file_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string file_with_uri = 1; + * @return The bytes for fileWithUri. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getFileWithUriBytes() { + java.lang.Object ref = ""; + if (fileCase_ == 1) { + ref = file_; + } + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + if (fileCase_ == 1) { + file_ = b; + } + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string file_with_uri = 1; + * @param value The fileWithUri to set. + * @return This builder for chaining. + */ + public Builder setFileWithUri( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + fileCase_ = 1; + file_ = value; + onChanged(); + return this; + } + /** + * string file_with_uri = 1; + * @return This builder for chaining. + */ + public Builder clearFileWithUri() { + if (fileCase_ == 1) { + fileCase_ = 0; + file_ = null; + onChanged(); + } + return this; + } + /** + * string file_with_uri = 1; + * @param value The bytes for fileWithUri to set. + * @return This builder for chaining. + */ + public Builder setFileWithUriBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + fileCase_ = 1; + file_ = value; + onChanged(); + return this; + } + + /** + * bytes file_with_bytes = 2; + * @return Whether the fileWithBytes field is set. + */ + public boolean hasFileWithBytes() { + return fileCase_ == 2; + } + /** + * bytes file_with_bytes = 2; + * @return The fileWithBytes. + */ + public com.google.protobuf.ByteString getFileWithBytes() { + if (fileCase_ == 2) { + return (com.google.protobuf.ByteString) file_; + } + return com.google.protobuf.ByteString.EMPTY; + } + /** + * bytes file_with_bytes = 2; + * @param value The fileWithBytes to set. + * @return This builder for chaining. + */ + public Builder setFileWithBytes(com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + fileCase_ = 2; + file_ = value; + onChanged(); + return this; + } + /** + * bytes file_with_bytes = 2; + * @return This builder for chaining. + */ + public Builder clearFileWithBytes() { + if (fileCase_ == 2) { + fileCase_ = 0; + file_ = null; + onChanged(); + } + return this; + } + + private java.lang.Object mimeType_ = ""; + /** + * string mime_type = 3; + * @return The mimeType. + */ + public java.lang.String getMimeType() { + java.lang.Object ref = mimeType_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + mimeType_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string mime_type = 3; + * @return The bytes for mimeType. + */ + public com.google.protobuf.ByteString + getMimeTypeBytes() { + java.lang.Object ref = mimeType_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + mimeType_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string mime_type = 3; + * @param value The mimeType to set. + * @return This builder for chaining. + */ + public Builder setMimeType( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + mimeType_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * string mime_type = 3; + * @return This builder for chaining. + */ + public Builder clearMimeType() { + mimeType_ = getDefaultInstance().getMimeType(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + * string mime_type = 3; + * @param value The bytes for mimeType to set. + * @return This builder for chaining. + */ + public Builder setMimeTypeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + mimeType_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.FilePart) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.FilePart) + private static final org.a2aproject.sdk.compat03.grpc.FilePart DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.FilePart(); + } + + public static org.a2aproject.sdk.compat03.grpc.FilePart getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public FilePart parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.FilePart getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/FilePartOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/FilePartOrBuilder.java new file mode 100644 index 000000000..8ce37ca51 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/FilePartOrBuilder.java @@ -0,0 +1,54 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface FilePartOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.FilePart) + com.google.protobuf.MessageOrBuilder { + + /** + * string file_with_uri = 1; + * @return Whether the fileWithUri field is set. + */ + boolean hasFileWithUri(); + /** + * string file_with_uri = 1; + * @return The fileWithUri. + */ + java.lang.String getFileWithUri(); + /** + * string file_with_uri = 1; + * @return The bytes for fileWithUri. + */ + com.google.protobuf.ByteString + getFileWithUriBytes(); + + /** + * bytes file_with_bytes = 2; + * @return Whether the fileWithBytes field is set. + */ + boolean hasFileWithBytes(); + /** + * bytes file_with_bytes = 2; + * @return The fileWithBytes. + */ + com.google.protobuf.ByteString getFileWithBytes(); + + /** + * string mime_type = 3; + * @return The mimeType. + */ + java.lang.String getMimeType(); + /** + * string mime_type = 3; + * @return The bytes for mimeType. + */ + com.google.protobuf.ByteString + getMimeTypeBytes(); + + org.a2aproject.sdk.compat03.grpc.FilePart.FileCase getFileCase(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetAgentCardRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetAgentCardRequest.java new file mode 100644 index 000000000..16bdee653 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetAgentCardRequest.java @@ -0,0 +1,367 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Empty. Added to fix linter violation.
            + * 
            + * + * Protobuf type {@code a2a.v1.GetAgentCardRequest} + */ +@com.google.protobuf.Generated +public final class GetAgentCardRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.GetAgentCardRequest) + GetAgentCardRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "GetAgentCardRequest"); + } + // Use GetAgentCardRequest.newBuilder() to construct. + private GetAgentCardRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private GetAgentCardRequest() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_GetAgentCardRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_GetAgentCardRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.class, org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.Builder.class); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest other = (org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest) obj; + + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Empty. Added to fix linter violation.
            +   * 
            + * + * Protobuf type {@code a2a.v1.GetAgentCardRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.GetAgentCardRequest) + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_GetAgentCardRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_GetAgentCardRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.class, org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_GetAgentCardRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest build() { + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest result = new org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest(this); + onBuilt(); + return result; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest.getDefaultInstance()) return this; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.GetAgentCardRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.GetAgentCardRequest) + private static final org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public GetAgentCardRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetAgentCardRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetAgentCardRequestOrBuilder.java new file mode 100644 index 000000000..0edb8f504 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetAgentCardRequestOrBuilder.java @@ -0,0 +1,12 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface GetAgentCardRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.GetAgentCardRequest) + com.google.protobuf.MessageOrBuilder { +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskPushNotificationConfigRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskPushNotificationConfigRequest.java new file mode 100644 index 000000000..cf0ad5d1e --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskPushNotificationConfigRequest.java @@ -0,0 +1,530 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.GetTaskPushNotificationConfigRequest} + */ +@com.google.protobuf.Generated +public final class GetTaskPushNotificationConfigRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.GetTaskPushNotificationConfigRequest) + GetTaskPushNotificationConfigRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "GetTaskPushNotificationConfigRequest"); + } + // Use GetTaskPushNotificationConfigRequest.newBuilder() to construct. + private GetTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private GetTaskPushNotificationConfigRequest() { + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.Builder.class); + } + + public static final int NAME_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest other = (org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest) obj; + + if (!getName() + .equals(other.getName())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.GetTaskPushNotificationConfigRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.GetTaskPushNotificationConfigRequest) + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + name_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest build() { + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest result = new org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.name_ = name_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000001; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +     * 
            + * + * string name = 1; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.GetTaskPushNotificationConfigRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.GetTaskPushNotificationConfigRequest) + private static final org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public GetTaskPushNotificationConfigRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java new file mode 100644 index 000000000..9cbc1a224 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java @@ -0,0 +1,32 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface GetTaskPushNotificationConfigRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.GetTaskPushNotificationConfigRequest) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{push_id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskRequest.java new file mode 100644 index 000000000..35c8c97e3 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskRequest.java @@ -0,0 +1,596 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.GetTaskRequest} + */ +@com.google.protobuf.Generated +public final class GetTaskRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.GetTaskRequest) + GetTaskRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "GetTaskRequest"); + } + // Use GetTaskRequest.newBuilder() to construct. + private GetTaskRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private GetTaskRequest() { + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.GetTaskRequest.class, org.a2aproject.sdk.compat03.grpc.GetTaskRequest.Builder.class); + } + + public static final int NAME_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int HISTORY_LENGTH_FIELD_NUMBER = 2; + private int historyLength_ = 0; + /** + * int32 history_length = 2; + * @return The historyLength. + */ + @java.lang.Override + public int getHistoryLength() { + return historyLength_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + if (historyLength_ != 0) { + output.writeInt32(2, historyLength_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + if (historyLength_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, historyLength_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.GetTaskRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.GetTaskRequest other = (org.a2aproject.sdk.compat03.grpc.GetTaskRequest) obj; + + if (!getName() + .equals(other.getName())) return false; + if (getHistoryLength() + != other.getHistoryLength()) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER; + hash = (53 * hash) + getHistoryLength(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.GetTaskRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.GetTaskRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.GetTaskRequest) + org.a2aproject.sdk.compat03.grpc.GetTaskRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.GetTaskRequest.class, org.a2aproject.sdk.compat03.grpc.GetTaskRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.GetTaskRequest.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + name_ = ""; + historyLength_ = 0; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetTaskRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.GetTaskRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetTaskRequest build() { + org.a2aproject.sdk.compat03.grpc.GetTaskRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetTaskRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.GetTaskRequest result = new org.a2aproject.sdk.compat03.grpc.GetTaskRequest(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.GetTaskRequest result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.name_ = name_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.historyLength_ = historyLength_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.GetTaskRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.GetTaskRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.GetTaskRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.GetTaskRequest.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (other.getHistoryLength() != 0) { + setHistoryLength(other.getHistoryLength()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 16: { + historyLength_ = input.readInt32(); + bitField0_ |= 0x00000002; + break; + } // case 16 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private int historyLength_ ; + /** + * int32 history_length = 2; + * @return The historyLength. + */ + @java.lang.Override + public int getHistoryLength() { + return historyLength_; + } + /** + * int32 history_length = 2; + * @param value The historyLength to set. + * @return This builder for chaining. + */ + public Builder setHistoryLength(int value) { + + historyLength_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * int32 history_length = 2; + * @return This builder for chaining. + */ + public Builder clearHistoryLength() { + bitField0_ = (bitField0_ & ~0x00000002); + historyLength_ = 0; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.GetTaskRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.GetTaskRequest) + private static final org.a2aproject.sdk.compat03.grpc.GetTaskRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.GetTaskRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.GetTaskRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public GetTaskRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.GetTaskRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskRequestOrBuilder.java new file mode 100644 index 000000000..d694fa444 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/GetTaskRequestOrBuilder.java @@ -0,0 +1,38 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface GetTaskRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.GetTaskRequest) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1 [(.google.api.field_behavior) = REQUIRED]; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + * int32 history_length = 2; + * @return The historyLength. + */ + int getHistoryLength(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/HTTPAuthSecurityScheme.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/HTTPAuthSecurityScheme.java new file mode 100644 index 000000000..dfec514a1 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/HTTPAuthSecurityScheme.java @@ -0,0 +1,893 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.HTTPAuthSecurityScheme} + */ +@com.google.protobuf.Generated +public final class HTTPAuthSecurityScheme extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.HTTPAuthSecurityScheme) + HTTPAuthSecuritySchemeOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "HTTPAuthSecurityScheme"); + } + // Use HTTPAuthSecurityScheme.newBuilder() to construct. + private HTTPAuthSecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private HTTPAuthSecurityScheme() { + description_ = ""; + scheme_ = ""; + bearerFormat_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.class, org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder.class); + } + + public static final int DESCRIPTION_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCHEME_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object scheme_ = ""; + /** + *
            +   * The name of the HTTP Authentication scheme to be used in the
            +   * Authorization header as defined in RFC7235. The values used SHOULD be
            +   * registered in the IANA Authentication Scheme registry.
            +   * The value is case-insensitive, as defined in RFC7235.
            +   * 
            + * + * string scheme = 2; + * @return The scheme. + */ + @java.lang.Override + public java.lang.String getScheme() { + java.lang.Object ref = scheme_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + scheme_ = s; + return s; + } + } + /** + *
            +   * The name of the HTTP Authentication scheme to be used in the
            +   * Authorization header as defined in RFC7235. The values used SHOULD be
            +   * registered in the IANA Authentication Scheme registry.
            +   * The value is case-insensitive, as defined in RFC7235.
            +   * 
            + * + * string scheme = 2; + * @return The bytes for scheme. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getSchemeBytes() { + java.lang.Object ref = scheme_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + scheme_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int BEARER_FORMAT_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object bearerFormat_ = ""; + /** + *
            +   * A hint to the client to identify how the bearer token is formatted.
            +   * Bearer tokens are usually generated by an authorization server, so
            +   * this information is primarily for documentation purposes.
            +   * 
            + * + * string bearer_format = 3; + * @return The bearerFormat. + */ + @java.lang.Override + public java.lang.String getBearerFormat() { + java.lang.Object ref = bearerFormat_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + bearerFormat_ = s; + return s; + } + } + /** + *
            +   * A hint to the client to identify how the bearer token is formatted.
            +   * Bearer tokens are usually generated by an authorization server, so
            +   * this information is primarily for documentation purposes.
            +   * 
            + * + * string bearer_format = 3; + * @return The bytes for bearerFormat. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getBearerFormatBytes() { + java.lang.Object ref = bearerFormat_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + bearerFormat_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(scheme_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, scheme_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(bearerFormat_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, bearerFormat_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(scheme_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, scheme_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(bearerFormat_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, bearerFormat_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme other = (org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) obj; + + if (!getDescription() + .equals(other.getDescription())) return false; + if (!getScheme() + .equals(other.getScheme())) return false; + if (!getBearerFormat() + .equals(other.getBearerFormat())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + hash = (37 * hash) + SCHEME_FIELD_NUMBER; + hash = (53 * hash) + getScheme().hashCode(); + hash = (37 * hash) + BEARER_FORMAT_FIELD_NUMBER; + hash = (53 * hash) + getBearerFormat().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.HTTPAuthSecurityScheme} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.HTTPAuthSecurityScheme) + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecuritySchemeOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.class, org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + description_ = ""; + scheme_ = ""; + bearerFormat_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme build() { + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme buildPartial() { + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme result = new org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.description_ = description_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.scheme_ = scheme_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.bearerFormat_ = bearerFormat_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme other) { + if (other == org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance()) return this; + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getScheme().isEmpty()) { + scheme_ = other.scheme_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getBearerFormat().isEmpty()) { + bearerFormat_ = other.bearerFormat_; + bitField0_ |= 0x00000004; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + scheme_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + bearerFormat_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object description_ = ""; + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object scheme_ = ""; + /** + *
            +     * The name of the HTTP Authentication scheme to be used in the
            +     * Authorization header as defined in RFC7235. The values used SHOULD be
            +     * registered in the IANA Authentication Scheme registry.
            +     * The value is case-insensitive, as defined in RFC7235.
            +     * 
            + * + * string scheme = 2; + * @return The scheme. + */ + public java.lang.String getScheme() { + java.lang.Object ref = scheme_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + scheme_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The name of the HTTP Authentication scheme to be used in the
            +     * Authorization header as defined in RFC7235. The values used SHOULD be
            +     * registered in the IANA Authentication Scheme registry.
            +     * The value is case-insensitive, as defined in RFC7235.
            +     * 
            + * + * string scheme = 2; + * @return The bytes for scheme. + */ + public com.google.protobuf.ByteString + getSchemeBytes() { + java.lang.Object ref = scheme_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + scheme_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The name of the HTTP Authentication scheme to be used in the
            +     * Authorization header as defined in RFC7235. The values used SHOULD be
            +     * registered in the IANA Authentication Scheme registry.
            +     * The value is case-insensitive, as defined in RFC7235.
            +     * 
            + * + * string scheme = 2; + * @param value The scheme to set. + * @return This builder for chaining. + */ + public Builder setScheme( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + scheme_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The name of the HTTP Authentication scheme to be used in the
            +     * Authorization header as defined in RFC7235. The values used SHOULD be
            +     * registered in the IANA Authentication Scheme registry.
            +     * The value is case-insensitive, as defined in RFC7235.
            +     * 
            + * + * string scheme = 2; + * @return This builder for chaining. + */ + public Builder clearScheme() { + scheme_ = getDefaultInstance().getScheme(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The name of the HTTP Authentication scheme to be used in the
            +     * Authorization header as defined in RFC7235. The values used SHOULD be
            +     * registered in the IANA Authentication Scheme registry.
            +     * The value is case-insensitive, as defined in RFC7235.
            +     * 
            + * + * string scheme = 2; + * @param value The bytes for scheme to set. + * @return This builder for chaining. + */ + public Builder setSchemeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + scheme_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object bearerFormat_ = ""; + /** + *
            +     * A hint to the client to identify how the bearer token is formatted.
            +     * Bearer tokens are usually generated by an authorization server, so
            +     * this information is primarily for documentation purposes.
            +     * 
            + * + * string bearer_format = 3; + * @return The bearerFormat. + */ + public java.lang.String getBearerFormat() { + java.lang.Object ref = bearerFormat_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + bearerFormat_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A hint to the client to identify how the bearer token is formatted.
            +     * Bearer tokens are usually generated by an authorization server, so
            +     * this information is primarily for documentation purposes.
            +     * 
            + * + * string bearer_format = 3; + * @return The bytes for bearerFormat. + */ + public com.google.protobuf.ByteString + getBearerFormatBytes() { + java.lang.Object ref = bearerFormat_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + bearerFormat_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A hint to the client to identify how the bearer token is formatted.
            +     * Bearer tokens are usually generated by an authorization server, so
            +     * this information is primarily for documentation purposes.
            +     * 
            + * + * string bearer_format = 3; + * @param value The bearerFormat to set. + * @return This builder for chaining. + */ + public Builder setBearerFormat( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + bearerFormat_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * A hint to the client to identify how the bearer token is formatted.
            +     * Bearer tokens are usually generated by an authorization server, so
            +     * this information is primarily for documentation purposes.
            +     * 
            + * + * string bearer_format = 3; + * @return This builder for chaining. + */ + public Builder clearBearerFormat() { + bearerFormat_ = getDefaultInstance().getBearerFormat(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * A hint to the client to identify how the bearer token is formatted.
            +     * Bearer tokens are usually generated by an authorization server, so
            +     * this information is primarily for documentation purposes.
            +     * 
            + * + * string bearer_format = 3; + * @param value The bytes for bearerFormat to set. + * @return This builder for chaining. + */ + public Builder setBearerFormatBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + bearerFormat_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.HTTPAuthSecurityScheme) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.HTTPAuthSecurityScheme) + private static final org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme(); + } + + public static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public HTTPAuthSecurityScheme parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/HTTPAuthSecuritySchemeOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/HTTPAuthSecuritySchemeOrBuilder.java new file mode 100644 index 000000000..93fff9618 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/HTTPAuthSecuritySchemeOrBuilder.java @@ -0,0 +1,82 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface HTTPAuthSecuritySchemeOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.HTTPAuthSecurityScheme) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + *
            +   * The name of the HTTP Authentication scheme to be used in the
            +   * Authorization header as defined in RFC7235. The values used SHOULD be
            +   * registered in the IANA Authentication Scheme registry.
            +   * The value is case-insensitive, as defined in RFC7235.
            +   * 
            + * + * string scheme = 2; + * @return The scheme. + */ + java.lang.String getScheme(); + /** + *
            +   * The name of the HTTP Authentication scheme to be used in the
            +   * Authorization header as defined in RFC7235. The values used SHOULD be
            +   * registered in the IANA Authentication Scheme registry.
            +   * The value is case-insensitive, as defined in RFC7235.
            +   * 
            + * + * string scheme = 2; + * @return The bytes for scheme. + */ + com.google.protobuf.ByteString + getSchemeBytes(); + + /** + *
            +   * A hint to the client to identify how the bearer token is formatted.
            +   * Bearer tokens are usually generated by an authorization server, so
            +   * this information is primarily for documentation purposes.
            +   * 
            + * + * string bearer_format = 3; + * @return The bearerFormat. + */ + java.lang.String getBearerFormat(); + /** + *
            +   * A hint to the client to identify how the bearer token is formatted.
            +   * Bearer tokens are usually generated by an authorization server, so
            +   * this information is primarily for documentation purposes.
            +   * 
            + * + * string bearer_format = 3; + * @return The bytes for bearerFormat. + */ + com.google.protobuf.ByteString + getBearerFormatBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ImplicitOAuthFlow.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ImplicitOAuthFlow.java new file mode 100644 index 000000000..c12b93bfc --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ImplicitOAuthFlow.java @@ -0,0 +1,1042 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} + */ +@com.google.protobuf.Generated +public final class ImplicitOAuthFlow extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.ImplicitOAuthFlow) + ImplicitOAuthFlowOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "ImplicitOAuthFlow"); + } + // Use ImplicitOAuthFlow.newBuilder() to construct. + private ImplicitOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private ImplicitOAuthFlow() { + authorizationUrl_ = ""; + refreshUrl_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.class, org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.Builder.class); + } + + public static final int AUTHORIZATION_URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object authorizationUrl_ = ""; + /** + *
            +   * The authorization URL to be used for this flow. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS
            +   * 
            + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + @java.lang.Override + public java.lang.String getAuthorizationUrl() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + authorizationUrl_ = s; + return s; + } + } + /** + *
            +   * The authorization URL to be used for this flow. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS
            +   * 
            + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getAuthorizationUrlBytes() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + authorizationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REFRESH_URL_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object refreshUrl_ = ""; + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + @java.lang.Override + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } + } + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCOPES_FIELD_NUMBER = 3; + private static final class ScopesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, java.lang.String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + A2A.internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, authorizationUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetScopes(), + ScopesDefaultEntryHolder.defaultEntry, + 3); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, authorizationUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); + } + for (java.util.Map.Entry entry + : internalGetScopes().getMap().entrySet()) { + com.google.protobuf.MapEntry + scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, scopes__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow other = (org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) obj; + + if (!getAuthorizationUrl() + .equals(other.getAuthorizationUrl())) return false; + if (!getRefreshUrl() + .equals(other.getRefreshUrl())) return false; + if (!internalGetScopes().equals( + other.internalGetScopes())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + AUTHORIZATION_URL_FIELD_NUMBER; + hash = (53 * hash) + getAuthorizationUrl().hashCode(); + hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; + hash = (53 * hash) + getRefreshUrl().hashCode(); + if (!internalGetScopes().getMap().isEmpty()) { + hash = (37 * hash) + SCOPES_FIELD_NUMBER; + hash = (53 * hash) + internalGetScopes().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.ImplicitOAuthFlow) + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlowOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetMutableScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.class, org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + authorizationUrl_ = ""; + refreshUrl_ = ""; + internalGetMutableScopes().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow build() { + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow buildPartial() { + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow result = new org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.authorizationUrl_ = authorizationUrl_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.refreshUrl_ = refreshUrl_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.scopes_ = internalGetScopes(); + result.scopes_.makeImmutable(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow other) { + if (other == org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance()) return this; + if (!other.getAuthorizationUrl().isEmpty()) { + authorizationUrl_ = other.authorizationUrl_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getRefreshUrl().isEmpty()) { + refreshUrl_ = other.refreshUrl_; + bitField0_ |= 0x00000002; + onChanged(); + } + internalGetMutableScopes().mergeFrom( + other.internalGetScopes()); + bitField0_ |= 0x00000004; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + authorizationUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + refreshUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + com.google.protobuf.MapEntry + scopes__ = input.readMessage( + ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableScopes().getMutableMap().put( + scopes__.getKey(), scopes__.getValue()); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object authorizationUrl_ = ""; + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + public java.lang.String getAuthorizationUrl() { + java.lang.Object ref = authorizationUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + authorizationUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + public com.google.protobuf.ByteString + getAuthorizationUrlBytes() { + java.lang.Object ref = authorizationUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + authorizationUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @param value The authorizationUrl to set. + * @return This builder for chaining. + */ + public Builder setAuthorizationUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + authorizationUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @return This builder for chaining. + */ + public Builder clearAuthorizationUrl() { + authorizationUrl_ = getDefaultInstance().getAuthorizationUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The authorization URL to be used for this flow. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS
            +     * 
            + * + * string authorization_url = 1; + * @param value The bytes for authorizationUrl to set. + * @return This builder for chaining. + */ + public Builder setAuthorizationUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + authorizationUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object refreshUrl_ = ""; + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @param value The refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return This builder for chaining. + */ + public Builder clearRefreshUrl() { + refreshUrl_ = getDefaultInstance().getRefreshUrl(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @param value The bytes for refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + private com.google.protobuf.MapField + internalGetMutableScopes() { + if (scopes_ == null) { + scopes_ = com.google.protobuf.MapField.newMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + if (!scopes_.isMutable()) { + scopes_ = scopes_.copy(); + } + bitField0_ |= 0x00000004; + onChanged(); + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + public Builder clearScopes() { + bitField0_ = (bitField0_ & ~0x00000004); + internalGetMutableScopes().getMutableMap() + .clear(); + return this; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder removeScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableScopes().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableScopes() { + bitField0_ |= 0x00000004; + return internalGetMutableScopes().getMutableMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder putScopes( + java.lang.String key, + java.lang.String value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableScopes().getMutableMap() + .put(key, value); + bitField0_ |= 0x00000004; + return this; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder putAllScopes( + java.util.Map values) { + internalGetMutableScopes().getMutableMap() + .putAll(values); + bitField0_ |= 0x00000004; + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.ImplicitOAuthFlow) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.ImplicitOAuthFlow) + private static final org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow(); + } + + public static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ImplicitOAuthFlow parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ImplicitOAuthFlowOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ImplicitOAuthFlowOrBuilder.java new file mode 100644 index 000000000..47a7e6670 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ImplicitOAuthFlowOrBuilder.java @@ -0,0 +1,115 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface ImplicitOAuthFlowOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.ImplicitOAuthFlow) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The authorization URL to be used for this flow. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS
            +   * 
            + * + * string authorization_url = 1; + * @return The authorizationUrl. + */ + java.lang.String getAuthorizationUrl(); + /** + *
            +   * The authorization URL to be used for this flow. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS
            +   * 
            + * + * string authorization_url = 1; + * @return The bytes for authorizationUrl. + */ + com.google.protobuf.ByteString + getAuthorizationUrlBytes(); + + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + java.lang.String getRefreshUrl(); + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + com.google.protobuf.ByteString + getRefreshUrlBytes(); + + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + int getScopesCount(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + boolean containsScopes( + java.lang.String key); + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getScopes(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + java.util.Map + getScopesMap(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + java.lang.String getScopesOrThrow( + java.lang.String key); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigRequest.java new file mode 100644 index 000000000..a18bebdb7 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigRequest.java @@ -0,0 +1,819 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigRequest} + */ +@com.google.protobuf.Generated +public final class ListTaskPushNotificationConfigRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.ListTaskPushNotificationConfigRequest) + ListTaskPushNotificationConfigRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "ListTaskPushNotificationConfigRequest"); + } + // Use ListTaskPushNotificationConfigRequest.newBuilder() to construct. + private ListTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private ListTaskPushNotificationConfigRequest() { + parent_ = ""; + pageToken_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.Builder.class); + } + + public static final int PARENT_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object parent_ = ""; + /** + *
            +   * parent=tasks/{id}
            +   * 
            + * + * string parent = 1; + * @return The parent. + */ + @java.lang.Override + public java.lang.String getParent() { + java.lang.Object ref = parent_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + parent_ = s; + return s; + } + } + /** + *
            +   * parent=tasks/{id}
            +   * 
            + * + * string parent = 1; + * @return The bytes for parent. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getParentBytes() { + java.lang.Object ref = parent_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + parent_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PAGE_SIZE_FIELD_NUMBER = 2; + private int pageSize_ = 0; + /** + *
            +   * For AIP-158 these fields are present. Usually not used/needed.
            +   * The maximum number of configurations to return.
            +   * If unspecified, all configs will be returned.
            +   * 
            + * + * int32 page_size = 2; + * @return The pageSize. + */ + @java.lang.Override + public int getPageSize() { + return pageSize_; + } + + public static final int PAGE_TOKEN_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object pageToken_ = ""; + /** + *
            +   * A page token received from a previous
            +   * ListTaskPushNotificationConfigRequest call.
            +   * Provide this to retrieve the subsequent page.
            +   * When paginating, all other parameters provided to
            +   * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +   * the page token.
            +   * 
            + * + * string page_token = 3; + * @return The pageToken. + */ + @java.lang.Override + public java.lang.String getPageToken() { + java.lang.Object ref = pageToken_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + pageToken_ = s; + return s; + } + } + /** + *
            +   * A page token received from a previous
            +   * ListTaskPushNotificationConfigRequest call.
            +   * Provide this to retrieve the subsequent page.
            +   * When paginating, all other parameters provided to
            +   * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +   * the page token.
            +   * 
            + * + * string page_token = 3; + * @return The bytes for pageToken. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getPageTokenBytes() { + java.lang.Object ref = pageToken_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + pageToken_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(parent_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, parent_); + } + if (pageSize_ != 0) { + output.writeInt32(2, pageSize_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(pageToken_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, pageToken_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(parent_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, parent_); + } + if (pageSize_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, pageSize_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(pageToken_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, pageToken_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest other = (org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest) obj; + + if (!getParent() + .equals(other.getParent())) return false; + if (getPageSize() + != other.getPageSize()) return false; + if (!getPageToken() + .equals(other.getPageToken())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + PARENT_FIELD_NUMBER; + hash = (53 * hash) + getParent().hashCode(); + hash = (37 * hash) + PAGE_SIZE_FIELD_NUMBER; + hash = (53 * hash) + getPageSize(); + hash = (37 * hash) + PAGE_TOKEN_FIELD_NUMBER; + hash = (53 * hash) + getPageToken().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.ListTaskPushNotificationConfigRequest) + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.class, org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + parent_ = ""; + pageSize_ = 0; + pageToken_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest build() { + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest result = new org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.parent_ = parent_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.pageSize_ = pageSize_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.pageToken_ = pageToken_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance()) return this; + if (!other.getParent().isEmpty()) { + parent_ = other.parent_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (other.getPageSize() != 0) { + setPageSize(other.getPageSize()); + } + if (!other.getPageToken().isEmpty()) { + pageToken_ = other.pageToken_; + bitField0_ |= 0x00000004; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + parent_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 16: { + pageSize_ = input.readInt32(); + bitField0_ |= 0x00000002; + break; + } // case 16 + case 26: { + pageToken_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object parent_ = ""; + /** + *
            +     * parent=tasks/{id}
            +     * 
            + * + * string parent = 1; + * @return The parent. + */ + public java.lang.String getParent() { + java.lang.Object ref = parent_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + parent_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * parent=tasks/{id}
            +     * 
            + * + * string parent = 1; + * @return The bytes for parent. + */ + public com.google.protobuf.ByteString + getParentBytes() { + java.lang.Object ref = parent_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + parent_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * parent=tasks/{id}
            +     * 
            + * + * string parent = 1; + * @param value The parent to set. + * @return This builder for chaining. + */ + public Builder setParent( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + parent_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * parent=tasks/{id}
            +     * 
            + * + * string parent = 1; + * @return This builder for chaining. + */ + public Builder clearParent() { + parent_ = getDefaultInstance().getParent(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * parent=tasks/{id}
            +     * 
            + * + * string parent = 1; + * @param value The bytes for parent to set. + * @return This builder for chaining. + */ + public Builder setParentBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + parent_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private int pageSize_ ; + /** + *
            +     * For AIP-158 these fields are present. Usually not used/needed.
            +     * The maximum number of configurations to return.
            +     * If unspecified, all configs will be returned.
            +     * 
            + * + * int32 page_size = 2; + * @return The pageSize. + */ + @java.lang.Override + public int getPageSize() { + return pageSize_; + } + /** + *
            +     * For AIP-158 these fields are present. Usually not used/needed.
            +     * The maximum number of configurations to return.
            +     * If unspecified, all configs will be returned.
            +     * 
            + * + * int32 page_size = 2; + * @param value The pageSize to set. + * @return This builder for chaining. + */ + public Builder setPageSize(int value) { + + pageSize_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * For AIP-158 these fields are present. Usually not used/needed.
            +     * The maximum number of configurations to return.
            +     * If unspecified, all configs will be returned.
            +     * 
            + * + * int32 page_size = 2; + * @return This builder for chaining. + */ + public Builder clearPageSize() { + bitField0_ = (bitField0_ & ~0x00000002); + pageSize_ = 0; + onChanged(); + return this; + } + + private java.lang.Object pageToken_ = ""; + /** + *
            +     * A page token received from a previous
            +     * ListTaskPushNotificationConfigRequest call.
            +     * Provide this to retrieve the subsequent page.
            +     * When paginating, all other parameters provided to
            +     * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +     * the page token.
            +     * 
            + * + * string page_token = 3; + * @return The pageToken. + */ + public java.lang.String getPageToken() { + java.lang.Object ref = pageToken_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + pageToken_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A page token received from a previous
            +     * ListTaskPushNotificationConfigRequest call.
            +     * Provide this to retrieve the subsequent page.
            +     * When paginating, all other parameters provided to
            +     * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +     * the page token.
            +     * 
            + * + * string page_token = 3; + * @return The bytes for pageToken. + */ + public com.google.protobuf.ByteString + getPageTokenBytes() { + java.lang.Object ref = pageToken_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + pageToken_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A page token received from a previous
            +     * ListTaskPushNotificationConfigRequest call.
            +     * Provide this to retrieve the subsequent page.
            +     * When paginating, all other parameters provided to
            +     * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +     * the page token.
            +     * 
            + * + * string page_token = 3; + * @param value The pageToken to set. + * @return This builder for chaining. + */ + public Builder setPageToken( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + pageToken_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * A page token received from a previous
            +     * ListTaskPushNotificationConfigRequest call.
            +     * Provide this to retrieve the subsequent page.
            +     * When paginating, all other parameters provided to
            +     * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +     * the page token.
            +     * 
            + * + * string page_token = 3; + * @return This builder for chaining. + */ + public Builder clearPageToken() { + pageToken_ = getDefaultInstance().getPageToken(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * A page token received from a previous
            +     * ListTaskPushNotificationConfigRequest call.
            +     * Provide this to retrieve the subsequent page.
            +     * When paginating, all other parameters provided to
            +     * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +     * the page token.
            +     * 
            + * + * string page_token = 3; + * @param value The bytes for pageToken to set. + * @return This builder for chaining. + */ + public Builder setPageTokenBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + pageToken_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.ListTaskPushNotificationConfigRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.ListTaskPushNotificationConfigRequest) + private static final org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ListTaskPushNotificationConfigRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java new file mode 100644 index 000000000..d49631f83 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java @@ -0,0 +1,74 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface ListTaskPushNotificationConfigRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.ListTaskPushNotificationConfigRequest) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * parent=tasks/{id}
            +   * 
            + * + * string parent = 1; + * @return The parent. + */ + java.lang.String getParent(); + /** + *
            +   * parent=tasks/{id}
            +   * 
            + * + * string parent = 1; + * @return The bytes for parent. + */ + com.google.protobuf.ByteString + getParentBytes(); + + /** + *
            +   * For AIP-158 these fields are present. Usually not used/needed.
            +   * The maximum number of configurations to return.
            +   * If unspecified, all configs will be returned.
            +   * 
            + * + * int32 page_size = 2; + * @return The pageSize. + */ + int getPageSize(); + + /** + *
            +   * A page token received from a previous
            +   * ListTaskPushNotificationConfigRequest call.
            +   * Provide this to retrieve the subsequent page.
            +   * When paginating, all other parameters provided to
            +   * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +   * the page token.
            +   * 
            + * + * string page_token = 3; + * @return The pageToken. + */ + java.lang.String getPageToken(); + /** + *
            +   * A page token received from a previous
            +   * ListTaskPushNotificationConfigRequest call.
            +   * Provide this to retrieve the subsequent page.
            +   * When paginating, all other parameters provided to
            +   * `ListTaskPushNotificationConfigRequest` must match the call that provided
            +   * the page token.
            +   * 
            + * + * string page_token = 3; + * @return The bytes for pageToken. + */ + com.google.protobuf.ByteString + getPageTokenBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigResponse.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigResponse.java new file mode 100644 index 000000000..6a4a4caa7 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigResponse.java @@ -0,0 +1,891 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigResponse} + */ +@com.google.protobuf.Generated +public final class ListTaskPushNotificationConfigResponse extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.ListTaskPushNotificationConfigResponse) + ListTaskPushNotificationConfigResponseOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "ListTaskPushNotificationConfigResponse"); + } + // Use ListTaskPushNotificationConfigResponse.newBuilder() to construct. + private ListTaskPushNotificationConfigResponse(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private ListTaskPushNotificationConfigResponse() { + configs_ = java.util.Collections.emptyList(); + nextPageToken_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.class, org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.Builder.class); + } + + public static final int CONFIGS_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private java.util.List configs_; + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + @java.lang.Override + public java.util.List getConfigsList() { + return configs_; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + @java.lang.Override + public java.util.List + getConfigsOrBuilderList() { + return configs_; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + @java.lang.Override + public int getConfigsCount() { + return configs_.size(); + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getConfigs(int index) { + return configs_.get(index); + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( + int index) { + return configs_.get(index); + } + + public static final int NEXT_PAGE_TOKEN_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object nextPageToken_ = ""; + /** + *
            +   * A token, which can be sent as `page_token` to retrieve the next page.
            +   * If this field is omitted, there are no subsequent pages.
            +   * 
            + * + * string next_page_token = 2; + * @return The nextPageToken. + */ + @java.lang.Override + public java.lang.String getNextPageToken() { + java.lang.Object ref = nextPageToken_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + nextPageToken_ = s; + return s; + } + } + /** + *
            +   * A token, which can be sent as `page_token` to retrieve the next page.
            +   * If this field is omitted, there are no subsequent pages.
            +   * 
            + * + * string next_page_token = 2; + * @return The bytes for nextPageToken. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNextPageTokenBytes() { + java.lang.Object ref = nextPageToken_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + nextPageToken_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < configs_.size(); i++) { + output.writeMessage(1, configs_.get(i)); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(nextPageToken_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, nextPageToken_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (int i = 0; i < configs_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, configs_.get(i)); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(nextPageToken_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, nextPageToken_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse other = (org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse) obj; + + if (!getConfigsList() + .equals(other.getConfigsList())) return false; + if (!getNextPageToken() + .equals(other.getNextPageToken())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getConfigsCount() > 0) { + hash = (37 * hash) + CONFIGS_FIELD_NUMBER; + hash = (53 * hash) + getConfigsList().hashCode(); + } + hash = (37 * hash) + NEXT_PAGE_TOKEN_FIELD_NUMBER; + hash = (53 * hash) + getNextPageToken().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigResponse} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.ListTaskPushNotificationConfigResponse) + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.class, org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + if (configsBuilder_ == null) { + configs_ = java.util.Collections.emptyList(); + } else { + configs_ = null; + configsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + nextPageToken_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse build() { + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse buildPartial() { + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse result = new org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse(this); + buildPartialRepeatedFields(result); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartialRepeatedFields(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse result) { + if (configsBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0)) { + configs_ = java.util.Collections.unmodifiableList(configs_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.configs_ = configs_; + } else { + result.configs_ = configsBuilder_.build(); + } + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000002) != 0)) { + result.nextPageToken_ = nextPageToken_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse other) { + if (other == org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance()) return this; + if (configsBuilder_ == null) { + if (!other.configs_.isEmpty()) { + if (configs_.isEmpty()) { + configs_ = other.configs_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureConfigsIsMutable(); + configs_.addAll(other.configs_); + } + onChanged(); + } + } else { + if (!other.configs_.isEmpty()) { + if (configsBuilder_.isEmpty()) { + configsBuilder_.dispose(); + configsBuilder_ = null; + configs_ = other.configs_; + bitField0_ = (bitField0_ & ~0x00000001); + configsBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetConfigsFieldBuilder() : null; + } else { + configsBuilder_.addAllMessages(other.configs_); + } + } + } + if (!other.getNextPageToken().isEmpty()) { + nextPageToken_ = other.nextPageToken_; + bitField0_ |= 0x00000002; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.parser(), + extensionRegistry); + if (configsBuilder_ == null) { + ensureConfigsIsMutable(); + configs_.add(m); + } else { + configsBuilder_.addMessage(m); + } + break; + } // case 10 + case 18: { + nextPageToken_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.util.List configs_ = + java.util.Collections.emptyList(); + private void ensureConfigsIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + configs_ = new java.util.ArrayList(configs_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder> configsBuilder_; + + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public java.util.List getConfigsList() { + if (configsBuilder_ == null) { + return java.util.Collections.unmodifiableList(configs_); + } else { + return configsBuilder_.getMessageList(); + } + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public int getConfigsCount() { + if (configsBuilder_ == null) { + return configs_.size(); + } else { + return configsBuilder_.getCount(); + } + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getConfigs(int index) { + if (configsBuilder_ == null) { + return configs_.get(index); + } else { + return configsBuilder_.getMessage(index); + } + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder setConfigs( + int index, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig value) { + if (configsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureConfigsIsMutable(); + configs_.set(index, value); + onChanged(); + } else { + configsBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder setConfigs( + int index, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder builderForValue) { + if (configsBuilder_ == null) { + ensureConfigsIsMutable(); + configs_.set(index, builderForValue.build()); + onChanged(); + } else { + configsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder addConfigs(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig value) { + if (configsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureConfigsIsMutable(); + configs_.add(value); + onChanged(); + } else { + configsBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder addConfigs( + int index, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig value) { + if (configsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureConfigsIsMutable(); + configs_.add(index, value); + onChanged(); + } else { + configsBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder addConfigs( + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder builderForValue) { + if (configsBuilder_ == null) { + ensureConfigsIsMutable(); + configs_.add(builderForValue.build()); + onChanged(); + } else { + configsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder addConfigs( + int index, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder builderForValue) { + if (configsBuilder_ == null) { + ensureConfigsIsMutable(); + configs_.add(index, builderForValue.build()); + onChanged(); + } else { + configsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder addAllConfigs( + java.lang.Iterable values) { + if (configsBuilder_ == null) { + ensureConfigsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, configs_); + onChanged(); + } else { + configsBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder clearConfigs() { + if (configsBuilder_ == null) { + configs_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + configsBuilder_.clear(); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public Builder removeConfigs(int index) { + if (configsBuilder_ == null) { + ensureConfigsIsMutable(); + configs_.remove(index); + onChanged(); + } else { + configsBuilder_.remove(index); + } + return this; + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder getConfigsBuilder( + int index) { + return internalGetConfigsFieldBuilder().getBuilder(index); + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( + int index) { + if (configsBuilder_ == null) { + return configs_.get(index); } else { + return configsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public java.util.List + getConfigsOrBuilderList() { + if (configsBuilder_ != null) { + return configsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(configs_); + } + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder() { + return internalGetConfigsFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance()); + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder( + int index) { + return internalGetConfigsFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance()); + } + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + public java.util.List + getConfigsBuilderList() { + return internalGetConfigsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder> + internalGetConfigsFieldBuilder() { + if (configsBuilder_ == null) { + configsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder>( + configs_, + ((bitField0_ & 0x00000001) != 0), + getParentForChildren(), + isClean()); + configs_ = null; + } + return configsBuilder_; + } + + private java.lang.Object nextPageToken_ = ""; + /** + *
            +     * A token, which can be sent as `page_token` to retrieve the next page.
            +     * If this field is omitted, there are no subsequent pages.
            +     * 
            + * + * string next_page_token = 2; + * @return The nextPageToken. + */ + public java.lang.String getNextPageToken() { + java.lang.Object ref = nextPageToken_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + nextPageToken_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A token, which can be sent as `page_token` to retrieve the next page.
            +     * If this field is omitted, there are no subsequent pages.
            +     * 
            + * + * string next_page_token = 2; + * @return The bytes for nextPageToken. + */ + public com.google.protobuf.ByteString + getNextPageTokenBytes() { + java.lang.Object ref = nextPageToken_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + nextPageToken_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A token, which can be sent as `page_token` to retrieve the next page.
            +     * If this field is omitted, there are no subsequent pages.
            +     * 
            + * + * string next_page_token = 2; + * @param value The nextPageToken to set. + * @return This builder for chaining. + */ + public Builder setNextPageToken( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + nextPageToken_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A token, which can be sent as `page_token` to retrieve the next page.
            +     * If this field is omitted, there are no subsequent pages.
            +     * 
            + * + * string next_page_token = 2; + * @return This builder for chaining. + */ + public Builder clearNextPageToken() { + nextPageToken_ = getDefaultInstance().getNextPageToken(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * A token, which can be sent as `page_token` to retrieve the next page.
            +     * If this field is omitted, there are no subsequent pages.
            +     * 
            + * + * string next_page_token = 2; + * @param value The bytes for nextPageToken to set. + * @return This builder for chaining. + */ + public Builder setNextPageTokenBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + nextPageToken_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.ListTaskPushNotificationConfigResponse) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.ListTaskPushNotificationConfigResponse) + private static final org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse(); + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ListTaskPushNotificationConfigResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java new file mode 100644 index 000000000..f952f588d --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java @@ -0,0 +1,58 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface ListTaskPushNotificationConfigResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.ListTaskPushNotificationConfigResponse) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + java.util.List + getConfigsList(); + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getConfigs(int index); + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + int getConfigsCount(); + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + java.util.List + getConfigsOrBuilderList(); + /** + * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; + */ + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( + int index); + + /** + *
            +   * A token, which can be sent as `page_token` to retrieve the next page.
            +   * If this field is omitted, there are no subsequent pages.
            +   * 
            + * + * string next_page_token = 2; + * @return The nextPageToken. + */ + java.lang.String getNextPageToken(); + /** + *
            +   * A token, which can be sent as `page_token` to retrieve the next page.
            +   * If this field is omitted, there are no subsequent pages.
            +   * 
            + * + * string next_page_token = 2; + * @return The bytes for nextPageToken. + */ + com.google.protobuf.ByteString + getNextPageTokenBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Message.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Message.java new file mode 100644 index 000000000..fcbb6d4bd --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Message.java @@ -0,0 +1,1983 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Message is one unit of communication between client and server. It is
            + * associated with a context and optionally a task. Since the server is
            + * responsible for the context definition, it must always provide a context_id
            + * in its messages. The client can optionally provide the context_id if it
            + * knows the context to associate the message to. Similarly for task_id,
            + * except the server decides if a task is created and whether to include the
            + * task_id.
            + * 
            + * + * Protobuf type {@code a2a.v1.Message} + */ +@com.google.protobuf.Generated +public final class Message extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.Message) + MessageOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "Message"); + } + // Use Message.newBuilder() to construct. + private Message(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Message() { + messageId_ = ""; + contextId_ = ""; + taskId_ = ""; + role_ = 0; + content_ = java.util.Collections.emptyList(); + extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Message_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Message_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Message.class, org.a2aproject.sdk.compat03.grpc.Message.Builder.class); + } + + private int bitField0_; + public static final int MESSAGE_ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object messageId_ = ""; + /** + *
            +   * The message id of the message. This is required and created by the
            +   * message creator.
            +   * 
            + * + * string message_id = 1; + * @return The messageId. + */ + @java.lang.Override + public java.lang.String getMessageId() { + java.lang.Object ref = messageId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + messageId_ = s; + return s; + } + } + /** + *
            +   * The message id of the message. This is required and created by the
            +   * message creator.
            +   * 
            + * + * string message_id = 1; + * @return The bytes for messageId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getMessageIdBytes() { + java.lang.Object ref = messageId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + messageId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CONTEXT_ID_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object contextId_ = ""; + /** + *
            +   * The context id of the message. This is optional and if set, the message
            +   * will be associated with the given context.
            +   * 
            + * + * string context_id = 2; + * @return The contextId. + */ + @java.lang.Override + public java.lang.String getContextId() { + java.lang.Object ref = contextId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + contextId_ = s; + return s; + } + } + /** + *
            +   * The context id of the message. This is optional and if set, the message
            +   * will be associated with the given context.
            +   * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getContextIdBytes() { + java.lang.Object ref = contextId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + contextId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TASK_ID_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object taskId_ = ""; + /** + *
            +   * The task id of the message. This is optional and if set, the message
            +   * will be associated with the given task.
            +   * 
            + * + * string task_id = 3; + * @return The taskId. + */ + @java.lang.Override + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + taskId_ = s; + return s; + } + } + /** + *
            +   * The task id of the message. This is optional and if set, the message
            +   * will be associated with the given task.
            +   * 
            + * + * string task_id = 3; + * @return The bytes for taskId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTaskIdBytes() { + java.lang.Object ref = taskId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int ROLE_FIELD_NUMBER = 4; + private int role_ = 0; + /** + *
            +   * A role for the message.
            +   * 
            + * + * .a2a.v1.Role role = 4; + * @return The enum numeric value on the wire for role. + */ + @java.lang.Override public int getRoleValue() { + return role_; + } + /** + *
            +   * A role for the message.
            +   * 
            + * + * .a2a.v1.Role role = 4; + * @return The role. + */ + @java.lang.Override public org.a2aproject.sdk.compat03.grpc.Role getRole() { + org.a2aproject.sdk.compat03.grpc.Role result = org.a2aproject.sdk.compat03.grpc.Role.forNumber(role_); + return result == null ? org.a2aproject.sdk.compat03.grpc.Role.UNRECOGNIZED : result; + } + + public static final int CONTENT_FIELD_NUMBER = 5; + @SuppressWarnings("serial") + private java.util.List content_; + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + @java.lang.Override + public java.util.List getContentList() { + return content_; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + @java.lang.Override + public java.util.List + getContentOrBuilderList() { + return content_; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + @java.lang.Override + public int getContentCount() { + return content_.size(); + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Part getContent(int index) { + return content_.get(index); + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PartOrBuilder getContentOrBuilder( + int index) { + return content_.get(index); + } + + public static final int METADATA_FIELD_NUMBER = 6; + private com.google.protobuf.Struct metadata_; + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Any optional metadata to provide along with the message.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + @java.lang.Override + public boolean hasMetadata() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Any optional metadata to provide along with the message.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + @java.lang.Override + public com.google.protobuf.Struct getMetadata() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Any optional metadata to provide along with the message.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + + public static final int EXTENSIONS_FIELD_NUMBER = 7; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * The URIs of extensions that are present or contributed to this Message.
            +   * 
            + * + * repeated string extensions = 7; + * @return A list containing the extensions. + */ + public com.google.protobuf.ProtocolStringList + getExtensionsList() { + return extensions_; + } + /** + *
            +   * The URIs of extensions that are present or contributed to this Message.
            +   * 
            + * + * repeated string extensions = 7; + * @return The count of extensions. + */ + public int getExtensionsCount() { + return extensions_.size(); + } + /** + *
            +   * The URIs of extensions that are present or contributed to this Message.
            +   * 
            + * + * repeated string extensions = 7; + * @param index The index of the element to return. + * @return The extensions at the given index. + */ + public java.lang.String getExtensions(int index) { + return extensions_.get(index); + } + /** + *
            +   * The URIs of extensions that are present or contributed to this Message.
            +   * 
            + * + * repeated string extensions = 7; + * @param index The index of the value to return. + * @return The bytes of the extensions at the given index. + */ + public com.google.protobuf.ByteString + getExtensionsBytes(int index) { + return extensions_.getByteString(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(messageId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, messageId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); + } + if (role_ != org.a2aproject.sdk.compat03.grpc.Role.ROLE_UNSPECIFIED.getNumber()) { + output.writeEnum(4, role_); + } + for (int i = 0; i < content_.size(); i++) { + output.writeMessage(5, content_.get(i)); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(6, getMetadata()); + } + for (int i = 0; i < extensions_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 7, extensions_.getRaw(i)); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(messageId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, messageId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); + } + if (role_ != org.a2aproject.sdk.compat03.grpc.Role.ROLE_UNSPECIFIED.getNumber()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(4, role_); + } + for (int i = 0; i < content_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, content_.get(i)); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, getMetadata()); + } + { + int dataSize = 0; + for (int i = 0; i < extensions_.size(); i++) { + dataSize += computeStringSizeNoTag(extensions_.getRaw(i)); + } + size += dataSize; + size += 1 * getExtensionsList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.Message)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.Message other = (org.a2aproject.sdk.compat03.grpc.Message) obj; + + if (!getMessageId() + .equals(other.getMessageId())) return false; + if (!getContextId() + .equals(other.getContextId())) return false; + if (!getTaskId() + .equals(other.getTaskId())) return false; + if (role_ != other.role_) return false; + if (!getContentList() + .equals(other.getContentList())) return false; + if (hasMetadata() != other.hasMetadata()) return false; + if (hasMetadata()) { + if (!getMetadata() + .equals(other.getMetadata())) return false; + } + if (!getExtensionsList() + .equals(other.getExtensionsList())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + MESSAGE_ID_FIELD_NUMBER; + hash = (53 * hash) + getMessageId().hashCode(); + hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; + hash = (53 * hash) + getContextId().hashCode(); + hash = (37 * hash) + TASK_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskId().hashCode(); + hash = (37 * hash) + ROLE_FIELD_NUMBER; + hash = (53 * hash) + role_; + if (getContentCount() > 0) { + hash = (37 * hash) + CONTENT_FIELD_NUMBER; + hash = (53 * hash) + getContentList().hashCode(); + } + if (hasMetadata()) { + hash = (37 * hash) + METADATA_FIELD_NUMBER; + hash = (53 * hash) + getMetadata().hashCode(); + } + if (getExtensionsCount() > 0) { + hash = (37 * hash) + EXTENSIONS_FIELD_NUMBER; + hash = (53 * hash) + getExtensionsList().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.Message parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.Message parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Message parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.Message prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Message is one unit of communication between client and server. It is
            +   * associated with a context and optionally a task. Since the server is
            +   * responsible for the context definition, it must always provide a context_id
            +   * in its messages. The client can optionally provide the context_id if it
            +   * knows the context to associate the message to. Similarly for task_id,
            +   * except the server decides if a task is created and whether to include the
            +   * task_id.
            +   * 
            + * + * Protobuf type {@code a2a.v1.Message} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.Message) + org.a2aproject.sdk.compat03.grpc.MessageOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Message_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Message_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Message.class, org.a2aproject.sdk.compat03.grpc.Message.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.Message.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetContentFieldBuilder(); + internalGetMetadataFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + messageId_ = ""; + contextId_ = ""; + taskId_ = ""; + role_ = 0; + if (contentBuilder_ == null) { + content_ = java.util.Collections.emptyList(); + } else { + content_ = null; + contentBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000010); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_Message_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message build() { + org.a2aproject.sdk.compat03.grpc.Message result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message buildPartial() { + org.a2aproject.sdk.compat03.grpc.Message result = new org.a2aproject.sdk.compat03.grpc.Message(this); + buildPartialRepeatedFields(result); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartialRepeatedFields(org.a2aproject.sdk.compat03.grpc.Message result) { + if (contentBuilder_ == null) { + if (((bitField0_ & 0x00000010) != 0)) { + content_ = java.util.Collections.unmodifiableList(content_); + bitField0_ = (bitField0_ & ~0x00000010); + } + result.content_ = content_; + } else { + result.content_ = contentBuilder_.build(); + } + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.Message result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.messageId_ = messageId_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.contextId_ = contextId_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.taskId_ = taskId_; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.role_ = role_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000020) != 0)) { + result.metadata_ = metadataBuilder_ == null + ? metadata_ + : metadataBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000040) != 0)) { + extensions_.makeImmutable(); + result.extensions_ = extensions_; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.Message) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.Message)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.Message other) { + if (other == org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance()) return this; + if (!other.getMessageId().isEmpty()) { + messageId_ = other.messageId_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getContextId().isEmpty()) { + contextId_ = other.contextId_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getTaskId().isEmpty()) { + taskId_ = other.taskId_; + bitField0_ |= 0x00000004; + onChanged(); + } + if (other.role_ != 0) { + setRoleValue(other.getRoleValue()); + } + if (contentBuilder_ == null) { + if (!other.content_.isEmpty()) { + if (content_.isEmpty()) { + content_ = other.content_; + bitField0_ = (bitField0_ & ~0x00000010); + } else { + ensureContentIsMutable(); + content_.addAll(other.content_); + } + onChanged(); + } + } else { + if (!other.content_.isEmpty()) { + if (contentBuilder_.isEmpty()) { + contentBuilder_.dispose(); + contentBuilder_ = null; + content_ = other.content_; + bitField0_ = (bitField0_ & ~0x00000010); + contentBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetContentFieldBuilder() : null; + } else { + contentBuilder_.addAllMessages(other.content_); + } + } + } + if (other.hasMetadata()) { + mergeMetadata(other.getMetadata()); + } + if (!other.extensions_.isEmpty()) { + if (extensions_.isEmpty()) { + extensions_ = other.extensions_; + bitField0_ |= 0x00000040; + } else { + ensureExtensionsIsMutable(); + extensions_.addAll(other.extensions_); + } + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + messageId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + contextId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 32: { + role_ = input.readEnum(); + bitField0_ |= 0x00000008; + break; + } // case 32 + case 42: { + org.a2aproject.sdk.compat03.grpc.Part m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.Part.parser(), + extensionRegistry); + if (contentBuilder_ == null) { + ensureContentIsMutable(); + content_.add(m); + } else { + contentBuilder_.addMessage(m); + } + break; + } // case 42 + case 50: { + input.readMessage( + internalGetMetadataFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000020; + break; + } // case 50 + case 58: { + java.lang.String s = input.readStringRequireUtf8(); + ensureExtensionsIsMutable(); + extensions_.add(s); + break; + } // case 58 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object messageId_ = ""; + /** + *
            +     * The message id of the message. This is required and created by the
            +     * message creator.
            +     * 
            + * + * string message_id = 1; + * @return The messageId. + */ + public java.lang.String getMessageId() { + java.lang.Object ref = messageId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + messageId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The message id of the message. This is required and created by the
            +     * message creator.
            +     * 
            + * + * string message_id = 1; + * @return The bytes for messageId. + */ + public com.google.protobuf.ByteString + getMessageIdBytes() { + java.lang.Object ref = messageId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + messageId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The message id of the message. This is required and created by the
            +     * message creator.
            +     * 
            + * + * string message_id = 1; + * @param value The messageId to set. + * @return This builder for chaining. + */ + public Builder setMessageId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + messageId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The message id of the message. This is required and created by the
            +     * message creator.
            +     * 
            + * + * string message_id = 1; + * @return This builder for chaining. + */ + public Builder clearMessageId() { + messageId_ = getDefaultInstance().getMessageId(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The message id of the message. This is required and created by the
            +     * message creator.
            +     * 
            + * + * string message_id = 1; + * @param value The bytes for messageId to set. + * @return This builder for chaining. + */ + public Builder setMessageIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + messageId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object contextId_ = ""; + /** + *
            +     * The context id of the message. This is optional and if set, the message
            +     * will be associated with the given context.
            +     * 
            + * + * string context_id = 2; + * @return The contextId. + */ + public java.lang.String getContextId() { + java.lang.Object ref = contextId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + contextId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The context id of the message. This is optional and if set, the message
            +     * will be associated with the given context.
            +     * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + public com.google.protobuf.ByteString + getContextIdBytes() { + java.lang.Object ref = contextId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + contextId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The context id of the message. This is optional and if set, the message
            +     * will be associated with the given context.
            +     * 
            + * + * string context_id = 2; + * @param value The contextId to set. + * @return This builder for chaining. + */ + public Builder setContextId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + contextId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The context id of the message. This is optional and if set, the message
            +     * will be associated with the given context.
            +     * 
            + * + * string context_id = 2; + * @return This builder for chaining. + */ + public Builder clearContextId() { + contextId_ = getDefaultInstance().getContextId(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The context id of the message. This is optional and if set, the message
            +     * will be associated with the given context.
            +     * 
            + * + * string context_id = 2; + * @param value The bytes for contextId to set. + * @return This builder for chaining. + */ + public Builder setContextIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + contextId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object taskId_ = ""; + /** + *
            +     * The task id of the message. This is optional and if set, the message
            +     * will be associated with the given task.
            +     * 
            + * + * string task_id = 3; + * @return The taskId. + */ + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + taskId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The task id of the message. This is optional and if set, the message
            +     * will be associated with the given task.
            +     * 
            + * + * string task_id = 3; + * @return The bytes for taskId. + */ + public com.google.protobuf.ByteString + getTaskIdBytes() { + java.lang.Object ref = taskId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The task id of the message. This is optional and if set, the message
            +     * will be associated with the given task.
            +     * 
            + * + * string task_id = 3; + * @param value The taskId to set. + * @return This builder for chaining. + */ + public Builder setTaskId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + taskId_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The task id of the message. This is optional and if set, the message
            +     * will be associated with the given task.
            +     * 
            + * + * string task_id = 3; + * @return This builder for chaining. + */ + public Builder clearTaskId() { + taskId_ = getDefaultInstance().getTaskId(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * The task id of the message. This is optional and if set, the message
            +     * will be associated with the given task.
            +     * 
            + * + * string task_id = 3; + * @param value The bytes for taskId to set. + * @return This builder for chaining. + */ + public Builder setTaskIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + taskId_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private int role_ = 0; + /** + *
            +     * A role for the message.
            +     * 
            + * + * .a2a.v1.Role role = 4; + * @return The enum numeric value on the wire for role. + */ + @java.lang.Override public int getRoleValue() { + return role_; + } + /** + *
            +     * A role for the message.
            +     * 
            + * + * .a2a.v1.Role role = 4; + * @param value The enum numeric value on the wire for role to set. + * @return This builder for chaining. + */ + public Builder setRoleValue(int value) { + role_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * A role for the message.
            +     * 
            + * + * .a2a.v1.Role role = 4; + * @return The role. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Role getRole() { + org.a2aproject.sdk.compat03.grpc.Role result = org.a2aproject.sdk.compat03.grpc.Role.forNumber(role_); + return result == null ? org.a2aproject.sdk.compat03.grpc.Role.UNRECOGNIZED : result; + } + /** + *
            +     * A role for the message.
            +     * 
            + * + * .a2a.v1.Role role = 4; + * @param value The role to set. + * @return This builder for chaining. + */ + public Builder setRole(org.a2aproject.sdk.compat03.grpc.Role value) { + if (value == null) { throw new NullPointerException(); } + bitField0_ |= 0x00000008; + role_ = value.getNumber(); + onChanged(); + return this; + } + /** + *
            +     * A role for the message.
            +     * 
            + * + * .a2a.v1.Role role = 4; + * @return This builder for chaining. + */ + public Builder clearRole() { + bitField0_ = (bitField0_ & ~0x00000008); + role_ = 0; + onChanged(); + return this; + } + + private java.util.List content_ = + java.util.Collections.emptyList(); + private void ensureContentIsMutable() { + if (!((bitField0_ & 0x00000010) != 0)) { + content_ = new java.util.ArrayList(content_); + bitField0_ |= 0x00000010; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Part, org.a2aproject.sdk.compat03.grpc.Part.Builder, org.a2aproject.sdk.compat03.grpc.PartOrBuilder> contentBuilder_; + + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public java.util.List getContentList() { + if (contentBuilder_ == null) { + return java.util.Collections.unmodifiableList(content_); + } else { + return contentBuilder_.getMessageList(); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public int getContentCount() { + if (contentBuilder_ == null) { + return content_.size(); + } else { + return contentBuilder_.getCount(); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Part getContent(int index) { + if (contentBuilder_ == null) { + return content_.get(index); + } else { + return contentBuilder_.getMessage(index); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder setContent( + int index, org.a2aproject.sdk.compat03.grpc.Part value) { + if (contentBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureContentIsMutable(); + content_.set(index, value); + onChanged(); + } else { + contentBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder setContent( + int index, org.a2aproject.sdk.compat03.grpc.Part.Builder builderForValue) { + if (contentBuilder_ == null) { + ensureContentIsMutable(); + content_.set(index, builderForValue.build()); + onChanged(); + } else { + contentBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder addContent(org.a2aproject.sdk.compat03.grpc.Part value) { + if (contentBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureContentIsMutable(); + content_.add(value); + onChanged(); + } else { + contentBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder addContent( + int index, org.a2aproject.sdk.compat03.grpc.Part value) { + if (contentBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureContentIsMutable(); + content_.add(index, value); + onChanged(); + } else { + contentBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder addContent( + org.a2aproject.sdk.compat03.grpc.Part.Builder builderForValue) { + if (contentBuilder_ == null) { + ensureContentIsMutable(); + content_.add(builderForValue.build()); + onChanged(); + } else { + contentBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder addContent( + int index, org.a2aproject.sdk.compat03.grpc.Part.Builder builderForValue) { + if (contentBuilder_ == null) { + ensureContentIsMutable(); + content_.add(index, builderForValue.build()); + onChanged(); + } else { + contentBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder addAllContent( + java.lang.Iterable values) { + if (contentBuilder_ == null) { + ensureContentIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, content_); + onChanged(); + } else { + contentBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder clearContent() { + if (contentBuilder_ == null) { + content_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + } else { + contentBuilder_.clear(); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public Builder removeContent(int index) { + if (contentBuilder_ == null) { + ensureContentIsMutable(); + content_.remove(index); + onChanged(); + } else { + contentBuilder_.remove(index); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Part.Builder getContentBuilder( + int index) { + return internalGetContentFieldBuilder().getBuilder(index); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public org.a2aproject.sdk.compat03.grpc.PartOrBuilder getContentOrBuilder( + int index) { + if (contentBuilder_ == null) { + return content_.get(index); } else { + return contentBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public java.util.List + getContentOrBuilderList() { + if (contentBuilder_ != null) { + return contentBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(content_); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Part.Builder addContentBuilder() { + return internalGetContentFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.Part.getDefaultInstance()); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Part.Builder addContentBuilder( + int index) { + return internalGetContentFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.Part.getDefaultInstance()); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Content is the container of the message content.
            +     * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + public java.util.List + getContentBuilderList() { + return internalGetContentFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Part, org.a2aproject.sdk.compat03.grpc.Part.Builder, org.a2aproject.sdk.compat03.grpc.PartOrBuilder> + internalGetContentFieldBuilder() { + if (contentBuilder_ == null) { + contentBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Part, org.a2aproject.sdk.compat03.grpc.Part.Builder, org.a2aproject.sdk.compat03.grpc.PartOrBuilder>( + content_, + ((bitField0_ & 0x00000010) != 0), + getParentForChildren(), + isClean()); + content_ = null; + } + return contentBuilder_; + } + + private com.google.protobuf.Struct metadata_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + public boolean hasMetadata() { + return ((bitField0_ & 0x00000020) != 0); + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + public com.google.protobuf.Struct getMetadata() { + if (metadataBuilder_ == null) { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } else { + return metadataBuilder_.getMessage(); + } + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder setMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + metadata_ = value; + } else { + metadataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder setMetadata( + com.google.protobuf.Struct.Builder builderForValue) { + if (metadataBuilder_ == null) { + metadata_ = builderForValue.build(); + } else { + metadataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder mergeMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0) && + metadata_ != null && + metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { + getMetadataBuilder().mergeFrom(value); + } else { + metadata_ = value; + } + } else { + metadataBuilder_.mergeFrom(value); + } + if (metadata_ != null) { + bitField0_ |= 0x00000020; + onChanged(); + } + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder clearMetadata() { + bitField0_ = (bitField0_ & ~0x00000020); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public com.google.protobuf.Struct.Builder getMetadataBuilder() { + bitField0_ |= 0x00000020; + onChanged(); + return internalGetMetadataFieldBuilder().getBuilder(); + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + if (metadataBuilder_ != null) { + return metadataBuilder_.getMessageOrBuilder(); + } else { + return metadata_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * Any optional metadata to provide along with the message.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetMetadataFieldBuilder() { + if (metadataBuilder_ == null) { + metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getMetadata(), + getParentForChildren(), + isClean()); + metadata_ = null; + } + return metadataBuilder_; + } + + private com.google.protobuf.LazyStringArrayList extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureExtensionsIsMutable() { + if (!extensions_.isModifiable()) { + extensions_ = new com.google.protobuf.LazyStringArrayList(extensions_); + } + bitField0_ |= 0x00000040; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @return A list containing the extensions. + */ + public com.google.protobuf.ProtocolStringList + getExtensionsList() { + extensions_.makeImmutable(); + return extensions_; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @return The count of extensions. + */ + public int getExtensionsCount() { + return extensions_.size(); + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @param index The index of the element to return. + * @return The extensions at the given index. + */ + public java.lang.String getExtensions(int index) { + return extensions_.get(index); + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @param index The index of the value to return. + * @return The bytes of the extensions at the given index. + */ + public com.google.protobuf.ByteString + getExtensionsBytes(int index) { + return extensions_.getByteString(index); + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @param index The index to set the value at. + * @param value The extensions to set. + * @return This builder for chaining. + */ + public Builder setExtensions( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureExtensionsIsMutable(); + extensions_.set(index, value); + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @param value The extensions to add. + * @return This builder for chaining. + */ + public Builder addExtensions( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureExtensionsIsMutable(); + extensions_.add(value); + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @param values The extensions to add. + * @return This builder for chaining. + */ + public Builder addAllExtensions( + java.lang.Iterable values) { + ensureExtensionsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, extensions_); + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @return This builder for chaining. + */ + public Builder clearExtensions() { + extensions_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000040);; + onChanged(); + return this; + } + /** + *
            +     * The URIs of extensions that are present or contributed to this Message.
            +     * 
            + * + * repeated string extensions = 7; + * @param value The bytes of the extensions to add. + * @return This builder for chaining. + */ + public Builder addExtensionsBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureExtensionsIsMutable(); + extensions_.add(value); + bitField0_ |= 0x00000040; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.Message) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.Message) + private static final org.a2aproject.sdk.compat03.grpc.Message DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.Message(); + } + + public static org.a2aproject.sdk.compat03.grpc.Message getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Message parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MessageOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MessageOrBuilder.java new file mode 100644 index 000000000..1c7dd4f27 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MessageOrBuilder.java @@ -0,0 +1,217 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface MessageOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.Message) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The message id of the message. This is required and created by the
            +   * message creator.
            +   * 
            + * + * string message_id = 1; + * @return The messageId. + */ + java.lang.String getMessageId(); + /** + *
            +   * The message id of the message. This is required and created by the
            +   * message creator.
            +   * 
            + * + * string message_id = 1; + * @return The bytes for messageId. + */ + com.google.protobuf.ByteString + getMessageIdBytes(); + + /** + *
            +   * The context id of the message. This is optional and if set, the message
            +   * will be associated with the given context.
            +   * 
            + * + * string context_id = 2; + * @return The contextId. + */ + java.lang.String getContextId(); + /** + *
            +   * The context id of the message. This is optional and if set, the message
            +   * will be associated with the given context.
            +   * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + com.google.protobuf.ByteString + getContextIdBytes(); + + /** + *
            +   * The task id of the message. This is optional and if set, the message
            +   * will be associated with the given task.
            +   * 
            + * + * string task_id = 3; + * @return The taskId. + */ + java.lang.String getTaskId(); + /** + *
            +   * The task id of the message. This is optional and if set, the message
            +   * will be associated with the given task.
            +   * 
            + * + * string task_id = 3; + * @return The bytes for taskId. + */ + com.google.protobuf.ByteString + getTaskIdBytes(); + + /** + *
            +   * A role for the message.
            +   * 
            + * + * .a2a.v1.Role role = 4; + * @return The enum numeric value on the wire for role. + */ + int getRoleValue(); + /** + *
            +   * A role for the message.
            +   * 
            + * + * .a2a.v1.Role role = 4; + * @return The role. + */ + org.a2aproject.sdk.compat03.grpc.Role getRole(); + + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + java.util.List + getContentList(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + org.a2aproject.sdk.compat03.grpc.Part getContent(int index); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + int getContentCount(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + java.util.List + getContentOrBuilderList(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Content is the container of the message content.
            +   * 
            + * + * repeated .a2a.v1.Part content = 5; + */ + org.a2aproject.sdk.compat03.grpc.PartOrBuilder getContentOrBuilder( + int index); + + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Any optional metadata to provide along with the message.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + boolean hasMetadata(); + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Any optional metadata to provide along with the message.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + com.google.protobuf.Struct getMetadata(); + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * Any optional metadata to provide along with the message.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); + + /** + *
            +   * The URIs of extensions that are present or contributed to this Message.
            +   * 
            + * + * repeated string extensions = 7; + * @return A list containing the extensions. + */ + java.util.List + getExtensionsList(); + /** + *
            +   * The URIs of extensions that are present or contributed to this Message.
            +   * 
            + * + * repeated string extensions = 7; + * @return The count of extensions. + */ + int getExtensionsCount(); + /** + *
            +   * The URIs of extensions that are present or contributed to this Message.
            +   * 
            + * + * repeated string extensions = 7; + * @param index The index of the element to return. + * @return The extensions at the given index. + */ + java.lang.String getExtensions(int index); + /** + *
            +   * The URIs of extensions that are present or contributed to this Message.
            +   * 
            + * + * repeated string extensions = 7; + * @param index The index of the value to return. + * @return The bytes of the extensions at the given index. + */ + com.google.protobuf.ByteString + getExtensionsBytes(int index); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MutualTlsSecurityScheme.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MutualTlsSecurityScheme.java new file mode 100644 index 000000000..d9b77af97 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MutualTlsSecurityScheme.java @@ -0,0 +1,530 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.MutualTlsSecurityScheme} + */ +@com.google.protobuf.Generated +public final class MutualTlsSecurityScheme extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.MutualTlsSecurityScheme) + MutualTlsSecuritySchemeOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "MutualTlsSecurityScheme"); + } + // Use MutualTlsSecurityScheme.newBuilder() to construct. + private MutualTlsSecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private MutualTlsSecurityScheme() { + description_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.class, org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder.class); + } + + public static final int DESCRIPTION_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme other = (org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) obj; + + if (!getDescription() + .equals(other.getDescription())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.MutualTlsSecurityScheme} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.MutualTlsSecurityScheme) + org.a2aproject.sdk.compat03.grpc.MutualTlsSecuritySchemeOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.class, org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + description_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme build() { + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme buildPartial() { + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme result = new org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.description_ = description_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme other) { + if (other == org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance()) return this; + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000001; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object description_ = ""; + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.MutualTlsSecurityScheme) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.MutualTlsSecurityScheme) + private static final org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme(); + } + + public static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public MutualTlsSecurityScheme parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MutualTlsSecuritySchemeOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MutualTlsSecuritySchemeOrBuilder.java new file mode 100644 index 000000000..bae87d5d3 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/MutualTlsSecuritySchemeOrBuilder.java @@ -0,0 +1,32 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface MutualTlsSecuritySchemeOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.MutualTlsSecurityScheme) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuth2SecurityScheme.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuth2SecurityScheme.java new file mode 100644 index 000000000..6fbaeed7b --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuth2SecurityScheme.java @@ -0,0 +1,942 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.OAuth2SecurityScheme} + */ +@com.google.protobuf.Generated +public final class OAuth2SecurityScheme extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.OAuth2SecurityScheme) + OAuth2SecuritySchemeOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "OAuth2SecurityScheme"); + } + // Use OAuth2SecurityScheme.newBuilder() to construct. + private OAuth2SecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private OAuth2SecurityScheme() { + description_ = ""; + oauth2MetadataUrl_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.class, org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder.class); + } + + private int bitField0_; + public static final int DESCRIPTION_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int FLOWS_FIELD_NUMBER = 2; + private org.a2aproject.sdk.compat03.grpc.OAuthFlows flows_; + /** + *
            +   * An object containing configuration information for the flow types supported
            +   * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + * @return Whether the flows field is set. + */ + @java.lang.Override + public boolean hasFlows() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * An object containing configuration information for the flow types supported
            +   * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + * @return The flows. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuthFlows getFlows() { + return flows_ == null ? org.a2aproject.sdk.compat03.grpc.OAuthFlows.getDefaultInstance() : flows_; + } + /** + *
            +   * An object containing configuration information for the flow types supported
            +   * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { + return flows_ == null ? org.a2aproject.sdk.compat03.grpc.OAuthFlows.getDefaultInstance() : flows_; + } + + public static final int OAUTH2_METADATA_URL_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object oauth2MetadataUrl_ = ""; + /** + *
            +   * URL to the oauth2 authorization server metadata
            +   * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +   * 
            + * + * string oauth2_metadata_url = 3; + * @return The oauth2MetadataUrl. + */ + @java.lang.Override + public java.lang.String getOauth2MetadataUrl() { + java.lang.Object ref = oauth2MetadataUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + oauth2MetadataUrl_ = s; + return s; + } + } + /** + *
            +   * URL to the oauth2 authorization server metadata
            +   * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +   * 
            + * + * string oauth2_metadata_url = 3; + * @return The bytes for oauth2MetadataUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getOauth2MetadataUrlBytes() { + java.lang.Object ref = oauth2MetadataUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + oauth2MetadataUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(2, getFlows()); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(oauth2MetadataUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, oauth2MetadataUrl_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getFlows()); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(oauth2MetadataUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, oauth2MetadataUrl_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme other = (org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) obj; + + if (!getDescription() + .equals(other.getDescription())) return false; + if (hasFlows() != other.hasFlows()) return false; + if (hasFlows()) { + if (!getFlows() + .equals(other.getFlows())) return false; + } + if (!getOauth2MetadataUrl() + .equals(other.getOauth2MetadataUrl())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + if (hasFlows()) { + hash = (37 * hash) + FLOWS_FIELD_NUMBER; + hash = (53 * hash) + getFlows().hashCode(); + } + hash = (37 * hash) + OAUTH2_METADATA_URL_FIELD_NUMBER; + hash = (53 * hash) + getOauth2MetadataUrl().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.OAuth2SecurityScheme} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.OAuth2SecurityScheme) + org.a2aproject.sdk.compat03.grpc.OAuth2SecuritySchemeOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.class, org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetFlowsFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + description_ = ""; + flows_ = null; + if (flowsBuilder_ != null) { + flowsBuilder_.dispose(); + flowsBuilder_ = null; + } + oauth2MetadataUrl_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme build() { + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme buildPartial() { + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme result = new org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.description_ = description_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000002) != 0)) { + result.flows_ = flowsBuilder_ == null + ? flows_ + : flowsBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.oauth2MetadataUrl_ = oauth2MetadataUrl_; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme other) { + if (other == org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance()) return this; + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (other.hasFlows()) { + mergeFlows(other.getFlows()); + } + if (!other.getOauth2MetadataUrl().isEmpty()) { + oauth2MetadataUrl_ = other.oauth2MetadataUrl_; + bitField0_ |= 0x00000004; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + input.readMessage( + internalGetFlowsFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + oauth2MetadataUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object description_ = ""; + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.OAuthFlows flows_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OAuthFlows, org.a2aproject.sdk.compat03.grpc.OAuthFlows.Builder, org.a2aproject.sdk.compat03.grpc.OAuthFlowsOrBuilder> flowsBuilder_; + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + * @return Whether the flows field is set. + */ + public boolean hasFlows() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + * @return The flows. + */ + public org.a2aproject.sdk.compat03.grpc.OAuthFlows getFlows() { + if (flowsBuilder_ == null) { + return flows_ == null ? org.a2aproject.sdk.compat03.grpc.OAuthFlows.getDefaultInstance() : flows_; + } else { + return flowsBuilder_.getMessage(); + } + } + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + public Builder setFlows(org.a2aproject.sdk.compat03.grpc.OAuthFlows value) { + if (flowsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + flows_ = value; + } else { + flowsBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + public Builder setFlows( + org.a2aproject.sdk.compat03.grpc.OAuthFlows.Builder builderForValue) { + if (flowsBuilder_ == null) { + flows_ = builderForValue.build(); + } else { + flowsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + public Builder mergeFlows(org.a2aproject.sdk.compat03.grpc.OAuthFlows value) { + if (flowsBuilder_ == null) { + if (((bitField0_ & 0x00000002) != 0) && + flows_ != null && + flows_ != org.a2aproject.sdk.compat03.grpc.OAuthFlows.getDefaultInstance()) { + getFlowsBuilder().mergeFrom(value); + } else { + flows_ = value; + } + } else { + flowsBuilder_.mergeFrom(value); + } + if (flows_ != null) { + bitField0_ |= 0x00000002; + onChanged(); + } + return this; + } + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + public Builder clearFlows() { + bitField0_ = (bitField0_ & ~0x00000002); + flows_ = null; + if (flowsBuilder_ != null) { + flowsBuilder_.dispose(); + flowsBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + public org.a2aproject.sdk.compat03.grpc.OAuthFlows.Builder getFlowsBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return internalGetFlowsFieldBuilder().getBuilder(); + } + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + public org.a2aproject.sdk.compat03.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { + if (flowsBuilder_ != null) { + return flowsBuilder_.getMessageOrBuilder(); + } else { + return flows_ == null ? + org.a2aproject.sdk.compat03.grpc.OAuthFlows.getDefaultInstance() : flows_; + } + } + /** + *
            +     * An object containing configuration information for the flow types supported
            +     * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OAuthFlows, org.a2aproject.sdk.compat03.grpc.OAuthFlows.Builder, org.a2aproject.sdk.compat03.grpc.OAuthFlowsOrBuilder> + internalGetFlowsFieldBuilder() { + if (flowsBuilder_ == null) { + flowsBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OAuthFlows, org.a2aproject.sdk.compat03.grpc.OAuthFlows.Builder, org.a2aproject.sdk.compat03.grpc.OAuthFlowsOrBuilder>( + getFlows(), + getParentForChildren(), + isClean()); + flows_ = null; + } + return flowsBuilder_; + } + + private java.lang.Object oauth2MetadataUrl_ = ""; + /** + *
            +     * URL to the oauth2 authorization server metadata
            +     * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +     * 
            + * + * string oauth2_metadata_url = 3; + * @return The oauth2MetadataUrl. + */ + public java.lang.String getOauth2MetadataUrl() { + java.lang.Object ref = oauth2MetadataUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + oauth2MetadataUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * URL to the oauth2 authorization server metadata
            +     * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +     * 
            + * + * string oauth2_metadata_url = 3; + * @return The bytes for oauth2MetadataUrl. + */ + public com.google.protobuf.ByteString + getOauth2MetadataUrlBytes() { + java.lang.Object ref = oauth2MetadataUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + oauth2MetadataUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * URL to the oauth2 authorization server metadata
            +     * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +     * 
            + * + * string oauth2_metadata_url = 3; + * @param value The oauth2MetadataUrl to set. + * @return This builder for chaining. + */ + public Builder setOauth2MetadataUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + oauth2MetadataUrl_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * URL to the oauth2 authorization server metadata
            +     * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +     * 
            + * + * string oauth2_metadata_url = 3; + * @return This builder for chaining. + */ + public Builder clearOauth2MetadataUrl() { + oauth2MetadataUrl_ = getDefaultInstance().getOauth2MetadataUrl(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * URL to the oauth2 authorization server metadata
            +     * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +     * 
            + * + * string oauth2_metadata_url = 3; + * @param value The bytes for oauth2MetadataUrl to set. + * @return This builder for chaining. + */ + public Builder setOauth2MetadataUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + oauth2MetadataUrl_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.OAuth2SecurityScheme) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.OAuth2SecurityScheme) + private static final org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme(); + } + + public static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public OAuth2SecurityScheme parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuth2SecuritySchemeOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuth2SecuritySchemeOrBuilder.java new file mode 100644 index 000000000..5c70e7de2 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuth2SecuritySchemeOrBuilder.java @@ -0,0 +1,81 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface OAuth2SecuritySchemeOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.OAuth2SecurityScheme) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + *
            +   * An object containing configuration information for the flow types supported
            +   * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + * @return Whether the flows field is set. + */ + boolean hasFlows(); + /** + *
            +   * An object containing configuration information for the flow types supported
            +   * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + * @return The flows. + */ + org.a2aproject.sdk.compat03.grpc.OAuthFlows getFlows(); + /** + *
            +   * An object containing configuration information for the flow types supported
            +   * 
            + * + * .a2a.v1.OAuthFlows flows = 2; + */ + org.a2aproject.sdk.compat03.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder(); + + /** + *
            +   * URL to the oauth2 authorization server metadata
            +   * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +   * 
            + * + * string oauth2_metadata_url = 3; + * @return The oauth2MetadataUrl. + */ + java.lang.String getOauth2MetadataUrl(); + /** + *
            +   * URL to the oauth2 authorization server metadata
            +   * [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
            +   * 
            + * + * string oauth2_metadata_url = 3; + * @return The bytes for oauth2MetadataUrl. + */ + com.google.protobuf.ByteString + getOauth2MetadataUrlBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuthFlows.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuthFlows.java new file mode 100644 index 000000000..26061124c --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuthFlows.java @@ -0,0 +1,1273 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.OAuthFlows} + */ +@com.google.protobuf.Generated +public final class OAuthFlows extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.OAuthFlows) + OAuthFlowsOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "OAuthFlows"); + } + // Use OAuthFlows.newBuilder() to construct. + private OAuthFlows(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private OAuthFlows() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_OAuthFlows_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_OAuthFlows_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.OAuthFlows.class, org.a2aproject.sdk.compat03.grpc.OAuthFlows.Builder.class); + } + + private int flowCase_ = 0; + @SuppressWarnings("serial") + private java.lang.Object flow_; + public enum FlowCase + implements com.google.protobuf.Internal.EnumLite, + com.google.protobuf.AbstractMessage.InternalOneOfEnum { + AUTHORIZATION_CODE(1), + CLIENT_CREDENTIALS(2), + IMPLICIT(3), + PASSWORD(4), + FLOW_NOT_SET(0); + private final int value; + private FlowCase(int value) { + this.value = value; + } + /** + * @param value The number of the enum to look for. + * @return The enum associated with the given number. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static FlowCase valueOf(int value) { + return forNumber(value); + } + + public static FlowCase forNumber(int value) { + switch (value) { + case 1: return AUTHORIZATION_CODE; + case 2: return CLIENT_CREDENTIALS; + case 3: return IMPLICIT; + case 4: return PASSWORD; + case 0: return FLOW_NOT_SET; + default: return null; + } + } + public int getNumber() { + return this.value; + } + }; + + public FlowCase + getFlowCase() { + return FlowCase.forNumber( + flowCase_); + } + + public static final int AUTHORIZATION_CODE_FIELD_NUMBER = 1; + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * @return Whether the authorizationCode field is set. + */ + @java.lang.Override + public boolean hasAuthorizationCode() { + return flowCase_ == 1; + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * @return The authorizationCode. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() { + if (flowCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() { + if (flowCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); + } + + public static final int CLIENT_CREDENTIALS_FIELD_NUMBER = 2; + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * @return Whether the clientCredentials field is set. + */ + @java.lang.Override + public boolean hasClientCredentials() { + return flowCase_ == 2; + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * @return The clientCredentials. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow getClientCredentials() { + if (flowCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() { + if (flowCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); + } + + public static final int IMPLICIT_FIELD_NUMBER = 3; + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + * @return Whether the implicit field is set. + */ + @java.lang.Override + public boolean hasImplicit() { + return flowCase_ == 3; + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + * @return The implicit. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow getImplicit() { + if (flowCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance(); + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() { + if (flowCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance(); + } + + public static final int PASSWORD_FIELD_NUMBER = 4; + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + * @return Whether the password field is set. + */ + @java.lang.Override + public boolean hasPassword() { + return flowCase_ == 4; + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + * @return The password. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow getPassword() { + if (flowCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance(); + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() { + if (flowCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance(); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (flowCase_ == 1) { + output.writeMessage(1, (org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) flow_); + } + if (flowCase_ == 2) { + output.writeMessage(2, (org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) flow_); + } + if (flowCase_ == 3) { + output.writeMessage(3, (org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) flow_); + } + if (flowCase_ == 4) { + output.writeMessage(4, (org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) flow_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (flowCase_ == 1) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, (org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) flow_); + } + if (flowCase_ == 2) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, (org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) flow_); + } + if (flowCase_ == 3) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, (org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) flow_); + } + if (flowCase_ == 4) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, (org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) flow_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.OAuthFlows)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.OAuthFlows other = (org.a2aproject.sdk.compat03.grpc.OAuthFlows) obj; + + if (!getFlowCase().equals(other.getFlowCase())) return false; + switch (flowCase_) { + case 1: + if (!getAuthorizationCode() + .equals(other.getAuthorizationCode())) return false; + break; + case 2: + if (!getClientCredentials() + .equals(other.getClientCredentials())) return false; + break; + case 3: + if (!getImplicit() + .equals(other.getImplicit())) return false; + break; + case 4: + if (!getPassword() + .equals(other.getPassword())) return false; + break; + case 0: + default: + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + switch (flowCase_) { + case 1: + hash = (37 * hash) + AUTHORIZATION_CODE_FIELD_NUMBER; + hash = (53 * hash) + getAuthorizationCode().hashCode(); + break; + case 2: + hash = (37 * hash) + CLIENT_CREDENTIALS_FIELD_NUMBER; + hash = (53 * hash) + getClientCredentials().hashCode(); + break; + case 3: + hash = (37 * hash) + IMPLICIT_FIELD_NUMBER; + hash = (53 * hash) + getImplicit().hashCode(); + break; + case 4: + hash = (37 * hash) + PASSWORD_FIELD_NUMBER; + hash = (53 * hash) + getPassword().hashCode(); + break; + case 0: + default: + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.OAuthFlows prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.OAuthFlows} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.OAuthFlows) + org.a2aproject.sdk.compat03.grpc.OAuthFlowsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_OAuthFlows_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_OAuthFlows_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.OAuthFlows.class, org.a2aproject.sdk.compat03.grpc.OAuthFlows.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.OAuthFlows.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + if (authorizationCodeBuilder_ != null) { + authorizationCodeBuilder_.clear(); + } + if (clientCredentialsBuilder_ != null) { + clientCredentialsBuilder_.clear(); + } + if (implicitBuilder_ != null) { + implicitBuilder_.clear(); + } + if (passwordBuilder_ != null) { + passwordBuilder_.clear(); + } + flowCase_ = 0; + flow_ = null; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_OAuthFlows_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuthFlows getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.OAuthFlows.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuthFlows build() { + org.a2aproject.sdk.compat03.grpc.OAuthFlows result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuthFlows buildPartial() { + org.a2aproject.sdk.compat03.grpc.OAuthFlows result = new org.a2aproject.sdk.compat03.grpc.OAuthFlows(this); + if (bitField0_ != 0) { buildPartial0(result); } + buildPartialOneofs(result); + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.OAuthFlows result) { + int from_bitField0_ = bitField0_; + } + + private void buildPartialOneofs(org.a2aproject.sdk.compat03.grpc.OAuthFlows result) { + result.flowCase_ = flowCase_; + result.flow_ = this.flow_; + if (flowCase_ == 1 && + authorizationCodeBuilder_ != null) { + result.flow_ = authorizationCodeBuilder_.build(); + } + if (flowCase_ == 2 && + clientCredentialsBuilder_ != null) { + result.flow_ = clientCredentialsBuilder_.build(); + } + if (flowCase_ == 3 && + implicitBuilder_ != null) { + result.flow_ = implicitBuilder_.build(); + } + if (flowCase_ == 4 && + passwordBuilder_ != null) { + result.flow_ = passwordBuilder_.build(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.OAuthFlows) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.OAuthFlows)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.OAuthFlows other) { + if (other == org.a2aproject.sdk.compat03.grpc.OAuthFlows.getDefaultInstance()) return this; + switch (other.getFlowCase()) { + case AUTHORIZATION_CODE: { + mergeAuthorizationCode(other.getAuthorizationCode()); + break; + } + case CLIENT_CREDENTIALS: { + mergeClientCredentials(other.getClientCredentials()); + break; + } + case IMPLICIT: { + mergeImplicit(other.getImplicit()); + break; + } + case PASSWORD: { + mergePassword(other.getPassword()); + break; + } + case FLOW_NOT_SET: { + break; + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + input.readMessage( + internalGetAuthorizationCodeFieldBuilder().getBuilder(), + extensionRegistry); + flowCase_ = 1; + break; + } // case 10 + case 18: { + input.readMessage( + internalGetClientCredentialsFieldBuilder().getBuilder(), + extensionRegistry); + flowCase_ = 2; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetImplicitFieldBuilder().getBuilder(), + extensionRegistry); + flowCase_ = 3; + break; + } // case 26 + case 34: { + input.readMessage( + internalGetPasswordFieldBuilder().getBuilder(), + extensionRegistry); + flowCase_ = 4; + break; + } // case 34 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int flowCase_ = 0; + private java.lang.Object flow_; + public FlowCase + getFlowCase() { + return FlowCase.forNumber( + flowCase_); + } + + public Builder clearFlow() { + flowCase_ = 0; + flow_ = null; + onChanged(); + return this; + } + + private int bitField0_; + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow, org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlowOrBuilder> authorizationCodeBuilder_; + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * @return Whether the authorizationCode field is set. + */ + @java.lang.Override + public boolean hasAuthorizationCode() { + return flowCase_ == 1; + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * @return The authorizationCode. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() { + if (authorizationCodeBuilder_ == null) { + if (flowCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); + } else { + if (flowCase_ == 1) { + return authorizationCodeBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); + } + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + public Builder setAuthorizationCode(org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow value) { + if (authorizationCodeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + flow_ = value; + onChanged(); + } else { + authorizationCodeBuilder_.setMessage(value); + } + flowCase_ = 1; + return this; + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + public Builder setAuthorizationCode( + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.Builder builderForValue) { + if (authorizationCodeBuilder_ == null) { + flow_ = builderForValue.build(); + onChanged(); + } else { + authorizationCodeBuilder_.setMessage(builderForValue.build()); + } + flowCase_ = 1; + return this; + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + public Builder mergeAuthorizationCode(org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow value) { + if (authorizationCodeBuilder_ == null) { + if (flowCase_ == 1 && + flow_ != org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance()) { + flow_ = org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.newBuilder((org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) flow_) + .mergeFrom(value).buildPartial(); + } else { + flow_ = value; + } + onChanged(); + } else { + if (flowCase_ == 1) { + authorizationCodeBuilder_.mergeFrom(value); + } else { + authorizationCodeBuilder_.setMessage(value); + } + } + flowCase_ = 1; + return this; + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + public Builder clearAuthorizationCode() { + if (authorizationCodeBuilder_ == null) { + if (flowCase_ == 1) { + flowCase_ = 0; + flow_ = null; + onChanged(); + } + } else { + if (flowCase_ == 1) { + flowCase_ = 0; + flow_ = null; + } + authorizationCodeBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.Builder getAuthorizationCodeBuilder() { + return internalGetAuthorizationCodeFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() { + if ((flowCase_ == 1) && (authorizationCodeBuilder_ != null)) { + return authorizationCodeBuilder_.getMessageOrBuilder(); + } else { + if (flowCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); + } + } + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow, org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlowOrBuilder> + internalGetAuthorizationCodeFieldBuilder() { + if (authorizationCodeBuilder_ == null) { + if (!(flowCase_ == 1)) { + flow_ = org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); + } + authorizationCodeBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow, org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlowOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow) flow_, + getParentForChildren(), + isClean()); + flow_ = null; + } + flowCase_ = 1; + onChanged(); + return authorizationCodeBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow, org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlowOrBuilder> clientCredentialsBuilder_; + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * @return Whether the clientCredentials field is set. + */ + @java.lang.Override + public boolean hasClientCredentials() { + return flowCase_ == 2; + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * @return The clientCredentials. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow getClientCredentials() { + if (clientCredentialsBuilder_ == null) { + if (flowCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); + } else { + if (flowCase_ == 2) { + return clientCredentialsBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); + } + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + public Builder setClientCredentials(org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow value) { + if (clientCredentialsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + flow_ = value; + onChanged(); + } else { + clientCredentialsBuilder_.setMessage(value); + } + flowCase_ = 2; + return this; + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + public Builder setClientCredentials( + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.Builder builderForValue) { + if (clientCredentialsBuilder_ == null) { + flow_ = builderForValue.build(); + onChanged(); + } else { + clientCredentialsBuilder_.setMessage(builderForValue.build()); + } + flowCase_ = 2; + return this; + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + public Builder mergeClientCredentials(org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow value) { + if (clientCredentialsBuilder_ == null) { + if (flowCase_ == 2 && + flow_ != org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance()) { + flow_ = org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.newBuilder((org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) flow_) + .mergeFrom(value).buildPartial(); + } else { + flow_ = value; + } + onChanged(); + } else { + if (flowCase_ == 2) { + clientCredentialsBuilder_.mergeFrom(value); + } else { + clientCredentialsBuilder_.setMessage(value); + } + } + flowCase_ = 2; + return this; + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + public Builder clearClientCredentials() { + if (clientCredentialsBuilder_ == null) { + if (flowCase_ == 2) { + flowCase_ = 0; + flow_ = null; + onChanged(); + } + } else { + if (flowCase_ == 2) { + flowCase_ = 0; + flow_ = null; + } + clientCredentialsBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.Builder getClientCredentialsBuilder() { + return internalGetClientCredentialsFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() { + if ((flowCase_ == 2) && (clientCredentialsBuilder_ != null)) { + return clientCredentialsBuilder_.getMessageOrBuilder(); + } else { + if (flowCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); + } + } + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow, org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlowOrBuilder> + internalGetClientCredentialsFieldBuilder() { + if (clientCredentialsBuilder_ == null) { + if (!(flowCase_ == 2)) { + flow_ = org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); + } + clientCredentialsBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow, org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlowOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow) flow_, + getParentForChildren(), + isClean()); + flow_ = null; + } + flowCase_ = 2; + onChanged(); + return clientCredentialsBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow, org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlowOrBuilder> implicitBuilder_; + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + * @return Whether the implicit field is set. + */ + @java.lang.Override + public boolean hasImplicit() { + return flowCase_ == 3; + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + * @return The implicit. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow getImplicit() { + if (implicitBuilder_ == null) { + if (flowCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance(); + } else { + if (flowCase_ == 3) { + return implicitBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance(); + } + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + public Builder setImplicit(org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow value) { + if (implicitBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + flow_ = value; + onChanged(); + } else { + implicitBuilder_.setMessage(value); + } + flowCase_ = 3; + return this; + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + public Builder setImplicit( + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.Builder builderForValue) { + if (implicitBuilder_ == null) { + flow_ = builderForValue.build(); + onChanged(); + } else { + implicitBuilder_.setMessage(builderForValue.build()); + } + flowCase_ = 3; + return this; + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + public Builder mergeImplicit(org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow value) { + if (implicitBuilder_ == null) { + if (flowCase_ == 3 && + flow_ != org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance()) { + flow_ = org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.newBuilder((org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) flow_) + .mergeFrom(value).buildPartial(); + } else { + flow_ = value; + } + onChanged(); + } else { + if (flowCase_ == 3) { + implicitBuilder_.mergeFrom(value); + } else { + implicitBuilder_.setMessage(value); + } + } + flowCase_ = 3; + return this; + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + public Builder clearImplicit() { + if (implicitBuilder_ == null) { + if (flowCase_ == 3) { + flowCase_ = 0; + flow_ = null; + onChanged(); + } + } else { + if (flowCase_ == 3) { + flowCase_ = 0; + flow_ = null; + } + implicitBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.Builder getImplicitBuilder() { + return internalGetImplicitFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() { + if ((flowCase_ == 3) && (implicitBuilder_ != null)) { + return implicitBuilder_.getMessageOrBuilder(); + } else { + if (flowCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance(); + } + } + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow, org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlowOrBuilder> + internalGetImplicitFieldBuilder() { + if (implicitBuilder_ == null) { + if (!(flowCase_ == 3)) { + flow_ = org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.getDefaultInstance(); + } + implicitBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow, org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlowOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow) flow_, + getParentForChildren(), + isClean()); + flow_ = null; + } + flowCase_ = 3; + onChanged(); + return implicitBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow, org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlowOrBuilder> passwordBuilder_; + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + * @return Whether the password field is set. + */ + @java.lang.Override + public boolean hasPassword() { + return flowCase_ == 4; + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + * @return The password. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow getPassword() { + if (passwordBuilder_ == null) { + if (flowCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance(); + } else { + if (flowCase_ == 4) { + return passwordBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance(); + } + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + public Builder setPassword(org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow value) { + if (passwordBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + flow_ = value; + onChanged(); + } else { + passwordBuilder_.setMessage(value); + } + flowCase_ = 4; + return this; + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + public Builder setPassword( + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.Builder builderForValue) { + if (passwordBuilder_ == null) { + flow_ = builderForValue.build(); + onChanged(); + } else { + passwordBuilder_.setMessage(builderForValue.build()); + } + flowCase_ = 4; + return this; + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + public Builder mergePassword(org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow value) { + if (passwordBuilder_ == null) { + if (flowCase_ == 4 && + flow_ != org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance()) { + flow_ = org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.newBuilder((org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) flow_) + .mergeFrom(value).buildPartial(); + } else { + flow_ = value; + } + onChanged(); + } else { + if (flowCase_ == 4) { + passwordBuilder_.mergeFrom(value); + } else { + passwordBuilder_.setMessage(value); + } + } + flowCase_ = 4; + return this; + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + public Builder clearPassword() { + if (passwordBuilder_ == null) { + if (flowCase_ == 4) { + flowCase_ = 0; + flow_ = null; + onChanged(); + } + } else { + if (flowCase_ == 4) { + flowCase_ = 0; + flow_ = null; + } + passwordBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.Builder getPasswordBuilder() { + return internalGetPasswordFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() { + if ((flowCase_ == 4) && (passwordBuilder_ != null)) { + return passwordBuilder_.getMessageOrBuilder(); + } else { + if (flowCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) flow_; + } + return org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance(); + } + } + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow, org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlowOrBuilder> + internalGetPasswordFieldBuilder() { + if (passwordBuilder_ == null) { + if (!(flowCase_ == 4)) { + flow_ = org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance(); + } + passwordBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow, org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.Builder, org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlowOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) flow_, + getParentForChildren(), + isClean()); + flow_ = null; + } + flowCase_ = 4; + onChanged(); + return passwordBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.OAuthFlows) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.OAuthFlows) + private static final org.a2aproject.sdk.compat03.grpc.OAuthFlows DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.OAuthFlows(); + } + + public static org.a2aproject.sdk.compat03.grpc.OAuthFlows getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public OAuthFlows parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuthFlows getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuthFlowsOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuthFlowsOrBuilder.java new file mode 100644 index 000000000..1e14dbf55 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OAuthFlowsOrBuilder.java @@ -0,0 +1,74 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface OAuthFlowsOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.OAuthFlows) + com.google.protobuf.MessageOrBuilder { + + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * @return Whether the authorizationCode field is set. + */ + boolean hasAuthorizationCode(); + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + * @return The authorizationCode. + */ + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode(); + /** + * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; + */ + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder(); + + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * @return Whether the clientCredentials field is set. + */ + boolean hasClientCredentials(); + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + * @return The clientCredentials. + */ + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow getClientCredentials(); + /** + * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; + */ + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder(); + + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + * @return Whether the implicit field is set. + */ + boolean hasImplicit(); + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + * @return The implicit. + */ + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow getImplicit(); + /** + * .a2a.v1.ImplicitOAuthFlow implicit = 3; + */ + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder(); + + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + * @return Whether the password field is set. + */ + boolean hasPassword(); + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + * @return The password. + */ + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow getPassword(); + /** + * .a2a.v1.PasswordOAuthFlow password = 4; + */ + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder(); + + org.a2aproject.sdk.compat03.grpc.OAuthFlows.FlowCase getFlowCase(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OpenIdConnectSecurityScheme.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OpenIdConnectSecurityScheme.java new file mode 100644 index 000000000..ff9ff9559 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OpenIdConnectSecurityScheme.java @@ -0,0 +1,701 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.OpenIdConnectSecurityScheme} + */ +@com.google.protobuf.Generated +public final class OpenIdConnectSecurityScheme extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.OpenIdConnectSecurityScheme) + OpenIdConnectSecuritySchemeOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "OpenIdConnectSecurityScheme"); + } + // Use OpenIdConnectSecurityScheme.newBuilder() to construct. + private OpenIdConnectSecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private OpenIdConnectSecurityScheme() { + description_ = ""; + openIdConnectUrl_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.class, org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder.class); + } + + public static final int DESCRIPTION_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object description_ = ""; + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + @java.lang.Override + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } + } + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int OPEN_ID_CONNECT_URL_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object openIdConnectUrl_ = ""; + /** + *
            +   * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +   * metadata.
            +   * 
            + * + * string open_id_connect_url = 2; + * @return The openIdConnectUrl. + */ + @java.lang.Override + public java.lang.String getOpenIdConnectUrl() { + java.lang.Object ref = openIdConnectUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + openIdConnectUrl_ = s; + return s; + } + } + /** + *
            +   * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +   * metadata.
            +   * 
            + * + * string open_id_connect_url = 2; + * @return The bytes for openIdConnectUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getOpenIdConnectUrlBytes() { + java.lang.Object ref = openIdConnectUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + openIdConnectUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(openIdConnectUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, openIdConnectUrl_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(openIdConnectUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, openIdConnectUrl_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme other = (org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) obj; + + if (!getDescription() + .equals(other.getDescription())) return false; + if (!getOpenIdConnectUrl() + .equals(other.getOpenIdConnectUrl())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; + hash = (53 * hash) + getDescription().hashCode(); + hash = (37 * hash) + OPEN_ID_CONNECT_URL_FIELD_NUMBER; + hash = (53 * hash) + getOpenIdConnectUrl().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.OpenIdConnectSecurityScheme} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.OpenIdConnectSecurityScheme) + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecuritySchemeOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.class, org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + description_ = ""; + openIdConnectUrl_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme build() { + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme buildPartial() { + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme result = new org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.description_ = description_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.openIdConnectUrl_ = openIdConnectUrl_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme other) { + if (other == org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance()) return this; + if (!other.getDescription().isEmpty()) { + description_ = other.description_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getOpenIdConnectUrl().isEmpty()) { + openIdConnectUrl_ = other.openIdConnectUrl_; + bitField0_ |= 0x00000002; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + description_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + openIdConnectUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object description_ = ""; + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The description. + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + description_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return The bytes for description. + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The description to set. + * @return This builder for chaining. + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @return This builder for chaining. + */ + public Builder clearDescription() { + description_ = getDefaultInstance().getDescription(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * Description of this security scheme.
            +     * 
            + * + * string description = 1; + * @param value The bytes for description to set. + * @return This builder for chaining. + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + description_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object openIdConnectUrl_ = ""; + /** + *
            +     * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +     * metadata.
            +     * 
            + * + * string open_id_connect_url = 2; + * @return The openIdConnectUrl. + */ + public java.lang.String getOpenIdConnectUrl() { + java.lang.Object ref = openIdConnectUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + openIdConnectUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +     * metadata.
            +     * 
            + * + * string open_id_connect_url = 2; + * @return The bytes for openIdConnectUrl. + */ + public com.google.protobuf.ByteString + getOpenIdConnectUrlBytes() { + java.lang.Object ref = openIdConnectUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + openIdConnectUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +     * metadata.
            +     * 
            + * + * string open_id_connect_url = 2; + * @param value The openIdConnectUrl to set. + * @return This builder for chaining. + */ + public Builder setOpenIdConnectUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + openIdConnectUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +     * metadata.
            +     * 
            + * + * string open_id_connect_url = 2; + * @return This builder for chaining. + */ + public Builder clearOpenIdConnectUrl() { + openIdConnectUrl_ = getDefaultInstance().getOpenIdConnectUrl(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +     * metadata.
            +     * 
            + * + * string open_id_connect_url = 2; + * @param value The bytes for openIdConnectUrl to set. + * @return This builder for chaining. + */ + public Builder setOpenIdConnectUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + openIdConnectUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.OpenIdConnectSecurityScheme) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.OpenIdConnectSecurityScheme) + private static final org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme(); + } + + public static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public OpenIdConnectSecurityScheme parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OpenIdConnectSecuritySchemeOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OpenIdConnectSecuritySchemeOrBuilder.java new file mode 100644 index 000000000..1f9237cad --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/OpenIdConnectSecuritySchemeOrBuilder.java @@ -0,0 +1,54 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface OpenIdConnectSecuritySchemeOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.OpenIdConnectSecurityScheme) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The description. + */ + java.lang.String getDescription(); + /** + *
            +   * Description of this security scheme.
            +   * 
            + * + * string description = 1; + * @return The bytes for description. + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + *
            +   * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +   * metadata.
            +   * 
            + * + * string open_id_connect_url = 2; + * @return The openIdConnectUrl. + */ + java.lang.String getOpenIdConnectUrl(); + /** + *
            +   * Well-known URL to discover the [[OpenID-Connect-Discovery]] provider
            +   * metadata.
            +   * 
            + * + * string open_id_connect_url = 2; + * @return The bytes for openIdConnectUrl. + */ + com.google.protobuf.ByteString + getOpenIdConnectUrlBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Part.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Part.java new file mode 100644 index 000000000..fc1133039 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Part.java @@ -0,0 +1,1042 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Part represents a container for a section of communication content.
            + * Parts can be purely textual, some sort of file (image, video, etc) or
            + * a structured data blob (i.e. JSON).
            + * 
            + * + * Protobuf type {@code a2a.v1.Part} + */ +@com.google.protobuf.Generated +public final class Part extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.Part) + PartOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "Part"); + } + // Use Part.newBuilder() to construct. + private Part(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Part() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Part_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Part_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Part.class, org.a2aproject.sdk.compat03.grpc.Part.Builder.class); + } + + private int partCase_ = 0; + @SuppressWarnings("serial") + private java.lang.Object part_; + public enum PartCase + implements com.google.protobuf.Internal.EnumLite, + com.google.protobuf.AbstractMessage.InternalOneOfEnum { + TEXT(1), + FILE(2), + DATA(3), + PART_NOT_SET(0); + private final int value; + private PartCase(int value) { + this.value = value; + } + /** + * @param value The number of the enum to look for. + * @return The enum associated with the given number. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static PartCase valueOf(int value) { + return forNumber(value); + } + + public static PartCase forNumber(int value) { + switch (value) { + case 1: return TEXT; + case 2: return FILE; + case 3: return DATA; + case 0: return PART_NOT_SET; + default: return null; + } + } + public int getNumber() { + return this.value; + } + }; + + public PartCase + getPartCase() { + return PartCase.forNumber( + partCase_); + } + + public static final int TEXT_FIELD_NUMBER = 1; + /** + * string text = 1; + * @return Whether the text field is set. + */ + public boolean hasText() { + return partCase_ == 1; + } + /** + * string text = 1; + * @return The text. + */ + public java.lang.String getText() { + java.lang.Object ref = ""; + if (partCase_ == 1) { + ref = part_; + } + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (partCase_ == 1) { + part_ = s; + } + return s; + } + } + /** + * string text = 1; + * @return The bytes for text. + */ + public com.google.protobuf.ByteString + getTextBytes() { + java.lang.Object ref = ""; + if (partCase_ == 1) { + ref = part_; + } + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + if (partCase_ == 1) { + part_ = b; + } + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int FILE_FIELD_NUMBER = 2; + /** + * .a2a.v1.FilePart file = 2; + * @return Whether the file field is set. + */ + @java.lang.Override + public boolean hasFile() { + return partCase_ == 2; + } + /** + * .a2a.v1.FilePart file = 2; + * @return The file. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.FilePart getFile() { + if (partCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.FilePart) part_; + } + return org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(); + } + /** + * .a2a.v1.FilePart file = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.FilePartOrBuilder getFileOrBuilder() { + if (partCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.FilePart) part_; + } + return org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(); + } + + public static final int DATA_FIELD_NUMBER = 3; + /** + * .a2a.v1.DataPart data = 3; + * @return Whether the data field is set. + */ + @java.lang.Override + public boolean hasData() { + return partCase_ == 3; + } + /** + * .a2a.v1.DataPart data = 3; + * @return The data. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DataPart getData() { + if (partCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.DataPart) part_; + } + return org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(); + } + /** + * .a2a.v1.DataPart data = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DataPartOrBuilder getDataOrBuilder() { + if (partCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.DataPart) part_; + } + return org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (partCase_ == 1) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, part_); + } + if (partCase_ == 2) { + output.writeMessage(2, (org.a2aproject.sdk.compat03.grpc.FilePart) part_); + } + if (partCase_ == 3) { + output.writeMessage(3, (org.a2aproject.sdk.compat03.grpc.DataPart) part_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (partCase_ == 1) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, part_); + } + if (partCase_ == 2) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, (org.a2aproject.sdk.compat03.grpc.FilePart) part_); + } + if (partCase_ == 3) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, (org.a2aproject.sdk.compat03.grpc.DataPart) part_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.Part)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.Part other = (org.a2aproject.sdk.compat03.grpc.Part) obj; + + if (!getPartCase().equals(other.getPartCase())) return false; + switch (partCase_) { + case 1: + if (!getText() + .equals(other.getText())) return false; + break; + case 2: + if (!getFile() + .equals(other.getFile())) return false; + break; + case 3: + if (!getData() + .equals(other.getData())) return false; + break; + case 0: + default: + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + switch (partCase_) { + case 1: + hash = (37 * hash) + TEXT_FIELD_NUMBER; + hash = (53 * hash) + getText().hashCode(); + break; + case 2: + hash = (37 * hash) + FILE_FIELD_NUMBER; + hash = (53 * hash) + getFile().hashCode(); + break; + case 3: + hash = (37 * hash) + DATA_FIELD_NUMBER; + hash = (53 * hash) + getData().hashCode(); + break; + case 0: + default: + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.Part parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.Part parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Part parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.Part prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Part represents a container for a section of communication content.
            +   * Parts can be purely textual, some sort of file (image, video, etc) or
            +   * a structured data blob (i.e. JSON).
            +   * 
            + * + * Protobuf type {@code a2a.v1.Part} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.Part) + org.a2aproject.sdk.compat03.grpc.PartOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Part_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Part_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Part.class, org.a2aproject.sdk.compat03.grpc.Part.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.Part.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + if (fileBuilder_ != null) { + fileBuilder_.clear(); + } + if (dataBuilder_ != null) { + dataBuilder_.clear(); + } + partCase_ = 0; + part_ = null; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_Part_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Part getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.Part.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Part build() { + org.a2aproject.sdk.compat03.grpc.Part result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Part buildPartial() { + org.a2aproject.sdk.compat03.grpc.Part result = new org.a2aproject.sdk.compat03.grpc.Part(this); + if (bitField0_ != 0) { buildPartial0(result); } + buildPartialOneofs(result); + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.Part result) { + int from_bitField0_ = bitField0_; + } + + private void buildPartialOneofs(org.a2aproject.sdk.compat03.grpc.Part result) { + result.partCase_ = partCase_; + result.part_ = this.part_; + if (partCase_ == 2 && + fileBuilder_ != null) { + result.part_ = fileBuilder_.build(); + } + if (partCase_ == 3 && + dataBuilder_ != null) { + result.part_ = dataBuilder_.build(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.Part) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.Part)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.Part other) { + if (other == org.a2aproject.sdk.compat03.grpc.Part.getDefaultInstance()) return this; + switch (other.getPartCase()) { + case TEXT: { + partCase_ = 1; + part_ = other.part_; + onChanged(); + break; + } + case FILE: { + mergeFile(other.getFile()); + break; + } + case DATA: { + mergeData(other.getData()); + break; + } + case PART_NOT_SET: { + break; + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + partCase_ = 1; + part_ = s; + break; + } // case 10 + case 18: { + input.readMessage( + internalGetFileFieldBuilder().getBuilder(), + extensionRegistry); + partCase_ = 2; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetDataFieldBuilder().getBuilder(), + extensionRegistry); + partCase_ = 3; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int partCase_ = 0; + private java.lang.Object part_; + public PartCase + getPartCase() { + return PartCase.forNumber( + partCase_); + } + + public Builder clearPart() { + partCase_ = 0; + part_ = null; + onChanged(); + return this; + } + + private int bitField0_; + + /** + * string text = 1; + * @return Whether the text field is set. + */ + @java.lang.Override + public boolean hasText() { + return partCase_ == 1; + } + /** + * string text = 1; + * @return The text. + */ + @java.lang.Override + public java.lang.String getText() { + java.lang.Object ref = ""; + if (partCase_ == 1) { + ref = part_; + } + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (partCase_ == 1) { + part_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string text = 1; + * @return The bytes for text. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTextBytes() { + java.lang.Object ref = ""; + if (partCase_ == 1) { + ref = part_; + } + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + if (partCase_ == 1) { + part_ = b; + } + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string text = 1; + * @param value The text to set. + * @return This builder for chaining. + */ + public Builder setText( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + partCase_ = 1; + part_ = value; + onChanged(); + return this; + } + /** + * string text = 1; + * @return This builder for chaining. + */ + public Builder clearText() { + if (partCase_ == 1) { + partCase_ = 0; + part_ = null; + onChanged(); + } + return this; + } + /** + * string text = 1; + * @param value The bytes for text to set. + * @return This builder for chaining. + */ + public Builder setTextBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + partCase_ = 1; + part_ = value; + onChanged(); + return this; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.FilePart, org.a2aproject.sdk.compat03.grpc.FilePart.Builder, org.a2aproject.sdk.compat03.grpc.FilePartOrBuilder> fileBuilder_; + /** + * .a2a.v1.FilePart file = 2; + * @return Whether the file field is set. + */ + @java.lang.Override + public boolean hasFile() { + return partCase_ == 2; + } + /** + * .a2a.v1.FilePart file = 2; + * @return The file. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.FilePart getFile() { + if (fileBuilder_ == null) { + if (partCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.FilePart) part_; + } + return org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(); + } else { + if (partCase_ == 2) { + return fileBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(); + } + } + /** + * .a2a.v1.FilePart file = 2; + */ + public Builder setFile(org.a2aproject.sdk.compat03.grpc.FilePart value) { + if (fileBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + part_ = value; + onChanged(); + } else { + fileBuilder_.setMessage(value); + } + partCase_ = 2; + return this; + } + /** + * .a2a.v1.FilePart file = 2; + */ + public Builder setFile( + org.a2aproject.sdk.compat03.grpc.FilePart.Builder builderForValue) { + if (fileBuilder_ == null) { + part_ = builderForValue.build(); + onChanged(); + } else { + fileBuilder_.setMessage(builderForValue.build()); + } + partCase_ = 2; + return this; + } + /** + * .a2a.v1.FilePart file = 2; + */ + public Builder mergeFile(org.a2aproject.sdk.compat03.grpc.FilePart value) { + if (fileBuilder_ == null) { + if (partCase_ == 2 && + part_ != org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance()) { + part_ = org.a2aproject.sdk.compat03.grpc.FilePart.newBuilder((org.a2aproject.sdk.compat03.grpc.FilePart) part_) + .mergeFrom(value).buildPartial(); + } else { + part_ = value; + } + onChanged(); + } else { + if (partCase_ == 2) { + fileBuilder_.mergeFrom(value); + } else { + fileBuilder_.setMessage(value); + } + } + partCase_ = 2; + return this; + } + /** + * .a2a.v1.FilePart file = 2; + */ + public Builder clearFile() { + if (fileBuilder_ == null) { + if (partCase_ == 2) { + partCase_ = 0; + part_ = null; + onChanged(); + } + } else { + if (partCase_ == 2) { + partCase_ = 0; + part_ = null; + } + fileBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.FilePart file = 2; + */ + public org.a2aproject.sdk.compat03.grpc.FilePart.Builder getFileBuilder() { + return internalGetFileFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.FilePart file = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.FilePartOrBuilder getFileOrBuilder() { + if ((partCase_ == 2) && (fileBuilder_ != null)) { + return fileBuilder_.getMessageOrBuilder(); + } else { + if (partCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.FilePart) part_; + } + return org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(); + } + } + /** + * .a2a.v1.FilePart file = 2; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.FilePart, org.a2aproject.sdk.compat03.grpc.FilePart.Builder, org.a2aproject.sdk.compat03.grpc.FilePartOrBuilder> + internalGetFileFieldBuilder() { + if (fileBuilder_ == null) { + if (!(partCase_ == 2)) { + part_ = org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(); + } + fileBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.FilePart, org.a2aproject.sdk.compat03.grpc.FilePart.Builder, org.a2aproject.sdk.compat03.grpc.FilePartOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.FilePart) part_, + getParentForChildren(), + isClean()); + part_ = null; + } + partCase_ = 2; + onChanged(); + return fileBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.DataPart, org.a2aproject.sdk.compat03.grpc.DataPart.Builder, org.a2aproject.sdk.compat03.grpc.DataPartOrBuilder> dataBuilder_; + /** + * .a2a.v1.DataPart data = 3; + * @return Whether the data field is set. + */ + @java.lang.Override + public boolean hasData() { + return partCase_ == 3; + } + /** + * .a2a.v1.DataPart data = 3; + * @return The data. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DataPart getData() { + if (dataBuilder_ == null) { + if (partCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.DataPart) part_; + } + return org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(); + } else { + if (partCase_ == 3) { + return dataBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(); + } + } + /** + * .a2a.v1.DataPart data = 3; + */ + public Builder setData(org.a2aproject.sdk.compat03.grpc.DataPart value) { + if (dataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + part_ = value; + onChanged(); + } else { + dataBuilder_.setMessage(value); + } + partCase_ = 3; + return this; + } + /** + * .a2a.v1.DataPart data = 3; + */ + public Builder setData( + org.a2aproject.sdk.compat03.grpc.DataPart.Builder builderForValue) { + if (dataBuilder_ == null) { + part_ = builderForValue.build(); + onChanged(); + } else { + dataBuilder_.setMessage(builderForValue.build()); + } + partCase_ = 3; + return this; + } + /** + * .a2a.v1.DataPart data = 3; + */ + public Builder mergeData(org.a2aproject.sdk.compat03.grpc.DataPart value) { + if (dataBuilder_ == null) { + if (partCase_ == 3 && + part_ != org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance()) { + part_ = org.a2aproject.sdk.compat03.grpc.DataPart.newBuilder((org.a2aproject.sdk.compat03.grpc.DataPart) part_) + .mergeFrom(value).buildPartial(); + } else { + part_ = value; + } + onChanged(); + } else { + if (partCase_ == 3) { + dataBuilder_.mergeFrom(value); + } else { + dataBuilder_.setMessage(value); + } + } + partCase_ = 3; + return this; + } + /** + * .a2a.v1.DataPart data = 3; + */ + public Builder clearData() { + if (dataBuilder_ == null) { + if (partCase_ == 3) { + partCase_ = 0; + part_ = null; + onChanged(); + } + } else { + if (partCase_ == 3) { + partCase_ = 0; + part_ = null; + } + dataBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.DataPart data = 3; + */ + public org.a2aproject.sdk.compat03.grpc.DataPart.Builder getDataBuilder() { + return internalGetDataFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.DataPart data = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.DataPartOrBuilder getDataOrBuilder() { + if ((partCase_ == 3) && (dataBuilder_ != null)) { + return dataBuilder_.getMessageOrBuilder(); + } else { + if (partCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.DataPart) part_; + } + return org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(); + } + } + /** + * .a2a.v1.DataPart data = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.DataPart, org.a2aproject.sdk.compat03.grpc.DataPart.Builder, org.a2aproject.sdk.compat03.grpc.DataPartOrBuilder> + internalGetDataFieldBuilder() { + if (dataBuilder_ == null) { + if (!(partCase_ == 3)) { + part_ = org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(); + } + dataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.DataPart, org.a2aproject.sdk.compat03.grpc.DataPart.Builder, org.a2aproject.sdk.compat03.grpc.DataPartOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.DataPart) part_, + getParentForChildren(), + isClean()); + part_ = null; + } + partCase_ = 3; + onChanged(); + return dataBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.Part) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.Part) + private static final org.a2aproject.sdk.compat03.grpc.Part DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.Part(); + } + + public static org.a2aproject.sdk.compat03.grpc.Part getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Part parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Part getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PartOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PartOrBuilder.java new file mode 100644 index 000000000..90b0075d5 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PartOrBuilder.java @@ -0,0 +1,61 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface PartOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.Part) + com.google.protobuf.MessageOrBuilder { + + /** + * string text = 1; + * @return Whether the text field is set. + */ + boolean hasText(); + /** + * string text = 1; + * @return The text. + */ + java.lang.String getText(); + /** + * string text = 1; + * @return The bytes for text. + */ + com.google.protobuf.ByteString + getTextBytes(); + + /** + * .a2a.v1.FilePart file = 2; + * @return Whether the file field is set. + */ + boolean hasFile(); + /** + * .a2a.v1.FilePart file = 2; + * @return The file. + */ + org.a2aproject.sdk.compat03.grpc.FilePart getFile(); + /** + * .a2a.v1.FilePart file = 2; + */ + org.a2aproject.sdk.compat03.grpc.FilePartOrBuilder getFileOrBuilder(); + + /** + * .a2a.v1.DataPart data = 3; + * @return Whether the data field is set. + */ + boolean hasData(); + /** + * .a2a.v1.DataPart data = 3; + * @return The data. + */ + org.a2aproject.sdk.compat03.grpc.DataPart getData(); + /** + * .a2a.v1.DataPart data = 3; + */ + org.a2aproject.sdk.compat03.grpc.DataPartOrBuilder getDataOrBuilder(); + + org.a2aproject.sdk.compat03.grpc.Part.PartCase getPartCase(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PasswordOAuthFlow.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PasswordOAuthFlow.java new file mode 100644 index 000000000..f37e34aad --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PasswordOAuthFlow.java @@ -0,0 +1,1042 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.PasswordOAuthFlow} + */ +@com.google.protobuf.Generated +public final class PasswordOAuthFlow extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.PasswordOAuthFlow) + PasswordOAuthFlowOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "PasswordOAuthFlow"); + } + // Use PasswordOAuthFlow.newBuilder() to construct. + private PasswordOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private PasswordOAuthFlow() { + tokenUrl_ = ""; + refreshUrl_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.class, org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.Builder.class); + } + + public static final int TOKEN_URL_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object tokenUrl_ = ""; + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 1; + * @return The tokenUrl. + */ + @java.lang.Override + public java.lang.String getTokenUrl() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + tokenUrl_ = s; + return s; + } + } + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTokenUrlBytes() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tokenUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REFRESH_URL_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object refreshUrl_ = ""; + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + @java.lang.Override + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } + } + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCOPES_FIELD_NUMBER = 3; + private static final class ScopesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, java.lang.String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + A2A.internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, tokenUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); + } + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetScopes(), + ScopesDefaultEntryHolder.defaultEntry, + 3); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tokenUrl_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); + } + for (java.util.Map.Entry entry + : internalGetScopes().getMap().entrySet()) { + com.google.protobuf.MapEntry + scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, scopes__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow other = (org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) obj; + + if (!getTokenUrl() + .equals(other.getTokenUrl())) return false; + if (!getRefreshUrl() + .equals(other.getRefreshUrl())) return false; + if (!internalGetScopes().equals( + other.internalGetScopes())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; + hash = (53 * hash) + getTokenUrl().hashCode(); + hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; + hash = (53 * hash) + getRefreshUrl().hashCode(); + if (!internalGetScopes().getMap().isEmpty()) { + hash = (37 * hash) + SCOPES_FIELD_NUMBER; + hash = (53 * hash) + internalGetScopes().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.PasswordOAuthFlow} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.PasswordOAuthFlow) + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlowOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 3: + return internalGetMutableScopes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.class, org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + tokenUrl_ = ""; + refreshUrl_ = ""; + internalGetMutableScopes().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow build() { + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow buildPartial() { + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow result = new org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.tokenUrl_ = tokenUrl_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.refreshUrl_ = refreshUrl_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.scopes_ = internalGetScopes(); + result.scopes_.makeImmutable(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow other) { + if (other == org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.getDefaultInstance()) return this; + if (!other.getTokenUrl().isEmpty()) { + tokenUrl_ = other.tokenUrl_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getRefreshUrl().isEmpty()) { + refreshUrl_ = other.refreshUrl_; + bitField0_ |= 0x00000002; + onChanged(); + } + internalGetMutableScopes().mergeFrom( + other.internalGetScopes()); + bitField0_ |= 0x00000004; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + tokenUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + refreshUrl_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + com.google.protobuf.MapEntry + scopes__ = input.readMessage( + ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableScopes().getMutableMap().put( + scopes__.getKey(), scopes__.getValue()); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object tokenUrl_ = ""; + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @return The tokenUrl. + */ + public java.lang.String getTokenUrl() { + java.lang.Object ref = tokenUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + tokenUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + public com.google.protobuf.ByteString + getTokenUrlBytes() { + java.lang.Object ref = tokenUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + tokenUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @param value The tokenUrl to set. + * @return This builder for chaining. + */ + public Builder setTokenUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + tokenUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @return This builder for chaining. + */ + public Builder clearTokenUrl() { + tokenUrl_ = getDefaultInstance().getTokenUrl(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The token URL to be used for this flow. This MUST be in the form of a URL.
            +     * The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string token_url = 1; + * @param value The bytes for tokenUrl to set. + * @return This builder for chaining. + */ + public Builder setTokenUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + tokenUrl_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object refreshUrl_ = ""; + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + public java.lang.String getRefreshUrl() { + java.lang.Object ref = refreshUrl_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + refreshUrl_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + public com.google.protobuf.ByteString + getRefreshUrlBytes() { + java.lang.Object ref = refreshUrl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + refreshUrl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @param value The refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @return This builder for chaining. + */ + public Builder clearRefreshUrl() { + refreshUrl_ = getDefaultInstance().getRefreshUrl(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The URL to be used for obtaining refresh tokens. This MUST be in the
            +     * form of a URL. The OAuth2 standard requires the use of TLS.
            +     * 
            + * + * string refresh_url = 2; + * @param value The bytes for refreshUrl to set. + * @return This builder for chaining. + */ + public Builder setRefreshUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + refreshUrl_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> scopes_; + private com.google.protobuf.MapField + internalGetScopes() { + if (scopes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + return scopes_; + } + private com.google.protobuf.MapField + internalGetMutableScopes() { + if (scopes_ == null) { + scopes_ = com.google.protobuf.MapField.newMapField( + ScopesDefaultEntryHolder.defaultEntry); + } + if (!scopes_.isMutable()) { + scopes_ = scopes_.copy(); + } + bitField0_ |= 0x00000004; + onChanged(); + return scopes_; + } + public int getScopesCount() { + return internalGetScopes().getMap().size(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public boolean containsScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetScopes().getMap().containsKey(key); + } + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getScopes() { + return getScopesMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.util.Map getScopesMap() { + return internalGetScopes().getMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + @java.lang.Override + public java.lang.String getScopesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetScopes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + public Builder clearScopes() { + bitField0_ = (bitField0_ & ~0x00000004); + internalGetMutableScopes().getMutableMap() + .clear(); + return this; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder removeScopes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableScopes().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableScopes() { + bitField0_ |= 0x00000004; + return internalGetMutableScopes().getMutableMap(); + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder putScopes( + java.lang.String key, + java.lang.String value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableScopes().getMutableMap() + .put(key, value); + bitField0_ |= 0x00000004; + return this; + } + /** + *
            +     * The available scopes for the OAuth2 security scheme. A map between the
            +     * scope name and a short description for it. The map MAY be empty.
            +     * 
            + * + * map<string, string> scopes = 3; + */ + public Builder putAllScopes( + java.util.Map values) { + internalGetMutableScopes().getMutableMap() + .putAll(values); + bitField0_ |= 0x00000004; + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.PasswordOAuthFlow) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.PasswordOAuthFlow) + private static final org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow(); + } + + public static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public PasswordOAuthFlow parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PasswordOAuthFlowOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PasswordOAuthFlowOrBuilder.java new file mode 100644 index 000000000..ec5a79ac1 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PasswordOAuthFlowOrBuilder.java @@ -0,0 +1,115 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface PasswordOAuthFlowOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.PasswordOAuthFlow) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 1; + * @return The tokenUrl. + */ + java.lang.String getTokenUrl(); + /** + *
            +   * The token URL to be used for this flow. This MUST be in the form of a URL.
            +   * The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string token_url = 1; + * @return The bytes for tokenUrl. + */ + com.google.protobuf.ByteString + getTokenUrlBytes(); + + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The refreshUrl. + */ + java.lang.String getRefreshUrl(); + /** + *
            +   * The URL to be used for obtaining refresh tokens. This MUST be in the
            +   * form of a URL. The OAuth2 standard requires the use of TLS.
            +   * 
            + * + * string refresh_url = 2; + * @return The bytes for refreshUrl. + */ + com.google.protobuf.ByteString + getRefreshUrlBytes(); + + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + int getScopesCount(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + boolean containsScopes( + java.lang.String key); + /** + * Use {@link #getScopesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getScopes(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + java.util.Map + getScopesMap(); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + /* nullable */ +java.lang.String getScopesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue); + /** + *
            +   * The available scopes for the OAuth2 security scheme. A map between the
            +   * scope name and a short description for it. The map MAY be empty.
            +   * 
            + * + * map<string, string> scopes = 3; + */ + java.lang.String getScopesOrThrow( + java.lang.String key); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PushNotificationConfig.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PushNotificationConfig.java new file mode 100644 index 000000000..c7c9d14c9 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PushNotificationConfig.java @@ -0,0 +1,1107 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Configuration for setting up push notifications for task updates.
            + * 
            + * + * Protobuf type {@code a2a.v1.PushNotificationConfig} + */ +@com.google.protobuf.Generated +public final class PushNotificationConfig extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.PushNotificationConfig) + PushNotificationConfigOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "PushNotificationConfig"); + } + // Use PushNotificationConfig.newBuilder() to construct. + private PushNotificationConfig(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private PushNotificationConfig() { + id_ = ""; + url_ = ""; + token_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.class, org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder.class); + } + + private int bitField0_; + public static final int ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object id_ = ""; + /** + *
            +   * A unique id for this push notification.
            +   * 
            + * + * string id = 1; + * @return The id. + */ + @java.lang.Override + public java.lang.String getId() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + *
            +   * A unique id for this push notification.
            +   * 
            + * + * string id = 1; + * @return The bytes for id. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int URL_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object url_ = ""; + /** + *
            +   * Url to send the notification too
            +   * 
            + * + * string url = 2; + * @return The url. + */ + @java.lang.Override + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } + } + /** + *
            +   * Url to send the notification too
            +   * 
            + * + * string url = 2; + * @return The bytes for url. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TOKEN_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object token_ = ""; + /** + *
            +   * Token unique for this task/session
            +   * 
            + * + * string token = 3; + * @return The token. + */ + @java.lang.Override + public java.lang.String getToken() { + java.lang.Object ref = token_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + token_ = s; + return s; + } + } + /** + *
            +   * Token unique for this task/session
            +   * 
            + * + * string token = 3; + * @return The bytes for token. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTokenBytes() { + java.lang.Object ref = token_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + token_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int AUTHENTICATION_FIELD_NUMBER = 4; + private org.a2aproject.sdk.compat03.grpc.AuthenticationInfo authentication_; + /** + *
            +   * Information about the authentication to sent with the notification
            +   * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + * @return Whether the authentication field is set. + */ + @java.lang.Override + public boolean hasAuthentication() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * Information about the authentication to sent with the notification
            +   * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + * @return The authentication. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfo getAuthentication() { + return authentication_ == null ? org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; + } + /** + *
            +   * Information about the authentication to sent with the notification
            +   * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { + return authentication_ == null ? org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, url_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(token_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, token_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(4, getAuthentication()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, url_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(token_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, token_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getAuthentication()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.PushNotificationConfig)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig other = (org.a2aproject.sdk.compat03.grpc.PushNotificationConfig) obj; + + if (!getId() + .equals(other.getId())) return false; + if (!getUrl() + .equals(other.getUrl())) return false; + if (!getToken() + .equals(other.getToken())) return false; + if (hasAuthentication() != other.hasAuthentication()) return false; + if (hasAuthentication()) { + if (!getAuthentication() + .equals(other.getAuthentication())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); + hash = (37 * hash) + URL_FIELD_NUMBER; + hash = (53 * hash) + getUrl().hashCode(); + hash = (37 * hash) + TOKEN_FIELD_NUMBER; + hash = (53 * hash) + getToken().hashCode(); + if (hasAuthentication()) { + hash = (37 * hash) + AUTHENTICATION_FIELD_NUMBER; + hash = (53 * hash) + getAuthentication().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.PushNotificationConfig prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Configuration for setting up push notifications for task updates.
            +   * 
            + * + * Protobuf type {@code a2a.v1.PushNotificationConfig} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.PushNotificationConfig) + org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.class, org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetAuthenticationFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + id_ = ""; + url_ = ""; + token_ = ""; + authentication_ = null; + if (authenticationBuilder_ != null) { + authenticationBuilder_.dispose(); + authenticationBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig build() { + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig buildPartial() { + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig result = new org.a2aproject.sdk.compat03.grpc.PushNotificationConfig(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.PushNotificationConfig result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.id_ = id_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.url_ = url_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.token_ = token_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000008) != 0)) { + result.authentication_ = authenticationBuilder_ == null + ? authentication_ + : authenticationBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.PushNotificationConfig) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.PushNotificationConfig)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.PushNotificationConfig other) { + if (other == org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance()) return this; + if (!other.getId().isEmpty()) { + id_ = other.id_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getUrl().isEmpty()) { + url_ = other.url_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getToken().isEmpty()) { + token_ = other.token_; + bitField0_ |= 0x00000004; + onChanged(); + } + if (other.hasAuthentication()) { + mergeAuthentication(other.getAuthentication()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + url_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + token_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 34: { + input.readMessage( + internalGetAuthenticationFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000008; + break; + } // case 34 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object id_ = ""; + /** + *
            +     * A unique id for this push notification.
            +     * 
            + * + * string id = 1; + * @return The id. + */ + public java.lang.String getId() { + java.lang.Object ref = id_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * A unique id for this push notification.
            +     * 
            + * + * string id = 1; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * A unique id for this push notification.
            +     * 
            + * + * string id = 1; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * A unique id for this push notification.
            +     * 
            + * + * string id = 1; + * @return This builder for chaining. + */ + public Builder clearId() { + id_ = getDefaultInstance().getId(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * A unique id for this push notification.
            +     * 
            + * + * string id = 1; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object url_ = ""; + /** + *
            +     * Url to send the notification too
            +     * 
            + * + * string url = 2; + * @return The url. + */ + public java.lang.String getUrl() { + java.lang.Object ref = url_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + url_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Url to send the notification too
            +     * 
            + * + * string url = 2; + * @return The bytes for url. + */ + public com.google.protobuf.ByteString + getUrlBytes() { + java.lang.Object ref = url_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Url to send the notification too
            +     * 
            + * + * string url = 2; + * @param value The url to set. + * @return This builder for chaining. + */ + public Builder setUrl( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + url_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * Url to send the notification too
            +     * 
            + * + * string url = 2; + * @return This builder for chaining. + */ + public Builder clearUrl() { + url_ = getDefaultInstance().getUrl(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * Url to send the notification too
            +     * 
            + * + * string url = 2; + * @param value The bytes for url to set. + * @return This builder for chaining. + */ + public Builder setUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + url_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object token_ = ""; + /** + *
            +     * Token unique for this task/session
            +     * 
            + * + * string token = 3; + * @return The token. + */ + public java.lang.String getToken() { + java.lang.Object ref = token_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + token_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Token unique for this task/session
            +     * 
            + * + * string token = 3; + * @return The bytes for token. + */ + public com.google.protobuf.ByteString + getTokenBytes() { + java.lang.Object ref = token_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + token_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Token unique for this task/session
            +     * 
            + * + * string token = 3; + * @param value The token to set. + * @return This builder for chaining. + */ + public Builder setToken( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + token_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * Token unique for this task/session
            +     * 
            + * + * string token = 3; + * @return This builder for chaining. + */ + public Builder clearToken() { + token_ = getDefaultInstance().getToken(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + *
            +     * Token unique for this task/session
            +     * 
            + * + * string token = 3; + * @param value The bytes for token to set. + * @return This builder for chaining. + */ + public Builder setTokenBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + token_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.AuthenticationInfo authentication_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo, org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.Builder, org.a2aproject.sdk.compat03.grpc.AuthenticationInfoOrBuilder> authenticationBuilder_; + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + * @return Whether the authentication field is set. + */ + public boolean hasAuthentication() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + * @return The authentication. + */ + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfo getAuthentication() { + if (authenticationBuilder_ == null) { + return authentication_ == null ? org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; + } else { + return authenticationBuilder_.getMessage(); + } + } + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + public Builder setAuthentication(org.a2aproject.sdk.compat03.grpc.AuthenticationInfo value) { + if (authenticationBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + authentication_ = value; + } else { + authenticationBuilder_.setMessage(value); + } + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + public Builder setAuthentication( + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.Builder builderForValue) { + if (authenticationBuilder_ == null) { + authentication_ = builderForValue.build(); + } else { + authenticationBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + public Builder mergeAuthentication(org.a2aproject.sdk.compat03.grpc.AuthenticationInfo value) { + if (authenticationBuilder_ == null) { + if (((bitField0_ & 0x00000008) != 0) && + authentication_ != null && + authentication_ != org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.getDefaultInstance()) { + getAuthenticationBuilder().mergeFrom(value); + } else { + authentication_ = value; + } + } else { + authenticationBuilder_.mergeFrom(value); + } + if (authentication_ != null) { + bitField0_ |= 0x00000008; + onChanged(); + } + return this; + } + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + public Builder clearAuthentication() { + bitField0_ = (bitField0_ & ~0x00000008); + authentication_ = null; + if (authenticationBuilder_ != null) { + authenticationBuilder_.dispose(); + authenticationBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() { + bitField0_ |= 0x00000008; + onChanged(); + return internalGetAuthenticationFieldBuilder().getBuilder(); + } + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + public org.a2aproject.sdk.compat03.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { + if (authenticationBuilder_ != null) { + return authenticationBuilder_.getMessageOrBuilder(); + } else { + return authentication_ == null ? + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; + } + } + /** + *
            +     * Information about the authentication to sent with the notification
            +     * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo, org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.Builder, org.a2aproject.sdk.compat03.grpc.AuthenticationInfoOrBuilder> + internalGetAuthenticationFieldBuilder() { + if (authenticationBuilder_ == null) { + authenticationBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo, org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.Builder, org.a2aproject.sdk.compat03.grpc.AuthenticationInfoOrBuilder>( + getAuthentication(), + getParentForChildren(), + isClean()); + authentication_ = null; + } + return authenticationBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.PushNotificationConfig) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.PushNotificationConfig) + private static final org.a2aproject.sdk.compat03.grpc.PushNotificationConfig DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.PushNotificationConfig(); + } + + public static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public PushNotificationConfig parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PushNotificationConfigOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PushNotificationConfigOrBuilder.java new file mode 100644 index 000000000..a8990646f --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/PushNotificationConfigOrBuilder.java @@ -0,0 +1,99 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface PushNotificationConfigOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.PushNotificationConfig) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * A unique id for this push notification.
            +   * 
            + * + * string id = 1; + * @return The id. + */ + java.lang.String getId(); + /** + *
            +   * A unique id for this push notification.
            +   * 
            + * + * string id = 1; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); + + /** + *
            +   * Url to send the notification too
            +   * 
            + * + * string url = 2; + * @return The url. + */ + java.lang.String getUrl(); + /** + *
            +   * Url to send the notification too
            +   * 
            + * + * string url = 2; + * @return The bytes for url. + */ + com.google.protobuf.ByteString + getUrlBytes(); + + /** + *
            +   * Token unique for this task/session
            +   * 
            + * + * string token = 3; + * @return The token. + */ + java.lang.String getToken(); + /** + *
            +   * Token unique for this task/session
            +   * 
            + * + * string token = 3; + * @return The bytes for token. + */ + com.google.protobuf.ByteString + getTokenBytes(); + + /** + *
            +   * Information about the authentication to sent with the notification
            +   * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + * @return Whether the authentication field is set. + */ + boolean hasAuthentication(); + /** + *
            +   * Information about the authentication to sent with the notification
            +   * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + * @return The authentication. + */ + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo getAuthentication(); + /** + *
            +   * Information about the authentication to sent with the notification
            +   * 
            + * + * .a2a.v1.AuthenticationInfo authentication = 4; + */ + org.a2aproject.sdk.compat03.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Role.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Role.java new file mode 100644 index 000000000..52116e3a7 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Role.java @@ -0,0 +1,150 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf enum {@code a2a.v1.Role} + */ +@com.google.protobuf.Generated +public enum Role + implements com.google.protobuf.ProtocolMessageEnum { + /** + * ROLE_UNSPECIFIED = 0; + */ + ROLE_UNSPECIFIED(0), + /** + *
            +   * USER role refers to communication from the client to the server.
            +   * 
            + * + * ROLE_USER = 1; + */ + ROLE_USER(1), + /** + *
            +   * AGENT role refers to communication from the server to the client.
            +   * 
            + * + * ROLE_AGENT = 2; + */ + ROLE_AGENT(2), + UNRECOGNIZED(-1), + ; + + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "Role"); + } + /** + * ROLE_UNSPECIFIED = 0; + */ + public static final int ROLE_UNSPECIFIED_VALUE = 0; + /** + *
            +   * USER role refers to communication from the client to the server.
            +   * 
            + * + * ROLE_USER = 1; + */ + public static final int ROLE_USER_VALUE = 1; + /** + *
            +   * AGENT role refers to communication from the server to the client.
            +   * 
            + * + * ROLE_AGENT = 2; + */ + public static final int ROLE_AGENT_VALUE = 2; + + + public final int getNumber() { + if (this == UNRECOGNIZED) { + throw new java.lang.IllegalArgumentException( + "Can't get the number of an unknown enum value."); + } + return value; + } + + /** + * @param value The numeric wire value of the corresponding enum entry. + * @return The enum associated with the given numeric wire value. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static Role valueOf(int value) { + return forNumber(value); + } + + /** + * @param value The numeric wire value of the corresponding enum entry. + * @return The enum associated with the given numeric wire value. + */ + public static Role forNumber(int value) { + switch (value) { + case 0: return ROLE_UNSPECIFIED; + case 1: return ROLE_USER; + case 2: return ROLE_AGENT; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + Role> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public Role findValueByNumber(int number) { + return Role.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + if (this == UNRECOGNIZED) { + throw new java.lang.IllegalStateException( + "Can't get the descriptor of an unrecognized enum value."); + } + return getDescriptor().getValues().get(ordinal()); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return A2A.getDescriptor().getEnumTypes().get(1); + } + + private static final Role[] VALUES = values(); + + public static Role valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private Role(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:a2a.v1.Role) +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Security.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Security.java new file mode 100644 index 000000000..5eea07a7e --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Security.java @@ -0,0 +1,672 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.Security} + */ +@com.google.protobuf.Generated +public final class Security extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.Security) + SecurityOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "Security"); + } + // Use Security.newBuilder() to construct. + private Security(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Security() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Security_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 1: + return internalGetSchemes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Security_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Security.class, org.a2aproject.sdk.compat03.grpc.Security.Builder.class); + } + + public static final int SCHEMES_FIELD_NUMBER = 1; + private static final class SchemesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, org.a2aproject.sdk.compat03.grpc.StringList> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + A2A.internal_static_a2a_v1_Security_SchemesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.MESSAGE, + org.a2aproject.sdk.compat03.grpc.StringList.getDefaultInstance()); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, org.a2aproject.sdk.compat03.grpc.StringList> schemes_; + private com.google.protobuf.MapField + internalGetSchemes() { + if (schemes_ == null) { + return com.google.protobuf.MapField.emptyMapField( + SchemesDefaultEntryHolder.defaultEntry); + } + return schemes_; + } + public int getSchemesCount() { + return internalGetSchemes().getMap().size(); + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + @java.lang.Override + public boolean containsSchemes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetSchemes().getMap().containsKey(key); + } + /** + * Use {@link #getSchemesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getSchemes() { + return getSchemesMap(); + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + @java.lang.Override + public java.util.Map getSchemesMap() { + return internalGetSchemes().getMap(); + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + @java.lang.Override + public /* nullable */ +org.a2aproject.sdk.compat03.grpc.StringList getSchemesOrDefault( + java.lang.String key, + /* nullable */ +org.a2aproject.sdk.compat03.grpc.StringList defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetSchemes().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StringList getSchemesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetSchemes().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + com.google.protobuf.GeneratedMessage + .serializeStringMapTo( + output, + internalGetSchemes(), + SchemesDefaultEntryHolder.defaultEntry, + 1); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (java.util.Map.Entry entry + : internalGetSchemes().getMap().entrySet()) { + com.google.protobuf.MapEntry + schemes__ = SchemesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, schemes__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.Security)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.Security other = (org.a2aproject.sdk.compat03.grpc.Security) obj; + + if (!internalGetSchemes().equals( + other.internalGetSchemes())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (!internalGetSchemes().getMap().isEmpty()) { + hash = (37 * hash) + SCHEMES_FIELD_NUMBER; + hash = (53 * hash) + internalGetSchemes().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.Security parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.Security parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Security parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.Security prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.Security} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.Security) + org.a2aproject.sdk.compat03.grpc.SecurityOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Security_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 1: + return internalGetSchemes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 1: + return internalGetMutableSchemes(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Security_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Security.class, org.a2aproject.sdk.compat03.grpc.Security.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.Security.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + internalGetMutableSchemes().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_Security_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Security getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.Security.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Security build() { + org.a2aproject.sdk.compat03.grpc.Security result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Security buildPartial() { + org.a2aproject.sdk.compat03.grpc.Security result = new org.a2aproject.sdk.compat03.grpc.Security(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.Security result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.schemes_ = internalGetSchemes().build(SchemesDefaultEntryHolder.defaultEntry); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.Security) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.Security)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.Security other) { + if (other == org.a2aproject.sdk.compat03.grpc.Security.getDefaultInstance()) return this; + internalGetMutableSchemes().mergeFrom( + other.internalGetSchemes()); + bitField0_ |= 0x00000001; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + com.google.protobuf.MapEntry + schemes__ = input.readMessage( + SchemesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableSchemes().ensureBuilderMap().put( + schemes__.getKey(), schemes__.getValue()); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private static final class SchemesConverter implements com.google.protobuf.MapFieldBuilder.Converter { + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StringList build(org.a2aproject.sdk.compat03.grpc.StringListOrBuilder val) { + if (val instanceof org.a2aproject.sdk.compat03.grpc.StringList) { return (org.a2aproject.sdk.compat03.grpc.StringList) val; } + return ((org.a2aproject.sdk.compat03.grpc.StringList.Builder) val).build(); + } + + @java.lang.Override + public com.google.protobuf.MapEntry defaultEntry() { + return SchemesDefaultEntryHolder.defaultEntry; + } + }; + private static final SchemesConverter schemesConverter = new SchemesConverter(); + + private com.google.protobuf.MapFieldBuilder< + java.lang.String, org.a2aproject.sdk.compat03.grpc.StringListOrBuilder, org.a2aproject.sdk.compat03.grpc.StringList, org.a2aproject.sdk.compat03.grpc.StringList.Builder> schemes_; + private com.google.protobuf.MapFieldBuilder + internalGetSchemes() { + if (schemes_ == null) { + return new com.google.protobuf.MapFieldBuilder<>(schemesConverter); + } + return schemes_; + } + private com.google.protobuf.MapFieldBuilder + internalGetMutableSchemes() { + if (schemes_ == null) { + schemes_ = new com.google.protobuf.MapFieldBuilder<>(schemesConverter); + } + bitField0_ |= 0x00000001; + onChanged(); + return schemes_; + } + public int getSchemesCount() { + return internalGetSchemes().ensureBuilderMap().size(); + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + @java.lang.Override + public boolean containsSchemes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetSchemes().ensureBuilderMap().containsKey(key); + } + /** + * Use {@link #getSchemesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getSchemes() { + return getSchemesMap(); + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + @java.lang.Override + public java.util.Map getSchemesMap() { + return internalGetSchemes().getImmutableMap(); + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + @java.lang.Override + public /* nullable */ +org.a2aproject.sdk.compat03.grpc.StringList getSchemesOrDefault( + java.lang.String key, + /* nullable */ +org.a2aproject.sdk.compat03.grpc.StringList defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = internalGetMutableSchemes().ensureBuilderMap(); + return map.containsKey(key) ? schemesConverter.build(map.get(key)) : defaultValue; + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StringList getSchemesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = internalGetMutableSchemes().ensureBuilderMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return schemesConverter.build(map.get(key)); + } + public Builder clearSchemes() { + bitField0_ = (bitField0_ & ~0x00000001); + internalGetMutableSchemes().clear(); + return this; + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + public Builder removeSchemes( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableSchemes().ensureBuilderMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableSchemes() { + bitField0_ |= 0x00000001; + return internalGetMutableSchemes().ensureMessageMap(); + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + public Builder putSchemes( + java.lang.String key, + org.a2aproject.sdk.compat03.grpc.StringList value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableSchemes().ensureBuilderMap() + .put(key, value); + bitField0_ |= 0x00000001; + return this; + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + public Builder putAllSchemes( + java.util.Map values) { + for (java.util.Map.Entry e : values.entrySet()) { + if (e.getKey() == null || e.getValue() == null) { + throw new NullPointerException(); + } + } + internalGetMutableSchemes().ensureBuilderMap() + .putAll(values); + bitField0_ |= 0x00000001; + return this; + } + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + public org.a2aproject.sdk.compat03.grpc.StringList.Builder putSchemesBuilderIfAbsent( + java.lang.String key) { + java.util.Map builderMap = internalGetMutableSchemes().ensureBuilderMap(); + org.a2aproject.sdk.compat03.grpc.StringListOrBuilder entry = builderMap.get(key); + if (entry == null) { + entry = org.a2aproject.sdk.compat03.grpc.StringList.newBuilder(); + builderMap.put(key, entry); + } + if (entry instanceof org.a2aproject.sdk.compat03.grpc.StringList) { + entry = ((org.a2aproject.sdk.compat03.grpc.StringList) entry).toBuilder(); + builderMap.put(key, entry); + } + return (org.a2aproject.sdk.compat03.grpc.StringList.Builder) entry; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.Security) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.Security) + private static final org.a2aproject.sdk.compat03.grpc.Security DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.Security(); + } + + public static org.a2aproject.sdk.compat03.grpc.Security getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Security parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Security getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecurityOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecurityOrBuilder.java new file mode 100644 index 000000000..9c65475cb --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecurityOrBuilder.java @@ -0,0 +1,46 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface SecurityOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.Security) + com.google.protobuf.MessageOrBuilder { + + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + int getSchemesCount(); + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + boolean containsSchemes( + java.lang.String key); + /** + * Use {@link #getSchemesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getSchemes(); + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + java.util.Map + getSchemesMap(); + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + /* nullable */ +org.a2aproject.sdk.compat03.grpc.StringList getSchemesOrDefault( + java.lang.String key, + /* nullable */ +org.a2aproject.sdk.compat03.grpc.StringList defaultValue); + /** + * map<string, .a2a.v1.StringList> schemes = 1; + */ + org.a2aproject.sdk.compat03.grpc.StringList getSchemesOrThrow( + java.lang.String key); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecurityScheme.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecurityScheme.java new file mode 100644 index 000000000..b1a96b77f --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecurityScheme.java @@ -0,0 +1,1481 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.SecurityScheme} + */ +@com.google.protobuf.Generated +public final class SecurityScheme extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.SecurityScheme) + SecuritySchemeOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "SecurityScheme"); + } + // Use SecurityScheme.newBuilder() to construct. + private SecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private SecurityScheme() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_SecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_SecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.SecurityScheme.class, org.a2aproject.sdk.compat03.grpc.SecurityScheme.Builder.class); + } + + private int schemeCase_ = 0; + @SuppressWarnings("serial") + private java.lang.Object scheme_; + public enum SchemeCase + implements com.google.protobuf.Internal.EnumLite, + com.google.protobuf.AbstractMessage.InternalOneOfEnum { + API_KEY_SECURITY_SCHEME(1), + HTTP_AUTH_SECURITY_SCHEME(2), + OAUTH2_SECURITY_SCHEME(3), + OPEN_ID_CONNECT_SECURITY_SCHEME(4), + MTLS_SECURITY_SCHEME(5), + SCHEME_NOT_SET(0); + private final int value; + private SchemeCase(int value) { + this.value = value; + } + /** + * @param value The number of the enum to look for. + * @return The enum associated with the given number. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static SchemeCase valueOf(int value) { + return forNumber(value); + } + + public static SchemeCase forNumber(int value) { + switch (value) { + case 1: return API_KEY_SECURITY_SCHEME; + case 2: return HTTP_AUTH_SECURITY_SCHEME; + case 3: return OAUTH2_SECURITY_SCHEME; + case 4: return OPEN_ID_CONNECT_SECURITY_SCHEME; + case 5: return MTLS_SECURITY_SCHEME; + case 0: return SCHEME_NOT_SET; + default: return null; + } + } + public int getNumber() { + return this.value; + } + }; + + public SchemeCase + getSchemeCase() { + return SchemeCase.forNumber( + schemeCase_); + } + + public static final int API_KEY_SECURITY_SCHEME_FIELD_NUMBER = 1; + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * @return Whether the apiKeySecurityScheme field is set. + */ + @java.lang.Override + public boolean hasApiKeySecurityScheme() { + return schemeCase_ == 1; + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * @return The apiKeySecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme getApiKeySecurityScheme() { + if (schemeCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance(); + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() { + if (schemeCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance(); + } + + public static final int HTTP_AUTH_SECURITY_SCHEME_FIELD_NUMBER = 2; + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * @return Whether the httpAuthSecurityScheme field is set. + */ + @java.lang.Override + public boolean hasHttpAuthSecurityScheme() { + return schemeCase_ == 2; + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * @return The httpAuthSecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() { + if (schemeCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() { + if (schemeCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); + } + + public static final int OAUTH2_SECURITY_SCHEME_FIELD_NUMBER = 3; + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * @return Whether the oauth2SecurityScheme field is set. + */ + @java.lang.Override + public boolean hasOauth2SecurityScheme() { + return schemeCase_ == 3; + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * @return The oauth2SecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() { + if (schemeCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance(); + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() { + if (schemeCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance(); + } + + public static final int OPEN_ID_CONNECT_SECURITY_SCHEME_FIELD_NUMBER = 4; + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * @return Whether the openIdConnectSecurityScheme field is set. + */ + @java.lang.Override + public boolean hasOpenIdConnectSecurityScheme() { + return schemeCase_ == 4; + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * @return The openIdConnectSecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() { + if (schemeCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() { + if (schemeCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); + } + + public static final int MTLS_SECURITY_SCHEME_FIELD_NUMBER = 5; + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * @return Whether the mtlsSecurityScheme field is set. + */ + @java.lang.Override + public boolean hasMtlsSecurityScheme() { + return schemeCase_ == 5; + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * @return The mtlsSecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() { + if (schemeCase_ == 5) { + return (org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance(); + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() { + if (schemeCase_ == 5) { + return (org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance(); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (schemeCase_ == 1) { + output.writeMessage(1, (org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) scheme_); + } + if (schemeCase_ == 2) { + output.writeMessage(2, (org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) scheme_); + } + if (schemeCase_ == 3) { + output.writeMessage(3, (org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) scheme_); + } + if (schemeCase_ == 4) { + output.writeMessage(4, (org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) scheme_); + } + if (schemeCase_ == 5) { + output.writeMessage(5, (org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) scheme_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (schemeCase_ == 1) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, (org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) scheme_); + } + if (schemeCase_ == 2) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, (org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) scheme_); + } + if (schemeCase_ == 3) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, (org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) scheme_); + } + if (schemeCase_ == 4) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, (org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) scheme_); + } + if (schemeCase_ == 5) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, (org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) scheme_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.SecurityScheme)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.SecurityScheme other = (org.a2aproject.sdk.compat03.grpc.SecurityScheme) obj; + + if (!getSchemeCase().equals(other.getSchemeCase())) return false; + switch (schemeCase_) { + case 1: + if (!getApiKeySecurityScheme() + .equals(other.getApiKeySecurityScheme())) return false; + break; + case 2: + if (!getHttpAuthSecurityScheme() + .equals(other.getHttpAuthSecurityScheme())) return false; + break; + case 3: + if (!getOauth2SecurityScheme() + .equals(other.getOauth2SecurityScheme())) return false; + break; + case 4: + if (!getOpenIdConnectSecurityScheme() + .equals(other.getOpenIdConnectSecurityScheme())) return false; + break; + case 5: + if (!getMtlsSecurityScheme() + .equals(other.getMtlsSecurityScheme())) return false; + break; + case 0: + default: + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + switch (schemeCase_) { + case 1: + hash = (37 * hash) + API_KEY_SECURITY_SCHEME_FIELD_NUMBER; + hash = (53 * hash) + getApiKeySecurityScheme().hashCode(); + break; + case 2: + hash = (37 * hash) + HTTP_AUTH_SECURITY_SCHEME_FIELD_NUMBER; + hash = (53 * hash) + getHttpAuthSecurityScheme().hashCode(); + break; + case 3: + hash = (37 * hash) + OAUTH2_SECURITY_SCHEME_FIELD_NUMBER; + hash = (53 * hash) + getOauth2SecurityScheme().hashCode(); + break; + case 4: + hash = (37 * hash) + OPEN_ID_CONNECT_SECURITY_SCHEME_FIELD_NUMBER; + hash = (53 * hash) + getOpenIdConnectSecurityScheme().hashCode(); + break; + case 5: + hash = (37 * hash) + MTLS_SECURITY_SCHEME_FIELD_NUMBER; + hash = (53 * hash) + getMtlsSecurityScheme().hashCode(); + break; + case 0: + default: + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.SecurityScheme prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.SecurityScheme} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.SecurityScheme) + org.a2aproject.sdk.compat03.grpc.SecuritySchemeOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_SecurityScheme_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_SecurityScheme_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.SecurityScheme.class, org.a2aproject.sdk.compat03.grpc.SecurityScheme.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.SecurityScheme.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + if (apiKeySecuritySchemeBuilder_ != null) { + apiKeySecuritySchemeBuilder_.clear(); + } + if (httpAuthSecuritySchemeBuilder_ != null) { + httpAuthSecuritySchemeBuilder_.clear(); + } + if (oauth2SecuritySchemeBuilder_ != null) { + oauth2SecuritySchemeBuilder_.clear(); + } + if (openIdConnectSecuritySchemeBuilder_ != null) { + openIdConnectSecuritySchemeBuilder_.clear(); + } + if (mtlsSecuritySchemeBuilder_ != null) { + mtlsSecuritySchemeBuilder_.clear(); + } + schemeCase_ = 0; + scheme_ = null; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_SecurityScheme_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityScheme getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.SecurityScheme.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityScheme build() { + org.a2aproject.sdk.compat03.grpc.SecurityScheme result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityScheme buildPartial() { + org.a2aproject.sdk.compat03.grpc.SecurityScheme result = new org.a2aproject.sdk.compat03.grpc.SecurityScheme(this); + if (bitField0_ != 0) { buildPartial0(result); } + buildPartialOneofs(result); + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.SecurityScheme result) { + int from_bitField0_ = bitField0_; + } + + private void buildPartialOneofs(org.a2aproject.sdk.compat03.grpc.SecurityScheme result) { + result.schemeCase_ = schemeCase_; + result.scheme_ = this.scheme_; + if (schemeCase_ == 1 && + apiKeySecuritySchemeBuilder_ != null) { + result.scheme_ = apiKeySecuritySchemeBuilder_.build(); + } + if (schemeCase_ == 2 && + httpAuthSecuritySchemeBuilder_ != null) { + result.scheme_ = httpAuthSecuritySchemeBuilder_.build(); + } + if (schemeCase_ == 3 && + oauth2SecuritySchemeBuilder_ != null) { + result.scheme_ = oauth2SecuritySchemeBuilder_.build(); + } + if (schemeCase_ == 4 && + openIdConnectSecuritySchemeBuilder_ != null) { + result.scheme_ = openIdConnectSecuritySchemeBuilder_.build(); + } + if (schemeCase_ == 5 && + mtlsSecuritySchemeBuilder_ != null) { + result.scheme_ = mtlsSecuritySchemeBuilder_.build(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.SecurityScheme) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.SecurityScheme)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.SecurityScheme other) { + if (other == org.a2aproject.sdk.compat03.grpc.SecurityScheme.getDefaultInstance()) return this; + switch (other.getSchemeCase()) { + case API_KEY_SECURITY_SCHEME: { + mergeApiKeySecurityScheme(other.getApiKeySecurityScheme()); + break; + } + case HTTP_AUTH_SECURITY_SCHEME: { + mergeHttpAuthSecurityScheme(other.getHttpAuthSecurityScheme()); + break; + } + case OAUTH2_SECURITY_SCHEME: { + mergeOauth2SecurityScheme(other.getOauth2SecurityScheme()); + break; + } + case OPEN_ID_CONNECT_SECURITY_SCHEME: { + mergeOpenIdConnectSecurityScheme(other.getOpenIdConnectSecurityScheme()); + break; + } + case MTLS_SECURITY_SCHEME: { + mergeMtlsSecurityScheme(other.getMtlsSecurityScheme()); + break; + } + case SCHEME_NOT_SET: { + break; + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + input.readMessage( + internalGetApiKeySecuritySchemeFieldBuilder().getBuilder(), + extensionRegistry); + schemeCase_ = 1; + break; + } // case 10 + case 18: { + input.readMessage( + internalGetHttpAuthSecuritySchemeFieldBuilder().getBuilder(), + extensionRegistry); + schemeCase_ = 2; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetOauth2SecuritySchemeFieldBuilder().getBuilder(), + extensionRegistry); + schemeCase_ = 3; + break; + } // case 26 + case 34: { + input.readMessage( + internalGetOpenIdConnectSecuritySchemeFieldBuilder().getBuilder(), + extensionRegistry); + schemeCase_ = 4; + break; + } // case 34 + case 42: { + input.readMessage( + internalGetMtlsSecuritySchemeFieldBuilder().getBuilder(), + extensionRegistry); + schemeCase_ = 5; + break; + } // case 42 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int schemeCase_ = 0; + private java.lang.Object scheme_; + public SchemeCase + getSchemeCase() { + return SchemeCase.forNumber( + schemeCase_); + } + + public Builder clearScheme() { + schemeCase_ = 0; + scheme_ = null; + onChanged(); + return this; + } + + private int bitField0_; + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme, org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.APIKeySecuritySchemeOrBuilder> apiKeySecuritySchemeBuilder_; + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * @return Whether the apiKeySecurityScheme field is set. + */ + @java.lang.Override + public boolean hasApiKeySecurityScheme() { + return schemeCase_ == 1; + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * @return The apiKeySecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme getApiKeySecurityScheme() { + if (apiKeySecuritySchemeBuilder_ == null) { + if (schemeCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance(); + } else { + if (schemeCase_ == 1) { + return apiKeySecuritySchemeBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + public Builder setApiKeySecurityScheme(org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme value) { + if (apiKeySecuritySchemeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + scheme_ = value; + onChanged(); + } else { + apiKeySecuritySchemeBuilder_.setMessage(value); + } + schemeCase_ = 1; + return this; + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + public Builder setApiKeySecurityScheme( + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder builderForValue) { + if (apiKeySecuritySchemeBuilder_ == null) { + scheme_ = builderForValue.build(); + onChanged(); + } else { + apiKeySecuritySchemeBuilder_.setMessage(builderForValue.build()); + } + schemeCase_ = 1; + return this; + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + public Builder mergeApiKeySecurityScheme(org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme value) { + if (apiKeySecuritySchemeBuilder_ == null) { + if (schemeCase_ == 1 && + scheme_ != org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance()) { + scheme_ = org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.newBuilder((org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) scheme_) + .mergeFrom(value).buildPartial(); + } else { + scheme_ = value; + } + onChanged(); + } else { + if (schemeCase_ == 1) { + apiKeySecuritySchemeBuilder_.mergeFrom(value); + } else { + apiKeySecuritySchemeBuilder_.setMessage(value); + } + } + schemeCase_ = 1; + return this; + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + public Builder clearApiKeySecurityScheme() { + if (apiKeySecuritySchemeBuilder_ == null) { + if (schemeCase_ == 1) { + schemeCase_ = 0; + scheme_ = null; + onChanged(); + } + } else { + if (schemeCase_ == 1) { + schemeCase_ = 0; + scheme_ = null; + } + apiKeySecuritySchemeBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + public org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder getApiKeySecuritySchemeBuilder() { + return internalGetApiKeySecuritySchemeFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() { + if ((schemeCase_ == 1) && (apiKeySecuritySchemeBuilder_ != null)) { + return apiKeySecuritySchemeBuilder_.getMessageOrBuilder(); + } else { + if (schemeCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme, org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.APIKeySecuritySchemeOrBuilder> + internalGetApiKeySecuritySchemeFieldBuilder() { + if (apiKeySecuritySchemeBuilder_ == null) { + if (!(schemeCase_ == 1)) { + scheme_ = org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.getDefaultInstance(); + } + apiKeySecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme, org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.APIKeySecuritySchemeOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme) scheme_, + getParentForChildren(), + isClean()); + scheme_ = null; + } + schemeCase_ = 1; + onChanged(); + return apiKeySecuritySchemeBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme, org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.HTTPAuthSecuritySchemeOrBuilder> httpAuthSecuritySchemeBuilder_; + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * @return Whether the httpAuthSecurityScheme field is set. + */ + @java.lang.Override + public boolean hasHttpAuthSecurityScheme() { + return schemeCase_ == 2; + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * @return The httpAuthSecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() { + if (httpAuthSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); + } else { + if (schemeCase_ == 2) { + return httpAuthSecuritySchemeBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + public Builder setHttpAuthSecurityScheme(org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme value) { + if (httpAuthSecuritySchemeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + scheme_ = value; + onChanged(); + } else { + httpAuthSecuritySchemeBuilder_.setMessage(value); + } + schemeCase_ = 2; + return this; + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + public Builder setHttpAuthSecurityScheme( + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder builderForValue) { + if (httpAuthSecuritySchemeBuilder_ == null) { + scheme_ = builderForValue.build(); + onChanged(); + } else { + httpAuthSecuritySchemeBuilder_.setMessage(builderForValue.build()); + } + schemeCase_ = 2; + return this; + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + public Builder mergeHttpAuthSecurityScheme(org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme value) { + if (httpAuthSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 2 && + scheme_ != org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance()) { + scheme_ = org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.newBuilder((org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) scheme_) + .mergeFrom(value).buildPartial(); + } else { + scheme_ = value; + } + onChanged(); + } else { + if (schemeCase_ == 2) { + httpAuthSecuritySchemeBuilder_.mergeFrom(value); + } else { + httpAuthSecuritySchemeBuilder_.setMessage(value); + } + } + schemeCase_ = 2; + return this; + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + public Builder clearHttpAuthSecurityScheme() { + if (httpAuthSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 2) { + schemeCase_ = 0; + scheme_ = null; + onChanged(); + } + } else { + if (schemeCase_ == 2) { + schemeCase_ = 0; + scheme_ = null; + } + httpAuthSecuritySchemeBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder getHttpAuthSecuritySchemeBuilder() { + return internalGetHttpAuthSecuritySchemeFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() { + if ((schemeCase_ == 2) && (httpAuthSecuritySchemeBuilder_ != null)) { + return httpAuthSecuritySchemeBuilder_.getMessageOrBuilder(); + } else { + if (schemeCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme, org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.HTTPAuthSecuritySchemeOrBuilder> + internalGetHttpAuthSecuritySchemeFieldBuilder() { + if (httpAuthSecuritySchemeBuilder_ == null) { + if (!(schemeCase_ == 2)) { + scheme_ = org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); + } + httpAuthSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme, org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.HTTPAuthSecuritySchemeOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme) scheme_, + getParentForChildren(), + isClean()); + scheme_ = null; + } + schemeCase_ = 2; + onChanged(); + return httpAuthSecuritySchemeBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme, org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.OAuth2SecuritySchemeOrBuilder> oauth2SecuritySchemeBuilder_; + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * @return Whether the oauth2SecurityScheme field is set. + */ + @java.lang.Override + public boolean hasOauth2SecurityScheme() { + return schemeCase_ == 3; + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * @return The oauth2SecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() { + if (oauth2SecuritySchemeBuilder_ == null) { + if (schemeCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance(); + } else { + if (schemeCase_ == 3) { + return oauth2SecuritySchemeBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + public Builder setOauth2SecurityScheme(org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme value) { + if (oauth2SecuritySchemeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + scheme_ = value; + onChanged(); + } else { + oauth2SecuritySchemeBuilder_.setMessage(value); + } + schemeCase_ = 3; + return this; + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + public Builder setOauth2SecurityScheme( + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder builderForValue) { + if (oauth2SecuritySchemeBuilder_ == null) { + scheme_ = builderForValue.build(); + onChanged(); + } else { + oauth2SecuritySchemeBuilder_.setMessage(builderForValue.build()); + } + schemeCase_ = 3; + return this; + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + public Builder mergeOauth2SecurityScheme(org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme value) { + if (oauth2SecuritySchemeBuilder_ == null) { + if (schemeCase_ == 3 && + scheme_ != org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance()) { + scheme_ = org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.newBuilder((org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) scheme_) + .mergeFrom(value).buildPartial(); + } else { + scheme_ = value; + } + onChanged(); + } else { + if (schemeCase_ == 3) { + oauth2SecuritySchemeBuilder_.mergeFrom(value); + } else { + oauth2SecuritySchemeBuilder_.setMessage(value); + } + } + schemeCase_ = 3; + return this; + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + public Builder clearOauth2SecurityScheme() { + if (oauth2SecuritySchemeBuilder_ == null) { + if (schemeCase_ == 3) { + schemeCase_ = 0; + scheme_ = null; + onChanged(); + } + } else { + if (schemeCase_ == 3) { + schemeCase_ = 0; + scheme_ = null; + } + oauth2SecuritySchemeBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + public org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder getOauth2SecuritySchemeBuilder() { + return internalGetOauth2SecuritySchemeFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() { + if ((schemeCase_ == 3) && (oauth2SecuritySchemeBuilder_ != null)) { + return oauth2SecuritySchemeBuilder_.getMessageOrBuilder(); + } else { + if (schemeCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme, org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.OAuth2SecuritySchemeOrBuilder> + internalGetOauth2SecuritySchemeFieldBuilder() { + if (oauth2SecuritySchemeBuilder_ == null) { + if (!(schemeCase_ == 3)) { + scheme_ = org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.getDefaultInstance(); + } + oauth2SecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme, org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.OAuth2SecuritySchemeOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme) scheme_, + getParentForChildren(), + isClean()); + scheme_ = null; + } + schemeCase_ = 3; + onChanged(); + return oauth2SecuritySchemeBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme, org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecuritySchemeOrBuilder> openIdConnectSecuritySchemeBuilder_; + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * @return Whether the openIdConnectSecurityScheme field is set. + */ + @java.lang.Override + public boolean hasOpenIdConnectSecurityScheme() { + return schemeCase_ == 4; + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * @return The openIdConnectSecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() { + if (openIdConnectSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); + } else { + if (schemeCase_ == 4) { + return openIdConnectSecuritySchemeBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + public Builder setOpenIdConnectSecurityScheme(org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme value) { + if (openIdConnectSecuritySchemeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + scheme_ = value; + onChanged(); + } else { + openIdConnectSecuritySchemeBuilder_.setMessage(value); + } + schemeCase_ = 4; + return this; + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + public Builder setOpenIdConnectSecurityScheme( + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder builderForValue) { + if (openIdConnectSecuritySchemeBuilder_ == null) { + scheme_ = builderForValue.build(); + onChanged(); + } else { + openIdConnectSecuritySchemeBuilder_.setMessage(builderForValue.build()); + } + schemeCase_ = 4; + return this; + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + public Builder mergeOpenIdConnectSecurityScheme(org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme value) { + if (openIdConnectSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 4 && + scheme_ != org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance()) { + scheme_ = org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.newBuilder((org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) scheme_) + .mergeFrom(value).buildPartial(); + } else { + scheme_ = value; + } + onChanged(); + } else { + if (schemeCase_ == 4) { + openIdConnectSecuritySchemeBuilder_.mergeFrom(value); + } else { + openIdConnectSecuritySchemeBuilder_.setMessage(value); + } + } + schemeCase_ = 4; + return this; + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + public Builder clearOpenIdConnectSecurityScheme() { + if (openIdConnectSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 4) { + schemeCase_ = 0; + scheme_ = null; + onChanged(); + } + } else { + if (schemeCase_ == 4) { + schemeCase_ = 0; + scheme_ = null; + } + openIdConnectSecuritySchemeBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder getOpenIdConnectSecuritySchemeBuilder() { + return internalGetOpenIdConnectSecuritySchemeFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() { + if ((schemeCase_ == 4) && (openIdConnectSecuritySchemeBuilder_ != null)) { + return openIdConnectSecuritySchemeBuilder_.getMessageOrBuilder(); + } else { + if (schemeCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme, org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecuritySchemeOrBuilder> + internalGetOpenIdConnectSecuritySchemeFieldBuilder() { + if (openIdConnectSecuritySchemeBuilder_ == null) { + if (!(schemeCase_ == 4)) { + scheme_ = org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); + } + openIdConnectSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme, org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecuritySchemeOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme) scheme_, + getParentForChildren(), + isClean()); + scheme_ = null; + } + schemeCase_ = 4; + onChanged(); + return openIdConnectSecuritySchemeBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme, org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.MutualTlsSecuritySchemeOrBuilder> mtlsSecuritySchemeBuilder_; + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * @return Whether the mtlsSecurityScheme field is set. + */ + @java.lang.Override + public boolean hasMtlsSecurityScheme() { + return schemeCase_ == 5; + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * @return The mtlsSecurityScheme. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() { + if (mtlsSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 5) { + return (org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance(); + } else { + if (schemeCase_ == 5) { + return mtlsSecuritySchemeBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + public Builder setMtlsSecurityScheme(org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme value) { + if (mtlsSecuritySchemeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + scheme_ = value; + onChanged(); + } else { + mtlsSecuritySchemeBuilder_.setMessage(value); + } + schemeCase_ = 5; + return this; + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + public Builder setMtlsSecurityScheme( + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder builderForValue) { + if (mtlsSecuritySchemeBuilder_ == null) { + scheme_ = builderForValue.build(); + onChanged(); + } else { + mtlsSecuritySchemeBuilder_.setMessage(builderForValue.build()); + } + schemeCase_ = 5; + return this; + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + public Builder mergeMtlsSecurityScheme(org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme value) { + if (mtlsSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 5 && + scheme_ != org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance()) { + scheme_ = org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.newBuilder((org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) scheme_) + .mergeFrom(value).buildPartial(); + } else { + scheme_ = value; + } + onChanged(); + } else { + if (schemeCase_ == 5) { + mtlsSecuritySchemeBuilder_.mergeFrom(value); + } else { + mtlsSecuritySchemeBuilder_.setMessage(value); + } + } + schemeCase_ = 5; + return this; + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + public Builder clearMtlsSecurityScheme() { + if (mtlsSecuritySchemeBuilder_ == null) { + if (schemeCase_ == 5) { + schemeCase_ = 0; + scheme_ = null; + onChanged(); + } + } else { + if (schemeCase_ == 5) { + schemeCase_ = 0; + scheme_ = null; + } + mtlsSecuritySchemeBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder getMtlsSecuritySchemeBuilder() { + return internalGetMtlsSecuritySchemeFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() { + if ((schemeCase_ == 5) && (mtlsSecuritySchemeBuilder_ != null)) { + return mtlsSecuritySchemeBuilder_.getMessageOrBuilder(); + } else { + if (schemeCase_ == 5) { + return (org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) scheme_; + } + return org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance(); + } + } + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme, org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.MutualTlsSecuritySchemeOrBuilder> + internalGetMtlsSecuritySchemeFieldBuilder() { + if (mtlsSecuritySchemeBuilder_ == null) { + if (!(schemeCase_ == 5)) { + scheme_ = org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.getDefaultInstance(); + } + mtlsSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme, org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder, org.a2aproject.sdk.compat03.grpc.MutualTlsSecuritySchemeOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme) scheme_, + getParentForChildren(), + isClean()); + scheme_ = null; + } + schemeCase_ = 5; + onChanged(); + return mtlsSecuritySchemeBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.SecurityScheme) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.SecurityScheme) + private static final org.a2aproject.sdk.compat03.grpc.SecurityScheme DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.SecurityScheme(); + } + + public static org.a2aproject.sdk.compat03.grpc.SecurityScheme getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public SecurityScheme parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SecurityScheme getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecuritySchemeOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecuritySchemeOrBuilder.java new file mode 100644 index 000000000..d7b60e978 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SecuritySchemeOrBuilder.java @@ -0,0 +1,89 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface SecuritySchemeOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.SecurityScheme) + com.google.protobuf.MessageOrBuilder { + + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * @return Whether the apiKeySecurityScheme field is set. + */ + boolean hasApiKeySecurityScheme(); + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + * @return The apiKeySecurityScheme. + */ + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme getApiKeySecurityScheme(); + /** + * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; + */ + org.a2aproject.sdk.compat03.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder(); + + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * @return Whether the httpAuthSecurityScheme field is set. + */ + boolean hasHttpAuthSecurityScheme(); + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + * @return The httpAuthSecurityScheme. + */ + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme(); + /** + * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; + */ + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder(); + + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * @return Whether the oauth2SecurityScheme field is set. + */ + boolean hasOauth2SecurityScheme(); + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + * @return The oauth2SecurityScheme. + */ + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme getOauth2SecurityScheme(); + /** + * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; + */ + org.a2aproject.sdk.compat03.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder(); + + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * @return Whether the openIdConnectSecurityScheme field is set. + */ + boolean hasOpenIdConnectSecurityScheme(); + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + * @return The openIdConnectSecurityScheme. + */ + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme(); + /** + * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + */ + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder(); + + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * @return Whether the mtlsSecurityScheme field is set. + */ + boolean hasMtlsSecurityScheme(); + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + * @return The mtlsSecurityScheme. + */ + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme(); + /** + * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; + */ + org.a2aproject.sdk.compat03.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder(); + + org.a2aproject.sdk.compat03.grpc.SecurityScheme.SchemeCase getSchemeCase(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageConfiguration.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageConfiguration.java new file mode 100644 index 000000000..38b6c6aad --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageConfiguration.java @@ -0,0 +1,1037 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Configuration of a send message request.
            + * 
            + * + * Protobuf type {@code a2a.v1.SendMessageConfiguration} + */ +@com.google.protobuf.Generated +public final class SendMessageConfiguration extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageConfiguration) + SendMessageConfigurationOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "SendMessageConfiguration"); + } + // Use SendMessageConfiguration.newBuilder() to construct. + private SendMessageConfiguration(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private SendMessageConfiguration() { + acceptedOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.class, org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.Builder.class); + } + + private int bitField0_; + public static final int ACCEPTED_OUTPUT_MODES_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList acceptedOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + *
            +   * The output modes that the agent is expected to respond with.
            +   * 
            + * + * repeated string accepted_output_modes = 1; + * @return A list containing the acceptedOutputModes. + */ + public com.google.protobuf.ProtocolStringList + getAcceptedOutputModesList() { + return acceptedOutputModes_; + } + /** + *
            +   * The output modes that the agent is expected to respond with.
            +   * 
            + * + * repeated string accepted_output_modes = 1; + * @return The count of acceptedOutputModes. + */ + public int getAcceptedOutputModesCount() { + return acceptedOutputModes_.size(); + } + /** + *
            +   * The output modes that the agent is expected to respond with.
            +   * 
            + * + * repeated string accepted_output_modes = 1; + * @param index The index of the element to return. + * @return The acceptedOutputModes at the given index. + */ + public java.lang.String getAcceptedOutputModes(int index) { + return acceptedOutputModes_.get(index); + } + /** + *
            +   * The output modes that the agent is expected to respond with.
            +   * 
            + * + * repeated string accepted_output_modes = 1; + * @param index The index of the value to return. + * @return The bytes of the acceptedOutputModes at the given index. + */ + public com.google.protobuf.ByteString + getAcceptedOutputModesBytes(int index) { + return acceptedOutputModes_.getByteString(index); + } + + public static final int PUSH_NOTIFICATION_FIELD_NUMBER = 2; + private org.a2aproject.sdk.compat03.grpc.PushNotificationConfig pushNotification_; + /** + *
            +   * A configuration of a webhook that can be used to receive updates
            +   * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + * @return Whether the pushNotification field is set. + */ + @java.lang.Override + public boolean hasPushNotification() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * A configuration of a webhook that can be used to receive updates
            +   * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + * @return The pushNotification. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getPushNotification() { + return pushNotification_ == null ? org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance() : pushNotification_; + } + /** + *
            +   * A configuration of a webhook that can be used to receive updates
            +   * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder getPushNotificationOrBuilder() { + return pushNotification_ == null ? org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance() : pushNotification_; + } + + public static final int HISTORY_LENGTH_FIELD_NUMBER = 3; + private int historyLength_ = 0; + /** + *
            +   * The maximum number of messages to include in the history. if 0, the
            +   * history will be unlimited.
            +   * 
            + * + * int32 history_length = 3; + * @return The historyLength. + */ + @java.lang.Override + public int getHistoryLength() { + return historyLength_; + } + + public static final int BLOCKING_FIELD_NUMBER = 4; + private boolean blocking_ = false; + /** + *
            +   * If true, the message will be blocking until the task is completed. If
            +   * false, the message will be non-blocking and the task will be returned
            +   * immediately. It is the caller's responsibility to check for any task
            +   * updates.
            +   * 
            + * + * bool blocking = 4; + * @return The blocking. + */ + @java.lang.Override + public boolean getBlocking() { + return blocking_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < acceptedOutputModes_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, acceptedOutputModes_.getRaw(i)); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(2, getPushNotification()); + } + if (historyLength_ != 0) { + output.writeInt32(3, historyLength_); + } + if (blocking_ != false) { + output.writeBool(4, blocking_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + { + int dataSize = 0; + for (int i = 0; i < acceptedOutputModes_.size(); i++) { + dataSize += computeStringSizeNoTag(acceptedOutputModes_.getRaw(i)); + } + size += dataSize; + size += 1 * getAcceptedOutputModesList().size(); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getPushNotification()); + } + if (historyLength_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, historyLength_); + } + if (blocking_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(4, blocking_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration other = (org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration) obj; + + if (!getAcceptedOutputModesList() + .equals(other.getAcceptedOutputModesList())) return false; + if (hasPushNotification() != other.hasPushNotification()) return false; + if (hasPushNotification()) { + if (!getPushNotification() + .equals(other.getPushNotification())) return false; + } + if (getHistoryLength() + != other.getHistoryLength()) return false; + if (getBlocking() + != other.getBlocking()) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getAcceptedOutputModesCount() > 0) { + hash = (37 * hash) + ACCEPTED_OUTPUT_MODES_FIELD_NUMBER; + hash = (53 * hash) + getAcceptedOutputModesList().hashCode(); + } + if (hasPushNotification()) { + hash = (37 * hash) + PUSH_NOTIFICATION_FIELD_NUMBER; + hash = (53 * hash) + getPushNotification().hashCode(); + } + hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER; + hash = (53 * hash) + getHistoryLength(); + hash = (37 * hash) + BLOCKING_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getBlocking()); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Configuration of a send message request.
            +   * 
            + * + * Protobuf type {@code a2a.v1.SendMessageConfiguration} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageConfiguration) + org.a2aproject.sdk.compat03.grpc.SendMessageConfigurationOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.class, org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetPushNotificationFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + acceptedOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + pushNotification_ = null; + if (pushNotificationBuilder_ != null) { + pushNotificationBuilder_.dispose(); + pushNotificationBuilder_ = null; + } + historyLength_ = 0; + blocking_ = false; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration build() { + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration buildPartial() { + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration result = new org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + acceptedOutputModes_.makeImmutable(); + result.acceptedOutputModes_ = acceptedOutputModes_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000002) != 0)) { + result.pushNotification_ = pushNotificationBuilder_ == null + ? pushNotification_ + : pushNotificationBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.historyLength_ = historyLength_; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.blocking_ = blocking_; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration other) { + if (other == org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.getDefaultInstance()) return this; + if (!other.acceptedOutputModes_.isEmpty()) { + if (acceptedOutputModes_.isEmpty()) { + acceptedOutputModes_ = other.acceptedOutputModes_; + bitField0_ |= 0x00000001; + } else { + ensureAcceptedOutputModesIsMutable(); + acceptedOutputModes_.addAll(other.acceptedOutputModes_); + } + onChanged(); + } + if (other.hasPushNotification()) { + mergePushNotification(other.getPushNotification()); + } + if (other.getHistoryLength() != 0) { + setHistoryLength(other.getHistoryLength()); + } + if (other.getBlocking() != false) { + setBlocking(other.getBlocking()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + ensureAcceptedOutputModesIsMutable(); + acceptedOutputModes_.add(s); + break; + } // case 10 + case 18: { + input.readMessage( + internalGetPushNotificationFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 24: { + historyLength_ = input.readInt32(); + bitField0_ |= 0x00000004; + break; + } // case 24 + case 32: { + blocking_ = input.readBool(); + bitField0_ |= 0x00000008; + break; + } // case 32 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private com.google.protobuf.LazyStringArrayList acceptedOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureAcceptedOutputModesIsMutable() { + if (!acceptedOutputModes_.isModifiable()) { + acceptedOutputModes_ = new com.google.protobuf.LazyStringArrayList(acceptedOutputModes_); + } + bitField0_ |= 0x00000001; + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @return A list containing the acceptedOutputModes. + */ + public com.google.protobuf.ProtocolStringList + getAcceptedOutputModesList() { + acceptedOutputModes_.makeImmutable(); + return acceptedOutputModes_; + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @return The count of acceptedOutputModes. + */ + public int getAcceptedOutputModesCount() { + return acceptedOutputModes_.size(); + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @param index The index of the element to return. + * @return The acceptedOutputModes at the given index. + */ + public java.lang.String getAcceptedOutputModes(int index) { + return acceptedOutputModes_.get(index); + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @param index The index of the value to return. + * @return The bytes of the acceptedOutputModes at the given index. + */ + public com.google.protobuf.ByteString + getAcceptedOutputModesBytes(int index) { + return acceptedOutputModes_.getByteString(index); + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @param index The index to set the value at. + * @param value The acceptedOutputModes to set. + * @return This builder for chaining. + */ + public Builder setAcceptedOutputModes( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureAcceptedOutputModesIsMutable(); + acceptedOutputModes_.set(index, value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @param value The acceptedOutputModes to add. + * @return This builder for chaining. + */ + public Builder addAcceptedOutputModes( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureAcceptedOutputModesIsMutable(); + acceptedOutputModes_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @param values The acceptedOutputModes to add. + * @return This builder for chaining. + */ + public Builder addAllAcceptedOutputModes( + java.lang.Iterable values) { + ensureAcceptedOutputModesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, acceptedOutputModes_); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @return This builder for chaining. + */ + public Builder clearAcceptedOutputModes() { + acceptedOutputModes_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001);; + onChanged(); + return this; + } + /** + *
            +     * The output modes that the agent is expected to respond with.
            +     * 
            + * + * repeated string accepted_output_modes = 1; + * @param value The bytes of the acceptedOutputModes to add. + * @return This builder for chaining. + */ + public Builder addAcceptedOutputModesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureAcceptedOutputModesIsMutable(); + acceptedOutputModes_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.PushNotificationConfig pushNotification_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig, org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder> pushNotificationBuilder_; + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + * @return Whether the pushNotification field is set. + */ + public boolean hasPushNotification() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + * @return The pushNotification. + */ + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getPushNotification() { + if (pushNotificationBuilder_ == null) { + return pushNotification_ == null ? org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance() : pushNotification_; + } else { + return pushNotificationBuilder_.getMessage(); + } + } + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + public Builder setPushNotification(org.a2aproject.sdk.compat03.grpc.PushNotificationConfig value) { + if (pushNotificationBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + pushNotification_ = value; + } else { + pushNotificationBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + public Builder setPushNotification( + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder builderForValue) { + if (pushNotificationBuilder_ == null) { + pushNotification_ = builderForValue.build(); + } else { + pushNotificationBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + public Builder mergePushNotification(org.a2aproject.sdk.compat03.grpc.PushNotificationConfig value) { + if (pushNotificationBuilder_ == null) { + if (((bitField0_ & 0x00000002) != 0) && + pushNotification_ != null && + pushNotification_ != org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance()) { + getPushNotificationBuilder().mergeFrom(value); + } else { + pushNotification_ = value; + } + } else { + pushNotificationBuilder_.mergeFrom(value); + } + if (pushNotification_ != null) { + bitField0_ |= 0x00000002; + onChanged(); + } + return this; + } + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + public Builder clearPushNotification() { + bitField0_ = (bitField0_ & ~0x00000002); + pushNotification_ = null; + if (pushNotificationBuilder_ != null) { + pushNotificationBuilder_.dispose(); + pushNotificationBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder getPushNotificationBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return internalGetPushNotificationFieldBuilder().getBuilder(); + } + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder getPushNotificationOrBuilder() { + if (pushNotificationBuilder_ != null) { + return pushNotificationBuilder_.getMessageOrBuilder(); + } else { + return pushNotification_ == null ? + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance() : pushNotification_; + } + } + /** + *
            +     * A configuration of a webhook that can be used to receive updates
            +     * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig, org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder> + internalGetPushNotificationFieldBuilder() { + if (pushNotificationBuilder_ == null) { + pushNotificationBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig, org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder>( + getPushNotification(), + getParentForChildren(), + isClean()); + pushNotification_ = null; + } + return pushNotificationBuilder_; + } + + private int historyLength_ ; + /** + *
            +     * The maximum number of messages to include in the history. if 0, the
            +     * history will be unlimited.
            +     * 
            + * + * int32 history_length = 3; + * @return The historyLength. + */ + @java.lang.Override + public int getHistoryLength() { + return historyLength_; + } + /** + *
            +     * The maximum number of messages to include in the history. if 0, the
            +     * history will be unlimited.
            +     * 
            + * + * int32 history_length = 3; + * @param value The historyLength to set. + * @return This builder for chaining. + */ + public Builder setHistoryLength(int value) { + + historyLength_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The maximum number of messages to include in the history. if 0, the
            +     * history will be unlimited.
            +     * 
            + * + * int32 history_length = 3; + * @return This builder for chaining. + */ + public Builder clearHistoryLength() { + bitField0_ = (bitField0_ & ~0x00000004); + historyLength_ = 0; + onChanged(); + return this; + } + + private boolean blocking_ ; + /** + *
            +     * If true, the message will be blocking until the task is completed. If
            +     * false, the message will be non-blocking and the task will be returned
            +     * immediately. It is the caller's responsibility to check for any task
            +     * updates.
            +     * 
            + * + * bool blocking = 4; + * @return The blocking. + */ + @java.lang.Override + public boolean getBlocking() { + return blocking_; + } + /** + *
            +     * If true, the message will be blocking until the task is completed. If
            +     * false, the message will be non-blocking and the task will be returned
            +     * immediately. It is the caller's responsibility to check for any task
            +     * updates.
            +     * 
            + * + * bool blocking = 4; + * @param value The blocking to set. + * @return This builder for chaining. + */ + public Builder setBlocking(boolean value) { + + blocking_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * If true, the message will be blocking until the task is completed. If
            +     * false, the message will be non-blocking and the task will be returned
            +     * immediately. It is the caller's responsibility to check for any task
            +     * updates.
            +     * 
            + * + * bool blocking = 4; + * @return This builder for chaining. + */ + public Builder clearBlocking() { + bitField0_ = (bitField0_ & ~0x00000008); + blocking_ = false; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageConfiguration) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageConfiguration) + private static final org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration(); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public SendMessageConfiguration parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageConfigurationOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageConfigurationOrBuilder.java new file mode 100644 index 000000000..cdc78e9bf --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageConfigurationOrBuilder.java @@ -0,0 +1,104 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface SendMessageConfigurationOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageConfiguration) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The output modes that the agent is expected to respond with.
            +   * 
            + * + * repeated string accepted_output_modes = 1; + * @return A list containing the acceptedOutputModes. + */ + java.util.List + getAcceptedOutputModesList(); + /** + *
            +   * The output modes that the agent is expected to respond with.
            +   * 
            + * + * repeated string accepted_output_modes = 1; + * @return The count of acceptedOutputModes. + */ + int getAcceptedOutputModesCount(); + /** + *
            +   * The output modes that the agent is expected to respond with.
            +   * 
            + * + * repeated string accepted_output_modes = 1; + * @param index The index of the element to return. + * @return The acceptedOutputModes at the given index. + */ + java.lang.String getAcceptedOutputModes(int index); + /** + *
            +   * The output modes that the agent is expected to respond with.
            +   * 
            + * + * repeated string accepted_output_modes = 1; + * @param index The index of the value to return. + * @return The bytes of the acceptedOutputModes at the given index. + */ + com.google.protobuf.ByteString + getAcceptedOutputModesBytes(int index); + + /** + *
            +   * A configuration of a webhook that can be used to receive updates
            +   * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + * @return Whether the pushNotification field is set. + */ + boolean hasPushNotification(); + /** + *
            +   * A configuration of a webhook that can be used to receive updates
            +   * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + * @return The pushNotification. + */ + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getPushNotification(); + /** + *
            +   * A configuration of a webhook that can be used to receive updates
            +   * 
            + * + * .a2a.v1.PushNotificationConfig push_notification = 2; + */ + org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder getPushNotificationOrBuilder(); + + /** + *
            +   * The maximum number of messages to include in the history. if 0, the
            +   * history will be unlimited.
            +   * 
            + * + * int32 history_length = 3; + * @return The historyLength. + */ + int getHistoryLength(); + + /** + *
            +   * If true, the message will be blocking until the task is completed. If
            +   * false, the message will be non-blocking and the task will be returned
            +   * immediately. It is the caller's responsibility to check for any task
            +   * updates.
            +   * 
            + * + * bool blocking = 4; + * @return The blocking. + */ + boolean getBlocking(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageRequest.java new file mode 100644 index 000000000..1bf76aae0 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageRequest.java @@ -0,0 +1,937 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * /////////// Request Messages ///////////
            + * 
            + * + * Protobuf type {@code a2a.v1.SendMessageRequest} + */ +@com.google.protobuf.Generated +public final class SendMessageRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageRequest) + SendMessageRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "SendMessageRequest"); + } + // Use SendMessageRequest.newBuilder() to construct. + private SendMessageRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private SendMessageRequest() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.class, org.a2aproject.sdk.compat03.grpc.SendMessageRequest.Builder.class); + } + + private int bitField0_; + public static final int REQUEST_FIELD_NUMBER = 1; + private org.a2aproject.sdk.compat03.grpc.Message request_; + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * @return Whether the request field is set. + */ + @java.lang.Override + public boolean hasRequest() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * @return The request. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getRequest() { + return request_ == null ? org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance() : request_; + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getRequestOrBuilder() { + return request_ == null ? org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance() : request_; + } + + public static final int CONFIGURATION_FIELD_NUMBER = 2; + private org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration configuration_; + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + * @return Whether the configuration field is set. + */ + @java.lang.Override + public boolean hasConfiguration() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + * @return The configuration. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration getConfiguration() { + return configuration_ == null ? org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() { + return configuration_ == null ? org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; + } + + public static final int METADATA_FIELD_NUMBER = 3; + private com.google.protobuf.Struct metadata_; + /** + * .google.protobuf.Struct metadata = 3; + * @return Whether the metadata field is set. + */ + @java.lang.Override + public boolean hasMetadata() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * .google.protobuf.Struct metadata = 3; + * @return The metadata. + */ + @java.lang.Override + public com.google.protobuf.Struct getMetadata() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + /** + * .google.protobuf.Struct metadata = 3; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(1, getRequest()); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(2, getConfiguration()); + } + if (((bitField0_ & 0x00000004) != 0)) { + output.writeMessage(3, getMetadata()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getRequest()); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getConfiguration()); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getMetadata()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.SendMessageRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.SendMessageRequest other = (org.a2aproject.sdk.compat03.grpc.SendMessageRequest) obj; + + if (hasRequest() != other.hasRequest()) return false; + if (hasRequest()) { + if (!getRequest() + .equals(other.getRequest())) return false; + } + if (hasConfiguration() != other.hasConfiguration()) return false; + if (hasConfiguration()) { + if (!getConfiguration() + .equals(other.getConfiguration())) return false; + } + if (hasMetadata() != other.hasMetadata()) return false; + if (hasMetadata()) { + if (!getMetadata() + .equals(other.getMetadata())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasRequest()) { + hash = (37 * hash) + REQUEST_FIELD_NUMBER; + hash = (53 * hash) + getRequest().hashCode(); + } + if (hasConfiguration()) { + hash = (37 * hash) + CONFIGURATION_FIELD_NUMBER; + hash = (53 * hash) + getConfiguration().hashCode(); + } + if (hasMetadata()) { + hash = (37 * hash) + METADATA_FIELD_NUMBER; + hash = (53 * hash) + getMetadata().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.SendMessageRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * /////////// Request Messages ///////////
            +   * 
            + * + * Protobuf type {@code a2a.v1.SendMessageRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageRequest) + org.a2aproject.sdk.compat03.grpc.SendMessageRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.class, org.a2aproject.sdk.compat03.grpc.SendMessageRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.SendMessageRequest.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetRequestFieldBuilder(); + internalGetConfigurationFieldBuilder(); + internalGetMetadataFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + request_ = null; + if (requestBuilder_ != null) { + requestBuilder_.dispose(); + requestBuilder_ = null; + } + configuration_ = null; + if (configurationBuilder_ != null) { + configurationBuilder_.dispose(); + configurationBuilder_ = null; + } + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.SendMessageRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageRequest build() { + org.a2aproject.sdk.compat03.grpc.SendMessageRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.SendMessageRequest result = new org.a2aproject.sdk.compat03.grpc.SendMessageRequest(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.SendMessageRequest result) { + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.request_ = requestBuilder_ == null + ? request_ + : requestBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.configuration_ = configurationBuilder_ == null + ? configuration_ + : configurationBuilder_.build(); + to_bitField0_ |= 0x00000002; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.metadata_ = metadataBuilder_ == null + ? metadata_ + : metadataBuilder_.build(); + to_bitField0_ |= 0x00000004; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.SendMessageRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.SendMessageRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.SendMessageRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.SendMessageRequest.getDefaultInstance()) return this; + if (other.hasRequest()) { + mergeRequest(other.getRequest()); + } + if (other.hasConfiguration()) { + mergeConfiguration(other.getConfiguration()); + } + if (other.hasMetadata()) { + mergeMetadata(other.getMetadata()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + input.readMessage( + internalGetRequestFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + input.readMessage( + internalGetConfigurationFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetMetadataFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private org.a2aproject.sdk.compat03.grpc.Message request_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> requestBuilder_; + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * @return Whether the request field is set. + */ + public boolean hasRequest() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * @return The request. + */ + public org.a2aproject.sdk.compat03.grpc.Message getRequest() { + if (requestBuilder_ == null) { + return request_ == null ? org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance() : request_; + } else { + return requestBuilder_.getMessage(); + } + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + public Builder setRequest(org.a2aproject.sdk.compat03.grpc.Message value) { + if (requestBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + request_ = value; + } else { + requestBuilder_.setMessage(value); + } + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + public Builder setRequest( + org.a2aproject.sdk.compat03.grpc.Message.Builder builderForValue) { + if (requestBuilder_ == null) { + request_ = builderForValue.build(); + } else { + requestBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + public Builder mergeRequest(org.a2aproject.sdk.compat03.grpc.Message value) { + if (requestBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0) && + request_ != null && + request_ != org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance()) { + getRequestBuilder().mergeFrom(value); + } else { + request_ = value; + } + } else { + requestBuilder_.mergeFrom(value); + } + if (request_ != null) { + bitField0_ |= 0x00000001; + onChanged(); + } + return this; + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + public Builder clearRequest() { + bitField0_ = (bitField0_ & ~0x00000001); + request_ = null; + if (requestBuilder_ != null) { + requestBuilder_.dispose(); + requestBuilder_ = null; + } + onChanged(); + return this; + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + public org.a2aproject.sdk.compat03.grpc.Message.Builder getRequestBuilder() { + bitField0_ |= 0x00000001; + onChanged(); + return internalGetRequestFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getRequestOrBuilder() { + if (requestBuilder_ != null) { + return requestBuilder_.getMessageOrBuilder(); + } else { + return request_ == null ? + org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance() : request_; + } + } + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> + internalGetRequestFieldBuilder() { + if (requestBuilder_ == null) { + requestBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder>( + getRequest(), + getParentForChildren(), + isClean()); + request_ = null; + } + return requestBuilder_; + } + + private org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration configuration_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration, org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.Builder, org.a2aproject.sdk.compat03.grpc.SendMessageConfigurationOrBuilder> configurationBuilder_; + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + * @return Whether the configuration field is set. + */ + public boolean hasConfiguration() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + * @return The configuration. + */ + public org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration getConfiguration() { + if (configurationBuilder_ == null) { + return configuration_ == null ? org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; + } else { + return configurationBuilder_.getMessage(); + } + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + public Builder setConfiguration(org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration value) { + if (configurationBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + configuration_ = value; + } else { + configurationBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + public Builder setConfiguration( + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.Builder builderForValue) { + if (configurationBuilder_ == null) { + configuration_ = builderForValue.build(); + } else { + configurationBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + public Builder mergeConfiguration(org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration value) { + if (configurationBuilder_ == null) { + if (((bitField0_ & 0x00000002) != 0) && + configuration_ != null && + configuration_ != org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.getDefaultInstance()) { + getConfigurationBuilder().mergeFrom(value); + } else { + configuration_ = value; + } + } else { + configurationBuilder_.mergeFrom(value); + } + if (configuration_ != null) { + bitField0_ |= 0x00000002; + onChanged(); + } + return this; + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + public Builder clearConfiguration() { + bitField0_ = (bitField0_ & ~0x00000002); + configuration_ = null; + if (configurationBuilder_ != null) { + configurationBuilder_.dispose(); + configurationBuilder_ = null; + } + onChanged(); + return this; + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + public org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.Builder getConfigurationBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return internalGetConfigurationFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + public org.a2aproject.sdk.compat03.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() { + if (configurationBuilder_ != null) { + return configurationBuilder_.getMessageOrBuilder(); + } else { + return configuration_ == null ? + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; + } + } + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration, org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.Builder, org.a2aproject.sdk.compat03.grpc.SendMessageConfigurationOrBuilder> + internalGetConfigurationFieldBuilder() { + if (configurationBuilder_ == null) { + configurationBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration, org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.Builder, org.a2aproject.sdk.compat03.grpc.SendMessageConfigurationOrBuilder>( + getConfiguration(), + getParentForChildren(), + isClean()); + configuration_ = null; + } + return configurationBuilder_; + } + + private com.google.protobuf.Struct metadata_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; + /** + * .google.protobuf.Struct metadata = 3; + * @return Whether the metadata field is set. + */ + public boolean hasMetadata() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * .google.protobuf.Struct metadata = 3; + * @return The metadata. + */ + public com.google.protobuf.Struct getMetadata() { + if (metadataBuilder_ == null) { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } else { + return metadataBuilder_.getMessage(); + } + } + /** + * .google.protobuf.Struct metadata = 3; + */ + public Builder setMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + metadata_ = value; + } else { + metadataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * .google.protobuf.Struct metadata = 3; + */ + public Builder setMetadata( + com.google.protobuf.Struct.Builder builderForValue) { + if (metadataBuilder_ == null) { + metadata_ = builderForValue.build(); + } else { + metadataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * .google.protobuf.Struct metadata = 3; + */ + public Builder mergeMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + metadata_ != null && + metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { + getMetadataBuilder().mergeFrom(value); + } else { + metadata_ = value; + } + } else { + metadataBuilder_.mergeFrom(value); + } + if (metadata_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + /** + * .google.protobuf.Struct metadata = 3; + */ + public Builder clearMetadata() { + bitField0_ = (bitField0_ & ~0x00000004); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + onChanged(); + return this; + } + /** + * .google.protobuf.Struct metadata = 3; + */ + public com.google.protobuf.Struct.Builder getMetadataBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return internalGetMetadataFieldBuilder().getBuilder(); + } + /** + * .google.protobuf.Struct metadata = 3; + */ + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + if (metadataBuilder_ != null) { + return metadataBuilder_.getMessageOrBuilder(); + } else { + return metadata_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + } + /** + * .google.protobuf.Struct metadata = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetMetadataFieldBuilder() { + if (metadataBuilder_ == null) { + metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getMetadata(), + getParentForChildren(), + isClean()); + metadata_ = null; + } + return metadataBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageRequest) + private static final org.a2aproject.sdk.compat03.grpc.SendMessageRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.SendMessageRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public SendMessageRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageRequestOrBuilder.java new file mode 100644 index 000000000..6adc2a4b0 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageRequestOrBuilder.java @@ -0,0 +1,57 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface SendMessageRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageRequest) + com.google.protobuf.MessageOrBuilder { + + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * @return Whether the request field is set. + */ + boolean hasRequest(); + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + * @return The request. + */ + org.a2aproject.sdk.compat03.grpc.Message getRequest(); + /** + * .a2a.v1.Message request = 1 [json_name = "message", (.google.api.field_behavior) = REQUIRED]; + */ + org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getRequestOrBuilder(); + + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + * @return Whether the configuration field is set. + */ + boolean hasConfiguration(); + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + * @return The configuration. + */ + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration getConfiguration(); + /** + * .a2a.v1.SendMessageConfiguration configuration = 2; + */ + org.a2aproject.sdk.compat03.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder(); + + /** + * .google.protobuf.Struct metadata = 3; + * @return Whether the metadata field is set. + */ + boolean hasMetadata(); + /** + * .google.protobuf.Struct metadata = 3; + * @return The metadata. + */ + com.google.protobuf.Struct getMetadata(); + /** + * .google.protobuf.Struct metadata = 3; + */ + com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageResponse.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageResponse.java new file mode 100644 index 000000000..054fb6a55 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageResponse.java @@ -0,0 +1,865 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * ////// Response Messages ///////////
            + * 
            + * + * Protobuf type {@code a2a.v1.SendMessageResponse} + */ +@com.google.protobuf.Generated +public final class SendMessageResponse extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageResponse) + SendMessageResponseOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "SendMessageResponse"); + } + // Use SendMessageResponse.newBuilder() to construct. + private SendMessageResponse(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private SendMessageResponse() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.SendMessageResponse.class, org.a2aproject.sdk.compat03.grpc.SendMessageResponse.Builder.class); + } + + private int payloadCase_ = 0; + @SuppressWarnings("serial") + private java.lang.Object payload_; + public enum PayloadCase + implements com.google.protobuf.Internal.EnumLite, + com.google.protobuf.AbstractMessage.InternalOneOfEnum { + TASK(1), + MSG(2), + PAYLOAD_NOT_SET(0); + private final int value; + private PayloadCase(int value) { + this.value = value; + } + /** + * @param value The number of the enum to look for. + * @return The enum associated with the given number. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static PayloadCase valueOf(int value) { + return forNumber(value); + } + + public static PayloadCase forNumber(int value) { + switch (value) { + case 1: return TASK; + case 2: return MSG; + case 0: return PAYLOAD_NOT_SET; + default: return null; + } + } + public int getNumber() { + return this.value; + } + }; + + public PayloadCase + getPayloadCase() { + return PayloadCase.forNumber( + payloadCase_); + } + + public static final int TASK_FIELD_NUMBER = 1; + /** + * .a2a.v1.Task task = 1; + * @return Whether the task field is set. + */ + @java.lang.Override + public boolean hasTask() { + return payloadCase_ == 1; + } + /** + * .a2a.v1.Task task = 1; + * @return The task. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Task getTask() { + if (payloadCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.Task) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + /** + * .a2a.v1.Task task = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskOrBuilder getTaskOrBuilder() { + if (payloadCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.Task) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + + public static final int MSG_FIELD_NUMBER = 2; + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return Whether the msg field is set. + */ + @java.lang.Override + public boolean hasMsg() { + return payloadCase_ == 2; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return The msg. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getMsg() { + if (payloadCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.Message) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getMsgOrBuilder() { + if (payloadCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.Message) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (payloadCase_ == 1) { + output.writeMessage(1, (org.a2aproject.sdk.compat03.grpc.Task) payload_); + } + if (payloadCase_ == 2) { + output.writeMessage(2, (org.a2aproject.sdk.compat03.grpc.Message) payload_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (payloadCase_ == 1) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, (org.a2aproject.sdk.compat03.grpc.Task) payload_); + } + if (payloadCase_ == 2) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, (org.a2aproject.sdk.compat03.grpc.Message) payload_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.SendMessageResponse)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.SendMessageResponse other = (org.a2aproject.sdk.compat03.grpc.SendMessageResponse) obj; + + if (!getPayloadCase().equals(other.getPayloadCase())) return false; + switch (payloadCase_) { + case 1: + if (!getTask() + .equals(other.getTask())) return false; + break; + case 2: + if (!getMsg() + .equals(other.getMsg())) return false; + break; + case 0: + default: + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + switch (payloadCase_) { + case 1: + hash = (37 * hash) + TASK_FIELD_NUMBER; + hash = (53 * hash) + getTask().hashCode(); + break; + case 2: + hash = (37 * hash) + MSG_FIELD_NUMBER; + hash = (53 * hash) + getMsg().hashCode(); + break; + case 0: + default: + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.SendMessageResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * ////// Response Messages ///////////
            +   * 
            + * + * Protobuf type {@code a2a.v1.SendMessageResponse} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageResponse) + org.a2aproject.sdk.compat03.grpc.SendMessageResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.SendMessageResponse.class, org.a2aproject.sdk.compat03.grpc.SendMessageResponse.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.SendMessageResponse.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + if (taskBuilder_ != null) { + taskBuilder_.clear(); + } + if (msgBuilder_ != null) { + msgBuilder_.clear(); + } + payloadCase_ = 0; + payload_ = null; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageResponse getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.SendMessageResponse.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageResponse build() { + org.a2aproject.sdk.compat03.grpc.SendMessageResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageResponse buildPartial() { + org.a2aproject.sdk.compat03.grpc.SendMessageResponse result = new org.a2aproject.sdk.compat03.grpc.SendMessageResponse(this); + if (bitField0_ != 0) { buildPartial0(result); } + buildPartialOneofs(result); + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.SendMessageResponse result) { + int from_bitField0_ = bitField0_; + } + + private void buildPartialOneofs(org.a2aproject.sdk.compat03.grpc.SendMessageResponse result) { + result.payloadCase_ = payloadCase_; + result.payload_ = this.payload_; + if (payloadCase_ == 1 && + taskBuilder_ != null) { + result.payload_ = taskBuilder_.build(); + } + if (payloadCase_ == 2 && + msgBuilder_ != null) { + result.payload_ = msgBuilder_.build(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.SendMessageResponse) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.SendMessageResponse)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.SendMessageResponse other) { + if (other == org.a2aproject.sdk.compat03.grpc.SendMessageResponse.getDefaultInstance()) return this; + switch (other.getPayloadCase()) { + case TASK: { + mergeTask(other.getTask()); + break; + } + case MSG: { + mergeMsg(other.getMsg()); + break; + } + case PAYLOAD_NOT_SET: { + break; + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + input.readMessage( + internalGetTaskFieldBuilder().getBuilder(), + extensionRegistry); + payloadCase_ = 1; + break; + } // case 10 + case 18: { + input.readMessage( + internalGetMsgFieldBuilder().getBuilder(), + extensionRegistry); + payloadCase_ = 2; + break; + } // case 18 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int payloadCase_ = 0; + private java.lang.Object payload_; + public PayloadCase + getPayloadCase() { + return PayloadCase.forNumber( + payloadCase_); + } + + public Builder clearPayload() { + payloadCase_ = 0; + payload_ = null; + onChanged(); + return this; + } + + private int bitField0_; + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Task, org.a2aproject.sdk.compat03.grpc.Task.Builder, org.a2aproject.sdk.compat03.grpc.TaskOrBuilder> taskBuilder_; + /** + * .a2a.v1.Task task = 1; + * @return Whether the task field is set. + */ + @java.lang.Override + public boolean hasTask() { + return payloadCase_ == 1; + } + /** + * .a2a.v1.Task task = 1; + * @return The task. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Task getTask() { + if (taskBuilder_ == null) { + if (payloadCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.Task) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } else { + if (payloadCase_ == 1) { + return taskBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + } + /** + * .a2a.v1.Task task = 1; + */ + public Builder setTask(org.a2aproject.sdk.compat03.grpc.Task value) { + if (taskBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + payload_ = value; + onChanged(); + } else { + taskBuilder_.setMessage(value); + } + payloadCase_ = 1; + return this; + } + /** + * .a2a.v1.Task task = 1; + */ + public Builder setTask( + org.a2aproject.sdk.compat03.grpc.Task.Builder builderForValue) { + if (taskBuilder_ == null) { + payload_ = builderForValue.build(); + onChanged(); + } else { + taskBuilder_.setMessage(builderForValue.build()); + } + payloadCase_ = 1; + return this; + } + /** + * .a2a.v1.Task task = 1; + */ + public Builder mergeTask(org.a2aproject.sdk.compat03.grpc.Task value) { + if (taskBuilder_ == null) { + if (payloadCase_ == 1 && + payload_ != org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance()) { + payload_ = org.a2aproject.sdk.compat03.grpc.Task.newBuilder((org.a2aproject.sdk.compat03.grpc.Task) payload_) + .mergeFrom(value).buildPartial(); + } else { + payload_ = value; + } + onChanged(); + } else { + if (payloadCase_ == 1) { + taskBuilder_.mergeFrom(value); + } else { + taskBuilder_.setMessage(value); + } + } + payloadCase_ = 1; + return this; + } + /** + * .a2a.v1.Task task = 1; + */ + public Builder clearTask() { + if (taskBuilder_ == null) { + if (payloadCase_ == 1) { + payloadCase_ = 0; + payload_ = null; + onChanged(); + } + } else { + if (payloadCase_ == 1) { + payloadCase_ = 0; + payload_ = null; + } + taskBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.Task task = 1; + */ + public org.a2aproject.sdk.compat03.grpc.Task.Builder getTaskBuilder() { + return internalGetTaskFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.Task task = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskOrBuilder getTaskOrBuilder() { + if ((payloadCase_ == 1) && (taskBuilder_ != null)) { + return taskBuilder_.getMessageOrBuilder(); + } else { + if (payloadCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.Task) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + } + /** + * .a2a.v1.Task task = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Task, org.a2aproject.sdk.compat03.grpc.Task.Builder, org.a2aproject.sdk.compat03.grpc.TaskOrBuilder> + internalGetTaskFieldBuilder() { + if (taskBuilder_ == null) { + if (!(payloadCase_ == 1)) { + payload_ = org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + taskBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Task, org.a2aproject.sdk.compat03.grpc.Task.Builder, org.a2aproject.sdk.compat03.grpc.TaskOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.Task) payload_, + getParentForChildren(), + isClean()); + payload_ = null; + } + payloadCase_ = 1; + onChanged(); + return taskBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> msgBuilder_; + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return Whether the msg field is set. + */ + @java.lang.Override + public boolean hasMsg() { + return payloadCase_ == 2; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return The msg. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getMsg() { + if (msgBuilder_ == null) { + if (payloadCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.Message) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } else { + if (payloadCase_ == 2) { + return msgBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public Builder setMsg(org.a2aproject.sdk.compat03.grpc.Message value) { + if (msgBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + payload_ = value; + onChanged(); + } else { + msgBuilder_.setMessage(value); + } + payloadCase_ = 2; + return this; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public Builder setMsg( + org.a2aproject.sdk.compat03.grpc.Message.Builder builderForValue) { + if (msgBuilder_ == null) { + payload_ = builderForValue.build(); + onChanged(); + } else { + msgBuilder_.setMessage(builderForValue.build()); + } + payloadCase_ = 2; + return this; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public Builder mergeMsg(org.a2aproject.sdk.compat03.grpc.Message value) { + if (msgBuilder_ == null) { + if (payloadCase_ == 2 && + payload_ != org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance()) { + payload_ = org.a2aproject.sdk.compat03.grpc.Message.newBuilder((org.a2aproject.sdk.compat03.grpc.Message) payload_) + .mergeFrom(value).buildPartial(); + } else { + payload_ = value; + } + onChanged(); + } else { + if (payloadCase_ == 2) { + msgBuilder_.mergeFrom(value); + } else { + msgBuilder_.setMessage(value); + } + } + payloadCase_ = 2; + return this; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public Builder clearMsg() { + if (msgBuilder_ == null) { + if (payloadCase_ == 2) { + payloadCase_ = 0; + payload_ = null; + onChanged(); + } + } else { + if (payloadCase_ == 2) { + payloadCase_ = 0; + payload_ = null; + } + msgBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public org.a2aproject.sdk.compat03.grpc.Message.Builder getMsgBuilder() { + return internalGetMsgFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getMsgOrBuilder() { + if ((payloadCase_ == 2) && (msgBuilder_ != null)) { + return msgBuilder_.getMessageOrBuilder(); + } else { + if (payloadCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.Message) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> + internalGetMsgFieldBuilder() { + if (msgBuilder_ == null) { + if (!(payloadCase_ == 2)) { + payload_ = org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + msgBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.Message) payload_, + getParentForChildren(), + isClean()); + payload_ = null; + } + payloadCase_ = 2; + onChanged(); + return msgBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageResponse) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageResponse) + private static final org.a2aproject.sdk.compat03.grpc.SendMessageResponse DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.SendMessageResponse(); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public SendMessageResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.SendMessageResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageResponseOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageResponseOrBuilder.java new file mode 100644 index 000000000..3b71db61f --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/SendMessageResponseOrBuilder.java @@ -0,0 +1,44 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface SendMessageResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageResponse) + com.google.protobuf.MessageOrBuilder { + + /** + * .a2a.v1.Task task = 1; + * @return Whether the task field is set. + */ + boolean hasTask(); + /** + * .a2a.v1.Task task = 1; + * @return The task. + */ + org.a2aproject.sdk.compat03.grpc.Task getTask(); + /** + * .a2a.v1.Task task = 1; + */ + org.a2aproject.sdk.compat03.grpc.TaskOrBuilder getTaskOrBuilder(); + + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return Whether the msg field is set. + */ + boolean hasMsg(); + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return The msg. + */ + org.a2aproject.sdk.compat03.grpc.Message getMsg(); + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getMsgOrBuilder(); + + org.a2aproject.sdk.compat03.grpc.SendMessageResponse.PayloadCase getPayloadCase(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StreamResponse.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StreamResponse.java new file mode 100644 index 000000000..4812ac200 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StreamResponse.java @@ -0,0 +1,1297 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * The stream response for a message. The stream should be one of the following
            + * sequences:
            + * If the response is a message, the stream should contain one, and only one,
            + * message and then close
            + * If the response is a task lifecycle, the first response should be a Task
            + * object followed by zero or more TaskStatusUpdateEvents and
            + * TaskArtifactUpdateEvents. The stream should complete when the Task
            + * if in an interrupted or terminal state. A stream that ends before these
            + * conditions are met are
            + * 
            + * + * Protobuf type {@code a2a.v1.StreamResponse} + */ +@com.google.protobuf.Generated +public final class StreamResponse extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.StreamResponse) + StreamResponseOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "StreamResponse"); + } + // Use StreamResponse.newBuilder() to construct. + private StreamResponse(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private StreamResponse() { + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_StreamResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_StreamResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.StreamResponse.class, org.a2aproject.sdk.compat03.grpc.StreamResponse.Builder.class); + } + + private int payloadCase_ = 0; + @SuppressWarnings("serial") + private java.lang.Object payload_; + public enum PayloadCase + implements com.google.protobuf.Internal.EnumLite, + com.google.protobuf.AbstractMessage.InternalOneOfEnum { + TASK(1), + MSG(2), + STATUS_UPDATE(3), + ARTIFACT_UPDATE(4), + PAYLOAD_NOT_SET(0); + private final int value; + private PayloadCase(int value) { + this.value = value; + } + /** + * @param value The number of the enum to look for. + * @return The enum associated with the given number. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static PayloadCase valueOf(int value) { + return forNumber(value); + } + + public static PayloadCase forNumber(int value) { + switch (value) { + case 1: return TASK; + case 2: return MSG; + case 3: return STATUS_UPDATE; + case 4: return ARTIFACT_UPDATE; + case 0: return PAYLOAD_NOT_SET; + default: return null; + } + } + public int getNumber() { + return this.value; + } + }; + + public PayloadCase + getPayloadCase() { + return PayloadCase.forNumber( + payloadCase_); + } + + public static final int TASK_FIELD_NUMBER = 1; + /** + * .a2a.v1.Task task = 1; + * @return Whether the task field is set. + */ + @java.lang.Override + public boolean hasTask() { + return payloadCase_ == 1; + } + /** + * .a2a.v1.Task task = 1; + * @return The task. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Task getTask() { + if (payloadCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.Task) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + /** + * .a2a.v1.Task task = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskOrBuilder getTaskOrBuilder() { + if (payloadCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.Task) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + + public static final int MSG_FIELD_NUMBER = 2; + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return Whether the msg field is set. + */ + @java.lang.Override + public boolean hasMsg() { + return payloadCase_ == 2; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return The msg. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getMsg() { + if (payloadCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.Message) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getMsgOrBuilder() { + if (payloadCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.Message) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + + public static final int STATUS_UPDATE_FIELD_NUMBER = 3; + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * @return Whether the statusUpdate field is set. + */ + @java.lang.Override + public boolean hasStatusUpdate() { + return payloadCase_ == 3; + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * @return The statusUpdate. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent getStatusUpdate() { + if (payloadCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) payload_; + } + return org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance(); + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { + if (payloadCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) payload_; + } + return org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance(); + } + + public static final int ARTIFACT_UPDATE_FIELD_NUMBER = 4; + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * @return Whether the artifactUpdate field is set. + */ + @java.lang.Override + public boolean hasArtifactUpdate() { + return payloadCase_ == 4; + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * @return The artifactUpdate. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent getArtifactUpdate() { + if (payloadCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) payload_; + } + return org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() { + if (payloadCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) payload_; + } + return org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (payloadCase_ == 1) { + output.writeMessage(1, (org.a2aproject.sdk.compat03.grpc.Task) payload_); + } + if (payloadCase_ == 2) { + output.writeMessage(2, (org.a2aproject.sdk.compat03.grpc.Message) payload_); + } + if (payloadCase_ == 3) { + output.writeMessage(3, (org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) payload_); + } + if (payloadCase_ == 4) { + output.writeMessage(4, (org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) payload_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (payloadCase_ == 1) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, (org.a2aproject.sdk.compat03.grpc.Task) payload_); + } + if (payloadCase_ == 2) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, (org.a2aproject.sdk.compat03.grpc.Message) payload_); + } + if (payloadCase_ == 3) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, (org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) payload_); + } + if (payloadCase_ == 4) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, (org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) payload_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.StreamResponse)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.StreamResponse other = (org.a2aproject.sdk.compat03.grpc.StreamResponse) obj; + + if (!getPayloadCase().equals(other.getPayloadCase())) return false; + switch (payloadCase_) { + case 1: + if (!getTask() + .equals(other.getTask())) return false; + break; + case 2: + if (!getMsg() + .equals(other.getMsg())) return false; + break; + case 3: + if (!getStatusUpdate() + .equals(other.getStatusUpdate())) return false; + break; + case 4: + if (!getArtifactUpdate() + .equals(other.getArtifactUpdate())) return false; + break; + case 0: + default: + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + switch (payloadCase_) { + case 1: + hash = (37 * hash) + TASK_FIELD_NUMBER; + hash = (53 * hash) + getTask().hashCode(); + break; + case 2: + hash = (37 * hash) + MSG_FIELD_NUMBER; + hash = (53 * hash) + getMsg().hashCode(); + break; + case 3: + hash = (37 * hash) + STATUS_UPDATE_FIELD_NUMBER; + hash = (53 * hash) + getStatusUpdate().hashCode(); + break; + case 4: + hash = (37 * hash) + ARTIFACT_UPDATE_FIELD_NUMBER; + hash = (53 * hash) + getArtifactUpdate().hashCode(); + break; + case 0: + default: + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.StreamResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.StreamResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * The stream response for a message. The stream should be one of the following
            +   * sequences:
            +   * If the response is a message, the stream should contain one, and only one,
            +   * message and then close
            +   * If the response is a task lifecycle, the first response should be a Task
            +   * object followed by zero or more TaskStatusUpdateEvents and
            +   * TaskArtifactUpdateEvents. The stream should complete when the Task
            +   * if in an interrupted or terminal state. A stream that ends before these
            +   * conditions are met are
            +   * 
            + * + * Protobuf type {@code a2a.v1.StreamResponse} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.StreamResponse) + org.a2aproject.sdk.compat03.grpc.StreamResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_StreamResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_StreamResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.StreamResponse.class, org.a2aproject.sdk.compat03.grpc.StreamResponse.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.StreamResponse.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + if (taskBuilder_ != null) { + taskBuilder_.clear(); + } + if (msgBuilder_ != null) { + msgBuilder_.clear(); + } + if (statusUpdateBuilder_ != null) { + statusUpdateBuilder_.clear(); + } + if (artifactUpdateBuilder_ != null) { + artifactUpdateBuilder_.clear(); + } + payloadCase_ = 0; + payload_ = null; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_StreamResponse_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StreamResponse getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.StreamResponse.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StreamResponse build() { + org.a2aproject.sdk.compat03.grpc.StreamResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StreamResponse buildPartial() { + org.a2aproject.sdk.compat03.grpc.StreamResponse result = new org.a2aproject.sdk.compat03.grpc.StreamResponse(this); + if (bitField0_ != 0) { buildPartial0(result); } + buildPartialOneofs(result); + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.StreamResponse result) { + int from_bitField0_ = bitField0_; + } + + private void buildPartialOneofs(org.a2aproject.sdk.compat03.grpc.StreamResponse result) { + result.payloadCase_ = payloadCase_; + result.payload_ = this.payload_; + if (payloadCase_ == 1 && + taskBuilder_ != null) { + result.payload_ = taskBuilder_.build(); + } + if (payloadCase_ == 2 && + msgBuilder_ != null) { + result.payload_ = msgBuilder_.build(); + } + if (payloadCase_ == 3 && + statusUpdateBuilder_ != null) { + result.payload_ = statusUpdateBuilder_.build(); + } + if (payloadCase_ == 4 && + artifactUpdateBuilder_ != null) { + result.payload_ = artifactUpdateBuilder_.build(); + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.StreamResponse) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.StreamResponse)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.StreamResponse other) { + if (other == org.a2aproject.sdk.compat03.grpc.StreamResponse.getDefaultInstance()) return this; + switch (other.getPayloadCase()) { + case TASK: { + mergeTask(other.getTask()); + break; + } + case MSG: { + mergeMsg(other.getMsg()); + break; + } + case STATUS_UPDATE: { + mergeStatusUpdate(other.getStatusUpdate()); + break; + } + case ARTIFACT_UPDATE: { + mergeArtifactUpdate(other.getArtifactUpdate()); + break; + } + case PAYLOAD_NOT_SET: { + break; + } + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + input.readMessage( + internalGetTaskFieldBuilder().getBuilder(), + extensionRegistry); + payloadCase_ = 1; + break; + } // case 10 + case 18: { + input.readMessage( + internalGetMsgFieldBuilder().getBuilder(), + extensionRegistry); + payloadCase_ = 2; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetStatusUpdateFieldBuilder().getBuilder(), + extensionRegistry); + payloadCase_ = 3; + break; + } // case 26 + case 34: { + input.readMessage( + internalGetArtifactUpdateFieldBuilder().getBuilder(), + extensionRegistry); + payloadCase_ = 4; + break; + } // case 34 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int payloadCase_ = 0; + private java.lang.Object payload_; + public PayloadCase + getPayloadCase() { + return PayloadCase.forNumber( + payloadCase_); + } + + public Builder clearPayload() { + payloadCase_ = 0; + payload_ = null; + onChanged(); + return this; + } + + private int bitField0_; + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Task, org.a2aproject.sdk.compat03.grpc.Task.Builder, org.a2aproject.sdk.compat03.grpc.TaskOrBuilder> taskBuilder_; + /** + * .a2a.v1.Task task = 1; + * @return Whether the task field is set. + */ + @java.lang.Override + public boolean hasTask() { + return payloadCase_ == 1; + } + /** + * .a2a.v1.Task task = 1; + * @return The task. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Task getTask() { + if (taskBuilder_ == null) { + if (payloadCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.Task) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } else { + if (payloadCase_ == 1) { + return taskBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + } + /** + * .a2a.v1.Task task = 1; + */ + public Builder setTask(org.a2aproject.sdk.compat03.grpc.Task value) { + if (taskBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + payload_ = value; + onChanged(); + } else { + taskBuilder_.setMessage(value); + } + payloadCase_ = 1; + return this; + } + /** + * .a2a.v1.Task task = 1; + */ + public Builder setTask( + org.a2aproject.sdk.compat03.grpc.Task.Builder builderForValue) { + if (taskBuilder_ == null) { + payload_ = builderForValue.build(); + onChanged(); + } else { + taskBuilder_.setMessage(builderForValue.build()); + } + payloadCase_ = 1; + return this; + } + /** + * .a2a.v1.Task task = 1; + */ + public Builder mergeTask(org.a2aproject.sdk.compat03.grpc.Task value) { + if (taskBuilder_ == null) { + if (payloadCase_ == 1 && + payload_ != org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance()) { + payload_ = org.a2aproject.sdk.compat03.grpc.Task.newBuilder((org.a2aproject.sdk.compat03.grpc.Task) payload_) + .mergeFrom(value).buildPartial(); + } else { + payload_ = value; + } + onChanged(); + } else { + if (payloadCase_ == 1) { + taskBuilder_.mergeFrom(value); + } else { + taskBuilder_.setMessage(value); + } + } + payloadCase_ = 1; + return this; + } + /** + * .a2a.v1.Task task = 1; + */ + public Builder clearTask() { + if (taskBuilder_ == null) { + if (payloadCase_ == 1) { + payloadCase_ = 0; + payload_ = null; + onChanged(); + } + } else { + if (payloadCase_ == 1) { + payloadCase_ = 0; + payload_ = null; + } + taskBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.Task task = 1; + */ + public org.a2aproject.sdk.compat03.grpc.Task.Builder getTaskBuilder() { + return internalGetTaskFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.Task task = 1; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskOrBuilder getTaskOrBuilder() { + if ((payloadCase_ == 1) && (taskBuilder_ != null)) { + return taskBuilder_.getMessageOrBuilder(); + } else { + if (payloadCase_ == 1) { + return (org.a2aproject.sdk.compat03.grpc.Task) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + } + /** + * .a2a.v1.Task task = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Task, org.a2aproject.sdk.compat03.grpc.Task.Builder, org.a2aproject.sdk.compat03.grpc.TaskOrBuilder> + internalGetTaskFieldBuilder() { + if (taskBuilder_ == null) { + if (!(payloadCase_ == 1)) { + payload_ = org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + taskBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Task, org.a2aproject.sdk.compat03.grpc.Task.Builder, org.a2aproject.sdk.compat03.grpc.TaskOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.Task) payload_, + getParentForChildren(), + isClean()); + payload_ = null; + } + payloadCase_ = 1; + onChanged(); + return taskBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> msgBuilder_; + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return Whether the msg field is set. + */ + @java.lang.Override + public boolean hasMsg() { + return payloadCase_ == 2; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return The msg. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getMsg() { + if (msgBuilder_ == null) { + if (payloadCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.Message) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } else { + if (payloadCase_ == 2) { + return msgBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public Builder setMsg(org.a2aproject.sdk.compat03.grpc.Message value) { + if (msgBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + payload_ = value; + onChanged(); + } else { + msgBuilder_.setMessage(value); + } + payloadCase_ = 2; + return this; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public Builder setMsg( + org.a2aproject.sdk.compat03.grpc.Message.Builder builderForValue) { + if (msgBuilder_ == null) { + payload_ = builderForValue.build(); + onChanged(); + } else { + msgBuilder_.setMessage(builderForValue.build()); + } + payloadCase_ = 2; + return this; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public Builder mergeMsg(org.a2aproject.sdk.compat03.grpc.Message value) { + if (msgBuilder_ == null) { + if (payloadCase_ == 2 && + payload_ != org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance()) { + payload_ = org.a2aproject.sdk.compat03.grpc.Message.newBuilder((org.a2aproject.sdk.compat03.grpc.Message) payload_) + .mergeFrom(value).buildPartial(); + } else { + payload_ = value; + } + onChanged(); + } else { + if (payloadCase_ == 2) { + msgBuilder_.mergeFrom(value); + } else { + msgBuilder_.setMessage(value); + } + } + payloadCase_ = 2; + return this; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public Builder clearMsg() { + if (msgBuilder_ == null) { + if (payloadCase_ == 2) { + payloadCase_ = 0; + payload_ = null; + onChanged(); + } + } else { + if (payloadCase_ == 2) { + payloadCase_ = 0; + payload_ = null; + } + msgBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + public org.a2aproject.sdk.compat03.grpc.Message.Builder getMsgBuilder() { + return internalGetMsgFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getMsgOrBuilder() { + if ((payloadCase_ == 2) && (msgBuilder_ != null)) { + return msgBuilder_.getMessageOrBuilder(); + } else { + if (payloadCase_ == 2) { + return (org.a2aproject.sdk.compat03.grpc.Message) payload_; + } + return org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + } + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> + internalGetMsgFieldBuilder() { + if (msgBuilder_ == null) { + if (!(payloadCase_ == 2)) { + payload_ = org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance(); + } + msgBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.Message) payload_, + getParentForChildren(), + isClean()); + payload_ = null; + } + payloadCase_ = 2; + onChanged(); + return msgBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent, org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEventOrBuilder> statusUpdateBuilder_; + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * @return Whether the statusUpdate field is set. + */ + @java.lang.Override + public boolean hasStatusUpdate() { + return payloadCase_ == 3; + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * @return The statusUpdate. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent getStatusUpdate() { + if (statusUpdateBuilder_ == null) { + if (payloadCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) payload_; + } + return org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance(); + } else { + if (payloadCase_ == 3) { + return statusUpdateBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance(); + } + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + public Builder setStatusUpdate(org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent value) { + if (statusUpdateBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + payload_ = value; + onChanged(); + } else { + statusUpdateBuilder_.setMessage(value); + } + payloadCase_ = 3; + return this; + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + public Builder setStatusUpdate( + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder builderForValue) { + if (statusUpdateBuilder_ == null) { + payload_ = builderForValue.build(); + onChanged(); + } else { + statusUpdateBuilder_.setMessage(builderForValue.build()); + } + payloadCase_ = 3; + return this; + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + public Builder mergeStatusUpdate(org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent value) { + if (statusUpdateBuilder_ == null) { + if (payloadCase_ == 3 && + payload_ != org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance()) { + payload_ = org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.newBuilder((org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) payload_) + .mergeFrom(value).buildPartial(); + } else { + payload_ = value; + } + onChanged(); + } else { + if (payloadCase_ == 3) { + statusUpdateBuilder_.mergeFrom(value); + } else { + statusUpdateBuilder_.setMessage(value); + } + } + payloadCase_ = 3; + return this; + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + public Builder clearStatusUpdate() { + if (statusUpdateBuilder_ == null) { + if (payloadCase_ == 3) { + payloadCase_ = 0; + payload_ = null; + onChanged(); + } + } else { + if (payloadCase_ == 3) { + payloadCase_ = 0; + payload_ = null; + } + statusUpdateBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder getStatusUpdateBuilder() { + return internalGetStatusUpdateFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { + if ((payloadCase_ == 3) && (statusUpdateBuilder_ != null)) { + return statusUpdateBuilder_.getMessageOrBuilder(); + } else { + if (payloadCase_ == 3) { + return (org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) payload_; + } + return org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance(); + } + } + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent, org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEventOrBuilder> + internalGetStatusUpdateFieldBuilder() { + if (statusUpdateBuilder_ == null) { + if (!(payloadCase_ == 3)) { + payload_ = org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance(); + } + statusUpdateBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent, org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEventOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) payload_, + getParentForChildren(), + isClean()); + payload_ = null; + } + payloadCase_ = 3; + onChanged(); + return statusUpdateBuilder_; + } + + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent, org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder, org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEventOrBuilder> artifactUpdateBuilder_; + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * @return Whether the artifactUpdate field is set. + */ + @java.lang.Override + public boolean hasArtifactUpdate() { + return payloadCase_ == 4; + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * @return The artifactUpdate. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent getArtifactUpdate() { + if (artifactUpdateBuilder_ == null) { + if (payloadCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) payload_; + } + return org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); + } else { + if (payloadCase_ == 4) { + return artifactUpdateBuilder_.getMessage(); + } + return org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); + } + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + public Builder setArtifactUpdate(org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent value) { + if (artifactUpdateBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + payload_ = value; + onChanged(); + } else { + artifactUpdateBuilder_.setMessage(value); + } + payloadCase_ = 4; + return this; + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + public Builder setArtifactUpdate( + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder builderForValue) { + if (artifactUpdateBuilder_ == null) { + payload_ = builderForValue.build(); + onChanged(); + } else { + artifactUpdateBuilder_.setMessage(builderForValue.build()); + } + payloadCase_ = 4; + return this; + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + public Builder mergeArtifactUpdate(org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent value) { + if (artifactUpdateBuilder_ == null) { + if (payloadCase_ == 4 && + payload_ != org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance()) { + payload_ = org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.newBuilder((org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) payload_) + .mergeFrom(value).buildPartial(); + } else { + payload_ = value; + } + onChanged(); + } else { + if (payloadCase_ == 4) { + artifactUpdateBuilder_.mergeFrom(value); + } else { + artifactUpdateBuilder_.setMessage(value); + } + } + payloadCase_ = 4; + return this; + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + public Builder clearArtifactUpdate() { + if (artifactUpdateBuilder_ == null) { + if (payloadCase_ == 4) { + payloadCase_ = 0; + payload_ = null; + onChanged(); + } + } else { + if (payloadCase_ == 4) { + payloadCase_ = 0; + payload_ = null; + } + artifactUpdateBuilder_.clear(); + } + return this; + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder getArtifactUpdateBuilder() { + return internalGetArtifactUpdateFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() { + if ((payloadCase_ == 4) && (artifactUpdateBuilder_ != null)) { + return artifactUpdateBuilder_.getMessageOrBuilder(); + } else { + if (payloadCase_ == 4) { + return (org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) payload_; + } + return org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); + } + } + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent, org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder, org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEventOrBuilder> + internalGetArtifactUpdateFieldBuilder() { + if (artifactUpdateBuilder_ == null) { + if (!(payloadCase_ == 4)) { + payload_ = org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); + } + artifactUpdateBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent, org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder, org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEventOrBuilder>( + (org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) payload_, + getParentForChildren(), + isClean()); + payload_ = null; + } + payloadCase_ = 4; + onChanged(); + return artifactUpdateBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.StreamResponse) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.StreamResponse) + private static final org.a2aproject.sdk.compat03.grpc.StreamResponse DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.StreamResponse(); + } + + public static org.a2aproject.sdk.compat03.grpc.StreamResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public StreamResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StreamResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StreamResponseOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StreamResponseOrBuilder.java new file mode 100644 index 000000000..a6b71e2f2 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StreamResponseOrBuilder.java @@ -0,0 +1,74 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface StreamResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.StreamResponse) + com.google.protobuf.MessageOrBuilder { + + /** + * .a2a.v1.Task task = 1; + * @return Whether the task field is set. + */ + boolean hasTask(); + /** + * .a2a.v1.Task task = 1; + * @return The task. + */ + org.a2aproject.sdk.compat03.grpc.Task getTask(); + /** + * .a2a.v1.Task task = 1; + */ + org.a2aproject.sdk.compat03.grpc.TaskOrBuilder getTaskOrBuilder(); + + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return Whether the msg field is set. + */ + boolean hasMsg(); + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + * @return The msg. + */ + org.a2aproject.sdk.compat03.grpc.Message getMsg(); + /** + * .a2a.v1.Message msg = 2 [json_name = "message"]; + */ + org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getMsgOrBuilder(); + + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * @return Whether the statusUpdate field is set. + */ + boolean hasStatusUpdate(); + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + * @return The statusUpdate. + */ + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent getStatusUpdate(); + /** + * .a2a.v1.TaskStatusUpdateEvent status_update = 3; + */ + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder(); + + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * @return Whether the artifactUpdate field is set. + */ + boolean hasArtifactUpdate(); + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + * @return The artifactUpdate. + */ + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent getArtifactUpdate(); + /** + * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; + */ + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder(); + + org.a2aproject.sdk.compat03.grpc.StreamResponse.PayloadCase getPayloadCase(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StringList.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StringList.java new file mode 100644 index 000000000..688a72984 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StringList.java @@ -0,0 +1,563 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            + * 
            + * + * Protobuf type {@code a2a.v1.StringList} + */ +@com.google.protobuf.Generated +public final class StringList extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.StringList) + StringListOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "StringList"); + } + // Use StringList.newBuilder() to construct. + private StringList(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private StringList() { + list_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_StringList_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_StringList_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.StringList.class, org.a2aproject.sdk.compat03.grpc.StringList.Builder.class); + } + + public static final int LIST_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private com.google.protobuf.LazyStringArrayList list_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + /** + * repeated string list = 1; + * @return A list containing the list. + */ + public com.google.protobuf.ProtocolStringList + getListList() { + return list_; + } + /** + * repeated string list = 1; + * @return The count of list. + */ + public int getListCount() { + return list_.size(); + } + /** + * repeated string list = 1; + * @param index The index of the element to return. + * @return The list at the given index. + */ + public java.lang.String getList(int index) { + return list_.get(index); + } + /** + * repeated string list = 1; + * @param index The index of the value to return. + * @return The bytes of the list at the given index. + */ + public com.google.protobuf.ByteString + getListBytes(int index) { + return list_.getByteString(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < list_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, list_.getRaw(i)); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + { + int dataSize = 0; + for (int i = 0; i < list_.size(); i++) { + dataSize += computeStringSizeNoTag(list_.getRaw(i)); + } + size += dataSize; + size += 1 * getListList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.StringList)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.StringList other = (org.a2aproject.sdk.compat03.grpc.StringList) obj; + + if (!getListList() + .equals(other.getListList())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getListCount() > 0) { + hash = (37 * hash) + LIST_FIELD_NUMBER; + hash = (53 * hash) + getListList().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.StringList parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.StringList parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.StringList parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.StringList prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * 
            + * + * Protobuf type {@code a2a.v1.StringList} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.StringList) + org.a2aproject.sdk.compat03.grpc.StringListOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_StringList_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_StringList_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.StringList.class, org.a2aproject.sdk.compat03.grpc.StringList.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.StringList.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + list_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_StringList_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StringList getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.StringList.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StringList build() { + org.a2aproject.sdk.compat03.grpc.StringList result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StringList buildPartial() { + org.a2aproject.sdk.compat03.grpc.StringList result = new org.a2aproject.sdk.compat03.grpc.StringList(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.StringList result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + list_.makeImmutable(); + result.list_ = list_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.StringList) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.StringList)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.StringList other) { + if (other == org.a2aproject.sdk.compat03.grpc.StringList.getDefaultInstance()) return this; + if (!other.list_.isEmpty()) { + if (list_.isEmpty()) { + list_ = other.list_; + bitField0_ |= 0x00000001; + } else { + ensureListIsMutable(); + list_.addAll(other.list_); + } + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + ensureListIsMutable(); + list_.add(s); + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private com.google.protobuf.LazyStringArrayList list_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + private void ensureListIsMutable() { + if (!list_.isModifiable()) { + list_ = new com.google.protobuf.LazyStringArrayList(list_); + } + bitField0_ |= 0x00000001; + } + /** + * repeated string list = 1; + * @return A list containing the list. + */ + public com.google.protobuf.ProtocolStringList + getListList() { + list_.makeImmutable(); + return list_; + } + /** + * repeated string list = 1; + * @return The count of list. + */ + public int getListCount() { + return list_.size(); + } + /** + * repeated string list = 1; + * @param index The index of the element to return. + * @return The list at the given index. + */ + public java.lang.String getList(int index) { + return list_.get(index); + } + /** + * repeated string list = 1; + * @param index The index of the value to return. + * @return The bytes of the list at the given index. + */ + public com.google.protobuf.ByteString + getListBytes(int index) { + return list_.getByteString(index); + } + /** + * repeated string list = 1; + * @param index The index to set the value at. + * @param value The list to set. + * @return This builder for chaining. + */ + public Builder setList( + int index, java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureListIsMutable(); + list_.set(index, value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * repeated string list = 1; + * @param value The list to add. + * @return This builder for chaining. + */ + public Builder addList( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + ensureListIsMutable(); + list_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * repeated string list = 1; + * @param values The list to add. + * @return This builder for chaining. + */ + public Builder addAllList( + java.lang.Iterable values) { + ensureListIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, list_); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * repeated string list = 1; + * @return This builder for chaining. + */ + public Builder clearList() { + list_ = + com.google.protobuf.LazyStringArrayList.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001);; + onChanged(); + return this; + } + /** + * repeated string list = 1; + * @param value The bytes of the list to add. + * @return This builder for chaining. + */ + public Builder addListBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + ensureListIsMutable(); + list_.add(value); + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.StringList) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.StringList) + private static final org.a2aproject.sdk.compat03.grpc.StringList DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.StringList(); + } + + public static org.a2aproject.sdk.compat03.grpc.StringList getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public StringList parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.StringList getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StringListOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StringListOrBuilder.java new file mode 100644 index 000000000..461eb119f --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/StringListOrBuilder.java @@ -0,0 +1,37 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface StringListOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.StringList) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated string list = 1; + * @return A list containing the list. + */ + java.util.List + getListList(); + /** + * repeated string list = 1; + * @return The count of list. + */ + int getListCount(); + /** + * repeated string list = 1; + * @param index The index of the element to return. + * @return The list at the given index. + */ + java.lang.String getList(int index); + /** + * repeated string list = 1; + * @param index The index of the value to return. + * @return The bytes of the list at the given index. + */ + com.google.protobuf.ByteString + getListBytes(int index); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Task.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Task.java new file mode 100644 index 000000000..25dc67af7 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/Task.java @@ -0,0 +1,2114 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * Task is the core unit of action for A2A. It has a current status
            + * and when results are created for the task they are stored in the
            + * artifact. If there are multiple turns for a task, these are stored in
            + * history.
            + * 
            + * + * Protobuf type {@code a2a.v1.Task} + */ +@com.google.protobuf.Generated +public final class Task extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.Task) + TaskOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "Task"); + } + // Use Task.newBuilder() to construct. + private Task(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Task() { + id_ = ""; + contextId_ = ""; + artifacts_ = java.util.Collections.emptyList(); + history_ = java.util.Collections.emptyList(); + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Task_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Task_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Task.class, org.a2aproject.sdk.compat03.grpc.Task.Builder.class); + } + + private int bitField0_; + public static final int ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object id_ = ""; + /** + *
            +   * Unique identifier for a task, created by the A2A server.
            +   * 
            + * + * string id = 1; + * @return The id. + */ + @java.lang.Override + public java.lang.String getId() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + *
            +   * Unique identifier for a task, created by the A2A server.
            +   * 
            + * + * string id = 1; + * @return The bytes for id. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CONTEXT_ID_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object contextId_ = ""; + /** + *
            +   * Unique identifier for the contextual collection of interactions (tasks
            +   * and messages). Created by the A2A server.
            +   * 
            + * + * string context_id = 2; + * @return The contextId. + */ + @java.lang.Override + public java.lang.String getContextId() { + java.lang.Object ref = contextId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + contextId_ = s; + return s; + } + } + /** + *
            +   * Unique identifier for the contextual collection of interactions (tasks
            +   * and messages). Created by the A2A server.
            +   * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getContextIdBytes() { + java.lang.Object ref = contextId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + contextId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int STATUS_FIELD_NUMBER = 3; + private org.a2aproject.sdk.compat03.grpc.TaskStatus status_; + /** + *
            +   * The current status of a Task, including state and a message.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return Whether the status field is set. + */ + @java.lang.Override + public boolean hasStatus() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * The current status of a Task, including state and a message.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return The status. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatus getStatus() { + return status_ == null ? org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance() : status_; + } + /** + *
            +   * The current status of a Task, including state and a message.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder getStatusOrBuilder() { + return status_ == null ? org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance() : status_; + } + + public static final int ARTIFACTS_FIELD_NUMBER = 4; + @SuppressWarnings("serial") + private java.util.List artifacts_; + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + @java.lang.Override + public java.util.List getArtifactsList() { + return artifacts_; + } + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + @java.lang.Override + public java.util.List + getArtifactsOrBuilderList() { + return artifacts_; + } + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + @java.lang.Override + public int getArtifactsCount() { + return artifacts_.size(); + } + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Artifact getArtifacts(int index) { + return artifacts_.get(index); + } + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder getArtifactsOrBuilder( + int index) { + return artifacts_.get(index); + } + + public static final int HISTORY_FIELD_NUMBER = 5; + @SuppressWarnings("serial") + private java.util.List history_; + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + @java.lang.Override + public java.util.List getHistoryList() { + return history_; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + @java.lang.Override + public java.util.List + getHistoryOrBuilderList() { + return history_; + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + @java.lang.Override + public int getHistoryCount() { + return history_.size(); + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getHistory(int index) { + return history_.get(index); + } + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getHistoryOrBuilder( + int index) { + return history_.get(index); + } + + public static final int METADATA_FIELD_NUMBER = 6; + private com.google.protobuf.Struct metadata_; + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * A key/value object to store custom metadata about a task.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + @java.lang.Override + public boolean hasMetadata() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * A key/value object to store custom metadata about a task.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + @java.lang.Override + public com.google.protobuf.Struct getMetadata() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * A key/value object to store custom metadata about a task.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(3, getStatus()); + } + for (int i = 0; i < artifacts_.size(); i++) { + output.writeMessage(4, artifacts_.get(i)); + } + for (int i = 0; i < history_.size(); i++) { + output.writeMessage(5, history_.get(i)); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(6, getMetadata()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getStatus()); + } + for (int i = 0; i < artifacts_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, artifacts_.get(i)); + } + for (int i = 0; i < history_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, history_.get(i)); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, getMetadata()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.Task)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.Task other = (org.a2aproject.sdk.compat03.grpc.Task) obj; + + if (!getId() + .equals(other.getId())) return false; + if (!getContextId() + .equals(other.getContextId())) return false; + if (hasStatus() != other.hasStatus()) return false; + if (hasStatus()) { + if (!getStatus() + .equals(other.getStatus())) return false; + } + if (!getArtifactsList() + .equals(other.getArtifactsList())) return false; + if (!getHistoryList() + .equals(other.getHistoryList())) return false; + if (hasMetadata() != other.hasMetadata()) return false; + if (hasMetadata()) { + if (!getMetadata() + .equals(other.getMetadata())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); + hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; + hash = (53 * hash) + getContextId().hashCode(); + if (hasStatus()) { + hash = (37 * hash) + STATUS_FIELD_NUMBER; + hash = (53 * hash) + getStatus().hashCode(); + } + if (getArtifactsCount() > 0) { + hash = (37 * hash) + ARTIFACTS_FIELD_NUMBER; + hash = (53 * hash) + getArtifactsList().hashCode(); + } + if (getHistoryCount() > 0) { + hash = (37 * hash) + HISTORY_FIELD_NUMBER; + hash = (53 * hash) + getHistoryList().hashCode(); + } + if (hasMetadata()) { + hash = (37 * hash) + METADATA_FIELD_NUMBER; + hash = (53 * hash) + getMetadata().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.Task parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.Task parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.Task parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.Task prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * Task is the core unit of action for A2A. It has a current status
            +   * and when results are created for the task they are stored in the
            +   * artifact. If there are multiple turns for a task, these are stored in
            +   * history.
            +   * 
            + * + * Protobuf type {@code a2a.v1.Task} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.Task) + org.a2aproject.sdk.compat03.grpc.TaskOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_Task_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_Task_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.Task.class, org.a2aproject.sdk.compat03.grpc.Task.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.Task.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetStatusFieldBuilder(); + internalGetArtifactsFieldBuilder(); + internalGetHistoryFieldBuilder(); + internalGetMetadataFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + id_ = ""; + contextId_ = ""; + status_ = null; + if (statusBuilder_ != null) { + statusBuilder_.dispose(); + statusBuilder_ = null; + } + if (artifactsBuilder_ == null) { + artifacts_ = java.util.Collections.emptyList(); + } else { + artifacts_ = null; + artifactsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); + if (historyBuilder_ == null) { + history_ = java.util.Collections.emptyList(); + } else { + history_ = null; + historyBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000010); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_Task_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Task getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Task build() { + org.a2aproject.sdk.compat03.grpc.Task result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Task buildPartial() { + org.a2aproject.sdk.compat03.grpc.Task result = new org.a2aproject.sdk.compat03.grpc.Task(this); + buildPartialRepeatedFields(result); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartialRepeatedFields(org.a2aproject.sdk.compat03.grpc.Task result) { + if (artifactsBuilder_ == null) { + if (((bitField0_ & 0x00000008) != 0)) { + artifacts_ = java.util.Collections.unmodifiableList(artifacts_); + bitField0_ = (bitField0_ & ~0x00000008); + } + result.artifacts_ = artifacts_; + } else { + result.artifacts_ = artifactsBuilder_.build(); + } + if (historyBuilder_ == null) { + if (((bitField0_ & 0x00000010) != 0)) { + history_ = java.util.Collections.unmodifiableList(history_); + bitField0_ = (bitField0_ & ~0x00000010); + } + result.history_ = history_; + } else { + result.history_ = historyBuilder_.build(); + } + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.Task result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.id_ = id_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.contextId_ = contextId_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000004) != 0)) { + result.status_ = statusBuilder_ == null + ? status_ + : statusBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000020) != 0)) { + result.metadata_ = metadataBuilder_ == null + ? metadata_ + : metadataBuilder_.build(); + to_bitField0_ |= 0x00000002; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.Task) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.Task)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.Task other) { + if (other == org.a2aproject.sdk.compat03.grpc.Task.getDefaultInstance()) return this; + if (!other.getId().isEmpty()) { + id_ = other.id_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getContextId().isEmpty()) { + contextId_ = other.contextId_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (other.hasStatus()) { + mergeStatus(other.getStatus()); + } + if (artifactsBuilder_ == null) { + if (!other.artifacts_.isEmpty()) { + if (artifacts_.isEmpty()) { + artifacts_ = other.artifacts_; + bitField0_ = (bitField0_ & ~0x00000008); + } else { + ensureArtifactsIsMutable(); + artifacts_.addAll(other.artifacts_); + } + onChanged(); + } + } else { + if (!other.artifacts_.isEmpty()) { + if (artifactsBuilder_.isEmpty()) { + artifactsBuilder_.dispose(); + artifactsBuilder_ = null; + artifacts_ = other.artifacts_; + bitField0_ = (bitField0_ & ~0x00000008); + artifactsBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetArtifactsFieldBuilder() : null; + } else { + artifactsBuilder_.addAllMessages(other.artifacts_); + } + } + } + if (historyBuilder_ == null) { + if (!other.history_.isEmpty()) { + if (history_.isEmpty()) { + history_ = other.history_; + bitField0_ = (bitField0_ & ~0x00000010); + } else { + ensureHistoryIsMutable(); + history_.addAll(other.history_); + } + onChanged(); + } + } else { + if (!other.history_.isEmpty()) { + if (historyBuilder_.isEmpty()) { + historyBuilder_.dispose(); + historyBuilder_ = null; + history_ = other.history_; + bitField0_ = (bitField0_ & ~0x00000010); + historyBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + internalGetHistoryFieldBuilder() : null; + } else { + historyBuilder_.addAllMessages(other.history_); + } + } + } + if (other.hasMetadata()) { + mergeMetadata(other.getMetadata()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + contextId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetStatusFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 34: { + org.a2aproject.sdk.compat03.grpc.Artifact m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.Artifact.parser(), + extensionRegistry); + if (artifactsBuilder_ == null) { + ensureArtifactsIsMutable(); + artifacts_.add(m); + } else { + artifactsBuilder_.addMessage(m); + } + break; + } // case 34 + case 42: { + org.a2aproject.sdk.compat03.grpc.Message m = + input.readMessage( + org.a2aproject.sdk.compat03.grpc.Message.parser(), + extensionRegistry); + if (historyBuilder_ == null) { + ensureHistoryIsMutable(); + history_.add(m); + } else { + historyBuilder_.addMessage(m); + } + break; + } // case 42 + case 50: { + input.readMessage( + internalGetMetadataFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000020; + break; + } // case 50 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object id_ = ""; + /** + *
            +     * Unique identifier for a task, created by the A2A server.
            +     * 
            + * + * string id = 1; + * @return The id. + */ + public java.lang.String getId() { + java.lang.Object ref = id_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Unique identifier for a task, created by the A2A server.
            +     * 
            + * + * string id = 1; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Unique identifier for a task, created by the A2A server.
            +     * 
            + * + * string id = 1; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * Unique identifier for a task, created by the A2A server.
            +     * 
            + * + * string id = 1; + * @return This builder for chaining. + */ + public Builder clearId() { + id_ = getDefaultInstance().getId(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * Unique identifier for a task, created by the A2A server.
            +     * 
            + * + * string id = 1; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object contextId_ = ""; + /** + *
            +     * Unique identifier for the contextual collection of interactions (tasks
            +     * and messages). Created by the A2A server.
            +     * 
            + * + * string context_id = 2; + * @return The contextId. + */ + public java.lang.String getContextId() { + java.lang.Object ref = contextId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + contextId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * Unique identifier for the contextual collection of interactions (tasks
            +     * and messages). Created by the A2A server.
            +     * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + public com.google.protobuf.ByteString + getContextIdBytes() { + java.lang.Object ref = contextId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + contextId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * Unique identifier for the contextual collection of interactions (tasks
            +     * and messages). Created by the A2A server.
            +     * 
            + * + * string context_id = 2; + * @param value The contextId to set. + * @return This builder for chaining. + */ + public Builder setContextId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + contextId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * Unique identifier for the contextual collection of interactions (tasks
            +     * and messages). Created by the A2A server.
            +     * 
            + * + * string context_id = 2; + * @return This builder for chaining. + */ + public Builder clearContextId() { + contextId_ = getDefaultInstance().getContextId(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * Unique identifier for the contextual collection of interactions (tasks
            +     * and messages). Created by the A2A server.
            +     * 
            + * + * string context_id = 2; + * @param value The bytes for contextId to set. + * @return This builder for chaining. + */ + public Builder setContextIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + contextId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.TaskStatus status_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatus, org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder> statusBuilder_; + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return Whether the status field is set. + */ + public boolean hasStatus() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return The status. + */ + public org.a2aproject.sdk.compat03.grpc.TaskStatus getStatus() { + if (statusBuilder_ == null) { + return status_ == null ? org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance() : status_; + } else { + return statusBuilder_.getMessage(); + } + } + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public Builder setStatus(org.a2aproject.sdk.compat03.grpc.TaskStatus value) { + if (statusBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + status_ = value; + } else { + statusBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public Builder setStatus( + org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder builderForValue) { + if (statusBuilder_ == null) { + status_ = builderForValue.build(); + } else { + statusBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public Builder mergeStatus(org.a2aproject.sdk.compat03.grpc.TaskStatus value) { + if (statusBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + status_ != null && + status_ != org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance()) { + getStatusBuilder().mergeFrom(value); + } else { + status_ = value; + } + } else { + statusBuilder_.mergeFrom(value); + } + if (status_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public Builder clearStatus() { + bitField0_ = (bitField0_ & ~0x00000004); + status_ = null; + if (statusBuilder_ != null) { + statusBuilder_.dispose(); + statusBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder getStatusBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return internalGetStatusFieldBuilder().getBuilder(); + } + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder getStatusOrBuilder() { + if (statusBuilder_ != null) { + return statusBuilder_.getMessageOrBuilder(); + } else { + return status_ == null ? + org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance() : status_; + } + } + /** + *
            +     * The current status of a Task, including state and a message.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatus, org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder> + internalGetStatusFieldBuilder() { + if (statusBuilder_ == null) { + statusBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatus, org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder>( + getStatus(), + getParentForChildren(), + isClean()); + status_ = null; + } + return statusBuilder_; + } + + private java.util.List artifacts_ = + java.util.Collections.emptyList(); + private void ensureArtifactsIsMutable() { + if (!((bitField0_ & 0x00000008) != 0)) { + artifacts_ = new java.util.ArrayList(artifacts_); + bitField0_ |= 0x00000008; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Artifact, org.a2aproject.sdk.compat03.grpc.Artifact.Builder, org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder> artifactsBuilder_; + + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public java.util.List getArtifactsList() { + if (artifactsBuilder_ == null) { + return java.util.Collections.unmodifiableList(artifacts_); + } else { + return artifactsBuilder_.getMessageList(); + } + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public int getArtifactsCount() { + if (artifactsBuilder_ == null) { + return artifacts_.size(); + } else { + return artifactsBuilder_.getCount(); + } + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public org.a2aproject.sdk.compat03.grpc.Artifact getArtifacts(int index) { + if (artifactsBuilder_ == null) { + return artifacts_.get(index); + } else { + return artifactsBuilder_.getMessage(index); + } + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder setArtifacts( + int index, org.a2aproject.sdk.compat03.grpc.Artifact value) { + if (artifactsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureArtifactsIsMutable(); + artifacts_.set(index, value); + onChanged(); + } else { + artifactsBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder setArtifacts( + int index, org.a2aproject.sdk.compat03.grpc.Artifact.Builder builderForValue) { + if (artifactsBuilder_ == null) { + ensureArtifactsIsMutable(); + artifacts_.set(index, builderForValue.build()); + onChanged(); + } else { + artifactsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder addArtifacts(org.a2aproject.sdk.compat03.grpc.Artifact value) { + if (artifactsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureArtifactsIsMutable(); + artifacts_.add(value); + onChanged(); + } else { + artifactsBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder addArtifacts( + int index, org.a2aproject.sdk.compat03.grpc.Artifact value) { + if (artifactsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureArtifactsIsMutable(); + artifacts_.add(index, value); + onChanged(); + } else { + artifactsBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder addArtifacts( + org.a2aproject.sdk.compat03.grpc.Artifact.Builder builderForValue) { + if (artifactsBuilder_ == null) { + ensureArtifactsIsMutable(); + artifacts_.add(builderForValue.build()); + onChanged(); + } else { + artifactsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder addArtifacts( + int index, org.a2aproject.sdk.compat03.grpc.Artifact.Builder builderForValue) { + if (artifactsBuilder_ == null) { + ensureArtifactsIsMutable(); + artifacts_.add(index, builderForValue.build()); + onChanged(); + } else { + artifactsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder addAllArtifacts( + java.lang.Iterable values) { + if (artifactsBuilder_ == null) { + ensureArtifactsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, artifacts_); + onChanged(); + } else { + artifactsBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder clearArtifacts() { + if (artifactsBuilder_ == null) { + artifacts_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + } else { + artifactsBuilder_.clear(); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public Builder removeArtifacts(int index) { + if (artifactsBuilder_ == null) { + ensureArtifactsIsMutable(); + artifacts_.remove(index); + onChanged(); + } else { + artifactsBuilder_.remove(index); + } + return this; + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public org.a2aproject.sdk.compat03.grpc.Artifact.Builder getArtifactsBuilder( + int index) { + return internalGetArtifactsFieldBuilder().getBuilder(index); + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder getArtifactsOrBuilder( + int index) { + if (artifactsBuilder_ == null) { + return artifacts_.get(index); } else { + return artifactsBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public java.util.List + getArtifactsOrBuilderList() { + if (artifactsBuilder_ != null) { + return artifactsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(artifacts_); + } + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public org.a2aproject.sdk.compat03.grpc.Artifact.Builder addArtifactsBuilder() { + return internalGetArtifactsFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance()); + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public org.a2aproject.sdk.compat03.grpc.Artifact.Builder addArtifactsBuilder( + int index) { + return internalGetArtifactsFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance()); + } + /** + *
            +     * A set of output artifacts for a Task.
            +     * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + public java.util.List + getArtifactsBuilderList() { + return internalGetArtifactsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Artifact, org.a2aproject.sdk.compat03.grpc.Artifact.Builder, org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder> + internalGetArtifactsFieldBuilder() { + if (artifactsBuilder_ == null) { + artifactsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Artifact, org.a2aproject.sdk.compat03.grpc.Artifact.Builder, org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder>( + artifacts_, + ((bitField0_ & 0x00000008) != 0), + getParentForChildren(), + isClean()); + artifacts_ = null; + } + return artifactsBuilder_; + } + + private java.util.List history_ = + java.util.Collections.emptyList(); + private void ensureHistoryIsMutable() { + if (!((bitField0_ & 0x00000010) != 0)) { + history_ = new java.util.ArrayList(history_); + bitField0_ |= 0x00000010; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> historyBuilder_; + + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public java.util.List getHistoryList() { + if (historyBuilder_ == null) { + return java.util.Collections.unmodifiableList(history_); + } else { + return historyBuilder_.getMessageList(); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public int getHistoryCount() { + if (historyBuilder_ == null) { + return history_.size(); + } else { + return historyBuilder_.getCount(); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Message getHistory(int index) { + if (historyBuilder_ == null) { + return history_.get(index); + } else { + return historyBuilder_.getMessage(index); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder setHistory( + int index, org.a2aproject.sdk.compat03.grpc.Message value) { + if (historyBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureHistoryIsMutable(); + history_.set(index, value); + onChanged(); + } else { + historyBuilder_.setMessage(index, value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder setHistory( + int index, org.a2aproject.sdk.compat03.grpc.Message.Builder builderForValue) { + if (historyBuilder_ == null) { + ensureHistoryIsMutable(); + history_.set(index, builderForValue.build()); + onChanged(); + } else { + historyBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder addHistory(org.a2aproject.sdk.compat03.grpc.Message value) { + if (historyBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureHistoryIsMutable(); + history_.add(value); + onChanged(); + } else { + historyBuilder_.addMessage(value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder addHistory( + int index, org.a2aproject.sdk.compat03.grpc.Message value) { + if (historyBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureHistoryIsMutable(); + history_.add(index, value); + onChanged(); + } else { + historyBuilder_.addMessage(index, value); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder addHistory( + org.a2aproject.sdk.compat03.grpc.Message.Builder builderForValue) { + if (historyBuilder_ == null) { + ensureHistoryIsMutable(); + history_.add(builderForValue.build()); + onChanged(); + } else { + historyBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder addHistory( + int index, org.a2aproject.sdk.compat03.grpc.Message.Builder builderForValue) { + if (historyBuilder_ == null) { + ensureHistoryIsMutable(); + history_.add(index, builderForValue.build()); + onChanged(); + } else { + historyBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder addAllHistory( + java.lang.Iterable values) { + if (historyBuilder_ == null) { + ensureHistoryIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, history_); + onChanged(); + } else { + historyBuilder_.addAllMessages(values); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder clearHistory() { + if (historyBuilder_ == null) { + history_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + } else { + historyBuilder_.clear(); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public Builder removeHistory(int index) { + if (historyBuilder_ == null) { + ensureHistoryIsMutable(); + history_.remove(index); + onChanged(); + } else { + historyBuilder_.remove(index); + } + return this; + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Message.Builder getHistoryBuilder( + int index) { + return internalGetHistoryFieldBuilder().getBuilder(index); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getHistoryOrBuilder( + int index) { + if (historyBuilder_ == null) { + return history_.get(index); } else { + return historyBuilder_.getMessageOrBuilder(index); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public java.util.List + getHistoryOrBuilderList() { + if (historyBuilder_ != null) { + return historyBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(history_); + } + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Message.Builder addHistoryBuilder() { + return internalGetHistoryFieldBuilder().addBuilder( + org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance()); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public org.a2aproject.sdk.compat03.grpc.Message.Builder addHistoryBuilder( + int index) { + return internalGetHistoryFieldBuilder().addBuilder( + index, org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance()); + } + /** + *
            +     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +     * The history of interactions from a task.
            +     * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + public java.util.List + getHistoryBuilderList() { + return internalGetHistoryFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> + internalGetHistoryFieldBuilder() { + if (historyBuilder_ == null) { + historyBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder>( + history_, + ((bitField0_ & 0x00000010) != 0), + getParentForChildren(), + isClean()); + history_ = null; + } + return historyBuilder_; + } + + private com.google.protobuf.Struct metadata_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + public boolean hasMetadata() { + return ((bitField0_ & 0x00000020) != 0); + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + public com.google.protobuf.Struct getMetadata() { + if (metadataBuilder_ == null) { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } else { + return metadataBuilder_.getMessage(); + } + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder setMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + metadata_ = value; + } else { + metadataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder setMetadata( + com.google.protobuf.Struct.Builder builderForValue) { + if (metadataBuilder_ == null) { + metadata_ = builderForValue.build(); + } else { + metadataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder mergeMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0) && + metadata_ != null && + metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { + getMetadataBuilder().mergeFrom(value); + } else { + metadata_ = value; + } + } else { + metadataBuilder_.mergeFrom(value); + } + if (metadata_ != null) { + bitField0_ |= 0x00000020; + onChanged(); + } + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder clearMetadata() { + bitField0_ = (bitField0_ & ~0x00000020); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public com.google.protobuf.Struct.Builder getMetadataBuilder() { + bitField0_ |= 0x00000020; + onChanged(); + return internalGetMetadataFieldBuilder().getBuilder(); + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + if (metadataBuilder_ != null) { + return metadataBuilder_.getMessageOrBuilder(); + } else { + return metadata_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + } + /** + *
            +     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +     * A key/value object to store custom metadata about a task.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetMetadataFieldBuilder() { + if (metadataBuilder_ == null) { + metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getMetadata(), + getParentForChildren(), + isClean()); + metadata_ = null; + } + return metadataBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.Task) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.Task) + private static final org.a2aproject.sdk.compat03.grpc.Task DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.Task(); + } + + public static org.a2aproject.sdk.compat03.grpc.Task getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Task parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Task getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskArtifactUpdateEvent.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskArtifactUpdateEvent.java new file mode 100644 index 000000000..a145eca7b --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskArtifactUpdateEvent.java @@ -0,0 +1,1344 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * TaskArtifactUpdateEvent represents a task delta where an artifact has
            + * been generated.
            + * 
            + * + * Protobuf type {@code a2a.v1.TaskArtifactUpdateEvent} + */ +@com.google.protobuf.Generated +public final class TaskArtifactUpdateEvent extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.TaskArtifactUpdateEvent) + TaskArtifactUpdateEventOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "TaskArtifactUpdateEvent"); + } + // Use TaskArtifactUpdateEvent.newBuilder() to construct. + private TaskArtifactUpdateEvent(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private TaskArtifactUpdateEvent() { + taskId_ = ""; + contextId_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.class, org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder.class); + } + + private int bitField0_; + public static final int TASK_ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object taskId_ = ""; + /** + *
            +   * The id of the task for this artifact
            +   * 
            + * + * string task_id = 1; + * @return The taskId. + */ + @java.lang.Override + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + taskId_ = s; + return s; + } + } + /** + *
            +   * The id of the task for this artifact
            +   * 
            + * + * string task_id = 1; + * @return The bytes for taskId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTaskIdBytes() { + java.lang.Object ref = taskId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CONTEXT_ID_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object contextId_ = ""; + /** + *
            +   * The id of the context that this task belongs too
            +   * 
            + * + * string context_id = 2; + * @return The contextId. + */ + @java.lang.Override + public java.lang.String getContextId() { + java.lang.Object ref = contextId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + contextId_ = s; + return s; + } + } + /** + *
            +   * The id of the context that this task belongs too
            +   * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getContextIdBytes() { + java.lang.Object ref = contextId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + contextId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int ARTIFACT_FIELD_NUMBER = 3; + private org.a2aproject.sdk.compat03.grpc.Artifact artifact_; + /** + *
            +   * The artifact itself
            +   * 
            + * + * .a2a.v1.Artifact artifact = 3; + * @return Whether the artifact field is set. + */ + @java.lang.Override + public boolean hasArtifact() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * The artifact itself
            +   * 
            + * + * .a2a.v1.Artifact artifact = 3; + * @return The artifact. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Artifact getArtifact() { + return artifact_ == null ? org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance() : artifact_; + } + /** + *
            +   * The artifact itself
            +   * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder getArtifactOrBuilder() { + return artifact_ == null ? org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance() : artifact_; + } + + public static final int APPEND_FIELD_NUMBER = 4; + private boolean append_ = false; + /** + *
            +   * Whether this should be appended to a prior one produced
            +   * 
            + * + * bool append = 4; + * @return The append. + */ + @java.lang.Override + public boolean getAppend() { + return append_; + } + + public static final int LAST_CHUNK_FIELD_NUMBER = 5; + private boolean lastChunk_ = false; + /** + *
            +   * Whether this represents the last part of an artifact
            +   * 
            + * + * bool last_chunk = 5; + * @return The lastChunk. + */ + @java.lang.Override + public boolean getLastChunk() { + return lastChunk_; + } + + public static final int METADATA_FIELD_NUMBER = 6; + private com.google.protobuf.Struct metadata_; + /** + *
            +   * Optional metadata associated with the artifact update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + @java.lang.Override + public boolean hasMetadata() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
            +   * Optional metadata associated with the artifact update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + @java.lang.Override + public com.google.protobuf.Struct getMetadata() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + /** + *
            +   * Optional metadata associated with the artifact update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(3, getArtifact()); + } + if (append_ != false) { + output.writeBool(4, append_); + } + if (lastChunk_ != false) { + output.writeBool(5, lastChunk_); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(6, getMetadata()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getArtifact()); + } + if (append_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(4, append_); + } + if (lastChunk_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(5, lastChunk_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, getMetadata()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent other = (org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) obj; + + if (!getTaskId() + .equals(other.getTaskId())) return false; + if (!getContextId() + .equals(other.getContextId())) return false; + if (hasArtifact() != other.hasArtifact()) return false; + if (hasArtifact()) { + if (!getArtifact() + .equals(other.getArtifact())) return false; + } + if (getAppend() + != other.getAppend()) return false; + if (getLastChunk() + != other.getLastChunk()) return false; + if (hasMetadata() != other.hasMetadata()) return false; + if (hasMetadata()) { + if (!getMetadata() + .equals(other.getMetadata())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + TASK_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskId().hashCode(); + hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; + hash = (53 * hash) + getContextId().hashCode(); + if (hasArtifact()) { + hash = (37 * hash) + ARTIFACT_FIELD_NUMBER; + hash = (53 * hash) + getArtifact().hashCode(); + } + hash = (37 * hash) + APPEND_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getAppend()); + hash = (37 * hash) + LAST_CHUNK_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getLastChunk()); + if (hasMetadata()) { + hash = (37 * hash) + METADATA_FIELD_NUMBER; + hash = (53 * hash) + getMetadata().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * TaskArtifactUpdateEvent represents a task delta where an artifact has
            +   * been generated.
            +   * 
            + * + * Protobuf type {@code a2a.v1.TaskArtifactUpdateEvent} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.TaskArtifactUpdateEvent) + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEventOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.class, org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetArtifactFieldBuilder(); + internalGetMetadataFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + taskId_ = ""; + contextId_ = ""; + artifact_ = null; + if (artifactBuilder_ != null) { + artifactBuilder_.dispose(); + artifactBuilder_ = null; + } + append_ = false; + lastChunk_ = false; + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent build() { + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent buildPartial() { + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent result = new org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.taskId_ = taskId_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.contextId_ = contextId_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000004) != 0)) { + result.artifact_ = artifactBuilder_ == null + ? artifact_ + : artifactBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.append_ = append_; + } + if (((from_bitField0_ & 0x00000010) != 0)) { + result.lastChunk_ = lastChunk_; + } + if (((from_bitField0_ & 0x00000020) != 0)) { + result.metadata_ = metadataBuilder_ == null + ? metadata_ + : metadataBuilder_.build(); + to_bitField0_ |= 0x00000002; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent other) { + if (other == org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.getDefaultInstance()) return this; + if (!other.getTaskId().isEmpty()) { + taskId_ = other.taskId_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getContextId().isEmpty()) { + contextId_ = other.contextId_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (other.hasArtifact()) { + mergeArtifact(other.getArtifact()); + } + if (other.getAppend() != false) { + setAppend(other.getAppend()); + } + if (other.getLastChunk() != false) { + setLastChunk(other.getLastChunk()); + } + if (other.hasMetadata()) { + mergeMetadata(other.getMetadata()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + contextId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetArtifactFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 32: { + append_ = input.readBool(); + bitField0_ |= 0x00000008; + break; + } // case 32 + case 40: { + lastChunk_ = input.readBool(); + bitField0_ |= 0x00000010; + break; + } // case 40 + case 50: { + input.readMessage( + internalGetMetadataFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000020; + break; + } // case 50 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object taskId_ = ""; + /** + *
            +     * The id of the task for this artifact
            +     * 
            + * + * string task_id = 1; + * @return The taskId. + */ + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + taskId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The id of the task for this artifact
            +     * 
            + * + * string task_id = 1; + * @return The bytes for taskId. + */ + public com.google.protobuf.ByteString + getTaskIdBytes() { + java.lang.Object ref = taskId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The id of the task for this artifact
            +     * 
            + * + * string task_id = 1; + * @param value The taskId to set. + * @return This builder for chaining. + */ + public Builder setTaskId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + taskId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The id of the task for this artifact
            +     * 
            + * + * string task_id = 1; + * @return This builder for chaining. + */ + public Builder clearTaskId() { + taskId_ = getDefaultInstance().getTaskId(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The id of the task for this artifact
            +     * 
            + * + * string task_id = 1; + * @param value The bytes for taskId to set. + * @return This builder for chaining. + */ + public Builder setTaskIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + taskId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object contextId_ = ""; + /** + *
            +     * The id of the context that this task belongs too
            +     * 
            + * + * string context_id = 2; + * @return The contextId. + */ + public java.lang.String getContextId() { + java.lang.Object ref = contextId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + contextId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The id of the context that this task belongs too
            +     * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + public com.google.protobuf.ByteString + getContextIdBytes() { + java.lang.Object ref = contextId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + contextId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The id of the context that this task belongs too
            +     * 
            + * + * string context_id = 2; + * @param value The contextId to set. + * @return This builder for chaining. + */ + public Builder setContextId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + contextId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The id of the context that this task belongs too
            +     * 
            + * + * string context_id = 2; + * @return This builder for chaining. + */ + public Builder clearContextId() { + contextId_ = getDefaultInstance().getContextId(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The id of the context that this task belongs too
            +     * 
            + * + * string context_id = 2; + * @param value The bytes for contextId to set. + * @return This builder for chaining. + */ + public Builder setContextIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + contextId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.Artifact artifact_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Artifact, org.a2aproject.sdk.compat03.grpc.Artifact.Builder, org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder> artifactBuilder_; + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + * @return Whether the artifact field is set. + */ + public boolean hasArtifact() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + * @return The artifact. + */ + public org.a2aproject.sdk.compat03.grpc.Artifact getArtifact() { + if (artifactBuilder_ == null) { + return artifact_ == null ? org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance() : artifact_; + } else { + return artifactBuilder_.getMessage(); + } + } + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + public Builder setArtifact(org.a2aproject.sdk.compat03.grpc.Artifact value) { + if (artifactBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + artifact_ = value; + } else { + artifactBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + public Builder setArtifact( + org.a2aproject.sdk.compat03.grpc.Artifact.Builder builderForValue) { + if (artifactBuilder_ == null) { + artifact_ = builderForValue.build(); + } else { + artifactBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + public Builder mergeArtifact(org.a2aproject.sdk.compat03.grpc.Artifact value) { + if (artifactBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + artifact_ != null && + artifact_ != org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance()) { + getArtifactBuilder().mergeFrom(value); + } else { + artifact_ = value; + } + } else { + artifactBuilder_.mergeFrom(value); + } + if (artifact_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + public Builder clearArtifact() { + bitField0_ = (bitField0_ & ~0x00000004); + artifact_ = null; + if (artifactBuilder_ != null) { + artifactBuilder_.dispose(); + artifactBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + public org.a2aproject.sdk.compat03.grpc.Artifact.Builder getArtifactBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return internalGetArtifactFieldBuilder().getBuilder(); + } + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + public org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder getArtifactOrBuilder() { + if (artifactBuilder_ != null) { + return artifactBuilder_.getMessageOrBuilder(); + } else { + return artifact_ == null ? + org.a2aproject.sdk.compat03.grpc.Artifact.getDefaultInstance() : artifact_; + } + } + /** + *
            +     * The artifact itself
            +     * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Artifact, org.a2aproject.sdk.compat03.grpc.Artifact.Builder, org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder> + internalGetArtifactFieldBuilder() { + if (artifactBuilder_ == null) { + artifactBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Artifact, org.a2aproject.sdk.compat03.grpc.Artifact.Builder, org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder>( + getArtifact(), + getParentForChildren(), + isClean()); + artifact_ = null; + } + return artifactBuilder_; + } + + private boolean append_ ; + /** + *
            +     * Whether this should be appended to a prior one produced
            +     * 
            + * + * bool append = 4; + * @return The append. + */ + @java.lang.Override + public boolean getAppend() { + return append_; + } + /** + *
            +     * Whether this should be appended to a prior one produced
            +     * 
            + * + * bool append = 4; + * @param value The append to set. + * @return This builder for chaining. + */ + public Builder setAppend(boolean value) { + + append_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * Whether this should be appended to a prior one produced
            +     * 
            + * + * bool append = 4; + * @return This builder for chaining. + */ + public Builder clearAppend() { + bitField0_ = (bitField0_ & ~0x00000008); + append_ = false; + onChanged(); + return this; + } + + private boolean lastChunk_ ; + /** + *
            +     * Whether this represents the last part of an artifact
            +     * 
            + * + * bool last_chunk = 5; + * @return The lastChunk. + */ + @java.lang.Override + public boolean getLastChunk() { + return lastChunk_; + } + /** + *
            +     * Whether this represents the last part of an artifact
            +     * 
            + * + * bool last_chunk = 5; + * @param value The lastChunk to set. + * @return This builder for chaining. + */ + public Builder setLastChunk(boolean value) { + + lastChunk_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * Whether this represents the last part of an artifact
            +     * 
            + * + * bool last_chunk = 5; + * @return This builder for chaining. + */ + public Builder clearLastChunk() { + bitField0_ = (bitField0_ & ~0x00000010); + lastChunk_ = false; + onChanged(); + return this; + } + + private com.google.protobuf.Struct metadata_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + public boolean hasMetadata() { + return ((bitField0_ & 0x00000020) != 0); + } + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + public com.google.protobuf.Struct getMetadata() { + if (metadataBuilder_ == null) { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } else { + return metadataBuilder_.getMessage(); + } + } + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder setMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + metadata_ = value; + } else { + metadataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder setMetadata( + com.google.protobuf.Struct.Builder builderForValue) { + if (metadataBuilder_ == null) { + metadata_ = builderForValue.build(); + } else { + metadataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder mergeMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0) && + metadata_ != null && + metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { + getMetadataBuilder().mergeFrom(value); + } else { + metadata_ = value; + } + } else { + metadataBuilder_.mergeFrom(value); + } + if (metadata_ != null) { + bitField0_ |= 0x00000020; + onChanged(); + } + return this; + } + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public Builder clearMetadata() { + bitField0_ = (bitField0_ & ~0x00000020); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public com.google.protobuf.Struct.Builder getMetadataBuilder() { + bitField0_ |= 0x00000020; + onChanged(); + return internalGetMetadataFieldBuilder().getBuilder(); + } + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + if (metadataBuilder_ != null) { + return metadataBuilder_.getMessageOrBuilder(); + } else { + return metadata_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + } + /** + *
            +     * Optional metadata associated with the artifact update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetMetadataFieldBuilder() { + if (metadataBuilder_ == null) { + metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getMetadata(), + getParentForChildren(), + isClean()); + metadata_ = null; + } + return metadataBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.TaskArtifactUpdateEvent) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.TaskArtifactUpdateEvent) + private static final org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent(); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TaskArtifactUpdateEvent parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskArtifactUpdateEventOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskArtifactUpdateEventOrBuilder.java new file mode 100644 index 000000000..9abdfe8dd --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskArtifactUpdateEventOrBuilder.java @@ -0,0 +1,126 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface TaskArtifactUpdateEventOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.TaskArtifactUpdateEvent) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The id of the task for this artifact
            +   * 
            + * + * string task_id = 1; + * @return The taskId. + */ + java.lang.String getTaskId(); + /** + *
            +   * The id of the task for this artifact
            +   * 
            + * + * string task_id = 1; + * @return The bytes for taskId. + */ + com.google.protobuf.ByteString + getTaskIdBytes(); + + /** + *
            +   * The id of the context that this task belongs too
            +   * 
            + * + * string context_id = 2; + * @return The contextId. + */ + java.lang.String getContextId(); + /** + *
            +   * The id of the context that this task belongs too
            +   * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + com.google.protobuf.ByteString + getContextIdBytes(); + + /** + *
            +   * The artifact itself
            +   * 
            + * + * .a2a.v1.Artifact artifact = 3; + * @return Whether the artifact field is set. + */ + boolean hasArtifact(); + /** + *
            +   * The artifact itself
            +   * 
            + * + * .a2a.v1.Artifact artifact = 3; + * @return The artifact. + */ + org.a2aproject.sdk.compat03.grpc.Artifact getArtifact(); + /** + *
            +   * The artifact itself
            +   * 
            + * + * .a2a.v1.Artifact artifact = 3; + */ + org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder getArtifactOrBuilder(); + + /** + *
            +   * Whether this should be appended to a prior one produced
            +   * 
            + * + * bool append = 4; + * @return The append. + */ + boolean getAppend(); + + /** + *
            +   * Whether this represents the last part of an artifact
            +   * 
            + * + * bool last_chunk = 5; + * @return The lastChunk. + */ + boolean getLastChunk(); + + /** + *
            +   * Optional metadata associated with the artifact update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + boolean hasMetadata(); + /** + *
            +   * Optional metadata associated with the artifact update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + com.google.protobuf.Struct getMetadata(); + /** + *
            +   * Optional metadata associated with the artifact update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskOrBuilder.java new file mode 100644 index 000000000..ee239d12c --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskOrBuilder.java @@ -0,0 +1,204 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface TaskOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.Task) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * Unique identifier for a task, created by the A2A server.
            +   * 
            + * + * string id = 1; + * @return The id. + */ + java.lang.String getId(); + /** + *
            +   * Unique identifier for a task, created by the A2A server.
            +   * 
            + * + * string id = 1; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); + + /** + *
            +   * Unique identifier for the contextual collection of interactions (tasks
            +   * and messages). Created by the A2A server.
            +   * 
            + * + * string context_id = 2; + * @return The contextId. + */ + java.lang.String getContextId(); + /** + *
            +   * Unique identifier for the contextual collection of interactions (tasks
            +   * and messages). Created by the A2A server.
            +   * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + com.google.protobuf.ByteString + getContextIdBytes(); + + /** + *
            +   * The current status of a Task, including state and a message.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return Whether the status field is set. + */ + boolean hasStatus(); + /** + *
            +   * The current status of a Task, including state and a message.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return The status. + */ + org.a2aproject.sdk.compat03.grpc.TaskStatus getStatus(); + /** + *
            +   * The current status of a Task, including state and a message.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder getStatusOrBuilder(); + + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + java.util.List + getArtifactsList(); + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + org.a2aproject.sdk.compat03.grpc.Artifact getArtifacts(int index); + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + int getArtifactsCount(); + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + java.util.List + getArtifactsOrBuilderList(); + /** + *
            +   * A set of output artifacts for a Task.
            +   * 
            + * + * repeated .a2a.v1.Artifact artifacts = 4; + */ + org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder getArtifactsOrBuilder( + int index); + + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + java.util.List + getHistoryList(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + org.a2aproject.sdk.compat03.grpc.Message getHistory(int index); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + int getHistoryCount(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + java.util.List + getHistoryOrBuilderList(); + /** + *
            +   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
            +   * The history of interactions from a task.
            +   * 
            + * + * repeated .a2a.v1.Message history = 5; + */ + org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getHistoryOrBuilder( + int index); + + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * A key/value object to store custom metadata about a task.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return Whether the metadata field is set. + */ + boolean hasMetadata(); + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * A key/value object to store custom metadata about a task.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + * @return The metadata. + */ + com.google.protobuf.Struct getMetadata(); + /** + *
            +   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
            +   * A key/value object to store custom metadata about a task.
            +   * 
            + * + * .google.protobuf.Struct metadata = 6; + */ + com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskPushNotificationConfig.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskPushNotificationConfig.java new file mode 100644 index 000000000..85691f7ca --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskPushNotificationConfig.java @@ -0,0 +1,723 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.TaskPushNotificationConfig} + */ +@com.google.protobuf.Generated +public final class TaskPushNotificationConfig extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.TaskPushNotificationConfig) + TaskPushNotificationConfigOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "TaskPushNotificationConfig"); + } + // Use TaskPushNotificationConfig.newBuilder() to construct. + private TaskPushNotificationConfig(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private TaskPushNotificationConfig() { + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.class, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder.class); + } + + private int bitField0_; + public static final int NAME_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 2; + private org.a2aproject.sdk.compat03.grpc.PushNotificationConfig pushNotificationConfig_; + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * @return Whether the pushNotificationConfig field is set. + */ + @java.lang.Override + public boolean hasPushNotificationConfig() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * @return The pushNotificationConfig. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getPushNotificationConfig() { + return pushNotificationConfig_ == null ? org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { + return pushNotificationConfig_ == null ? org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(2, getPushNotificationConfig()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getPushNotificationConfig()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig other = (org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig) obj; + + if (!getName() + .equals(other.getName())) return false; + if (hasPushNotificationConfig() != other.hasPushNotificationConfig()) return false; + if (hasPushNotificationConfig()) { + if (!getPushNotificationConfig() + .equals(other.getPushNotificationConfig())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + if (hasPushNotificationConfig()) { + hash = (37 * hash) + PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER; + hash = (53 * hash) + getPushNotificationConfig().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.TaskPushNotificationConfig} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.TaskPushNotificationConfig) + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.class, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetPushNotificationConfigFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + name_ = ""; + pushNotificationConfig_ = null; + if (pushNotificationConfigBuilder_ != null) { + pushNotificationConfigBuilder_.dispose(); + pushNotificationConfigBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig build() { + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig buildPartial() { + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig result = new org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.name_ = name_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000002) != 0)) { + result.pushNotificationConfig_ = pushNotificationConfigBuilder_ == null + ? pushNotificationConfig_ + : pushNotificationConfigBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig other) { + if (other == org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (other.hasPushNotificationConfig()) { + mergePushNotificationConfig(other.getPushNotificationConfig()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + input.readMessage( + internalGetPushNotificationConfigFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000002; + break; + } // case 18 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{id}
            +     * 
            + * + * string name = 1; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{id}
            +     * 
            + * + * string name = 1; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{id}
            +     * 
            + * + * string name = 1; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{id}
            +     * 
            + * + * string name = 1; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}/pushNotificationConfigs/{id}
            +     * 
            + * + * string name = 1; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.PushNotificationConfig pushNotificationConfig_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig, org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder> pushNotificationConfigBuilder_; + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * @return Whether the pushNotificationConfig field is set. + */ + public boolean hasPushNotificationConfig() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * @return The pushNotificationConfig. + */ + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getPushNotificationConfig() { + if (pushNotificationConfigBuilder_ == null) { + return pushNotificationConfig_ == null ? org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + } else { + return pushNotificationConfigBuilder_.getMessage(); + } + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + public Builder setPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.PushNotificationConfig value) { + if (pushNotificationConfigBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + pushNotificationConfig_ = value; + } else { + pushNotificationConfigBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + public Builder setPushNotificationConfig( + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder builderForValue) { + if (pushNotificationConfigBuilder_ == null) { + pushNotificationConfig_ = builderForValue.build(); + } else { + pushNotificationConfigBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + public Builder mergePushNotificationConfig(org.a2aproject.sdk.compat03.grpc.PushNotificationConfig value) { + if (pushNotificationConfigBuilder_ == null) { + if (((bitField0_ & 0x00000002) != 0) && + pushNotificationConfig_ != null && + pushNotificationConfig_ != org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance()) { + getPushNotificationConfigBuilder().mergeFrom(value); + } else { + pushNotificationConfig_ = value; + } + } else { + pushNotificationConfigBuilder_.mergeFrom(value); + } + if (pushNotificationConfig_ != null) { + bitField0_ |= 0x00000002; + onChanged(); + } + return this; + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + public Builder clearPushNotificationConfig() { + bitField0_ = (bitField0_ & ~0x00000002); + pushNotificationConfig_ = null; + if (pushNotificationConfigBuilder_ != null) { + pushNotificationConfigBuilder_.dispose(); + pushNotificationConfigBuilder_ = null; + } + onChanged(); + return this; + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return internalGetPushNotificationConfigFieldBuilder().getBuilder(); + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + public org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { + if (pushNotificationConfigBuilder_ != null) { + return pushNotificationConfigBuilder_.getMessageOrBuilder(); + } else { + return pushNotificationConfig_ == null ? + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; + } + } + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig, org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder> + internalGetPushNotificationConfigFieldBuilder() { + if (pushNotificationConfigBuilder_ == null) { + pushNotificationConfigBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig, org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder, org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder>( + getPushNotificationConfig(), + getParentForChildren(), + isClean()); + pushNotificationConfig_ = null; + } + return pushNotificationConfigBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.TaskPushNotificationConfig) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.TaskPushNotificationConfig) + private static final org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig(); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TaskPushNotificationConfig parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskPushNotificationConfigOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskPushNotificationConfigOrBuilder.java new file mode 100644 index 000000000..3320be16c --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskPushNotificationConfigOrBuilder.java @@ -0,0 +1,47 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface TaskPushNotificationConfigOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.TaskPushNotificationConfig) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * name=tasks/{id}/pushNotificationConfigs/{id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * @return Whether the pushNotificationConfig field is set. + */ + boolean hasPushNotificationConfig(); + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + * @return The pushNotificationConfig. + */ + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig getPushNotificationConfig(); + /** + * .a2a.v1.PushNotificationConfig push_notification_config = 2; + */ + org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskState.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskState.java new file mode 100644 index 000000000..57e21b3d7 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskState.java @@ -0,0 +1,268 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * The set of states a Task can be in.
            + * 
            + * + * Protobuf enum {@code a2a.v1.TaskState} + */ +@com.google.protobuf.Generated +public enum TaskState + implements com.google.protobuf.ProtocolMessageEnum { + /** + * TASK_STATE_UNSPECIFIED = 0; + */ + TASK_STATE_UNSPECIFIED(0), + /** + *
            +   * Represents the status that acknowledges a task is created
            +   * 
            + * + * TASK_STATE_SUBMITTED = 1; + */ + TASK_STATE_SUBMITTED(1), + /** + *
            +   * Represents the status that a task is actively being processed
            +   * 
            + * + * TASK_STATE_WORKING = 2; + */ + TASK_STATE_WORKING(2), + /** + *
            +   * Represents the status a task is finished. This is a terminal state
            +   * 
            + * + * TASK_STATE_COMPLETED = 3; + */ + TASK_STATE_COMPLETED(3), + /** + *
            +   * Represents the status a task is done but failed. This is a terminal state
            +   * 
            + * + * TASK_STATE_FAILED = 4; + */ + TASK_STATE_FAILED(4), + /** + *
            +   * Represents the status a task was cancelled before it finished.
            +   * This is a terminal state.
            +   * 
            + * + * TASK_STATE_CANCELLED = 5; + */ + TASK_STATE_CANCELLED(5), + /** + *
            +   * Represents the status that the task requires information to complete.
            +   * This is an interrupted state.
            +   * 
            + * + * TASK_STATE_INPUT_REQUIRED = 6; + */ + TASK_STATE_INPUT_REQUIRED(6), + /** + *
            +   * Represents the status that the agent has decided to not perform the task.
            +   * This may be done during initial task creation or later once an agent
            +   * has determined it can't or won't proceed. This is a terminal state.
            +   * 
            + * + * TASK_STATE_REJECTED = 7; + */ + TASK_STATE_REJECTED(7), + /** + *
            +   * Represents the state that some authentication is needed from the upstream
            +   * client. Authentication is expected to come out-of-band thus this is not
            +   * an interrupted or terminal state.
            +   * 
            + * + * TASK_STATE_AUTH_REQUIRED = 8; + */ + TASK_STATE_AUTH_REQUIRED(8), + UNRECOGNIZED(-1), + ; + + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "TaskState"); + } + /** + * TASK_STATE_UNSPECIFIED = 0; + */ + public static final int TASK_STATE_UNSPECIFIED_VALUE = 0; + /** + *
            +   * Represents the status that acknowledges a task is created
            +   * 
            + * + * TASK_STATE_SUBMITTED = 1; + */ + public static final int TASK_STATE_SUBMITTED_VALUE = 1; + /** + *
            +   * Represents the status that a task is actively being processed
            +   * 
            + * + * TASK_STATE_WORKING = 2; + */ + public static final int TASK_STATE_WORKING_VALUE = 2; + /** + *
            +   * Represents the status a task is finished. This is a terminal state
            +   * 
            + * + * TASK_STATE_COMPLETED = 3; + */ + public static final int TASK_STATE_COMPLETED_VALUE = 3; + /** + *
            +   * Represents the status a task is done but failed. This is a terminal state
            +   * 
            + * + * TASK_STATE_FAILED = 4; + */ + public static final int TASK_STATE_FAILED_VALUE = 4; + /** + *
            +   * Represents the status a task was cancelled before it finished.
            +   * This is a terminal state.
            +   * 
            + * + * TASK_STATE_CANCELLED = 5; + */ + public static final int TASK_STATE_CANCELLED_VALUE = 5; + /** + *
            +   * Represents the status that the task requires information to complete.
            +   * This is an interrupted state.
            +   * 
            + * + * TASK_STATE_INPUT_REQUIRED = 6; + */ + public static final int TASK_STATE_INPUT_REQUIRED_VALUE = 6; + /** + *
            +   * Represents the status that the agent has decided to not perform the task.
            +   * This may be done during initial task creation or later once an agent
            +   * has determined it can't or won't proceed. This is a terminal state.
            +   * 
            + * + * TASK_STATE_REJECTED = 7; + */ + public static final int TASK_STATE_REJECTED_VALUE = 7; + /** + *
            +   * Represents the state that some authentication is needed from the upstream
            +   * client. Authentication is expected to come out-of-band thus this is not
            +   * an interrupted or terminal state.
            +   * 
            + * + * TASK_STATE_AUTH_REQUIRED = 8; + */ + public static final int TASK_STATE_AUTH_REQUIRED_VALUE = 8; + + + public final int getNumber() { + if (this == UNRECOGNIZED) { + throw new java.lang.IllegalArgumentException( + "Can't get the number of an unknown enum value."); + } + return value; + } + + /** + * @param value The numeric wire value of the corresponding enum entry. + * @return The enum associated with the given numeric wire value. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static TaskState valueOf(int value) { + return forNumber(value); + } + + /** + * @param value The numeric wire value of the corresponding enum entry. + * @return The enum associated with the given numeric wire value. + */ + public static TaskState forNumber(int value) { + switch (value) { + case 0: return TASK_STATE_UNSPECIFIED; + case 1: return TASK_STATE_SUBMITTED; + case 2: return TASK_STATE_WORKING; + case 3: return TASK_STATE_COMPLETED; + case 4: return TASK_STATE_FAILED; + case 5: return TASK_STATE_CANCELLED; + case 6: return TASK_STATE_INPUT_REQUIRED; + case 7: return TASK_STATE_REJECTED; + case 8: return TASK_STATE_AUTH_REQUIRED; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + TaskState> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public TaskState findValueByNumber(int number) { + return TaskState.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + if (this == UNRECOGNIZED) { + throw new java.lang.IllegalStateException( + "Can't get the descriptor of an unrecognized enum value."); + } + return getDescriptor().getValues().get(ordinal()); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return A2A.getDescriptor().getEnumTypes().get(0); + } + + private static final TaskState[] VALUES = values(); + + public static TaskState valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private TaskState(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:a2a.v1.TaskState) +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatus.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatus.java new file mode 100644 index 000000000..0d63d5502 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatus.java @@ -0,0 +1,980 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * A container for the status of a task
            + * 
            + * + * Protobuf type {@code a2a.v1.TaskStatus} + */ +@com.google.protobuf.Generated +public final class TaskStatus extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.TaskStatus) + TaskStatusOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "TaskStatus"); + } + // Use TaskStatus.newBuilder() to construct. + private TaskStatus(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private TaskStatus() { + state_ = 0; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskStatus_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskStatus_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskStatus.class, org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder.class); + } + + private int bitField0_; + public static final int STATE_FIELD_NUMBER = 1; + private int state_ = 0; + /** + *
            +   * The current state of this task
            +   * 
            + * + * .a2a.v1.TaskState state = 1; + * @return The enum numeric value on the wire for state. + */ + @java.lang.Override public int getStateValue() { + return state_; + } + /** + *
            +   * The current state of this task
            +   * 
            + * + * .a2a.v1.TaskState state = 1; + * @return The state. + */ + @java.lang.Override public org.a2aproject.sdk.compat03.grpc.TaskState getState() { + org.a2aproject.sdk.compat03.grpc.TaskState result = org.a2aproject.sdk.compat03.grpc.TaskState.forNumber(state_); + return result == null ? org.a2aproject.sdk.compat03.grpc.TaskState.UNRECOGNIZED : result; + } + + public static final int UPDATE_FIELD_NUMBER = 2; + private org.a2aproject.sdk.compat03.grpc.Message update_; + /** + *
            +   * A message associated with the status.
            +   * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + * @return Whether the update field is set. + */ + @java.lang.Override + public boolean hasUpdate() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * A message associated with the status.
            +   * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + * @return The update. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.Message getUpdate() { + return update_ == null ? org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance() : update_; + } + /** + *
            +   * A message associated with the status.
            +   * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getUpdateOrBuilder() { + return update_ == null ? org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance() : update_; + } + + public static final int TIMESTAMP_FIELD_NUMBER = 3; + private com.google.protobuf.Timestamp timestamp_; + /** + *
            +   * Timestamp when the status was recorded.
            +   * Example: "2023-10-27T10:00:00Z"
            +   * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + * @return Whether the timestamp field is set. + */ + @java.lang.Override + public boolean hasTimestamp() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
            +   * Timestamp when the status was recorded.
            +   * Example: "2023-10-27T10:00:00Z"
            +   * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + * @return The timestamp. + */ + @java.lang.Override + public com.google.protobuf.Timestamp getTimestamp() { + return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_; + } + /** + *
            +   * Timestamp when the status was recorded.
            +   * Example: "2023-10-27T10:00:00Z"
            +   * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + @java.lang.Override + public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() { + return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (state_ != org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) { + output.writeEnum(1, state_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(2, getUpdate()); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(3, getTimestamp()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (state_ != org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, state_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getUpdate()); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getTimestamp()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.TaskStatus)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.TaskStatus other = (org.a2aproject.sdk.compat03.grpc.TaskStatus) obj; + + if (state_ != other.state_) return false; + if (hasUpdate() != other.hasUpdate()) return false; + if (hasUpdate()) { + if (!getUpdate() + .equals(other.getUpdate())) return false; + } + if (hasTimestamp() != other.hasTimestamp()) return false; + if (hasTimestamp()) { + if (!getTimestamp() + .equals(other.getTimestamp())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + STATE_FIELD_NUMBER; + hash = (53 * hash) + state_; + if (hasUpdate()) { + hash = (37 * hash) + UPDATE_FIELD_NUMBER; + hash = (53 * hash) + getUpdate().hashCode(); + } + if (hasTimestamp()) { + hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER; + hash = (53 * hash) + getTimestamp().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatus parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.TaskStatus prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * A container for the status of a task
            +   * 
            + * + * Protobuf type {@code a2a.v1.TaskStatus} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.TaskStatus) + org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskStatus_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskStatus_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskStatus.class, org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.TaskStatus.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetUpdateFieldBuilder(); + internalGetTimestampFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + state_ = 0; + update_ = null; + if (updateBuilder_ != null) { + updateBuilder_.dispose(); + updateBuilder_ = null; + } + timestamp_ = null; + if (timestampBuilder_ != null) { + timestampBuilder_.dispose(); + timestampBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_TaskStatus_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatus getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatus build() { + org.a2aproject.sdk.compat03.grpc.TaskStatus result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatus buildPartial() { + org.a2aproject.sdk.compat03.grpc.TaskStatus result = new org.a2aproject.sdk.compat03.grpc.TaskStatus(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.TaskStatus result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.state_ = state_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000002) != 0)) { + result.update_ = updateBuilder_ == null + ? update_ + : updateBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.timestamp_ = timestampBuilder_ == null + ? timestamp_ + : timestampBuilder_.build(); + to_bitField0_ |= 0x00000002; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.TaskStatus) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.TaskStatus)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.TaskStatus other) { + if (other == org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance()) return this; + if (other.state_ != 0) { + setStateValue(other.getStateValue()); + } + if (other.hasUpdate()) { + mergeUpdate(other.getUpdate()); + } + if (other.hasTimestamp()) { + mergeTimestamp(other.getTimestamp()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + state_ = input.readEnum(); + bitField0_ |= 0x00000001; + break; + } // case 8 + case 18: { + input.readMessage( + internalGetUpdateFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetTimestampFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private int state_ = 0; + /** + *
            +     * The current state of this task
            +     * 
            + * + * .a2a.v1.TaskState state = 1; + * @return The enum numeric value on the wire for state. + */ + @java.lang.Override public int getStateValue() { + return state_; + } + /** + *
            +     * The current state of this task
            +     * 
            + * + * .a2a.v1.TaskState state = 1; + * @param value The enum numeric value on the wire for state to set. + * @return This builder for chaining. + */ + public Builder setStateValue(int value) { + state_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The current state of this task
            +     * 
            + * + * .a2a.v1.TaskState state = 1; + * @return The state. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskState getState() { + org.a2aproject.sdk.compat03.grpc.TaskState result = org.a2aproject.sdk.compat03.grpc.TaskState.forNumber(state_); + return result == null ? org.a2aproject.sdk.compat03.grpc.TaskState.UNRECOGNIZED : result; + } + /** + *
            +     * The current state of this task
            +     * 
            + * + * .a2a.v1.TaskState state = 1; + * @param value The state to set. + * @return This builder for chaining. + */ + public Builder setState(org.a2aproject.sdk.compat03.grpc.TaskState value) { + if (value == null) { throw new NullPointerException(); } + bitField0_ |= 0x00000001; + state_ = value.getNumber(); + onChanged(); + return this; + } + /** + *
            +     * The current state of this task
            +     * 
            + * + * .a2a.v1.TaskState state = 1; + * @return This builder for chaining. + */ + public Builder clearState() { + bitField0_ = (bitField0_ & ~0x00000001); + state_ = 0; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.Message update_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> updateBuilder_; + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + * @return Whether the update field is set. + */ + public boolean hasUpdate() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + * @return The update. + */ + public org.a2aproject.sdk.compat03.grpc.Message getUpdate() { + if (updateBuilder_ == null) { + return update_ == null ? org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance() : update_; + } else { + return updateBuilder_.getMessage(); + } + } + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + public Builder setUpdate(org.a2aproject.sdk.compat03.grpc.Message value) { + if (updateBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + update_ = value; + } else { + updateBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + public Builder setUpdate( + org.a2aproject.sdk.compat03.grpc.Message.Builder builderForValue) { + if (updateBuilder_ == null) { + update_ = builderForValue.build(); + } else { + updateBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + public Builder mergeUpdate(org.a2aproject.sdk.compat03.grpc.Message value) { + if (updateBuilder_ == null) { + if (((bitField0_ & 0x00000002) != 0) && + update_ != null && + update_ != org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance()) { + getUpdateBuilder().mergeFrom(value); + } else { + update_ = value; + } + } else { + updateBuilder_.mergeFrom(value); + } + if (update_ != null) { + bitField0_ |= 0x00000002; + onChanged(); + } + return this; + } + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + public Builder clearUpdate() { + bitField0_ = (bitField0_ & ~0x00000002); + update_ = null; + if (updateBuilder_ != null) { + updateBuilder_.dispose(); + updateBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + public org.a2aproject.sdk.compat03.grpc.Message.Builder getUpdateBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return internalGetUpdateFieldBuilder().getBuilder(); + } + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + public org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getUpdateOrBuilder() { + if (updateBuilder_ != null) { + return updateBuilder_.getMessageOrBuilder(); + } else { + return update_ == null ? + org.a2aproject.sdk.compat03.grpc.Message.getDefaultInstance() : update_; + } + } + /** + *
            +     * A message associated with the status.
            +     * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder> + internalGetUpdateFieldBuilder() { + if (updateBuilder_ == null) { + updateBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.Message, org.a2aproject.sdk.compat03.grpc.Message.Builder, org.a2aproject.sdk.compat03.grpc.MessageOrBuilder>( + getUpdate(), + getParentForChildren(), + isClean()); + update_ = null; + } + return updateBuilder_; + } + + private com.google.protobuf.Timestamp timestamp_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> timestampBuilder_; + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + * @return Whether the timestamp field is set. + */ + public boolean hasTimestamp() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + * @return The timestamp. + */ + public com.google.protobuf.Timestamp getTimestamp() { + if (timestampBuilder_ == null) { + return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_; + } else { + return timestampBuilder_.getMessage(); + } + } + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + public Builder setTimestamp(com.google.protobuf.Timestamp value) { + if (timestampBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + timestamp_ = value; + } else { + timestampBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + public Builder setTimestamp( + com.google.protobuf.Timestamp.Builder builderForValue) { + if (timestampBuilder_ == null) { + timestamp_ = builderForValue.build(); + } else { + timestampBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + public Builder mergeTimestamp(com.google.protobuf.Timestamp value) { + if (timestampBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + timestamp_ != null && + timestamp_ != com.google.protobuf.Timestamp.getDefaultInstance()) { + getTimestampBuilder().mergeFrom(value); + } else { + timestamp_ = value; + } + } else { + timestampBuilder_.mergeFrom(value); + } + if (timestamp_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + public Builder clearTimestamp() { + bitField0_ = (bitField0_ & ~0x00000004); + timestamp_ = null; + if (timestampBuilder_ != null) { + timestampBuilder_.dispose(); + timestampBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + public com.google.protobuf.Timestamp.Builder getTimestampBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return internalGetTimestampFieldBuilder().getBuilder(); + } + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() { + if (timestampBuilder_ != null) { + return timestampBuilder_.getMessageOrBuilder(); + } else { + return timestamp_ == null ? + com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_; + } + } + /** + *
            +     * Timestamp when the status was recorded.
            +     * Example: "2023-10-27T10:00:00Z"
            +     * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> + internalGetTimestampFieldBuilder() { + if (timestampBuilder_ == null) { + timestampBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>( + getTimestamp(), + getParentForChildren(), + isClean()); + timestamp_ = null; + } + return timestampBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.TaskStatus) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.TaskStatus) + private static final org.a2aproject.sdk.compat03.grpc.TaskStatus DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.TaskStatus(); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatus getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TaskStatus parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatus getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusOrBuilder.java new file mode 100644 index 000000000..025ed99bc --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusOrBuilder.java @@ -0,0 +1,88 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface TaskStatusOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.TaskStatus) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The current state of this task
            +   * 
            + * + * .a2a.v1.TaskState state = 1; + * @return The enum numeric value on the wire for state. + */ + int getStateValue(); + /** + *
            +   * The current state of this task
            +   * 
            + * + * .a2a.v1.TaskState state = 1; + * @return The state. + */ + org.a2aproject.sdk.compat03.grpc.TaskState getState(); + + /** + *
            +   * A message associated with the status.
            +   * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + * @return Whether the update field is set. + */ + boolean hasUpdate(); + /** + *
            +   * A message associated with the status.
            +   * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + * @return The update. + */ + org.a2aproject.sdk.compat03.grpc.Message getUpdate(); + /** + *
            +   * A message associated with the status.
            +   * 
            + * + * .a2a.v1.Message update = 2 [json_name = "message"]; + */ + org.a2aproject.sdk.compat03.grpc.MessageOrBuilder getUpdateOrBuilder(); + + /** + *
            +   * Timestamp when the status was recorded.
            +   * Example: "2023-10-27T10:00:00Z"
            +   * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + * @return Whether the timestamp field is set. + */ + boolean hasTimestamp(); + /** + *
            +   * Timestamp when the status was recorded.
            +   * Example: "2023-10-27T10:00:00Z"
            +   * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + * @return The timestamp. + */ + com.google.protobuf.Timestamp getTimestamp(); + /** + *
            +   * Timestamp when the status was recorded.
            +   * Example: "2023-10-27T10:00:00Z"
            +   * 
            + * + * .google.protobuf.Timestamp timestamp = 3; + */ + com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusUpdateEvent.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusUpdateEvent.java new file mode 100644 index 000000000..5d146bfa5 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusUpdateEvent.java @@ -0,0 +1,1261 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + *
            + * TaskStatusUpdateEvent is a delta even on a task indicating that a task
            + * has changed.
            + * 
            + * + * Protobuf type {@code a2a.v1.TaskStatusUpdateEvent} + */ +@com.google.protobuf.Generated +public final class TaskStatusUpdateEvent extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.TaskStatusUpdateEvent) + TaskStatusUpdateEventOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "TaskStatusUpdateEvent"); + } + // Use TaskStatusUpdateEvent.newBuilder() to construct. + private TaskStatusUpdateEvent(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private TaskStatusUpdateEvent() { + taskId_ = ""; + contextId_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.class, org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder.class); + } + + private int bitField0_; + public static final int TASK_ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object taskId_ = ""; + /** + *
            +   * The id of the task that is changed
            +   * 
            + * + * string task_id = 1; + * @return The taskId. + */ + @java.lang.Override + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + taskId_ = s; + return s; + } + } + /** + *
            +   * The id of the task that is changed
            +   * 
            + * + * string task_id = 1; + * @return The bytes for taskId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTaskIdBytes() { + java.lang.Object ref = taskId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CONTEXT_ID_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object contextId_ = ""; + /** + *
            +   * The id of the context that the task belongs to
            +   * 
            + * + * string context_id = 2; + * @return The contextId. + */ + @java.lang.Override + public java.lang.String getContextId() { + java.lang.Object ref = contextId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + contextId_ = s; + return s; + } + } + /** + *
            +   * The id of the context that the task belongs to
            +   * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getContextIdBytes() { + java.lang.Object ref = contextId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + contextId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int STATUS_FIELD_NUMBER = 3; + private org.a2aproject.sdk.compat03.grpc.TaskStatus status_; + /** + *
            +   * The new status of the task.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return Whether the status field is set. + */ + @java.lang.Override + public boolean hasStatus() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
            +   * The new status of the task.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return The status. + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatus getStatus() { + return status_ == null ? org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance() : status_; + } + /** + *
            +   * The new status of the task.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder getStatusOrBuilder() { + return status_ == null ? org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance() : status_; + } + + public static final int FINAL_FIELD_NUMBER = 4; + private boolean final_ = false; + /** + *
            +   * Whether this is the last status update expected for this task.
            +   * 
            + * + * bool final = 4; + * @return The final. + */ + @java.lang.Override + public boolean getFinal() { + return final_; + } + + public static final int METADATA_FIELD_NUMBER = 5; + private com.google.protobuf.Struct metadata_; + /** + *
            +   * Optional metadata to associate with the task update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 5; + * @return Whether the metadata field is set. + */ + @java.lang.Override + public boolean hasMetadata() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + *
            +   * Optional metadata to associate with the task update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 5; + * @return The metadata. + */ + @java.lang.Override + public com.google.protobuf.Struct getMetadata() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + /** + *
            +   * Optional metadata to associate with the task update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + @java.lang.Override + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(3, getStatus()); + } + if (final_ != false) { + output.writeBool(4, final_); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(5, getMetadata()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getStatus()); + } + if (final_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(4, final_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, getMetadata()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent other = (org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) obj; + + if (!getTaskId() + .equals(other.getTaskId())) return false; + if (!getContextId() + .equals(other.getContextId())) return false; + if (hasStatus() != other.hasStatus()) return false; + if (hasStatus()) { + if (!getStatus() + .equals(other.getStatus())) return false; + } + if (getFinal() + != other.getFinal()) return false; + if (hasMetadata() != other.hasMetadata()) return false; + if (hasMetadata()) { + if (!getMetadata() + .equals(other.getMetadata())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + TASK_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskId().hashCode(); + hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; + hash = (53 * hash) + getContextId().hashCode(); + if (hasStatus()) { + hash = (37 * hash) + STATUS_FIELD_NUMBER; + hash = (53 * hash) + getStatus().hashCode(); + } + hash = (37 * hash) + FINAL_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getFinal()); + if (hasMetadata()) { + hash = (37 * hash) + METADATA_FIELD_NUMBER; + hash = (53 * hash) + getMetadata().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
            +   * TaskStatusUpdateEvent is a delta even on a task indicating that a task
            +   * has changed.
            +   * 
            + * + * Protobuf type {@code a2a.v1.TaskStatusUpdateEvent} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.TaskStatusUpdateEvent) + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEventOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.class, org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage + .alwaysUseFieldBuilders) { + internalGetStatusFieldBuilder(); + internalGetMetadataFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + taskId_ = ""; + contextId_ = ""; + status_ = null; + if (statusBuilder_ != null) { + statusBuilder_.dispose(); + statusBuilder_ = null; + } + final_ = false; + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent build() { + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent buildPartial() { + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent result = new org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.taskId_ = taskId_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.contextId_ = contextId_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000004) != 0)) { + result.status_ = statusBuilder_ == null + ? status_ + : statusBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.final_ = final_; + } + if (((from_bitField0_ & 0x00000010) != 0)) { + result.metadata_ = metadataBuilder_ == null + ? metadata_ + : metadataBuilder_.build(); + to_bitField0_ |= 0x00000002; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent other) { + if (other == org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.getDefaultInstance()) return this; + if (!other.getTaskId().isEmpty()) { + taskId_ = other.taskId_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getContextId().isEmpty()) { + contextId_ = other.contextId_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (other.hasStatus()) { + mergeStatus(other.getStatus()); + } + if (other.getFinal() != false) { + setFinal(other.getFinal()); + } + if (other.hasMetadata()) { + mergeMetadata(other.getMetadata()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + taskId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + contextId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + input.readMessage( + internalGetStatusFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 32: { + final_ = input.readBool(); + bitField0_ |= 0x00000008; + break; + } // case 32 + case 42: { + input.readMessage( + internalGetMetadataFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000010; + break; + } // case 42 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object taskId_ = ""; + /** + *
            +     * The id of the task that is changed
            +     * 
            + * + * string task_id = 1; + * @return The taskId. + */ + public java.lang.String getTaskId() { + java.lang.Object ref = taskId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + taskId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The id of the task that is changed
            +     * 
            + * + * string task_id = 1; + * @return The bytes for taskId. + */ + public com.google.protobuf.ByteString + getTaskIdBytes() { + java.lang.Object ref = taskId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + taskId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The id of the task that is changed
            +     * 
            + * + * string task_id = 1; + * @param value The taskId to set. + * @return This builder for chaining. + */ + public Builder setTaskId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + taskId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * The id of the task that is changed
            +     * 
            + * + * string task_id = 1; + * @return This builder for chaining. + */ + public Builder clearTaskId() { + taskId_ = getDefaultInstance().getTaskId(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * The id of the task that is changed
            +     * 
            + * + * string task_id = 1; + * @param value The bytes for taskId to set. + * @return This builder for chaining. + */ + public Builder setTaskIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + taskId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object contextId_ = ""; + /** + *
            +     * The id of the context that the task belongs to
            +     * 
            + * + * string context_id = 2; + * @return The contextId. + */ + public java.lang.String getContextId() { + java.lang.Object ref = contextId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + contextId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * The id of the context that the task belongs to
            +     * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + public com.google.protobuf.ByteString + getContextIdBytes() { + java.lang.Object ref = contextId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + contextId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * The id of the context that the task belongs to
            +     * 
            + * + * string context_id = 2; + * @param value The contextId to set. + * @return This builder for chaining. + */ + public Builder setContextId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + contextId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + *
            +     * The id of the context that the task belongs to
            +     * 
            + * + * string context_id = 2; + * @return This builder for chaining. + */ + public Builder clearContextId() { + contextId_ = getDefaultInstance().getContextId(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + *
            +     * The id of the context that the task belongs to
            +     * 
            + * + * string context_id = 2; + * @param value The bytes for contextId to set. + * @return This builder for chaining. + */ + public Builder setContextIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + contextId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private org.a2aproject.sdk.compat03.grpc.TaskStatus status_; + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatus, org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder> statusBuilder_; + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return Whether the status field is set. + */ + public boolean hasStatus() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return The status. + */ + public org.a2aproject.sdk.compat03.grpc.TaskStatus getStatus() { + if (statusBuilder_ == null) { + return status_ == null ? org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance() : status_; + } else { + return statusBuilder_.getMessage(); + } + } + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public Builder setStatus(org.a2aproject.sdk.compat03.grpc.TaskStatus value) { + if (statusBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + status_ = value; + } else { + statusBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public Builder setStatus( + org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder builderForValue) { + if (statusBuilder_ == null) { + status_ = builderForValue.build(); + } else { + statusBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public Builder mergeStatus(org.a2aproject.sdk.compat03.grpc.TaskStatus value) { + if (statusBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) && + status_ != null && + status_ != org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance()) { + getStatusBuilder().mergeFrom(value); + } else { + status_ = value; + } + } else { + statusBuilder_.mergeFrom(value); + } + if (status_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public Builder clearStatus() { + bitField0_ = (bitField0_ & ~0x00000004); + status_ = null; + if (statusBuilder_ != null) { + statusBuilder_.dispose(); + statusBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder getStatusBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return internalGetStatusFieldBuilder().getBuilder(); + } + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + public org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder getStatusOrBuilder() { + if (statusBuilder_ != null) { + return statusBuilder_.getMessageOrBuilder(); + } else { + return status_ == null ? + org.a2aproject.sdk.compat03.grpc.TaskStatus.getDefaultInstance() : status_; + } + } + /** + *
            +     * The new status of the task.
            +     * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatus, org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder> + internalGetStatusFieldBuilder() { + if (statusBuilder_ == null) { + statusBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.a2aproject.sdk.compat03.grpc.TaskStatus, org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder, org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder>( + getStatus(), + getParentForChildren(), + isClean()); + status_ = null; + } + return statusBuilder_; + } + + private boolean final_ ; + /** + *
            +     * Whether this is the last status update expected for this task.
            +     * 
            + * + * bool final = 4; + * @return The final. + */ + @java.lang.Override + public boolean getFinal() { + return final_; + } + /** + *
            +     * Whether this is the last status update expected for this task.
            +     * 
            + * + * bool final = 4; + * @param value The final to set. + * @return This builder for chaining. + */ + public Builder setFinal(boolean value) { + + final_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
            +     * Whether this is the last status update expected for this task.
            +     * 
            + * + * bool final = 4; + * @return This builder for chaining. + */ + public Builder clearFinal() { + bitField0_ = (bitField0_ & ~0x00000008); + final_ = false; + onChanged(); + return this; + } + + private com.google.protobuf.Struct metadata_; + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + * @return Whether the metadata field is set. + */ + public boolean hasMetadata() { + return ((bitField0_ & 0x00000010) != 0); + } + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + * @return The metadata. + */ + public com.google.protobuf.Struct getMetadata() { + if (metadataBuilder_ == null) { + return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } else { + return metadataBuilder_.getMessage(); + } + } + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + public Builder setMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + metadata_ = value; + } else { + metadataBuilder_.setMessage(value); + } + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + public Builder setMetadata( + com.google.protobuf.Struct.Builder builderForValue) { + if (metadataBuilder_ == null) { + metadata_ = builderForValue.build(); + } else { + metadataBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + public Builder mergeMetadata(com.google.protobuf.Struct value) { + if (metadataBuilder_ == null) { + if (((bitField0_ & 0x00000010) != 0) && + metadata_ != null && + metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { + getMetadataBuilder().mergeFrom(value); + } else { + metadata_ = value; + } + } else { + metadataBuilder_.mergeFrom(value); + } + if (metadata_ != null) { + bitField0_ |= 0x00000010; + onChanged(); + } + return this; + } + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + public Builder clearMetadata() { + bitField0_ = (bitField0_ & ~0x00000010); + metadata_ = null; + if (metadataBuilder_ != null) { + metadataBuilder_.dispose(); + metadataBuilder_ = null; + } + onChanged(); + return this; + } + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + public com.google.protobuf.Struct.Builder getMetadataBuilder() { + bitField0_ |= 0x00000010; + onChanged(); + return internalGetMetadataFieldBuilder().getBuilder(); + } + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { + if (metadataBuilder_ != null) { + return metadataBuilder_.getMessageOrBuilder(); + } else { + return metadata_ == null ? + com.google.protobuf.Struct.getDefaultInstance() : metadata_; + } + } + /** + *
            +     * Optional metadata to associate with the task update.
            +     * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + private com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> + internalGetMetadataFieldBuilder() { + if (metadataBuilder_ == null) { + metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< + com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( + getMetadata(), + getParentForChildren(), + isClean()); + metadata_ = null; + } + return metadataBuilder_; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.TaskStatusUpdateEvent) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.TaskStatusUpdateEvent) + private static final org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent(); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TaskStatusUpdateEvent parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusUpdateEventOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusUpdateEventOrBuilder.java new file mode 100644 index 000000000..02a951004 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskStatusUpdateEventOrBuilder.java @@ -0,0 +1,116 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface TaskStatusUpdateEventOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.TaskStatusUpdateEvent) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * The id of the task that is changed
            +   * 
            + * + * string task_id = 1; + * @return The taskId. + */ + java.lang.String getTaskId(); + /** + *
            +   * The id of the task that is changed
            +   * 
            + * + * string task_id = 1; + * @return The bytes for taskId. + */ + com.google.protobuf.ByteString + getTaskIdBytes(); + + /** + *
            +   * The id of the context that the task belongs to
            +   * 
            + * + * string context_id = 2; + * @return The contextId. + */ + java.lang.String getContextId(); + /** + *
            +   * The id of the context that the task belongs to
            +   * 
            + * + * string context_id = 2; + * @return The bytes for contextId. + */ + com.google.protobuf.ByteString + getContextIdBytes(); + + /** + *
            +   * The new status of the task.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return Whether the status field is set. + */ + boolean hasStatus(); + /** + *
            +   * The new status of the task.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + * @return The status. + */ + org.a2aproject.sdk.compat03.grpc.TaskStatus getStatus(); + /** + *
            +   * The new status of the task.
            +   * 
            + * + * .a2a.v1.TaskStatus status = 3; + */ + org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder getStatusOrBuilder(); + + /** + *
            +   * Whether this is the last status update expected for this task.
            +   * 
            + * + * bool final = 4; + * @return The final. + */ + boolean getFinal(); + + /** + *
            +   * Optional metadata to associate with the task update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 5; + * @return Whether the metadata field is set. + */ + boolean hasMetadata(); + /** + *
            +   * Optional metadata to associate with the task update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 5; + * @return The metadata. + */ + com.google.protobuf.Struct getMetadata(); + /** + *
            +   * Optional metadata to associate with the task update.
            +   * 
            + * + * .google.protobuf.Struct metadata = 5; + */ + com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskSubscriptionRequest.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskSubscriptionRequest.java new file mode 100644 index 000000000..239543702 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskSubscriptionRequest.java @@ -0,0 +1,530 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +/** + * Protobuf type {@code a2a.v1.TaskSubscriptionRequest} + */ +@com.google.protobuf.Generated +public final class TaskSubscriptionRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:a2a.v1.TaskSubscriptionRequest) + TaskSubscriptionRequestOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 33, + /* patch= */ 1, + /* suffix= */ "", + "TaskSubscriptionRequest"); + } + // Use TaskSubscriptionRequest.newBuilder() to construct. + private TaskSubscriptionRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private TaskSubscriptionRequest() { + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskSubscriptionRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskSubscriptionRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.class, org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.Builder.class); + } + + public static final int NAME_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest)) { + return super.equals(obj); + } + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest other = (org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest) obj; + + if (!getName() + .equals(other.getName())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code a2a.v1.TaskSubscriptionRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:a2a.v1.TaskSubscriptionRequest) + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return A2A.internal_static_a2a_v1_TaskSubscriptionRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return A2A.internal_static_a2a_v1_TaskSubscriptionRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.class, org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.Builder.class); + } + + // Construct using org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + name_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return A2A.internal_static_a2a_v1_TaskSubscriptionRequest_descriptor; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest getDefaultInstanceForType() { + return org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.getDefaultInstance(); + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest build() { + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest buildPartial() { + org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest result = new org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.name_ = name_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest) { + return mergeFrom((org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest other) { + if (other == org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000001; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object name_ = ""; + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
            +     * name=tasks/{id}
            +     * 
            + * + * string name = 1; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:a2a.v1.TaskSubscriptionRequest) + } + + // @@protoc_insertion_point(class_scope:a2a.v1.TaskSubscriptionRequest) + private static final org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest(); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TaskSubscriptionRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskSubscriptionRequestOrBuilder.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskSubscriptionRequestOrBuilder.java new file mode 100644 index 000000000..a5edfc6f0 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/TaskSubscriptionRequestOrBuilder.java @@ -0,0 +1,32 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: a2a.proto +// Protobuf Java Version: 4.33.1 + +package org.a2aproject.sdk.compat03.grpc; + +@com.google.protobuf.Generated +public interface TaskSubscriptionRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:a2a.v1.TaskSubscriptionRequest) + com.google.protobuf.MessageOrBuilder { + + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1; + * @return The name. + */ + java.lang.String getName(); + /** + *
            +   * name=tasks/{id}
            +   * 
            + * + * string name = 1; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java new file mode 100644 index 000000000..a69a376c8 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java @@ -0,0 +1,1025 @@ +package org.a2aproject.sdk.compat03.grpc.utils; + + +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.google.protobuf.ByteString; +import com.google.protobuf.Struct; +import com.google.protobuf.Value; +import org.a2aproject.sdk.compat03.grpc.StreamResponse; +import org.a2aproject.sdk.compat03.spec.APIKeySecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCardSignature_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentExtension_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentInterface_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentProvider_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.AuthorizationCodeOAuthFlow_v0_3; +import org.a2aproject.sdk.compat03.spec.ClientCredentialsOAuthFlow_v0_3; +import org.a2aproject.sdk.compat03.spec.DataPart_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.FileContent_v0_3; +import org.a2aproject.sdk.compat03.spec.FilePart_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithBytes_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithUri_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.ImplicitOAuthFlow_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendConfiguration_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.MutualTLSSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.OAuth2SecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.OAuthFlows_v0_3; +import org.a2aproject.sdk.compat03.spec.OpenIdConnectSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.PasswordOAuthFlow_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationAuthenticationInfo_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.SecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.jspecify.annotations.Nullable; + +/** + * Utility class to convert between GRPC and Spec objects. + */ +public class ProtoUtils_v0_3 { + + public static class ToProto { + + public static org.a2aproject.sdk.compat03.grpc.AgentCard agentCard(AgentCard_v0_3 agentCard) { + org.a2aproject.sdk.compat03.grpc.AgentCard.Builder builder = org.a2aproject.sdk.compat03.grpc.AgentCard.newBuilder(); + if (agentCard.protocolVersion() != null) { + builder.setProtocolVersion(agentCard.protocolVersion()); + } + if (agentCard.name() != null) { + builder.setName(agentCard.name()); + } + if (agentCard.description() != null) { + builder.setDescription(agentCard.description()); + } + if (agentCard.url() != null) { + builder.setUrl(agentCard.url()); + } + if (agentCard.preferredTransport() != null) { + builder.setPreferredTransport(agentCard.preferredTransport()); + } + if (agentCard.additionalInterfaces() != null) { + builder.addAllAdditionalInterfaces(agentCard.additionalInterfaces().stream().map(item -> agentInterface(item)).collect(Collectors.toList())); + } + if (agentCard.provider() != null) { + builder.setProvider(agentProvider(agentCard.provider())); + } + if (agentCard.version() != null) { + builder.setVersion(agentCard.version()); + } + if (agentCard.documentationUrl() != null) { + builder.setDocumentationUrl(agentCard.documentationUrl()); + } + if (agentCard.capabilities() != null) { + builder.setCapabilities(agentCapabilities(agentCard.capabilities())); + } + if (agentCard.securitySchemes() != null) { + builder.putAllSecuritySchemes( + agentCard.securitySchemes().entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> securityScheme(e.getValue()))) + ); + } + if (agentCard.security() != null) { + builder.addAllSecurity(agentCard.security().stream().map(s -> { + org.a2aproject.sdk.compat03.grpc.Security.Builder securityBuilder = org.a2aproject.sdk.compat03.grpc.Security.newBuilder(); + s.forEach((key, value) -> { + org.a2aproject.sdk.compat03.grpc.StringList.Builder stringListBuilder = org.a2aproject.sdk.compat03.grpc.StringList.newBuilder(); + stringListBuilder.addAllList(value); + securityBuilder.putSchemes(key, stringListBuilder.build()); + }); + return securityBuilder.build(); + }).collect(Collectors.toList())); + } + if (agentCard.defaultInputModes() != null) { + builder.addAllDefaultInputModes(agentCard.defaultInputModes()); + } + if (agentCard.defaultOutputModes() != null) { + builder.addAllDefaultOutputModes(agentCard.defaultOutputModes()); + } + if (agentCard.skills() != null) { + builder.addAllSkills(agentCard.skills().stream().map(ToProto::agentSkill).collect(Collectors.toList())); + } + builder.setSupportsAuthenticatedExtendedCard(agentCard.supportsAuthenticatedExtendedCard()); + if (agentCard.signatures() != null) { + builder.addAllSignatures(agentCard.signatures().stream().map(ToProto::agentCardSignature).collect(Collectors.toList())); + } + return builder.build(); + } + + public static org.a2aproject.sdk.compat03.grpc.Task task(Task_v0_3 task) { + org.a2aproject.sdk.compat03.grpc.Task.Builder builder = org.a2aproject.sdk.compat03.grpc.Task.newBuilder(); + builder.setId(task.getId()); + builder.setContextId(task.getContextId()); + builder.setStatus(taskStatus(task.getStatus())); + if (task.getArtifacts() != null) { + builder.addAllArtifacts(task.getArtifacts().stream().map(ToProto::artifact).collect(Collectors.toList())); + } + if (task.getHistory() != null) { + builder.addAllHistory(task.getHistory().stream().map(ToProto::message).collect(Collectors.toList())); + } + builder.setMetadata(struct(task.getMetadata())); + return builder.build(); + } + + public static org.a2aproject.sdk.compat03.grpc.Message message(Message_v0_3 message) { + org.a2aproject.sdk.compat03.grpc.Message.Builder builder = org.a2aproject.sdk.compat03.grpc.Message.newBuilder(); + builder.setMessageId(message.getMessageId()); + if (message.getContextId() != null) { + builder.setContextId(message.getContextId()); + } + if (message.getTaskId() != null) { + builder.setTaskId(message.getTaskId()); + } + builder.setRole(role(message.getRole())); + if (message.getParts() != null) { + builder.addAllContent(message.getParts().stream().map(ToProto::part).collect(Collectors.toList())); + } + builder.setMetadata(struct(message.getMetadata())); + return builder.build(); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig taskPushNotificationConfig(TaskPushNotificationConfig_v0_3 config) { + String id = config.pushNotificationConfig().id(); + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.Builder builder = org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.newBuilder(); + builder.setName("tasks/" + config.taskId() + "/pushNotificationConfigs" + (id == null ? "" : ('/' + id))); + builder.setPushNotificationConfig(pushNotificationConfig(config.pushNotificationConfig())); + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig pushNotificationConfig(PushNotificationConfig_v0_3 config) { + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.Builder builder = org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.newBuilder(); + if (config.url() != null) { + builder.setUrl(config.url()); + } + if (config.token() != null) { + builder.setToken(config.token()); + } + if (config.authentication() != null) { + builder.setAuthentication(authenticationInfo(config.authentication())); + } + if (config.id() != null) { + builder.setId(config.id()); + } + return builder.build(); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent taskArtifactUpdateEvent(TaskArtifactUpdateEvent_v0_3 event) { + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder builder = org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.newBuilder(); + builder.setTaskId(event.getTaskId()); + builder.setContextId(event.getContextId()); + builder.setArtifact(artifact(event.getArtifact())); + if (event.isAppend() != null) { + builder.setAppend(event.isAppend()); + } + if (event.isLastChunk() != null) { + builder.setLastChunk(event.isLastChunk()); + } + if (event.getMetadata() != null) { + builder.setMetadata(struct(event.getMetadata())); + } + return builder.build(); + } + + public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent taskStatusUpdateEvent(TaskStatusUpdateEvent_v0_3 event) { + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder builder = org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.newBuilder(); + builder.setTaskId(event.getTaskId()); + builder.setContextId(event.getContextId()); + builder.setStatus(taskStatus(event.getStatus())); + builder.setFinal(event.isFinal()); + if (event.getMetadata() != null) { + builder.setMetadata(struct(event.getMetadata())); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.Artifact artifact(Artifact_v0_3 artifact) { + org.a2aproject.sdk.compat03.grpc.Artifact.Builder builder = org.a2aproject.sdk.compat03.grpc.Artifact.newBuilder(); + if (artifact.artifactId() != null) { + builder.setArtifactId(artifact.artifactId()); + } + if (artifact.name() != null) { + builder.setName(artifact.name()); + } + if (artifact.description() != null) { + builder.setDescription(artifact.description()); + } + if (artifact.parts() != null) { + builder.addAllParts(artifact.parts().stream().map(ToProto::part).collect(Collectors.toList())); + } + if (artifact.metadata() != null) { + builder.setMetadata(struct(artifact.metadata())); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.Part part(Part_v0_3 part) { + org.a2aproject.sdk.compat03.grpc.Part.Builder builder = org.a2aproject.sdk.compat03.grpc.Part.newBuilder(); + if (part instanceof TextPart_v0_3) { + builder.setText(((TextPart_v0_3) part).getText()); + } else if (part instanceof FilePart_v0_3) { + builder.setFile(filePart((FilePart_v0_3) part)); + } else if (part instanceof DataPart_v0_3) { + builder.setData(dataPart((DataPart_v0_3) part)); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.FilePart filePart(FilePart_v0_3 filePart) { + org.a2aproject.sdk.compat03.grpc.FilePart.Builder builder = org.a2aproject.sdk.compat03.grpc.FilePart.newBuilder(); + FileContent_v0_3 fileContent = filePart.getFile(); + if (fileContent instanceof FileWithBytes_v0_3) { + builder.setFileWithBytes(ByteString.copyFrom(((FileWithBytes_v0_3) fileContent).bytes(), StandardCharsets.UTF_8)); + } else if (fileContent instanceof FileWithUri_v0_3) { + builder.setFileWithUri(((FileWithUri_v0_3) fileContent).uri()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.DataPart dataPart(DataPart_v0_3 dataPart) { + org.a2aproject.sdk.compat03.grpc.DataPart.Builder builder = org.a2aproject.sdk.compat03.grpc.DataPart.newBuilder(); + if (dataPart.getData() != null) { + builder.setData(struct(dataPart.getData())); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.Role role(Message_v0_3.Role role) { + if (role == null) { + return org.a2aproject.sdk.compat03.grpc.Role.ROLE_UNSPECIFIED; + } + return switch (role) { + case USER -> + org.a2aproject.sdk.compat03.grpc.Role.ROLE_USER; + case AGENT -> + org.a2aproject.sdk.compat03.grpc.Role.ROLE_AGENT; + }; + } + + private static org.a2aproject.sdk.compat03.grpc.TaskStatus taskStatus(TaskStatus_v0_3 taskStatus) { + org.a2aproject.sdk.compat03.grpc.TaskStatus.Builder builder = org.a2aproject.sdk.compat03.grpc.TaskStatus.newBuilder(); + if (taskStatus.state() != null) { + builder.setState(taskState(taskStatus.state())); + } + if (taskStatus.message() != null) { + builder.setUpdate(message(taskStatus.message())); + } + if (taskStatus.timestamp() != null) { + Instant instant = taskStatus.timestamp().toInstant(); + builder.setTimestamp(com.google.protobuf.Timestamp.newBuilder().setSeconds(instant.getEpochSecond()).setNanos(instant.getNano()).build()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.TaskState taskState(TaskState_v0_3 taskState) { + if (taskState == null) { + return org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_UNSPECIFIED; + } + return switch (taskState) { + case SUBMITTED -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_SUBMITTED; + case WORKING -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_WORKING; + case INPUT_REQUIRED -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_INPUT_REQUIRED; + case AUTH_REQUIRED -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_AUTH_REQUIRED; + case COMPLETED -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_COMPLETED; + case CANCELED -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_CANCELLED; + case FAILED -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_FAILED; + case REJECTED -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_REJECTED; + default -> + org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_UNSPECIFIED; + }; + } + + private static org.a2aproject.sdk.compat03.grpc.AuthenticationInfo authenticationInfo(PushNotificationAuthenticationInfo_v0_3 pushNotificationAuthenticationInfo) { + org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.Builder builder = org.a2aproject.sdk.compat03.grpc.AuthenticationInfo.newBuilder(); + if (pushNotificationAuthenticationInfo.schemes() != null) { + builder.addAllSchemes(pushNotificationAuthenticationInfo.schemes()); + } + if (pushNotificationAuthenticationInfo.credentials() != null) { + builder.setCredentials(pushNotificationAuthenticationInfo.credentials()); + } + return builder.build(); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration messageSendConfiguration(MessageSendConfiguration_v0_3 messageSendConfiguration) { + org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.Builder builder = org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration.newBuilder(); + if (messageSendConfiguration.acceptedOutputModes() != null) { + builder.addAllAcceptedOutputModes(messageSendConfiguration.acceptedOutputModes()); + } + if (messageSendConfiguration.historyLength() != null) { + builder.setHistoryLength(messageSendConfiguration.historyLength()); + } + if (messageSendConfiguration.pushNotificationConfig() != null) { + builder.setPushNotification(pushNotificationConfig(messageSendConfiguration.pushNotificationConfig())); + } + builder.setBlocking(messageSendConfiguration.blocking()); + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.AgentProvider agentProvider(AgentProvider_v0_3 agentProvider) { + org.a2aproject.sdk.compat03.grpc.AgentProvider.Builder builder = org.a2aproject.sdk.compat03.grpc.AgentProvider.newBuilder(); + builder.setOrganization(agentProvider.organization()); + builder.setUrl(agentProvider.url()); + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.AgentCapabilities agentCapabilities(AgentCapabilities_v0_3 agentCapabilities) { + org.a2aproject.sdk.compat03.grpc.AgentCapabilities.Builder builder = org.a2aproject.sdk.compat03.grpc.AgentCapabilities.newBuilder(); + builder.setStreaming(agentCapabilities.streaming()); + builder.setPushNotifications(agentCapabilities.pushNotifications()); + if (agentCapabilities.extensions() != null) { + builder.addAllExtensions(agentCapabilities.extensions().stream().map(ToProto::agentExtension).collect(Collectors.toList())); + } + return builder.build(); + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageRequest sendMessageRequest(MessageSendParams_v0_3 request) { + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.Builder builder = org.a2aproject.sdk.compat03.grpc.SendMessageRequest.newBuilder(); + builder.setRequest(message(request.message())); + if (request.configuration() != null) { + builder.setConfiguration(messageSendConfiguration(request.configuration())); + } + if (request.metadata() != null && ! request.metadata().isEmpty()) { + builder.setMetadata(struct(request.metadata())); + } + return builder.build(); + } + private static org.a2aproject.sdk.compat03.grpc.AgentExtension agentExtension(AgentExtension_v0_3 agentExtension) { + org.a2aproject.sdk.compat03.grpc.AgentExtension.Builder builder = org.a2aproject.sdk.compat03.grpc.AgentExtension.newBuilder(); + if (agentExtension.description() != null) { + builder.setDescription(agentExtension.description()); + } + if (agentExtension.params() != null) { + builder.setParams(struct(agentExtension.params())); + } + builder.setRequired(agentExtension.required()); + if (agentExtension.uri() != null) { + builder.setUri(agentExtension.uri()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.AgentSkill agentSkill(AgentSkill_v0_3 agentSkill) { + org.a2aproject.sdk.compat03.grpc.AgentSkill.Builder builder = org.a2aproject.sdk.compat03.grpc.AgentSkill.newBuilder(); + if (agentSkill.id() != null) { + builder.setId(agentSkill.id()); + } + if (agentSkill.name() != null) { + builder.setName(agentSkill.name()); + } + if (agentSkill.description() != null) { + builder.setDescription(agentSkill.description()); + } + if (agentSkill.tags() != null) { + builder.addAllTags(agentSkill.tags()); + } + if (agentSkill.examples() != null) { + builder.addAllExamples(agentSkill.examples()); + } + if (agentSkill.inputModes() != null) { + builder.addAllInputModes(agentSkill.inputModes()); + } + if (agentSkill.outputModes() != null) { + builder.addAllOutputModes(agentSkill.outputModes()); + } + if (agentSkill.security() != null) { + builder.addAllSecurity(agentSkill.security().stream().map(s -> { + org.a2aproject.sdk.compat03.grpc.Security.Builder securityBuilder = org.a2aproject.sdk.compat03.grpc.Security.newBuilder(); + s.forEach((key, value) -> { + org.a2aproject.sdk.compat03.grpc.StringList.Builder stringListBuilder = org.a2aproject.sdk.compat03.grpc.StringList.newBuilder(); + stringListBuilder.addAllList(value); + securityBuilder.putSchemes(key, stringListBuilder.build()); + }); + return securityBuilder.build(); + }).collect(Collectors.toList())); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.AgentCardSignature agentCardSignature(AgentCardSignature_v0_3 agentCardSignature) { + org.a2aproject.sdk.compat03.grpc.AgentCardSignature.Builder builder = org.a2aproject.sdk.compat03.grpc.AgentCardSignature.newBuilder(); + builder.setProtected(agentCardSignature.protectedHeader()); + builder.setSignature(agentCardSignature.signature()); + if (agentCardSignature.header() != null) { + builder.setHeader(struct(agentCardSignature.header())); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.SecurityScheme securityScheme(SecurityScheme_v0_3 securityScheme) { + org.a2aproject.sdk.compat03.grpc.SecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.SecurityScheme.newBuilder(); + if (securityScheme instanceof APIKeySecurityScheme_v0_3) { + builder.setApiKeySecurityScheme(apiKeySecurityScheme((APIKeySecurityScheme_v0_3) securityScheme)); + } else if (securityScheme instanceof HTTPAuthSecurityScheme_v0_3) { + builder.setHttpAuthSecurityScheme(httpAuthSecurityScheme((HTTPAuthSecurityScheme_v0_3) securityScheme)); + } else if (securityScheme instanceof OAuth2SecurityScheme_v0_3) { + builder.setOauth2SecurityScheme(oauthSecurityScheme((OAuth2SecurityScheme_v0_3) securityScheme)); + } else if (securityScheme instanceof OpenIdConnectSecurityScheme_v0_3) { + builder.setOpenIdConnectSecurityScheme(openIdConnectSecurityScheme((OpenIdConnectSecurityScheme_v0_3) securityScheme)); + } else if (securityScheme instanceof MutualTLSSecurityScheme_v0_3) { + builder.setMtlsSecurityScheme(mutualTlsSecurityScheme((MutualTLSSecurityScheme_v0_3) securityScheme)); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme apiKeySecurityScheme(APIKeySecurityScheme_v0_3 apiKeySecurityScheme) { + org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.newBuilder(); + if (apiKeySecurityScheme.getDescription() != null) { + builder.setDescription(apiKeySecurityScheme.getDescription()); + } + if (apiKeySecurityScheme.getIn() != null) { + builder.setLocation(apiKeySecurityScheme.getIn()); + } + if (apiKeySecurityScheme.getName() != null) { + builder.setName(apiKeySecurityScheme.getName()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme httpAuthSecurityScheme(HTTPAuthSecurityScheme_v0_3 httpAuthSecurityScheme) { + org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.newBuilder(); + if (httpAuthSecurityScheme.getBearerFormat() != null) { + builder.setBearerFormat(httpAuthSecurityScheme.getBearerFormat()); + } + if (httpAuthSecurityScheme.getDescription() != null) { + builder.setDescription(httpAuthSecurityScheme.getDescription()); + } + if (httpAuthSecurityScheme.getScheme() != null) { + builder.setScheme(httpAuthSecurityScheme.getScheme()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme oauthSecurityScheme(OAuth2SecurityScheme_v0_3 oauth2SecurityScheme) { + org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.newBuilder(); + if (oauth2SecurityScheme.getDescription() != null) { + builder.setDescription(oauth2SecurityScheme.getDescription()); + } + if (oauth2SecurityScheme.getFlows() != null) { + builder.setFlows(oauthFlows(oauth2SecurityScheme.getFlows())); + } + if (oauth2SecurityScheme.getOauth2MetadataUrl() != null) { + builder.setOauth2MetadataUrl(oauth2SecurityScheme.getOauth2MetadataUrl()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.OAuthFlows oauthFlows(OAuthFlows_v0_3 oAuthFlows) { + org.a2aproject.sdk.compat03.grpc.OAuthFlows.Builder builder = org.a2aproject.sdk.compat03.grpc.OAuthFlows.newBuilder(); + if (oAuthFlows.authorizationCode() != null) { + builder.setAuthorizationCode(authorizationCodeOAuthFlow(oAuthFlows.authorizationCode())); + } + if (oAuthFlows.clientCredentials() != null) { + builder.setClientCredentials(clientCredentialsOAuthFlow(oAuthFlows.clientCredentials())); + } + if (oAuthFlows.implicit() != null) { + builder.setImplicit(implicitOAuthFlow(oAuthFlows.implicit())); + } + if (oAuthFlows.password() != null) { + builder.setPassword(passwordOAuthFlow(oAuthFlows.password())); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow authorizationCodeOAuthFlow(AuthorizationCodeOAuthFlow_v0_3 authorizationCodeOAuthFlow) { + org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.Builder builder = org.a2aproject.sdk.compat03.grpc.AuthorizationCodeOAuthFlow.newBuilder(); + if (authorizationCodeOAuthFlow.authorizationUrl() != null) { + builder.setAuthorizationUrl(authorizationCodeOAuthFlow.authorizationUrl()); + } + if (authorizationCodeOAuthFlow.refreshUrl() != null) { + builder.setRefreshUrl(authorizationCodeOAuthFlow.refreshUrl()); + } + if (authorizationCodeOAuthFlow.scopes() != null) { + builder.putAllScopes(authorizationCodeOAuthFlow.scopes()); + } + if (authorizationCodeOAuthFlow.tokenUrl() != null) { + builder.setTokenUrl(authorizationCodeOAuthFlow.tokenUrl()); + } + return builder.build(); + } + + public static org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfigResponse(List configs) { + List confs = new ArrayList<>(configs.size()); + for(TaskPushNotificationConfig_v0_3 config: configs) { + confs.add(taskPushNotificationConfig(config)); + } + return org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.newBuilder().addAllConfigs(confs).build(); + } + + private static org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow clientCredentialsOAuthFlow(ClientCredentialsOAuthFlow_v0_3 clientCredentialsOAuthFlow) { + org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.Builder builder = org.a2aproject.sdk.compat03.grpc.ClientCredentialsOAuthFlow.newBuilder(); + if (clientCredentialsOAuthFlow.refreshUrl() != null) { + builder.setRefreshUrl(clientCredentialsOAuthFlow.refreshUrl()); + } + if (clientCredentialsOAuthFlow.scopes() != null) { + builder.putAllScopes(clientCredentialsOAuthFlow.scopes()); + } + if (clientCredentialsOAuthFlow.tokenUrl() != null) { + builder.setTokenUrl(clientCredentialsOAuthFlow.tokenUrl()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow implicitOAuthFlow(ImplicitOAuthFlow_v0_3 implicitOAuthFlow) { + org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.Builder builder = org.a2aproject.sdk.compat03.grpc.ImplicitOAuthFlow.newBuilder(); + if (implicitOAuthFlow.authorizationUrl() != null) { + builder.setAuthorizationUrl(implicitOAuthFlow.authorizationUrl()); + } + if (implicitOAuthFlow.refreshUrl() != null) { + builder.setRefreshUrl(implicitOAuthFlow.refreshUrl()); + } + if (implicitOAuthFlow.scopes() != null) { + builder.putAllScopes(implicitOAuthFlow.scopes()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow passwordOAuthFlow(PasswordOAuthFlow_v0_3 passwordOAuthFlow) { + org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.Builder builder = org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow.newBuilder(); + if (passwordOAuthFlow.refreshUrl() != null) { + builder.setRefreshUrl(passwordOAuthFlow.refreshUrl()); + } + if (passwordOAuthFlow.scopes() != null) { + builder.putAllScopes(passwordOAuthFlow.scopes()); + } + if (passwordOAuthFlow.tokenUrl() != null) { + builder.setTokenUrl(passwordOAuthFlow.tokenUrl()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme openIdConnectSecurityScheme(OpenIdConnectSecurityScheme_v0_3 openIdConnectSecurityScheme) { + org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.newBuilder(); + if (openIdConnectSecurityScheme.getDescription() != null) { + builder.setDescription(openIdConnectSecurityScheme.getDescription()); + } + if (openIdConnectSecurityScheme.getOpenIdConnectUrl() != null) { + builder.setOpenIdConnectUrl(openIdConnectSecurityScheme.getOpenIdConnectUrl()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme mutualTlsSecurityScheme(MutualTLSSecurityScheme_v0_3 mutualTlsSecurityScheme) { + org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.newBuilder(); + if (mutualTlsSecurityScheme.getDescription() != null) { + builder.setDescription(mutualTlsSecurityScheme.getDescription()); + } + return builder.build(); + } + + private static org.a2aproject.sdk.compat03.grpc.AgentInterface agentInterface(AgentInterface_v0_3 agentInterface) { + org.a2aproject.sdk.compat03.grpc.AgentInterface.Builder builder = org.a2aproject.sdk.compat03.grpc.AgentInterface.newBuilder(); + if (agentInterface.transport() != null) { + builder.setTransport(agentInterface.transport()); + } + if (agentInterface.url() != null) { + builder.setUrl(agentInterface.url()); + } + return builder.build(); + } + + public static Struct struct(Map map) { + Struct.Builder structBuilder = Struct.newBuilder(); + if (map != null) { + map.forEach((k, v) -> structBuilder.putFields(k, value(v))); + } + return structBuilder.build(); + } + + private static Value value(Object value) { + Value.Builder valueBuilder = Value.newBuilder(); + if (value instanceof String) { + valueBuilder.setStringValue((String) value); + } else if (value instanceof Number) { + valueBuilder.setNumberValue(((Number) value).doubleValue()); + } else if (value instanceof Boolean) { + valueBuilder.setBoolValue((Boolean) value); + } else if (value instanceof Map) { + valueBuilder.setStructValue(struct((Map) value)); + } else if (value instanceof List) { + valueBuilder.setListValue(listValue((List) value)); + } + return valueBuilder.build(); + } + + private static com.google.protobuf.ListValue listValue(List list) { + com.google.protobuf.ListValue.Builder listValueBuilder = com.google.protobuf.ListValue.newBuilder(); + if (list != null) { + list.forEach(o -> listValueBuilder.addValues(value(o))); + } + return listValueBuilder.build(); + } + + public static StreamResponse streamResponse(StreamingEventKind_v0_3 streamingEventKind) { + if (streamingEventKind instanceof TaskStatusUpdateEvent_v0_3) { + return StreamResponse.newBuilder() + .setStatusUpdate(taskStatusUpdateEvent((TaskStatusUpdateEvent_v0_3) streamingEventKind)) + .build(); + } else if (streamingEventKind instanceof TaskArtifactUpdateEvent_v0_3) { + return StreamResponse.newBuilder() + .setArtifactUpdate(taskArtifactUpdateEvent((TaskArtifactUpdateEvent_v0_3) streamingEventKind)) + .build(); + } else if (streamingEventKind instanceof Message_v0_3) { + return StreamResponse.newBuilder() + .setMsg(message((Message_v0_3) streamingEventKind)) + .build(); + } else if (streamingEventKind instanceof Task_v0_3) { + return StreamResponse.newBuilder() + .setTask(task((Task_v0_3) streamingEventKind)) + .build(); + } else { + throw new IllegalArgumentException("Unsupported event type: " + streamingEventKind); + } + } + + public static org.a2aproject.sdk.compat03.grpc.SendMessageResponse taskOrMessage(EventKind_v0_3 eventKind) { + if (eventKind instanceof Task_v0_3) { + return org.a2aproject.sdk.compat03.grpc.SendMessageResponse.newBuilder() + .setTask(task((Task_v0_3) eventKind)) + .build(); + } else if (eventKind instanceof Message_v0_3) { + return org.a2aproject.sdk.compat03.grpc.SendMessageResponse.newBuilder() + .setMsg(message((Message_v0_3) eventKind)) + .build(); + } else { + throw new IllegalArgumentException("Unsupported event type: " + eventKind); + } + } + + public static org.a2aproject.sdk.compat03.grpc.StreamResponse taskOrMessageStream(StreamingEventKind_v0_3 eventKind) { + if (eventKind instanceof Task_v0_3 task) { + return org.a2aproject.sdk.compat03.grpc.StreamResponse.newBuilder() + .setTask(task(task)) + .build(); + } else if (eventKind instanceof Message_v0_3 msg) { + return org.a2aproject.sdk.compat03.grpc.StreamResponse.newBuilder() + .setMsg(message(msg)) + .build(); + } else if (eventKind instanceof TaskArtifactUpdateEvent_v0_3 update) { + return org.a2aproject.sdk.compat03.grpc.StreamResponse.newBuilder() + .setArtifactUpdate(taskArtifactUpdateEvent(update)) + .build(); + } else if (eventKind instanceof TaskStatusUpdateEvent_v0_3 update) { + return org.a2aproject.sdk.compat03.grpc.StreamResponse.newBuilder() + .setStatusUpdate(taskStatusUpdateEvent(update)) + .build(); + } else { + throw new IllegalArgumentException("Unsupported event type: " + eventKind); + } + } + + } + + public static class FromProto { + + public static TaskQueryParams_v0_3 taskQueryParams(org.a2aproject.sdk.compat03.grpc.GetTaskRequestOrBuilder request) { + String name = request.getName(); + String id = name.substring(name.lastIndexOf('/') + 1); + return new TaskQueryParams_v0_3(id, request.getHistoryLength()); + } + + public static TaskIdParams_v0_3 taskIdParams(org.a2aproject.sdk.compat03.grpc.CancelTaskRequestOrBuilder request) { + String name = request.getName(); + String id = name.substring(name.lastIndexOf('/') + 1); + return new TaskIdParams_v0_3(id); + } + + public static MessageSendParams_v0_3 messageSendParams(org.a2aproject.sdk.compat03.grpc.SendMessageRequestOrBuilder request) { + MessageSendParams_v0_3.Builder builder = new MessageSendParams_v0_3.Builder(); + builder.message(message(request.getRequest())); + if (request.hasConfiguration()) { + builder.configuration(messageSendConfiguration(request.getConfiguration())); + } + if (request.hasMetadata()) { + builder.metadata(struct(request.getMetadata())); + } + return builder.build(); + } + + public static TaskPushNotificationConfig_v0_3 taskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequestOrBuilder request) { + return taskPushNotificationConfig(request.getConfig(), true); + } + + public static TaskPushNotificationConfig_v0_3 taskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder config) { + return taskPushNotificationConfig(config, false); + } + + private static TaskPushNotificationConfig_v0_3 taskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfigOrBuilder config, boolean create) { + String name = config.getName(); // "tasks/{id}/pushNotificationConfigs/{push_id}" + String[] parts = name.split("/"); + String taskId = parts[1]; + String configId = ""; + if (create) { + if (parts.length < 3) { + throw new IllegalArgumentException("Invalid name format for TaskPushNotificationConfig: " + name); + } + if (parts.length == 4) { + configId = parts[3]; + } else { + configId = taskId; + } + } else { + if (parts.length < 4) { + throw new IllegalArgumentException("Invalid name format for TaskPushNotificationConfig: " + name); + } + configId = parts[3]; + } + PushNotificationConfig_v0_3 pnc = pushNotification(config.getPushNotificationConfig(), configId); + return new TaskPushNotificationConfig_v0_3(taskId, pnc); + } + + public static GetTaskPushNotificationConfigParams_v0_3 getTaskPushNotificationConfigParams(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequestOrBuilder request) { + String name = request.getName(); // "tasks/{id}/pushNotificationConfigs/{push_id}" + String[] parts = name.split("/"); + String taskId = parts[1]; + String configId; + if (parts.length == 2) { + configId = taskId; + } else if (parts.length < 4) { + throw new IllegalArgumentException("Invalid name format for GetTaskPushNotificationConfigRequest: " + name); + } else { + configId = parts[3]; + } + return new GetTaskPushNotificationConfigParams_v0_3(taskId, configId); + } + + public static TaskIdParams_v0_3 taskIdParams(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequestOrBuilder request) { + String name = request.getName(); + String id = name.substring(name.lastIndexOf('/') + 1); + return new TaskIdParams_v0_3(id); + } + + public static List listTaskPushNotificationConfigParams(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponseOrBuilder response) { + List configs = response.getConfigsList(); + List result = new ArrayList<>(configs.size()); + for(org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig config : configs) { + result.add(taskPushNotificationConfig(config, false)); + } + return result; + } + + public static ListTaskPushNotificationConfigParams_v0_3 listTaskPushNotificationConfigParams(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequestOrBuilder request) { + String parent = request.getParent(); + String id = parent.substring(parent.lastIndexOf('/') + 1); + return new ListTaskPushNotificationConfigParams_v0_3(id); + } + + public static DeleteTaskPushNotificationConfigParams_v0_3 deleteTaskPushNotificationConfigParams(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder request) { + String name = request.getName(); // "tasks/{id}/pushNotificationConfigs/{push_id}" + String[] parts = name.split("/"); + if (parts.length < 4) { + throw new IllegalArgumentException("Invalid name format for DeleteTaskPushNotificationConfigRequest: " + name); + } + String taskId = parts[1]; + String configId = parts[3]; + return new DeleteTaskPushNotificationConfigParams_v0_3(taskId, configId); + } + + private static AgentExtension_v0_3 agentExtension(org.a2aproject.sdk.compat03.grpc.AgentExtensionOrBuilder agentExtension) { + return new AgentExtension_v0_3( + agentExtension.getDescription(), + struct(agentExtension.getParams()), + agentExtension.getRequired(), + agentExtension.getUri() + ); + } + + private static MessageSendConfiguration_v0_3 messageSendConfiguration(org.a2aproject.sdk.compat03.grpc.SendMessageConfigurationOrBuilder sendMessageConfiguration) { + return new MessageSendConfiguration_v0_3( + sendMessageConfiguration.getAcceptedOutputModesList().isEmpty() ? null : + new ArrayList<>(sendMessageConfiguration.getAcceptedOutputModesList()), + sendMessageConfiguration.getHistoryLength(), + pushNotification(sendMessageConfiguration.getPushNotification()), + sendMessageConfiguration.getBlocking() + ); + } + + private static @Nullable PushNotificationConfig_v0_3 pushNotification(org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder pushNotification, String configId) { + if(pushNotification == null || pushNotification.getDefaultInstanceForType().equals(pushNotification)) { + return null; + } + return new PushNotificationConfig_v0_3( + pushNotification.getUrl(), + pushNotification.getToken().isEmpty() ? null : pushNotification.getToken(), + pushNotification.hasAuthentication() ? authenticationInfo(pushNotification.getAuthentication()) : null, + pushNotification.getId().isEmpty() ? configId : pushNotification.getId() + ); + } + + private static @Nullable PushNotificationConfig_v0_3 pushNotification(org.a2aproject.sdk.compat03.grpc.PushNotificationConfigOrBuilder pushNotification) { + return pushNotification(pushNotification, pushNotification.getId()); + } + + private static PushNotificationAuthenticationInfo_v0_3 authenticationInfo(org.a2aproject.sdk.compat03.grpc.AuthenticationInfoOrBuilder authenticationInfo) { + return new PushNotificationAuthenticationInfo_v0_3( + new ArrayList<>(authenticationInfo.getSchemesList()), + authenticationInfo.getCredentials() + ); + } + + public static Task_v0_3 task(org.a2aproject.sdk.compat03.grpc.TaskOrBuilder task) { + return new Task_v0_3( + task.getId(), + task.getContextId(), + taskStatus(task.getStatus()), + task.getArtifactsList().stream().map(item -> artifact(item)).collect(Collectors.toList()), + task.getHistoryList().stream().map(item -> message(item)).collect(Collectors.toList()), + struct(task.getMetadata()) + ); + } + + public static Message_v0_3 message(org.a2aproject.sdk.compat03.grpc.MessageOrBuilder message) { + if (message.getMessageId().isEmpty()) { + throw new InvalidParamsError_v0_3(); + } + + return new Message_v0_3( + role(message.getRole()), + message.getContentList().stream().map(item -> part(item)).collect(Collectors.toList()), + message.getMessageId().isEmpty() ? null : message.getMessageId(), + message.getContextId().isEmpty() ? null : message.getContextId(), + message.getTaskId().isEmpty() ? null : message.getTaskId(), + null, // referenceTaskIds is not in grpc message + struct(message.getMetadata()), + message.getExtensionsList().isEmpty() ? null : message.getExtensionsList() + ); + } + + public static TaskStatusUpdateEvent_v0_3 taskStatusUpdateEvent(org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEventOrBuilder taskStatusUpdateEvent) { + return new TaskStatusUpdateEvent_v0_3.Builder() + .taskId(taskStatusUpdateEvent.getTaskId()) + .status(taskStatus(taskStatusUpdateEvent.getStatus())) + .contextId(taskStatusUpdateEvent.getContextId()) + .isFinal(taskStatusUpdateEvent.getFinal()) + .metadata(struct(taskStatusUpdateEvent.getMetadata())) + .build(); + } + + public static TaskArtifactUpdateEvent_v0_3 taskArtifactUpdateEvent(org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEventOrBuilder taskArtifactUpdateEvent) { + return new TaskArtifactUpdateEvent_v0_3.Builder() + .taskId(taskArtifactUpdateEvent.getTaskId()) + .append(taskArtifactUpdateEvent.getAppend()) + .lastChunk(taskArtifactUpdateEvent.getLastChunk()) + .artifact(artifact(taskArtifactUpdateEvent.getArtifact())) + .contextId(taskArtifactUpdateEvent.getContextId()) + .metadata(struct(taskArtifactUpdateEvent.getMetadata())) + .build(); + } + + private static Artifact_v0_3 artifact(org.a2aproject.sdk.compat03.grpc.ArtifactOrBuilder artifact) { + return new Artifact_v0_3( + artifact.getArtifactId(), + artifact.getName(), + artifact.getDescription(), + artifact.getPartsList().stream().map(item -> part(item)).collect(Collectors.toList()), + struct(artifact.getMetadata()), + artifact.getExtensionsList().isEmpty() ? null : artifact.getExtensionsList() + ); + } + + private static Part_v0_3 part(org.a2aproject.sdk.compat03.grpc.PartOrBuilder part) { + if (part.hasText()) { + return textPart(part.getText()); + } else if (part.hasFile()) { + return filePart(part.getFile()); + } else if (part.hasData()) { + return dataPart(part.getData()); + } + throw new InvalidRequestError_v0_3(); + } + + private static TextPart_v0_3 textPart(String text) { + return new TextPart_v0_3(text); + } + + private static FilePart_v0_3 filePart(org.a2aproject.sdk.compat03.grpc.FilePartOrBuilder filePart) { + if (filePart.hasFileWithBytes()) { + return new FilePart_v0_3(new FileWithBytes_v0_3(filePart.getMimeType(), null, filePart.getFileWithBytes().toStringUtf8())); + } else if (filePart.hasFileWithUri()) { + return new FilePart_v0_3(new FileWithUri_v0_3(filePart.getMimeType(), null, filePart.getFileWithUri())); + } + throw new InvalidRequestError_v0_3(); + } + + private static DataPart_v0_3 dataPart(org.a2aproject.sdk.compat03.grpc.DataPartOrBuilder dataPart) { + return new DataPart_v0_3(struct(dataPart.getData())); + } + + private static @Nullable TaskStatus_v0_3 taskStatus(org.a2aproject.sdk.compat03.grpc.TaskStatusOrBuilder taskStatus) { + TaskState_v0_3 state = taskState(taskStatus.getState()); + if (state == null) { + return null; + } + return new TaskStatus_v0_3( + taskState(taskStatus.getState()), + taskStatus.hasUpdate() ? message(taskStatus.getUpdateOrBuilder()) : null, + OffsetDateTime.ofInstant(Instant.ofEpochSecond(taskStatus.getTimestamp().getSeconds(), taskStatus.getTimestamp().getNanos()), ZoneOffset.UTC) + ); + } + + private static Message_v0_3.@Nullable Role role(org.a2aproject.sdk.compat03.grpc.Role role) { + if (role == null) { + return null; + } + return switch (role) { + case ROLE_USER -> + Message_v0_3.Role.USER; + case ROLE_AGENT -> + Message_v0_3.Role.AGENT; + default -> + throw new InvalidRequestError_v0_3(); + }; + } + + private static @Nullable TaskState_v0_3 taskState(org.a2aproject.sdk.compat03.grpc.TaskState taskState) { + if (taskState == null) { + return null; + } + return switch (taskState) { + case TASK_STATE_SUBMITTED -> + TaskState_v0_3.SUBMITTED; + case TASK_STATE_WORKING -> + TaskState_v0_3.WORKING; + case TASK_STATE_INPUT_REQUIRED -> + TaskState_v0_3.INPUT_REQUIRED; + case TASK_STATE_AUTH_REQUIRED -> + TaskState_v0_3.AUTH_REQUIRED; + case TASK_STATE_COMPLETED -> + TaskState_v0_3.COMPLETED; + case TASK_STATE_CANCELLED -> + TaskState_v0_3.CANCELED; + case TASK_STATE_FAILED -> + TaskState_v0_3.FAILED; + case TASK_STATE_REJECTED -> + TaskState_v0_3.REJECTED; + case TASK_STATE_UNSPECIFIED -> + null; + case UNRECOGNIZED -> + null; + }; + } + + private static @Nullable Map struct(Struct struct) { + if (struct == null || struct.getFieldsCount() == 0) { + return null; + } + return struct.getFieldsMap().entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> value(e.getValue()))); + } + + private static @Nullable Object value(Value value) { + switch (value.getKindCase()) { + case STRUCT_VALUE: + return struct(value.getStructValue()); + case LIST_VALUE: + return value.getListValue().getValuesList().stream() + .map(FromProto::value) + .collect(Collectors.toList()); + case BOOL_VALUE: + return value.getBoolValue(); + case NUMBER_VALUE: + return value.getNumberValue(); + case STRING_VALUE: + return value.getStringValue(); + case NULL_VALUE: + default: + throw new InvalidRequestError_v0_3(); + } + } + } + +} diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/package-info.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/package-info.java new file mode 100644 index 000000000..bd0d8d936 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package org.a2aproject.sdk.compat03.grpc.utils; + +import org.jspecify.annotations.NullMarked; + diff --git a/compat-0.3/spec-grpc/src/main/proto/a2a.proto b/compat-0.3/spec-grpc/src/main/proto/a2a.proto new file mode 100644 index 000000000..89b21a258 --- /dev/null +++ b/compat-0.3/spec-grpc/src/main/proto/a2a.proto @@ -0,0 +1,717 @@ +// Older protoc compilers don't understand edition yet. +syntax = "proto3"; +package a2a.v1; + +import "google/api/annotations.proto"; +import "google/api/client.proto"; +import "google/api/field_behavior.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; + +// Copied from https://github.com/a2aproject/A2A/blob/v0.3.0/specification/grpc/a2a.proto +// The only change is the 'java_package' update + +option csharp_namespace = "A2a.V1"; +option go_package = "google.golang.org/a2a/v1"; +option java_multiple_files = true; +option java_outer_classname = "A2A"; +// Update package from the spec version +option java_package = "org.a2aproject.sdk.compat03.grpc"; + +// A2AService defines the gRPC version of the A2A protocol. This has a slightly +// different shape than the JSONRPC version to better conform to AIP-127, +// where appropriate. The nouns are AgentCard, Message, Task and +// TaskPushNotificationConfig. +// - Messages are not a standard resource so there is no get/delete/update/list +// interface, only a send and stream custom methods. +// - Tasks have a get interface and custom cancel and subscribe methods. +// - TaskPushNotificationConfig are a resource whose parent is a task. +// They have get, list and create methods. +// - AgentCard is a static resource with only a get method. +// fields are not present as they don't comply with AIP rules, and the +// optional history_length on the get task method is not present as it also +// violates AIP-127 and AIP-131. +service A2AService { + // Send a message to the agent. This is a blocking call that will return the + // task once it is completed, or a LRO if requested. + rpc SendMessage(SendMessageRequest) returns (SendMessageResponse) { + option (google.api.http) = { + post: "/v1/message:send" + body: "*" + }; + } + // SendStreamingMessage is a streaming call that will return a stream of + // task update events until the Task is in an interrupted or terminal state. + rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse) { + option (google.api.http) = { + post: "/v1/message:stream" + body: "*" + }; + } + + // Get the current state of a task from the agent. + rpc GetTask(GetTaskRequest) returns (Task) { + option (google.api.http) = { + get: "/v1/{name=tasks/*}" + }; + option (google.api.method_signature) = "name"; + } + // Cancel a task from the agent. If supported one should expect no + // more task updates for the task. + rpc CancelTask(CancelTaskRequest) returns (Task) { + option (google.api.http) = { + post: "/v1/{name=tasks/*}:cancel" + body: "*" + }; + } + // TaskSubscription is a streaming call that will return a stream of task + // update events. This attaches the stream to an existing in process task. + // If the task is complete the stream will return the completed task (like + // GetTask) and close the stream. + rpc TaskSubscription(TaskSubscriptionRequest) + returns (stream StreamResponse) { + option (google.api.http) = { + get: "/v1/{name=tasks/*}:subscribe" + }; + } + + // Set a push notification config for a task. + rpc CreateTaskPushNotificationConfig(CreateTaskPushNotificationConfigRequest) + returns (TaskPushNotificationConfig) { + option (google.api.http) = { + post: "/v1/{parent=task/*/pushNotificationConfigs}" + body: "config" + }; + option (google.api.method_signature) = "parent,config"; + } + // Get a push notification config for a task. + rpc GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest) + returns (TaskPushNotificationConfig) { + option (google.api.http) = { + get: "/v1/{name=tasks/*/pushNotificationConfigs/*}" + }; + option (google.api.method_signature) = "name"; + } + // Get a list of push notifications configured for a task. + rpc ListTaskPushNotificationConfig(ListTaskPushNotificationConfigRequest) + returns (ListTaskPushNotificationConfigResponse) { + option (google.api.http) = { + get: "/v1/{parent=tasks/*}/pushNotificationConfigs" + }; + option (google.api.method_signature) = "parent"; + } + // GetAgentCard returns the agent card for the agent. + rpc GetAgentCard(GetAgentCardRequest) returns (AgentCard) { + option (google.api.http) = { + get: "/v1/card" + }; + } + // Delete a push notification config for a task. + rpc DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest) + returns (google.protobuf.Empty) { + option (google.api.http) = { + delete: "/v1/{name=tasks/*/pushNotificationConfigs/*}" + }; + option (google.api.method_signature) = "name"; + } +} + +///////// Data Model //////////// + +// Configuration of a send message request. +message SendMessageConfiguration { + // The output modes that the agent is expected to respond with. + repeated string accepted_output_modes = 1; + // A configuration of a webhook that can be used to receive updates + PushNotificationConfig push_notification = 2; + // The maximum number of messages to include in the history. if 0, the + // history will be unlimited. + int32 history_length = 3; + // If true, the message will be blocking until the task is completed. If + // false, the message will be non-blocking and the task will be returned + // immediately. It is the caller's responsibility to check for any task + // updates. + bool blocking = 4; +} + +// Task is the core unit of action for A2A. It has a current status +// and when results are created for the task they are stored in the +// artifact. If there are multiple turns for a task, these are stored in +// history. +message Task { + // Unique identifier for a task, created by the A2A server. + string id = 1; + // Unique identifier for the contextual collection of interactions (tasks + // and messages). Created by the A2A server. + string context_id = 2; + // The current status of a Task, including state and a message. + TaskStatus status = 3; + // A set of output artifacts for a Task. + repeated Artifact artifacts = 4; + // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED + // The history of interactions from a task. + repeated Message history = 5; + // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED + // A key/value object to store custom metadata about a task. + google.protobuf.Struct metadata = 6; +} + +// The set of states a Task can be in. +enum TaskState { + TASK_STATE_UNSPECIFIED = 0; + // Represents the status that acknowledges a task is created + TASK_STATE_SUBMITTED = 1; + // Represents the status that a task is actively being processed + TASK_STATE_WORKING = 2; + // Represents the status a task is finished. This is a terminal state + TASK_STATE_COMPLETED = 3; + // Represents the status a task is done but failed. This is a terminal state + TASK_STATE_FAILED = 4; + // Represents the status a task was cancelled before it finished. + // This is a terminal state. + TASK_STATE_CANCELLED = 5; + // Represents the status that the task requires information to complete. + // This is an interrupted state. + TASK_STATE_INPUT_REQUIRED = 6; + // Represents the status that the agent has decided to not perform the task. + // This may be done during initial task creation or later once an agent + // has determined it can't or won't proceed. This is a terminal state. + TASK_STATE_REJECTED = 7; + // Represents the state that some authentication is needed from the upstream + // client. Authentication is expected to come out-of-band thus this is not + // an interrupted or terminal state. + TASK_STATE_AUTH_REQUIRED = 8; +} + +// A container for the status of a task +message TaskStatus { + // The current state of this task + TaskState state = 1; + // A message associated with the status. + Message update = 2 [json_name = "message"]; + // Timestamp when the status was recorded. + // Example: "2023-10-27T10:00:00Z" + google.protobuf.Timestamp timestamp = 3; +} + +// Part represents a container for a section of communication content. +// Parts can be purely textual, some sort of file (image, video, etc) or +// a structured data blob (i.e. JSON). +message Part { + oneof part { + string text = 1; + FilePart file = 2; + DataPart data = 3; + } +} + +// FilePart represents the different ways files can be provided. If files are +// small, directly feeding the bytes is supported via file_with_bytes. If the +// file is large, the agent should read the content as appropriate directly +// from the file_with_uri source. +message FilePart { + oneof file { + string file_with_uri = 1; + bytes file_with_bytes = 2; + } + string mime_type = 3; +} + +// DataPart represents a structured blob. This is most commonly a JSON payload. +message DataPart { + google.protobuf.Struct data = 1; +} + +enum Role { + ROLE_UNSPECIFIED = 0; + // USER role refers to communication from the client to the server. + ROLE_USER = 1; + // AGENT role refers to communication from the server to the client. + ROLE_AGENT = 2; +} + +// Message is one unit of communication between client and server. It is +// associated with a context and optionally a task. Since the server is +// responsible for the context definition, it must always provide a context_id +// in its messages. The client can optionally provide the context_id if it +// knows the context to associate the message to. Similarly for task_id, +// except the server decides if a task is created and whether to include the +// task_id. +message Message { + // The message id of the message. This is required and created by the + // message creator. + string message_id = 1; + // The context id of the message. This is optional and if set, the message + // will be associated with the given context. + string context_id = 2; + // The task id of the message. This is optional and if set, the message + // will be associated with the given task. + string task_id = 3; + // A role for the message. + Role role = 4; + // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED + // Content is the container of the message content. + repeated Part content = 5; + // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED + // Any optional metadata to provide along with the message. + google.protobuf.Struct metadata = 6; + // The URIs of extensions that are present or contributed to this Message. + repeated string extensions = 7; +} + +// Artifacts are the container for task completed results. These are similar +// to Messages but are intended to be the product of a task, as opposed to +// point-to-point communication. +message Artifact { + // Unique id for the artifact. It must be at least unique within a task. + string artifact_id = 1; + // A human readable name for the artifact. + string name = 3; + // A human readable description of the artifact, optional. + string description = 4; + // The content of the artifact. + repeated Part parts = 5; + // Optional metadata included with the artifact. + google.protobuf.Struct metadata = 6; + // The URIs of extensions that are present or contributed to this Artifact. + repeated string extensions = 7; +} + +// TaskStatusUpdateEvent is a delta even on a task indicating that a task +// has changed. +message TaskStatusUpdateEvent { + // The id of the task that is changed + string task_id = 1; + // The id of the context that the task belongs to + string context_id = 2; + // The new status of the task. + TaskStatus status = 3; + // Whether this is the last status update expected for this task. + bool final = 4; + // Optional metadata to associate with the task update. + google.protobuf.Struct metadata = 5; +} + +// TaskArtifactUpdateEvent represents a task delta where an artifact has +// been generated. +message TaskArtifactUpdateEvent { + // The id of the task for this artifact + string task_id = 1; + // The id of the context that this task belongs too + string context_id = 2; + // The artifact itself + Artifact artifact = 3; + // Whether this should be appended to a prior one produced + bool append = 4; + // Whether this represents the last part of an artifact + bool last_chunk = 5; + // Optional metadata associated with the artifact update. + google.protobuf.Struct metadata = 6; +} + +// Configuration for setting up push notifications for task updates. +message PushNotificationConfig { + // A unique id for this push notification. + string id = 1; + // Url to send the notification too + string url = 2; + // Token unique for this task/session + string token = 3; + // Information about the authentication to sent with the notification + AuthenticationInfo authentication = 4; +} + +// Defines authentication details, used for push notifications. +message AuthenticationInfo { + // Supported authentication schemes - e.g. Basic, Bearer, etc + repeated string schemes = 1; + // Optional credentials + string credentials = 2; +} + +// Defines additional transport information for the agent. +message AgentInterface { + // The url this interface is found at. + string url = 1; + // The transport supported this url. This is an open form string, to be + // easily extended for many transport protocols. The core ones officially + // supported are JSONRPC, GRPC and HTTP+JSON. + string transport = 2; +} + +// AgentCard conveys key information: +// - Overall details (version, name, description, uses) +// - Skills; a set of actions/solutions the agent can perform +// - Default modalities/content types supported by the agent. +// - Authentication requirements +// Next ID: 18 +message AgentCard { + // The version of the A2A protocol this agent supports. + string protocol_version = 16; + // A human readable name for the agent. + // Example: "Recipe Agent" + string name = 1; + // A description of the agent's domain of action/solution space. + // Example: "Agent that helps users with recipes and cooking." + string description = 2; + // A URL to the address the agent is hosted at. This represents the + // preferred endpoint as declared by the agent. + string url = 3; + // The transport of the preferred endpoint. If empty, defaults to JSONRPC. + string preferred_transport = 14; + // Announcement of additional supported transports. Client can use any of + // the supported transports. + repeated AgentInterface additional_interfaces = 15; + // The service provider of the agent. + AgentProvider provider = 4; + // The version of the agent. + // Example: "1.0.0" + string version = 5; + // A url to provide additional documentation about the agent. + string documentation_url = 6; + // A2A Capability set supported by the agent. + AgentCapabilities capabilities = 7; + // The security scheme details used for authenticating with this agent. + map security_schemes = 8; + // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED + // Security requirements for contacting the agent. + // This list can be seen as an OR of ANDs. Each object in the list describes + // one possible set of security requirements that must be present on a + // request. This allows specifying, for example, "callers must either use + // OAuth OR an API Key AND mTLS." + // Example: + // security { + // schemes { key: "oauth" value { list: ["read"] } } + // } + // security { + // schemes { key: "api-key" } + // schemes { key: "mtls" } + // } + repeated Security security = 9; + // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED + // The set of interaction modes that the agent supports across all skills. + // This can be overridden per skill. Defined as mime types. + repeated string default_input_modes = 10; + // The mime types supported as outputs from this agent. + repeated string default_output_modes = 11; + // Skills represent a unit of ability an agent can perform. This may + // somewhat abstract but represents a more focused set of actions that the + // agent is highly likely to succeed at. + repeated AgentSkill skills = 12; + // Whether the agent supports providing an extended agent card when + // the user is authenticated, i.e. is the card from .well-known + // different than the card from GetAgentCard. + bool supports_authenticated_extended_card = 13; + // JSON Web Signatures computed for this AgentCard. + repeated AgentCardSignature signatures = 17; +} + +// Represents information about the service provider of an agent. +message AgentProvider { + // The providers reference url + // Example: "https://ai.google.dev" + string url = 1; + // The providers organization name + // Example: "Google" + string organization = 2; +} + +// Defines the A2A feature set supported by the agent +message AgentCapabilities { + // If the agent will support streaming responses + bool streaming = 1; + // If the agent can send push notifications to the clients webhook + bool push_notifications = 2; + // Extensions supported by this agent. + repeated AgentExtension extensions = 3; +} + +// A declaration of an extension supported by an Agent. +message AgentExtension { + // The URI of the extension. + // Example: "https://developers.google.com/identity/protocols/oauth2" + string uri = 1; + // A description of how this agent uses this extension. + // Example: "Google OAuth 2.0 authentication" + string description = 2; + // Whether the client must follow specific requirements of the extension. + // Example: false + bool required = 3; + // Optional configuration for the extension. + google.protobuf.Struct params = 4; +} + +// AgentSkill represents a unit of action/solution that the agent can perform. +// One can think of this as a type of highly reliable solution that an agent +// can be tasked to provide. Agents have the autonomy to choose how and when +// to use specific skills, but clients should have confidence that if the +// skill is defined that unit of action can be reliably performed. +message AgentSkill { + // Unique id of the skill within this agent. + string id = 1; + // A human readable name for the skill. + string name = 2; + // A human (or llm) readable description of the skill + // details and behaviors. + string description = 3; + // A set of tags for the skill to enhance categorization/utilization. + // Example: ["cooking", "customer support", "billing"] + repeated string tags = 4; + // A set of example queries that this skill is designed to address. + // These examples should help the caller to understand how to craft requests + // to the agent to achieve specific goals. + // Example: ["I need a recipe for bread"] + repeated string examples = 5; + // Possible input modalities supported. + repeated string input_modes = 6; + // Possible output modalities produced + repeated string output_modes = 7; + // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED + // Security schemes necessary for the agent to leverage this skill. + // As in the overall AgentCard.security, this list represents a logical OR of + // security requirement objects. Each object is a set of security schemes + // that must be used together (a logical AND). + repeated Security security = 8; +} + +// AgentCardSignature represents a JWS signature of an AgentCard. +// This follows the JSON format of an RFC 7515 JSON Web Signature (JWS). +message AgentCardSignature { + // The protected JWS header for the signature. This is always a + // base64url-encoded JSON object. Required. + string protected = 1 [(google.api.field_behavior) = REQUIRED]; + // The computed signature, base64url-encoded. Required. + string signature = 2 [(google.api.field_behavior) = REQUIRED]; + // The unprotected JWS header values. + google.protobuf.Struct header = 3; +} + +message TaskPushNotificationConfig { + // name=tasks/{id}/pushNotificationConfigs/{id} + string name = 1; + PushNotificationConfig push_notification_config = 2; +} + +// protolint:disable REPEATED_FIELD_NAMES_PLURALIZED +message StringList { + repeated string list = 1; +} +// protolint:enable REPEATED_FIELD_NAMES_PLURALIZED + +message Security { + map schemes = 1; +} + +message SecurityScheme { + oneof scheme { + APIKeySecurityScheme api_key_security_scheme = 1; + HTTPAuthSecurityScheme http_auth_security_scheme = 2; + OAuth2SecurityScheme oauth2_security_scheme = 3; + OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; + MutualTlsSecurityScheme mtls_security_scheme = 5; + } +} + +message APIKeySecurityScheme { + // Description of this security scheme. + string description = 1; + // Location of the API key, valid values are "query", "header", or "cookie" + string location = 2; + // Name of the header, query or cookie parameter to be used. + string name = 3; +} + +message HTTPAuthSecurityScheme { + // Description of this security scheme. + string description = 1; + // The name of the HTTP Authentication scheme to be used in the + // Authorization header as defined in RFC7235. The values used SHOULD be + // registered in the IANA Authentication Scheme registry. + // The value is case-insensitive, as defined in RFC7235. + string scheme = 2; + // A hint to the client to identify how the bearer token is formatted. + // Bearer tokens are usually generated by an authorization server, so + // this information is primarily for documentation purposes. + string bearer_format = 3; +} + +message OAuth2SecurityScheme { + // Description of this security scheme. + string description = 1; + // An object containing configuration information for the flow types supported + OAuthFlows flows = 2; + // URL to the oauth2 authorization server metadata + // [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required. + string oauth2_metadata_url = 3; +} + +message OpenIdConnectSecurityScheme { + // Description of this security scheme. + string description = 1; + // Well-known URL to discover the [[OpenID-Connect-Discovery]] provider + // metadata. + string open_id_connect_url = 2; +} + +message MutualTlsSecurityScheme { + // Description of this security scheme. + string description = 1; +} + +message OAuthFlows { + oneof flow { + AuthorizationCodeOAuthFlow authorization_code = 1; + ClientCredentialsOAuthFlow client_credentials = 2; + ImplicitOAuthFlow implicit = 3; + PasswordOAuthFlow password = 4; + } +} + +message AuthorizationCodeOAuthFlow { + // The authorization URL to be used for this flow. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS + string authorization_url = 1; + // The token URL to be used for this flow. This MUST be in the form of a URL. + // The OAuth2 standard requires the use of TLS. + string token_url = 2; + // The URL to be used for obtaining refresh tokens. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS. + string refresh_url = 3; + // The available scopes for the OAuth2 security scheme. A map between the + // scope name and a short description for it. The map MAY be empty. + map scopes = 4; +} + +message ClientCredentialsOAuthFlow { + // The token URL to be used for this flow. This MUST be in the form of a URL. + // The OAuth2 standard requires the use of TLS. + string token_url = 1; + // The URL to be used for obtaining refresh tokens. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS. + string refresh_url = 2; + // The available scopes for the OAuth2 security scheme. A map between the + // scope name and a short description for it. The map MAY be empty. + map scopes = 3; +} + +message ImplicitOAuthFlow { + // The authorization URL to be used for this flow. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS + string authorization_url = 1; + // The URL to be used for obtaining refresh tokens. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS. + string refresh_url = 2; + // The available scopes for the OAuth2 security scheme. A map between the + // scope name and a short description for it. The map MAY be empty. + map scopes = 3; +} + +message PasswordOAuthFlow { + // The token URL to be used for this flow. This MUST be in the form of a URL. + // The OAuth2 standard requires the use of TLS. + string token_url = 1; + // The URL to be used for obtaining refresh tokens. This MUST be in the + // form of a URL. The OAuth2 standard requires the use of TLS. + string refresh_url = 2; + // The available scopes for the OAuth2 security scheme. A map between the + // scope name and a short description for it. The map MAY be empty. + map scopes = 3; +} + +///////////// Request Messages /////////// +message SendMessageRequest { + Message request = 1 + [(google.api.field_behavior) = REQUIRED, json_name = "message"]; + SendMessageConfiguration configuration = 2; + google.protobuf.Struct metadata = 3; +} + +message GetTaskRequest { + // name=tasks/{id} + string name = 1 [(google.api.field_behavior) = REQUIRED]; + int32 history_length = 2; +} + +message CancelTaskRequest { + // name=tasks/{id} + string name = 1; +} + +message GetTaskPushNotificationConfigRequest { + // name=tasks/{id}/pushNotificationConfigs/{push_id} + string name = 1; +} + +message DeleteTaskPushNotificationConfigRequest { + // name=tasks/{id}/pushNotificationConfigs/{push_id} + string name = 1; +} + +message CreateTaskPushNotificationConfigRequest { + // The task resource for this config. + // Format: tasks/{id} + string parent = 1 [(google.api.field_behavior) = REQUIRED]; + string config_id = 2 [(google.api.field_behavior) = REQUIRED]; + TaskPushNotificationConfig config = 3 + [(google.api.field_behavior) = REQUIRED]; +} + +message TaskSubscriptionRequest { + // name=tasks/{id} + string name = 1; +} + +message ListTaskPushNotificationConfigRequest { + // parent=tasks/{id} + string parent = 1; + // For AIP-158 these fields are present. Usually not used/needed. + // The maximum number of configurations to return. + // If unspecified, all configs will be returned. + int32 page_size = 2; + + // A page token received from a previous + // ListTaskPushNotificationConfigRequest call. + // Provide this to retrieve the subsequent page. + // When paginating, all other parameters provided to + // `ListTaskPushNotificationConfigRequest` must match the call that provided + // the page token. + string page_token = 3; +} + +message GetAgentCardRequest { + // Empty. Added to fix linter violation. +} + +//////// Response Messages /////////// +message SendMessageResponse { + oneof payload { + Task task = 1; + Message msg = 2 [json_name = "message"]; + } +} + +// The stream response for a message. The stream should be one of the following +// sequences: +// If the response is a message, the stream should contain one, and only one, +// message and then close +// If the response is a task lifecycle, the first response should be a Task +// object followed by zero or more TaskStatusUpdateEvents and +// TaskArtifactUpdateEvents. The stream should complete when the Task +// if in an interrupted or terminal state. A stream that ends before these +// conditions are met are +message StreamResponse { + oneof payload { + Task task = 1; + Message msg = 2 [json_name = "message"]; + TaskStatusUpdateEvent status_update = 3; + TaskArtifactUpdateEvent artifact_update = 4; + } +} + +message ListTaskPushNotificationConfigResponse { + repeated TaskPushNotificationConfig configs = 1; + // A token, which can be sent as `page_token` to retrieve the next page. + // If this field is omitted, there are no subsequent pages. + string next_page_token = 2; +} diff --git a/compat-0.3/spec-grpc/src/main/resources/META-INF/beans.xml b/compat-0.3/spec-grpc/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..e69de29bb diff --git a/compat-0.3/spec-grpc/src/test/java/org/a2aproject/sdk/compat03/grpc/utils/ToProto_v0_3_Test.java b/compat-0.3/spec-grpc/src/test/java/org/a2aproject/sdk/compat03/grpc/utils/ToProto_v0_3_Test.java new file mode 100644 index 000000000..f4b7d9204 --- /dev/null +++ b/compat-0.3/spec-grpc/src/test/java/org/a2aproject/sdk/compat03/grpc/utils/ToProto_v0_3_Test.java @@ -0,0 +1,292 @@ +package org.a2aproject.sdk.compat03.grpc.utils; + +import static org.a2aproject.sdk.compat03.grpc.Role.ROLE_AGENT; +import static org.a2aproject.sdk.compat03.grpc.Role.ROLE_USER; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.time.OffsetDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.compat03.grpc.SendMessageConfiguration; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendConfiguration_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationAuthenticationInfo_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.junit.jupiter.api.Test; + +public class ToProto_v0_3_Test { + + private static final Message_v0_3 SIMPLE_MESSAGE = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(Collections.singletonList(new TextPart_v0_3("tell me a joke"))) + .contextId("context-1234") + .messageId("message-1234") + .build(); + + @Test + public void convertAgentCard() { + AgentCard_v0_3 agentCard = new AgentCard_v0_3.Builder() + .name("Hello World Agent") + .description("Just a hello world agent") + .url("http://localhost:9999") + .version("1.0.0") + .documentationUrl("http://example.com/docs") + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(true) + .pushNotifications(true) + .stateTransitionHistory(true) + .build()) + .defaultInputModes(Collections.singletonList("text")) + .defaultOutputModes(Collections.singletonList("text")) + .skills(Collections.singletonList(new AgentSkill_v0_3.Builder() + .id("hello_world") + .name("Returns hello world") + .description("just returns hello world") + .tags(Collections.singletonList("hello world")) + .examples(List.of("hi", "hello world")) + .build())) + .protocolVersion("0.2.5") + .build(); + org.a2aproject.sdk.compat03.grpc.AgentCard result = ProtoUtils_v0_3.ToProto.agentCard(agentCard); + assertEquals("Hello World Agent", result.getName()); + assertEquals("Just a hello world agent", result.getDescription()); + assertEquals("http://localhost:9999", result.getUrl()); + assertEquals("1.0.0", result.getVersion()); + assertEquals("http://example.com/docs", result.getDocumentationUrl()); + assertEquals(1, result.getDefaultInputModesCount()); + assertEquals("text", result.getDefaultInputModes(0)); + assertEquals(1, result.getDefaultOutputModesCount()); + assertEquals("text", result.getDefaultOutputModes(0)); + assertEquals("0.2.5", result.getProtocolVersion()); + agentCard = new AgentCard_v0_3.Builder() + .name("Hello World Agent") + .description("Just a hello world agent") + .url("http://localhost:9999") + .version("1.0.0") + .documentationUrl("http://example.com/docs") + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(true) + .pushNotifications(true) + .stateTransitionHistory(true) + .build()) + .defaultInputModes(Collections.singletonList("text")) + .defaultOutputModes(Collections.singletonList("text")) + .skills(Collections.singletonList(new AgentSkill_v0_3.Builder() + .id("hello_world") + .name("Returns hello world") + .description("just returns hello world") + .tags(Collections.singletonList("hello world")) + .examples(List.of("hi", "hello world")) + .build())) + .preferredTransport("HTTP+JSON") +// .iconUrl("http://example.com/icon.svg") + .securitySchemes(Map.of("basic", new HTTPAuthSecurityScheme_v0_3.Builder().scheme("basic").description("Basic Auth").build())) + .security(List.of(Map.of("oauth", List.of("read")))) + .protocolVersion("0.2.5") + .build(); + result = ProtoUtils_v0_3.ToProto.agentCard(agentCard); + assertEquals("Hello World Agent", result.getName()); + assertEquals("Just a hello world agent", result.getDescription()); + assertEquals("http://localhost:9999", result.getUrl()); + assertEquals("1.0.0", result.getVersion()); + assertEquals("http://example.com/docs", result.getDocumentationUrl()); + assertEquals(1, result.getDefaultInputModesCount()); + assertEquals("text", result.getDefaultInputModes(0)); + assertEquals(1, result.getDefaultOutputModesCount()); + assertEquals("text", result.getDefaultOutputModes(0)); + assertEquals("0.2.5", result.getProtocolVersion()); + assertEquals("HTTP+JSON", result.getPreferredTransport()); + assertEquals(1, result.getSecurityCount()); + assertEquals(1, result.getSecurity(0).getSchemesMap().size()); + assertEquals(true, result.getSecurity(0).getSchemesMap().containsKey("oauth")); + assertEquals(1, result.getSecurity(0).getSchemesMap().get("oauth").getListCount()); + assertEquals("read", result.getSecurity(0).getSchemesMap().get("oauth").getList(0)); + assertEquals(1, result.getSecuritySchemesMap().size()); + assertEquals(true, result.getSecuritySchemesMap().containsKey("basic")); + assertEquals(result.getSecuritySchemesMap().get("basic").getApiKeySecurityScheme().getDefaultInstanceForType(), result.getSecuritySchemesMap().get("basic").getApiKeySecurityScheme()); + assertEquals(result.getSecuritySchemesMap().get("basic").getOauth2SecurityScheme().getDefaultInstanceForType(), result.getSecuritySchemesMap().get("basic").getOauth2SecurityScheme()); + assertEquals("basic", result.getSecuritySchemesMap().get("basic").getHttpAuthSecurityScheme().getScheme()); + assertEquals("Basic Auth", result.getSecuritySchemesMap().get("basic").getHttpAuthSecurityScheme().getDescription()); + } + + @Test + public void convertTask() { + Task_v0_3 task = new Task_v0_3.Builder().id("cancel-task-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + org.a2aproject.sdk.compat03.grpc.Task result = ProtoUtils_v0_3.ToProto.task(task); + assertEquals("session-xyz", result.getContextId()); + assertEquals("cancel-task-123", result.getId()); + assertEquals(org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_SUBMITTED, result.getStatus().getState()); + assertEquals(0, result.getArtifactsCount()); + assertEquals(0, result.getHistoryCount()); + task = new Task_v0_3.Builder().id("cancel-task-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .artifacts(List.of(new Artifact_v0_3.Builder() + .artifactId("11") + .name("artefact") + .parts(new TextPart_v0_3("text")) + .build())) + .history(List.of(SIMPLE_MESSAGE)) + .metadata(Collections.emptyMap()) + .build(); + result = ProtoUtils_v0_3.ToProto.task(task); + assertEquals("session-xyz", result.getContextId()); + assertEquals("cancel-task-123", result.getId()); + assertEquals(org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_SUBMITTED, result.getStatus().getState()); + assertEquals(1, result.getArtifactsCount()); + assertEquals("11", result.getArtifacts(0).getArtifactId()); + assertEquals("artefact", result.getArtifacts(0).getName()); + assertEquals(1, result.getArtifacts(0).getPartsCount()); + assertEquals(true, result.getArtifacts(0).getParts(0).hasText()); + assertEquals(false, result.getArtifacts(0).getParts(0).hasFile()); + assertEquals(false, result.getArtifacts(0).getParts(0).hasData()); + assertEquals("text", result.getArtifacts(0).getParts(0).getText()); + assertEquals(1, result.getHistoryCount()); + assertEquals("context-1234", result.getHistory(0).getContextId()); + assertEquals("message-1234", result.getHistory(0).getMessageId()); + assertEquals(ROLE_USER, result.getHistory(0).getRole()); + assertEquals(1, result.getHistory(0).getContentCount()); + assertEquals("tell me a joke", result.getHistory(0).getContent(0).getText()); + assertEquals(org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(), result.getHistory(0).getContent(0).getFile()); + assertEquals(org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(), result.getHistory(0).getContent(0).getData()); + } + + @Test + public void convertMessage() { + org.a2aproject.sdk.compat03.grpc.Message result = ProtoUtils_v0_3.ToProto.message(SIMPLE_MESSAGE); + assertEquals("context-1234", result.getContextId()); + assertEquals("message-1234", result.getMessageId()); + assertEquals(ROLE_USER, result.getRole()); + assertEquals(1, result.getContentCount()); + assertEquals("tell me a joke", result.getContent(0).getText()); + assertEquals(org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(), result.getContent(0).getFile()); + assertEquals(org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(), result.getContent(0).getData()); + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.AGENT) + .parts(Collections.singletonList(new TextPart_v0_3("tell me a joke"))) + .messageId("message-1234") + .build(); + result = ProtoUtils_v0_3.ToProto.message(message); + assertEquals("", result.getContextId()); + assertEquals("message-1234", result.getMessageId()); + assertEquals(ROLE_AGENT, result.getRole()); + assertEquals(1, result.getContentCount()); + assertEquals("tell me a joke", result.getContent(0).getText()); + assertEquals(org.a2aproject.sdk.compat03.grpc.FilePart.getDefaultInstance(), result.getContent(0).getFile()); + assertEquals(org.a2aproject.sdk.compat03.grpc.DataPart.getDefaultInstance(), result.getContent(0).getData()); + } + + @Test + public void convertTaskPushNotificationConfig() { + TaskPushNotificationConfig_v0_3 taskPushConfig = new TaskPushNotificationConfig_v0_3("push-task-123", + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id("xyz") + .build()); + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig result = ProtoUtils_v0_3.ToProto.taskPushNotificationConfig(taskPushConfig); + assertEquals("tasks/push-task-123/pushNotificationConfigs/xyz", result.getName()); + assertNotNull(result.getPushNotificationConfig()); + assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); + assertEquals("xyz", result.getPushNotificationConfig().getId()); + assertEquals(false, result.getPushNotificationConfig().hasAuthentication()); + taskPushConfig + = new TaskPushNotificationConfig_v0_3("push-task-123", + new PushNotificationConfig_v0_3.Builder() + .token("AAAAAA") + .authenticationInfo(new PushNotificationAuthenticationInfo_v0_3(Collections.singletonList("jwt"), "credentials")) + .url("http://example.com") + .id("xyz") + .build()); + result = ProtoUtils_v0_3.ToProto.taskPushNotificationConfig(taskPushConfig); + assertEquals("tasks/push-task-123/pushNotificationConfigs/xyz", result.getName()); + assertNotNull(result.getPushNotificationConfig()); + assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); + assertEquals("xyz", result.getPushNotificationConfig().getId()); + assertEquals("AAAAAA", result.getPushNotificationConfig().getToken()); + assertEquals(true, result.getPushNotificationConfig().hasAuthentication()); + assertEquals("credentials", result.getPushNotificationConfig().getAuthentication().getCredentials()); + assertEquals(1, result.getPushNotificationConfig().getAuthentication().getSchemesCount()); + assertEquals("jwt", result.getPushNotificationConfig().getAuthentication().getSchemes(0)); + } + + @Test + public void convertTaskArtifactUpdateEvent() { + TaskArtifactUpdateEvent_v0_3 task = new TaskArtifactUpdateEvent_v0_3.Builder() + .taskId("task-123") + .contextId("session-123") + .artifact(new Artifact_v0_3.Builder() + .artifactId("11") + .parts(new TextPart_v0_3("text")) + .build()).build(); + org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent result = ProtoUtils_v0_3.ToProto.taskArtifactUpdateEvent(task); + assertEquals("task-123", result.getTaskId()); + assertEquals("session-123", result.getContextId()); + assertNotNull(result.getArtifact()); + assertEquals("11", result.getArtifact().getArtifactId()); + assertEquals(1, result.getArtifact().getPartsCount()); + assertEquals("text", result.getArtifact().getParts(0).getText()); + } + + @Test + public void convertTaskStatusUpdateEvent() { + TaskStatusUpdateEvent_v0_3 tsue = new TaskStatusUpdateEvent_v0_3.Builder() + .taskId("1234") + .contextId("xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .isFinal(true) + .build(); + org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent result = ProtoUtils_v0_3.ToProto.taskStatusUpdateEvent(tsue); + assertEquals("1234", result.getTaskId()); + assertEquals("xyz", result.getContextId()); + assertEquals(true, result.getFinal()); + assertEquals(org.a2aproject.sdk.compat03.grpc.TaskState.TASK_STATE_COMPLETED, result.getStatus().getState()); + } + + @Test + public void convertSendMessageConfiguration() { + MessageSendConfiguration_v0_3 configuration = new MessageSendConfiguration_v0_3.Builder() + .acceptedOutputModes(List.of("text")) + .blocking(false) + .build(); + SendMessageConfiguration result = ProtoUtils_v0_3.ToProto.messageSendConfiguration(configuration); + assertEquals(false, result.getBlocking()); + assertEquals(1, result.getAcceptedOutputModesCount()); + assertEquals("text", result.getAcceptedOutputModesBytes(0).toStringUtf8()); + } + + @Test + public void convertTaskTimestampStatus() { + OffsetDateTime expectedTimestamp = OffsetDateTime.parse("2024-10-05T12:34:56Z"); + TaskStatus_v0_3 testStatus = new TaskStatus_v0_3(TaskState_v0_3.COMPLETED, null, expectedTimestamp); + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(testStatus) + .build(); + + org.a2aproject.sdk.compat03.grpc.Task grpcTask = ProtoUtils_v0_3.ToProto.task(task); + task = ProtoUtils_v0_3.FromProto.task(grpcTask); + TaskStatus_v0_3 status = task.getStatus(); + assertEquals(TaskState_v0_3.COMPLETED, status.state()); + assertNotNull(status.timestamp()); + assertEquals(expectedTimestamp, status.timestamp()); + } +} diff --git a/compat-0.3/spec/pom.xml b/compat-0.3/spec/pom.xml new file mode 100644 index 000000000..045ebaa50 --- /dev/null +++ b/compat-0.3/spec/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + .. + + a2a-java-sdk-compat-0.3-spec + + jar + + Java SDK A2A Compat 0.3 Spec + Java SDK for the Agent2Agent Protocol (A2A) - Spec + + + + ${project.groupId} + a2a-java-sdk-common + + + com.google.code.gson + gson + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + + \ No newline at end of file diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/common/A2AHeaders_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/common/A2AHeaders_v0_3.java new file mode 100644 index 000000000..9c73d55b7 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/common/A2AHeaders_v0_3.java @@ -0,0 +1,18 @@ +package org.a2aproject.sdk.compat03.common; + +/** + * A2A Protocol v0.3 specific headers. + * These headers differ from the current protocol version. + */ +public final class A2AHeaders_v0_3 { + + /** + * HTTP header name for A2A extensions in protocol v0.3. + * Note: In current versions this is "A2A-Extensions" without the "X-" prefix. + */ + public static final String X_A2A_EXTENSIONS = "X-A2A-Extensions"; + + private A2AHeaders_v0_3() { + // Utility class + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonMappingException_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonMappingException_v0_3.java new file mode 100644 index 000000000..c03399149 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonMappingException_v0_3.java @@ -0,0 +1,102 @@ +package org.a2aproject.sdk.compat03.json; + +import org.jspecify.annotations.Nullable; + +/** + * Exception for JSON mapping errors when converting between JSON and Java objects. + *

            + * This exception serves as a replacement for Jackson's JsonMappingException, allowing + * the A2A Java SDK to remain independent of any specific JSON library implementation. + * It represents errors that occur during the mapping phase of deserialization or + * serialization, such as type mismatches, invalid values, or constraint violations. + *

            + * This exception extends {@link JsonProcessingException_v0_3} and is used for more specific + * mapping-related errors compared to general parsing errors. + *

            + * Usage example: + *

            {@code
            + * try {
            + *     Task task = JsonUtil.fromJson(json, Task.class);
            + *     if (task.getId() == null) {
            + *         throw new JsonMappingException(null, "Task ID cannot be null");
            + *     }
            + * } catch (JsonProcessingException e) {
            + *     throw new JsonMappingException(null, "Invalid task format: " + e.getMessage(), e);
            + * }
            + * }
            + * + * @see JsonProcessingException_v0_3 for the base exception class + */ +public class JsonMappingException_v0_3 extends JsonProcessingException_v0_3 { + + /** + * Optional reference object that caused the mapping error (e.g., JsonParser or field path). + */ + private final @Nullable Object reference; + + /** + * Constructs a new JsonMappingException with the specified reference and message. + *

            + * The reference parameter can be used to provide context about where the mapping + * error occurred (e.g., a field name, path, or parser reference). It can be null + * if no specific reference is available. + * + * @param reference optional reference object providing context for the error (may be null) + * @param message the detail message explaining the mapping error + */ + public JsonMappingException_v0_3(@Nullable Object reference, String message) { + super(message); + this.reference = reference; + } + + /** + * Constructs a new JsonMappingException with the specified reference, message, and cause. + *

            + * The reference parameter can be used to provide context about where the mapping + * error occurred (e.g., a field name, path, or parser reference). It can be null + * if no specific reference is available. + * + * @param reference optional reference object providing context for the error (may be null) + * @param message the detail message explaining the mapping error + * @param cause the underlying cause of the mapping error (may be null) + */ + public JsonMappingException_v0_3(@Nullable Object reference, String message, @Nullable Throwable cause) { + super(message, cause); + this.reference = reference; + } + + /** + * Constructs a new JsonMappingException with the specified message and cause. + *

            + * This constructor is provided for compatibility when no reference object is needed. + * + * @param message the detail message explaining the mapping error + * @param cause the underlying cause of the mapping error (may be null) + */ + public JsonMappingException_v0_3(String message, @Nullable Throwable cause) { + this(null, message, cause); + } + + /** + * Constructs a new JsonMappingException with the specified message. + *

            + * This constructor is provided for compatibility when no reference object is needed. + * + * @param message the detail message explaining the mapping error + */ + public JsonMappingException_v0_3(String message) { + this(null, message); + } + + /** + * Returns the reference object that provides context for the mapping error. + *

            + * This may be null if no specific reference was available when the exception + * was created. + * + * @return the reference object, or null if not available + */ + public @Nullable Object getReference() { + return reference; + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonProcessingException_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonProcessingException_v0_3.java new file mode 100644 index 000000000..3d33f103c --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonProcessingException_v0_3.java @@ -0,0 +1,55 @@ +package org.a2aproject.sdk.compat03.json; + +import org.jspecify.annotations.Nullable; + +/** + * General exception for JSON processing errors during serialization or deserialization. + *

            + * This exception serves as a replacement for Jackson's JsonProcessingException, allowing + * the A2A Java SDK to remain independent of any specific JSON library implementation. + * It can be used with any JSON processing library (Gson, Jackson, etc.). + *

            + * This is the base class for more specific JSON processing exceptions like + * {@link JsonMappingException_v0_3}. + *

            + * Usage example: + *

            {@code
            + * try {
            + *     String json = gson.toJson(object);
            + * } catch (Exception e) {
            + *     throw new JsonProcessingException("Failed to serialize object", e);
            + * }
            + * }
            + * + * @see JsonMappingException_v0_3 for mapping-specific errors + */ +public class JsonProcessingException_v0_3 extends Exception { + + /** + * Constructs a new JsonProcessingException with the specified message. + * + * @param message the detail message explaining the cause of the exception + */ + public JsonProcessingException_v0_3(String message) { + super(message); + } + + /** + * Constructs a new JsonProcessingException with the specified message and cause. + * + * @param message the detail message explaining the cause of the exception + * @param cause the underlying cause of the exception (may be null) + */ + public JsonProcessingException_v0_3(String message, @Nullable Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new JsonProcessingException with the specified cause. + * + * @param cause the underlying cause of the exception + */ + public JsonProcessingException_v0_3(Throwable cause) { + super(cause); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java new file mode 100644 index 000000000..b28ee7f64 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java @@ -0,0 +1,1048 @@ +package org.a2aproject.sdk.compat03.json; + +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.INTERNAL_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.INVALID_AGENT_RESPONSE_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.INVALID_PARAMS_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.INVALID_REQUEST_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.JSON_PARSE_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.METHOD_NOT_FOUND_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.TASK_NOT_CANCELABLE_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.TASK_NOT_FOUND_ERROR_CODE; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.UNSUPPORTED_OPERATION_ERROR_CODE; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; +import com.google.gson.ToNumberPolicy; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import org.a2aproject.sdk.compat03.spec.APIKeySecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.DataPart_v0_3; +import org.a2aproject.sdk.compat03.spec.FileContent_v0_3; +import org.a2aproject.sdk.compat03.spec.FilePart_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithBytes_v0_3; +import org.a2aproject.sdk.compat03.spec.FileWithUri_v0_3; +import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.MutualTLSSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.OAuth2SecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.OpenIdConnectSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.SecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +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.List; +import org.jspecify.annotations.Nullable; + +import static org.a2aproject.sdk.compat03.json.JsonUtil_v0_3.JSONRPCErrorTypeAdapter.THROWABLE_MARKER_FIELD; + +public class JsonUtil_v0_3 { + + private static GsonBuilder createBaseGsonBuilder() { + return new GsonBuilder() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) + // Register JSONRPCError hierarchy adapter for all error subclasses + .registerTypeHierarchyAdapter(JSONRPCError_v0_3.class, new JSONRPCErrorTypeAdapter()) + // Register Throwable adapter for EXACT Throwable.class only (not subclasses) + // This prevents it from being used for JSONRPCError which extends Throwable + .registerTypeAdapter(Throwable.class, new ThrowableTypeAdapter()) + .registerTypeAdapter(TaskState_v0_3.class, new TaskStateTypeAdapter()) + .registerTypeAdapter(Message_v0_3.Role.class, new RoleTypeAdapter()) + .registerTypeAdapter(Part_v0_3.Kind.class, new PartKindTypeAdapter()) + .registerTypeHierarchyAdapter(FileContent_v0_3.class, new FileContentTypeAdapter()) + .registerTypeHierarchyAdapter(SecurityScheme_v0_3.class, new SecuritySchemeTypeAdapter()) + .registerTypeAdapter(void.class, new VoidTypeAdapter()) + .registerTypeAdapter(Void.class, new VoidTypeAdapter()) + .registerTypeAdapterFactory(new JSONRPCResponseTypeAdapterFactory()) + .registerTypeAdapter(AgentCapabilities_v0_3.class, new AgentCapabilitiesTypeAdapter()); + } + + /** + * Pre-configured {@link Gson} instance for JSON operations. + *

            + * This mapper is configured with strict parsing mode and all necessary custom TypeAdapters + * for A2A Protocol types including polymorphic types, enums, and date/time types. + *

            + * Used throughout the SDK for consistent JSON serialization and deserialization. + */ + public static final Gson OBJECT_MAPPER = createBaseGsonBuilder() + .registerTypeHierarchyAdapter(Part_v0_3.class, new PartTypeAdapter()) + .registerTypeHierarchyAdapter(StreamingEventKind_v0_3.class, new StreamingEventKindTypeAdapter()) + .registerTypeAdapter(EventKind_v0_3.class, new EventKindTypeAdapter()) + .create(); + + public static T fromJson(String json, Class classOfT) throws JsonProcessingException_v0_3 { + try { + return OBJECT_MAPPER.fromJson(json, classOfT); + } catch (JsonSyntaxException e) { + throw new JsonProcessingException_v0_3("Failed to parse JSON", e); + } + } + + public static T fromJson(String json, Type type) throws JsonProcessingException_v0_3 { + try { + return OBJECT_MAPPER.fromJson(json, type); + } catch (JsonSyntaxException e) { + throw new JsonProcessingException_v0_3("Failed to parse JSON", e); + } + } + + /** + * Serializes an object to a JSON string using Gson. + *

            + * This method uses the pre-configured {@link #OBJECT_MAPPER} to produce + * JSON representation of the provided object. + * + * @param data the object to serialize + * @return JSON string representation of the object + */ + public static String toJson(Object data) throws JsonProcessingException_v0_3 { + try { + return OBJECT_MAPPER.toJson(data); + } catch (JsonSyntaxException e) { + throw new JsonProcessingException_v0_3("Failed to generate JSON", e); + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link OffsetDateTime} to/from ISO-8601 format. + *

            + * This adapter ensures that OffsetDateTime instances are serialized to ISO-8601 formatted strings + * (e.g., "2023-10-01T12:00:00.234-05:00") and deserialized from the same format. + * This is necessary because Gson cannot access private fields of java.time classes via reflection + * in Java 17+ due to module system restrictions. + *

            + * The adapter uses {@link DateTimeFormatter#ISO_OFFSET_DATE_TIME} for both serialization and + * deserialization, which ensures proper handling of timezone offsets. + * + * @see OffsetDateTime + * @see DateTimeFormatter#ISO_OFFSET_DATE_TIME + */ + static class OffsetDateTimeTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, OffsetDateTime value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(value.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); + } + } + + @Override + public @Nullable + OffsetDateTime read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + String dateTimeString = in.nextString(); + try { + return OffsetDateTime.parse(dateTimeString, DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } catch (DateTimeParseException e) { + throw new JsonSyntaxException("Failed to parse OffsetDateTime: " + dateTimeString, e); + } + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link Throwable} and its subclasses. + *

            + * This adapter avoids reflection into {@link Throwable}'s private fields, which is not allowed + * in Java 17+ due to module system restrictions. Instead, it serializes Throwables as simple + * objects containing only the type (fully qualified class name) and message. + *

            + * Serialization: Converts a Throwable to a JSON object with: + *

              + *
            • "type": The fully qualified class name (e.g., "java.lang.IllegalArgumentException")
            • + *
            • "message": The exception message
            • + *
            + *

            + * Deserialization: Reads the JSON and reconstructs the Throwable using reflection to find + * a constructor that accepts a String message parameter. If no such constructor exists or if + * instantiation fails, returns a generic {@link RuntimeException} with the message. + * + * @see Throwable + */ + static class ThrowableTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, Throwable value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + out.beginObject(); + out.name("type").value(value.getClass().getName()); + out.name("message").value(value.getMessage()); + out.name(THROWABLE_MARKER_FIELD).value(true); + out.endObject(); + } + + @Override + public @Nullable + Throwable read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + + String type = null; + String message = null; + + in.beginObject(); + while (in.hasNext()) { + String fieldName = in.nextName(); + switch (fieldName) { + case "type" -> + type = in.nextString(); + case "message" -> + message = in.nextString(); + default -> + in.skipValue(); + } + } + in.endObject(); + + // Try to reconstruct the Throwable + if (type != null) { + try { + Class throwableClass = Class.forName(type); + if (Throwable.class.isAssignableFrom(throwableClass)) { + // Try to find a constructor that takes a String message + try { + var constructor = throwableClass.getConstructor(String.class); + return (Throwable) constructor.newInstance(message); + } catch (NoSuchMethodException e) { + // No String constructor, return a generic RuntimeException + return new RuntimeException(message); + } + } + } catch (Exception e) { + // If we can't reconstruct the exact type, return a generic RuntimeException + return new RuntimeException(message); + } + } + return new RuntimeException(message); + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link JSONRPCError_v0_3} and its subclasses. + *

            + * This adapter handles polymorphic deserialization based on the error code, creating the + * appropriate subclass instance. + *

            + * The adapter maps error codes to their corresponding error classes: + *

              + *
            • -32700: {@link JSONParseError_v0_3}
            • + *
            • -32600: {@link InvalidRequestError_v0_3}
            • + *
            • -32601: {@link MethodNotFoundError_v0_3}
            • + *
            • -32602: {@link InvalidParamsError_v0_3}
            • + *
            • -32603: {@link InternalError}
            • + *
            • -32001: {@link TaskNotFoundError_v0_3}
            • + *
            • -32002: {@link TaskNotCancelableError_v0_3}
            • + *
            • -32003: {@link PushNotificationNotSupportedError_v0_3}
            • + *
            • -32004: {@link UnsupportedOperationError_v0_3}
            • + *
            • -32005: {@link ContentTypeNotSupportedError_v0_3}
            • + *
            • -32006: {@link InvalidAgentResponseError_v0_3}
            • + *
            • Other codes: {@link JSONRPCError_v0_3}
            • + *
            + * + * @see JSONRPCError_v0_3 + */ + static class JSONRPCErrorTypeAdapter extends TypeAdapter { + + private static final ThrowableTypeAdapter THROWABLE_ADAPTER = new ThrowableTypeAdapter(); + static final String THROWABLE_MARKER_FIELD = "__throwable"; + private static final String CODE_FIELD = "code"; + private static final String DATA_FIELD = "data"; + private static final String MESSAGE_FIELD = "message"; + private static final String TYPE_FIELD = "type"; + + @Override + public void write(JsonWriter out, JSONRPCError_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + out.beginObject(); + out.name(CODE_FIELD).value(value.getCode()); + out.name(MESSAGE_FIELD).value(value.getMessage()); + if (value.getData() != null) { + out.name(DATA_FIELD); + // If data is a Throwable, use ThrowableTypeAdapter to avoid reflection issues + if (value.getData() instanceof Throwable throwable) { + THROWABLE_ADAPTER.write(out, throwable); + } else { + // Use Gson to serialize the data field for non-Throwable types + OBJECT_MAPPER.toJson(value.getData(), Object.class, out); + } + } + out.endObject(); + } + + @Override + public @Nullable + JSONRPCError_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + + Integer code = null; + String message = null; + Object data = null; + + in.beginObject(); + while (in.hasNext()) { + String fieldName = in.nextName(); + switch (fieldName) { + case CODE_FIELD -> + code = in.nextInt(); + case MESSAGE_FIELD -> + message = in.nextString(); + case DATA_FIELD -> { + // Read data as a generic object (could be string, number, object, etc.) + data = readDataValue(in); + } + default -> + in.skipValue(); + } + } + in.endObject(); + + // Create the appropriate subclass based on the error code + return createErrorInstance(code, message, data); + } + + /** + * Reads the data field value, which can be of any JSON type. + */ + private @Nullable + Object readDataValue(JsonReader in) throws java.io.IOException { + return switch (in.peek()) { + case STRING -> + in.nextString(); + case NUMBER -> + in.nextDouble(); + case BOOLEAN -> + in.nextBoolean(); + case NULL -> { + in.nextNull(); + yield null; + } + case BEGIN_OBJECT -> { + // Parse as JsonElement to check if it's a Throwable + com.google.gson.JsonElement element = com.google.gson.JsonParser.parseReader(in); + if (element.isJsonObject()) { + com.google.gson.JsonObject obj = element.getAsJsonObject(); + // Check if it has the structure of a serialized Throwable (type + message) + if (obj.has(TYPE_FIELD) && obj.has(MESSAGE_FIELD) && obj.has(THROWABLE_MARKER_FIELD)) { + // Deserialize as Throwable using ThrowableTypeAdapter + yield THROWABLE_ADAPTER.read(new JsonReader(new StringReader(element.toString()))); + } + } + // Otherwise, deserialize as generic object + yield OBJECT_MAPPER.fromJson(element, Object.class); + } + case BEGIN_ARRAY -> + // For arrays, read as raw JSON using Gson + OBJECT_MAPPER.fromJson(in, Object.class); + default -> { + in.skipValue(); + yield null; + } + }; + } + + /** + * Creates the appropriate JSONRPCError subclass based on the error code. + */ + private JSONRPCError_v0_3 createErrorInstance(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + if (code == null) { + throw new JsonSyntaxException("JSONRPCError must have a code field"); + } + + return switch (code) { + case JSON_PARSE_ERROR_CODE -> + new JSONParseError_v0_3(code, message, data); + case INVALID_REQUEST_ERROR_CODE -> + new InvalidRequestError_v0_3(code, message, data); + case METHOD_NOT_FOUND_ERROR_CODE -> + new MethodNotFoundError_v0_3(code, message, data); + case INVALID_PARAMS_ERROR_CODE -> + new InvalidParamsError_v0_3(code, message, data); + case INTERNAL_ERROR_CODE -> + new InternalError_v0_3(code, message, data); + case TASK_NOT_FOUND_ERROR_CODE -> + new TaskNotFoundError_v0_3(code, message, data); + case TASK_NOT_CANCELABLE_ERROR_CODE -> + new TaskNotCancelableError_v0_3(code, message, data); + case PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE -> + new PushNotificationNotSupportedError_v0_3(code, message, data); + case UNSUPPORTED_OPERATION_ERROR_CODE -> + new UnsupportedOperationError_v0_3(code, message, data); + case CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE -> + new ContentTypeNotSupportedError_v0_3(code, message, data); + case INVALID_AGENT_RESPONSE_ERROR_CODE -> + new InvalidAgentResponseError_v0_3(code, message, data); + default -> + new JSONRPCError_v0_3(code, message, data); + }; + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link TaskState_v0_3} enum. + *

            + * This adapter ensures that TaskState enum values are serialized using their + * wire format string representation (e.g., "completed", "working") rather than + * the Java enum constant name (e.g., "COMPLETED", "WORKING"). + *

            + * For serialization, it uses {@link TaskState_v0_3#asString()} to get the wire format. + * For deserialization, it uses {@link TaskState_v0_3#fromString(String)} to parse the + * wire format back to the enum constant. + * + * @see TaskState_v0_3 + * @see TaskState_v0_3#asString() + * @see TaskState_v0_3#fromString(String) + */ + static class TaskStateTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, TaskState_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(value.asString()); + } + } + + @Override + public @Nullable + TaskState_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + String stateString = in.nextString(); + try { + return TaskState_v0_3.fromString(stateString); + } catch (IllegalArgumentException e) { + throw new JsonSyntaxException("Invalid TaskState: " + stateString, e); + } + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link Message_v0_3.Role} enum. + *

            + * This adapter ensures that Message.Role enum values are serialized using their + * wire format string representation (e.g., "user", "agent") rather than the Java + * enum constant name (e.g., "USER", "AGENT"). + *

            + * For serialization, it uses {@link Message_v0_3.Role#asString()} to get the wire format. + * For deserialization, it parses the string to the enum constant. + * + * @see Message_v0_3.Role + * @see Message_v0_3.Role#asString() + */ + static class RoleTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, Message_v0_3.Role value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(value.asString()); + } + } + + @Override + public Message_v0_3.@Nullable Role read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + String roleString = in.nextString(); + try { + return switch (roleString) { + case "user" -> + Message_v0_3.Role.USER; + case "agent" -> + Message_v0_3.Role.AGENT; + default -> + throw new IllegalArgumentException("Invalid Role: " + roleString); + }; + } catch (IllegalArgumentException e) { + throw new JsonSyntaxException("Invalid Message.Role: " + roleString, e); + } + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link Part_v0_3.Kind} enum. + *

            + * This adapter ensures that Part.Kind enum values are serialized using their + * wire format string representation (e.g., "text", "file", "data") rather than + * the Java enum constant name (e.g., "TEXT", "FILE", "DATA"). + *

            + * For serialization, it uses {@link Part_v0_3.Kind#asString()} to get the wire format. + * For deserialization, it parses the string to the enum constant. + * + * @see Part_v0_3.Kind + * @see Part_v0_3.Kind#asString() + */ + static class PartKindTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, Part_v0_3.Kind value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(value.asString()); + } + } + + @Override + public Part_v0_3.@Nullable Kind read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + String kindString = in.nextString(); + try { + return switch (kindString) { + case "text" -> + Part_v0_3.Kind.TEXT; + case "file" -> + Part_v0_3.Kind.FILE; + case "data" -> + Part_v0_3.Kind.DATA; + default -> + throw new IllegalArgumentException("Invalid Part.Kind: " + kindString); + }; + } catch (IllegalArgumentException e) { + throw new JsonSyntaxException("Invalid Part.Kind: " + kindString, e); + } + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link Part_v0_3} and its subclasses. + *

            + * This adapter handles polymorphic deserialization based on the "kind" field, creating the + * appropriate subclass instance (TextPart, FilePart, or DataPart). + *

            + * The adapter uses a two-pass approach: first reads the JSON as a tree to inspect the "kind" + * field, then deserializes to the appropriate concrete type. + * + * @see Part_v0_3 + * @see TextPart_v0_3 + * @see FilePart_v0_3 + * @see DataPart_v0_3 + */ + static class PartTypeAdapter extends TypeAdapter> { + + // Create separate Gson instance without the Part adapter to avoid recursion + private final Gson delegateGson = createBaseGsonBuilder().create(); + + @Override + public void write(JsonWriter out, Part_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + // Delegate to Gson's default serialization for the concrete type + if (value instanceof TextPart_v0_3 textPart) { + delegateGson.toJson(textPart, TextPart_v0_3.class, out); + } else if (value instanceof FilePart_v0_3 filePart) { + delegateGson.toJson(filePart, FilePart_v0_3.class, out); + } else if (value instanceof DataPart_v0_3 dataPart) { + delegateGson.toJson(dataPart, DataPart_v0_3.class, out); + } else { + throw new JsonSyntaxException("Unknown Part subclass: " + value.getClass().getName()); + } + } + + @Override + public @Nullable + Part_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + + // Read the JSON as a tree so we can inspect the "kind" field + com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); + if (!jsonElement.isJsonObject()) { + throw new JsonSyntaxException("Part must be a JSON object"); + } + + com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); + com.google.gson.JsonElement kindElement = jsonObject.get("kind"); + if (kindElement == null || !kindElement.isJsonPrimitive()) { + throw new JsonSyntaxException("Part must have a 'kind' field"); + } + + String kind = kindElement.getAsString(); + // Use the delegate Gson to deserialize to the concrete type + return switch (kind) { + case "text" -> + delegateGson.fromJson(jsonElement, TextPart_v0_3.class); + case "file" -> + delegateGson.fromJson(jsonElement, FilePart_v0_3.class); + case "data" -> + delegateGson.fromJson(jsonElement, DataPart_v0_3.class); + default -> + throw new JsonSyntaxException("Unknown Part kind: " + kind); + }; + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link EventKind_v0_3} and its implementations. + *

            + * Discriminates based on the {@code "kind"} field: + *

              + *
            • {@code "task"} → {@link Task_v0_3}
            • + *
            • {@code "message"} → {@link Message_v0_3}
            • + *
            + */ + static class EventKindTypeAdapter extends TypeAdapter { + + private final Gson delegateGson = createBaseGsonBuilder() + .registerTypeHierarchyAdapter(Part_v0_3.class, new PartTypeAdapter()) + .create(); + + @Override + public void write(JsonWriter out, EventKind_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + if (value instanceof Task_v0_3 task) { + delegateGson.toJson(task, Task_v0_3.class, out); + } else if (value instanceof Message_v0_3 message) { + delegateGson.toJson(message, Message_v0_3.class, out); + } else { + throw new JsonSyntaxException("Unknown EventKind implementation: " + value.getClass().getName()); + } + } + + @Override + public @Nullable EventKind_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + + com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); + if (!jsonElement.isJsonObject()) { + throw new JsonSyntaxException("EventKind must be a JSON object"); + } + + com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); + com.google.gson.JsonElement kindElement = jsonObject.get("kind"); + if (kindElement == null || !kindElement.isJsonPrimitive()) { + throw new JsonSyntaxException("EventKind must have a 'kind' field"); + } + + String kind = kindElement.getAsString(); + return switch (kind) { + case Task_v0_3.TASK -> delegateGson.fromJson(jsonElement, Task_v0_3.class); + case Message_v0_3.MESSAGE -> delegateGson.fromJson(jsonElement, Message_v0_3.class); + default -> throw new JsonSyntaxException("Unknown EventKind kind: " + kind); + }; + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link StreamingEventKind_v0_3} and its implementations. + *

            + * This adapter handles polymorphic deserialization based on the "kind" field, creating the + * appropriate implementation instance (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent). + *

            + * The adapter uses a two-pass approach: first reads the JSON as a tree to inspect the "kind" + * field, then deserializes to the appropriate concrete type. + * + * @see StreamingEventKind_v0_3 + * @see Task_v0_3 + * @see Message_v0_3 + * @see TaskStatusUpdateEvent_v0_3 + * @see TaskArtifactUpdateEvent_v0_3 + */ + static class StreamingEventKindTypeAdapter extends TypeAdapter { + + // Create separate Gson instance without the StreamingEventKind adapter to avoid recursion + private final Gson delegateGson = createBaseGsonBuilder() + .registerTypeHierarchyAdapter(Part_v0_3.class, new PartTypeAdapter()) + .create(); + + @Override + public void write(JsonWriter out, StreamingEventKind_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + // Delegate to Gson's default serialization for the concrete type + if (value instanceof Task_v0_3 task) { + delegateGson.toJson(task, Task_v0_3.class, out); + } else if (value instanceof Message_v0_3 message) { + delegateGson.toJson(message, Message_v0_3.class, out); + } else if (value instanceof TaskStatusUpdateEvent_v0_3 event) { + delegateGson.toJson(event, TaskStatusUpdateEvent_v0_3.class, out); + } else if (value instanceof TaskArtifactUpdateEvent_v0_3 event) { + delegateGson.toJson(event, TaskArtifactUpdateEvent_v0_3.class, out); + } else { + throw new JsonSyntaxException("Unknown StreamingEventKind implementation: " + value.getClass().getName()); + } + } + + @Override + public @Nullable + StreamingEventKind_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + + // Read the JSON as a tree so we can inspect the "kind" field + com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); + if (!jsonElement.isJsonObject()) { + throw new JsonSyntaxException("StreamingEventKind must be a JSON object"); + } + + com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); + com.google.gson.JsonElement kindElement = jsonObject.get("kind"); + if (kindElement == null || !kindElement.isJsonPrimitive()) { + throw new JsonSyntaxException("StreamingEventKind must have a 'kind' field"); + } + + String kind = kindElement.getAsString(); + // Use the delegate Gson to deserialize to the concrete type + return switch (kind) { + case "task" -> + delegateGson.fromJson(jsonElement, Task_v0_3.class); + case "message" -> + delegateGson.fromJson(jsonElement, Message_v0_3.class); + case "status-update" -> + delegateGson.fromJson(jsonElement, TaskStatusUpdateEvent_v0_3.class); + case "artifact-update" -> + delegateGson.fromJson(jsonElement, TaskArtifactUpdateEvent_v0_3.class); + default -> + throw new JsonSyntaxException("Unknown StreamingEventKind kind: " + kind); + }; + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link SecurityScheme_v0_3} and its implementations. + *

            + * Discriminates based on the {@code "type"} field: + *

              + *
            • {@code "apiKey"} → {@link APIKeySecurityScheme_v0_3}
            • + *
            • {@code "http"} → {@link HTTPAuthSecurityScheme_v0_3}
            • + *
            • {@code "oauth2"} → {@link OAuth2SecurityScheme_v0_3}
            • + *
            • {@code "openIdConnect"} → {@link OpenIdConnectSecurityScheme_v0_3}
            • + *
            • {@code "mutualTLS"} → {@link MutualTLSSecurityScheme_v0_3}
            • + *
            + */ + static class SecuritySchemeTypeAdapter extends TypeAdapter { + + // Use a plain Gson to avoid circular initialization — SecurityScheme concrete types + // contain only simple fields (Strings, OAuthFlows) that need no custom adapters. + private final Gson delegateGson = new Gson(); + + @Override + public void write(JsonWriter out, SecurityScheme_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + if (value instanceof APIKeySecurityScheme_v0_3 v) { + delegateGson.toJson(v, APIKeySecurityScheme_v0_3.class, out); + } else if (value instanceof HTTPAuthSecurityScheme_v0_3 v) { + delegateGson.toJson(v, HTTPAuthSecurityScheme_v0_3.class, out); + } else if (value instanceof OAuth2SecurityScheme_v0_3 v) { + delegateGson.toJson(v, OAuth2SecurityScheme_v0_3.class, out); + } else if (value instanceof OpenIdConnectSecurityScheme_v0_3 v) { + delegateGson.toJson(v, OpenIdConnectSecurityScheme_v0_3.class, out); + } else if (value instanceof MutualTLSSecurityScheme_v0_3 v) { + delegateGson.toJson(v, MutualTLSSecurityScheme_v0_3.class, out); + } else { + throw new JsonSyntaxException("Unknown SecurityScheme implementation: " + value.getClass().getName()); + } + } + + @Override + public @Nullable SecurityScheme_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + + com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); + if (!jsonElement.isJsonObject()) { + throw new JsonSyntaxException("SecurityScheme must be a JSON object"); + } + + com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); + com.google.gson.JsonElement typeElement = jsonObject.get("type"); + if (typeElement == null || !typeElement.isJsonPrimitive()) { + throw new JsonSyntaxException("SecurityScheme must have a 'type' field"); + } + + String type = typeElement.getAsString(); + return switch (type) { + case APIKeySecurityScheme_v0_3.API_KEY -> + delegateGson.fromJson(jsonElement, APIKeySecurityScheme_v0_3.class); + case HTTPAuthSecurityScheme_v0_3.HTTP -> + delegateGson.fromJson(jsonElement, HTTPAuthSecurityScheme_v0_3.class); + case OAuth2SecurityScheme_v0_3.OAUTH2 -> + delegateGson.fromJson(jsonElement, OAuth2SecurityScheme_v0_3.class); + case OpenIdConnectSecurityScheme_v0_3.OPENID_CONNECT -> + delegateGson.fromJson(jsonElement, OpenIdConnectSecurityScheme_v0_3.class); + case MutualTLSSecurityScheme_v0_3.MUTUAL_TLS -> + delegateGson.fromJson(jsonElement, MutualTLSSecurityScheme_v0_3.class); + default -> + throw new JsonSyntaxException("Unknown SecurityScheme type: " + type); + }; + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link FileContent_v0_3} and its implementations. + *

            + * This adapter handles polymorphic deserialization for the sealed FileContent interface, + * which permits two implementations: + *

              + *
            • {@link FileWithBytes_v0_3} - File content embedded as base64-encoded bytes
            • + *
            • {@link FileWithUri_v0_3} - File content referenced by URI
            • + *
            + *

            + * The adapter distinguishes between the two types by checking for the presence of + * "bytes" or "uri" fields in the JSON object. + * + * @see FileContent_v0_3 + * @see FileWithBytes_v0_3 + * @see FileWithUri_v0_3 + */ + static class FileContentTypeAdapter extends TypeAdapter { + + // Create separate Gson instance without the FileContent adapter to avoid recursion + private final Gson delegateGson = new Gson(); + + @Override + public void write(JsonWriter out, FileContent_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + // Delegate to Gson's default serialization for the concrete type + if (value instanceof FileWithBytes_v0_3 fileWithBytes) { + delegateGson.toJson(fileWithBytes, FileWithBytes_v0_3.class, out); + } else if (value instanceof FileWithUri_v0_3 fileWithUri) { + delegateGson.toJson(fileWithUri, FileWithUri_v0_3.class, out); + } else { + throw new JsonSyntaxException("Unknown FileContent implementation: " + value.getClass().getName()); + } + } + + @Override + public @Nullable + FileContent_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + + // Read the JSON as a tree to inspect the fields + com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); + if (!jsonElement.isJsonObject()) { + throw new JsonSyntaxException("FileContent must be a JSON object"); + } + + com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); + + // Distinguish between FileWithBytes and FileWithUri by checking for "bytes" or "uri" field + if (jsonObject.has("bytes")) { + return delegateGson.fromJson(jsonElement, FileWithBytes_v0_3.class); + } else if (jsonObject.has("uri")) { + return delegateGson.fromJson(jsonElement, FileWithUri_v0_3.class); + } else { + throw new JsonSyntaxException("FileContent must have either 'bytes' or 'uri' field"); + } + } + } + + /** + * Gson TypeAdapter for serializing and deserializing {@link AgentCapabilities_v0_3}. + *

            + * This adapter ensures that the {@code extensions} field is serialized as an empty array {@code []} + * when it is {@code null}, as required by the A2A v0.3 specification. + */ + static class AgentCapabilitiesTypeAdapter extends TypeAdapter { + + private final Gson delegateGson = new Gson(); + + @Override + public void write(JsonWriter out, AgentCapabilities_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + + out.beginObject(); + out.name("streaming").value(value.streaming()); + out.name("pushNotifications").value(value.pushNotifications()); + out.name("stateTransitionHistory").value(value.stateTransitionHistory()); + out.name("extensions"); + if (value.extensions() == null) { + out.beginArray(); + out.endArray(); + } else { + delegateGson.toJson(value.extensions(), List.class, out); + } + out.endObject(); + } + + @Override + public org.a2aproject.sdk.compat03.spec.@Nullable AgentCapabilities_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { + in.nextNull(); + return null; + } + + com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); + return delegateGson.fromJson(jsonElement, AgentCapabilities_v0_3.class); + } + } + + static class VoidTypeAdapter extends TypeAdapter { + + + @Override + @SuppressWarnings("resource") + public void write(final JsonWriter out, final Void value) throws java.io.IOException { + out.nullValue(); + } + + @Override + public @Nullable Void read(final JsonReader in) throws java.io.IOException { + in.skipValue(); + return null; + } + + } + + /** + * Gson TypeAdapterFactory for serializing {@link JSONRPCResponse_v0_3} subclasses. + *

            + * JSON-RPC 2.0 requires that: + *

              + *
            • {@code result} MUST be present (possibly null) on success, and MUST NOT be present on error
            • + *
            • {@code error} MUST be present on error, and MUST NOT be present on success
            • + *
            + * Gson's default null-field-skipping behavior would omit {@code "result": null} for Void responses, + * so this factory writes the fields explicitly to comply with the spec. + */ + static class JSONRPCResponseTypeAdapterFactory implements TypeAdapterFactory { + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { + if (!JSONRPCResponse_v0_3.class.isAssignableFrom(type.getRawType())) { + return null; + } + + TypeAdapter delegateAdapter = gson.getDelegateAdapter(this, type); + TypeAdapter errorAdapter = gson.getAdapter(JSONRPCError_v0_3.class); + + return new TypeAdapter() { + @Override + public void write(JsonWriter out, T value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + + JSONRPCResponse_v0_3 response = (JSONRPCResponse_v0_3) value; + + out.beginObject(); + out.name("jsonrpc").value(response.getJsonrpc()); + + Object id = response.getId(); + out.name("id"); + if (id == null) { + out.nullValue(); + } else if (id instanceof Number n) { + out.value(n.longValue()); + } else { + out.value(id.toString()); + } + + JSONRPCError_v0_3 error = response.getError(); + if (error != null) { + out.name("error"); + errorAdapter.write(out, error); + } else { + out.name("result"); + Object result = response.getResult(); + if (result == null) { + // JsonWriter.nullValue() skips both name+value when serializeNulls=false, + // so we must temporarily enable it to write "result":null as required + // by JSON-RPC 2.0. + boolean prev = out.getSerializeNulls(); + out.setSerializeNulls(true); + out.nullValue(); + out.setSerializeNulls(prev); + } else { + TypeAdapter resultAdapter = gson.getAdapter(result.getClass()); + resultAdapter.write(out, result); + } + } + + out.endObject(); + } + + @Override + public T read(JsonReader in) throws java.io.IOException { + return delegateAdapter.read(in); + } + }; + } + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/package-info.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/package-info.java new file mode 100644 index 000000000..b1b9a5b5c --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/package-info.java @@ -0,0 +1,8 @@ +/** + * JSON processing exceptions for the A2A Java SDK. + *

            + * This package provides custom exceptions that replace Jackson's JSON processing exceptions, + * allowing the SDK to be independent of any specific JSON library implementation. + */ +@org.jspecify.annotations.NullMarked +package org.a2aproject.sdk.compat03.json; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientError_v0_3.java new file mode 100644 index 000000000..d5aeaa5e0 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientError_v0_3.java @@ -0,0 +1,17 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Base exception for A2A Client errors. + */ +public class A2AClientError_v0_3 extends RuntimeException { + public A2AClientError_v0_3() { + } + + public A2AClientError_v0_3(String message) { + super(message); + } + + public A2AClientError_v0_3(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientException_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientException_v0_3.java new file mode 100644 index 000000000..676127971 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientException_v0_3.java @@ -0,0 +1,23 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Exception to indicate a general failure related to an A2A client. + */ +public class A2AClientException_v0_3 extends A2AException_v0_3 { + + public A2AClientException_v0_3() { + super(); + } + + public A2AClientException_v0_3(final String msg) { + super(msg); + } + + public A2AClientException_v0_3(final Throwable cause) { + super(cause); + } + + public A2AClientException_v0_3(final String msg, final Throwable cause) { + super(msg, cause); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientHTTPError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientHTTPError_v0_3.java new file mode 100644 index 000000000..40168cc2c --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientHTTPError_v0_3.java @@ -0,0 +1,34 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +public class A2AClientHTTPError_v0_3 extends A2AClientError_v0_3 { + private final int code; + private final String message; + + public A2AClientHTTPError_v0_3(int code, String message, Object data) { + Assert.checkNotNullParam("code", code); + Assert.checkNotNullParam("message", message); + this.code = code; + this.message = message; + } + + /** + * Gets the error code + * + * @return the error code + */ + public int getCode() { + return code; + } + + /** + * Gets the error message + * + * @return the error message + */ + @Override + public String getMessage() { + return message; + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientInvalidArgsError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientInvalidArgsError_v0_3.java new file mode 100644 index 000000000..0900d6a04 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientInvalidArgsError_v0_3.java @@ -0,0 +1,15 @@ +package org.a2aproject.sdk.compat03.spec; + +public class A2AClientInvalidArgsError_v0_3 extends A2AClientError_v0_3 { + + public A2AClientInvalidArgsError_v0_3() { + } + + public A2AClientInvalidArgsError_v0_3(String message) { + super("Invalid arguments error: " + message); + } + + public A2AClientInvalidArgsError_v0_3(String message, Throwable cause) { + super("Invalid arguments error: " + message, cause); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientInvalidStateError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientInvalidStateError_v0_3.java new file mode 100644 index 000000000..4b94d442b --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientInvalidStateError_v0_3.java @@ -0,0 +1,15 @@ +package org.a2aproject.sdk.compat03.spec; + +public class A2AClientInvalidStateError_v0_3 extends A2AClientError_v0_3 { + + public A2AClientInvalidStateError_v0_3() { + } + + public A2AClientInvalidStateError_v0_3(String message) { + super("Invalid state error: " + message); + } + + public A2AClientInvalidStateError_v0_3(String message, Throwable cause) { + super("Invalid state error: " + message, cause); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientJSONError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientJSONError_v0_3.java new file mode 100644 index 000000000..2c094e4d5 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AClientJSONError_v0_3.java @@ -0,0 +1,40 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Client exception indicating a JSON serialization or deserialization error. + *

            + * This exception is thrown when the A2A client SDK encounters errors while + * parsing JSON responses from agents or serializing requests. This typically + * indicates: + *

              + *
            • Malformed JSON in agent responses
            • + *
            • Unexpected JSON structure or field types
            • + *
            • Missing required JSON fields
            • + *
            • JSON encoding/decoding errors
            • + *
            + *

            + * Usage example: + *

            {@code
            + * try {
            + *     AgentCard card = objectMapper.readValue(json, AgentCard.class);
            + * } catch (org.a2aproject.sdk.compat03.json.JsonProcessingException e) {
            + *     throw new A2AClientJSONError("Failed to parse agent card", e);
            + * }
            + * }
            + * + * @see A2AClientError_v0_3 for the base client error class + * @see JSONParseError_v0_3 for protocol-level JSON errors + */ +public class A2AClientJSONError_v0_3 extends A2AClientError_v0_3 { + + public A2AClientJSONError_v0_3() { + } + + public A2AClientJSONError_v0_3(String message) { + super(message); + } + + public A2AClientJSONError_v0_3(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AErrorCodes_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AErrorCodes_v0_3.java new file mode 100644 index 000000000..13198bb53 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AErrorCodes_v0_3.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * All the error codes for A2A errors. + */ +public interface A2AErrorCodes_v0_3 { + + int TASK_NOT_FOUND_ERROR_CODE = -32001; + int TASK_NOT_CANCELABLE_ERROR_CODE = -32002; + int PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE = -32003; + int UNSUPPORTED_OPERATION_ERROR_CODE = -32004; + int CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE = -32005; + int INVALID_AGENT_RESPONSE_ERROR_CODE = -32006; + int AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED_ERROR_CODE = -32007; + + int INVALID_REQUEST_ERROR_CODE = -32600; + int METHOD_NOT_FOUND_ERROR_CODE = -32601; + int INVALID_PARAMS_ERROR_CODE = -32602; + int INTERNAL_ERROR_CODE = -32603; + + int JSON_PARSE_ERROR_CODE = -32700; +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AError_v0_3.java new file mode 100644 index 000000000..05986fa39 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AError_v0_3.java @@ -0,0 +1,4 @@ +package org.a2aproject.sdk.compat03.spec; + +public interface A2AError_v0_3 extends Event_v0_3 { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AException_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AException_v0_3.java new file mode 100644 index 000000000..ae81343b2 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AException_v0_3.java @@ -0,0 +1,44 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Exception to indicate a general failure related to the A2A protocol. + */ +public class A2AException_v0_3 extends RuntimeException { + + /** + * Constructs a new {@code A2AException} instance. The message is left blank ({@code null}), and no + * cause is specified. + */ + public A2AException_v0_3() { + } + + /** + * Constructs a new {@code A2AException} instance with an initial message. No cause is specified. + * + * @param msg the message + */ + public A2AException_v0_3(final String msg) { + super(msg); + } + + /** + * Constructs a new {@code A2AException} instance with an initial cause. If a non-{@code null} cause + * is specified, its message is used to initialize the message of this {@code A2AException}; otherwise + * the message is left blank ({@code null}). + * + * @param cause the cause + */ + public A2AException_v0_3(final Throwable cause) { + super(cause); + } + + /** + * Constructs a new {@code A2AException} instance with an initial message and cause. + * + * @param msg the message + * @param cause the cause + */ + public A2AException_v0_3(final String msg, final Throwable cause) { + super(msg, cause); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AServerException_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AServerException_v0_3.java new file mode 100644 index 000000000..174d9627c --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/A2AServerException_v0_3.java @@ -0,0 +1,23 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Exception to indicate a general failure related to an A2A server. + */ +public class A2AServerException_v0_3 extends A2AException_v0_3 { + + public A2AServerException_v0_3() { + super(); + } + + public A2AServerException_v0_3(final String msg) { + super(msg); + } + + public A2AServerException_v0_3(final Throwable cause) { + super(cause); + } + + public A2AServerException_v0_3(final String msg, final Throwable cause) { + super(msg, cause); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java new file mode 100644 index 000000000..33fde3d61 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java @@ -0,0 +1,110 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines a security scheme using an API key. + */ +public final class APIKeySecurityScheme_v0_3 implements SecurityScheme_v0_3 { + + public static final String API_KEY = "apiKey"; + private final String in; + private final String name; + private final String type; + private final String description; + + /** + * Represents the location of the API key. + */ + public enum Location { + COOKIE("cookie"), + HEADER("header"), + QUERY("query"); + + private final String location; + + Location(String location) { + this.location = location; + } + + public String asString() { + return location; + } + + public static Location fromString(String location) { + switch (location) { + case "cookie" -> { + return COOKIE; + } + case "header" -> { + return HEADER; + } + case "query" -> { + return QUERY; + } + default -> throw new IllegalArgumentException("Invalid API key location: " + location); + } + } + } + + public APIKeySecurityScheme_v0_3(String in, String name, String description) { + this(in, name, description, API_KEY); + } + + public APIKeySecurityScheme_v0_3(String in, String name, + String description, String type) { + Assert.checkNotNullParam("in", in); + Assert.checkNotNullParam("name", name); + Assert.checkNotNullParam("type", type); + if (! type.equals(API_KEY)) { + throw new IllegalArgumentException("Invalid type for APIKeySecurityScheme"); + } + this.in = in; + this.name = name; + this.description = description; + this.type = type; + } + + @Override + public String getDescription() { + return description; + } + + + public String getIn() { + return in; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public static class Builder { + private String in; + private String name; + private String description; + + public Builder in(String in) { + this.in = in; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public APIKeySecurityScheme_v0_3 build() { + return new APIKeySecurityScheme_v0_3(in, name, description); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCapabilities_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCapabilities_v0_3.java new file mode 100644 index 000000000..c69eb62e7 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCapabilities_v0_3.java @@ -0,0 +1,42 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; + +/** + * Defines optional capabilities supported by an agent. + */ +public record AgentCapabilities_v0_3(boolean streaming, boolean pushNotifications, boolean stateTransitionHistory, + List extensions) { + + public static class Builder { + + private boolean streaming; + private boolean pushNotifications; + private boolean stateTransitionHistory; + private List extensions; + + public Builder streaming(boolean streaming) { + this.streaming = streaming; + return this; + } + + public Builder pushNotifications(boolean pushNotifications) { + this.pushNotifications = pushNotifications; + return this; + } + + public Builder stateTransitionHistory(boolean stateTransitionHistory) { + this.stateTransitionHistory = stateTransitionHistory; + return this; + } + + public Builder extensions(List extensions) { + this.extensions = extensions; + return this; + } + + public AgentCapabilities_v0_3 build() { + return new AgentCapabilities_v0_3(streaming, pushNotifications, stateTransitionHistory, extensions); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCardSignature_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCardSignature_v0_3.java new file mode 100644 index 000000000..eeda617ac --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCardSignature_v0_3.java @@ -0,0 +1,44 @@ +package org.a2aproject.sdk.compat03.spec; + +import com.google.gson.annotations.SerializedName; +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a JWS signature of an AgentCard. + * This follows the JSON format of an RFC 7515 JSON Web Signature (JWS). + */ +public record AgentCardSignature_v0_3(Map header, @SerializedName("protected")String protectedHeader, + String signature) { + + public AgentCardSignature_v0_3 { + Assert.checkNotNullParam("protectedHeader", protectedHeader); + Assert.checkNotNullParam("signature", signature); + } + + public static class Builder { + private Map header; + String protectedHeader; + String signature; + + public Builder header(Map header) { + this.header = header; + return this; + } + + public Builder protectedHeader(String protectedHeader) { + this.protectedHeader = protectedHeader; + return this; + } + + public Builder signature(String signature) { + this.signature = signature; + return this; + } + + public AgentCardSignature_v0_3 build() { + return new AgentCardSignature_v0_3(header, protectedHeader, signature); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCard_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCard_v0_3.java new file mode 100644 index 000000000..d5ab8010d --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentCard_v0_3.java @@ -0,0 +1,199 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * The AgentCard is a self-describing manifest for an agent. It provides essential + * metadata including the agent's identity, capabilities, skills, supported + * communication methods, and security requirements. + */ +public record AgentCard_v0_3(String name, String description, String url, AgentProvider_v0_3 provider, + String version, String documentationUrl, AgentCapabilities_v0_3 capabilities, + List defaultInputModes, List defaultOutputModes, List skills, + boolean supportsAuthenticatedExtendedCard, Map securitySchemes, + List>> security, String iconUrl, List additionalInterfaces, + String preferredTransport, String protocolVersion, List signatures) { + + private static final String DEFAULT_PROTOCOL_VERSION = "0.3.0"; + private static final TransportProtocol_v0_3 DEFAULT_TRANSPORT = TransportProtocol_v0_3.JSONRPC; + + public AgentCard_v0_3 { + Assert.checkNotNullParam("capabilities", capabilities); + Assert.checkNotNullParam("defaultInputModes", defaultInputModes); + Assert.checkNotNullParam("defaultOutputModes", defaultOutputModes); + Assert.checkNotNullParam("description", description); + Assert.checkNotNullParam("name", name); + Assert.checkNotNullParam("skills", skills); + Assert.checkNotNullParam("url", url); + Assert.checkNotNullParam("version", version); + if (protocolVersion == null) { + protocolVersion = DEFAULT_PROTOCOL_VERSION; + } + if (preferredTransport == null) { + preferredTransport = DEFAULT_TRANSPORT.asString(); + } + } + + public static class Builder { + private String name; + private String description; + private String url; + private AgentProvider_v0_3 provider; + private String version; + private String documentationUrl; + private AgentCapabilities_v0_3 capabilities; + private List defaultInputModes; + private List defaultOutputModes; + private List skills; + private boolean supportsAuthenticatedExtendedCard = false; + private Map securitySchemes; + private List>> security; + private String iconUrl; + private List additionalInterfaces; + private String preferredTransport; + private String protocolVersion; + private List signatures; + + /** + * Creates a new Builder. + */ + public Builder() { + + } + + /** + * Creates a new Builder as a copy of an existing AgentCard. + * + * @param card the AgentCard to copy + */ + public Builder(AgentCard_v0_3 card) { + this.name = card.name; + this.description = card.description; + this.url = card.url; + this.provider = card.provider; + this.version = card.version; + this.documentationUrl = card.documentationUrl; + this.capabilities = card.capabilities; + this.defaultInputModes = card.defaultInputModes != null ? new ArrayList<>(card.defaultInputModes) : null; + this.defaultOutputModes = card.defaultOutputModes != null ? new ArrayList<>(card.defaultOutputModes) : null; + this.skills = card.skills != null ? new ArrayList<>(card.skills) : null; + this.supportsAuthenticatedExtendedCard = card.supportsAuthenticatedExtendedCard; + this.securitySchemes = card.securitySchemes != null ? Map.copyOf(card.securitySchemes) : null; + this.security = card.security != null ? new ArrayList<>(card.security) : null; + this.iconUrl = card.iconUrl; + this.additionalInterfaces = card.additionalInterfaces != null ? new ArrayList<>(card.additionalInterfaces) : null; + this.preferredTransport = card.preferredTransport; + this.protocolVersion = card.protocolVersion; + this.signatures = card.signatures != null ? new ArrayList<>(card.signatures) : null; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder url(String url) { + this.url = url; + return this; + } + + public Builder provider(AgentProvider_v0_3 provider) { + this.provider = provider; + return this; + } + + public Builder version(String version) { + this.version = version; + return this; + } + + public Builder documentationUrl(String documentationUrl) { + this.documentationUrl = documentationUrl; + return this; + } + + public Builder capabilities(AgentCapabilities_v0_3 capabilities) { + this.capabilities = capabilities; + return this; + } + + public Builder defaultInputModes(List defaultInputModes) { + this.defaultInputModes = defaultInputModes; + return this; + } + + public Builder defaultOutputModes(List defaultOutputModes) { + this.defaultOutputModes = defaultOutputModes; + return this; + } + + public Builder skills(List skills) { + this.skills = skills; + return this; + } + + public Builder supportsAuthenticatedExtendedCard(boolean supportsAuthenticatedExtendedCard) { + this.supportsAuthenticatedExtendedCard = supportsAuthenticatedExtendedCard; + return this; + } + + public Builder securitySchemes(Map securitySchemes) { + this.securitySchemes = securitySchemes; + return this; + } + + public Builder security(List>> security) { + this.security = security; + return this; + } + + public Builder iconUrl(String iconUrl) { + this.iconUrl = iconUrl; + return this; + } + + public Builder additionalInterfaces(List additionalInterfaces) { + this.additionalInterfaces = additionalInterfaces; + return this; + } + + public Builder preferredTransport(String preferredTransport) { + this.preferredTransport = preferredTransport; + return this; + } + + public Builder protocolVersion(String protocolVersion) { + this.protocolVersion = protocolVersion; + return this; + } + + public Builder signatures(List signatures) { + this.signatures = signatures; + return this; + } + + public AgentCard_v0_3 build() { + if (preferredTransport == null) { + preferredTransport = DEFAULT_TRANSPORT.asString(); + } + if (additionalInterfaces == null) { + // should include an entry matching the main 'url' and 'preferredTransport' + additionalInterfaces = new ArrayList<>(); + additionalInterfaces.add(new AgentInterface_v0_3(preferredTransport, url)); + } + return new AgentCard_v0_3(name, description, url, provider, version, documentationUrl, + capabilities, defaultInputModes, defaultOutputModes, skills, + supportsAuthenticatedExtendedCard, securitySchemes, security, iconUrl, + additionalInterfaces, preferredTransport, protocolVersion, signatures); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentExtension_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentExtension_v0_3.java new file mode 100644 index 000000000..7b06c26b7 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentExtension_v0_3.java @@ -0,0 +1,47 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * A declaration of a protocol extension supported by an Agent. + */ +public record AgentExtension_v0_3(String description, Map params, boolean required, String uri) { + + public AgentExtension_v0_3 { + Assert.checkNotNullParam("uri", uri); + } + + public static class Builder { + String description; + Map params; + boolean required; + String uri; + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder params(Map params) { + this.params = params; + return this; + } + + public Builder required(boolean required) { + this.required = required; + return this; + } + + public Builder uri(String uri) { + this.uri = uri; + return this; + } + + public AgentExtension_v0_3 build() { + return new AgentExtension_v0_3(description, params, required, uri); + } + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentInterface_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentInterface_v0_3.java new file mode 100644 index 000000000..839b7482d --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentInterface_v0_3.java @@ -0,0 +1,15 @@ +package org.a2aproject.sdk.compat03.spec; + + +import org.a2aproject.sdk.util.Assert; + +/** + * Declares a combination of a target URL and a transport protocol for interacting with the agent. + */ + +public record AgentInterface_v0_3(String transport, String url) { + public AgentInterface_v0_3 { + Assert.checkNotNullParam("transport", transport); + Assert.checkNotNullParam("url", url); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentProvider_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentProvider_v0_3.java new file mode 100644 index 000000000..3d70bab74 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentProvider_v0_3.java @@ -0,0 +1,14 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents the service provider of an agent. + */ +public record AgentProvider_v0_3(String organization, String url) { + + public AgentProvider_v0_3 { + Assert.checkNotNullParam("organization", organization); + Assert.checkNotNullParam("url", url); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentSkill_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentSkill_v0_3.java new file mode 100644 index 000000000..cbb40a0fd --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AgentSkill_v0_3.java @@ -0,0 +1,77 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * The set of skills, or distinct capabilities, that the agent can perform. + */ +public record AgentSkill_v0_3(String id, String name, String description, List tags, + List examples, List inputModes, List outputModes, + List>> security) { + + public AgentSkill_v0_3 { + Assert.checkNotNullParam("description", description); + Assert.checkNotNullParam("id", id); + Assert.checkNotNullParam("name", name); + Assert.checkNotNullParam("tags", tags); + } + + public static class Builder { + + private String id; + private String name; + private String description; + private List tags; + private List examples; + private List inputModes; + private List outputModes; + private List>> security; + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder tags(List tags) { + this.tags = tags; + return this; + } + + public Builder examples(List examples) { + this.examples = examples; + return this; + } + + public Builder inputModes(List inputModes) { + this.inputModes = inputModes; + return this; + } + + public Builder outputModes(List outputModes) { + this.outputModes = outputModes; + return this; + } + + public Builder security(List>> security) { + this.security = security; + return this; + } + + public AgentSkill_v0_3 build() { + return new AgentSkill_v0_3(id, name, description, tags, examples, inputModes, outputModes, security); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Artifact_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Artifact_v0_3.java new file mode 100644 index 000000000..a98a10074 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Artifact_v0_3.java @@ -0,0 +1,82 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a file, data structure, or other resource generated by an agent during a task. + */ +public record Artifact_v0_3(String artifactId, String name, String description, List> parts, Map metadata, + List extensions) { + + public Artifact_v0_3 { + Assert.checkNotNullParam("artifactId", artifactId); + Assert.checkNotNullParam("parts", parts); + if (parts.isEmpty()) { + throw new IllegalArgumentException("Parts cannot be empty"); + } + } + + public static class Builder { + private String artifactId; + private String name; + private String description; + private List> parts; + private Map metadata; + private List extensions; + + public Builder(){ + } + + public Builder(Artifact_v0_3 existingArtifact) { + artifactId = existingArtifact.artifactId; + name = existingArtifact.name; + description = existingArtifact.description; + parts = existingArtifact.parts; + metadata = existingArtifact.metadata; + extensions = existingArtifact.extensions; + } + + public Builder artifactId(String artifactId) { + this.artifactId = artifactId; + return this; + } + + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder parts(List> parts) { + this.parts = parts; + return this; + } + + public Builder parts(Part_v0_3... parts) { + this.parts = List.of(parts); + return this; + } + + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public Builder extensions(List extensions) { + this.extensions = (extensions == null) ? null : List.copyOf(extensions); + return this; + } + + public Artifact_v0_3 build() { + return new Artifact_v0_3(artifactId, name, description, parts, metadata, extensions); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthenticatedExtendedCardNotConfiguredError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthenticatedExtendedCardNotConfiguredError_v0_3.java new file mode 100644 index 000000000..2fb9b1928 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthenticatedExtendedCardNotConfiguredError_v0_3.java @@ -0,0 +1,20 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + + +/** + * An A2A-specific error indicating that the agent does not have an + * Authenticated Extended Card configured + */ +public class AuthenticatedExtendedCardNotConfiguredError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = -32007; + + public AuthenticatedExtendedCardNotConfiguredError_v0_3(Integer code, String message, Object data) { + super( + defaultIfNull(code, DEFAULT_CODE), + defaultIfNull(message, "Authenticated Extended Card not configured"), + data); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthenticationInfo_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthenticationInfo_v0_3.java new file mode 100644 index 000000000..064cb3ec9 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthenticationInfo_v0_3.java @@ -0,0 +1,15 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; + +import org.a2aproject.sdk.util.Assert; + +/** + * The authentication info for an agent. + */ +public record AuthenticationInfo_v0_3(List schemes, String credentials) { + + public AuthenticationInfo_v0_3 { + Assert.checkNotNullParam("schemes", schemes); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthorizationCodeOAuthFlow_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthorizationCodeOAuthFlow_v0_3.java new file mode 100644 index 000000000..4dd875f0c --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/AuthorizationCodeOAuthFlow_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines configuration details for the OAuth 2.0 Authorization Code flow. + */ +public record AuthorizationCodeOAuthFlow_v0_3(String authorizationUrl, String refreshUrl, Map scopes, + String tokenUrl) { + + public AuthorizationCodeOAuthFlow_v0_3 { + Assert.checkNotNullParam("authorizationUrl", authorizationUrl); + Assert.checkNotNullParam("scopes", scopes); + Assert.checkNotNullParam("tokenUrl", tokenUrl); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskRequest_v0_3.java new file mode 100644 index 000000000..2aa02e9fe --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskRequest_v0_3.java @@ -0,0 +1,70 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +import java.util.UUID; + + +import org.a2aproject.sdk.util.Assert; + +/** + * A request that can be used to cancel a task. + */ +public final class CancelTaskRequest_v0_3 extends NonStreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "tasks/cancel"; + + public CancelTaskRequest_v0_3(String jsonrpc, Object id, String method, TaskIdParams_v0_3 params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid CancelTaskRequest method"); + } + Assert.checkNotNullParam("params", params); + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public CancelTaskRequest_v0_3(Object id, TaskIdParams_v0_3 params) { + this(null, id, METHOD, params); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method = METHOD; + private TaskIdParams_v0_3 params; + + public CancelTaskRequest_v0_3.Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public CancelTaskRequest_v0_3.Builder id(Object id) { + this.id = id; + return this; + } + + public CancelTaskRequest_v0_3.Builder method(String method) { + this.method = method; + return this; + } + + public CancelTaskRequest_v0_3.Builder params(TaskIdParams_v0_3 params) { + this.params = params; + return this; + } + + public CancelTaskRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new CancelTaskRequest_v0_3(jsonrpc, id, method, params); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskResponse_v0_3.java new file mode 100644 index 000000000..e4a58fe74 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskResponse_v0_3.java @@ -0,0 +1,21 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * A response to a cancel task request. + */ + +public final class CancelTaskResponse_v0_3 extends JSONRPCResponse_v0_3 { + + public CancelTaskResponse_v0_3(String jsonrpc, Object id, Task_v0_3 result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, Task_v0_3.class); + } + + public CancelTaskResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } + + + public CancelTaskResponse_v0_3(Object id, Task_v0_3 result) { + this(null, id, result, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ClientCredentialsOAuthFlow_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ClientCredentialsOAuthFlow_v0_3.java new file mode 100644 index 000000000..a0f8b31f3 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ClientCredentialsOAuthFlow_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.spec; + + +import java.util.Map; + + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines configuration details for the OAuth 2.0 Client Credentials flow. + */ +public record ClientCredentialsOAuthFlow_v0_3(String refreshUrl, Map scopes, String tokenUrl) { + + public ClientCredentialsOAuthFlow_v0_3 { + Assert.checkNotNullParam("scopes", scopes); + Assert.checkNotNullParam("tokenUrl", tokenUrl); + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ContentTypeNotSupportedError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ContentTypeNotSupportedError_v0_3.java new file mode 100644 index 000000000..028a80efe --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ContentTypeNotSupportedError_v0_3.java @@ -0,0 +1,20 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + + +/** + * An A2A-specific error indicating an incompatibility between the requested + * content types and the agent's capabilities. + */ +public class ContentTypeNotSupportedError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; + + public ContentTypeNotSupportedError_v0_3(Integer code, String message, Object data) { + super(defaultIfNull(code, CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE), + defaultIfNull(message, "Incompatible content types"), + data); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java new file mode 100644 index 000000000..a53b55a60 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java @@ -0,0 +1,43 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + + +/** + * Represents a structured data segment (e.g., JSON) within a message or artifact. + */ +public class DataPart_v0_3 extends Part_v0_3> { + + public static final String DATA = "data"; + private final Map data; + private final Map metadata; + private final Kind kind; + + public DataPart_v0_3(Map data) { + this(data, null); + } + + public DataPart_v0_3(Map data, Map metadata) { + Assert.checkNotNullParam("data", data); + this.data = data; + this.metadata = metadata; + this.kind = Kind.DATA; + } + + @Override + public Kind getKind() { + return kind; + } + + public Map getData() { + return data; + } + + @Override + public Map getMetadata() { + return metadata; + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigParams_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigParams_v0_3.java new file mode 100644 index 000000000..400ef8c25 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigParams_v0_3.java @@ -0,0 +1,46 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + + +import org.a2aproject.sdk.util.Assert; + +/** + * Parameters for removing pushNotificationConfiguration associated with a Task. + */ +public record DeleteTaskPushNotificationConfigParams_v0_3(String id, String pushNotificationConfigId, Map metadata) { + + public DeleteTaskPushNotificationConfigParams_v0_3 { + Assert.checkNotNullParam("id", id); + Assert.checkNotNullParam("pushNotificationConfigId", pushNotificationConfigId); + } + + public DeleteTaskPushNotificationConfigParams_v0_3(String id, String pushNotificationConfigId) { + this(id, pushNotificationConfigId, null); + } + + public static class Builder { + String id; + String pushNotificationConfigId; + Map metadata; + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder pushNotificationConfigId(String pushNotificationConfigId) { + this.pushNotificationConfigId = pushNotificationConfigId; + return this; + } + + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public DeleteTaskPushNotificationConfigParams_v0_3 build() { + return new DeleteTaskPushNotificationConfigParams_v0_3(id, pushNotificationConfigId, metadata); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigRequest_v0_3.java new file mode 100644 index 000000000..a90894e54 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigRequest_v0_3.java @@ -0,0 +1,67 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.UUID; + +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.compat03.util.Utils_v0_3; + +/** + * A delete task push notification config request. + */ +public final class DeleteTaskPushNotificationConfigRequest_v0_3 extends NonStreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "tasks/pushNotificationConfig/delete"; + + public DeleteTaskPushNotificationConfigRequest_v0_3(String jsonrpc, Object id, String method, DeleteTaskPushNotificationConfigParams_v0_3 params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid DeleteTaskPushNotificationConfigRequest method"); + } + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = Utils_v0_3.defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public DeleteTaskPushNotificationConfigRequest_v0_3(String id, DeleteTaskPushNotificationConfigParams_v0_3 params) { + this(null, id, METHOD, params); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method; + private DeleteTaskPushNotificationConfigParams_v0_3 params; + + public Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public Builder id(Object id) { + this.id = id; + return this; + } + + public Builder method(String method) { + this.method = method; + return this; + } + + public Builder params(DeleteTaskPushNotificationConfigParams_v0_3 params) { + this.params = params; + return this; + } + + public DeleteTaskPushNotificationConfigRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new DeleteTaskPushNotificationConfigRequest_v0_3(jsonrpc, id, method, params); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigResponse_v0_3.java new file mode 100644 index 000000000..e581bedaa --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigResponse_v0_3.java @@ -0,0 +1,20 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * A response for a delete task push notification config request. + */ +public final class DeleteTaskPushNotificationConfigResponse_v0_3 extends JSONRPCResponse_v0_3 { + + public DeleteTaskPushNotificationConfigResponse_v0_3(String jsonrpc, Object id, Void result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, Void.class); + } + + public DeleteTaskPushNotificationConfigResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } + + public DeleteTaskPushNotificationConfigResponse_v0_3(Object id) { + this(null, id, null, null); + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/EventKind_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/EventKind_v0_3.java new file mode 100644 index 000000000..374120a33 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/EventKind_v0_3.java @@ -0,0 +1,25 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Interface for events that can be returned from non-streaming A2A Protocol operations. + *

            + * EventKind represents events that are suitable for synchronous request-response patterns. + * These events provide complete state information and are typically returned as the final + * result of an operation. + *

            + * EventKind implementations use polymorphic JSON serialization with the "kind" discriminator + * to determine the concrete type during deserialization. + *

            + * Permitted implementations: + *

              + *
            • {@link Task_v0_3} - Complete task state with status and artifacts
            • + *
            • {@link Message_v0_3} - Full message with all content parts
            • + *
            + * + * @see StreamingEventKind_v0_3 + * @see Event_v0_3 + */ +public interface EventKind_v0_3 { + + String getKind(); +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Event_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Event_v0_3.java new file mode 100644 index 000000000..8aa7e6369 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Event_v0_3.java @@ -0,0 +1,4 @@ +package org.a2aproject.sdk.compat03.spec; + +public interface Event_v0_3 { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileContent_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileContent_v0_3.java new file mode 100644 index 000000000..387e6443b --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileContent_v0_3.java @@ -0,0 +1,32 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Sealed interface representing file content in the A2A Protocol. + *

            + * FileContent provides a polymorphic abstraction for file data, allowing files to be + * represented either as embedded binary content or as URI references. This flexibility + * enables different strategies for file transmission based on size, security, and + * accessibility requirements. + *

            + * The sealed interface permits only two implementations: + *

              + *
            • {@link FileWithBytes_v0_3} - File content embedded as base64-encoded bytes (for small files or inline data)
            • + *
            • {@link FileWithUri_v0_3} - File content referenced by URI (for large files or external resources)
            • + *
            + *

            + * Both implementations must provide: + *

              + *
            • MIME type - Describes the file format (e.g., "image/png", "application/pdf")
            • + *
            • File name - The original or display name for the file
            • + *
            + * + * @see FilePart_v0_3 + * @see FileWithBytes_v0_3 + * @see FileWithUri_v0_3 + */ +public sealed interface FileContent_v0_3 permits FileWithBytes_v0_3, FileWithUri_v0_3 { + + String mimeType(); + + String name(); +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java new file mode 100644 index 000000000..bb2fba6ed --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java @@ -0,0 +1,43 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a file segment within a message or artifact. The file content can be + * provided either directly as bytes or as a URI. + */ +public class FilePart_v0_3 extends Part_v0_3 { + + public static final String FILE = "file"; + private final FileContent_v0_3 file; + private final Map metadata; + private final Kind kind; + + public FilePart_v0_3(FileContent_v0_3 file) { + this(file, null); + } + + public FilePart_v0_3(FileContent_v0_3 file, Map metadata) { + Assert.checkNotNullParam("file", file); + this.file = file; + this.metadata = metadata; + this.kind = Kind.FILE; + } + + @Override + public Kind getKind() { + return kind; + } + + public FileContent_v0_3 getFile() { + return file; + } + + @Override + public Map getMetadata() { + return metadata; + } + +} \ No newline at end of file diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileWithBytes_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileWithBytes_v0_3.java new file mode 100644 index 000000000..5740908be --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileWithBytes_v0_3.java @@ -0,0 +1,7 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Represents a file with its content provided directly as a base64-encoded string. + */ +public record FileWithBytes_v0_3(String mimeType, String name, String bytes) implements FileContent_v0_3 { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileWithUri_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileWithUri_v0_3.java new file mode 100644 index 000000000..7f302f9e8 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FileWithUri_v0_3.java @@ -0,0 +1,8 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Represents a file with its content located at a specific URI. + */ +public record FileWithUri_v0_3(String mimeType, String name, String uri) implements FileContent_v0_3 { +} + diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardRequest_v0_3.java new file mode 100644 index 000000000..55a95d4a8 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardRequest_v0_3.java @@ -0,0 +1,62 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.UUID; + + +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.compat03.util.Utils_v0_3; + +/** + * Represents a JSON-RPC request for the `agent/getAuthenticatedExtendedCard` method. + */ +public final class GetAuthenticatedExtendedCardRequest_v0_3 extends NonStreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "agent/getAuthenticatedExtendedCard"; + + public GetAuthenticatedExtendedCardRequest_v0_3(String jsonrpc, Object id, String method, Void params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid GetAuthenticatedExtendedCardRequest method"); + } + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = Utils_v0_3.defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public GetAuthenticatedExtendedCardRequest_v0_3(String id) { + this(null, id, METHOD, null); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method; + + public GetAuthenticatedExtendedCardRequest_v0_3.Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public GetAuthenticatedExtendedCardRequest_v0_3.Builder id(Object id) { + this.id = id; + return this; + } + + public GetAuthenticatedExtendedCardRequest_v0_3.Builder method(String method) { + this.method = method; + return this; + } + + public GetAuthenticatedExtendedCardRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new GetAuthenticatedExtendedCardRequest_v0_3(jsonrpc, id, method, null); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardResponse_v0_3.java new file mode 100644 index 000000000..5a7db5167 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardResponse_v0_3.java @@ -0,0 +1,20 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * A response for the `agent/getAuthenticatedExtendedCard` method. + */ +public final class GetAuthenticatedExtendedCardResponse_v0_3 extends JSONRPCResponse_v0_3 { + + public GetAuthenticatedExtendedCardResponse_v0_3(String jsonrpc, Object id, AgentCard_v0_3 result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, AgentCard_v0_3.class); + } + + public GetAuthenticatedExtendedCardResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } + + public GetAuthenticatedExtendedCardResponse_v0_3(Object id, AgentCard_v0_3 result) { + this(null, id, result, null); + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigParams_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigParams_v0_3.java new file mode 100644 index 000000000..6a5687565 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigParams_v0_3.java @@ -0,0 +1,50 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + + +import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; + +/** + * Parameters for fetching a pushNotificationConfiguration associated with a Task. + */ +public record GetTaskPushNotificationConfigParams_v0_3(String id, @Nullable String pushNotificationConfigId, @Nullable Map metadata) { + + public GetTaskPushNotificationConfigParams_v0_3 { + Assert.checkNotNullParam("id", id); + } + + public GetTaskPushNotificationConfigParams_v0_3(String id) { + this(id, null, null); + } + + public GetTaskPushNotificationConfigParams_v0_3(String id, String pushNotificationConfigId) { + this(id, pushNotificationConfigId, null); + } + + public static class Builder { + String id; + String pushNotificationConfigId; + Map metadata; + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder pushNotificationConfigId(String pushNotificationConfigId) { + this.pushNotificationConfigId = pushNotificationConfigId; + return this; + } + + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public GetTaskPushNotificationConfigParams_v0_3 build() { + return new GetTaskPushNotificationConfigParams_v0_3(id, pushNotificationConfigId, metadata); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigRequest_v0_3.java new file mode 100644 index 000000000..536423fe8 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigRequest_v0_3.java @@ -0,0 +1,67 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.compat03.util.Utils_v0_3; + +import java.util.UUID; + +/** + * A get task push notification request. + */ +public final class GetTaskPushNotificationConfigRequest_v0_3 extends NonStreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "tasks/pushNotificationConfig/get"; + + public GetTaskPushNotificationConfigRequest_v0_3(String jsonrpc, Object id, String method, GetTaskPushNotificationConfigParams_v0_3 params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid GetTaskPushNotificationRequest method"); + } + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = Utils_v0_3.defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public GetTaskPushNotificationConfigRequest_v0_3(String id, GetTaskPushNotificationConfigParams_v0_3 params) { + this(null, id, METHOD, params); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method; + private GetTaskPushNotificationConfigParams_v0_3 params; + + public GetTaskPushNotificationConfigRequest_v0_3.Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public GetTaskPushNotificationConfigRequest_v0_3.Builder id(Object id) { + this.id = id; + return this; + } + + public GetTaskPushNotificationConfigRequest_v0_3.Builder method(String method) { + this.method = method; + return this; + } + + public GetTaskPushNotificationConfigRequest_v0_3.Builder params(GetTaskPushNotificationConfigParams_v0_3 params) { + this.params = params; + return this; + } + + public GetTaskPushNotificationConfigRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new GetTaskPushNotificationConfigRequest_v0_3(jsonrpc, id, method, params); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigResponse_v0_3.java new file mode 100644 index 000000000..d817cf844 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigResponse_v0_3.java @@ -0,0 +1,20 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * A response for a get task push notification request. + */ +public final class GetTaskPushNotificationConfigResponse_v0_3 extends JSONRPCResponse_v0_3 { + + public GetTaskPushNotificationConfigResponse_v0_3(String jsonrpc, Object id, TaskPushNotificationConfig_v0_3 result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, TaskPushNotificationConfig_v0_3.class); + } + + public GetTaskPushNotificationConfigResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } + + public GetTaskPushNotificationConfigResponse_v0_3(Object id, TaskPushNotificationConfig_v0_3 result) { + this(null, id, result, null); + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskRequest_v0_3.java new file mode 100644 index 000000000..ac097bdcb --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskRequest_v0_3.java @@ -0,0 +1,71 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +import java.util.UUID; + + +import org.a2aproject.sdk.util.Assert; + +/** + * A get task request. + */ +public final class GetTaskRequest_v0_3 extends NonStreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "tasks/get"; + + public GetTaskRequest_v0_3(String jsonrpc, Object id, String method, TaskQueryParams_v0_3 params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid GetTaskRequest method"); + } + Assert.checkNotNullParam("params", params); + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public GetTaskRequest_v0_3(Object id, TaskQueryParams_v0_3 params) { + this(null, id, METHOD, params); + } + + + public static class Builder { + private String jsonrpc; + private Object id; + private String method = "tasks/get"; + private TaskQueryParams_v0_3 params; + + public GetTaskRequest_v0_3.Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public GetTaskRequest_v0_3.Builder id(Object id) { + this.id = id; + return this; + } + + public GetTaskRequest_v0_3.Builder method(String method) { + this.method = method; + return this; + } + + public GetTaskRequest_v0_3.Builder params(TaskQueryParams_v0_3 params) { + this.params = params; + return this; + } + + public GetTaskRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new GetTaskRequest_v0_3(jsonrpc, id, method, params); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskResponse_v0_3.java new file mode 100644 index 000000000..68f768bcc --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskResponse_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * The response for a get task request. + */ +public final class GetTaskResponse_v0_3 extends JSONRPCResponse_v0_3 { + + public GetTaskResponse_v0_3(String jsonrpc, Object id, Task_v0_3 result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, Task_v0_3.class); + } + + public GetTaskResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } + + public GetTaskResponse_v0_3(Object id, Task_v0_3 result) { + this(null, id, result, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java new file mode 100644 index 000000000..15729a7d6 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java @@ -0,0 +1,73 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines a security scheme using HTTP authentication. + */ +public final class HTTPAuthSecurityScheme_v0_3 implements SecurityScheme_v0_3 { + + public static final String HTTP = "http"; + private final String bearerFormat; + private final String scheme; + private final String description; + private final String type; + + public HTTPAuthSecurityScheme_v0_3(String bearerFormat, String scheme, String description) { + this(bearerFormat, scheme, description, HTTP); + } + + public HTTPAuthSecurityScheme_v0_3(String bearerFormat, String scheme, String description, String type) { + Assert.checkNotNullParam("scheme", scheme); + Assert.checkNotNullParam("type", type); + if (! HTTP.equals(type)) { + throw new IllegalArgumentException("Invalid type for HTTPAuthSecurityScheme"); + } + this.bearerFormat = bearerFormat; + this.scheme = scheme; + this.description = description; + this.type = type; + } + + @Override + public String getDescription() { + return description; + } + + public String getBearerFormat() { + return bearerFormat; + } + + public String getScheme() { + return scheme; + } + + public String getType() { + return type; + } + + public static class Builder { + private String bearerFormat; + private String scheme; + private String description; + + public Builder bearerFormat(String bearerFormat) { + this.bearerFormat = bearerFormat; + return this; + } + + public Builder scheme(String scheme) { + this.scheme = scheme; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public HTTPAuthSecurityScheme_v0_3 build() { + return new HTTPAuthSecurityScheme_v0_3(bearerFormat, scheme, description); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IdJsonMappingException_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IdJsonMappingException_v0_3.java new file mode 100644 index 000000000..c0971fcb0 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IdJsonMappingException_v0_3.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.compat03.json.JsonMappingException_v0_3; + +public class IdJsonMappingException_v0_3 extends JsonMappingException_v0_3 { + + Object id; + + public IdJsonMappingException_v0_3(String msg, Object id) { + super(msg); + this.id = id; + } + + public IdJsonMappingException_v0_3(String msg, Throwable cause, Object id) { + super(msg, cause); + this.id = id; + } + + public Object getId() { + return id; + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ImplicitOAuthFlow_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ImplicitOAuthFlow_v0_3.java new file mode 100644 index 000000000..200abacbe --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ImplicitOAuthFlow_v0_3.java @@ -0,0 +1,17 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines configuration details for the OAuth 2.0 Implicit flow. + */ +public record ImplicitOAuthFlow_v0_3(String authorizationUrl, String refreshUrl, Map scopes) { + + public ImplicitOAuthFlow_v0_3 { + Assert.checkNotNullParam("authorizationUrl", authorizationUrl); + Assert.checkNotNullParam("scopes", scopes); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IntegerJsonrpcId_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IntegerJsonrpcId_v0_3.java new file mode 100644 index 000000000..c84c65cac --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IntegerJsonrpcId_v0_3.java @@ -0,0 +1,4 @@ +package org.a2aproject.sdk.compat03.spec; + +public class IntegerJsonrpcId_v0_3 { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InternalError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InternalError_v0_3.java new file mode 100644 index 000000000..ac01992b3 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InternalError_v0_3.java @@ -0,0 +1,23 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + + +/** + * An error indicating an internal error on the server. + */ +public class InternalError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = A2AErrorCodes_v0_3.INTERNAL_ERROR_CODE; + + public InternalError_v0_3(Integer code, String message, Object data) { + super( + defaultIfNull(code, A2AErrorCodes_v0_3.INTERNAL_ERROR_CODE), + defaultIfNull(message, "Internal Error"), + data); + } + + public InternalError_v0_3(String message) { + this(null, message, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidAgentResponseError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidAgentResponseError_v0_3.java new file mode 100644 index 000000000..ee222fe71 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidAgentResponseError_v0_3.java @@ -0,0 +1,50 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + + +/** + * A2A Protocol error indicating that an agent returned a response not conforming to protocol specifications. + *

            + * This error is typically raised by client implementations when validating agent responses. + * It indicates that the agent's response structure, content, or format violates the A2A Protocol + * requirements for the invoked method. + *

            + * Common violations: + *

              + *
            • Missing required fields in response objects
            • + *
            • Invalid field types or values
            • + *
            • Malformed event stream data
            • + *
            • Response doesn't match declared agent capabilities
            • + *
            + *

            + * Corresponds to A2A-specific error code {@code -32006}. + *

            + * Usage example: + *

            {@code
            + * SendMessageResponse response = client.sendMessage(request);
            + * if (response.task() == null) {
            + *     throw new InvalidAgentResponseError(
            + *         null,
            + *         "Response missing required 'task' field",
            + *         null
            + *     );
            + * }
            + * }
            + * + * @see JSONRPCResponse_v0_3 for response structure + * @see SendMessageResponse_v0_3 for message send response + * @see A2A Protocol Specification + + */ +public class InvalidAgentResponseError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = A2AErrorCodes_v0_3.INVALID_AGENT_RESPONSE_ERROR_CODE; + + public InvalidAgentResponseError_v0_3(Integer code, String message, Object data) { + super( + defaultIfNull(code, A2AErrorCodes_v0_3.INVALID_AGENT_RESPONSE_ERROR_CODE), + defaultIfNull(message, "Invalid agent response"), + data); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidParamsError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidParamsError_v0_3.java new file mode 100644 index 000000000..a7864a9ac --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidParamsError_v0_3.java @@ -0,0 +1,50 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +/** + * JSON-RPC error indicating that method parameters are invalid or missing required fields. + *

            + * This error is returned when a JSON-RPC method is called with parameters that fail validation. + * Common causes include: + *

              + *
            • Missing required parameters
            • + *
            • Parameters of incorrect type
            • + *
            • Parameter values outside acceptable ranges
            • + *
            • Malformed parameter structures
            • + *
            + *

            + * Corresponds to JSON-RPC 2.0 error code {@code -32602}. + *

            + * Usage example: + *

            {@code
            + * // Default error with standard message
            + * throw new InvalidParamsError();
            + *
            + * // Custom error message
            + * throw new InvalidParamsError("taskId parameter is required");
            + * }
            + * + * @see JSONRPCError_v0_3 for the base error class + * @see A2AError_v0_3 for the error marker interface + * @see JSON-RPC 2.0 Error Codes + */ +public class InvalidParamsError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = A2AErrorCodes_v0_3.INVALID_PARAMS_ERROR_CODE; + + public InvalidParamsError_v0_3(Integer code, String message, Object data) { + super( + defaultIfNull(code, A2AErrorCodes_v0_3.INVALID_PARAMS_ERROR_CODE), + defaultIfNull(message, "Invalid parameters"), + data); + } + + public InvalidParamsError_v0_3(String message) { + this(null, message, null); + } + + public InvalidParamsError_v0_3() { + this(null, null, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidParamsJsonMappingException_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidParamsJsonMappingException_v0_3.java new file mode 100644 index 000000000..3ebb2e505 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidParamsJsonMappingException_v0_3.java @@ -0,0 +1,12 @@ +package org.a2aproject.sdk.compat03.spec; + +public class InvalidParamsJsonMappingException_v0_3 extends IdJsonMappingException_v0_3 { + + public InvalidParamsJsonMappingException_v0_3(String msg, Object id) { + super(msg, id); + } + + public InvalidParamsJsonMappingException_v0_3(String msg, Throwable cause, Object id) { + super(msg, cause, id); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidRequestError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidRequestError_v0_3.java new file mode 100644 index 000000000..f86c2de48 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/InvalidRequestError_v0_3.java @@ -0,0 +1,51 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + + +/** + * JSON-RPC error indicating that the request payload is not a valid JSON-RPC Request object. + *

            + * This error is returned when the JSON-RPC request fails structural validation. + * Common causes include: + *

              + *
            • Missing required JSON-RPC fields (jsonrpc, method, id)
            • + *
            • Invalid JSON-RPC version (must be "2.0")
            • + *
            • Malformed request structure
            • + *
            • Type mismatches in required fields
            • + *
            + *

            + * Corresponds to JSON-RPC 2.0 error code {@code -32600}. + *

            + * Usage example: + *

            {@code
            + * // Default error with standard message
            + * throw new InvalidRequestError();
            + *
            + * // Custom error message
            + * throw new InvalidRequestError("Missing 'method' field in request");
            + * }
            + * + * @see JSONRPCError_v0_3 for the base error class + * @see A2AError_v0_3 for the error marker interface + * @see JSON-RPC 2.0 Error Codes + */ +public class InvalidRequestError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = A2AErrorCodes_v0_3.INVALID_REQUEST_ERROR_CODE; + + public InvalidRequestError_v0_3() { + this(null, null, null); + } + + public InvalidRequestError_v0_3(Integer code, String message, Object data) { + super( + defaultIfNull(code, A2AErrorCodes_v0_3.INVALID_REQUEST_ERROR_CODE), + defaultIfNull(message, "Request payload validation error"), + data); + } + + public InvalidRequestError_v0_3(String message) { + this(null, message, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONErrorResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONErrorResponse_v0_3.java new file mode 100644 index 000000000..acf16d9a8 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONErrorResponse_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.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_v0_3}, 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_v0_3 + * @see JSONRPCError_v0_3 + */ +public record JSONErrorResponse_v0_3(String error) { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONParseError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONParseError_v0_3.java new file mode 100644 index 000000000..78c1d398b --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONParseError_v0_3.java @@ -0,0 +1,50 @@ +package org.a2aproject.sdk.compat03.spec; + + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +/** + * JSON-RPC error indicating that the server received invalid JSON that could not be parsed. + *

            + * This error is returned when the request payload is not valid JSON, such as malformed syntax, + * unexpected tokens, or encoding issues. This is distinct from {@link InvalidRequestError_v0_3}, + * which indicates structurally valid JSON that doesn't conform to the JSON-RPC specification. + *

            + * Corresponds to JSON-RPC 2.0 error code {@code -32700}. + *

            + * Usage example: + *

            {@code
            + * try {
            + *     objectMapper.readValue(payload, JSONRPCRequest.class);
            + * } catch (org.a2aproject.sdk.compat03.json.JsonProcessingException e) {
            + *     throw new JSONParseError("Malformed JSON: " + e.getMessage());
            + * }
            + * }
            + * + * @see JSONRPCError_v0_3 for the base error class + * @see A2AError_v0_3 for the error marker interface + * @see InvalidRequestError_v0_3 for structurally valid but invalid requests + * @see JSON-RPC 2.0 Error Codes + */ +public class JSONParseError_v0_3 extends JSONRPCError_v0_3 implements A2AError_v0_3 { + + public final static Integer DEFAULT_CODE = -32700; + + public JSONParseError_v0_3() { + this(null, null, null); + } + + public JSONParseError_v0_3(String message) { + this(null, message, null); + } + + public JSONParseError_v0_3( + Integer code, + String message, + Object data) { + super( + defaultIfNull(code, DEFAULT_CODE), + defaultIfNull(message, "Invalid JSON payload"), + data); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCErrorResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCErrorResponse_v0_3.java new file mode 100644 index 000000000..87548fd73 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCErrorResponse_v0_3.java @@ -0,0 +1,33 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * A JSON RPC error response. + */ +public final class JSONRPCErrorResponse_v0_3 extends JSONRPCResponse_v0_3 { + + /** + * Constructs a JSON-RPC error response with all fields. + *

            + * This constructor is used for JSON deserialization. + * + * @param jsonrpc the JSON-RPC version (must be "2.0") + * @param id the request ID, or null if the ID could not be determined from the request + * @param result must be null for error responses + * @param error the error object describing what went wrong (required) + * @throws IllegalArgumentException if error is null + */ + public JSONRPCErrorResponse_v0_3(String jsonrpc, Object id, Void result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, Void.class); + Assert.checkNotNullParam("error", error); + } + + public JSONRPCErrorResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } + + public JSONRPCErrorResponse_v0_3(JSONRPCError_v0_3 error) { + this(null, null, null, error); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCError_v0_3.java new file mode 100644 index 000000000..3dcde042a --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCError_v0_3.java @@ -0,0 +1,49 @@ +package org.a2aproject.sdk.compat03.spec; + + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a JSON-RPC 2.0 Error object, included in an error response. + */ +public class JSONRPCError_v0_3 extends Error implements Event_v0_3, A2AError_v0_3 { + + private final Integer 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_v0_3(Integer code, String message, Object data) { + super(message); + Assert.checkNotNullParam("code", code); + Assert.checkNotNullParam("message", message); + this.code = code; + this.data = data; + } + + /** + * Gets the error code + * + * @return the error code + */ + public Integer getCode() { + return code; + } + + /** + * Gets the data associated with the error. + * + * @return the data. May be {@code null} + */ + public Object getData() { + return data; + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCMessage_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCMessage_v0_3.java new file mode 100644 index 000000000..10e4da716 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCMessage_v0_3.java @@ -0,0 +1,13 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Defines the base structure for any JSON-RPC 2.0 request, response, or notification. + */ +public sealed interface JSONRPCMessage_v0_3 permits JSONRPCRequest_v0_3, JSONRPCResponse_v0_3 { + + String JSONRPC_VERSION = "2.0"; + + String getJsonrpc(); + Object getId(); + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCRequest_v0_3.java new file mode 100644 index 000000000..fc5fc58bf --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCRequest_v0_3.java @@ -0,0 +1,47 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a JSONRPC request. + */ +public abstract sealed class JSONRPCRequest_v0_3 implements JSONRPCMessage_v0_3 permits NonStreamingJSONRPCRequest_v0_3, StreamingJSONRPCRequest_v0_3 { + + protected String jsonrpc; + protected Object id; + protected String method; + protected T params; + + public JSONRPCRequest_v0_3() { + } + + public JSONRPCRequest_v0_3(String jsonrpc, Object id, String method, T params) { + Assert.checkNotNullParam("jsonrpc", jsonrpc); + Assert.checkNotNullParam("method", method); + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + @Override + public String getJsonrpc() { + return this.jsonrpc; + } + + @Override + public Object getId() { + return this.id; + } + + public String getMethod() { + return this.method; + } + + public T getParams() { + return this.params; + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCResponse_v0_3.java new file mode 100644 index 000000000..58822eea1 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCResponse_v0_3.java @@ -0,0 +1,57 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a JSONRPC response. + */ +public abstract sealed class JSONRPCResponse_v0_3 implements JSONRPCMessage_v0_3 permits SendStreamingMessageResponse_v0_3, + GetTaskResponse_v0_3, CancelTaskResponse_v0_3, SetTaskPushNotificationConfigResponse_v0_3, GetTaskPushNotificationConfigResponse_v0_3, + SendMessageResponse_v0_3, DeleteTaskPushNotificationConfigResponse_v0_3, ListTaskPushNotificationConfigResponse_v0_3, JSONRPCErrorResponse_v0_3, + GetAuthenticatedExtendedCardResponse_v0_3 { + + protected String jsonrpc; + protected Object id; + protected T result; + protected JSONRPCError_v0_3 error; + + public JSONRPCResponse_v0_3() { + } + + public JSONRPCResponse_v0_3(String jsonrpc, Object id, T result, JSONRPCError_v0_3 error, Class resultType) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + if (error != null && result != null) { + throw new IllegalArgumentException("Invalid JSON-RPC error response"); + } + if (error == null && result == null && ! Void.class.equals(resultType)) { + throw new IllegalArgumentException("Invalid JSON-RPC success response"); + } + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.result = result; + this.error = error; + } + + @Override + public String getJsonrpc() { + return this.jsonrpc; + } + + @Override + public Object getId() { + return this.id; + } + + public T getResult() { + return this.result; + } + + public JSONRPCError_v0_3 getError() { + return this.error; + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JsonrpcId_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JsonrpcId_v0_3.java new file mode 100644 index 000000000..1817c46f2 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JsonrpcId_v0_3.java @@ -0,0 +1,4 @@ +package org.a2aproject.sdk.compat03.spec; + +public interface JsonrpcId_v0_3 { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigParams_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigParams_v0_3.java new file mode 100644 index 000000000..b68456343 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigParams_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Parameters for getting list of pushNotificationConfigurations associated with a Task. + */ +public record ListTaskPushNotificationConfigParams_v0_3(String id, Map metadata) { + + public ListTaskPushNotificationConfigParams_v0_3 { + Assert.checkNotNullParam("id", id); + } + + public ListTaskPushNotificationConfigParams_v0_3(String id) { + this(id, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigRequest_v0_3.java new file mode 100644 index 000000000..f8c1b597e --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigRequest_v0_3.java @@ -0,0 +1,67 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.UUID; + +import org.a2aproject.sdk.util.Assert; +import org.a2aproject.sdk.compat03.util.Utils_v0_3; + +/** + * A list task push notification config request. + */ +public final class ListTaskPushNotificationConfigRequest_v0_3 extends NonStreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "tasks/pushNotificationConfig/list"; + + public ListTaskPushNotificationConfigRequest_v0_3(String jsonrpc, Object id, String method, ListTaskPushNotificationConfigParams_v0_3 params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid ListTaskPushNotificationConfigRequest method"); + } + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = Utils_v0_3.defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public ListTaskPushNotificationConfigRequest_v0_3(String id, ListTaskPushNotificationConfigParams_v0_3 params) { + this(null, id, METHOD, params); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method; + private ListTaskPushNotificationConfigParams_v0_3 params; + + public Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public Builder id(Object id) { + this.id = id; + return this; + } + + public Builder method(String method) { + this.method = method; + return this; + } + + public Builder params(ListTaskPushNotificationConfigParams_v0_3 params) { + this.params = params; + return this; + } + + public ListTaskPushNotificationConfigRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new ListTaskPushNotificationConfigRequest_v0_3(jsonrpc, id, method, params); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigResponse_v0_3.java new file mode 100644 index 000000000..447fe02de --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigResponse_v0_3.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; + +/** + * A response for a list task push notification config request. + */ +public final class ListTaskPushNotificationConfigResponse_v0_3 extends JSONRPCResponse_v0_3> { + + public ListTaskPushNotificationConfigResponse_v0_3(String jsonrpc, Object id, List result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, (Class>) (Class) List.class); + } + + public ListTaskPushNotificationConfigResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } + + public ListTaskPushNotificationConfigResponse_v0_3(Object id, List result) { + this(null, id, result, null); + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendConfiguration_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendConfiguration_v0_3.java new file mode 100644 index 000000000..6ca4cef69 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendConfiguration_v0_3.java @@ -0,0 +1,54 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; + +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + +/** + * Defines configuration options for a `message/send` or `message/stream` request. + */ +public record MessageSendConfiguration_v0_3(List acceptedOutputModes, Integer historyLength, + PushNotificationConfig_v0_3 pushNotificationConfig, Boolean blocking) { + + public MessageSendConfiguration_v0_3 { + if (historyLength != null && historyLength < 0) { + throw new IllegalArgumentException("Invalid history length"); + } + } + + public static class Builder { + + List acceptedOutputModes; + Integer historyLength; + PushNotificationConfig_v0_3 pushNotificationConfig; + Boolean blocking = true; + + public Builder acceptedOutputModes(List acceptedOutputModes) { + this.acceptedOutputModes = acceptedOutputModes; + return this; + } + + public Builder pushNotificationConfig(@Nullable PushNotificationConfig_v0_3 pushNotificationConfig) { + this.pushNotificationConfig = pushNotificationConfig; + return this; + } + + public Builder historyLength(@Nullable Integer historyLength) { + if (historyLength != null && historyLength < 0) { + throw new IllegalArgumentException("Invalid history length"); + } + this.historyLength = historyLength; + return this; + } + + public Builder blocking(@NonNull Boolean blocking) { + this.blocking = blocking; + return this; + } + + public MessageSendConfiguration_v0_3 build() { + return new MessageSendConfiguration_v0_3(acceptedOutputModes, historyLength, pushNotificationConfig, blocking); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendParams_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendParams_v0_3.java new file mode 100644 index 000000000..3b5571c52 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendParams_v0_3.java @@ -0,0 +1,47 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines the parameters for a request to send a message to an agent. This can be used + * to create a new task, continue an existing one, or restart a task. + */ +public record MessageSendParams_v0_3(Message_v0_3 message, MessageSendConfiguration_v0_3 configuration, + Map metadata) { + + public MessageSendParams_v0_3 { + Assert.checkNotNullParam("message", message); + } + + public void check() { + Assert.checkNotNullParam("message", message); + message.check(); + } + + public static class Builder { + Message_v0_3 message; + MessageSendConfiguration_v0_3 configuration; + Map metadata; + + public Builder message(Message_v0_3 message) { + this.message = message; + return this; + } + + public Builder configuration(MessageSendConfiguration_v0_3 configuration) { + this.configuration = configuration; + return this; + } + + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public MessageSendParams_v0_3 build() { + return new MessageSendParams_v0_3(message, configuration, metadata); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java new file mode 100644 index 000000000..16dc0ad8e --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java @@ -0,0 +1,209 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a single message in the conversation between a user and an agent. + */ +public final class Message_v0_3 implements EventKind_v0_3, StreamingEventKind_v0_3 { + + public static final String MESSAGE = "message"; + private final Role role; + private final List> parts; + private final String messageId; + private String contextId; + private String taskId; + private final Map metadata; + private final String kind; + private final List referenceTaskIds; + private final List extensions; + + public Message_v0_3(Role role, List> parts, String messageId, String contextId, String taskId, + List referenceTaskIds, Map metadata, List extensions) { + this(role, parts, messageId, contextId, taskId, referenceTaskIds, metadata, extensions, MESSAGE); + } + + public Message_v0_3(Role role, List> parts, + String messageId, String contextId, + String taskId, List referenceTaskIds, + Map metadata, List extensions, + String kind) { + Assert.checkNotNullParam("kind", kind); + Assert.checkNotNullParam("parts", parts); + if (parts.isEmpty()) { + throw new IllegalArgumentException("Parts cannot be empty"); + } + Assert.checkNotNullParam("role", role); + if (! kind.equals(MESSAGE)) { + throw new IllegalArgumentException("Invalid Message"); + } + Assert.checkNotNullParam("messageId", messageId); + this.role = role; + this.parts = parts; + this.messageId = messageId; + this.contextId = contextId; + this.taskId = taskId; + this.referenceTaskIds = referenceTaskIds; + this.metadata = metadata; + this.extensions = extensions; + this.kind = kind; + } + + public void check() { + Assert.checkNotNullParam("kind", kind); + Assert.checkNotNullParam("parts", parts); + if (parts.isEmpty()) { + throw new IllegalArgumentException("Parts cannot be empty"); + } + Assert.checkNotNullParam("role", role); + if (!kind.equals(MESSAGE)) { + throw new IllegalArgumentException("Invalid Message"); + } + Assert.checkNotNullParam("messageId", messageId); + } + + public Role getRole() { + return role; + } + + public List> getParts() { + return parts; + } + + public String getMessageId() { + return messageId; + } + + public String getContextId() { + return contextId; + } + + public String getTaskId() { + return taskId; + } + + public Map getMetadata() { + return metadata; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public void setContextId(String contextId) { + this.contextId = contextId; + } + + public List getReferenceTaskIds() { + return referenceTaskIds; + } + + public List getExtensions() { + return extensions; + } + + @Override + public String getKind() { + return kind; + } + + public enum Role { + USER("user"), + AGENT("agent"); + + private final String role; + + Role(String role) { + this.role = role; + } + + /** + * Returns the string representation of the role for JSON serialization. + * + * @return the role as a string ("user" or "agent") + */ + public String asString() { + return this.role; + } + } + + public static class Builder { + + private Role role; + private List> parts; + private String messageId; + private String contextId; + private String taskId; + private List referenceTaskIds; + private Map metadata; + private List extensions; + + public Builder() { + } + + public Builder(Message_v0_3 message) { + role = message.role; + parts = message.parts; + messageId = message.messageId; + contextId = message.contextId; + taskId = message.taskId; + referenceTaskIds = message.referenceTaskIds; + metadata = message.metadata; + extensions = message.extensions; + } + + public Builder role(Role role) { + this.role = role; + return this; + } + + public Builder parts(List> parts) { + this.parts = parts; + return this; + } + + public Builder parts(Part_v0_3...parts) { + this.parts = List.of(parts); + return this; + } + + public Builder messageId(String messageId) { + this.messageId = messageId; + return this; + } + + public Builder contextId(String contextId) { + this.contextId = contextId; + return this; + } + + public Builder taskId(String taskId) { + this.taskId = taskId; + return this; + } + + public Builder referenceTaskIds(List referenceTaskIds) { + this.referenceTaskIds = referenceTaskIds; + return this; + } + + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public Builder extensions(List extensions) { + this.extensions = (extensions == null) ? null : List.copyOf(extensions); + return this; + } + + public Message_v0_3 build() { + return new Message_v0_3(role, parts, messageId == null ? UUID.randomUUID().toString() : messageId, + contextId, taskId, referenceTaskIds, metadata, extensions); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MethodNotFoundError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MethodNotFoundError_v0_3.java new file mode 100644 index 000000000..1ceba9637 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MethodNotFoundError_v0_3.java @@ -0,0 +1,20 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.METHOD_NOT_FOUND_ERROR_CODE; +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +/** + * An error indicating that the requested method does not exist or is not available. + */ +public class MethodNotFoundError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = METHOD_NOT_FOUND_ERROR_CODE; + + public MethodNotFoundError_v0_3(Integer code, String message, Object data) { + super(defaultIfNull(code, METHOD_NOT_FOUND_ERROR_CODE), defaultIfNull(message, "Method not found"), data); + } + + public MethodNotFoundError_v0_3() { + this(METHOD_NOT_FOUND_ERROR_CODE, null, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MethodNotFoundJsonMappingException_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MethodNotFoundJsonMappingException_v0_3.java new file mode 100644 index 000000000..819b72b4d --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MethodNotFoundJsonMappingException_v0_3.java @@ -0,0 +1,12 @@ +package org.a2aproject.sdk.compat03.spec; + +public class MethodNotFoundJsonMappingException_v0_3 extends IdJsonMappingException_v0_3 { + + public MethodNotFoundJsonMappingException_v0_3(String msg, Object id) { + super(msg, id); + } + + public MethodNotFoundJsonMappingException_v0_3(String msg, Throwable cause, Object id) { + super(msg, cause, id); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java new file mode 100644 index 000000000..dd7ca56ec --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java @@ -0,0 +1,40 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines a security scheme using mTLS authentication. + */ +public final class MutualTLSSecurityScheme_v0_3 implements SecurityScheme_v0_3 { + + public static final String MUTUAL_TLS = "mutualTLS"; + private final String description; + private final String type; + + public MutualTLSSecurityScheme_v0_3(String description) { + this(description, MUTUAL_TLS); + } + + public MutualTLSSecurityScheme_v0_3() { + this(null, MUTUAL_TLS); + } + + public MutualTLSSecurityScheme_v0_3(String description, String type) { + Assert.checkNotNullParam("type", type); + if (!type.equals(MUTUAL_TLS)) { + throw new IllegalArgumentException("Invalid type for MutualTLSSecurityScheme"); + } + this.description = description; + this.type = type; + } + + @Override + public String getDescription() { + return description; + } + + public String getType() { + return type; + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/NonStreamingJSONRPCRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/NonStreamingJSONRPCRequest_v0_3.java new file mode 100644 index 000000000..972a1fb39 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/NonStreamingJSONRPCRequest_v0_3.java @@ -0,0 +1,10 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Represents a non-streaming JSON-RPC request. + */ +public abstract sealed class NonStreamingJSONRPCRequest_v0_3 extends JSONRPCRequest_v0_3 permits GetTaskRequest_v0_3, + CancelTaskRequest_v0_3, SetTaskPushNotificationConfigRequest_v0_3, GetTaskPushNotificationConfigRequest_v0_3, + SendMessageRequest_v0_3, DeleteTaskPushNotificationConfigRequest_v0_3, ListTaskPushNotificationConfigRequest_v0_3, + GetAuthenticatedExtendedCardRequest_v0_3 { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java new file mode 100644 index 000000000..c0f1de56e --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java @@ -0,0 +1,73 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines a security scheme using OAuth 2.0. + */ +public final class OAuth2SecurityScheme_v0_3 implements SecurityScheme_v0_3 { + + public static final String OAUTH2 = "oauth2"; + private final OAuthFlows_v0_3 flows; + private final String description; + private final String type; + private final String oauth2MetadataUrl; + + public OAuth2SecurityScheme_v0_3(OAuthFlows_v0_3 flows, String description, String oauth2MetadataUrl) { + this(flows, description, oauth2MetadataUrl, OAUTH2); + } + + public OAuth2SecurityScheme_v0_3(OAuthFlows_v0_3 flows, String description, String oauth2MetadataUrl, String type) { + Assert.checkNotNullParam("flows", flows); + Assert.checkNotNullParam("type", type); + if (!type.equals(OAUTH2)) { + throw new IllegalArgumentException("Invalid type for OAuth2SecurityScheme"); + } + this.flows = flows; + this.description = description; + this.oauth2MetadataUrl = oauth2MetadataUrl; + this.type = type; + } + + @Override + public String getDescription() { + return description; + } + + public OAuthFlows_v0_3 getFlows() { + return flows; + } + + public String getType() { + return type; + } + + public String getOauth2MetadataUrl() { + return oauth2MetadataUrl; + } + + public static class Builder { + private OAuthFlows_v0_3 flows; + private String description; + private String oauth2MetadataUrl; + + public Builder flows(OAuthFlows_v0_3 flows) { + this.flows = flows; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder oauth2MetadataUrl(String oauth2MetadataUrl) { + this.oauth2MetadataUrl = oauth2MetadataUrl; + return this; + } + + public OAuth2SecurityScheme_v0_3 build() { + return new OAuth2SecurityScheme_v0_3(flows, description, oauth2MetadataUrl); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuthFlows_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuthFlows_v0_3.java new file mode 100644 index 000000000..1acf64c57 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuthFlows_v0_3.java @@ -0,0 +1,39 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Defines the configuration for the supported OAuth 2.0 flows. + */ +public record OAuthFlows_v0_3(AuthorizationCodeOAuthFlow_v0_3 authorizationCode, ClientCredentialsOAuthFlow_v0_3 clientCredentials, + ImplicitOAuthFlow_v0_3 implicit, PasswordOAuthFlow_v0_3 password) { + + public static class Builder { + private AuthorizationCodeOAuthFlow_v0_3 authorizationCode; + private ClientCredentialsOAuthFlow_v0_3 clientCredentials; + private ImplicitOAuthFlow_v0_3 implicit; + private PasswordOAuthFlow_v0_3 password; + + public Builder authorizationCode(AuthorizationCodeOAuthFlow_v0_3 authorizationCode) { + this.authorizationCode = authorizationCode; + return this; + } + + public Builder clientCredentials(ClientCredentialsOAuthFlow_v0_3 clientCredentials) { + this.clientCredentials = clientCredentials; + return this; + } + + public Builder implicit(ImplicitOAuthFlow_v0_3 implicit) { + this.implicit = implicit; + return this; + } + + public Builder password(PasswordOAuthFlow_v0_3 password) { + this.password = password; + return this; + } + + public OAuthFlows_v0_3 build() { + return new OAuthFlows_v0_3(authorizationCode, clientCredentials, implicit, password); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OpenIdConnectSecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OpenIdConnectSecurityScheme_v0_3.java new file mode 100644 index 000000000..81cbcc4c4 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OpenIdConnectSecurityScheme_v0_3.java @@ -0,0 +1,62 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines a security scheme using OpenID Connect. + */ +public final class OpenIdConnectSecurityScheme_v0_3 implements SecurityScheme_v0_3 { + + public static final String OPENID_CONNECT = "openIdConnect"; + private final String openIdConnectUrl; + private final String description; + private final String type; + + public OpenIdConnectSecurityScheme_v0_3(String openIdConnectUrl, String description) { + this(openIdConnectUrl, description, OPENID_CONNECT); + } + + public OpenIdConnectSecurityScheme_v0_3(String openIdConnectUrl, String description, String type) { + Assert.checkNotNullParam("type", type); + Assert.checkNotNullParam("openIdConnectUrl", openIdConnectUrl); + if (!type.equals(OPENID_CONNECT)) { + throw new IllegalArgumentException("Invalid type for OpenIdConnectSecurityScheme"); + } + this.openIdConnectUrl = openIdConnectUrl; + this.description = description; + this.type = type; + } + + @Override + public String getDescription() { + return description; + } + + public String getOpenIdConnectUrl() { + return openIdConnectUrl; + } + + public String getType() { + return type; + } + + public static class Builder { + private String openIdConnectUrl; + private String description; + + public Builder openIdConnectUrl(String openIdConnectUrl) { + this.openIdConnectUrl = openIdConnectUrl; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public OpenIdConnectSecurityScheme_v0_3 build() { + return new OpenIdConnectSecurityScheme_v0_3(openIdConnectUrl, description); + } + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Part_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Part_v0_3.java new file mode 100644 index 000000000..79d3df4d7 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Part_v0_3.java @@ -0,0 +1,35 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +/** + * A fundamental unit with a Message or Artifact. + * @param the type of unit + */ +public abstract class Part_v0_3 { + public enum Kind { + TEXT("text"), + FILE("file"), + DATA("data"); + + private final String kind; + + Kind(String kind) { + this.kind = kind; + } + + /** + * Returns the string representation of the kind for JSON serialization. + * + * @return the kind as a string + */ + public String asString() { + return this.kind; + } + } + + public abstract Kind getKind(); + + public abstract Map getMetadata(); + +} \ No newline at end of file diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PasswordOAuthFlow_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PasswordOAuthFlow_v0_3.java new file mode 100644 index 000000000..eb1dec150 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PasswordOAuthFlow_v0_3.java @@ -0,0 +1,16 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines configuration details for the OAuth 2.0 Resource Owner Password flow. + */ +public record PasswordOAuthFlow_v0_3(String refreshUrl, Map scopes, String tokenUrl) { + + public PasswordOAuthFlow_v0_3 { + Assert.checkNotNullParam("scopes", scopes); + Assert.checkNotNullParam("tokenUrl", tokenUrl); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationAuthenticationInfo_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationAuthenticationInfo_v0_3.java new file mode 100644 index 000000000..e4f9d235a --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationAuthenticationInfo_v0_3.java @@ -0,0 +1,14 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; +import org.a2aproject.sdk.util.Assert; + +/** + * Defines authentication details for a push notification endpoint. + */ +public record PushNotificationAuthenticationInfo_v0_3(List schemes, String credentials) { + + public PushNotificationAuthenticationInfo_v0_3 { + Assert.checkNotNullParam("schemes", schemes); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationConfig_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationConfig_v0_3.java new file mode 100644 index 000000000..de8c7a68e --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationConfig_v0_3.java @@ -0,0 +1,54 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines the configuration for setting up push notifications for task updates. + */ +public record PushNotificationConfig_v0_3(String url, String token, PushNotificationAuthenticationInfo_v0_3 authentication, String id) { + + public PushNotificationConfig_v0_3 { + Assert.checkNotNullParam("url", url); + } + + public static class Builder { + private String url; + private String token; + private PushNotificationAuthenticationInfo_v0_3 authentication; + private String id; + + public Builder() { + } + + public Builder(PushNotificationConfig_v0_3 notificationConfig) { + this.url = notificationConfig.url; + this.token = notificationConfig.token; + this.authentication = notificationConfig.authentication; + this.id = notificationConfig.id; + } + + public Builder url(String url) { + this.url = url; + return this; + } + + public Builder token(String token) { + this.token = token; + return this; + } + + public Builder authenticationInfo(PushNotificationAuthenticationInfo_v0_3 authenticationInfo) { + this.authentication = authenticationInfo; + return this; + } + + public Builder id(String id) { + this.id = id; + return this; + } + + public PushNotificationConfig_v0_3 build() { + return new PushNotificationConfig_v0_3(url, token, authentication, id); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationNotSupportedError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationNotSupportedError_v0_3.java new file mode 100644 index 000000000..1b660e287 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/PushNotificationNotSupportedError_v0_3.java @@ -0,0 +1,25 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +/** + * An A2A-specific error indicating that the agent does not support push notifications. + */ +public class PushNotificationNotSupportedError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = -32003; + + public PushNotificationNotSupportedError_v0_3() { + this(null, null, null); + } + + public PushNotificationNotSupportedError_v0_3( + Integer code, + String message, + Object data) { + super( + defaultIfNull(code, DEFAULT_CODE), + defaultIfNull(message, "Push Notification is not supported"), + data); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SecurityScheme_v0_3.java new file mode 100644 index 000000000..36903e849 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SecurityScheme_v0_3.java @@ -0,0 +1,11 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Defines a security scheme that can be used to secure an agent's endpoints. + * This is a discriminated union type based on the OpenAPI 3.0 Security Scheme Object. + */ +public sealed interface SecurityScheme_v0_3 permits APIKeySecurityScheme_v0_3, HTTPAuthSecurityScheme_v0_3, OAuth2SecurityScheme_v0_3, + OpenIdConnectSecurityScheme_v0_3, MutualTLSSecurityScheme_v0_3 { + + String getDescription(); +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageRequest_v0_3.java new file mode 100644 index 000000000..c57a6cba9 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageRequest_v0_3.java @@ -0,0 +1,100 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +import java.util.UUID; + +import org.a2aproject.sdk.util.Assert; + +/** + * Used to send a message request. + */ +public final class SendMessageRequest_v0_3 extends NonStreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "message/send"; + + /** + * Constructs a SendMessageRequest with the specified JSON-RPC fields. + *

            + * This constructor is used for JSON deserialization and validates + * that the method name is exactly "SendMessage". + * + * @param jsonrpc the JSON-RPC version (must be "2.0") + * @param id the request correlation identifier (String, Integer, or null) + * @param method the method name (must be {@value #METHOD}) + * @param params the message send parameters (required) + * @throws IllegalArgumentException if validation fails + */ + public SendMessageRequest_v0_3(String jsonrpc, Object id, String method, MessageSendParams_v0_3 params) { + if (jsonrpc == null || jsonrpc.isEmpty()) { + throw new IllegalArgumentException("JSON-RPC protocol version cannot be null or empty"); + } + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid SendMessageRequest method"); + } + Assert.checkNotNullParam("params", params); + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public void check() { + if (jsonrpc == null || jsonrpc.isEmpty()) { + throw new IllegalArgumentException("JSON-RPC protocol version cannot be null or empty"); + } + if (jsonrpc != null && !jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (!method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid SendMessageRequest method"); + } + Assert.checkNotNullParam("params", params); + Assert.isNullOrStringOrInteger(id); + params.check(); + } + + public SendMessageRequest_v0_3(Object id, MessageSendParams_v0_3 params) { + this(JSONRPC_VERSION, id, METHOD, params); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method; + private MessageSendParams_v0_3 params; + + public Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public Builder id(Object id) { + this.id = id; + return this; + } + + public Builder method(String method) { + this.method = method; + return this; + } + + public Builder params(MessageSendParams_v0_3 params) { + this.params = params; + return this; + } + + public SendMessageRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new SendMessageRequest_v0_3(jsonrpc, id, method, params); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageResponse_v0_3.java new file mode 100644 index 000000000..b779bca00 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageResponse_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * The response after receiving a send message request. + */ +public final class SendMessageResponse_v0_3 extends JSONRPCResponse_v0_3 { + + public SendMessageResponse_v0_3(String jsonrpc, Object id, EventKind_v0_3 result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, EventKind_v0_3.class); + } + + public SendMessageResponse_v0_3(Object id, EventKind_v0_3 result) { + this(null, id, result, null); + } + + public SendMessageResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageRequest_v0_3.java new file mode 100644 index 000000000..91e7f3260 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageRequest_v0_3.java @@ -0,0 +1,82 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +import org.a2aproject.sdk.util.Assert; + +import java.util.UUID; + +/** + * Used to initiate a task with streaming. + */ +public final class SendStreamingMessageRequest_v0_3 extends StreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "message/stream"; + + public SendStreamingMessageRequest_v0_3(String jsonrpc, Object id, String method, MessageSendParams_v0_3 params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid SendStreamingMessageRequest method"); + } + Assert.checkNotNullParam("params", params); + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public void check() { + if (jsonrpc != null && !jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (!method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid SendStreamingMessageRequest method"); + } + Assert.checkNotNullParam("params", params); + Assert.isNullOrStringOrInteger(id); + params.check(); + } + + public SendStreamingMessageRequest_v0_3(Object id, MessageSendParams_v0_3 params) { + this(null, id, METHOD, params); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method = METHOD; + private MessageSendParams_v0_3 params; + + public Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public Builder id(Object id) { + this.id = id; + return this; + } + + public Builder method(String method) { + this.method = method; + return this; + } + + public Builder params(MessageSendParams_v0_3 params) { + this.params = params; + return this; + } + + public SendStreamingMessageRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new SendStreamingMessageRequest_v0_3(jsonrpc, id, method, params); + } + } + } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageResponse_v0_3.java new file mode 100644 index 000000000..75df3f983 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageResponse_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * The response after receiving a request to initiate a task with streaming. + */ +public final class SendStreamingMessageResponse_v0_3 extends JSONRPCResponse_v0_3 { + + public SendStreamingMessageResponse_v0_3(String jsonrpc, Object id, StreamingEventKind_v0_3 result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, StreamingEventKind_v0_3.class); + } + + public SendStreamingMessageResponse_v0_3(Object id, StreamingEventKind_v0_3 result) { + this(null, id, result, null); + } + + public SendStreamingMessageResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigRequest_v0_3.java new file mode 100644 index 000000000..130831b0e --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigRequest_v0_3.java @@ -0,0 +1,69 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +import java.util.UUID; + +import org.a2aproject.sdk.util.Assert; + +/** + * Used to set a task push notification request. + */ +public final class SetTaskPushNotificationConfigRequest_v0_3 extends NonStreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "tasks/pushNotificationConfig/set"; + + public SetTaskPushNotificationConfigRequest_v0_3(String jsonrpc, Object id, String method, TaskPushNotificationConfig_v0_3 params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid SetTaskPushNotificationRequest method"); + } + Assert.checkNotNullParam("params", params); + Assert.isNullOrStringOrInteger(id); + this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id; + this.method = method; + this.params = params; + } + + public SetTaskPushNotificationConfigRequest_v0_3(String id, TaskPushNotificationConfig_v0_3 taskPushConfig) { + this(null, id, METHOD, taskPushConfig); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method = METHOD; + private TaskPushNotificationConfig_v0_3 params; + + public SetTaskPushNotificationConfigRequest_v0_3.Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public SetTaskPushNotificationConfigRequest_v0_3.Builder id(Object id) { + this.id = id; + return this; + } + + public SetTaskPushNotificationConfigRequest_v0_3.Builder method(String method) { + this.method = method; + return this; + } + + public SetTaskPushNotificationConfigRequest_v0_3.Builder params(TaskPushNotificationConfig_v0_3 params) { + this.params = params; + return this; + } + + public SetTaskPushNotificationConfigRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new SetTaskPushNotificationConfigRequest_v0_3(jsonrpc, id, method, params); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigResponse_v0_3.java new file mode 100644 index 000000000..054826f72 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigResponse_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * The response after receiving a set task push notification request. + */ +public final class SetTaskPushNotificationConfigResponse_v0_3 extends JSONRPCResponse_v0_3 { + + public SetTaskPushNotificationConfigResponse_v0_3(String jsonrpc, Object id, TaskPushNotificationConfig_v0_3 result, JSONRPCError_v0_3 error) { + super(jsonrpc, id, result, error, TaskPushNotificationConfig_v0_3.class); + } + + public SetTaskPushNotificationConfigResponse_v0_3(Object id, JSONRPCError_v0_3 error) { + this(null, id, null, error); + } + + public SetTaskPushNotificationConfigResponse_v0_3(Object id, TaskPushNotificationConfig_v0_3 result) { + this(null, id, result, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingEventKind_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingEventKind_v0_3.java new file mode 100644 index 000000000..ffc40df0e --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingEventKind_v0_3.java @@ -0,0 +1,35 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Sealed interface for events that can be emitted during streaming A2A Protocol operations. + *

            + * StreamingEventKind represents events suitable for asynchronous, progressive updates during + * agent task execution. Streaming allows agents to provide incremental feedback as work progresses, + * rather than waiting until task completion. + *

            + * Streaming events use polymorphic JSON serialization with the "kind" discriminator to determine + * the concrete type during deserialization. + *

            + * Permitted implementations: + *

              + *
            • {@link Task_v0_3} - Complete task state (typically the final event in a stream)
            • + *
            • {@link Message_v0_3} - Full message (complete message in the stream)
            • + *
            • {@link TaskStatusUpdateEvent_v0_3} - Incremental status updates (e.g., SUBMITTED → WORKING → COMPLETED)
            • + *
            • {@link TaskArtifactUpdateEvent_v0_3} - Incremental artifact updates (partial results, chunks)
            • + *
            + *

            + * Streaming events enable patterns like: + *

              + *
            • Progressive text generation (chunks of response as generated)
            • + *
            • Status notifications (task state transitions)
            • + *
            • Partial results (early artifacts before task completion)
            • + *
            + * + * @see Event_v0_3 + * @see EventKind_v0_3 + * @see UpdateEvent_v0_3 + */ +public sealed interface StreamingEventKind_v0_3 extends Event_v0_3 permits Task_v0_3, Message_v0_3, TaskStatusUpdateEvent_v0_3, TaskArtifactUpdateEvent_v0_3 { + + String getKind(); +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingJSONRPCRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingJSONRPCRequest_v0_3.java new file mode 100644 index 000000000..956fd8aab --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingJSONRPCRequest_v0_3.java @@ -0,0 +1,10 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Represents a streaming JSON-RPC request. + */ + +public abstract sealed class StreamingJSONRPCRequest_v0_3 extends JSONRPCRequest_v0_3 permits TaskResubscriptionRequest_v0_3, + SendStreamingMessageRequest_v0_3 { + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StringJsonrpcId_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StringJsonrpcId_v0_3.java new file mode 100644 index 000000000..f4ced0850 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StringJsonrpcId_v0_3.java @@ -0,0 +1,4 @@ +package org.a2aproject.sdk.compat03.spec; + +public class StringJsonrpcId_v0_3 { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java new file mode 100644 index 000000000..397756a2b --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java @@ -0,0 +1,128 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * An event sent by the agent to notify the client that an artifact has been + * generated or updated. This is typically used in streaming models. + */ +public final class TaskArtifactUpdateEvent_v0_3 implements EventKind_v0_3, StreamingEventKind_v0_3, UpdateEvent_v0_3 { + + public static final String ARTIFACT_UPDATE = "artifact-update"; + private final String taskId; + private final Boolean append; + private final Boolean lastChunk; + private final Artifact_v0_3 artifact; + private final String contextId; + private final Map metadata; + private final String kind; + + public TaskArtifactUpdateEvent_v0_3(String taskId, Artifact_v0_3 artifact, String contextId, Boolean append, Boolean lastChunk, Map metadata) { + this(taskId, artifact, contextId, append, lastChunk, metadata, ARTIFACT_UPDATE); + } + + public TaskArtifactUpdateEvent_v0_3(String taskId, Artifact_v0_3 artifact, String contextId, Boolean append, Boolean lastChunk, Map metadata, String kind) { + Assert.checkNotNullParam("taskId", taskId); + Assert.checkNotNullParam("artifact", artifact); + Assert.checkNotNullParam("contextId", contextId); + Assert.checkNotNullParam("kind", kind); + if (! kind.equals(ARTIFACT_UPDATE)) { + throw new IllegalArgumentException("Invalid TaskArtifactUpdateEvent"); + } + this.taskId = taskId; + this.artifact = artifact; + this.contextId = contextId; + this.append = append; + this.lastChunk = lastChunk; + this.metadata = metadata; + this.kind = kind; + } + + public String getTaskId() { + return taskId; + } + + public Artifact_v0_3 getArtifact() { + return artifact; + } + + public String getContextId() { + return contextId; + } + + public Boolean isAppend() { + return append; + } + + public Boolean isLastChunk() { + return lastChunk; + } + + public Map getMetadata() { + return metadata; + } + + @Override + public String getKind() { + return kind; + } + + public static class Builder { + + private String taskId; + private Artifact_v0_3 artifact; + private String contextId; + private Boolean append; + private Boolean lastChunk; + private Map metadata; + + public Builder() { + } + + public Builder(TaskArtifactUpdateEvent_v0_3 existingTaskArtifactUpdateEvent) { + this.taskId = existingTaskArtifactUpdateEvent.taskId; + this.artifact = existingTaskArtifactUpdateEvent.artifact; + this.contextId = existingTaskArtifactUpdateEvent.contextId; + this.append = existingTaskArtifactUpdateEvent.append; + this.lastChunk = existingTaskArtifactUpdateEvent.lastChunk; + this.metadata = existingTaskArtifactUpdateEvent.metadata; + } + + public Builder taskId(String taskId) { + this.taskId = taskId; + return this; + } + + public Builder artifact(Artifact_v0_3 artifact) { + this.artifact = artifact; + return this; + } + + public Builder contextId(String contextId) { + this.contextId = contextId; + return this; + } + + public Builder append(Boolean append) { + this.append = append; + return this; + } + + public Builder lastChunk(Boolean lastChunk) { + this.lastChunk = lastChunk; + return this; + } + + + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public TaskArtifactUpdateEvent_v0_3 build() { + return new TaskArtifactUpdateEvent_v0_3(taskId, artifact, contextId, append, lastChunk, metadata); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskIdParams_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskIdParams_v0_3.java new file mode 100644 index 000000000..5c44557da --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskIdParams_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Defines parameters containing a task ID, used for simple task operations. + */ +public record TaskIdParams_v0_3(String id, Map metadata) { + + public TaskIdParams_v0_3 { + Assert.checkNotNullParam("id", id); + } + + public TaskIdParams_v0_3(String id) { + this(id, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskNotCancelableError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskNotCancelableError_v0_3.java new file mode 100644 index 000000000..859f3c004 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskNotCancelableError_v0_3.java @@ -0,0 +1,30 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +/** + * An A2A-specific error indicating that the task is in a state where it cannot be canceled. + */ +public class TaskNotCancelableError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = -32002; + + public TaskNotCancelableError_v0_3() { + this(null, null, null); + } + + public TaskNotCancelableError_v0_3( + Integer code, + String message, + Object data) { + super( + defaultIfNull(code, DEFAULT_CODE), + defaultIfNull(message, "Task cannot be canceled"), + data); + } + + public TaskNotCancelableError_v0_3(String message) { + this(null, message, null); + } + +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskNotFoundError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskNotFoundError_v0_3.java new file mode 100644 index 000000000..b0786e906 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskNotFoundError_v0_3.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +/** + * An A2A-specific error indicating that the requested task ID was not found. + */ +public class TaskNotFoundError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = A2AErrorCodes_v0_3.TASK_NOT_FOUND_ERROR_CODE; + + public TaskNotFoundError_v0_3() { + this(null, null, null); + } + + public TaskNotFoundError_v0_3(Integer code, String message, Object data) { + super( + defaultIfNull(code, A2AErrorCodes_v0_3.TASK_NOT_FOUND_ERROR_CODE), + defaultIfNull(message, "Task not found"), + data); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskPushNotificationConfig_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskPushNotificationConfig_v0_3.java new file mode 100644 index 000000000..2efbe9a6f --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskPushNotificationConfig_v0_3.java @@ -0,0 +1,14 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * A container associating a push notification configuration with a specific task. + */ +public record TaskPushNotificationConfig_v0_3(String taskId, PushNotificationConfig_v0_3 pushNotificationConfig) { + + public TaskPushNotificationConfig_v0_3 { + Assert.checkNotNullParam("taskId", taskId); + Assert.checkNotNullParam("pushNotificationConfig", pushNotificationConfig); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskQueryParams_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskQueryParams_v0_3.java new file mode 100644 index 000000000..b96bfa8c2 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskQueryParams_v0_3.java @@ -0,0 +1,30 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.util.Assert; +import java.util.Map; +import org.jspecify.annotations.Nullable; + +/** + * Defines parameters for querying a task, with an option to limit history length. + * + * @param id the ID for the task to be queried + * @param historyLength the maximum number of items of history for the task to include in the response + * @param metadata additional properties + */ +public record TaskQueryParams_v0_3(String id, int historyLength, @Nullable Map metadata) { + + public TaskQueryParams_v0_3 { + Assert.checkNotNullParam("id", id); + if (historyLength < 0) { + throw new IllegalArgumentException("Invalid history length"); + } + } + + public TaskQueryParams_v0_3(String id) { + this(id, 0, null); + } + + public TaskQueryParams_v0_3(String id, int historyLength) { + this(id, historyLength, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskResubscriptionRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskResubscriptionRequest_v0_3.java new file mode 100644 index 000000000..d9bfbb7ed --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskResubscriptionRequest_v0_3.java @@ -0,0 +1,68 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +import org.a2aproject.sdk.util.Assert; + +import java.util.UUID; + +/** + * Used to resubscribe to a task. + */ +public final class TaskResubscriptionRequest_v0_3 extends StreamingJSONRPCRequest_v0_3 { + + public static final String METHOD = "tasks/resubscribe"; + + public TaskResubscriptionRequest_v0_3(String jsonrpc, Object id, String method, TaskIdParams_v0_3 params) { + if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { + throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); + } + Assert.checkNotNullParam("method", method); + if (! method.equals(METHOD)) { + throw new IllegalArgumentException("Invalid TaskResubscriptionRequest method"); + } + Assert.checkNotNullParam("params", params); + this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); + this.id = id == null ? UUID.randomUUID().toString() : id; + this.method = method; + this.params = params; + } + + public TaskResubscriptionRequest_v0_3(Object id, TaskIdParams_v0_3 params) { + this(null, id, METHOD, params); + } + + public static class Builder { + private String jsonrpc; + private Object id; + private String method = METHOD; + private TaskIdParams_v0_3 params; + + public TaskResubscriptionRequest_v0_3.Builder jsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + return this; + } + + public TaskResubscriptionRequest_v0_3.Builder id(Object id) { + this.id = id; + return this; + } + + public TaskResubscriptionRequest_v0_3.Builder method(String method) { + this.method = method; + return this; + } + + public TaskResubscriptionRequest_v0_3.Builder params(TaskIdParams_v0_3 params) { + this.params = params; + return this; + } + + public TaskResubscriptionRequest_v0_3 build() { + if (id == null) { + id = UUID.randomUUID().toString(); + } + return new TaskResubscriptionRequest_v0_3(jsonrpc, id, method, params); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskState_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskState_v0_3.java new file mode 100644 index 000000000..0bcbaa54d --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskState_v0_3.java @@ -0,0 +1,69 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Defines the lifecycle states of a Task. + */ +public enum TaskState_v0_3 { + SUBMITTED("submitted"), + WORKING("working"), + INPUT_REQUIRED("input-required"), + AUTH_REQUIRED("auth-required"), + COMPLETED("completed", true), + CANCELED("canceled", true), + FAILED("failed", true), + REJECTED("rejected", true), + UNKNOWN("unknown", true); + + private final String state; + private final boolean isFinal; + + TaskState_v0_3(String state) { + this(state, false); + } + + TaskState_v0_3(String state, boolean isFinal) { + this.state = state; + this.isFinal = isFinal; + } + + /** + * Returns the string representation of this task state for JSON serialization. + *

            + * This method is used to serialize TaskState values to their + * wire format (e.g., "working", "completed"). + * + * @return the string representation of this state + */ + public String asString() { + return state; + } + + public boolean isFinal(){ + return isFinal; + } + + /** + * Deserializes a string value into a TaskState enum constant. + *

            + * This method is used to deserialize TaskState values from their + * wire format during JSON parsing. + * + * @param state the string representation of the state + * @return the corresponding TaskState enum constant + * @throws IllegalArgumentException if the state string is not recognized + */ + public static TaskState_v0_3 fromString(String state) { + return switch (state) { + case "submitted" -> SUBMITTED; + case "working" -> WORKING; + case "input-required" -> INPUT_REQUIRED; + case "auth-required" -> AUTH_REQUIRED; + case "completed" -> COMPLETED; + case "canceled" -> CANCELED; + case "failed" -> FAILED; + case "rejected" -> REJECTED; + case "unknown" -> UNKNOWN; + default -> throw new IllegalArgumentException("Invalid TaskState: " + state); + }; + } +} \ No newline at end of file diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java new file mode 100644 index 000000000..f337169f6 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java @@ -0,0 +1,116 @@ +package org.a2aproject.sdk.compat03.spec; + +import com.google.gson.annotations.SerializedName; +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * An event sent by the agent to notify the client of a change in a task's status. + * This is typically used in streaming or subscription models. + */ +public final class TaskStatusUpdateEvent_v0_3 implements EventKind_v0_3, StreamingEventKind_v0_3, UpdateEvent_v0_3 { + + public static final String STATUS_UPDATE = "status-update"; + private final String taskId; + private final TaskStatus_v0_3 status; + private final String contextId; + @SerializedName("final") + private final boolean isFinal; + private final Map metadata; + private final String kind; + + + public TaskStatusUpdateEvent_v0_3(String taskId, TaskStatus_v0_3 status, String contextId, boolean isFinal, + Map metadata) { + this(taskId, status, contextId, isFinal, metadata, STATUS_UPDATE); + } + + public TaskStatusUpdateEvent_v0_3(String taskId, TaskStatus_v0_3 status, String contextId, boolean isFinal, Map metadata, String kind) { + Assert.checkNotNullParam("taskId", taskId); + Assert.checkNotNullParam("status", status); + Assert.checkNotNullParam("contextId", contextId); + Assert.checkNotNullParam("kind", kind); + if (! kind.equals(STATUS_UPDATE)) { + throw new IllegalArgumentException("Invalid TaskStatusUpdateEvent"); + } + this.taskId = taskId; + this.status = status; + this.contextId = contextId; + this.isFinal = isFinal; + this.metadata = metadata; + this.kind = kind; + } + + public String getTaskId() { + return taskId; + } + + public TaskStatus_v0_3 getStatus() { + return status; + } + + public String getContextId() { + return contextId; + } + + public boolean isFinal() { + return isFinal; + } + + public Map getMetadata() { + return metadata; + } + + @Override + public String getKind() { + return kind; + } + + public static class Builder { + private String taskId; + private TaskStatus_v0_3 status; + private String contextId; + private boolean isFinal; + private Map metadata; + + public Builder() { + } + + public Builder(TaskStatusUpdateEvent_v0_3 existingTaskStatusUpdateEvent) { + this.taskId = existingTaskStatusUpdateEvent.taskId; + this.status = existingTaskStatusUpdateEvent.status; + this.contextId = existingTaskStatusUpdateEvent.contextId; + this.isFinal = existingTaskStatusUpdateEvent.isFinal; + this.metadata = existingTaskStatusUpdateEvent.metadata; + } + public Builder taskId(String id) { + this.taskId = id; + return this; + } + + public Builder status(TaskStatus_v0_3 status) { + this.status = status; + return this; + } + + public Builder contextId(String contextId) { + this.contextId = contextId; + return this; + } + + public Builder isFinal(boolean isFinal) { + this.isFinal = isFinal; + return this; + } + + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public TaskStatusUpdateEvent_v0_3 build() { + return new TaskStatusUpdateEvent_v0_3(taskId, status, contextId, isFinal, metadata); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatus_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatus_v0_3.java new file mode 100644 index 000000000..6ffa77ac3 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatus_v0_3.java @@ -0,0 +1,31 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents the status of a task at a specific point in time. + */ +public record TaskStatus_v0_3(TaskState_v0_3 state, Message_v0_3 message, + OffsetDateTime timestamp) { + + public TaskStatus_v0_3 { + Assert.checkNotNullParam("state", state); + timestamp = timestamp == null ? OffsetDateTime.now(ZoneOffset.UTC) : timestamp; + } + + public TaskStatus_v0_3(TaskState_v0_3 state) { + this(state, null, null); + } + + /** + * Constructor for testing purposes. + * @param state the task state + * @param timestamp timestamp generation + */ + TaskStatus_v0_3(TaskState_v0_3 state, OffsetDateTime timestamp) { + this(state, null, timestamp); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java new file mode 100644 index 000000000..87e486013 --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java @@ -0,0 +1,136 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.List; +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a single, stateful operation or conversation between a client and an agent. + */ +public final class Task_v0_3 implements EventKind_v0_3, StreamingEventKind_v0_3 { + + public static final String TASK = "task"; + private final String id; + private final String contextId; + private final TaskStatus_v0_3 status; + private final List artifacts; + private final List history; + private final Map metadata; + private final String kind; + + public Task_v0_3(String id, String contextId, TaskStatus_v0_3 status, List artifacts, + List history, Map metadata) { + this(id, contextId, status, artifacts, history, metadata, TASK); + } + + public Task_v0_3(String id, String contextId, TaskStatus_v0_3 status, + List artifacts, List history, + Map metadata, String kind) { + Assert.checkNotNullParam("id", id); + Assert.checkNotNullParam("contextId", contextId); + Assert.checkNotNullParam("status", status); + Assert.checkNotNullParam("kind", kind); + if (! kind.equals(TASK)) { + throw new IllegalArgumentException("Invalid Task"); + } + this.id = id; + this.contextId = contextId; + this.status = status; + this.artifacts = artifacts != null ? List.copyOf(artifacts) : List.of(); + this.history = history != null ? List.copyOf(history) : List.of(); + this.metadata = metadata; + this.kind = kind; + } + + public String getId() { + return id; + } + + public String getContextId() { + return contextId; + } + + public TaskStatus_v0_3 getStatus() { + return status; + } + + public List getArtifacts() { + return artifacts; + } + + public List getHistory() { + return history; + } + + public Map getMetadata() { + return metadata; + } + + @Override + public String getKind() { + return kind; + } + + public static class Builder { + private String id; + private String contextId; + private TaskStatus_v0_3 status; + private List artifacts; + private List history; + private Map metadata; + + public Builder() { + + } + + public Builder(Task_v0_3 task) { + id = task.id; + contextId = task.contextId; + status = task.status; + artifacts = task.artifacts; + history = task.history; + metadata = task.metadata; + + } + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder contextId(String contextId) { + this.contextId = contextId; + return this; + } + + public Builder status(TaskStatus_v0_3 status) { + this.status = status; + return this; + } + + public Builder artifacts(List artifacts) { + this.artifacts = artifacts; + return this; + } + + public Builder history(List history) { + this.history = history; + return this; + } + + public Builder history(Message_v0_3... history) { + this.history = List.of(history); + return this; + } + + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public Task_v0_3 build() { + return new Task_v0_3(id, contextId, status, artifacts, history, metadata); + } + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java new file mode 100644 index 000000000..4d5b604ce --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java @@ -0,0 +1,41 @@ +package org.a2aproject.sdk.compat03.spec; + +import java.util.Map; + +import org.a2aproject.sdk.util.Assert; + +/** + * Represents a text segment within a message or artifact. + */ +public class TextPart_v0_3 extends Part_v0_3 { + + public static final String TEXT = "text"; + private final String text; + private final Map metadata; + private final Kind kind; + + public TextPart_v0_3(String text) { + this(text, null); + } + + public TextPart_v0_3(String text, Map metadata) { + Assert.checkNotNullParam("text", text); + this.text = text; + this.metadata = metadata; + this.kind = Kind.TEXT; + } + + @Override + public Kind getKind() { + return kind; + } + + public String getText() { + return text; + } + + @Override + public Map getMetadata() { + return metadata; + } +} \ No newline at end of file diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TransportProtocol_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TransportProtocol_v0_3.java new file mode 100644 index 000000000..f6368f9cc --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TransportProtocol_v0_3.java @@ -0,0 +1,45 @@ +package org.a2aproject.sdk.compat03.spec; + +/** + * Supported A2A transport protocols. + */ +public enum TransportProtocol_v0_3 { + JSONRPC("JSONRPC"), + GRPC("GRPC"), + HTTP_JSON("HTTP+JSON"); + + private final String transport; + + TransportProtocol_v0_3(String transport) { + this.transport = transport; + } + + /** + * Returns the string representation of this transport protocol. + *

            + * Used for JSON serialization. + * + * @return the transport protocol name as a string + */ + public String asString() { + return transport; + } + + /** + * Parses a string into a {@link TransportProtocol_v0_3} enum constant. + *

            + * Used for JSON deserialization. + * + * @param transport the transport protocol string (e.g., "JSONRPC", "GRPC", "HTTP+JSON") + * @return the corresponding TransportProtocol enum constant + * @throws IllegalArgumentException if the transport string is not recognized + */ + public static TransportProtocol_v0_3 fromString(String transport) { + return switch (transport) { + case "JSONRPC" -> JSONRPC; + case "GRPC" -> GRPC; + case "HTTP+JSON" -> HTTP_JSON; + default -> throw new IllegalArgumentException("Invalid transport: " + transport); + }; + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/UnsupportedOperationError_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/UnsupportedOperationError_v0_3.java new file mode 100644 index 000000000..434aab21c --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/UnsupportedOperationError_v0_3.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.spec; + +import static org.a2aproject.sdk.compat03.util.Utils_v0_3.defaultIfNull; + +/** + * An A2A-specific error indicating that the requested operation is not supported by the agent. + */ +public class UnsupportedOperationError_v0_3 extends JSONRPCError_v0_3 { + + public final static Integer DEFAULT_CODE = A2AErrorCodes_v0_3.UNSUPPORTED_OPERATION_ERROR_CODE; + + public UnsupportedOperationError_v0_3(Integer code, String message, Object data) { + super( + defaultIfNull(code, A2AErrorCodes_v0_3.UNSUPPORTED_OPERATION_ERROR_CODE), + defaultIfNull(message, "This operation is not supported"), + data); + } + + public UnsupportedOperationError_v0_3() { + this(null, null, null); + } +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/UpdateEvent_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/UpdateEvent_v0_3.java new file mode 100644 index 000000000..d2f7b8e7f --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/UpdateEvent_v0_3.java @@ -0,0 +1,4 @@ +package org.a2aproject.sdk.compat03.spec; + +public sealed interface UpdateEvent_v0_3 permits TaskStatusUpdateEvent_v0_3, TaskArtifactUpdateEvent_v0_3 { +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/util/Utils_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/util/Utils_v0_3.java new file mode 100644 index 000000000..38df3adfc --- /dev/null +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/util/Utils_v0_3.java @@ -0,0 +1,168 @@ +package org.a2aproject.sdk.compat03.util; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.Gson; +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; + +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.Part_v0_3; +import java.util.logging.Logger; + + + +/** + * Utility class providing common helper methods for A2A Protocol operations. + *

            + * This class contains static utility methods for JSON serialization/deserialization, + * null-safe operations, artifact management, and other common tasks used throughout + * the A2A Java SDK. + *

            + * Key capabilities: + *

              + *
            • JSON processing with pre-configured {@link Gson}
            • + *
            • Null-safe value defaults via {@link #defaultIfNull(Object, Object)}
            • + *
            • Artifact streaming support via {@link #appendArtifactToTask(Task_v0_3, TaskArtifactUpdateEvent_v0_3, String)}
            • + *
            • Type-safe exception rethrowing via {@link #rethrow(Throwable)}
            • + *
            + * + * @see Gson for JSON processing + * @see TaskArtifactUpdateEvent_v0_3 for streaming artifact updates + */ +public class Utils_v0_3 { + + + private static final Logger log = Logger.getLogger(Utils_v0_3.class.getName()); + + /** + * Deserializes JSON string into a typed object using Gson. + *

            + * This method uses the pre-configured {@link JsonUtil_v0_3#OBJECT_MAPPER} 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_v0_3 if JSON parsing fails + */ + public static T unmarshalFrom(String data, Class typeRef) throws JsonProcessingException_v0_3 { + return JsonUtil_v0_3.fromJson(data, typeRef); + } + + public static String toJsonString(Object data) { + try { + return JsonUtil_v0_3.toJson(data); + } catch (JsonProcessingException_v0_3 e) { + throw new RuntimeException("Failed to serialize to JSON", e); + } + } + + public static T defaultIfNull(T value, T defaultValue) { + if (value == null) { + return defaultValue; + } + return value; + } + + public static void rethrow(Throwable t) throws T { + throw (T) t; + } + + /** + * Appends or updates an artifact in a task based on a {@link TaskArtifactUpdateEvent_v0_3}. + *

            + * This method handles streaming artifact updates, supporting both: + *

              + *
            • Adding new artifacts to the task
            • + *
            • Replacing existing artifacts (when {@code append=false})
            • + *
            • Appending parts to existing artifacts (when {@code append=true})
            • + *
            + *

            + * The {@code append} flag in the event determines the behavior: + *

              + *
            • {@code false} or {@code null}: Replace/add the entire artifact
            • + *
            • {@code true}: Append the new artifact's parts to an existing artifact with matching {@code artifactId}
            • + *
            + * + * @param task the current task to update + * @param event the artifact update event containing the new/updated artifact + * @param taskId the task ID (for logging purposes) + * @return a new Task instance with the updated artifacts list + * @see TaskArtifactUpdateEvent_v0_3 for streaming artifact updates + * @see Artifact_v0_3 for artifact structure + */ + public static Task_v0_3 appendArtifactToTask(Task_v0_3 task, TaskArtifactUpdateEvent_v0_3 event, String taskId) { + // Append artifacts + List artifacts = task.getArtifacts() == null ? new ArrayList<>() : new ArrayList<>(task.getArtifacts()); + + Artifact_v0_3 newArtifact = event.getArtifact(); + String artifactId = newArtifact.artifactId(); + boolean appendParts = event.isAppend() != null && event.isAppend(); + + Artifact_v0_3 existingArtifact = null; + int existingArtifactIndex = -1; + + for (int i = 0; i < artifacts.size(); i++) { + Artifact_v0_3 curr = artifacts.get(i); + if (curr.artifactId() != null && curr.artifactId().equals(artifactId)) { + existingArtifact = curr; + existingArtifactIndex = i; + break; + } + } + + if (!appendParts) { + // This represents the first chunk for this artifact index + if (existingArtifactIndex >= 0) { + // Replace the existing artifact entirely with the new artifact + log.fine(String.format("Replacing artifact at id %s for task %s", artifactId, taskId)); + artifacts.set(existingArtifactIndex, newArtifact); + } else { + // Append the new artifact since no artifact with this id/index exists yet + log.fine(String.format("Adding artifact at id %s for task %s", artifactId, taskId)); + artifacts.add(newArtifact); + } + + } else if (existingArtifact != null) { + // Append new parts to the existing artifact's parts list + // Do this to a copy + log.fine(String.format("Appending parts to artifact id %s for task %s", artifactId, taskId)); + List> parts = new ArrayList<>(existingArtifact.parts()); + parts.addAll(newArtifact.parts()); + Artifact_v0_3 updated = new Artifact_v0_3.Builder(existingArtifact) + .parts(parts) + .build(); + artifacts.set(existingArtifactIndex, updated); + } else { + // We received a chunk to append, but we don't have an existing artifact. + // We will ignore this chunk + log.warning( + String.format("Received append=true for nonexistent artifact index for artifact %s in task %s. Ignoring chunk.", + artifactId, taskId)); + } + + return new Task_v0_3.Builder(task) + .artifacts(artifacts) + .build(); + + } + + /** + * Get the first defined URL in the supported interaces of the agent card. + * + * @param agentCard the agentcard where the interfaces are defined. + * @return the first defined URL in the supported interaces of the agent card. + * @throws A2AClientException + */ +// public static String getFavoriteInterface(AgentCard agentCard) throws A2AClientException { +// if (agentCard.supportedInterfaces() == null || agentCard.supportedInterfaces().isEmpty()) { +// throw new A2AClientException("No server interface available in the AgentCard"); +// } +// return agentCard.supportedInterfaces().get(0).url(); +// } + +} diff --git a/compat-0.3/spec/src/main/resources/META-INF/beans.xml b/compat-0.3/spec/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..e69de29bb diff --git a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/JSONRPCErrorSerialization_v0_3_Test.java b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/JSONRPCErrorSerialization_v0_3_Test.java new file mode 100644 index 000000000..5060770b8 --- /dev/null +++ b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/JSONRPCErrorSerialization_v0_3_Test.java @@ -0,0 +1,82 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +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.assertTrue; + +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; + + +public class JSONRPCErrorSerialization_v0_3_Test { + @Test + public void shouldDeserializeToCorrectJSONRPCErrorSubclass() throws JsonProcessingException_v0_3 { + String jsonTemplate = """ + {"code": %s, "message": "error", "data": "anything"} + """; + + record ErrorCase(int code, Class clazz) {} + + List cases = List.of( + new ErrorCase(JSONParseError_v0_3.DEFAULT_CODE, JSONParseError_v0_3.class), + new ErrorCase(InvalidRequestError_v0_3.DEFAULT_CODE, InvalidRequestError_v0_3.class), + new ErrorCase(MethodNotFoundError_v0_3.DEFAULT_CODE, MethodNotFoundError_v0_3.class), + new ErrorCase(InvalidParamsError_v0_3.DEFAULT_CODE, InvalidParamsError_v0_3.class), + new ErrorCase(InternalError_v0_3.DEFAULT_CODE, InternalError_v0_3.class), + new ErrorCase(PushNotificationNotSupportedError_v0_3.DEFAULT_CODE, PushNotificationNotSupportedError_v0_3.class), + new ErrorCase(UnsupportedOperationError_v0_3.DEFAULT_CODE, UnsupportedOperationError_v0_3.class), + new ErrorCase(ContentTypeNotSupportedError_v0_3.DEFAULT_CODE, ContentTypeNotSupportedError_v0_3.class), + new ErrorCase(InvalidAgentResponseError_v0_3.DEFAULT_CODE, InvalidAgentResponseError_v0_3.class), + new ErrorCase(TaskNotCancelableError_v0_3.DEFAULT_CODE, TaskNotCancelableError_v0_3.class), + new ErrorCase(TaskNotFoundError_v0_3.DEFAULT_CODE, TaskNotFoundError_v0_3.class), + new ErrorCase(Integer.MAX_VALUE, JSONRPCError_v0_3.class) // Any unknown code will be treated as JSONRPCError + ); + + for (ErrorCase errorCase : cases) { + String json = jsonTemplate.formatted(errorCase.code()); + JSONRPCError_v0_3 error = JsonUtil_v0_3.fromJson(json, JSONRPCError_v0_3.class); + assertInstanceOf(errorCase.clazz(), error); + assertEquals("error", error.getMessage()); + assertEquals("anything", error.getData().toString()); + } + } + + @Test + @SuppressWarnings("unchecked") + void deleteTaskPushNotificationConfigSuccessResponseSerializesResultAsNull() throws JsonProcessingException_v0_3 { + DeleteTaskPushNotificationConfigResponse_v0_3 response = + new DeleteTaskPushNotificationConfigResponse_v0_3("req-123"); + + String json = JsonUtil_v0_3.toJson(response); + Map map = JsonUtil_v0_3.fromJson(json, Map.class); + + assertEquals("2.0", map.get("jsonrpc")); + assertEquals("req-123", map.get("id")); + assertTrue(map.containsKey("result"), "result field must be present in success response"); + assertEquals(null, map.get("result"), "result must be null for delete response"); + assertFalse(map.containsKey("error"), "error field must not be present in success response"); + } + + @Test + @SuppressWarnings("unchecked") + void deleteTaskPushNotificationConfigErrorResponseSerializesErrorWithoutResult() throws JsonProcessingException_v0_3 { + DeleteTaskPushNotificationConfigResponse_v0_3 response = + new DeleteTaskPushNotificationConfigResponse_v0_3("req-456", new TaskNotFoundError_v0_3()); + + String json = JsonUtil_v0_3.toJson(response); + Map map = JsonUtil_v0_3.fromJson(json, Map.class); + + assertEquals("2.0", map.get("jsonrpc")); + assertEquals("req-456", map.get("id")); + assertTrue(map.containsKey("error"), "error field must be present in error response"); + assertFalse(map.containsKey("result"), "result field must not be present in error response"); + } + + +} diff --git a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/SubTypeSerialization_v0_3_Test.java b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/SubTypeSerialization_v0_3_Test.java new file mode 100644 index 000000000..96c89c152 --- /dev/null +++ b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/SubTypeSerialization_v0_3_Test.java @@ -0,0 +1,102 @@ +package org.a2aproject.sdk.compat03.spec; + +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Map; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SubTypeSerialization_v0_3_Test { + + private static final Task_v0_3 MINIMAL_TASK = new Task_v0_3.Builder() + .id("task-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + + @ParameterizedTest + @MethodSource("serializationTestCases") + void testSubtypeSerialization(Object objectToSerialize, String typePropertyName, String expectedTypeValue) throws JsonProcessingException_v0_3 { + String json = JsonUtil_v0_3.toJson(objectToSerialize); + @SuppressWarnings("unchecked") + Map map = JsonUtil_v0_3.fromJson(json, Map.class); + assertEquals(expectedTypeValue, map.get(typePropertyName)); + } + + private static Stream serializationTestCases() { + return Stream.of( + Arguments.of( + new TaskStatusUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .isFinal(true) + .build(), "kind", TaskStatusUpdateEvent_v0_3.STATUS_UPDATE + ), + Arguments.of( + new TaskArtifactUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .artifact(new Artifact_v0_3.Builder() + .artifactId("11") + .parts(new TextPart_v0_3("text")) + .build()) + .build(), "kind", TaskArtifactUpdateEvent_v0_3.ARTIFACT_UPDATE + ), + Arguments.of( + MINIMAL_TASK, "kind", Task_v0_3.TASK + ), + Arguments.of( + new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(new TextPart_v0_3("tell me some jokes")) + .contextId("context-1234") + .messageId("message-1234") + .build(), "kind", Message_v0_3.MESSAGE + ), + Arguments.of( + new TextPart_v0_3("text"), "kind", TextPart_v0_3.TEXT + ), + Arguments.of( + new FilePart_v0_3(new FileWithUri_v0_3( + "image/jpeg", null, "file:///path/to/image.jpg")), + "kind", FilePart_v0_3.FILE + ), + Arguments.of( + new DataPart_v0_3(Map.of("chartType", "bar")), "kind", DataPart_v0_3.DATA + ), + Arguments.of( + new APIKeySecurityScheme_v0_3.Builder() + .in("test").name("name").description("description").build(), + "type", APIKeySecurityScheme_v0_3.API_KEY + ), + Arguments.of( + new HTTPAuthSecurityScheme_v0_3.Builder() + .scheme("basic").description("Basic Auth").build(), + "type", HTTPAuthSecurityScheme_v0_3.HTTP + ), + Arguments.of( + new OAuth2SecurityScheme_v0_3.Builder() + .flows(new OAuthFlows_v0_3.Builder().build()) + .description("oAuth2SecurityScheme").build(), + "type", OAuth2SecurityScheme_v0_3.OAUTH2 + ), + Arguments.of( + new OpenIdConnectSecurityScheme_v0_3.Builder() + .openIdConnectUrl("https://accounts.google.com/.well-known/openid-configuration") + .description("OpenId").build(), + "type", OpenIdConnectSecurityScheme_v0_3.OPENID_CONNECT + ), + Arguments.of( + new MutualTLSSecurityScheme_v0_3("mutual tls test"), + "type", MutualTLSSecurityScheme_v0_3.MUTUAL_TLS + ) + ); + } + +} diff --git a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java new file mode 100644 index 000000000..f1ed534a9 --- /dev/null +++ b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java @@ -0,0 +1,713 @@ +package org.a2aproject.sdk.compat03.spec; + +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 static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.OffsetDateTime; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; + +/** + * Tests for Task serialization and deserialization using Gson. + */ +class TaskSerialization_v0_3_Test { + + @Test + void testBasicTaskSerialization() throws JsonProcessingException_v0_3 { + // Create a basic task + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + + // Serialize to JSON + String json = JsonUtil_v0_3.toJson(task); + + // Verify JSON contains expected fields + assertNotNull(json); + assertTrue(json.contains("\"id\":\"task-123\"")); + assertTrue(json.contains("\"state\":\"submitted\"")); + + // Deserialize back to Task + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify deserialized task matches original + assertEquals(task.getId(), deserialized.getId()); + assertEquals(task.getStatus().state(), deserialized.getStatus().state()); + } + + @Test + void testTaskWithTimestamp() throws JsonProcessingException_v0_3 { + OffsetDateTime timestamp = OffsetDateTime.now(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.WORKING, null, timestamp)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify OffsetDateTime timestamp is preserved + assertNotNull(deserialized.getStatus().timestamp()); + assertEquals(task.getStatus().timestamp(), deserialized.getStatus().timestamp()); + } + + @Test + void testTaskWithArtifacts() throws JsonProcessingException_v0_3 { + Artifact_v0_3 artifact = new Artifact_v0_3.Builder() + .artifactId("artifact-1") + .name("Test Artifact") + .description("Description of artifact") + .parts(List.of( + new TextPart_v0_3("Hello"), + new TextPart_v0_3("World") + )) + .build(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .artifacts(List.of(artifact)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Verify JSON contains artifact data + assertTrue(json.contains("\"artifactId\":\"artifact-1\"")); + assertTrue(json.contains("Hello")); + assertTrue(json.contains("World")); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify artifacts are preserved + assertNotNull(deserialized.getArtifacts()); + assertEquals(1, deserialized.getArtifacts().size()); + assertEquals("artifact-1", deserialized.getArtifacts().get(0).artifactId()); + assertEquals(2, deserialized.getArtifacts().get(0).parts().size()); + } + + @Test + void testTaskWithHistory() throws JsonProcessingException_v0_3 { + Message_v0_3 message = new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(List.of(new TextPart_v0_3("Test message"))) + .build(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.WORKING)) + .history(List.of(message)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Verify JSON contains history data + assertTrue(json.contains("\"role\":\"user\"")); + assertTrue(json.contains("Test message")); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify history is preserved + assertNotNull(deserialized.getHistory()); + assertEquals(1, deserialized.getHistory().size()); + assertEquals(Message_v0_3.Role.USER, deserialized.getHistory().get(0).getRole()); + assertEquals(1, deserialized.getHistory().get(0).getParts().size()); + } + + @Test + void testTaskWithAllFields() throws JsonProcessingException_v0_3 { + OffsetDateTime timestamp = OffsetDateTime.now(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-789") + .status(new TaskStatus_v0_3(TaskState_v0_3.WORKING, null, timestamp)) + .history(List.of( + new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(List.of(new TextPart_v0_3("User message"))) + .build(), + new Message_v0_3.Builder() + .role(Message_v0_3.Role.AGENT) + .parts(List.of(new TextPart_v0_3("Agent response"))) + .build() + )) + .artifacts(List.of( + new Artifact_v0_3.Builder() + .artifactId("artifact-1") + .parts(List.of(new TextPart_v0_3("Artifact content"))) + .build() + )) + .metadata(Map.of("key1", "value1", "key2", 42)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify all fields are preserved + assertEquals(task.getId(), deserialized.getId()); + assertEquals(task.getContextId(), deserialized.getContextId()); + assertEquals(task.getStatus().state(), deserialized.getStatus().state()); + assertEquals(task.getStatus().timestamp(), deserialized.getStatus().timestamp()); + assertEquals(task.getHistory().size(), deserialized.getHistory().size()); + assertEquals(task.getArtifacts().size(), deserialized.getArtifacts().size()); + assertNotNull(deserialized.getMetadata()); + assertEquals("value1", deserialized.getMetadata().get("key1")); + } + + @Test + void testTaskWithDifferentStates() throws JsonProcessingException_v0_3 { + for (TaskState_v0_3 state : TaskState_v0_3.values()) { + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-" + state.asString()) + .contextId("context-123") + .status(new TaskStatus_v0_3(state)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Verify state is serialized correctly + assertTrue(json.contains("\"state\":\"" + state.asString() + "\"")); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify state is preserved + assertEquals(state, deserialized.getStatus().state()); + } + } + + @Test + void testTaskWithNullOptionalFields() throws JsonProcessingException_v0_3 { + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + // artifacts, history, metadata not set + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify required fields are present + assertEquals("task-123", deserialized.getId()); + assertEquals("context-456", deserialized.getContextId()); + assertEquals(TaskState_v0_3.SUBMITTED, deserialized.getStatus().state()); + + // Verify optional lists default to empty + assertNotNull(deserialized.getArtifacts()); + assertEquals(0, deserialized.getArtifacts().size()); + assertNotNull(deserialized.getHistory()); + assertEquals(0, deserialized.getHistory().size()); + } + + @Test + void testTaskWithFilePartBytes() throws JsonProcessingException_v0_3 { + FilePart_v0_3 filePart = new FilePart_v0_3(new FileWithBytes_v0_3("application/pdf", "document.pdf", "base64data")); + + Artifact_v0_3 artifact = new Artifact_v0_3.Builder() + .artifactId("file-artifact") + .parts(List.of(filePart)) + .build(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .artifacts(List.of(artifact)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Verify JSON contains file part data + assertTrue(json.contains("\"kind\":\"file\"")); + assertTrue(json.contains("document.pdf")); + assertTrue(json.contains("application/pdf")); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify file part is preserved + Part_v0_3 part = deserialized.getArtifacts().get(0).parts().get(0); + assertTrue(part instanceof FilePart_v0_3); + FilePart_v0_3 deserializedFilePart = (FilePart_v0_3) part; + assertTrue(deserializedFilePart.getFile() instanceof FileWithBytes_v0_3); + FileWithBytes_v0_3 fileWithBytes = (FileWithBytes_v0_3) deserializedFilePart.getFile(); + assertEquals("document.pdf", fileWithBytes.name()); + assertEquals("application/pdf", fileWithBytes.mimeType()); + } + + @Test + void testTaskWithFilePartUri() throws JsonProcessingException_v0_3 { + FilePart_v0_3 filePart = new FilePart_v0_3(new FileWithUri_v0_3("image/png", "photo.png", "https://example.com/photo.png")); + + Artifact_v0_3 artifact = new Artifact_v0_3.Builder() + .artifactId("uri-artifact") + .parts(List.of(filePart)) + .build(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .artifacts(List.of(artifact)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Verify JSON contains URI + assertTrue(json.contains("https://example.com/photo.png")); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify file part URI is preserved + Part_v0_3 part = deserialized.getArtifacts().get(0).parts().get(0); + assertTrue(part instanceof FilePart_v0_3); + FilePart_v0_3 deserializedFilePart = (FilePart_v0_3) part; + assertTrue(deserializedFilePart.getFile() instanceof FileWithUri_v0_3); + FileWithUri_v0_3 fileWithUri = (FileWithUri_v0_3) deserializedFilePart.getFile(); + assertEquals("https://example.com/photo.png", fileWithUri.uri()); + } + + @Test + void testTaskWithDataPart() throws JsonProcessingException_v0_3 { + DataPart_v0_3 dataPart = new DataPart_v0_3(Map.of("temperature", 22.5, "humidity", 65)); + + Artifact_v0_3 artifact = new Artifact_v0_3.Builder() + .artifactId("data-artifact") + .parts(List.of(dataPart)) + .build(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .artifacts(List.of(artifact)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Verify JSON contains data part + assertTrue(json.contains("\"kind\":\"data\"")); + assertTrue(json.contains("temperature")); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify data part is preserved + Part_v0_3 part = deserialized.getArtifacts().get(0).parts().get(0); + assertTrue(part instanceof DataPart_v0_3); + DataPart_v0_3 deserializedDataPart = (DataPart_v0_3) part; + assertNotNull(deserializedDataPart.getData()); + } + + @Test + void testTaskRoundTrip() throws JsonProcessingException_v0_3 { + // Create a comprehensive task with all part types + OffsetDateTime timestamp = OffsetDateTime.now(); + + Task_v0_3 original = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-789") + .status(new TaskStatus_v0_3(TaskState_v0_3.WORKING, null, timestamp)) + .history(List.of( + new Message_v0_3.Builder() + .role(Message_v0_3.Role.USER) + .parts(List.of( + new TextPart_v0_3("Text"), + new FilePart_v0_3(new FileWithBytes_v0_3("text/plain", "file.txt", "data")), + new DataPart_v0_3(Map.of("key", "value")) + )) + .build() + )) + .artifacts(List.of( + new Artifact_v0_3.Builder() + .artifactId("artifact-1") + .parts(List.of(new TextPart_v0_3("Content"))) + .build() + )) + .metadata(Map.of("meta1", "value1")) + .build(); + + // Serialize to JSON + String json = JsonUtil_v0_3.toJson(original); + + // Deserialize back to Task + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Serialize again + String json2 = JsonUtil_v0_3.toJson(deserialized); + + // Deserialize again + Task_v0_3 deserialized2 = JsonUtil_v0_3.fromJson(json2, Task_v0_3.class); + + // Verify multiple round-trips produce identical results + assertEquals(deserialized.getId(), deserialized2.getId()); + assertEquals(deserialized.getContextId(), deserialized2.getContextId()); + assertEquals(deserialized.getStatus().state(), deserialized2.getStatus().state()); + assertEquals(deserialized.getHistory().size(), deserialized2.getHistory().size()); + assertEquals(deserialized.getArtifacts().size(), deserialized2.getArtifacts().size()); + } + + @Test + void testTaskStatusWithMessage() throws JsonProcessingException_v0_3 { + Message_v0_3 statusMessage = new Message_v0_3.Builder() + .role(Message_v0_3.Role.AGENT) + .parts(List.of(new TextPart_v0_3("Processing complete"))) + .build(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED, statusMessage, null)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Verify JSON contains status message + assertTrue(json.contains("\"state\":\"completed\"")); + assertTrue(json.contains("Processing complete")); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify status message is preserved + assertEquals(TaskState_v0_3.COMPLETED, deserialized.getStatus().state()); + assertNotNull(deserialized.getStatus().message()); + assertEquals(Message_v0_3.Role.AGENT, deserialized.getStatus().message().getRole()); + assertTrue(deserialized.getStatus().message().getParts().get(0) instanceof TextPart_v0_3); + } + + @Test + void testDeserializeTaskFromJson() throws JsonProcessingException_v0_3 { + String json = """ + { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "submitted" + }, + "kind": "task" + } + """; + + Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + assertEquals("task-123", task.getId()); + assertEquals("context-456", task.getContextId()); + assertEquals(TaskState_v0_3.SUBMITTED, task.getStatus().state()); + assertNull(task.getStatus().message()); + // TaskStatus automatically sets timestamp to current time if not provided + assertNotNull(task.getStatus().timestamp()); + } + + @Test + void testDeserializeTaskWithArtifactsFromJson() throws JsonProcessingException_v0_3 { + String json = """ + { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "artifact-1", + "name": "Result", + "parts": [ + { + "kind": "text", + "text": "Hello World" + } + ] + } + ], + "kind": "task" + } + """; + + Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + assertEquals("task-123", task.getId()); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + assertEquals(1, task.getArtifacts().size()); + assertEquals("artifact-1", task.getArtifacts().get(0).artifactId()); + assertEquals("Result", task.getArtifacts().get(0).name()); + assertEquals(1, task.getArtifacts().get(0).parts().size()); + assertTrue(task.getArtifacts().get(0).parts().get(0) instanceof TextPart_v0_3); + assertEquals("Hello World", ((TextPart_v0_3) task.getArtifacts().get(0).parts().get(0)).getText()); + } + + @Test + void testDeserializeTaskWithFilePartBytesFromJson() throws JsonProcessingException_v0_3 { + String json = """ + { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "file-artifact", + "parts": [ + { + "kind": "file", + "file": { + "mimeType": "application/pdf", + "name": "document.pdf", + "bytes": "base64encodeddata" + } + } + ] + } + ], + "kind": "task" + } + """; + + Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + assertEquals("task-123", task.getId()); + assertEquals(1, task.getArtifacts().size()); + Part_v0_3 part = task.getArtifacts().get(0).parts().get(0); + assertTrue(part instanceof FilePart_v0_3); + FilePart_v0_3 filePart = (FilePart_v0_3) part; + assertTrue(filePart.getFile() instanceof FileWithBytes_v0_3); + FileWithBytes_v0_3 fileWithBytes = (FileWithBytes_v0_3) filePart.getFile(); + assertEquals("application/pdf", fileWithBytes.mimeType()); + assertEquals("document.pdf", fileWithBytes.name()); + assertEquals("base64encodeddata", fileWithBytes.bytes()); + } + + @Test + void testDeserializeTaskWithFilePartUriFromJson() throws JsonProcessingException_v0_3 { + String json = """ + { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "uri-artifact", + "parts": [ + { + "kind": "file", + "file": { + "mimeType": "image/png", + "name": "photo.png", + "uri": "https://example.com/photo.png" + } + } + ] + } + ], + "kind": "task" + } + """; + + Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + assertEquals("task-123", task.getId()); + Part_v0_3 part = task.getArtifacts().get(0).parts().get(0); + assertTrue(part instanceof FilePart_v0_3); + FilePart_v0_3 filePart = (FilePart_v0_3) part; + assertTrue(filePart.getFile() instanceof FileWithUri_v0_3); + FileWithUri_v0_3 fileWithUri = (FileWithUri_v0_3) filePart.getFile(); + assertEquals("image/png", fileWithUri.mimeType()); + assertEquals("photo.png", fileWithUri.name()); + assertEquals("https://example.com/photo.png", fileWithUri.uri()); + } + + @Test + void testDeserializeTaskWithDataPartFromJson() throws JsonProcessingException_v0_3 { + String json = """ + { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "data-artifact", + "parts": [ + { + "kind": "data", + "data": { + "temperature": 22.5, + "humidity": 65 + } + } + ] + } + ], + "kind": "task" + } + """; + + Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + assertEquals("task-123", task.getId()); + Part_v0_3 part = task.getArtifacts().get(0).parts().get(0); + assertTrue(part instanceof DataPart_v0_3); + DataPart_v0_3 dataPart = (DataPart_v0_3) part; + assertNotNull(dataPart.getData()); + } + + @Test + void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException_v0_3 { + String json = """ + { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "working" + }, + "history": [ + { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "User message" + } + ] + }, + { + "role": "agent", + "parts": [ + { + "kind": "text", + "text": "Agent response" + } + ] + } + ], + "kind": "task" + } + """; + + Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + assertEquals("task-123", task.getId()); + assertEquals(2, task.getHistory().size()); + assertEquals(Message_v0_3.Role.USER, task.getHistory().get(0).getRole()); + assertEquals(Message_v0_3.Role.AGENT, task.getHistory().get(1).getRole()); + assertTrue(task.getHistory().get(0).getParts().get(0) instanceof TextPart_v0_3); + assertEquals("User message", ((TextPart_v0_3) task.getHistory().get(0).getParts().get(0)).getText()); + } + + @Test + void testDeserializeTaskWithTimestampFromJson() throws JsonProcessingException_v0_3 { + String json = """ + { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "working", + "timestamp": "2023-10-01T12:00:00.234-05:00" + }, + "kind": "task" + } + """; + + Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + assertEquals("task-123", task.getId()); + assertEquals(TaskState_v0_3.WORKING, task.getStatus().state()); + assertNotNull(task.getStatus().timestamp()); + assertEquals("2023-10-01T12:00:00.234-05:00", task.getStatus().timestamp().toString()); + } + + @Test + void testDeserializeTaskWithMetadataFromJson() throws JsonProcessingException_v0_3 { + String json = """ + { + "id": "task-123", + "contextId": "context-456", + "status": { + "state": "completed" + }, + "metadata": { + "key1": "value1", + "key2": 42 + }, + "kind": "task" + } + """; + + Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + assertEquals("task-123", task.getId()); + assertNotNull(task.getMetadata()); + assertEquals("value1", task.getMetadata().get("key1")); + } + + @Test + void testTaskWithMixedPartTypes() throws JsonProcessingException_v0_3 { + Artifact_v0_3 artifact = new Artifact_v0_3.Builder() + .artifactId("mixed-artifact") + .parts(List.of( + new TextPart_v0_3("Text content"), + new FilePart_v0_3(new FileWithBytes_v0_3("application/json", "data.json", "{}")), + new DataPart_v0_3(Map.of("result", 42)), + new FilePart_v0_3(new FileWithUri_v0_3("image/png", "image.png", "https://example.com/img.png")) + )) + .build(); + + Task_v0_3 task = new Task_v0_3.Builder() + .id("task-123") + .contextId("context-456") + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .artifacts(List.of(artifact)) + .build(); + + // Serialize + String json = JsonUtil_v0_3.toJson(task); + + // Deserialize + Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); + + // Verify all part types are preserved + List> parts = deserialized.getArtifacts().get(0).parts(); + assertEquals(4, parts.size()); + assertTrue(parts.get(0) instanceof TextPart_v0_3); + assertTrue(parts.get(1) instanceof FilePart_v0_3); + assertTrue(parts.get(2) instanceof DataPart_v0_3); + assertTrue(parts.get(3) instanceof FilePart_v0_3); + } +} diff --git a/compat-0.3/tck/pom.xml b/compat-0.3/tck/pom.xml new file mode 100644 index 000000000..b0cb5c5c8 --- /dev/null +++ b/compat-0.3/tck/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + .. + + + a2a-compat-0.3-tck-server + + Java SDK A2A Compat 0.3 TCK Server + Server example to use with the A2A TCK + + + + ${project.groupId} + a2a-java-sdk-server-common + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-jsonrpc + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-grpc + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-rest + + + io.quarkus + quarkus-rest-jackson + provided + + + jakarta.enterprise + jakarta.enterprise.cdi-api + provided + + + jakarta.ws.rs + jakarta.ws.rs-api + + + + + + + io.quarkus + quarkus-maven-plugin + true + + + + build + generate-code + generate-code-tests + + + + + + + diff --git a/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/AgentCardProducer_v0_3.java b/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/AgentCardProducer_v0_3.java new file mode 100644 index 000000000..14b1f1528 --- /dev/null +++ b/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/AgentCardProducer_v0_3.java @@ -0,0 +1,61 @@ +package org.a2aproject.sdk.compat03.tck.server; + +import java.util.Collections; +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentInterface_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; + +@ApplicationScoped +public class AgentCardProducer_v0_3 { + + private static final String DEFAULT_SUT_URL = "http://localhost:9999"; + + @Produces + @PublicAgentCard + public AgentCard_v0_3 agentCard() { + + String sutJsonRpcUrl = getEnvOrDefault("SUT_JSONRPC_URL", DEFAULT_SUT_URL); + String sutGrpcUrl = getEnvOrDefault("SUT_GRPC_URL", DEFAULT_SUT_URL); + String sutRestcUrl = getEnvOrDefault("SUT_REST_URL", DEFAULT_SUT_URL); + return new AgentCard_v0_3.Builder() + .name("Hello World Agent") + .description("Just a hello world agent") + .url(sutJsonRpcUrl) + .version("1.0.0") + .documentationUrl("http://example.com/docs") + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(true) + .pushNotifications(true) + .stateTransitionHistory(true) + .build()) + .defaultInputModes(Collections.singletonList("text")) + .defaultOutputModes(Collections.singletonList("text")) + .skills(Collections.singletonList(new AgentSkill_v0_3.Builder() + .id("hello_world") + .name("Returns hello world") + .description("just returns hello world") + .tags(Collections.singletonList("hello world")) + .examples(List.of("hi", "hello world")) + .build())) + .protocolVersion("0.3.0") + .additionalInterfaces(List.of( + new AgentInterface_v0_3(TransportProtocol_v0_3.JSONRPC.asString(), sutJsonRpcUrl), + new AgentInterface_v0_3(TransportProtocol_v0_3.GRPC.asString(), sutGrpcUrl), + new AgentInterface_v0_3(TransportProtocol_v0_3.HTTP_JSON.asString(), sutRestcUrl))) + .build(); + } + + private static String getEnvOrDefault(String envVar, String defaultValue) { + String value = System.getenv(envVar); + return value == null || value.isBlank() ? defaultValue : value; + } +} + diff --git a/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/AgentExecutorProducer_v0_3.java b/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/AgentExecutorProducer_v0_3.java new file mode 100644 index 000000000..9f89162c7 --- /dev/null +++ b/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/AgentExecutorProducer_v0_3.java @@ -0,0 +1,84 @@ +package org.a2aproject.sdk.compat03.tck.server; + +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.util.Assert; + +@ApplicationScoped +public class AgentExecutorProducer_v0_3 { + + @Produces + public AgentExecutor agentExecutor() { + return new FireAndForgetAgentExecutor(); + } + + private static class FireAndForgetAgentExecutor implements AgentExecutor { + @Override + public void execute(RequestContext context, AgentEmitter emitter) throws A2AError { + Task task = context.getTask(); + + if (task == null) { + // The 0.3 TCK requires the initial message to be part of the Task history + // However, the 1.0 spec says it is up to the agent what is saved + emitter.submit(context.getMessage()); + } + + // Sleep to allow task state persistence before TCK resubscribe test + Message message = context.getMessage(); + if (message != null && message.messageId() != null && message.messageId().startsWith("test-resubscribe-message-id")) { + int timeoutMs = Integer.parseInt(System.getenv().getOrDefault("RESUBSCRIBE_TIMEOUT_MS", "3000")); + System.out.println("====> task id starts with test-resubscribe-message-id, sleeping for " + timeoutMs + " ms"); + try { + Thread.sleep(timeoutMs); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + // Immediately set to WORKING state + emitter.startWork(); + System.out.println("====> task set to WORKING, starting background execution"); + + // Method returns immediately - task continues in background + System.out.println("====> execute() method returning immediately, task running in background"); + } + + @Override + public void cancel(RequestContext context, AgentEmitter emitter) throws A2AError { + System.out.println("====> task cancel request received"); + Task task = Assert.checkNotNullParam("task", context.getTask()); + + if (task.status().state() == TaskState.TASK_STATE_CANCELED) { + System.out.println("====> task already canceled"); + throw new TaskNotCancelableError(); + } + + if (task.status().state() == TaskState.TASK_STATE_COMPLETED) { + System.out.println("====> task already completed"); + throw new TaskNotCancelableError(); + } + + emitter.cancel(); + + System.out.println("====> task canceled"); + } + + /** + * Cleanup method for proper resource management + */ + @PreDestroy + public void cleanup() { + System.out.println("====> shutting down task executor"); + } + } +} \ No newline at end of file diff --git a/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/package-info.java b/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/package-info.java new file mode 100644 index 000000000..4539f9136 --- /dev/null +++ b/compat-0.3/tck/src/main/java/org/a2aproject/sdk/compat03/tck/server/package-info.java @@ -0,0 +1,10 @@ +@NullMarked +package org.a2aproject.sdk.compat03.tck.server; + +import org.jspecify.annotations.NullMarked; + +//The following had @Nullable annotation applied from JSpecify +//AgentCardProducer.java getEnvOrDefault method, +//AgentExecutorProducer.java execute method +// + diff --git a/compat-0.3/tck/src/main/resources/application.properties b/compat-0.3/tck/src/main/resources/application.properties new file mode 100644 index 000000000..c68793be4 --- /dev/null +++ b/compat-0.3/tck/src/main/resources/application.properties @@ -0,0 +1,20 @@ +# Use the new gRPC implementation which uses the main HTTP port +quarkus.grpc.server.use-separate-server=false +%dev.quarkus.http.port=9999 + +# Thread pool configuration for TCK testing +# Limit max threads to prevent resource exhaustion in CI environments +a2a.executor.core-pool-size=5 +a2a.executor.max-pool-size=15 +a2a.executor.keep-alive-seconds=60 + +# Enable debug logging for troubleshooting TCK failures +quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG +quarkus.log.category."io.a2a.server.events".level=DEBUG +quarkus.log.category."io.a2a.server.tasks".level=DEBUG + +# Log to file for analysis +quarkus.log.file.enable=true +quarkus.log.file.path=target/tck-test.log +quarkus.log.file.level=DEBUG +quarkus.log.console.level=INFO diff --git a/compat-0.3/transport/grpc/pom.xml b/compat-0.3/transport/grpc/pom.xml new file mode 100644 index 000000000..7ad780db3 --- /dev/null +++ b/compat-0.3/transport/grpc/pom.xml @@ -0,0 +1,93 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../.. + + a2a-java-sdk-compat-0.3-transport-grpc + + jar + + Java SDK A2A Compat 0.3 Transport: gRPC + Java SDK for the Agent2Agent Protocol (A2A) - gRPC + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-server-common + + + ${project.groupId} + a2a-java-sdk-server-common + test-jar + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec-grpc + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + ${project.version} + test-jar + test + + + com.google.protobuf + protobuf-java + + + io.grpc + grpc-protobuf + + + io.grpc + grpc-stub + + + jakarta.enterprise + jakarta.enterprise.cdi-api + + + jakarta.inject + jakarta.inject-api + + + ch.qos.logback + logback-classic + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.mockito + mockito-core + test + + + io.grpc + grpc-testing + test + + + + + diff --git a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/context/GrpcContextKeys_v0_3.java b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/context/GrpcContextKeys_v0_3.java new file mode 100644 index 000000000..178725bc3 --- /dev/null +++ b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/context/GrpcContextKeys_v0_3.java @@ -0,0 +1,45 @@ +package org.a2aproject.sdk.compat03.transport.grpc.context; + +import io.grpc.Context; + +/** + * Shared gRPC context keys for A2A protocol data. + * + * These keys provide access to gRPC context information similar to + * Python's grpc.aio.ServicerContext, enabling rich context access + * in service method implementations. + */ +public final class GrpcContextKeys_v0_3 { + + /** + * Context key for storing the X-A2A-Extensions header value. + * Set by server interceptors and accessed by service handlers. + */ + public static final Context.Key EXTENSIONS_HEADER_KEY = + Context.key("x-a2a-extensions"); + + /** + * Context key for storing the complete gRPC Metadata object. + * Provides access to all request headers and metadata. + */ + public static final Context.Key METADATA_KEY = + Context.key("grpc-metadata"); + + /** + * Context key for storing the method name being called. + * Equivalent to Python's context.method() functionality. + */ + public static final Context.Key METHOD_NAME_KEY = + Context.key("grpc-method-name"); + + /** + * Context key for storing the peer information. + * Provides access to client connection details. + */ + public static final Context.Key PEER_INFO_KEY = + Context.key("grpc-peer-info"); + + private GrpcContextKeys_v0_3() { + // Utility class + } +} diff --git a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/CallContextFactory_v0_3.java b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/CallContextFactory_v0_3.java new file mode 100644 index 000000000..c5dc184cc --- /dev/null +++ b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/CallContextFactory_v0_3.java @@ -0,0 +1,12 @@ +package org.a2aproject.sdk.compat03.transport.grpc.handler; + +import org.a2aproject.sdk.server.ServerCallContext; +import io.grpc.stub.StreamObserver; + +/** + * Factory interface for creating ServerCallContext from gRPC StreamObserver. + * Implementations can provide custom context creation logic. + */ +public interface CallContextFactory_v0_3 { + ServerCallContext create(StreamObserver responseObserver); +} diff --git a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java new file mode 100644 index 000000000..369835f55 --- /dev/null +++ b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java @@ -0,0 +1,403 @@ +package org.a2aproject.sdk.compat03.transport.grpc.handler; + +import static org.a2aproject.sdk.compat03.grpc.utils.ProtoUtils_v0_3.FromProto; +import static org.a2aproject.sdk.compat03.grpc.utils.ProtoUtils_v0_3.ToProto; + +import jakarta.enterprise.inject.Vetoed; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Flow; + +import com.google.protobuf.Empty; +import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; +import org.a2aproject.sdk.compat03.conversion.ErrorConverter_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.spec.A2AError; +import io.grpc.Status; +import io.grpc.stub.StreamObserver; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Abstract gRPC handler for v0.3 protocol with translation layer to v1.0. + */ +@Vetoed +public abstract class GrpcHandler_v0_3 extends org.a2aproject.sdk.compat03.grpc.A2AServiceGrpc.A2AServiceImplBase { + + private Convert_v0_3_To10RequestHandler requestHandler; + + // Hook so testing can wait until streaming is subscribed. + // Without this we get intermittent failures + private static volatile Runnable streamingSubscribedRunnable; + + protected abstract AgentCard_v0_3 getAgentCard(); + + protected abstract CallContextFactory_v0_3 getCallContextFactory(); + + protected abstract Executor getExecutor(); + + protected Convert_v0_3_To10RequestHandler getRequestHandler() { + return requestHandler; + } + + protected void setRequestHandler(Convert_v0_3_To10RequestHandler requestHandler) { + this.requestHandler = requestHandler; + } + + @Override + public void sendMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request, + StreamObserver responseObserver) { + try { + ServerCallContext context = createCallContext(responseObserver); + MessageSendParams_v0_3 params = FromProto.messageSendParams(request); + EventKind_v0_3 taskOrMessage = requestHandler.onMessageSend(params, context); + org.a2aproject.sdk.compat03.grpc.SendMessageResponse response = ToProto.taskOrMessage(taskOrMessage); + responseObserver.onNext(response); + responseObserver.onCompleted(); + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + @Override + public void getTask(org.a2aproject.sdk.compat03.grpc.GetTaskRequest request, + StreamObserver responseObserver) { + try { + ServerCallContext context = createCallContext(responseObserver); + TaskQueryParams_v0_3 params = FromProto.taskQueryParams(request); + Task_v0_3 task = requestHandler.onGetTask(params, context); + if (task != null) { + responseObserver.onNext(ToProto.task(task)); + responseObserver.onCompleted(); + } else { + handleError(responseObserver, new TaskNotFoundError_v0_3()); + } + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + @Override + public void cancelTask(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest request, + StreamObserver responseObserver) { + try { + ServerCallContext context = createCallContext(responseObserver); + TaskIdParams_v0_3 params = FromProto.taskIdParams(request); + Task_v0_3 task = requestHandler.onCancelTask(params, context); + if (task != null) { + responseObserver.onNext(ToProto.task(task)); + responseObserver.onCompleted(); + } else { + handleError(responseObserver, new TaskNotFoundError_v0_3()); + } + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + @Override + public void createTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest request, + StreamObserver responseObserver) { + if (!getAgentCard().capabilities().pushNotifications()) { + handleError(responseObserver, new PushNotificationNotSupportedError_v0_3()); + return; + } + + try { + ServerCallContext context = createCallContext(responseObserver); + TaskPushNotificationConfig_v0_3 config = FromProto.taskPushNotificationConfig(request); + TaskPushNotificationConfig_v0_3 responseConfig = requestHandler.onSetTaskPushNotificationConfig(config, context); + responseObserver.onNext(ToProto.taskPushNotificationConfig(responseConfig)); + responseObserver.onCompleted(); + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + @Override + public void getTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest request, + StreamObserver responseObserver) { + if (!getAgentCard().capabilities().pushNotifications()) { + handleError(responseObserver, new PushNotificationNotSupportedError_v0_3()); + return; + } + + try { + ServerCallContext context = createCallContext(responseObserver); + GetTaskPushNotificationConfigParams_v0_3 params = FromProto.getTaskPushNotificationConfigParams(request); + TaskPushNotificationConfig_v0_3 config = requestHandler.onGetTaskPushNotificationConfig(params, context); + responseObserver.onNext(ToProto.taskPushNotificationConfig(config)); + responseObserver.onCompleted(); + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + @Override + public void listTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest request, + StreamObserver responseObserver) { + if (!getAgentCard().capabilities().pushNotifications()) { + handleError(responseObserver, new PushNotificationNotSupportedError_v0_3()); + return; + } + + try { + ServerCallContext context = createCallContext(responseObserver); + ListTaskPushNotificationConfigParams_v0_3 params = FromProto.listTaskPushNotificationConfigParams(request); + List configList = requestHandler.onListTaskPushNotificationConfig(params, context); + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.Builder responseBuilder = + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.newBuilder(); + for (TaskPushNotificationConfig_v0_3 config : configList) { + responseBuilder.addConfigs(ToProto.taskPushNotificationConfig(config)); + } + responseObserver.onNext(responseBuilder.build()); + responseObserver.onCompleted(); + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + @Override + public void sendStreamingMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest request, + StreamObserver responseObserver) { + if (!getAgentCard().capabilities().streaming()) { + handleError(responseObserver, new InvalidRequestError_v0_3("Streaming is not supported by the agent")); + return; + } + + try { + ServerCallContext context = createCallContext(responseObserver); + MessageSendParams_v0_3 params = FromProto.messageSendParams(request); + Flow.Publisher publisher = requestHandler.onMessageSendStream(params, context); + convertToStreamResponse(publisher, responseObserver); + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + @Override + public void taskSubscription(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest request, + StreamObserver responseObserver) { + if (!getAgentCard().capabilities().streaming()) { + handleError(responseObserver, new InvalidRequestError_v0_3("Streaming is not supported by the agent")); + return; + } + + try { + ServerCallContext context = createCallContext(responseObserver); + TaskIdParams_v0_3 params = FromProto.taskIdParams(request); + Flow.Publisher publisher = requestHandler.onResubscribeToTask(params, context); + convertToStreamResponse(publisher, responseObserver); + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + private void convertToStreamResponse(Flow.Publisher publisher, + StreamObserver responseObserver) { + CompletableFuture.runAsync(() -> { + publisher.subscribe(new Flow.Subscriber() { + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + if (streamingSubscribedRunnable != null) { + streamingSubscribedRunnable.run(); + } + subscription.request(1); + } + + @Override + public void onNext(StreamingEventKind_v0_3 event) { + org.a2aproject.sdk.compat03.grpc.StreamResponse response = ToProto.streamResponse(event); + responseObserver.onNext(response); + if (response.hasStatusUpdate() && response.getStatusUpdate().getFinal()) { + responseObserver.onCompleted(); + } else { + subscription.request(1); + } + } + + @Override + public void onError(Throwable throwable) { + if (throwable instanceof A2AError a2aError) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(a2aError)); + } else if (throwable instanceof JSONRPCError_v0_3 jsonrpcError) { + handleError(responseObserver, jsonrpcError); + } else { + handleInternalError(responseObserver, throwable); + } + responseObserver.onCompleted(); + } + + @Override + public void onComplete() { + responseObserver.onCompleted(); + } + }); + }, getExecutor()); + } + + @Override + public void getAgentCard(org.a2aproject.sdk.compat03.grpc.GetAgentCardRequest request, + StreamObserver responseObserver) { + try { + responseObserver.onNext(ToProto.agentCard(getAgentCard())); + responseObserver.onCompleted(); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + @Override + public void deleteTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest request, + StreamObserver responseObserver) { + if (!getAgentCard().capabilities().pushNotifications()) { + handleError(responseObserver, new PushNotificationNotSupportedError_v0_3()); + return; + } + + try { + ServerCallContext context = createCallContext(responseObserver); + DeleteTaskPushNotificationConfigParams_v0_3 params = FromProto.deleteTaskPushNotificationConfigParams(request); + requestHandler.onDeleteTaskPushNotificationConfig(params, context); + // void response + responseObserver.onNext(Empty.getDefaultInstance()); + responseObserver.onCompleted(); + } catch (A2AError e) { + handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + handleError(responseObserver, e); + } catch (Throwable t) { + handleInternalError(responseObserver, t); + } + } + + private ServerCallContext createCallContext(StreamObserver responseObserver) { + CallContextFactory_v0_3 factory = getCallContextFactory(); + if (factory == null) { + // Default implementation when no custom CallContextFactory is provided + User user = UnauthenticatedUser.INSTANCE; + Map state = new HashMap<>(); + state.put("grpc_response_observer", responseObserver); + Set requestedExtensions = new HashSet<>(); + return new ServerCallContext(user, state, requestedExtensions); + } else { + return factory.create(responseObserver); + } + } + + private void handleError(StreamObserver responseObserver, JSONRPCError_v0_3 error) { + Status status; + String description; + if (error instanceof InvalidRequestError_v0_3) { + status = Status.INVALID_ARGUMENT; + description = "InvalidRequestError: " + error.getMessage(); + } else if (error instanceof MethodNotFoundError_v0_3) { + status = Status.NOT_FOUND; + description = "MethodNotFoundError: " + error.getMessage(); + } else if (error instanceof InvalidParamsError_v0_3) { + status = Status.INVALID_ARGUMENT; + description = "InvalidParamsError: " + error.getMessage(); + } else if (error instanceof InternalError_v0_3) { + status = Status.INTERNAL; + description = "InternalError: " + error.getMessage(); + } else if (error instanceof TaskNotFoundError_v0_3) { + status = Status.NOT_FOUND; + description = "TaskNotFoundError: " + error.getMessage(); + } else if (error instanceof TaskNotCancelableError_v0_3) { + status = Status.UNIMPLEMENTED; + description = "TaskNotCancelableError: " + error.getMessage(); + } else if (error instanceof PushNotificationNotSupportedError_v0_3) { + status = Status.UNIMPLEMENTED; + description = "PushNotificationNotSupportedError: " + error.getMessage(); + } else if (error instanceof UnsupportedOperationError_v0_3) { + status = Status.UNIMPLEMENTED; + description = "UnsupportedOperationError: " + error.getMessage(); + } else if (error instanceof JSONParseError_v0_3) { + status = Status.INTERNAL; + description = "JSONParseError: " + error.getMessage(); + } else if (error instanceof ContentTypeNotSupportedError_v0_3) { + status = Status.UNIMPLEMENTED; + description = "ContentTypeNotSupportedError: " + error.getMessage(); + } else if (error instanceof InvalidAgentResponseError_v0_3) { + status = Status.INTERNAL; + description = "InvalidAgentResponseError: " + error.getMessage(); + } else { + status = Status.UNKNOWN; + description = "Unknown error type: " + error.getMessage(); + } + responseObserver.onError(status.withDescription(description).asRuntimeException()); + } + + private void handleInternalError(StreamObserver responseObserver, Throwable t) { + handleError(responseObserver, new InternalError_v0_3(t.getMessage())); + } + + public static void setStreamingSubscribedRunnable(Runnable runnable) { + streamingSubscribedRunnable = runnable; + } +} diff --git a/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java b/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java new file mode 100644 index 000000000..5a422c3bd --- /dev/null +++ b/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java @@ -0,0 +1,555 @@ +package org.a2aproject.sdk.compat03.transport.grpc.handler; + +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.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.a2aproject.sdk.compat03.conversion.AbstractA2ARequestHandlerTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +// gRPC test imports +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import io.grpc.testing.StreamRecorder; + +// v0.3 gRPC proto imports +import org.a2aproject.sdk.compat03.grpc.CancelTaskRequest; +import org.a2aproject.sdk.compat03.grpc.GetTaskRequest; +import org.a2aproject.sdk.compat03.grpc.Message; +import org.a2aproject.sdk.compat03.grpc.Part; +import org.a2aproject.sdk.compat03.grpc.Role; +import org.a2aproject.sdk.compat03.grpc.SendMessageRequest; +import org.a2aproject.sdk.compat03.grpc.SendMessageResponse; +import org.a2aproject.sdk.compat03.grpc.StreamResponse; +import org.a2aproject.sdk.compat03.grpc.Task; +import org.a2aproject.sdk.compat03.grpc.TaskState; +import org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRequest; + +/** + * Test suite for v0.3 GrpcHandler with v1.0 backend. + *

            + * Tests verify that v0.3 gRPC clients can successfully communicate with the v1.0 backend + * via the {@link Convert_v0_3_To10RequestHandler} conversion layer. + *

            + *

            + * Phase 3 Focus: Core non-streaming tests (GetTask, SendMessage, CancelTask). + * Streaming tests are deferred to Phase 4. + *

            + */ +public class GrpcHandler_v0_3_Test extends AbstractA2ARequestHandlerTest_v0_3 { + + // gRPC Message fixture (protobuf format) + private static final Message GRPC_MESSAGE = Message.newBuilder() + .setTaskId(MINIMAL_TASK.getId()) + .setContextId(MINIMAL_TASK.getContextId()) + .setMessageId(MESSAGE.getMessageId()) + .setRole(Role.ROLE_AGENT) + .addContent(Part.newBuilder().setText(((TextPart_v0_3) MESSAGE.getParts().get(0)).getText()).build()) + .build(); + + private final ServerCallContext callContext = new ServerCallContext( + UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + + // ======================================== + // GetTask Tests + // ======================================== + + @Test + public void testOnGetTaskSuccess() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save v0.3 task by converting to v1.0 + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + GetTaskRequest request = GetTaskRequest.newBuilder() + .setName("tasks/" + MINIMAL_TASK.getId()) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.getTask(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + + Assertions.assertNull(streamRecorder.getError()); + List result = streamRecorder.getValues(); + Assertions.assertEquals(1, result.size()); + Task task = result.get(0); + assertEquals(MINIMAL_TASK.getId(), task.getId()); + assertEquals(MINIMAL_TASK.getContextId(), task.getContextId()); + } + + @Test + public void testOnGetTaskNotFound() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + GetTaskRequest request = GetTaskRequest.newBuilder() + .setName("tasks/" + MINIMAL_TASK.getId()) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.getTask(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + + assertGrpcError(streamRecorder, Status.Code.NOT_FOUND); + } + + // ======================================== + // CancelTask Tests + // ======================================== + + @Test + public void testOnCancelTaskSuccess() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save v0.3 task by converting to v1.0 + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to cancel the task + agentExecutorCancel = (context, emitter) -> { + emitter.cancel(); + }; + + CancelTaskRequest request = CancelTaskRequest.newBuilder() + .setName("tasks/" + MINIMAL_TASK.getId()) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.cancelTask(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + + Assertions.assertNull(streamRecorder.getError()); + List result = streamRecorder.getValues(); + Assertions.assertEquals(1, result.size()); + Task task = result.get(0); + assertEquals(MINIMAL_TASK.getId(), task.getId()); + assertEquals(MINIMAL_TASK.getContextId(), task.getContextId()); + assertEquals(TaskState.TASK_STATE_CANCELLED, task.getStatus().getState()); + } + + @Test + public void testOnCancelTaskNotSupported() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save v0.3 task by converting to v1.0 + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to throw UnsupportedOperationError + agentExecutorCancel = (context, emitter) -> { + throw new org.a2aproject.sdk.spec.UnsupportedOperationError(); + }; + + CancelTaskRequest request = CancelTaskRequest.newBuilder() + .setName("tasks/" + MINIMAL_TASK.getId()) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.cancelTask(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + + assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); + } + + @Test + public void testOnCancelTaskNotFound() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + CancelTaskRequest request = CancelTaskRequest.newBuilder() + .setName("tasks/" + MINIMAL_TASK.getId()) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.cancelTask(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + + assertGrpcError(streamRecorder, Status.Code.NOT_FOUND); + } + + // ======================================== + // SendMessage Tests (Non-Streaming) + // ======================================== + + @Test + public void testOnMessageNewMessageSuccess() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to echo the message back + agentExecutorExecute = (context, emitter) -> { + emitter.emitEvent(context.getMessage()); + }; + + StreamRecorder streamRecorder = sendMessageRequest(handler); + + Assertions.assertNull(streamRecorder.getError()); + List result = streamRecorder.getValues(); + Assertions.assertEquals(1, result.size()); + SendMessageResponse response = result.get(0); + Assertions.assertTrue(response.hasMsg()); + Message message = response.getMsg(); + assertEquals(GRPC_MESSAGE.getMessageId(), message.getMessageId()); + } + + @Test + public void testOnMessageNewMessageWithExistingTaskSuccess() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to emit message + agentExecutorExecute = (context, emitter) -> { + emitter.emitEvent(context.getMessage()); + }; + + StreamRecorder streamRecorder = sendMessageRequest(handler); + + Assertions.assertNull(streamRecorder.getError()); + List result = streamRecorder.getValues(); + Assertions.assertEquals(1, result.size()); + SendMessageResponse response = result.get(0); + Assertions.assertTrue(response.hasMsg()); + Message message = response.getMsg(); + assertEquals(GRPC_MESSAGE.getMessageId(), message.getMessageId()); + } + + @Test + public void testOnMessageError() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to throw error + agentExecutorExecute = (context, emitter) -> { + emitter.emitEvent(new org.a2aproject.sdk.spec.UnsupportedOperationError()); + }; + + StreamRecorder streamRecorder = sendMessageRequest(handler); + + assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); + } + + // ======================================== + // Streaming Tests + // ======================================== + + @Test + public void testOnMessageStreamNewMessageSuccess() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to emit the message back (v1.0 context contains v1.0 Message) + agentExecutorExecute = (context, emitter) -> { + emitter.emitEvent(context.getMessage()); + }; + + StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); + + assertNull(streamRecorder.getError(), "No error should occur"); + List result = streamRecorder.getValues(); + assertNotNull(result, "Result should not be null"); + assertEquals(1, result.size(), "Should receive exactly 1 event"); + + StreamResponse response = result.get(0); + assertTrue(response.hasMsg(), "Response should contain a message"); + Message message = response.getMsg(); + assertEquals(GRPC_MESSAGE.getMessageId(), message.getMessageId()); + } + + @Test + public void testStreamingNotSupportedError() throws Exception { + // Create agent card with streaming disabled + AgentCard_v0_3 nonStreamingCard = + new AgentCard_v0_3.Builder(CARD) + .capabilities(new AgentCapabilities_v0_3(false, true, false, null)) + .build(); + + TestGrpcHandler handler = new TestGrpcHandler(nonStreamingCard, convert03To10Handler, internalExecutor); + + StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); + + // Should receive INVALID_ARGUMENT status + assertGrpcError(streamRecorder, Status.Code.INVALID_ARGUMENT); + } + + @Test + public void testStreamingNotSupportedErrorOnResubscribeToTask() throws Exception { + // Create agent card with streaming disabled + AgentCard_v0_3 nonStreamingCard = + new AgentCard_v0_3.Builder(CARD) + .capabilities(new AgentCapabilities_v0_3(false, true, false, null)) + .build(); + + TestGrpcHandler handler = new TestGrpcHandler(nonStreamingCard, convert03To10Handler, internalExecutor); + + TaskSubscriptionRequest request = TaskSubscriptionRequest.newBuilder() + .setName("tasks/" + MINIMAL_TASK.getId()) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.taskSubscription(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + + // Should receive INVALID_ARGUMENT status + assertGrpcError(streamRecorder, Status.Code.INVALID_ARGUMENT); + } + + @Test + public void testOnMessageStreamInternalError() throws Exception { + // Mock the Convert03To10RequestHandler to throw InternalError + Convert_v0_3_To10RequestHandler mockedHandler = Mockito.mock(Convert_v0_3_To10RequestHandler.class); + Mockito.doThrow(new org.a2aproject.sdk.spec.InternalError("Internal Error")) + .when(mockedHandler) + .onMessageSendStream( + Mockito.any(MessageSendParams_v0_3.class), + Mockito.any(ServerCallContext.class)); + + TestGrpcHandler handler = new TestGrpcHandler(CARD, mockedHandler, internalExecutor); + + StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); + + // Should receive INTERNAL status + assertGrpcError(streamRecorder, Status.Code.INTERNAL); + } + + // ======================================== + // Push Notification Tests + // ======================================== + + @Test + public void testSetPushNotificationConfigSuccess() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + String NAME = "tasks/" + MINIMAL_TASK.getId() + "/pushNotificationConfigs/config456"; + StreamRecorder streamRecorder = + createTaskPushNotificationConfigRequest(handler, NAME); + + assertNull(streamRecorder.getError()); + List result = streamRecorder.getValues(); + assertNotNull(result); + assertEquals(1, result.size()); + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig response = result.get(0); + assertEquals(NAME, response.getName()); + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig responseConfig = response.getPushNotificationConfig(); + assertEquals("config456", responseConfig.getId()); + assertEquals("http://example.com", responseConfig.getUrl()); + } + + @Test + public void testGetPushNotificationConfigSuccess() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + }; + + String NAME = "tasks/" + MINIMAL_TASK.getId() + "/pushNotificationConfigs/config456"; + + // First set the task push notification config + StreamRecorder streamRecorder = + createTaskPushNotificationConfigRequest(handler, NAME); + assertNull(streamRecorder.getError()); + + // Then get the task push notification config + streamRecorder = getTaskPushNotificationConfigRequest(handler, NAME); + assertNull(streamRecorder.getError()); + List result = streamRecorder.getValues(); + assertNotNull(result); + assertEquals(1, result.size()); + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig response = result.get(0); + assertEquals(NAME, response.getName()); + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig responseConfig = response.getPushNotificationConfig(); + assertEquals("config456", responseConfig.getId()); + assertEquals("http://example.com", responseConfig.getUrl()); + } + + @Test + public void testPushNotificationsNotSupportedError() throws Exception { + AgentCard_v0_3 card = createAgentCard(true, false, false); + TestGrpcHandler handler = new TestGrpcHandler(card, convert03To10Handler, internalExecutor); + + String NAME = "tasks/" + MINIMAL_TASK.getId() + "/pushNotificationConfigs/" + MINIMAL_TASK.getId(); + StreamRecorder streamRecorder = + createTaskPushNotificationConfigRequest(handler, NAME); + + assertNotNull(streamRecorder.getError()); + assertInstanceOf(StatusRuntimeException.class, streamRecorder.getError()); + StatusRuntimeException error = (StatusRuntimeException) streamRecorder.getError(); + assertEquals(Status.Code.UNIMPLEMENTED, error.getStatus().getCode()); + } + + @Test + public void testDeletePushNotificationConfig() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save task to v1.0 backend + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + String NAME = "tasks/" + MINIMAL_TASK.getId() + "/pushNotificationConfigs/" + MINIMAL_TASK.getId(); + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest request = + org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder() + .setName(NAME) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.deleteTaskPushNotificationConfig(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + + assertNull(streamRecorder.getError()); + List result = streamRecorder.getValues(); + assertEquals(1, result.size()); + } + + @Test + public void testListPushNotificationConfig() throws Exception { + TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); + + // Save task to v1.0 backend + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + String PARENT = "tasks/" + MINIMAL_TASK.getId(); + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest request = + org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.newBuilder() + .setParent(PARENT) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.listTaskPushNotificationConfig(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + + assertNull(streamRecorder.getError()); + List result = streamRecorder.getValues(); + assertEquals(1, result.size()); + } + + // ======================================== + // Helper Methods + // ======================================== + + private StreamRecorder sendMessageRequest(TestGrpcHandler handler) throws Exception { + SendMessageRequest request = SendMessageRequest.newBuilder() + .setRequest(GRPC_MESSAGE) + .build(); + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.sendMessage(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + return streamRecorder; + } + + private StreamRecorder sendStreamingMessageRequest(TestGrpcHandler handler) throws Exception { + SendMessageRequest request = SendMessageRequest.newBuilder() + .setRequest(GRPC_MESSAGE) + .build(); + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.sendStreamingMessage(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + return streamRecorder; + } + + private void assertGrpcError(StreamRecorder streamRecorder, Status.Code expectedStatusCode) { + Assertions.assertNotNull(streamRecorder.getError()); + Assertions.assertInstanceOf(StatusRuntimeException.class, streamRecorder.getError()); + Assertions.assertEquals(expectedStatusCode, ((StatusRuntimeException) streamRecorder.getError()).getStatus().getCode()); + Assertions.assertTrue(streamRecorder.getValues().isEmpty()); + } + + + private StreamRecorder createTaskPushNotificationConfigRequest( + TestGrpcHandler handler, String name) throws Exception { + // Save task to v1.0 backend + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig config = + org.a2aproject.sdk.compat03.grpc.PushNotificationConfig.newBuilder() + .setUrl("http://example.com") + .build(); + + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig taskPushNotificationConfig = + org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.newBuilder() + .setName(name) + .setPushNotificationConfig(config) + .build(); + + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest setRequest = + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() + .setConfig(taskPushNotificationConfig) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.createTaskPushNotificationConfig(setRequest, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + return streamRecorder; + } + + private StreamRecorder getTaskPushNotificationConfigRequest( + TestGrpcHandler handler, String name) throws Exception { + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest request = + org.a2aproject.sdk.compat03.grpc.GetTaskPushNotificationConfigRequest.newBuilder() + .setName(name) + .build(); + + StreamRecorder streamRecorder = StreamRecorder.create(); + handler.getTaskPushNotificationConfig(request, streamRecorder); + streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); + return streamRecorder; + } + // ======================================== + // Test Handler Implementation + // ======================================== + + private static class TestGrpcHandler extends GrpcHandler_v0_3 { + private final AgentCard_v0_3 card; + private final Convert_v0_3_To10RequestHandler handler; + private final java.util.concurrent.Executor executor; + + TestGrpcHandler(AgentCard_v0_3 card, + Convert_v0_3_To10RequestHandler handler, + java.util.concurrent.Executor executor) { + this.card = card; + this.handler = handler; + this.executor = executor; + setRequestHandler(handler); + } + + @Override + protected AgentCard_v0_3 getAgentCard() { + return card; + } + + @Override + protected Convert_v0_3_To10RequestHandler getRequestHandler() { + return handler; + } + + @Override + protected CallContextFactory_v0_3 getCallContextFactory() { + return null; + } + + @Override + protected java.util.concurrent.Executor getExecutor() { + return executor; + } + } + +} diff --git a/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcTestTransportMetadata_v0_3.java b/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcTestTransportMetadata_v0_3.java new file mode 100644 index 000000000..55ebd84cd --- /dev/null +++ b/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcTestTransportMetadata_v0_3.java @@ -0,0 +1,9 @@ +package org.a2aproject.sdk.compat03.transport.grpc.handler; + +// TODO: Uncomment when server-common is ported + +/** + * Placeholder stub - awaiting server-common port. + */ +public class GrpcTestTransportMetadata_v0_3 { +} diff --git a/compat-0.3/transport/jsonrpc/pom.xml b/compat-0.3/transport/jsonrpc/pom.xml new file mode 100644 index 000000000..fc5b918b3 --- /dev/null +++ b/compat-0.3/transport/jsonrpc/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../.. + + a2a-java-sdk-compat-0.3-transport-jsonrpc + + jar + + Java SDK A2A Compat 0.3 Transport: JSONRPC + Java SDK for the Agent2Agent Protocol (A2A) - JSONRPC + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + + + ${project.groupId} + a2a-java-sdk-server-common + + + ${project.groupId} + a2a-java-sdk-server-common + test-jar + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + ${project.version} + test-jar + test + + + ch.qos.logback + logback-classic + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.mockito + mockito-core + test + + + + + diff --git a/compat-0.3/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/transport/jsonrpc/context/JSONRPCContextKeys_v0_3.java b/compat-0.3/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/transport/jsonrpc/context/JSONRPCContextKeys_v0_3.java new file mode 100644 index 000000000..b73763a87 --- /dev/null +++ b/compat-0.3/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/transport/jsonrpc/context/JSONRPCContextKeys_v0_3.java @@ -0,0 +1,24 @@ +package org.a2aproject.sdk.compat03.transport.jsonrpc.context; + +/** + * Shared JSON-RPC context keys for A2A protocol data. + * + * These keys provide access to JSON-RPC context information, + * enabling rich context access in service method implementations. + */ +public final class JSONRPCContextKeys_v0_3 { + + /** + * Context key for storing the headers. + */ + public static final String HEADERS_KEY = "headers"; + + /** + * Context key for storing the method name being called. + */ + public static final String METHOD_NAME_KEY = "method"; + + private JSONRPCContextKeys_v0_3() { + // Utility class + } +} diff --git a/compat-0.3/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3.java b/compat-0.3/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3.java new file mode 100644 index 000000000..a5b1bbe4f --- /dev/null +++ b/compat-0.3/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3.java @@ -0,0 +1,283 @@ +package org.a2aproject.sdk.compat03.transport.jsonrpc.handler; + +import static org.a2aproject.sdk.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 org.a2aproject.sdk.server.ExtendedAgentCard; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AuthenticatedExtendedCardNotConfiguredError_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetAuthenticatedExtendedCardRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetAuthenticatedExtendedCardResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskResubscriptionRequest_v0_3; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; +import org.a2aproject.sdk.compat03.conversion.ErrorConverter_v0_3; +import org.a2aproject.sdk.spec.A2AError; +import mutiny.zero.ZeroPublisher; + +@ApplicationScoped +public class JSONRPCHandler_v0_3 { + + private AgentCard_v0_3 agentCard; + private Instance extendedAgentCard; + private Convert_v0_3_To10RequestHandler requestHandler; + private final Executor executor; + + protected JSONRPCHandler_v0_3() { + this.executor = null; + } + + @Inject + public JSONRPCHandler_v0_3(@PublicAgentCard AgentCard_v0_3 agentCard, @ExtendedAgentCard Instance extendedAgentCard, + @Internal Executor executor, Convert_v0_3_To10RequestHandler requestHandler) { + this.agentCard = agentCard; + this.extendedAgentCard = extendedAgentCard; + this.requestHandler = requestHandler; + this.executor = executor; + + // TODO: Port AgentCardValidator for v0.3 AgentCard or skip validation in compat layer + // AgentCardValidator.validateTransportConfiguration(agentCard); + } + + public JSONRPCHandler_v0_3(@PublicAgentCard AgentCard_v0_3 agentCard, Executor executor, Convert_v0_3_To10RequestHandler requestHandler) { + this(agentCard, null, executor, requestHandler); + } + + public SendMessageResponse_v0_3 onMessageSend(SendMessageRequest_v0_3 request, ServerCallContext context) { + try { + request.check(); + EventKind_v0_3 result = requestHandler.onMessageSend(request.getParams(), context); + return new SendMessageResponse_v0_3(request.getId(), result); + } catch (A2AError e) { + return new SendMessageResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e)); + } catch (IllegalArgumentException t) { + return new SendMessageResponse_v0_3(request.getId(), new InvalidParamsError_v0_3(t.getMessage())); + } catch (Throwable t) { + return new SendMessageResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage())); + } + } + + public Flow.Publisher onMessageSendStream( + SendStreamingMessageRequest_v0_3 request, ServerCallContext context) { + if (!agentCard.capabilities().streaming()) { + return ZeroPublisher.fromItems( + new SendStreamingMessageResponse_v0_3( + request.getId(), + new InvalidRequestError_v0_3("Streaming is not supported by the agent"))); + } + try { + request.check(); + Flow.Publisher publisher = requestHandler.onMessageSendStream(request.getParams(), context); + return convertToSendStreamingMessageResponse(request.getId(), publisher); + } catch (A2AError e) { + return ZeroPublisher.fromItems(new SendStreamingMessageResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e))); + } catch (Throwable t) { + return ZeroPublisher.fromItems(new SendStreamingMessageResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage()))); + } + } + + public CancelTaskResponse_v0_3 onCancelTask(CancelTaskRequest_v0_3 request, ServerCallContext context) { + try { + Task_v0_3 result = requestHandler.onCancelTask(request.getParams(), context); + return new CancelTaskResponse_v0_3(request.getId(), result); + } catch (A2AError e) { + return new CancelTaskResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e)); + } catch (Throwable t) { + return new CancelTaskResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage())); + } + } + + public Flow.Publisher onResubscribeToTask( + TaskResubscriptionRequest_v0_3 request, ServerCallContext context) { + if (!agentCard.capabilities().streaming()) { + return ZeroPublisher.fromItems( + new SendStreamingMessageResponse_v0_3( + request.getId(), + new InvalidRequestError_v0_3("Streaming is not supported by the agent"))); + } + + try { + Flow.Publisher publisher = requestHandler.onResubscribeToTask(request.getParams(), context); + return convertToSendStreamingMessageResponse(request.getId(), publisher); + } catch (A2AError e) { + return ZeroPublisher.fromItems(new SendStreamingMessageResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e))); + } catch (Throwable t) { + return ZeroPublisher.fromItems(new SendStreamingMessageResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage()))); + } + } + + public GetTaskPushNotificationConfigResponse_v0_3 getPushNotificationConfig( + GetTaskPushNotificationConfigRequest_v0_3 request, ServerCallContext context) { + if (!agentCard.capabilities().pushNotifications()) { + return new GetTaskPushNotificationConfigResponse_v0_3(request.getId(), + new PushNotificationNotSupportedError_v0_3()); + } + try { + TaskPushNotificationConfig_v0_3 result = requestHandler.onGetTaskPushNotificationConfig(request.getParams(), context); + return new GetTaskPushNotificationConfigResponse_v0_3(request.getId(), result); + } catch (A2AError e) { + return new GetTaskPushNotificationConfigResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e)); + } catch (Throwable t) { + return new GetTaskPushNotificationConfigResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage())); + } + } + + public SetTaskPushNotificationConfigResponse_v0_3 setPushNotificationConfig( + SetTaskPushNotificationConfigRequest_v0_3 request, ServerCallContext context) { + if (!agentCard.capabilities().pushNotifications()) { + return new SetTaskPushNotificationConfigResponse_v0_3(request.getId(), + new PushNotificationNotSupportedError_v0_3()); + } + try { + TaskPushNotificationConfig_v0_3 result = requestHandler.onSetTaskPushNotificationConfig(request.getParams(), context); + return new SetTaskPushNotificationConfigResponse_v0_3(request.getId(), result); + } catch (A2AError e) { + return new SetTaskPushNotificationConfigResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e)); + } catch (Throwable t) { + return new SetTaskPushNotificationConfigResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage())); + } + } + + public GetTaskResponse_v0_3 onGetTask(GetTaskRequest_v0_3 request, ServerCallContext context) { + try { + Task_v0_3 result = requestHandler.onGetTask(request.getParams(), context); + return new GetTaskResponse_v0_3(request.getId(), result); + } catch (A2AError e) { + return new GetTaskResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e)); + } catch (Throwable t) { + return new GetTaskResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage())); + } + } + + public ListTaskPushNotificationConfigResponse_v0_3 listPushNotificationConfig( + ListTaskPushNotificationConfigRequest_v0_3 request, ServerCallContext context) { + if (!agentCard.capabilities().pushNotifications()) { + return new ListTaskPushNotificationConfigResponse_v0_3(request.getId(), + new PushNotificationNotSupportedError_v0_3()); + } + try { + List pushNotificationConfigList = + requestHandler.onListTaskPushNotificationConfig(request.getParams(), context); + return new ListTaskPushNotificationConfigResponse_v0_3(request.getId(), pushNotificationConfigList); + } catch (A2AError e) { + return new ListTaskPushNotificationConfigResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e)); + } catch (Throwable t) { + return new ListTaskPushNotificationConfigResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage())); + } + } + + public DeleteTaskPushNotificationConfigResponse_v0_3 deletePushNotificationConfig( + DeleteTaskPushNotificationConfigRequest_v0_3 request, ServerCallContext context) { + if (!agentCard.capabilities().pushNotifications()) { + return new DeleteTaskPushNotificationConfigResponse_v0_3(request.getId(), + new PushNotificationNotSupportedError_v0_3()); + } + try { + requestHandler.onDeleteTaskPushNotificationConfig(request.getParams(), context); + return new DeleteTaskPushNotificationConfigResponse_v0_3(request.getId()); + } catch (A2AError e) { + return new DeleteTaskPushNotificationConfigResponse_v0_3(request.getId(), ErrorConverter_v0_3.convertA2AError(e)); + } catch (Throwable t) { + return new DeleteTaskPushNotificationConfigResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage())); + } + } + + // TODO: Add authentication (https://github.com/a2aproject/a2a-java/issues/77) + public GetAuthenticatedExtendedCardResponse_v0_3 onGetAuthenticatedExtendedCardRequest( + GetAuthenticatedExtendedCardRequest_v0_3 request, ServerCallContext context) { + if (!agentCard.supportsAuthenticatedExtendedCard() || !extendedAgentCard.isResolvable()) { + return new GetAuthenticatedExtendedCardResponse_v0_3(request.getId(), + new AuthenticatedExtendedCardNotConfiguredError_v0_3(null, "Authenticated Extended Card not configured", null)); + } + try { + return new GetAuthenticatedExtendedCardResponse_v0_3(request.getId(), extendedAgentCard.get()); + } catch (JSONRPCError_v0_3 e) { + return new GetAuthenticatedExtendedCardResponse_v0_3(request.getId(), e); + } catch (Throwable t) { + return new GetAuthenticatedExtendedCardResponse_v0_3(request.getId(), new InternalError_v0_3(t.getMessage())); + } + } + + public AgentCard_v0_3 getAgentCard() { + return agentCard; + } + + private Flow.Publisher convertToSendStreamingMessageResponse( + Object requestId, + Flow.Publisher publisher) { + // We can't use the normal convertingProcessor since that propagates any errors as an error handled + // via Subscriber.onError() rather than as part of the SendStreamingResponse payload + return ZeroPublisher.create(createTubeConfig(), tube -> { + CompletableFuture.runAsync(() -> { + publisher.subscribe(new Flow.Subscriber() { + Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(StreamingEventKind_v0_3 item) { + tube.send(new SendStreamingMessageResponse_v0_3(requestId, item)); + subscription.request(1); + } + + @Override + public void onError(Throwable throwable) { + if (throwable instanceof JSONRPCError_v0_3 jsonrpcError) { + tube.send(new SendStreamingMessageResponse_v0_3(requestId, jsonrpcError)); + } else { + tube.send( + new SendStreamingMessageResponse_v0_3( + requestId, new + InternalError_v0_3(throwable.getMessage()))); + } + onComplete(); + } + + @Override + public void onComplete() { + tube.complete(); + } + }); + }, executor); + }); + } +} diff --git a/compat-0.3/transport/jsonrpc/src/main/resources/META-INF/beans.xml b/compat-0.3/transport/jsonrpc/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..548d44b72 --- /dev/null +++ b/compat-0.3/transport/jsonrpc/src/main/resources/META-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java new file mode 100644 index 000000000..a564905d4 --- /dev/null +++ b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java @@ -0,0 +1,1150 @@ +package org.a2aproject.sdk.compat03.transport.jsonrpc.handler; + +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.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.Flow; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import org.a2aproject.sdk.compat03.conversion.AbstractA2ARequestHandlerTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskArtifactUpdateEventMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskStatusUpdateEventMapper_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Event_v0_3; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +// V0.3 spec imports (client perspective) +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.Artifact_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.CancelTaskResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.Message_v0_3; +import org.a2aproject.sdk.compat03.spec.MessageSendParams_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendMessageResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SetTaskPushNotificationConfigResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.SendStreamingMessageResponse_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskResubscriptionRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; +import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; + +/** + * Test suite for v0.3 JSONRPCHandler with v1.0 backend. + *

            + * Tests verify that v0.3 clients can successfully communicate with the v1.0 backend + * via the {@link Convert_v0_3_To10RequestHandler} conversion layer. + *

            + *

            + * Phase 2 Focus: Core non-streaming tests (GetTask, SendMessage, CancelTask). + * Streaming tests and push notification tests are deferred to later phases. + *

            + */ +public class JSONRPCHandler_v0_3_Test extends AbstractA2ARequestHandlerTest_v0_3 { + + private final ServerCallContext callContext = new ServerCallContext( + UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + + // ======================================== + // GetTask Tests + // ======================================== + + @Test + public void testOnGetTaskSuccess() throws Exception { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save v0.3 task by converting to v1.0 for taskStore + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + GetTaskRequest_v0_3 request = new GetTaskRequest_v0_3("1", new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + GetTaskResponse_v0_3 response = handler.onGetTask(request, callContext); + + assertEquals(request.getId(), response.getId()); + assertNull(response.getError()); + + // Response should contain v0.3 task (converted back from v1.0) + Task_v0_3 result = response.getResult(); + assertEquals(MINIMAL_TASK.getId(), result.getId()); + assertEquals(MINIMAL_TASK.getContextId(), result.getContextId()); + } + + @Test + public void testOnGetTaskNotFound() throws Exception { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + GetTaskRequest_v0_3 request = new GetTaskRequest_v0_3("1", new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + GetTaskResponse_v0_3 response = handler.onGetTask(request, callContext); + + assertEquals(request.getId(), response.getId()); + assertInstanceOf(TaskNotFoundError_v0_3.class, response.getError()); + assertNull(response.getResult()); + } + + // ======================================== + // CancelTask Tests + // ======================================== + + @Test + public void testOnCancelTaskSuccess() throws Exception { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save v0.3 task by converting to v1.0 + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to cancel the task + // In v1.0, we use AgentEmitter.cancel() instead of TaskUpdater + agentExecutorCancel = (context, emitter) -> { + emitter.cancel(); + }; + + CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("111", new TaskIdParams_v0_3(MINIMAL_TASK.getId())); + CancelTaskResponse_v0_3 response = handler.onCancelTask(request, callContext); + + assertNull(response.getError()); + assertEquals(request.getId(), response.getId()); + + // Verify task was canceled + Task_v0_3 task = response.getResult(); + assertEquals(MINIMAL_TASK.getId(), task.getId()); + assertEquals(MINIMAL_TASK.getContextId(), task.getContextId()); + assertEquals(TaskState_v0_3.CANCELED, task.getStatus().state()); + } + + @Test + public void testOnCancelTaskNotSupported() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save v0.3 task by converting to v1.0 + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to throw UnsupportedOperationError + agentExecutorCancel = (context, emitter) -> { + throw new org.a2aproject.sdk.spec.UnsupportedOperationError(); + }; + + CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.getId())); + CancelTaskResponse_v0_3 response = handler.onCancelTask(request, callContext); + + assertEquals(request.getId(), response.getId()); + assertNull(response.getResult()); + assertInstanceOf(UnsupportedOperationError_v0_3.class, response.getError()); + } + + @Test + public void testOnCancelTaskNotFound() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.getId())); + CancelTaskResponse_v0_3 response = handler.onCancelTask(request, callContext); + + assertEquals(request.getId(), response.getId()); + assertNull(response.getResult()); + assertInstanceOf(TaskNotFoundError_v0_3.class, response.getError()); + } + + // ======================================== + // SendMessage Tests (Non-Streaming) + // ======================================== + + @Test + public void testOnMessageSendSuccess() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to echo the message back + agentExecutorExecute = (context, emitter) -> { + // Note: context.getMessage() contains v1.0 Message (already converted by Convert03To10RequestHandler) + // Emit the v1.0 message, it will be converted back to v0.3 in the response + emitter.emitEvent(context.getMessage()); + }; + + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .build(); + + SendMessageRequest_v0_3 request = new SendMessageRequest_v0_3("1", new MessageSendParams_v0_3(message, null, null)); + SendMessageResponse_v0_3 response = handler.onMessageSend(request, callContext); + + assertNull(response.getError()); + // Response should contain the message (converted back from v1.0) + EventKind_v0_3 result = response.getResult(); + if (result instanceof Message_v0_3) { + assertEquals(message.getMessageId(), ((Message_v0_3) result).getMessageId()); + } + } + + @Test + public void testOnMessageSendWithExistingTaskSuccess() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to emit message + agentExecutorExecute = (context, emitter) -> { + // Emit v1.0 message from context + emitter.emitEvent(context.getMessage()); + }; + + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .build(); + + SendMessageRequest_v0_3 request = new SendMessageRequest_v0_3("1", new MessageSendParams_v0_3(message, null, null)); + SendMessageResponse_v0_3 response = handler.onMessageSend(request, callContext); + + assertNull(response.getError()); + EventKind_v0_3 result = response.getResult(); + if (result instanceof Message_v0_3) { + assertEquals(message.getMessageId(), ((Message_v0_3) result).getMessageId()); + } + } + + @Test + public void testOnMessageSendError() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to throw error + agentExecutorExecute = (context, emitter) -> { + emitter.emitEvent(new org.a2aproject.sdk.spec.UnsupportedOperationError()); + }; + + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .build(); + + SendMessageRequest_v0_3 request = new SendMessageRequest_v0_3("1", new MessageSendParams_v0_3(message, null, null)); + SendMessageResponse_v0_3 response = handler.onMessageSend(request, callContext); + + assertInstanceOf(UnsupportedOperationError_v0_3.class, response.getError()); + assertNull(response.getResult()); + } + + // ======================================== + // Streaming Tests + // ======================================== + + @Test + public void testOnMessageSendStreamSuccess() throws InterruptedException { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to emit the message back (v1.0 context contains v1.0 Message) + agentExecutorExecute = (context, emitter) -> { + // Emit v1.0 message - will be converted to v0.3 StreamingEventKind + emitter.emitEvent(context.getMessage()); + }; + + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .build(); + + SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( + "1", new MessageSendParams_v0_3(message, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); + + List results = new ArrayList<>(); + CountDownLatch latch = new CountDownLatch(1); + AtomicReference error = new AtomicReference<>(); + + response.subscribe(new Flow.Subscriber<>() { + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse_v0_3 item) { + results.add(item.getResult()); + subscription.request(1); + latch.countDown(); + } + + @Override + public void onError(Throwable throwable) { + error.set(throwable); + subscription.cancel(); + // Release latch to prevent timeout + while (latch.getCount() > 0) { + latch.countDown(); + } + } + + @Override + public void onComplete() { + subscription.cancel(); + } + }); + + // Wait for event to be received + assertTrue(latch.await(2, TimeUnit.SECONDS), "Expected to receive 1 event within timeout"); + + // Assert no error occurred during streaming + assertNull(error.get(), "No error should occur during streaming"); + + // Verify that the message was received + assertEquals(1, results.size(), "Should have received exactly 1 event"); + + // Verify the event is the message (converted back from v1.0) + Message_v0_3 receivedMessage = assertInstanceOf(Message_v0_3.class, results.get(0), "Event should be a Message"); + assertEquals(message.getMessageId(), receivedMessage.getMessageId()); + } + + @Test + public void testOnMessageSendStreamMultipleEventsSuccess() throws InterruptedException { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Create v0.3 events for reference (we'll emit v1.0 equivalents) + Task_v0_3 v03TaskEvent = new Task_v0_3.Builder(MINIMAL_TASK) + .status(new TaskStatus_v0_3(TaskState_v0_3.WORKING)) + .build(); + + TaskArtifactUpdateEvent_v0_3 v03ArtifactEvent = new TaskArtifactUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .artifact(new Artifact_v0_3.Builder() + .artifactId("artifact-1") + .parts(new TextPart_v0_3("Generated artifact content")) + .build()) + .build(); + + TaskStatusUpdateEvent_v0_3 v03StatusEvent = new TaskStatusUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .isFinal(true) // Must be true for COMPLETED state in v1.0 + .build(); + + // Configure the agent executor to emit multiple v1.0 events + agentExecutorExecute = (context, emitter) -> { + // Convert v0.3 events to v1.0 and emit them + // The emitter will convert them back to v0.3 StreamingEventKind for the response + emitter.emitEvent(TaskMapper_v0_3.INSTANCE.toV10(v03TaskEvent)); + emitter.emitEvent(TaskArtifactUpdateEventMapper_v0_3.INSTANCE.toV10(v03ArtifactEvent)); + emitter.emitEvent(TaskStatusUpdateEventMapper_v0_3.INSTANCE.toV10(v03StatusEvent)); + }; + + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .build(); + + SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( + "1", new MessageSendParams_v0_3(message, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); + + List results = new ArrayList<>(); + CountDownLatch latch = new CountDownLatch(3); // Expect 3 events + AtomicReference error = new AtomicReference<>(); + + response.subscribe(new Flow.Subscriber<>() { + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse_v0_3 item) { + results.add(item.getResult()); + subscription.request(1); + latch.countDown(); + } + + @Override + public void onError(Throwable throwable) { + error.set(throwable); + subscription.cancel(); + // Release latch to prevent timeout + while (latch.getCount() > 0) { + latch.countDown(); + } + } + + @Override + public void onComplete() { + subscription.cancel(); + } + }); + + // Wait for all events to be received + assertTrue(latch.await(2, TimeUnit.SECONDS), "Expected to receive 3 events within timeout"); + + // Assert no error occurred during streaming + assertNull(error.get(), "No error should occur during streaming"); + + // Verify that all 3 events were received + assertEquals(3, results.size(), "Should have received exactly 3 events"); + + // Verify the first event is the task + Task_v0_3 receivedTask = assertInstanceOf(Task_v0_3.class, results.get(0), "First event should be a Task"); + assertEquals(MINIMAL_TASK.getId(), receivedTask.getId()); + assertEquals(MINIMAL_TASK.getContextId(), receivedTask.getContextId()); + assertEquals(TaskState_v0_3.WORKING, receivedTask.getStatus().state()); + + // Verify the second event is the artifact update + TaskArtifactUpdateEvent_v0_3 receivedArtifact = assertInstanceOf(TaskArtifactUpdateEvent_v0_3.class, results.get(1), + "Second event should be a TaskArtifactUpdateEvent"); + assertEquals(MINIMAL_TASK.getId(), receivedArtifact.getTaskId()); + assertEquals("artifact-1", receivedArtifact.getArtifact().artifactId()); + + // Verify the third event is the status update + TaskStatusUpdateEvent_v0_3 receivedStatus = assertInstanceOf(TaskStatusUpdateEvent_v0_3.class, results.get(2), + "Third event should be a TaskStatusUpdateEvent"); + assertEquals(MINIMAL_TASK.getId(), receivedStatus.getTaskId()); + assertEquals(TaskState_v0_3.COMPLETED, receivedStatus.getStatus().state()); + } + + @Test + public void testOnMessageSendStreamExistingTaskSuccess() throws InterruptedException { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Configure agent to emit the task (v1.0 context contains v1.0 Task) + agentExecutorExecute = (context, emitter) -> { + // Emit v1.0 task - will be converted to v0.3 StreamingEventKind + emitter.emitEvent(context.getTask()); + }; + + // Save existing v0.3 task (convert to v1.0 for storage) + Task_v0_3 v03Task = new Task_v0_3.Builder(MINIMAL_TASK) + .history(new ArrayList<>()) + .build(); + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(v03Task), false); + + Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) + .taskId(v03Task.getId()) + .contextId(v03Task.getContextId()) + .build(); + + SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( + "1", new MessageSendParams_v0_3(message, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); + + // For non-final tasks, the publisher doesn't complete, so we subscribe in a new thread + // and manually cancel after receiving the first event + final List results = new ArrayList<>(); + final AtomicReference subscriptionRef = new AtomicReference<>(); + final CountDownLatch latch = new CountDownLatch(1); + final AtomicReference error = new AtomicReference<>(); + + Executors.newSingleThreadExecutor().execute(() -> { + response.subscribe(new Flow.Subscriber<>() { + @Override + public void onSubscribe(Flow.Subscription subscription) { + subscriptionRef.set(subscription); + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse_v0_3 item) { + results.add(item.getResult()); + subscriptionRef.get().request(1); + latch.countDown(); + } + + @Override + public void onError(Throwable throwable) { + error.set(throwable); + subscriptionRef.get().cancel(); + // Release latch to prevent timeout + while (latch.getCount() > 0) { + latch.countDown(); + } + } + + @Override + public void onComplete() { + subscriptionRef.get().cancel(); + } + }); + }); + + // Wait for the first event + assertTrue(latch.await(2, TimeUnit.SECONDS), "Expected to receive 1 event within timeout"); + subscriptionRef.get().cancel(); + + // Assert no error occurred during streaming + assertNull(error.get(), "No error should occur during streaming"); + + // Verify the task was received + assertEquals(1, results.size(), "Should have received exactly 1 event"); + Task_v0_3 receivedTask = assertInstanceOf(Task_v0_3.class, results.get(0), "Event should be a Task"); + assertEquals(v03Task.getId(), receivedTask.getId()); + assertEquals(v03Task.getContextId(), receivedTask.getContextId()); + // Note: v1.0 backend manages task history differently than v0.3 + // The key assertion is that we received a Task event for the existing task + } + + // ======================================== + // Streaming Error Tests + // ======================================== + + @Test + public void testStreamingNotSupportedError() { + // Create agent card with streaming disabled + AgentCard_v0_3 nonStreamingCard = new AgentCard_v0_3.Builder(CARD) + .capabilities(new AgentCapabilities_v0_3(false, true, false, null)) + .build(); + + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(nonStreamingCard, internalExecutor, convert03To10Handler); + + SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( + "1", new MessageSendParams_v0_3(MESSAGE, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); + + List results = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + response.subscribe(new Flow.Subscriber<>() { + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse_v0_3 item) { + results.add(item); + subscription.request(1); + } + + @Override + public void onError(Throwable throwable) { + error.set(throwable); + subscription.cancel(); + } + + @Override + public void onComplete() { + subscription.cancel(); + } + }); + + // Verify that an error response was returned + assertEquals(1, results.size(), "Should receive exactly one error response"); + SendStreamingMessageResponse_v0_3 errorResponse = results.get(0); + assertNotNull(errorResponse.getError(), "Response should contain an error"); + assertInstanceOf(InvalidRequestError_v0_3.class, errorResponse.getError(), "Error should be InvalidRequestError"); + assertEquals("Streaming is not supported by the agent", + ((InvalidRequestError_v0_3) errorResponse.getError()).getMessage()); + } + + @Test + public void testOnMessageStreamTaskIdMismatch() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save existing task + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to emit a task with DIFFERENT task ID than the message + agentExecutorExecute = (context, emitter) -> { + // Emit MINIMAL_TASK (which has different ID from MESSAGE) + emitter.emitEvent(context.getTask()); + }; + + // Send MESSAGE (which has a different task ID) + SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( + "1", new MessageSendParams_v0_3(MESSAGE, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); + + CompletableFuture future = new CompletableFuture<>(); + List results = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + response.subscribe(new Flow.Subscriber<>() { + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse_v0_3 item) { + results.add(item); + subscription.request(1); + } + + @Override + public void onError(Throwable throwable) { + error.set(throwable); + subscription.cancel(); + future.completeExceptionally(throwable); + } + + @Override + public void onComplete() { + subscription.cancel(); + future.complete(null); + } + }); + + future.join(); + + // Stream should complete without throwing + assertNull(error.get(), "No exception should be thrown"); + + // Should receive an error response for the task ID mismatch + assertEquals(1, results.size(), "Should receive exactly one error response"); + SendStreamingMessageResponse_v0_3 errorResponse = results.get(0); + assertInstanceOf(InternalError_v0_3.class, errorResponse.getError(), + "Task ID mismatch should result in InternalError"); + } + + @Test + public void testOnMessageStreamInternalError() { + // Mock the Convert03To10RequestHandler to throw InternalError + Convert_v0_3_To10RequestHandler mockedHandler = Mockito.mock(Convert_v0_3_To10RequestHandler.class); + Mockito.doThrow(new org.a2aproject.sdk.spec.InternalError("Internal Error")) + .when(mockedHandler) + .onMessageSendStream( + Mockito.any(MessageSendParams_v0_3.class), + Mockito.any(ServerCallContext.class)); + + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, mockedHandler); + + SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3("1", new MessageSendParams_v0_3(MESSAGE, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); + + List results = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + response.subscribe(new Flow.Subscriber<>() { + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse_v0_3 item) { + results.add(item); + subscription.request(1); + } + + @Override + public void onError(Throwable throwable) { + error.set(throwable); + subscription.cancel(); + } + + @Override + public void onComplete() { + subscription.cancel(); + } + }); + + // Verify that an InternalError response was returned + assertEquals(1, results.size(), "Should receive exactly one error response"); + assertInstanceOf(InternalError_v0_3.class, results.get(0).getError(), "Error should be InternalError"); + } + + @Test + public void testStreamingNotSupportedErrorOnResubscribeToTask() { + // Create agent card with streaming disabled + AgentCard_v0_3 nonStreamingCard = new AgentCard_v0_3.Builder(CARD) + .capabilities(new AgentCapabilities_v0_3(false, true, false, null)) + .build(); + + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(nonStreamingCard, internalExecutor, convert03To10Handler); + + TaskResubscriptionRequest_v0_3 request = new TaskResubscriptionRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.getId())); + Flow.Publisher response = handler.onResubscribeToTask(request, callContext); + + List results = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + response.subscribe(new Flow.Subscriber<>() { + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse_v0_3 item) { + results.add(item); + subscription.request(1); + } + + @Override + public void onError(Throwable throwable) { + error.set(throwable); + subscription.cancel(); + } + + @Override + public void onComplete() { + subscription.cancel(); + } + }); + + // Verify that an error response was returned + assertEquals(1, results.size(), "Should receive exactly one error response"); + SendStreamingMessageResponse_v0_3 errorResponse = results.get(0); + assertNotNull(errorResponse.getError(), "Response should contain an error"); + assertInstanceOf(InvalidRequestError_v0_3.class, errorResponse.getError(), "Error should be InvalidRequestError"); + assertEquals("Streaming is not supported by the agent", + ((InvalidRequestError_v0_3) errorResponse.getError()).getMessage()); + } + + // ======================================== + // Push Notification Tests + // ======================================== + + @Test + public void testSetPushNotificationConfigSuccess() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend (conversion happens internally) + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK); + taskStore.save(v10Task, false); + + TaskPushNotificationConfig_v0_3 taskPushConfig = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .build()); + SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3("1", taskPushConfig); + SetTaskPushNotificationConfigResponse_v0_3 response = handler.setPushNotificationConfig(request, callContext); + + assertNull(response.getError(), "Error: " + response.getError()); + assertNotNull(response.getResult()); + + TaskPushNotificationConfig_v0_3 taskPushConfigResult = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id(MINIMAL_TASK.getId()) + .build()); + assertEquals(taskPushConfigResult, response.getResult()); + } + + @Test + public void testGetPushNotificationConfigSuccess() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK); + taskStore.save(v10Task, false); + + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + }; + + TaskPushNotificationConfig_v0_3 taskPushConfig = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .build()); + + SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3("1", taskPushConfig); + handler.setPushNotificationConfig(request, callContext); + + GetTaskPushNotificationConfigRequest_v0_3 getRequest = + new GetTaskPushNotificationConfigRequest_v0_3("111", new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + GetTaskPushNotificationConfigResponse_v0_3 getResponse = handler.getPushNotificationConfig(getRequest, callContext); + + TaskPushNotificationConfig_v0_3 expectedConfig = new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder().id(MINIMAL_TASK.getId()).url("http://example.com").build()); + assertEquals(expectedConfig, getResponse.getResult()); + } + + @Test + public void testDeletePushNotificationConfig() { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK); + taskStore.save(v10Task, false); + + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + }; + + TaskPushNotificationConfig_v0_3 taskPushConfig = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id(MINIMAL_TASK.getId()) + .build()); + SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3("1", taskPushConfig); + handler.setPushNotificationConfig(request, callContext); + + DeleteTaskPushNotificationConfigRequest_v0_3 deleteRequest = + new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), MINIMAL_TASK.getId())); + DeleteTaskPushNotificationConfigResponse_v0_3 deleteResponse = + handler.deletePushNotificationConfig(deleteRequest, callContext); + + assertEquals("111", deleteResponse.getId()); + assertNull(deleteResponse.getError()); + assertNull(deleteResponse.getResult()); + } + + @Test + public void testOnGetPushNotificationNoPushNotifierConfig() { + // Create v1.0 request handler without push config store + org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler v10Handler = + org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler.create( + agentExecutor, taskStore, queueManager, null, mainEventBusProcessor, + internalExecutor, internalExecutor); + + // Wrap in v0.3 conversion handler + Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(); + handlerWithoutPushConfig.v10Handler = v10Handler; + + AgentCard_v0_3 card = createAgentCard(false, true, false); + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(card, internalExecutor, handlerWithoutPushConfig); + + // Save task to v1.0 backend + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK); + taskStore.save(v10Task, false); + + GetTaskPushNotificationConfigRequest_v0_3 request = + new GetTaskPushNotificationConfigRequest_v0_3("id", new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + GetTaskPushNotificationConfigResponse_v0_3 response = handler.getPushNotificationConfig(request, callContext); + + assertNotNull(response.getError()); + assertInstanceOf(UnsupportedOperationError_v0_3.class, response.getError()); + assertEquals("This operation is not supported", response.getError().getMessage()); + } + + @Test + public void testOnSetPushNotificationNoPushNotifierConfig() { + // Create v1.0 request handler without push config store + org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler v10Handler = + org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler.create( + agentExecutor, taskStore, queueManager, null, mainEventBusProcessor, + internalExecutor, internalExecutor); + + // Wrap in v0.3 conversion handler + Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(); + handlerWithoutPushConfig.v10Handler = v10Handler; + + AgentCard_v0_3 card = createAgentCard(false, true, false); + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(card, internalExecutor, handlerWithoutPushConfig); + + // Save task to v1.0 backend + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK); + taskStore.save(v10Task, false); + + TaskPushNotificationConfig_v0_3 config = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .build()); + + SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3.Builder() + .params(config) + .build(); + SetTaskPushNotificationConfigResponse_v0_3 response = handler.setPushNotificationConfig(request, callContext); + + assertInstanceOf(UnsupportedOperationError_v0_3.class, response.getError()); + assertEquals("This operation is not supported", response.getError().getMessage()); + } + + @Test + public void testDeletePushNotificationConfigNotSupported() { + AgentCard_v0_3 card = createAgentCard(true, false, false); + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(card, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK); + taskStore.save(v10Task, false); + + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + }; + + TaskPushNotificationConfig_v0_3 taskPushConfig = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id(MINIMAL_TASK.getId()) + .build()); + SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3("1", taskPushConfig); + handler.setPushNotificationConfig(request, callContext); + + DeleteTaskPushNotificationConfigRequest_v0_3 deleteRequest = + new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), MINIMAL_TASK.getId())); + DeleteTaskPushNotificationConfigResponse_v0_3 deleteResponse = + handler.deletePushNotificationConfig(deleteRequest, callContext); + + assertEquals("111", deleteResponse.getId()); + assertNull(deleteResponse.getResult()); + assertInstanceOf(PushNotificationNotSupportedError_v0_3.class, deleteResponse.getError()); + } + + @Test + public void testDeletePushNotificationConfigNoPushConfigStore() { + // Create v1.0 request handler without push config store + org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler v10Handler = + org.a2aproject.sdk.server.requesthandlers.DefaultRequestHandler.create( + agentExecutor, taskStore, queueManager, null, mainEventBusProcessor, + internalExecutor, internalExecutor); + + // Wrap in v0.3 conversion handler + Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(); + handlerWithoutPushConfig.v10Handler = v10Handler; + + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, handlerWithoutPushConfig); + + // Save task to v1.0 backend + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK); + taskStore.save(v10Task, false); + + agentExecutorExecute = (context, agentEmitter) -> { + agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); + }; + + TaskPushNotificationConfig_v0_3 taskPushConfig = + new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder() + .url("http://example.com") + .id(MINIMAL_TASK.getId()) + .build()); + SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3("1", taskPushConfig); + handler.setPushNotificationConfig(request, callContext); + + DeleteTaskPushNotificationConfigRequest_v0_3 deleteRequest = + new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), MINIMAL_TASK.getId())); + DeleteTaskPushNotificationConfigResponse_v0_3 deleteResponse = + handler.deletePushNotificationConfig(deleteRequest, callContext); + + assertEquals("111", deleteResponse.getId()); + assertNull(deleteResponse.getResult()); + assertInstanceOf(UnsupportedOperationError_v0_3.class, deleteResponse.getError()); + } + + @Test + public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Exception { + // Use synchronous executor for push notifications to ensure deterministic ordering + // Without this, async push notifications can execute out of order, causing test flakiness + mainEventBusProcessor.setPushNotificationExecutor(Runnable::run); + + try { + JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK); + taskStore.save(v10Task, false); + + // Clear any previous events from httpClient + httpClient.events.clear(); + + // Create v0.3 events that the agent executor will emit + List events = List.of( + MINIMAL_TASK, + new TaskArtifactUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .artifact(new Artifact_v0_3.Builder() + .artifactId("11") + .parts(new TextPart_v0_3("text")) + .build()) + .build(), + new TaskStatusUpdateEvent_v0_3.Builder() + .taskId(MINIMAL_TASK.getId()) + .contextId(MINIMAL_TASK.getContextId()) + .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) + .isFinal(true) + .build()); + + agentExecutorExecute = (context, agentEmitter) -> { + // Convert v0.3 events to v1.0 and emit + for (Event_v0_3 event : events) { + if (event instanceof Task_v0_3) { + agentEmitter.emitEvent(TaskMapper_v0_3.INSTANCE.toV10((Task_v0_3) event)); + } else if (event instanceof TaskArtifactUpdateEvent_v0_3) { + agentEmitter.emitEvent(TaskArtifactUpdateEventMapper_v0_3.INSTANCE.toV10((TaskArtifactUpdateEvent_v0_3) event)); + } else if (event instanceof TaskStatusUpdateEvent_v0_3) { + agentEmitter.emitEvent(TaskStatusUpdateEventMapper_v0_3.INSTANCE.toV10((TaskStatusUpdateEvent_v0_3) event)); + } + } + }; + + // Set push notification config + TaskPushNotificationConfig_v0_3 config = new TaskPushNotificationConfig_v0_3( + MINIMAL_TASK.getId(), + new PushNotificationConfig_v0_3.Builder().url("http://example.com").build()); + SetTaskPushNotificationConfigRequest_v0_3 stpnRequest = new SetTaskPushNotificationConfigRequest_v0_3("1", config); + SetTaskPushNotificationConfigResponse_v0_3 stpnResponse = handler.setPushNotificationConfig(stpnRequest, callContext); + assertNull(stpnResponse.getError()); + + // Send streaming message + Message_v0_3 msg = new Message_v0_3.Builder(MESSAGE) + .taskId(MINIMAL_TASK.getId()) + .build(); + SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3("1", new MessageSendParams_v0_3(msg, null, null)); + Flow.Publisher response = handler.onMessageSendStream(request, callContext); + + final List results = Collections.synchronizedList(new ArrayList<>()); + final AtomicReference subscriptionRef = new AtomicReference<>(); + final CountDownLatch latch = new CountDownLatch(6); // 3 streaming responses + 3 push notifications + httpClient.latch = latch; + + Executors.newSingleThreadExecutor().execute(() -> { + response.subscribe(new Flow.Subscriber<>() { + @Override + public void onSubscribe(Flow.Subscription subscription) { + subscriptionRef.set(subscription); + subscription.request(1); + } + + @Override + public void onNext(SendStreamingMessageResponse_v0_3 item) { + results.add(item.getResult()); + subscriptionRef.get().request(1); + latch.countDown(); + } + + @Override + public void onError(Throwable throwable) { + subscriptionRef.get().cancel(); + } + + @Override + public void onComplete() { + subscriptionRef.get().cancel(); + } + }); + }); + + boolean timedOut = !latch.await(5, TimeUnit.SECONDS); + if (timedOut) { + System.out.println("Test timed out! Received " + results.size() + " streaming responses, " + + httpClient.events.size() + " push notifications. Latch count: " + latch.getCount()); + System.out.println("Push notifications received:"); + for (int i = 0; i < httpClient.events.size(); i++) { + org.a2aproject.sdk.spec.StreamingEventKind event = httpClient.events.get(i); + if (event instanceof org.a2aproject.sdk.spec.Task) { + System.out.println(" [" + i + "] Task"); + } else if (event instanceof org.a2aproject.sdk.spec.TaskArtifactUpdateEvent) { + System.out.println(" [" + i + "] TaskArtifactUpdateEvent"); + } else if (event instanceof org.a2aproject.sdk.spec.TaskStatusUpdateEvent) { + System.out.println(" [" + i + "] TaskStatusUpdateEvent"); + } else if (event instanceof org.a2aproject.sdk.spec.Message) { + System.out.println(" [" + i + "] Message"); + } + } + } + assertTrue(!timedOut, "Test timed out waiting for events. Received " + results.size() + " streaming responses, " + + httpClient.events.size() + " push notifications"); + subscriptionRef.get().cancel(); + + // Verify streaming responses (v0.3 format) + assertEquals(3, results.size()); + + // Verify push notifications were sent (v1.0 StreamingEventKind format) + assertEquals(3, httpClient.events.size()); + + // First event: task + org.a2aproject.sdk.spec.StreamingEventKind pushEvent0 = httpClient.events.get(0); + assertTrue(pushEvent0 instanceof org.a2aproject.sdk.spec.Task); + org.a2aproject.sdk.spec.Task v10PushedTask0 = (org.a2aproject.sdk.spec.Task) pushEvent0; + assertEquals(MINIMAL_TASK.getId(), v10PushedTask0.id()); + assertEquals(MINIMAL_TASK.getContextId(), v10PushedTask0.contextId()); + // v0.3 SUBMITTED maps to v1.0 TASK_STATE_SUBMITTED + assertEquals(org.a2aproject.sdk.spec.TaskState.TASK_STATE_SUBMITTED, v10PushedTask0.status().state()); + assertTrue(v10PushedTask0.artifacts() == null || v10PushedTask0.artifacts().isEmpty()); + + // Second event: artifact update + org.a2aproject.sdk.spec.StreamingEventKind pushEvent1 = httpClient.events.get(1); + assertTrue(pushEvent1 instanceof org.a2aproject.sdk.spec.TaskArtifactUpdateEvent); + org.a2aproject.sdk.spec.TaskArtifactUpdateEvent v10ArtifactUpdate = (org.a2aproject.sdk.spec.TaskArtifactUpdateEvent) pushEvent1; + assertEquals(MINIMAL_TASK.getId(), v10ArtifactUpdate.taskId()); + assertEquals(MINIMAL_TASK.getContextId(), v10ArtifactUpdate.contextId()); + assertNotNull(v10ArtifactUpdate.artifact()); + assertEquals(1, v10ArtifactUpdate.artifact().parts().size()); + assertEquals("text", ((org.a2aproject.sdk.spec.TextPart) v10ArtifactUpdate.artifact().parts().get(0)).text()); + + // Third event: status update + org.a2aproject.sdk.spec.StreamingEventKind pushEvent2 = httpClient.events.get(2); + assertTrue(pushEvent2 instanceof org.a2aproject.sdk.spec.TaskStatusUpdateEvent); + org.a2aproject.sdk.spec.TaskStatusUpdateEvent v10StatusUpdate = (org.a2aproject.sdk.spec.TaskStatusUpdateEvent) pushEvent2; + assertEquals(MINIMAL_TASK.getId(), v10StatusUpdate.taskId()); + assertEquals(MINIMAL_TASK.getContextId(), v10StatusUpdate.contextId()); + assertEquals(org.a2aproject.sdk.spec.TaskState.TASK_STATE_COMPLETED, v10StatusUpdate.status().state()); + } finally { + // Reset push notification executor to async + mainEventBusProcessor.setPushNotificationExecutor(null); + } + } + + // TODO Phase 6: Add authenticated extended card tests +} diff --git a/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCTestTransportMetadata_v0_3.java b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCTestTransportMetadata_v0_3.java new file mode 100644 index 000000000..ab9e169ee --- /dev/null +++ b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCTestTransportMetadata_v0_3.java @@ -0,0 +1,19 @@ +package org.a2aproject.sdk.compat03.transport.jsonrpc.handler; + +// TODO: Uncomment when server-common is ported + +// import org.a2aproject.sdk.compat03.server.TransportMetadata; +// import org.a2aproject.sdk.compat03.spec.TransportProtocol; + +// public class JSONRPCTestTransportMetadata implements TransportMetadata { +// @Override +// public String getTransportProtocol() { +// return TransportProtocol.JSONRPC.asString(); +// } +// } + +/** + * Placeholder stub - awaiting server-common port. + */ +public class JSONRPCTestTransportMetadata_v0_3 { +} diff --git a/compat-0.3/transport/rest/pom.xml b/compat-0.3/transport/rest/pom.xml new file mode 100644 index 000000000..fe31a68fb --- /dev/null +++ b/compat-0.3/transport/rest/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.Beta2-SNAPSHOT + ../.. + + a2a-java-sdk-compat-0.3-transport-rest + + jar + + Java SDK A2A Compat 0.3 Transport: JSON+HTTP/REST + Java SDK for the Agent2Agent Protocol (A2A) - JSON+HTTP/REST Transport + + + + ${project.groupId} + a2a-java-sdk-server-common + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec-grpc + + + ${project.groupId} + a2a-java-sdk-compat-0.3-spec + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + + + ${project.groupId} + a2a-java-sdk-server-common + test-jar + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + ${project.version} + test-jar + test + + + ch.qos.logback + logback-classic + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.mockito + mockito-core + test + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + com.google.protobuf + protobuf-java-util + + + org.slf4j + slf4j-jdk14 + test + + + + + \ No newline at end of file diff --git a/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/context/RestContextKeys_v0_3.java b/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/context/RestContextKeys_v0_3.java new file mode 100644 index 000000000..8ec416605 --- /dev/null +++ b/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/context/RestContextKeys_v0_3.java @@ -0,0 +1,24 @@ +package org.a2aproject.sdk.compat03.transport.rest.context; + +/** + * Shared REST context keys for A2A protocol data. + * + * These keys provide access to REST context information, + * enabling rich context access in service method implementations. + */ +public final class RestContextKeys_v0_3 { + + /** + * Context key for storing the headers. + */ + public static final String HEADERS_KEY = "headers"; + + /** + * Context key for storing the method name being called. + */ + public static final String METHOD_NAME_KEY = "method"; + + private RestContextKeys_v0_3() { + // Utility class + } +} diff --git a/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3.java b/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3.java new file mode 100644 index 000000000..39be61aee --- /dev/null +++ b/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3.java @@ -0,0 +1,451 @@ +package org.a2aproject.sdk.compat03.transport.rest.handler; + +import static org.a2aproject.sdk.server.util.async.AsyncUtils.createTubeConfig; + +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; +import org.a2aproject.sdk.compat03.grpc.utils.ProtoUtils_v0_3; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import java.util.List; +import java.util.concurrent.Flow; + +import org.a2aproject.sdk.server.ExtendedAgentCard; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AuthenticatedExtendedCardNotConfiguredError_v0_3; +import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; +import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskIdParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskPushNotificationConfig_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; +import org.a2aproject.sdk.server.util.async.Internal; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; +import org.a2aproject.sdk.compat03.conversion.ErrorConverter_v0_3; +import org.a2aproject.sdk.spec.A2AError; +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; + +@ApplicationScoped +public class RestHandler_v0_3 { + + private static final Logger log = Logger.getLogger(RestHandler_v0_3.class.getName()); + private AgentCard_v0_3 agentCard; + private @Nullable + Instance extendedAgentCard; + private Convert_v0_3_To10RequestHandler requestHandler; + private final Executor executor; + + @SuppressWarnings("NullAway") + protected RestHandler_v0_3() { + // For CDI + this.executor = null; + } + + @Inject + public RestHandler_v0_3(@PublicAgentCard AgentCard_v0_3 agentCard, @ExtendedAgentCard Instance extendedAgentCard, + @Internal Executor executor, Convert_v0_3_To10RequestHandler requestHandler) { + this.agentCard = agentCard; + this.extendedAgentCard = extendedAgentCard; + this.requestHandler = requestHandler; + this.executor = executor; + + // TODO: Port AgentCardValidator for v0.3 AgentCard or skip validation in compat layer + // AgentCardValidator.validateTransportConfiguration(agentCard); + } + + public RestHandler_v0_3(AgentCard_v0_3 agentCard, Executor executor, Convert_v0_3_To10RequestHandler requestHandler) { + this.agentCard = agentCard; + this.executor = executor; + this.requestHandler = requestHandler; + } + + public HTTPRestResponse sendMessage(String body, ServerCallContext context) { + try { + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.Builder request = org.a2aproject.sdk.compat03.grpc.SendMessageRequest.newBuilder(); + parseRequestBody(body, request); + EventKind_v0_3 result = requestHandler.onMessageSend(ProtoUtils_v0_3.FromProto.messageSendParams(request), context); + return createSuccessResponse(200, org.a2aproject.sdk.compat03.grpc.SendMessageResponse.newBuilder(ProtoUtils_v0_3.ToProto.taskOrMessage(result))); + } catch (A2AError e) { + return createErrorResponse(ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + return createErrorResponse(e); + } catch (Throwable throwable) { + return createErrorResponse(new InternalError_v0_3(throwable.getMessage())); + } + } + + public HTTPRestResponse sendStreamingMessage(String body, ServerCallContext context) { + try { + if (!agentCard.capabilities().streaming()) { + return createErrorResponse(new InvalidRequestError_v0_3("Streaming is not supported by the agent")); + } + org.a2aproject.sdk.compat03.grpc.SendMessageRequest.Builder request = org.a2aproject.sdk.compat03.grpc.SendMessageRequest.newBuilder(); + parseRequestBody(body, request); + Flow.Publisher publisher = requestHandler.onMessageSendStream(ProtoUtils_v0_3.FromProto.messageSendParams(request), context); + return createStreamingResponse(publisher); + } catch (A2AError e) { + return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(ErrorConverter_v0_3.convertA2AError(e)).toJson())); + } catch (JSONRPCError_v0_3 e) { + return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(e).toJson())); + } catch (Throwable throwable) { + return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(new InternalError_v0_3(throwable.getMessage())).toJson())); + } + } + + public HTTPRestResponse cancelTask(String taskId, ServerCallContext context) { + try { + if (taskId == null || taskId.isEmpty()) { + throw new InvalidParamsError_v0_3(); + } + TaskIdParams_v0_3 params = new TaskIdParams_v0_3(taskId); + Task_v0_3 task = requestHandler.onCancelTask(params, context); + if (task != null) { + return createSuccessResponse(200, org.a2aproject.sdk.compat03.grpc.Task.newBuilder(ProtoUtils_v0_3.ToProto.task(task))); + } + throw new UnsupportedOperationError_v0_3(); + } catch (A2AError e) { + return createErrorResponse(ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + return createErrorResponse(e); + } catch (Throwable throwable) { + return createErrorResponse(new InternalError_v0_3(throwable.getMessage())); + } + } + + public HTTPRestResponse setTaskPushNotificationConfiguration(String taskId, String body, ServerCallContext context) { + try { + if (!agentCard.capabilities().pushNotifications()) { + throw new PushNotificationNotSupportedError_v0_3(); + } + org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.Builder builder = org.a2aproject.sdk.compat03.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); + parseRequestBody(body, builder); + TaskPushNotificationConfig_v0_3 result = requestHandler.onSetTaskPushNotificationConfig(ProtoUtils_v0_3.FromProto.taskPushNotificationConfig(builder), context); + return createSuccessResponse(201, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils_v0_3.ToProto.taskPushNotificationConfig(result))); + } catch (A2AError e) { + return createErrorResponse(ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + return createErrorResponse(e); + } catch (Throwable throwable) { + return createErrorResponse(new InternalError_v0_3(throwable.getMessage())); + } + } + + public HTTPRestResponse resubscribeTask(String taskId, ServerCallContext context) { + try { + if (!agentCard.capabilities().streaming()) { + return createErrorResponse(new InvalidRequestError_v0_3("Streaming is not supported by the agent")); + } + TaskIdParams_v0_3 params = new TaskIdParams_v0_3(taskId); + Flow.Publisher publisher = requestHandler.onResubscribeToTask(params, context); + return createStreamingResponse(publisher); + } catch (A2AError e) { + return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(ErrorConverter_v0_3.convertA2AError(e)).toJson())); + } catch (JSONRPCError_v0_3 e) { + return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(e).toJson())); + } catch (Throwable throwable) { + return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(new InternalError_v0_3(throwable.getMessage())).toJson())); + } + } + + public HTTPRestResponse getTask(String taskId, int historyLength, ServerCallContext context) { + try { + TaskQueryParams_v0_3 params = new TaskQueryParams_v0_3(taskId, historyLength); + Task_v0_3 task = requestHandler.onGetTask(params, context); + if (task != null) { + return createSuccessResponse(200, org.a2aproject.sdk.compat03.grpc.Task.newBuilder(ProtoUtils_v0_3.ToProto.task(task))); + } + throw new TaskNotFoundError_v0_3(); + } catch (A2AError e) { + return createErrorResponse(ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + return createErrorResponse(e); + } catch (Throwable throwable) { + return createErrorResponse(new InternalError_v0_3(throwable.getMessage())); + } + } + + public HTTPRestResponse getTaskPushNotificationConfiguration(String taskId, @Nullable String configId, ServerCallContext context) { + try { + if (!agentCard.capabilities().pushNotifications()) { + throw new PushNotificationNotSupportedError_v0_3(); + } + GetTaskPushNotificationConfigParams_v0_3 params = new GetTaskPushNotificationConfigParams_v0_3(taskId, configId); + TaskPushNotificationConfig_v0_3 config = requestHandler.onGetTaskPushNotificationConfig(params, context); + return createSuccessResponse(200, org.a2aproject.sdk.compat03.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils_v0_3.ToProto.taskPushNotificationConfig(config))); + } catch (A2AError e) { + return createErrorResponse(ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + return createErrorResponse(e); + } catch (Throwable throwable) { + return createErrorResponse(new InternalError_v0_3(throwable.getMessage())); + } + } + + public HTTPRestResponse listTaskPushNotificationConfigurations(String taskId, ServerCallContext context) { + try { + if (!agentCard.capabilities().pushNotifications()) { + throw new PushNotificationNotSupportedError_v0_3(); + } + ListTaskPushNotificationConfigParams_v0_3 params = new ListTaskPushNotificationConfigParams_v0_3(taskId); + List configs = requestHandler.onListTaskPushNotificationConfig(params, context); + return createSuccessResponse(200, org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigResponse.newBuilder(ProtoUtils_v0_3.ToProto.listTaskPushNotificationConfigResponse(configs))); + } catch (A2AError e) { + return createErrorResponse(ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + return createErrorResponse(e); + } catch (Throwable throwable) { + return createErrorResponse(new InternalError_v0_3(throwable.getMessage())); + } + } + + public HTTPRestResponse deleteTaskPushNotificationConfiguration(String taskId, String configId, ServerCallContext context) { + try { + if (!agentCard.capabilities().pushNotifications()) { + throw new PushNotificationNotSupportedError_v0_3(); + } + DeleteTaskPushNotificationConfigParams_v0_3 params = new DeleteTaskPushNotificationConfigParams_v0_3(taskId, configId); + requestHandler.onDeleteTaskPushNotificationConfig(params, context); + return new HTTPRestResponse(204, "application/json", ""); + } catch (A2AError e) { + return createErrorResponse(ErrorConverter_v0_3.convertA2AError(e)); + } catch (JSONRPCError_v0_3 e) { + return createErrorResponse(e); + } catch (Throwable throwable) { + return createErrorResponse(new InternalError_v0_3(throwable.getMessage())); + } + } + + private void parseRequestBody(String body, com.google.protobuf.Message.Builder builder) throws JSONRPCError_v0_3 { + try { + if (body == null || body.trim().isEmpty()) { + throw new InvalidRequestError_v0_3("Request body is required"); + } + validate(body); + JsonFormat.parser().merge(body, builder); + } catch (InvalidProtocolBufferException e) { + log.log(Level.SEVERE, "Error parsing JSON request body: {0}", body); + log.log(Level.SEVERE, "Parse error details", e); + throw new InvalidParamsError_v0_3("Failed to parse request body: " + e.getMessage()); + } + } + + private void validate(String json) { + try { + JsonParser.parseString(json); + } catch (JsonSyntaxException e) { + throw new JSONParseError_v0_3(JSONParseError_v0_3.DEFAULT_CODE, "Failed to parse json", e.getMessage()); + } + } + + private HTTPRestResponse createSuccessResponse(int statusCode, com.google.protobuf.Message.Builder builder) { + try { + String jsonBody = JsonFormat.printer().print(builder); + return new HTTPRestResponse(statusCode, "application/json", jsonBody); + } catch (InvalidProtocolBufferException e) { + return createErrorResponse(new InternalError_v0_3("Failed to serialize response: " + e.getMessage())); + } + } + + public HTTPRestResponse createErrorResponse(JSONRPCError_v0_3 error) { + int statusCode = mapErrorToHttpStatus(error); + return createErrorResponse(statusCode, error); + } + + private HTTPRestResponse createErrorResponse(int statusCode, JSONRPCError_v0_3 error) { + String jsonBody = new HTTPRestErrorResponse(error).toJson(); + return new HTTPRestResponse(statusCode, "application/json", jsonBody); + } + + private HTTPRestStreamingResponse createStreamingResponse(Flow.Publisher publisher) { + return new HTTPRestStreamingResponse(convertToSendStreamingMessageResponse(publisher)); + } + + @SuppressWarnings("FutureReturnValueIgnored") + private Flow.Publisher convertToSendStreamingMessageResponse( + Flow.Publisher publisher) { + // We can't use the normal convertingProcessor since that propagates any errors as an error handled + // via Subscriber.onError() rather than as part of the SendStreamingResponse payload + return ZeroPublisher.create(createTubeConfig(), tube -> { + CompletableFuture.runAsync(() -> { + publisher.subscribe(new Flow.Subscriber() { + Flow.@Nullable Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(StreamingEventKind_v0_3 item) { + try { + String payload = JsonFormat.printer().omittingInsignificantWhitespace().print(ProtoUtils_v0_3.ToProto.taskOrMessageStream(item)); + tube.send(payload); + if (subscription != null) { + subscription.request(1); + } + } catch (InvalidProtocolBufferException ex) { + onError(ex); + } + } + + @Override + public void onError(Throwable throwable) { + if (throwable instanceof JSONRPCError_v0_3 jsonrpcError) { + tube.send(new HTTPRestErrorResponse(jsonrpcError).toJson()); + } else { + tube.send(new HTTPRestErrorResponse(new InternalError_v0_3(throwable.getMessage())).toJson()); + } + onComplete(); + } + + @Override + public void onComplete() { + tube.complete(); + } + }); + }, executor); + }); + } + + private int mapErrorToHttpStatus(JSONRPCError_v0_3 error) { + if (error instanceof InvalidRequestError_v0_3 || error instanceof JSONParseError_v0_3) { + return 400; + } + if (error instanceof InvalidParamsError_v0_3) { + return 422; + } + if (error instanceof MethodNotFoundError_v0_3 || error instanceof TaskNotFoundError_v0_3 || error instanceof AuthenticatedExtendedCardNotConfiguredError_v0_3) { + return 404; + } + if (error instanceof TaskNotCancelableError_v0_3) { + return 409; + } + if (error instanceof PushNotificationNotSupportedError_v0_3 || error instanceof UnsupportedOperationError_v0_3) { + return 501; + } + if (error instanceof ContentTypeNotSupportedError_v0_3) { + return 415; + } + if (error instanceof InvalidAgentResponseError_v0_3) { + return 502; + } + if (error instanceof InternalError_v0_3) { + return 500; + } + return 500; + } + + public HTTPRestResponse getAuthenticatedExtendedCard() { + try { + if (!agentCard.supportsAuthenticatedExtendedCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { + throw new AuthenticatedExtendedCardNotConfiguredError_v0_3(null, "Authenticated Extended Card not configured", null); + } + return new HTTPRestResponse(200, "application/json", JsonUtil_v0_3.toJson(extendedAgentCard.get())); + } catch (JSONRPCError_v0_3 e) { + return createErrorResponse(e); + } catch (Throwable t) { + return createErrorResponse(500, new InternalError_v0_3(t.getMessage())); + } + } + + public HTTPRestResponse getAgentCard() { + try { + return new HTTPRestResponse(200, "application/json", JsonUtil_v0_3.toJson(agentCard)); + } catch (Throwable t) { + return createErrorResponse(500, new InternalError_v0_3(t.getMessage())); + } + } + + public static class HTTPRestResponse { + + private final int statusCode; + private final String contentType; + private final String body; + + public HTTPRestResponse(int statusCode, String contentType, String body) { + this.statusCode = statusCode; + this.contentType = contentType; + this.body = body; + } + + public int getStatusCode() { + return statusCode; + } + + public String getContentType() { + return contentType; + } + + public String getBody() { + return body; + } + + @Override + public String toString() { + return "HTTPRestResponse{" + "statusCode=" + statusCode + ", contentType=" + contentType + ", body=" + body + '}'; + } + } + + public static class HTTPRestStreamingResponse extends HTTPRestResponse { + + private final Flow.Publisher publisher; + + public HTTPRestStreamingResponse(Flow.Publisher publisher) { + super(200, "text/event-stream", ""); + this.publisher = publisher; + } + + public Flow.Publisher getPublisher() { + return publisher; + } + } + + private static class HTTPRestErrorResponse { + + private final String error; + private final @Nullable + String message; + + private HTTPRestErrorResponse(JSONRPCError_v0_3 jsonRpcError) { + this.error = jsonRpcError.getClass().getName(); + this.message = jsonRpcError.getMessage(); + } + + private String toJson() { + return "{\"error\": \"" + error + "\", \"message\": \"" + message + "\"}"; + } + + @Override + public String toString() { + return "HTTPRestErrorResponse{" + "error=" + error + ", message=" + message + '}'; + } + } +} diff --git a/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/package-info.java b/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/package-info.java new file mode 100644 index 000000000..43cf2bd7d --- /dev/null +++ b/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package org.a2aproject.sdk.compat03.transport.rest.handler; + +import org.jspecify.annotations.NullMarked; diff --git a/compat-0.3/transport/rest/src/main/resources/META-INF/beans.xml b/compat-0.3/transport/rest/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..548d44b72 --- /dev/null +++ b/compat-0.3/transport/rest/src/main/resources/META-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java b/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java new file mode 100644 index 000000000..a76f2259d --- /dev/null +++ b/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java @@ -0,0 +1,376 @@ +package org.a2aproject.sdk.compat03.transport.rest.handler; + +import java.util.HashSet; +import java.util.Map; + +import org.a2aproject.sdk.compat03.conversion.AbstractA2ARequestHandlerTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +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.assertTrue; + +/** + * Test suite for v0.3 RestHandler with v1.0 backend. + *

            + * Tests verify that v0.3 REST clients can successfully communicate with the v1.0 backend + * via the {@link Convert_v0_3_To10RequestHandler} conversion layer. + *

            + *

            + * Phase 3 Focus: Core non-streaming tests (GetTask, SendMessage, CancelTask). + * Streaming tests are deferred to Phase 4. + *

            + */ +public class RestHandler_v0_3_Test extends AbstractA2ARequestHandlerTest_v0_3 { + + private final ServerCallContext callContext = new ServerCallContext( + UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + + // ======================================== + // GetTask Tests + // ======================================== + + @Test + public void testGetTaskSuccess() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save v0.3 task by converting to v1.0 + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + RestHandler_v0_3.HTTPRestResponse response = handler.getTask(MINIMAL_TASK.getId(), 0, callContext); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.getId())); + + // Test with different version parameter + response = handler.getTask(MINIMAL_TASK.getId(), 2, callContext); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.getId())); + } + + @Test + public void testGetTaskNotFound() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + RestHandler_v0_3.HTTPRestResponse response = handler.getTask("nonexistent", 0, callContext); + + Assertions.assertEquals(404, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains("TaskNotFoundError")); + } + + // ======================================== + // SendMessage Tests + // ======================================== + + @Test + public void testSendMessage() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Configure agent to echo the message back + agentExecutorExecute = (context, emitter) -> { + emitter.emitEvent(context.getMessage()); + }; + + String requestBody = """ + { + "message": + { + "messageId": "message-1234", + "contextId": "context-1234", + "role": "ROLE_USER", + "content": [{ + "text": "tell me a joke" + }], + "metadata": { + } + }, + "configuration": + { + "blocking": true + } + }"""; + + RestHandler_v0_3.HTTPRestResponse response = handler.sendMessage(requestBody, callContext); + + Assertions.assertEquals(200, response.getStatusCode(), response.toString()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertNotNull(response.getBody()); + } + + @Test + public void testSendMessageInvalidBody() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + String invalidBody = "invalid json"; + RestHandler_v0_3.HTTPRestResponse response = handler.sendMessage(invalidBody, callContext); + + Assertions.assertEquals(400, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains("JSONParseError"), response.getBody()); + } + + @Test + public void testSendMessageWrongValueBody() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Invalid role value "user" instead of "ROLE_USER" + String requestBody = """ + { + "message": + { + "messageId": "message-1234", + "contextId": "context-1234", + "role": "user", + "content": [{ + "text": "tell me a joke" + }], + "metadata": { + } + } + }"""; + + RestHandler_v0_3.HTTPRestResponse response = handler.sendMessage(requestBody, callContext); + + Assertions.assertEquals(422, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); + } + + @Test + public void testSendMessageEmptyBody() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + RestHandler_v0_3.HTTPRestResponse response = handler.sendMessage("", callContext); + + Assertions.assertEquals(400, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains("InvalidRequestError")); + } + + // ======================================== + // CancelTask Tests + // ======================================== + + @Test + public void testCancelTaskSuccess() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save v0.3 task by converting to v1.0 + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // Configure agent to cancel the task + agentExecutorCancel = (context, emitter) -> { + emitter.cancel(); + }; + + RestHandler_v0_3.HTTPRestResponse response = handler.cancelTask(MINIMAL_TASK.getId(), callContext); + + Assertions.assertEquals(200, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.getId())); + } + + @Test + public void testCancelTaskNotFound() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + RestHandler_v0_3.HTTPRestResponse response = handler.cancelTask("nonexistent", callContext); + + Assertions.assertEquals(404, response.getStatusCode()); + Assertions.assertEquals("application/json", response.getContentType()); + Assertions.assertTrue(response.getBody().contains("TaskNotFoundError")); + } + + // ======================================== + // Streaming Tests + // ======================================== + + @Test + public void testSendStreamingMessageSuccess() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Configure agent to emit the message back + agentExecutorExecute = (context, emitter) -> { + emitter.emitEvent(context.getMessage()); + }; + + String requestBody = """ + { + "message": { + "role": "ROLE_USER", + "content": [ + { + "text": "tell me some jokes" + } + ], + "messageId": "message-1234", + "contextId": "context-1234" + }, + "configuration": { + "acceptedOutputModes": ["text"] + } + }"""; + + RestHandler_v0_3.HTTPRestResponse response = handler.sendStreamingMessage(requestBody, callContext); + + // Verify streaming response + assertEquals(200, response.getStatusCode(), response.toString()); + assertInstanceOf(RestHandler_v0_3.HTTPRestStreamingResponse.class, response, + "Response should be HTTPRestStreamingResponse"); + + RestHandler_v0_3.HTTPRestStreamingResponse streamingResponse = + (RestHandler_v0_3.HTTPRestStreamingResponse) response; + assertNotNull(streamingResponse.getPublisher(), "Publisher should not be null"); + assertEquals("text/event-stream", streamingResponse.getContentType(), + "Content type should be text/event-stream for SSE"); + } + + @Test + public void testSendStreamingMessageNotSupported() { + // Create agent card with streaming disabled + AgentCard_v0_3 nonStreamingCard = new AgentCard_v0_3.Builder(CARD) + .capabilities(new AgentCapabilities_v0_3(false, true, false, null)) + .build(); + + RestHandler_v0_3 handler = new RestHandler_v0_3(nonStreamingCard, internalExecutor, convert03To10Handler); + + String requestBody = """ + { + "message": { + "contextId": "ctx123", + "role": "ROLE_USER", + "content": [{ + "text": "Hello" + }] + } + }"""; + + RestHandler_v0_3.HTTPRestResponse response = handler.sendStreamingMessage(requestBody, callContext); + + // Verify error response + assertEquals(400, response.getStatusCode(), "Should return 400 for streaming not supported"); + assertTrue(response.getBody().contains("InvalidRequestError"), + "Error should be InvalidRequestError"); + assertTrue(response.getBody().contains("Streaming is not supported by the agent"), + "Error message should indicate streaming not supported"); + } + + // ======================================== + // Push Notification Tests + // ======================================== + + @Test + public void testPushNotificationConfigSuccess() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + String requestBody = """ + { + "parent": "tasks/%s", + "config": { + "name": "tasks/%s/pushNotificationConfigs/", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": ["jwt"] + } + } + } + }""".formatted(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); + + RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), requestBody, callContext); + + assertEquals(201, response.getStatusCode(), response.toString()); + assertEquals("application/json", response.getContentType()); + assertNotNull(response.getBody()); + } + + @Test + public void testPushNotificationConfigNotSupported() { + AgentCard_v0_3 card = createAgentCard(true, false, false); + RestHandler_v0_3 handler = new RestHandler_v0_3(card, internalExecutor, convert03To10Handler); + + String requestBody = """ + { + "taskId": "%s", + "pushNotificationConfig": { + "url": "http://example.com" + } + } + """.formatted(MINIMAL_TASK.getId()); + + RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), requestBody, callContext); + + assertEquals(501, response.getStatusCode()); + assertTrue(response.getBody().contains("PushNotificationNotSupportedError")); + } + + @Test + public void testGetPushNotificationConfig() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + // First, create a push notification config + String createRequestBody = """ + { + "parent": "tasks/%s", + "config": { + "name": "tasks/%s/pushNotificationConfigs/", + "pushNotificationConfig": { + "url": "https://example.com/callback", + "authentication": { + "schemes": ["jwt"] + } + } + } + }""".formatted(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); + RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), createRequestBody, callContext); + assertEquals(201, response.getStatusCode(), response.toString()); + assertEquals("application/json", response.getContentType()); + + // Now get it (using taskId as configId since that's the default) + response = handler.getTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), MINIMAL_TASK.getId(), callContext); + assertEquals(200, response.getStatusCode(), response.toString()); + assertEquals("application/json", response.getContentType()); + } + + @Test + public void testDeletePushNotificationConfig() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + RestHandler_v0_3.HTTPRestResponse response = handler.deleteTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), MINIMAL_TASK.getId(), callContext); + assertEquals(204, response.getStatusCode()); + } + + @Test + public void testListPushNotificationConfigs() { + RestHandler_v0_3 handler = new RestHandler_v0_3(CARD, internalExecutor, convert03To10Handler); + + // Save task to v1.0 backend + taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); + + RestHandler_v0_3.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(MINIMAL_TASK.getId(), callContext); + + assertEquals(200, response.getStatusCode()); + assertEquals("application/json", response.getContentType()); + } +} diff --git a/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestTestTransportMetadata_v0_3.java b/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestTestTransportMetadata_v0_3.java new file mode 100644 index 000000000..65484b4ed --- /dev/null +++ b/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestTestTransportMetadata_v0_3.java @@ -0,0 +1,9 @@ +package org.a2aproject.sdk.compat03.transport.rest.handler; + +// TODO: Uncomment when server-common is ported + +/** + * Placeholder stub - awaiting server-common port. + */ +public class RestTestTransportMetadata_v0_3 { +} diff --git a/pom.xml b/pom.xml index b1d1da715..d2174f424 100644 --- a/pom.xml +++ b/pom.xml @@ -589,6 +589,9 @@ transport/grpc transport/rest + + compat-0.3 + boms/extras boms/reference diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/ServerCallContext.java b/server-common/src/main/java/org/a2aproject/sdk/server/ServerCallContext.java index aed6827ed..ff4652158 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/ServerCallContext.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/ServerCallContext.java @@ -15,6 +15,14 @@ public class ServerCallContext { */ public static final String TRANSPORT_KEY = "transport"; + /** + * Key for context ID validation mode in the state map. + * Value should be a {@link Boolean}. + * If true or absent, strict validation is enabled (v1.0 behavior). + * If false, context ID mismatch validation is skipped (v0.3 compatibility). + */ + public static final String STRICT_CONTEXT_VALIDATION_KEY = "strictContextValidation"; + // TODO Not totally sure yet about these field types private final Map modelConfig = new ConcurrentHashMap<>(); private final Map state; @@ -30,7 +38,8 @@ public ServerCallContext(User user, Map state, Set reque public ServerCallContext(User user, Map state, Set requestedExtensions, @Nullable String requestedProtocolVersion) { this.user = user; - this.state = state; + this.state = new ConcurrentHashMap<>(); + this.state.putAll(state); this.requestedExtensions = new HashSet<>(requestedExtensions); this.activatedExtensions = new HashSet<>(); // Always starts empty, populated later by application code this.requestedProtocolVersion = requestedProtocolVersion; diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java index 71aab7e94..b81cc22c7 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java @@ -1026,7 +1026,7 @@ private CompletableFuture cleanupProducer(@Nullable CompletableFuture Date: Wed, 29 Apr 2026 15:13:38 +0100 Subject: [PATCH 139/192] feat: Migrate compat-0.3 JSONRPC reference module from Reactive Routes to Vert.x Web Router Replace Quarkus Reactive Routes (@Route annotations) with Vert.x Web Router (@Observes Router) in the compat-0.3 JSONRPC reference module, matching the pattern established in the main reference modules (commit 8be6e407). Key changes: - Replace quarkus-reactive-routes dependency with a2a-java-sdk-reference-common in both JSONRPC and REST POMs (REST POM change is prep for next commit) - Use VertxSecurityHelper for authentication instead of @Authenticated annotation - Fix SSE race condition: subscribe synchronously instead of wrapping in executor.execute(), preventing 100-600ms delays that caused event loss - Replace MultiSseSupport inner class with improved version: close handler for client disconnect detection, setWriteQueueMaxSize(1) for anti-buffering, Cache-Control/X-Accel-Buffering headers - Use per-route BodyHandler instead of global to avoid ordering issues with test routes Co-Authored-By: Claude Opus 4.6 --- compat-0.3/reference/jsonrpc/pom.xml | 4 +- .../apps/quarkus/A2AServerRoutes_v0_3.java | 178 +++++++++--------- .../apps/quarkus/A2ATestRoutes_v0_3.java | 118 +++++++++--- compat-0.3/reference/rest/pom.xml | 4 +- 4 files changed, 190 insertions(+), 114 deletions(-) diff --git a/compat-0.3/reference/jsonrpc/pom.xml b/compat-0.3/reference/jsonrpc/pom.xml index 4bbd63ef4..69ca834ac 100644 --- a/compat-0.3/reference/jsonrpc/pom.xml +++ b/compat-0.3/reference/jsonrpc/pom.xml @@ -49,8 +49,8 @@ test - io.quarkus - quarkus-reactive-routes + ${project.groupId} + a2a-java-sdk-reference-common jakarta.enterprise diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java index e7fff4e8e..0aed736d4 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -10,28 +10,27 @@ 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; -import java.util.function.Function; +import jakarta.enterprise.event.Observes; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import jakarta.inject.Singleton; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; -import io.quarkus.security.Authenticated; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.ReactiveRoutes; -import io.quarkus.vertx.web.Route; +import io.quarkus.security.ForbiddenException; +import io.quarkus.security.UnauthorizedException; import io.smallrye.mutiny.Multi; import io.vertx.core.AsyncResult; import io.vertx.core.Handler; import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; import org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3; import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; @@ -64,8 +63,11 @@ import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.UnauthenticatedUser; import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.server.extensions.A2AExtensions; -import org.a2aproject.sdk.server.util.async.Internal; +import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @Singleton public class A2AServerRoutes_v0_3 { @@ -75,18 +77,48 @@ public class A2AServerRoutes_v0_3 { // Hook so testing can wait until the MultiSseSupport is subscribed. // Without this we get intermittent failures - private static volatile Runnable streamingMultiSseSupportSubscribedRunnable; + private static volatile @Nullable Runnable streamingMultiSseSupportSubscribedRunnable; @Inject - @Internal - Executor executor; + Instance callContextFactory; @Inject - Instance callContextFactory; + VertxSecurityHelper vertxSecurityHelper; + + void setupRoutes(@Observes Router router) { + // Main JSON-RPC endpoint: POST / + router.post("/") + .consumes(APPLICATION_JSON) + .handler(BodyHandler.create()) + .blockingHandler(ctx -> { + try { + vertxSecurityHelper.runInRequestContext(ctx, () -> { + invokeJSONRPCHandler(ctx.body().asString(), ctx); + }); + } catch (UnauthorizedException | ForbiddenException e) { + VertxSecurityHelper.handleAuthError(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }); - @Route(path = "/", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - @Authenticated - public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { + // Agent card endpoint: GET /.well-known/agent-card.json + router.get("/.well-known/agent-card.json") + .produces(APPLICATION_JSON) + .handler(ctx -> { + try { + String agentCard = JsonUtil_v0_3.toJson(jsonRpcHandler.getAgentCard()); + ctx.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(agentCard); + } catch (JsonProcessingException_v0_3 e) { + ctx.response().setStatusCode(500).end("Internal Server Error"); + } + }); + } + + public void invokeJSONRPCHandler(String body, RoutingContext rc) { boolean streaming = false; ServerCallContext context = createCallContext(rc); JSONRPCResponse_v0_3 nonStreamingResponse = null; @@ -150,12 +182,10 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { .putHeader(CONTENT_TYPE, APPLICATION_JSON) .end(Utils_v0_3.toJsonString(error)); } else if (streaming) { - final Multi> finalStreamingResponse = streamingResponse; - executor.execute(() -> { - MultiSseSupport.subscribeObject( - finalStreamingResponse.map(i -> (Object) i), rc); - }); - + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = streamingResponse + .map(response -> formatSseEvent(response, eventIdCounter.getAndIncrement())); + MultiSseSupport.writeSseStrings(sseEvents, rc, context); } else { rc.response() .setStatusCode(200) @@ -165,17 +195,8 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { } } - /** - * /** - * Handles incoming GET requests to the agent card endpoint. - * Returns the agent card in JSON format. - * - * @return the agent card - * @throws JsonProcessingException_v0_3 if serialization fails - */ - @Route(path = "/.well-known/agent-card.json", methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) - public String getAgentCard() throws JsonProcessingException_v0_3 { - return JsonUtil_v0_3.toJson(jsonRpcHandler.getAgentCard()); + private static String formatSseEvent(Object data, long id) { + return "data: " + Utils_v0_3.toJsonString(data) + "\nid: " + id + "\n\n"; } private NonStreamingJSONRPCRequest_v0_3 deserializeNonStreamingRequest(String body, String methodName) { @@ -276,9 +297,6 @@ public String getUsername() { }; } Map state = new HashMap<>(); - // TODO Python's impl has - // state['auth'] = request.auth - // in jsonrpc_app.py. Figure out what this maps to in what Vert.X gives us Map headers = new HashMap<>(); Set headerNames = rc.request().headers().names(); @@ -296,41 +314,30 @@ public String getUsername() { } } - // Port of import io.quarkus.vertx.web.runtime.MultiSseSupport, which is considered internal API private static class MultiSseSupport { + private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); private MultiSseSupport() { // Avoid direct instantiation. } - private static void initialize(HttpServerResponse response) { - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - response.setChunked(true); - } - } - - private static void onWriteDone(Flow.Subscription subscription, AsyncResult ar, RoutingContext rc) { - if (ar.failed()) { - rc.fail(ar.cause()); - } else { - subscription.request(1); - } - } - - public static void write(Multi multi, RoutingContext rc) { + public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { HttpServerResponse response = rc.response(); - multi.subscribe().withSubscriber(new Flow.Subscriber() { - Flow.Subscription upstream; + + sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { + Flow.@Nullable Subscription upstream; @Override public void onSubscribe(Flow.Subscription subscription) { this.upstream = subscription; this.upstream.request(1); + response.closeHandler(v -> { + logger.info("SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); + context.invokeEventConsumerCancelCallback(); + subscription.cancel(); + }); + // Notify tests that we are subscribed Runnable runnable = streamingMultiSseSupportSubscribedRunnable; if (runnable != null) { @@ -339,52 +346,49 @@ public void onSubscribe(Flow.Subscription subscription) { } @Override - public void onNext(Buffer item) { - initialize(response); - response.write(item, new Handler>() { + public void onNext(String sseEvent) { + if (response.bytesWritten() == 0) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + headers.set("Cache-Control", "no-cache"); + headers.set("X-Accel-Buffering", "no"); + response.setChunked(true); + response.setWriteQueueMaxSize(1); + response.write(": SSE stream started\n\n"); + } + + response.write(Buffer.buffer(sseEvent), new Handler>() { @Override public void handle(AsyncResult ar) { - onWriteDone(upstream, ar, rc); + if (ar.failed()) { + java.util.Objects.requireNonNull(upstream).cancel(); + rc.fail(ar.cause()); + } else { + java.util.Objects.requireNonNull(upstream).request(1); + } } }); } @Override public void onError(Throwable throwable) { + java.util.Objects.requireNonNull(upstream).cancel(); rc.fail(throwable); } @Override public void onComplete() { - endOfStream(response); - } - }); - } - - public static void subscribeObject(Multi multi, RoutingContext rc) { - AtomicLong count = new AtomicLong(); - write(multi.map(new Function() { - @Override - public Buffer apply(Object o) { - if (o instanceof ReactiveRoutes.ServerSentEvent) { - ReactiveRoutes.ServerSentEvent ev = (ReactiveRoutes.ServerSentEvent) o; - long id = ev.id() != -1 ? ev.id() : count.getAndIncrement(); - String e = ev.event() == null ? "" : "event: " + ev.event() + "\n"; - return Buffer.buffer(e + "data: " + Utils_v0_3.toJsonString(ev.data()) + "\nid: " + id + "\n\n"); + if (response.bytesWritten() == 0) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } } - return Buffer.buffer("data: " + Utils_v0_3.toJsonString(o) + "\nid: " + count.getAndIncrement() + "\n\n"); + response.end(); } - }), rc); - } - - private static void endOfStream(HttpServerResponse response) { - if (response.bytesWritten() == 0) { // No item - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); + }); } } } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2ATestRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2ATestRoutes_v0_3.java index 96b30d362..ab460d8b1 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2ATestRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2ATestRoutes_v0_3.java @@ -7,6 +7,7 @@ import java.util.concurrent.atomic.AtomicInteger; import jakarta.annotation.PostConstruct; +import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -16,13 +17,12 @@ import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Param; -import io.quarkus.vertx.web.Route; +import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; /** - * Exposes the {@link TestUtilsBean_v0_3} via REST using Quarkus Reactive Routes + * Exposes the {@link TestUtilsBean_v0_3} via REST using the Vert.x Web Router */ @Singleton public class A2ATestRoutes_v0_3 { @@ -39,9 +39,90 @@ public void init() { A2AServerRoutes_v0_3.setStreamingMultiSseSupportSubscribedRunnable(() -> streamingSubscribedCount.incrementAndGet()); } + void setupRoutes(@Observes Router router) { + // Save task: POST /test/task + router.post("/test/task") + .consumes(APPLICATION_JSON) + .handler(BodyHandler.create()) + .blockingHandler(ctx -> { + String body = ctx.body().asString(); + saveTask(body, ctx); + }); - @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void saveTask(@Body String body, RoutingContext rc) { + // Get task: GET /test/task/:taskId + router.get("/test/task/:taskId") + .produces(APPLICATION_JSON) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getTask(taskId, ctx); + }); + + // Delete task: DELETE /test/task/:taskId + router.delete("/test/task/:taskId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + deleteTask(taskId, ctx); + }); + + // Ensure task queue: POST /test/queue/ensure/:taskId + router.post("/test/queue/ensure/:taskId") + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + ensureTaskQueue(taskId, ctx); + }); + + // Enqueue task status update event: POST /test/queue/enqueueTaskStatusUpdateEvent/:taskId + router.post("/test/queue/enqueueTaskStatusUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + enqueueTaskStatusUpdateEvent(taskId, body, ctx); + }); + + // Enqueue task artifact update event: POST /test/queue/enqueueTaskArtifactUpdateEvent/:taskId + router.post("/test/queue/enqueueTaskArtifactUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + enqueueTaskArtifactUpdateEvent(taskId, body, ctx); + }); + + // Get streaming subscribed count: GET /test/streamingSubscribedCount + router.get("/test/streamingSubscribedCount") + .produces(TEXT_PLAIN) + .handler(ctx -> { + getStreamingSubscribedCount(ctx); + }); + + // Get child queue count: GET /test/queue/childCount/:taskId + router.get("/test/queue/childCount/:taskId") + .produces(TEXT_PLAIN) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getChildQueueCount(taskId, ctx); + }); + + // Delete task push notification config: DELETE /test/task/:taskId/config/:configId + router.delete("/test/task/:taskId/config/:configId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String configId = ctx.pathParam("configId"); + deleteTaskPushNotificationConfig(taskId, configId, ctx); + }); + + // Save task push notification config: POST /test/task/:taskId + router.post("/test/task/:taskId") + .handler(BodyHandler.create()) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + saveTaskPushNotificationConfig(taskId, body, ctx); + }); + } + + public void saveTask(String body, RoutingContext rc) { try { Task task = JsonUtil.fromJson(body, Task.class); testUtilsBean.saveTask(task); @@ -53,8 +134,7 @@ public void saveTask(@Body String body, RoutingContext rc) { } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void getTask(@Param String taskId, RoutingContext rc) { + public void getTask(String taskId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -73,8 +153,7 @@ public void getTask(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTask(@Param String taskId, RoutingContext rc) { + public void deleteTask(String taskId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -92,8 +171,7 @@ public void deleteTask(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) - public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { + public void ensureTaskQueue(String taskId, RoutingContext rc) { try { testUtilsBean.ensureQueue(taskId); rc.response() @@ -104,8 +182,7 @@ public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + public void enqueueTaskStatusUpdateEvent(String taskId, String body, RoutingContext rc) { try { TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); @@ -118,8 +195,7 @@ public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body } } - @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + public void enqueueTaskArtifactUpdateEvent(String taskId, String body, RoutingContext rc) { try { TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); @@ -132,23 +208,20 @@ public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String bo } } - @Route(path = "/test/streamingSubscribedCount", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) public void getStreamingSubscribedCount(RoutingContext rc) { rc.response() .setStatusCode(200) .end(String.valueOf(streamingSubscribedCount.get())); } - @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getChildQueueCount(@Param String taskId, RoutingContext rc) { + public void getChildQueueCount(String taskId, RoutingContext rc) { int count = testUtilsBean.getChildQueueCount(taskId); rc.response() .setStatusCode(200) .end(String.valueOf(count)); } - @Route(path = "/test/task/:taskId/config/:configId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String configId, RoutingContext rc) { + public void deleteTaskPushNotificationConfig(String taskId, String configId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -166,8 +239,7 @@ public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { + public void saveTaskPushNotificationConfig(String taskId, String body, RoutingContext rc) { try { TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); if (notificationConfig == null) { diff --git a/compat-0.3/reference/rest/pom.xml b/compat-0.3/reference/rest/pom.xml index 3677c6a51..e3f5d9f32 100644 --- a/compat-0.3/reference/rest/pom.xml +++ b/compat-0.3/reference/rest/pom.xml @@ -50,8 +50,8 @@ test - io.quarkus - quarkus-reactive-routes + ${project.groupId} + a2a-java-sdk-reference-common jakarta.enterprise From 31dcd09e8089abcc0103a9b8072974078d7b05e2 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 29 Apr 2026 15:50:07 +0100 Subject: [PATCH 140/192] feat: Migrate compat-0.3 REST reference module from Reactive Routes to Vert.x Web Router Replace @Route annotations with @Observes @Priority(10) Router pattern, add VertxSecurityHelper for manual authentication, fix SSE race condition with synchronous subscription, and add per-route BodyHandler. Move compat-0.3 reference modules from SDK BOM to Reference BOM since they depend on reference-common (VertxSecurityHelper), and update both BOM verifiers accordingly. Co-Authored-By: Claude Opus 4.6 --- boms/reference/pom.xml | 17 ++ .../src/it/reference-usage-test/pom.xml | 14 + .../sdk/test/ReferenceBomVerifier.java | 16 +- boms/sdk/pom.xml | 17 -- boms/sdk/src/it/sdk-usage-test/pom.xml | 14 - .../a2aproject/sdk/test/SdkBomVerifier.java | 13 +- .../rest/quarkus/A2AServerRoutes_v0_3.java | 287 ++++++++++-------- .../rest/quarkus/A2ATestRoutes_v0_3.java | 118 +++++-- 8 files changed, 308 insertions(+), 188 deletions(-) diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index f1efe016e..8243b6250 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -59,6 +59,23 @@ ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-grpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-rest + ${project.version} + + ${project.groupId} diff --git a/boms/reference/src/it/reference-usage-test/pom.xml b/boms/reference/src/it/reference-usage-test/pom.xml index a6bc0c32b..89c335295 100644 --- a/boms/reference/src/it/reference-usage-test/pom.xml +++ b/boms/reference/src/it/reference-usage-test/pom.xml @@ -56,6 +56,20 @@ a2a-java-sdk-reference-rest + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-grpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-rest + + org.a2aproject.sdk diff --git a/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java b/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java index d25473846..316cee850 100644 --- a/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java +++ b/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java @@ -12,13 +12,15 @@ public class ReferenceBomVerifier extends DynamicBomVerifier { private static final Set REFERENCE_EXCLUSIONS = Set.of( - "boms/", // BOM test modules themselves - "examples/", // Example applications - "tck/", // TCK test suite - "tests/", // Integration tests - "test-utils-docker/", // Test utilities for Docker-based tests - "compat-0.3/" // Compat 0.3 modules (part of SDK BOM, not reference BOM) - // Note: reference/ is NOT in this list - we want to verify those classes load + "boms/", // BOM test modules themselves + "examples/", // Example applications + "tck/", // TCK test suite + "tests/", // Integration tests + "test-utils-docker/", // Test utilities for Docker-based tests + "compat-0.3/client/", // Compat 0.3 client modules (part of SDK BOM) + "compat-0.3/http-client/", // Compat 0.3 HTTP client (part of SDK BOM) + "compat-0.3/tck/" // Compat 0.3 TCK (not yet enabled) + // Note: reference/ and compat-0.3/reference/ are NOT excluded - we verify those classes load ); private static final Set REFERENCE_FORBIDDEN = Set.of( diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index d901f680d..149ebd6d3 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -171,23 +171,6 @@ ${project.version} - - - ${project.groupId} - a2a-java-sdk-compat-0.3-reference-jsonrpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-compat-0.3-reference-grpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-compat-0.3-reference-rest - ${project.version} - - ${project.groupId} diff --git a/boms/sdk/src/it/sdk-usage-test/pom.xml b/boms/sdk/src/it/sdk-usage-test/pom.xml index 3d158598b..851f98ea9 100644 --- a/boms/sdk/src/it/sdk-usage-test/pom.xml +++ b/boms/sdk/src/it/sdk-usage-test/pom.xml @@ -155,20 +155,6 @@ a2a-java-sdk-compat-0.3-transport-rest - - - org.a2aproject.sdk - a2a-java-sdk-compat-0.3-reference-jsonrpc - - - org.a2aproject.sdk - a2a-java-sdk-compat-0.3-reference-grpc - - - org.a2aproject.sdk - a2a-java-sdk-compat-0.3-reference-rest - - org.slf4j diff --git a/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java b/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java index 7f0607b8d..6fb7aefca 100644 --- a/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java +++ b/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java @@ -12,12 +12,13 @@ public class SdkBomVerifier extends DynamicBomVerifier { private static final Set SDK_EXCLUSIONS = Set.of( - "boms/", // BOM test modules themselves - "examples/", // Example applications - "tck/", // TCK test suite - "compat-0.3/tck/", // Compat 0.3 TCK (not yet enabled) - "tests/", // Integration tests - "test-utils-docker/" // Test utilities for Docker-based tests + "boms/", // BOM test modules themselves + "examples/", // Example applications + "tck/", // TCK test suite + "compat-0.3/tck/", // Compat 0.3 TCK (not yet enabled) + "compat-0.3/reference/", // Compat 0.3 reference implementations (in reference BOM) + "tests/", // Integration tests + "test-utils-docker/" // Test utilities for Docker-based tests ); private static final Set SDK_FORBIDDEN = Set.of( diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java index 7e424dcfa..f086f9ce0 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -1,35 +1,44 @@ package org.a2aproject.sdk.compat03.server.rest.quarkus; -import static org.a2aproject.sdk.compat03.transport.rest.context.RestContextKeys_v0_3.HEADERS_KEY; -import static org.a2aproject.sdk.compat03.transport.rest.context.RestContextKeys_v0_3.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 static org.a2aproject.sdk.compat03.transport.rest.context.RestContextKeys_v0_3.HEADERS_KEY; +import static org.a2aproject.sdk.compat03.transport.rest.context.RestContextKeys_v0_3.METHOD_NAME_KEY; -import java.util.concurrent.Executor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Function; +import java.util.function.Consumer; -import jakarta.annotation.security.PermitAll; +import jakarta.annotation.Priority; +import jakarta.enterprise.event.Observes; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import jakarta.inject.Singleton; +import io.quarkus.security.ForbiddenException; +import io.quarkus.security.UnauthorizedException; +import io.smallrye.mutiny.Multi; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; import org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3; -import org.a2aproject.sdk.server.ServerCallContext; -import org.a2aproject.sdk.server.auth.UnauthenticatedUser; -import org.a2aproject.sdk.server.auth.User; -import org.a2aproject.sdk.server.util.async.Internal; -import org.a2aproject.sdk.server.extensions.A2AExtensions; -import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; -import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; -import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; -import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; import org.a2aproject.sdk.compat03.spec.GetTaskRequest_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigRequest_v0_3; import org.a2aproject.sdk.compat03.spec.SendMessageRequest_v0_3; import org.a2aproject.sdk.compat03.spec.SendStreamingMessageRequest_v0_3; @@ -38,25 +47,16 @@ import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3; import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3.HTTPRestResponse; import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3.HTTPRestStreamingResponse; -import io.quarkus.security.Authenticated; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.ReactiveRoutes; -import io.quarkus.vertx.web.Route; -import io.smallrye.mutiny.Multi; -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -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 org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; +import org.a2aproject.sdk.server.extensions.A2AExtensions; import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @Singleton -@Authenticated public class A2AServerRoutes_v0_3 { @Inject @@ -67,14 +67,90 @@ public class A2AServerRoutes_v0_3 { private static volatile @Nullable Runnable streamingMultiSseSupportSubscribedRunnable; @Inject - @Internal - Executor executor; + Instance callContextFactory; @Inject - Instance callContextFactory; + VertxSecurityHelper vertxSecurityHelper; + + void setupRouter(@Observes @Priority(10) Router router) { + // POST /v1/message:send + router.postWithRegex("^\\/v1\\/message:send$") + .handler(BodyHandler.create()) + .blockingHandler(authenticated(ctx -> { + sendMessage(extractBody(ctx), ctx); + })); + + // POST /v1/message:stream + router.postWithRegex("^\\/v1\\/message:stream$") + .handler(BodyHandler.create()) + .blockingHandler(authenticated(ctx -> { + sendMessageStreaming(extractBody(ctx), ctx); + })); + + // GET /v1/tasks/:id + router.get("/v1/tasks/:id") + .order(1) + .blockingHandler(authenticated(this::getTask)); + + // POST /v1/tasks/{id}:cancel + router.postWithRegex("^\\/v1\\/tasks\\/([^/]+):cancel$") + .order(1) + .blockingHandler(authenticated(this::cancelTask)); + + // POST /v1/tasks/{id}:subscribe + router.postWithRegex("^\\/v1\\/tasks\\/([^/]+):subscribe$") + .order(1) + .blockingHandler(authenticated(this::resubscribeTask)); + + // POST /v1/tasks/:id/pushNotificationConfigs + router.post("/v1/tasks/:id/pushNotificationConfigs") + .order(1) + .handler(BodyHandler.create()) + .blockingHandler(authenticated(ctx -> { + setTaskPushNotificationConfiguration(extractBody(ctx), ctx); + })); + + // GET /v1/tasks/:id/pushNotificationConfigs/:configId + router.get("/v1/tasks/:id/pushNotificationConfigs/:configId") + .order(1) + .blockingHandler(authenticated(this::getTaskPushNotificationConfiguration)); + + // GET /v1/tasks/:id/pushNotificationConfigs + router.get("/v1/tasks/:id/pushNotificationConfigs") + .order(2) + .blockingHandler(authenticated(this::listTaskPushNotificationConfigurations)); + + // DELETE /v1/tasks/:id/pushNotificationConfigs/:configId + router.delete("/v1/tasks/:id/pushNotificationConfigs/:configId") + .order(1) + .blockingHandler(authenticated(this::deleteTaskPushNotificationConfiguration)); + + // GET /.well-known/agent-card.json - public + router.get("/.well-known/agent-card.json") + .order(1) + .produces(APPLICATION_JSON) + .handler(this::getAgentCard); + + // GET /v1/card - authenticated + router.get("/v1/card") + .order(1) + .produces(APPLICATION_JSON) + .blockingHandler(authenticated(this::getAuthenticatedExtendedCard)); + } + + private Handler authenticated(Consumer action) { + return ctx -> { + try { + vertxSecurityHelper.runInRequestContext(ctx, () -> action.accept(ctx)); + } catch (UnauthorizedException | ForbiddenException e) { + VertxSecurityHelper.handleAuthError(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }; + } - @Route(regex = "^/v1/message:send$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void sendMessage(@Body String body, RoutingContext rc) { + public void sendMessage(String body, RoutingContext rc) { ServerCallContext context = createCallContext(rc, SendMessageRequest_v0_3.METHOD); HTTPRestResponse response = null; try { @@ -86,8 +162,7 @@ public void sendMessage(@Body String body, RoutingContext rc) { } } - @Route(regex = "^/v1/message:stream$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void sendMessageStreaming(@Body String body, RoutingContext rc) { + public void sendMessageStreaming(String body, RoutingContext rc) { ServerCallContext context = createCallContext(rc, SendStreamingMessageRequest_v0_3.METHOD); HTTPRestStreamingResponse streamingResponse = null; HTTPRestResponse error = null; @@ -102,16 +177,14 @@ public void sendMessageStreaming(@Body String body, RoutingContext rc) { if (error != null) { sendResponse(rc, error); } else if (streamingResponse != null) { - Multi events = Multi.createFrom().publisher(streamingResponse.getPublisher()); - executor.execute(() -> { - MultiSseSupport.subscribeObject( - events.map(i -> (Object) i), rc); - }); + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = Multi.createFrom().publisher(streamingResponse.getPublisher()) + .map(json -> formatSseEvent(json, eventIdCounter.getAndIncrement())); + MultiSseSupport.writeSseStrings(sseEvents, rc, context); } } } - @Route(path = "/v1/tasks/:id", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void getTask(RoutingContext rc) { String taskId = rc.pathParam("id"); ServerCallContext context = createCallContext(rc, GetTaskRequest_v0_3.METHOD); @@ -146,7 +219,6 @@ public void getTask(RoutingContext rc) { } } - @Route(regex = "^/v1/tasks/([^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void cancelTask(RoutingContext rc) { String taskId = rc.pathParam("param0"); ServerCallContext context = createCallContext(rc, CancelTaskRequest_v0_3.METHOD); @@ -179,7 +251,6 @@ private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response } } - @Route(regex = "^/v1/tasks/([^/]+):subscribe$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void resubscribeTask(RoutingContext rc) { String taskId = rc.pathParam("param0"); ServerCallContext context = createCallContext(rc, TaskResubscriptionRequest_v0_3.METHOD); @@ -200,17 +271,15 @@ public void resubscribeTask(RoutingContext rc) { if (error != null) { sendResponse(rc, error); } else if (streamingResponse != null) { - Multi events = Multi.createFrom().publisher(streamingResponse.getPublisher()); - executor.execute(() -> { - MultiSseSupport.subscribeObject( - events.map(i -> (Object) i), rc); - }); + AtomicLong eventIdCounter = new AtomicLong(0); + Multi sseEvents = Multi.createFrom().publisher(streamingResponse.getPublisher()) + .map(json -> formatSseEvent(json, eventIdCounter.getAndIncrement())); + MultiSseSupport.writeSseStrings(sseEvents, rc, context); } } } - @Route(path = "/v1/tasks/:id/pushNotificationConfigs", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void setTaskPushNotificationConfiguration(@Body String body, RoutingContext rc) { + public void setTaskPushNotificationConfiguration(String body, RoutingContext rc) { String taskId = rc.pathParam("id"); ServerCallContext context = createCallContext(rc, SetTaskPushNotificationConfigRequest_v0_3.METHOD); HTTPRestResponse response = null; @@ -227,7 +296,6 @@ public void setTaskPushNotificationConfiguration(@Body String body, RoutingConte } } - @Route(path = "/v1/tasks/:id/pushNotificationConfigs/:configId", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void getTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("id"); String configId = rc.pathParam("configId"); @@ -246,7 +314,6 @@ public void getTaskPushNotificationConfiguration(RoutingContext rc) { } } - @Route(path = "/v1/tasks/:id/pushNotificationConfigs", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void listTaskPushNotificationConfigurations(RoutingContext rc) { String taskId = rc.pathParam("id"); ServerCallContext context = createCallContext(rc, ListTaskPushNotificationConfigRequest_v0_3.METHOD); @@ -264,7 +331,6 @@ public void listTaskPushNotificationConfigurations(RoutingContext rc) { } } - @Route(path = "/v1/tasks/:id/pushNotificationConfigs/:configId", order = 1, methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("id"); String configId = rc.pathParam("configId"); @@ -285,29 +351,23 @@ public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { } } - /** - * Handles incoming GET requests to the agent card endpoint. - * Returns the agent card in JSON format. - * - * @param rc the routing context - */ - @Route(path = "/.well-known/agent-card.json", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) - @PermitAll public void getAgentCard(RoutingContext rc) { HTTPRestResponse response = jsonRestHandler.getAgentCard(); sendResponse(rc, response); } - @Route(path = "/v1/card", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) public void getAuthenticatedExtendedCard(RoutingContext rc) { HTTPRestResponse response = jsonRestHandler.getAuthenticatedExtendedCard(); sendResponse(rc, response); } - @Route(path = "^/v1/.*", order = 100, methods = {Route.HttpMethod.DELETE, Route.HttpMethod.GET, Route.HttpMethod.HEAD, Route.HttpMethod.OPTIONS, Route.HttpMethod.POST, Route.HttpMethod.PUT}, produces = APPLICATION_JSON) - public void methodNotFoundMessage(RoutingContext rc) { - HTTPRestResponse response = jsonRestHandler.createErrorResponse(new MethodNotFoundError_v0_3()); - sendResponse(rc, response); + private static String extractBody(RoutingContext rc) { + String body = rc.body().asString(); + return body != null ? body : ""; + } + + private static String formatSseEvent(String data, long id) { + return "data: " + data + "\nid: " + id + "\n\n"; } static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { @@ -358,34 +418,17 @@ public String getUsername() { } } - // Port of import io.quarkus.vertx.web.runtime.MultiSseSupport, which is considered internal API private static class MultiSseSupport { + private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); private MultiSseSupport() { // Avoid direct instantiation. } - private static void initialize(HttpServerResponse response) { - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - response.setChunked(true); - } - } - - private static void onWriteDone(Flow.@Nullable Subscription subscription, AsyncResult ar, RoutingContext rc) { - if (ar.failed()) { - rc.fail(ar.cause()); - } else if (subscription != null) { - subscription.request(1); - } - } - - private static void write(Multi multi, RoutingContext rc) { + public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { HttpServerResponse response = rc.response(); - multi.subscribe().withSubscriber(new Flow.Subscriber() { + + sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { Flow.@Nullable Subscription upstream; @Override @@ -393,6 +436,12 @@ public void onSubscribe(Flow.Subscription subscription) { this.upstream = subscription; this.upstream.request(1); + response.closeHandler(v -> { + logger.info("REST SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); + context.invokeEventConsumerCancelCallback(); + subscription.cancel(); + }); + // Notify tests that we are subscribed Runnable runnable = streamingMultiSseSupportSubscribedRunnable; if (runnable != null) { @@ -401,53 +450,49 @@ public void onSubscribe(Flow.Subscription subscription) { } @Override - public void onNext(Buffer item) { - initialize(response); - response.write(item, new Handler>() { + public void onNext(String sseEvent) { + if (response.bytesWritten() == 0) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + headers.set("Cache-Control", "no-cache"); + headers.set("X-Accel-Buffering", "no"); + response.setChunked(true); + response.setWriteQueueMaxSize(1); + response.write(": SSE stream started\n\n"); + } + + response.write(Buffer.buffer(sseEvent), new Handler>() { @Override public void handle(AsyncResult ar) { - onWriteDone(upstream, ar, rc); + if (ar.failed()) { + java.util.Objects.requireNonNull(upstream).cancel(); + rc.fail(ar.cause()); + } else { + java.util.Objects.requireNonNull(upstream).request(1); + } } }); } @Override public void onError(Throwable throwable) { + java.util.Objects.requireNonNull(upstream).cancel(); rc.fail(throwable); } @Override public void onComplete() { - endOfStream(response); - } - }); - } - - private static void subscribeObject(Multi multi, RoutingContext rc) { - AtomicLong count = new AtomicLong(); - write(multi.map(new Function() { - @Override - public Buffer apply(Object o) { - if (o instanceof ReactiveRoutes.ServerSentEvent) { - ReactiveRoutes.ServerSentEvent ev = (ReactiveRoutes.ServerSentEvent) o; - long id = ev.id() != -1 ? ev.id() : count.getAndIncrement(); - String e = ev.event() == null ? "" : "event: " + ev.event() + "\n"; - return Buffer.buffer(e + "data: " + ev.data() + "\nid: " + id + "\n\n"); - } else { - return Buffer.buffer("data: " + o + "\nid: " + count.getAndIncrement() + "\n\n"); + if (response.bytesWritten() == 0) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } } + response.end(); } - }), rc); - } - - private static void endOfStream(HttpServerResponse response) { - if (response.bytesWritten() == 0) { // No item - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); + }); } } } diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2ATestRoutes_v0_3.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2ATestRoutes_v0_3.java index 33f0586aa..753cca76f 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2ATestRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2ATestRoutes_v0_3.java @@ -7,6 +7,7 @@ import java.util.concurrent.atomic.AtomicInteger; import jakarta.annotation.PostConstruct; +import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -16,13 +17,12 @@ import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Param; -import io.quarkus.vertx.web.Route; +import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; /** - * Exposes the {@link TestUtilsBean_v0_3} via REST using Quarkus Reactive Routes + * Exposes the {@link TestUtilsBean_v0_3} via REST using the Vert.x Web Router */ @Singleton public class A2ATestRoutes_v0_3 { @@ -39,9 +39,90 @@ public void init() { A2AServerRoutes_v0_3.setStreamingMultiSseSupportSubscribedRunnable(() -> streamingSubscribedCount.incrementAndGet()); } + void setupRoutes(@Observes Router router) { + // Save task: POST /test/task + router.post("/test/task") + .consumes(APPLICATION_JSON) + .handler(BodyHandler.create()) + .blockingHandler(ctx -> { + String body = ctx.body().asString(); + saveTask(body, ctx); + }); - @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void saveTask(@Body String body, RoutingContext rc) { + // Get task: GET /test/task/:taskId + router.get("/test/task/:taskId") + .produces(APPLICATION_JSON) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getTask(taskId, ctx); + }); + + // Delete task: DELETE /test/task/:taskId + router.delete("/test/task/:taskId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + deleteTask(taskId, ctx); + }); + + // Ensure task queue: POST /test/queue/ensure/:taskId + router.post("/test/queue/ensure/:taskId") + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + ensureTaskQueue(taskId, ctx); + }); + + // Enqueue task status update event: POST /test/queue/enqueueTaskStatusUpdateEvent/:taskId + router.post("/test/queue/enqueueTaskStatusUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + enqueueTaskStatusUpdateEvent(taskId, body, ctx); + }); + + // Enqueue task artifact update event: POST /test/queue/enqueueTaskArtifactUpdateEvent/:taskId + router.post("/test/queue/enqueueTaskArtifactUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + enqueueTaskArtifactUpdateEvent(taskId, body, ctx); + }); + + // Get streaming subscribed count: GET /test/streamingSubscribedCount + router.get("/test/streamingSubscribedCount") + .produces(TEXT_PLAIN) + .handler(ctx -> { + getStreamingSubscribedCount(ctx); + }); + + // Get child queue count: GET /test/queue/childCount/:taskId + router.get("/test/queue/childCount/:taskId") + .produces(TEXT_PLAIN) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getChildQueueCount(taskId, ctx); + }); + + // Delete task push notification config: DELETE /test/task/:taskId/config/:configId + router.delete("/test/task/:taskId/config/:configId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String configId = ctx.pathParam("configId"); + deleteTaskPushNotificationConfig(taskId, configId, ctx); + }); + + // Save task push notification config: POST /test/task/:taskId + router.post("/test/task/:taskId") + .handler(BodyHandler.create()) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + saveTaskPushNotificationConfig(taskId, body, ctx); + }); + } + + public void saveTask(String body, RoutingContext rc) { try { Task task = JsonUtil.fromJson(body, Task.class); testUtilsBean.saveTask(task); @@ -53,8 +134,7 @@ public void saveTask(@Body String body, RoutingContext rc) { } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void getTask(@Param String taskId, RoutingContext rc) { + public void getTask(String taskId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -73,8 +153,7 @@ public void getTask(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTask(@Param String taskId, RoutingContext rc) { + public void deleteTask(String taskId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -92,8 +171,7 @@ public void deleteTask(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) - public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { + public void ensureTaskQueue(String taskId, RoutingContext rc) { try { testUtilsBean.ensureQueue(taskId); rc.response() @@ -104,8 +182,7 @@ public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { } } - @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + public void enqueueTaskStatusUpdateEvent(String taskId, String body, RoutingContext rc) { try { TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); @@ -118,8 +195,7 @@ public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body } } - @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { + public void enqueueTaskArtifactUpdateEvent(String taskId, String body, RoutingContext rc) { try { TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); @@ -132,23 +208,20 @@ public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String bo } } - @Route(path = "/test/streamingSubscribedCount", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) public void getStreamingSubscribedCount(RoutingContext rc) { rc.response() .setStatusCode(200) .end(String.valueOf(streamingSubscribedCount.get())); } - @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getChildQueueCount(@Param String taskId, RoutingContext rc) { + public void getChildQueueCount(String taskId, RoutingContext rc) { int count = testUtilsBean.getChildQueueCount(taskId); rc.response() .setStatusCode(200) .end(String.valueOf(count)); } - @Route(path = "/test/task/:taskId/config/:configId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String configId, RoutingContext rc) { + public void deleteTaskPushNotificationConfig(String taskId, String configId, RoutingContext rc) { try { Task task = testUtilsBean.getTask(taskId); if (task == null) { @@ -166,8 +239,7 @@ public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String } } - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { + public void saveTaskPushNotificationConfig(String taskId, String body, RoutingContext rc) { try { TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); if (notificationConfig == null) { From d7ba05555cc1eeec5f2abc43f050cf29667fb9bd Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 29 Apr 2026 16:47:46 +0100 Subject: [PATCH 141/192] feat: Add security tests for compat-0.3 JSONRPC reference module - Add HTTP Basic auth support to AuthInterceptor_v0_3 (matching v1.0) - Add @Authenticated annotations to compat-0.3 JSONRPC and REST route handler methods for security enforcement - Update AgentCardProducer_v0_3 to conditionally include security schemes when test.agent.security.enabled=true - Create AbstractA2AServerWithAuthTest_v0_3 base class in server-conversion with v0.3 client types - Add JSONRPC auth test (QuarkusA2AJSONRPC_v0_3_WithAuthTest) with AuthTestProfile, TestIdentityProvider, and security dependencies - Add security config to JSONRPC application.properties Co-Authored-By: Claude Opus 4.6 --- .../auth/AuthInterceptor_v0_3.java | 12 +- compat-0.3/reference/jsonrpc/pom.xml | 16 ++ .../apps/quarkus/A2AServerRoutes_v0_3.java | 2 + .../apps/quarkus/AuthTestProfile_v0_3.java | 36 +++ .../QuarkusA2AJSONRPC_v0_3_WithAuthTest.java | 45 ++++ .../quarkus/TestIdentityProvider_v0_3.java | 29 +++ .../src/test/resources/application.properties | 7 + .../rest/quarkus/A2AServerRoutes_v0_3.java | 11 + .../AbstractA2AServerWithAuthTest_v0_3.java | 241 ++++++++++++++++++ .../conversion/AgentCardProducer_v0_3.java | 28 +- 10 files changed, 422 insertions(+), 5 deletions(-) create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/AuthTestProfile_v0_3.java create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/TestIdentityProvider_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerWithAuthTest_v0_3.java diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java index 82d1f0739..cf28b4f03 100644 --- a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java @@ -23,8 +23,10 @@ public class AuthInterceptor_v0_3 extends ClientCallInterceptor_v0_3 { private static final String BEARER_SCHEME = "bearer"; + private static final String BASIC_SCHEME = "basic"; public static final String AUTHORIZATION = "Authorization"; private static final String BEARER = "Bearer "; + private static final String BASIC = "Basic "; private final CredentialService_v0_3 credentialService; public AuthInterceptor_v0_3(final CredentialService_v0_3 credentialService) { @@ -47,9 +49,13 @@ public PayloadAndHeaders_v0_3 intercept(String methodName, @Nullable Object payl continue; } if (securityScheme instanceof HTTPAuthSecurityScheme_v0_3 httpAuthSecurityScheme) { - if (httpAuthSecurityScheme.getScheme().toLowerCase(Locale.ROOT).equals(BEARER_SCHEME)) { + String scheme = httpAuthSecurityScheme.getScheme().toLowerCase(Locale.ROOT); + if (scheme.equals(BEARER_SCHEME)) { updatedHeaders.put(AUTHORIZATION, getBearerValue(credential)); return new PayloadAndHeaders_v0_3(payload, updatedHeaders); + } else if (scheme.equals(BASIC_SCHEME)) { + updatedHeaders.put(AUTHORIZATION, getBasicValue(credential)); + return new PayloadAndHeaders_v0_3(payload, updatedHeaders); } } else if (securityScheme instanceof OAuth2SecurityScheme_v0_3 || securityScheme instanceof OpenIdConnectSecurityScheme_v0_3) { @@ -68,4 +74,8 @@ public PayloadAndHeaders_v0_3 intercept(String methodName, @Nullable Object payl private static String getBearerValue(String credential) { return BEARER + credential; } + + private static String getBasicValue(String credential) { + return BASIC + credential; + } } diff --git a/compat-0.3/reference/jsonrpc/pom.xml b/compat-0.3/reference/jsonrpc/pom.xml index 69ca834ac..34876a7a6 100644 --- a/compat-0.3/reference/jsonrpc/pom.xml +++ b/compat-0.3/reference/jsonrpc/pom.xml @@ -94,6 +94,22 @@ mockito-junit-jupiter test + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java index 0aed736d4..8de1e304f 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -20,6 +20,7 @@ import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; +import io.quarkus.security.Authenticated; import io.quarkus.security.ForbiddenException; import io.quarkus.security.UnauthorizedException; import io.smallrye.mutiny.Multi; @@ -118,6 +119,7 @@ void setupRoutes(@Observes Router router) { }); } + @Authenticated public void invokeJSONRPCHandler(String body, RoutingContext rc) { boolean streaming = false; ServerCallContext context = createCallContext(rc); diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/AuthTestProfile_v0_3.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/AuthTestProfile_v0_3.java new file mode 100644 index 000000000..348dffa3f --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/AuthTestProfile_v0_3.java @@ -0,0 +1,36 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class AuthTestProfile_v0_3 implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + // Disable the TestIdentityProvider - we want real authentication + Map.entry("test.identity.auto-auth", "false"), + + // Enable security in AgentCard (server advertises Basic Auth support) + Map.entry("test.agent.security.enabled", "true"), + + // Enable embedded user store + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + + // Enable HTTP Basic authentication + Map.entry("quarkus.http.auth.basic", "true"), + + // Enable proactive authentication - authenticate at HTTP layer before route handler + Map.entry("quarkus.http.auth.proactive", "true") + ); + } + + @Override + public String getConfigProfile() { + return "test"; + } +} diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java new file mode 100644 index 000000000..1ef8b516f --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java @@ -0,0 +1,45 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +@QuarkusTest +@TestProfile(AuthTestProfile_v0_3.class) +public class QuarkusA2AJSONRPC_v0_3_WithAuthTest extends AbstractA2AServerWithAuthTest_v0_3 { + + public QuarkusA2AJSONRPC_v0_3_WithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3() + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); + } +} diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/TestIdentityProvider_v0_3.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/TestIdentityProvider_v0_3.java new file mode 100644 index 000000000..40ff22620 --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/TestIdentityProvider_v0_3.java @@ -0,0 +1,29 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.quarkus.arc.Unremovable; +import io.quarkus.arc.properties.IfBuildProperty; +import io.quarkus.security.identity.AuthenticationRequestContext; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.identity.SecurityIdentityAugmentor; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; + +@ApplicationScoped +@Unremovable +@IfBuildProperty(name = "test.identity.auto-auth", stringValue = "true", enableIfMissing = true) +public class TestIdentityProvider_v0_3 implements SecurityIdentityAugmentor { + + @Override + public Uni augment(SecurityIdentity identity, AuthenticationRequestContext context) { + if (identity.isAnonymous()) { + return Uni.createFrom().item(QuarkusSecurityIdentity.builder() + .setPrincipal(() -> "testuser") + .addRole("user") + .setAnonymous(false) + .build()); + } + return Uni.createFrom().item(identity); + } +} diff --git a/compat-0.3/reference/jsonrpc/src/test/resources/application.properties b/compat-0.3/reference/jsonrpc/src/test/resources/application.properties index f7b5a7d9f..79f484467 100644 --- a/compat-0.3/reference/jsonrpc/src/test/resources/application.properties +++ b/compat-0.3/reference/jsonrpc/src/test/resources/application.properties @@ -10,3 +10,10 @@ quarkus.arc.selected-alternatives=org.a2aproject.sdk.compat03.conversion.TestHtt quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG + +# Security configuration for regular tests +# Provide a test identity provider that always authenticates +# AuthTestProfile overrides this to require real HTTP Basic Auth +%test.quarkus.test-security.test-enabled=true +%test.quarkus.test-security.user=testuser +%test.quarkus.test-security.roles=user diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java index f086f9ce0..aec3da7f5 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -20,6 +20,7 @@ import jakarta.inject.Inject; import jakarta.inject.Singleton; +import io.quarkus.security.Authenticated; import io.quarkus.security.ForbiddenException; import io.quarkus.security.UnauthorizedException; import io.smallrye.mutiny.Multi; @@ -150,6 +151,7 @@ private Handler authenticated(Consumer action) { }; } + @Authenticated public void sendMessage(String body, RoutingContext rc) { ServerCallContext context = createCallContext(rc, SendMessageRequest_v0_3.METHOD); HTTPRestResponse response = null; @@ -162,6 +164,7 @@ public void sendMessage(String body, RoutingContext rc) { } } + @Authenticated public void sendMessageStreaming(String body, RoutingContext rc) { ServerCallContext context = createCallContext(rc, SendStreamingMessageRequest_v0_3.METHOD); HTTPRestStreamingResponse streamingResponse = null; @@ -185,6 +188,7 @@ public void sendMessageStreaming(String body, RoutingContext rc) { } } + @Authenticated public void getTask(RoutingContext rc) { String taskId = rc.pathParam("id"); ServerCallContext context = createCallContext(rc, GetTaskRequest_v0_3.METHOD); @@ -219,6 +223,7 @@ public void getTask(RoutingContext rc) { } } + @Authenticated public void cancelTask(RoutingContext rc) { String taskId = rc.pathParam("param0"); ServerCallContext context = createCallContext(rc, CancelTaskRequest_v0_3.METHOD); @@ -251,6 +256,7 @@ private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response } } + @Authenticated public void resubscribeTask(RoutingContext rc) { String taskId = rc.pathParam("param0"); ServerCallContext context = createCallContext(rc, TaskResubscriptionRequest_v0_3.METHOD); @@ -279,6 +285,7 @@ public void resubscribeTask(RoutingContext rc) { } } + @Authenticated public void setTaskPushNotificationConfiguration(String body, RoutingContext rc) { String taskId = rc.pathParam("id"); ServerCallContext context = createCallContext(rc, SetTaskPushNotificationConfigRequest_v0_3.METHOD); @@ -296,6 +303,7 @@ public void setTaskPushNotificationConfiguration(String body, RoutingContext rc) } } + @Authenticated public void getTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("id"); String configId = rc.pathParam("configId"); @@ -314,6 +322,7 @@ public void getTaskPushNotificationConfiguration(RoutingContext rc) { } } + @Authenticated public void listTaskPushNotificationConfigurations(RoutingContext rc) { String taskId = rc.pathParam("id"); ServerCallContext context = createCallContext(rc, ListTaskPushNotificationConfigRequest_v0_3.METHOD); @@ -331,6 +340,7 @@ public void listTaskPushNotificationConfigurations(RoutingContext rc) { } } + @Authenticated public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("id"); String configId = rc.pathParam("configId"); @@ -356,6 +366,7 @@ public void getAgentCard(RoutingContext rc) { sendResponse(rc, response); } + @Authenticated public void getAuthenticatedExtendedCard(RoutingContext rc) { HTTPRestResponse response = jsonRestHandler.getAuthenticatedExtendedCard(); sendResponse(rc, response); diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerWithAuthTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerWithAuthTest_v0_3.java new file mode 100644 index 000000000..08540b61c --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerWithAuthTest_v0_3.java @@ -0,0 +1,241 @@ +package org.a2aproject.sdk.compat03.conversion; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Map; + +import io.restassured.RestAssured; +import io.restassured.config.ObjectMapperConfig; +import io.restassured.specification.RequestSpecification; +import jakarta.ws.rs.core.MediaType; +import org.a2aproject.sdk.compat03.client.Client_v0_3; +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.config.ClientConfig_v0_3; +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; +import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentInterface_v0_3; +import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskStatus_v0_3; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.junit.jupiter.api.Test; + +/** + * Abstract base class for v0.3 authentication tests. + *

            + * Mirrors {@code AbstractA2AServerWithAuthTest} from v1.0 but uses v0.3 client types. + * Tests verify that security enforcement works correctly through the v0.3 compatibility layer. + */ +public abstract class AbstractA2AServerWithAuthTest_v0_3 { + + protected static final String TEST_USERNAME = "testuser"; + protected static final String TEST_PASSWORD = "testpass"; + protected static final String BASIC_AUTH_SCHEME_NAME = "basicAuth"; + + protected static String getEncodedCredentials() { + String credentials = TEST_USERNAME + ":" + TEST_PASSWORD; + return Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8)); + } + + protected static final Task_v0_3 MINIMAL_TASK = new Task_v0_3.Builder() + .id("task-123") + .contextId("session-xyz") + .status(new TaskStatus_v0_3(TaskState_v0_3.SUBMITTED)) + .build(); + + protected final int serverPort; + private Client_v0_3 authenticatedClient; + private Client_v0_3 unauthenticatedClient; + + protected AbstractA2AServerWithAuthTest_v0_3(int serverPort) { + this.serverPort = serverPort; + } + + protected abstract String getTransportProtocol(); + + protected abstract String getTransportUrl(); + + protected abstract void configureTransport(ClientBuilder_v0_3 builder); + + protected abstract void configureTransportWithAuth(ClientBuilder_v0_3 builder); + + protected Client_v0_3 getAuthenticatedClient() throws A2AClientException_v0_3 { + if (authenticatedClient == null) { + authenticatedClient = createAuthenticatedClient(); + } + return authenticatedClient; + } + + protected Client_v0_3 getUnauthenticatedClient() throws A2AClientException_v0_3 { + if (unauthenticatedClient == null) { + unauthenticatedClient = createUnauthenticatedClient(); + } + return unauthenticatedClient; + } + + private Client_v0_3 createAuthenticatedClient() throws A2AClientException_v0_3 { + AgentCard_v0_3 agentCard = createTestAgentCard(); + ClientConfig_v0_3 clientConfig = new ClientConfig_v0_3.Builder() + .setStreaming(false) + .build(); + + ClientBuilder_v0_3 clientBuilder = Client_v0_3.builder(agentCard) + .clientConfig(clientConfig); + + configureTransportWithAuth(clientBuilder); + + return clientBuilder.build(); + } + + private Client_v0_3 createUnauthenticatedClient() throws A2AClientException_v0_3 { + AgentCard_v0_3 agentCard = createTestAgentCard(); + ClientConfig_v0_3 clientConfig = new ClientConfig_v0_3.Builder() + .setStreaming(false) + .build(); + + ClientBuilder_v0_3 clientBuilder = Client_v0_3.builder(agentCard) + .clientConfig(clientConfig); + + configureTransport(clientBuilder); + + return clientBuilder.build(); + } + + private AgentCard_v0_3 createTestAgentCard() { + return new AgentCard_v0_3.Builder() + .name("test-card") + .description("A test agent card") + .url(getTransportUrl()) + .version("1.0") + .preferredTransport(getTransportProtocol()) + .capabilities(new AgentCapabilities_v0_3.Builder() + .streaming(false) + .pushNotifications(false) + .stateTransitionHistory(false) + .build()) + .defaultInputModes(List.of("text")) + .defaultOutputModes(List.of("text")) + .skills(List.of()) + .additionalInterfaces(List.of(new AgentInterface_v0_3(getTransportProtocol(), getTransportUrl()))) + .securitySchemes(Map.of( + BASIC_AUTH_SCHEME_NAME, + new HTTPAuthSecurityScheme_v0_3.Builder() + .scheme("basic") + .description("HTTP Basic authentication") + .build())) + .security(List.of(Map.of(BASIC_AUTH_SCHEME_NAME, List.of()))) + .build(); + } + + protected static RequestSpecification given() { + return RestAssured.given() + .config(RestAssured.config() + .objectMapperConfig(new ObjectMapperConfig(V10GsonObjectMapper_v0_3.INSTANCE))); + } + + protected RequestSpecification givenAuthenticated() { + return given() + .auth().basic(TEST_USERNAME, TEST_PASSWORD); + } + + protected RequestSpecification givenUnauthenticated() { + return given(); + } + + protected void saveTaskInTaskStore(Task_v0_3 task) throws Exception { + org.a2aproject.sdk.spec.Task v10Task = TaskMapper_v0_3.INSTANCE.toV10(task); + + HttpClient httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task")) + .header("Content-Type", MediaType.APPLICATION_JSON) + .POST(HttpRequest.BodyPublishers.ofString(JsonUtil.toJson(v10Task))) + .build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + if (response.statusCode() != 200 && response.statusCode() != 204) { + throw new RuntimeException("Failed to save task: " + response.statusCode() + " " + response.body()); + } + } + + protected void deleteTaskInTaskStore(String taskId) throws Exception { + HttpClient httpClient = HttpClient.newHttpClient(); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + serverPort + "/test/task/" + taskId)) + .DELETE() + .build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() != 200 && response.statusCode() != 204) { + throw new RuntimeException("Failed to delete task: " + response.statusCode() + " " + response.body()); + } + } + + @Test + public void testGetTaskRequiresAuthenticationUnauthenticated() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + Client_v0_3 unauthClient = getUnauthenticatedClient(); + A2AClientException_v0_3 error = assertThrows(A2AClientException_v0_3.class, () -> { + unauthClient.getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + }); + assertTrue(error.getMessage().contains("Authentication failed") || + error.getMessage().contains("401") || + error.getMessage().contains("Unauthorized"), + "Expected authentication error, got: " + error.getMessage()); + + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + + @Test + public void testGetTaskWithAuthentication() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + Client_v0_3 client = getAuthenticatedClient(); + Task_v0_3 result = client.getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + assertNotNull(result); + assertEquals(MINIMAL_TASK.getId(), result.getId()); + + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } + + @Test + public void testGetAgentCardIsPublic() { + givenUnauthenticated() + .get("/.well-known/agent-card.json") + .then() + .statusCode(200); + } + + @Test + public void testBasicAuthWorksViaHttp() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .contentType("application/json") + .body("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tasks/get\",\"params\":{\"id\":\"" + MINIMAL_TASK.getId() + "\"}}") + .post("/") + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentCardProducer_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentCardProducer_v0_3.java index 130ace31c..576fdae06 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentCardProducer_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentCardProducer_v0_3.java @@ -5,14 +5,18 @@ import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Properties; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; -import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; import org.a2aproject.sdk.server.PublicAgentCard; +import org.eclipse.microprofile.config.inject.ConfigProperty; import io.quarkus.arc.DefaultBean; import io.quarkus.arc.profile.IfBuildProfile; @@ -27,6 +31,11 @@ public class AgentCardProducer_v0_3 { private static final String PREFERRED_TRANSPORT = "preferred-transport"; private static final String PROPERTIES_FILE = "/compat-0.3-requesthandler-test.properties"; + private static final String BASIC_AUTH_SCHEME_NAME = "basicAuth"; + + @Inject + @ConfigProperty(name = "test.agent.security.enabled", defaultValue = "false") + boolean securityEnabled; @Produces @PublicAgentCard @@ -40,7 +49,7 @@ public AgentCard_v0_3 createTestAgentCard() { ? "localhost:" + port : "http://localhost:" + port; - return new AgentCard_v0_3.Builder() + AgentCard_v0_3.Builder builder = new AgentCard_v0_3.Builder() .name("compat-0.3-test-agent") .description("Test agent for v0.3 compatibility layer") .url(url) @@ -50,8 +59,19 @@ public AgentCard_v0_3 createTestAgentCard() { .defaultInputModes(List.of("text")) .defaultOutputModes(List.of("text")) .skills(List.of()) - .additionalInterfaces(new ArrayList<>()) - .build(); + .additionalInterfaces(new ArrayList<>()); + + if (securityEnabled) { + builder.securitySchemes(Map.of( + BASIC_AUTH_SCHEME_NAME, + new HTTPAuthSecurityScheme_v0_3.Builder() + .scheme("basic") + .description("HTTP Basic authentication") + .build())) + .security(List.of(Map.of(BASIC_AUTH_SCHEME_NAME, List.of()))); + } + + return builder.build(); } private static String loadPreferredTransportFromProperties() { From 26cdb5a79c68d9acc4dfffe6b591b4987457853b Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 29 Apr 2026 17:32:12 +0100 Subject: [PATCH 142/192] feat: Add security tests for compat-0.3 REST reference module Add authentication test infrastructure for the v0.3 REST reference module, mirroring the v1.0 auth test structure. Fix missing 401/403 error handling in v0.3 JDK HTTP client's get() and delete() methods that prevented proper authentication failure reporting. - Add AuthTestProfile_v0_3 with embedded user store and HTTP Basic auth - Add TestIdentityProvider_v0_3 for auto-auth in regular tests - Add QuarkusA2ARest_v0_3_WithAuthTest extending AbstractA2AServerWithAuthTest_v0_3 - Add quarkus-security, quarkus-elytron-security-properties-file, quarkus-test-security test dependencies - Add test security configuration to application.properties - Fix JdkA2AHttpClient_v0_3 get()/delete() to throw IOException on 401/403 responses, matching post() and v1.0 behavior Co-Authored-By: Claude Opus 4.6 --- .../client/http/JdkA2AHttpClient_v0_3.java | 14 +++++ compat-0.3/reference/rest/pom.xml | 16 +++++ .../rest/quarkus/AuthTestProfile_v0_3.java | 37 ++++++++++++ .../QuarkusA2ARest_v0_3_WithAuthTest.java | 59 +++++++++++++++++++ .../quarkus/TestIdentityProvider_v0_3.java | 29 +++++++++ .../src/test/resources/application.properties | 7 +++ 6 files changed, 162 insertions(+) create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/AuthTestProfile_v0_3.java create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/TestIdentityProvider_v0_3.java diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java index 1a968059b..2d1838b86 100644 --- a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java +++ b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java @@ -215,6 +215,13 @@ public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { .build(); HttpResponse response = httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); + + if (response.statusCode() == HTTP_UNAUTHORIZED) { + throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); + } else if (response.statusCode() == HTTP_FORBIDDEN) { + throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); + } + return new JdkHttpResponse(response); } @@ -237,6 +244,13 @@ public A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException { HttpRequest request = super.createRequestBuilder().DELETE().build(); HttpResponse response = httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); + + if (response.statusCode() == HTTP_UNAUTHORIZED) { + throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); + } else if (response.statusCode() == HTTP_FORBIDDEN) { + throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); + } + return new JdkHttpResponse(response); } diff --git a/compat-0.3/reference/rest/pom.xml b/compat-0.3/reference/rest/pom.xml index e3f5d9f32..061583d8d 100644 --- a/compat-0.3/reference/rest/pom.xml +++ b/compat-0.3/reference/rest/pom.xml @@ -95,6 +95,22 @@ mockito-junit-jupiter test + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/AuthTestProfile_v0_3.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/AuthTestProfile_v0_3.java new file mode 100644 index 000000000..30fc51072 --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/AuthTestProfile_v0_3.java @@ -0,0 +1,37 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class AuthTestProfile_v0_3 implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + // Disable test security (injected test user) - we want REAL authentication + Map.entry("quarkus.test.security.auth.enabled", "false"), + + // Disable TestIdentityProvider auto-authentication + Map.entry("test.identity.auto-auth", "false"), + + // Enable security in agent card + Map.entry("test.agent.security.enabled", "true"), + + // Enable embedded user store + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + + // Enable HTTP Basic authentication + Map.entry("quarkus.http.auth.basic", "true"), + Map.entry("quarkus.http.auth.proactive", "true") + ); + } + + @Override + public String getConfigProfile() { + return "test"; + } +} diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java new file mode 100644 index 000000000..9109d5fbb --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java @@ -0,0 +1,59 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile_v0_3.class) +public class QuarkusA2ARest_v0_3_WithAuthTest extends AbstractA2AServerWithAuthTest_v0_3 { + + public QuarkusA2ARest_v0_3_WithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3() + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); + } + + @Test + @Override + public void testBasicAuthWorksViaHttp() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .get("/v1/tasks/" + MINIMAL_TASK.getId()) + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } +} diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/TestIdentityProvider_v0_3.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/TestIdentityProvider_v0_3.java new file mode 100644 index 000000000..a8576b71d --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/TestIdentityProvider_v0_3.java @@ -0,0 +1,29 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.quarkus.arc.Unremovable; +import io.quarkus.arc.properties.IfBuildProperty; +import io.quarkus.security.identity.AuthenticationRequestContext; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.identity.SecurityIdentityAugmentor; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; + +@ApplicationScoped +@Unremovable +@IfBuildProperty(name = "test.identity.auto-auth", stringValue = "true", enableIfMissing = true) +public class TestIdentityProvider_v0_3 implements SecurityIdentityAugmentor { + + @Override + public Uni augment(SecurityIdentity identity, AuthenticationRequestContext context) { + if (identity.isAnonymous()) { + return Uni.createFrom().item(QuarkusSecurityIdentity.builder() + .setPrincipal(() -> "testuser") + .addRole("user") + .setAnonymous(false) + .build()); + } + return Uni.createFrom().item(identity); + } +} diff --git a/compat-0.3/reference/rest/src/test/resources/application.properties b/compat-0.3/reference/rest/src/test/resources/application.properties index 3412ec5de..520e4473f 100644 --- a/compat-0.3/reference/rest/src/test/resources/application.properties +++ b/compat-0.3/reference/rest/src/test/resources/application.properties @@ -18,3 +18,10 @@ quarkus.arc.selected-alternatives=org.a2aproject.sdk.compat03.conversion.TestHtt quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG + +# Security configuration for regular tests +# Inject a test user automatically so @Authenticated checks pass without requiring credentials +# AuthTestProfile overrides this to require REAL HTTP Basic Auth +quarkus.test.security.auth.enabled=true +quarkus.test.security.default-user=testuser +quarkus.test.security.default-roles=user From edf62c56b9a5c315acf803e50c8e619630ed6d4c Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 29 Apr 2026 17:44:00 +0100 Subject: [PATCH 143/192] feat: Add security tests for compat-0.3 gRPC reference module Add authentication test infrastructure for the v0.3 gRPC reference module, mirroring the v1.0 gRPC auth test structure. - Add TestAuthorizationController_v0_3 to disable @Authenticated enforcement for regular tests via AuthorizationController - Add AuthTestProfile_v0_3 to enable real auth for auth-specific tests - Add QuarkusA2AGrpc_v0_3_WithAuthTest extending AbstractA2AServerWithAuthTest_v0_3 - Add quarkus-security, quarkus-elytron-security-properties-file, quarkus-test-security test dependencies - Fix GrpcHandler_v0_3 to catch SecurityException and map to UNAUTHENTICATED/PERMISSION_DENIED gRPC status codes instead of falling through to INTERNAL error handling Co-Authored-By: Claude Opus 4.6 --- compat-0.3/reference/grpc/pom.xml | 16 +++ .../grpc/quarkus/AuthTestProfile_v0_3.java | 36 +++++++ .../QuarkusA2AGrpc_v0_3_WithAuthTest.java | 101 ++++++++++++++++++ .../TestAuthorizationController_v0_3.java | 24 +++++ .../grpc/handler/GrpcHandler_v0_3.java | 43 ++++++++ 5 files changed, 220 insertions(+) create mode 100644 compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/AuthTestProfile_v0_3.java create mode 100644 compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_WithAuthTest.java create mode 100644 compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/TestAuthorizationController_v0_3.java diff --git a/compat-0.3/reference/grpc/pom.xml b/compat-0.3/reference/grpc/pom.xml index 356a1f0f8..446b63c86 100644 --- a/compat-0.3/reference/grpc/pom.xml +++ b/compat-0.3/reference/grpc/pom.xml @@ -101,6 +101,22 @@ rest-assured test + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + diff --git a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/AuthTestProfile_v0_3.java b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/AuthTestProfile_v0_3.java new file mode 100644 index 000000000..29a137595 --- /dev/null +++ b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/AuthTestProfile_v0_3.java @@ -0,0 +1,36 @@ +package org.a2aproject.sdk.compat03.server.grpc.quarkus; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class AuthTestProfile_v0_3 implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + // Disable test security (injected test user) - we want REAL authentication + Map.entry("quarkus.test.security.auth.enabled", "false"), + + // Enable embedded user store + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + + // Enable security in agent card + Map.entry("test.agent.security.enabled", "true"), + + // Enable authorization so @Authenticated is enforced + Map.entry("test.authorization.enabled", "true"), + + // Enable HTTP Basic authentication + Map.entry("quarkus.http.auth.basic", "true") + ); + } + + @Override + public String getConfigProfile() { + return "test"; + } +} diff --git a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_WithAuthTest.java b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_WithAuthTest.java new file mode 100644 index 000000000..f14470efd --- /dev/null +++ b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_WithAuthTest.java @@ -0,0 +1,101 @@ +package org.a2aproject.sdk.compat03.server.grpc.quarkus; + +import java.util.concurrent.TimeUnit; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile_v0_3.class) +public class QuarkusA2AGrpc_v0_3_WithAuthTest extends AbstractA2AServerWithAuthTest_v0_3 { + + private static ManagedChannel authenticatedChannel; + private static ManagedChannel unauthenticatedChannel; + + public QuarkusA2AGrpc_v0_3_WithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.GRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(GrpcTransport_v0_3.class, new GrpcTransportConfigBuilder_v0_3() + .channelFactory(target -> { + authenticatedChannel = ManagedChannelBuilder + .forTarget(target) + .usePlaintext() + .build(); + return authenticatedChannel; + }) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(GrpcTransport_v0_3.class, new GrpcTransportConfigBuilder_v0_3().channelFactory(target -> { + unauthenticatedChannel = ManagedChannelBuilder + .forTarget(target) + .usePlaintext() + .build(); + return unauthenticatedChannel; + })); + } + + @AfterAll + public static void closeChannels() { + if (authenticatedChannel != null) { + authenticatedChannel.shutdownNow(); + try { + authenticatedChannel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + if (unauthenticatedChannel != null) { + unauthenticatedChannel.shutdownNow(); + try { + unauthenticatedChannel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + @Test + @Override + @Disabled + public void testGetAgentCardIsPublic() { + // Skip - gRPC doesn't have /.well-known/agent-card.json endpoint + } + + @Test + @Override + @Disabled + public void testBasicAuthWorksViaHttp() { + // Skip - HTTP-specific test + } +} diff --git a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/TestAuthorizationController_v0_3.java b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/TestAuthorizationController_v0_3.java new file mode 100644 index 000000000..f01ddd848 --- /dev/null +++ b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/TestAuthorizationController_v0_3.java @@ -0,0 +1,24 @@ +package org.a2aproject.sdk.compat03.server.grpc.quarkus; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.Alternative; +import jakarta.inject.Singleton; +import jakarta.interceptor.Interceptor; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import io.quarkus.security.spi.runtime.AuthorizationController; + +@Alternative +@Priority(Interceptor.Priority.LIBRARY_AFTER + 1) +@Singleton +public class TestAuthorizationController_v0_3 extends AuthorizationController { + + @ConfigProperty(name = "test.authorization.enabled", defaultValue = "false") + boolean enabled; + + @Override + public boolean isAuthorizationEnabled() { + return enabled; + } +} diff --git a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java index 369835f55..12694af91 100644 --- a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java +++ b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java @@ -38,6 +38,7 @@ import org.a2aproject.sdk.compat03.spec.TaskQueryParams_v0_3; import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.common.A2AErrorMessages; import org.a2aproject.sdk.server.auth.UnauthenticatedUser; import org.a2aproject.sdk.server.auth.User; import org.a2aproject.sdk.spec.A2AError; @@ -88,6 +89,8 @@ public void sendMessage(org.a2aproject.sdk.compat03.grpc.SendMessageRequest requ handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -110,6 +113,8 @@ public void getTask(org.a2aproject.sdk.compat03.grpc.GetTaskRequest request, handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -132,6 +137,8 @@ public void cancelTask(org.a2aproject.sdk.compat03.grpc.CancelTaskRequest reques handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -155,6 +162,8 @@ public void createTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.Cr handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -178,6 +187,8 @@ public void getTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.GetTa handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -206,6 +217,8 @@ public void listTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.List handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -228,6 +241,8 @@ public void sendStreamingMessage(org.a2aproject.sdk.compat03.grpc.SendMessageReq handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -250,6 +265,8 @@ public void taskSubscription(org.a2aproject.sdk.compat03.grpc.TaskSubscriptionRe handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -331,6 +348,8 @@ public void deleteTaskPushNotificationConfig(org.a2aproject.sdk.compat03.grpc.De handleError(responseObserver, ErrorConverter_v0_3.convertA2AError(e)); } catch (JSONRPCError_v0_3 e) { handleError(responseObserver, e); + } catch (SecurityException e) { + handleSecurityException(responseObserver, e); } catch (Throwable t) { handleInternalError(responseObserver, t); } @@ -393,6 +412,30 @@ private void handleError(StreamObserver responseObserver, JSONRPCError_v0 responseObserver.onError(status.withDescription(description).asRuntimeException()); } + private void handleSecurityException(StreamObserver responseObserver, SecurityException e) { + Status status; + String description; + + String exceptionClassName = e.getClass().getName(); + + if (exceptionClassName.contains("Unauthorized") || + exceptionClassName.contains("Unauthenticated") || + exceptionClassName.contains("Authentication")) { + status = Status.UNAUTHENTICATED; + description = A2AErrorMessages.AUTHENTICATION_FAILED; + } else if (exceptionClassName.contains("Forbidden") || + exceptionClassName.contains("AccessDenied") || + exceptionClassName.contains("Authorization")) { + status = Status.PERMISSION_DENIED; + description = A2AErrorMessages.AUTHORIZATION_FAILED; + } else { + status = Status.PERMISSION_DENIED; + description = "Authorization failed: " + (e.getMessage() != null ? e.getMessage() : "Access denied"); + } + + responseObserver.onError(status.withDescription(description).asRuntimeException()); + } + private void handleInternalError(StreamObserver responseObserver, Throwable t) { handleError(responseObserver, new InternalError_v0_3(t.getMessage())); } From 7801162c683644985695b1be86b9251458b2a726 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 29 Apr 2026 18:20:43 +0200 Subject: [PATCH 144/192] refactor(compat-0.3): improve error serialization, DI, and JSON-RPC id handling - Switch JSONRPCErrorTypeAdapter to TypeAdapterFactory for correct subclass resolution - Migrate Convert_v0_3_To10RequestHandler to constructor injection - Extract writeJsonRpcId() utility to deduplicate id serialization logic - Always write JSON-RPC id field (null when unknown) per spec - Fix spurious leading slash in listTaskPushNotificationConfigurations URL - Add AuthenticatedExtendedCardNotConfiguredError to error code mapping - Remove debug log statement from RestHandler Signed-off-by: Emmanuel Hugonnet --- .../transport/rest/RestErrorMapper_v0_3.java | 15 +- .../transport/rest/RestTransport_v0_3.java | 2 +- .../Convert_v0_3_To10RequestHandler.java | 6 +- .../AbstractA2ARequestHandlerTest_v0_3.java | 3 +- .../sdk/compat03/json/JsonUtil_v0_3.java | 320 +++++++++--------- .../handler/JSONRPCHandler_v0_3_Test.java | 9 +- .../sdk/jsonrpc/common/json/JsonUtil.java | 19 ++ .../sdk/grpc/utils/JSONRPCUtils.java | 22 +- .../transport/rest/handler/RestHandler.java | 1 - 9 files changed, 216 insertions(+), 181 deletions(-) diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java index 8e77af39f..d6732726e 100644 --- a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java @@ -1,5 +1,6 @@ package org.a2aproject.sdk.compat03.client.transport.rest; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; @@ -33,8 +34,8 @@ public static A2AClientException_v0_3 mapRestError(String body, int code) { try { if (body != null && !body.isBlank()) { JsonObject node = JsonUtil_v0_3.fromJson(body, JsonObject.class); - String className = node.has("error") ? node.get("error").getAsString() : ""; - String errorMessage = node.has("message") ? node.get("message").getAsString() : ""; + String className = safeGetString(node, "error"); + String errorMessage = safeGetString(node, "message"); return mapRestError(className, errorMessage, code); } return mapRestError("", "", code); @@ -44,6 +45,16 @@ public static A2AClientException_v0_3 mapRestError(String body, int code) { } } + private static String safeGetString(JsonObject obj, String fieldName) { + if (obj.has(fieldName)) { + JsonElement element = obj.get(fieldName); + if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) { + return element.getAsString(); + } + } + return ""; + } + public static A2AClientException_v0_3 mapRestError(String className, String errorMessage, int code) { return switch (className) { case "org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3" -> new A2AClientException_v0_3(errorMessage, new TaskNotFoundError_v0_3()); diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java index 656da61ee..7dc0b40fb 100644 --- a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java @@ -238,7 +238,7 @@ public TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration(GetT public List listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams_v0_3 request, @Nullable ClientCallContext_v0_3 context) throws A2AClientException_v0_3 { checkNotNullParam("request", request); ListTaskPushNotificationConfigRequest.Builder builder = ListTaskPushNotificationConfigRequest.newBuilder(); - builder.setParent(String.format("/tasks/%1s/pushNotificationConfigs", request.id())); + builder.setParent(String.format("tasks/%1s/pushNotificationConfigs", request.id())); PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(ListTaskPushNotificationConfigRequest_v0_3.METHOD, builder, agentCard, context); try { diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java index 39773edbb..a300b8044 100644 --- a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java @@ -70,8 +70,12 @@ public class Convert_v0_3_To10RequestHandler { /** * The v1.0 {@link RequestHandler} to which all converted requests are delegated. */ + private final RequestHandler v10Handler; + @Inject - public RequestHandler v10Handler; + public Convert_v0_3_To10RequestHandler(org.a2aproject.sdk.server.requesthandlers.RequestHandler v10Handler) { + this.v10Handler = v10Handler; + } /** * Gets a task by ID. diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java index 701e2ea63..9e4c3b692 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java @@ -143,8 +143,7 @@ public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2A mainEventBusProcessor, internalExecutor, internalExecutor); // Wrap in v0.3 conversion handler - convert03To10Handler = new Convert_v0_3_To10RequestHandler(); - convert03To10Handler.v10Handler = v10Handler; + convert03To10Handler = new Convert_v0_3_To10RequestHandler(v10Handler); } @AfterEach diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java index b28ee7f64..5798b27bf 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java @@ -1,5 +1,6 @@ package org.a2aproject.sdk.compat03.json; +import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED_ERROR_CODE; import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.INTERNAL_ERROR_CODE; import static org.a2aproject.sdk.compat03.spec.A2AErrorCodes_v0_3.INVALID_AGENT_RESPONSE_ERROR_CODE; @@ -25,54 +26,54 @@ import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; import org.a2aproject.sdk.compat03.spec.EventKind_v0_3; import org.a2aproject.sdk.compat03.spec.JSONRPCResponse_v0_3; -import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; import org.a2aproject.sdk.compat03.spec.DataPart_v0_3; import org.a2aproject.sdk.compat03.spec.FileContent_v0_3; import org.a2aproject.sdk.compat03.spec.FilePart_v0_3; import org.a2aproject.sdk.compat03.spec.FileWithBytes_v0_3; import org.a2aproject.sdk.compat03.spec.FileWithUri_v0_3; import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; -import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; -import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; -import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; -import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; -import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; import org.a2aproject.sdk.compat03.spec.JSONRPCError_v0_3; import org.a2aproject.sdk.compat03.spec.Message_v0_3; -import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; import org.a2aproject.sdk.compat03.spec.MutualTLSSecurityScheme_v0_3; import org.a2aproject.sdk.compat03.spec.OAuth2SecurityScheme_v0_3; import org.a2aproject.sdk.compat03.spec.OpenIdConnectSecurityScheme_v0_3; import org.a2aproject.sdk.compat03.spec.Part_v0_3; -import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; import org.a2aproject.sdk.compat03.spec.SecurityScheme_v0_3; import org.a2aproject.sdk.compat03.spec.StreamingEventKind_v0_3; import org.a2aproject.sdk.compat03.spec.Task_v0_3; import org.a2aproject.sdk.compat03.spec.TaskArtifactUpdateEvent_v0_3; -import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; -import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; import org.a2aproject.sdk.compat03.spec.TaskState_v0_3; import org.a2aproject.sdk.compat03.spec.TaskStatusUpdateEvent_v0_3; import org.a2aproject.sdk.compat03.spec.TextPart_v0_3; -import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; -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.List; +import org.a2aproject.sdk.compat03.spec.AuthenticatedExtendedCardNotConfiguredError_v0_3; +import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.InternalError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidAgentResponseError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; +import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; +import org.a2aproject.sdk.compat03.spec.JSONParseError_v0_3; +import org.a2aproject.sdk.compat03.spec.MethodNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.PushNotificationNotSupportedError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotCancelableError_v0_3; +import org.a2aproject.sdk.compat03.spec.TaskNotFoundError_v0_3; +import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; import org.jspecify.annotations.Nullable; -import static org.a2aproject.sdk.compat03.json.JsonUtil_v0_3.JSONRPCErrorTypeAdapter.THROWABLE_MARKER_FIELD; public class JsonUtil_v0_3 { + private static final String THROWABLE_MARKER_FIELD = "__throwable"; private static GsonBuilder createBaseGsonBuilder() { return new GsonBuilder() .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) // Register JSONRPCError hierarchy adapter for all error subclasses - .registerTypeHierarchyAdapter(JSONRPCError_v0_3.class, new JSONRPCErrorTypeAdapter()) + .registerTypeAdapterFactory(new JSONRPCErrorTypeAdapterFactory()) // Register Throwable adapter for EXACT Throwable.class only (not subclasses) // This prevents it from being used for JSONRPCError which extends Throwable .registerTypeAdapter(Throwable.class, new ThrowableTypeAdapter()) @@ -134,6 +135,25 @@ public static String toJson(Object data) throws JsonProcessingException_v0_3 { } } + /** + * Writes a JSON-RPC {@code id} field. Handles null, String, and Number values, + * preserving fractional precision for non-integer numeric IDs. + */ + public static void writeJsonRpcId(JsonWriter out, @Nullable Object id) throws java.io.IOException { + out.name("id"); + if (id == null) { + out.nullValue(); + } else if (id instanceof Number n) { + if (id instanceof Long || id instanceof Integer || id instanceof Short || id instanceof Byte) { + out.value(n.longValue()); + } else { + out.value(n); + } + } else { + out.value(id.toString()); + } + } + /** * Gson TypeAdapter for serializing and deserializing {@link OffsetDateTime} to/from ISO-8601 format. *

            @@ -258,171 +278,175 @@ Throwable read(JsonReader in) throws java.io.IOException { } /** - * Gson TypeAdapter for serializing and deserializing {@link JSONRPCError_v0_3} and its subclasses. + * Gson TypeAdapter for serializing and deserializing {@link JSONRPCError} and its subclasses. *

            * This adapter handles polymorphic deserialization based on the error code, creating the * appropriate subclass instance. *

            * The adapter maps error codes to their corresponding error classes: *

              - *
            • -32700: {@link JSONParseError_v0_3}
            • - *
            • -32600: {@link InvalidRequestError_v0_3}
            • - *
            • -32601: {@link MethodNotFoundError_v0_3}
            • - *
            • -32602: {@link InvalidParamsError_v0_3}
            • + *
            • -32700: {@link JSONParseError}
            • + *
            • -32600: {@link InvalidRequestError}
            • + *
            • -32601: {@link MethodNotFoundError}
            • + *
            • -32602: {@link InvalidParamsError}
            • *
            • -32603: {@link InternalError}
            • - *
            • -32001: {@link TaskNotFoundError_v0_3}
            • - *
            • -32002: {@link TaskNotCancelableError_v0_3}
            • - *
            • -32003: {@link PushNotificationNotSupportedError_v0_3}
            • - *
            • -32004: {@link UnsupportedOperationError_v0_3}
            • - *
            • -32005: {@link ContentTypeNotSupportedError_v0_3}
            • - *
            • -32006: {@link InvalidAgentResponseError_v0_3}
            • - *
            • Other codes: {@link JSONRPCError_v0_3}
            • + *
            • -32001: {@link TaskNotFoundError}
            • + *
            • -32002: {@link TaskNotCancelableError}
            • + *
            • -32003: {@link PushNotificationNotSupportedError}
            • + *
            • -32004: {@link UnsupportedOperationError}
            • + *
            • -32005: {@link ContentTypeNotSupportedError}
            • + *
            • -32006: {@link InvalidAgentResponseError}
            • + *
            • Other codes: {@link JSONRPCError}
            • *
            * - * @see JSONRPCError_v0_3 + * @see JSONRPCError */ - static class JSONRPCErrorTypeAdapter extends TypeAdapter { + static class JSONRPCErrorTypeAdapterFactory implements TypeAdapterFactory { - private static final ThrowableTypeAdapter THROWABLE_ADAPTER = new ThrowableTypeAdapter(); - static final String THROWABLE_MARKER_FIELD = "__throwable"; + static final ThrowableTypeAdapter THROWABLE_ADAPTER = new ThrowableTypeAdapter(); private static final String CODE_FIELD = "code"; private static final String DATA_FIELD = "data"; private static final String MESSAGE_FIELD = "message"; private static final String TYPE_FIELD = "type"; @Override - public void write(JsonWriter out, JSONRPCError_v0_3 value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - out.beginObject(); - out.name(CODE_FIELD).value(value.getCode()); - out.name(MESSAGE_FIELD).value(value.getMessage()); - if (value.getData() != null) { - out.name(DATA_FIELD); - // If data is a Throwable, use ThrowableTypeAdapter to avoid reflection issues - if (value.getData() instanceof Throwable throwable) { - THROWABLE_ADAPTER.write(out, throwable); - } else { - // Use Gson to serialize the data field for non-Throwable types - OBJECT_MAPPER.toJson(value.getData(), Object.class, out); - } + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { + if (!JSONRPCError_v0_3.class.isAssignableFrom(type.getRawType())) { + return null; } - out.endObject(); + + @SuppressWarnings("unchecked") + TypeAdapter adapter = (TypeAdapter) new JSONRPCErrorTypeAdapter(gson); + return adapter; } - @Override - public @Nullable - JSONRPCError_v0_3 read(JsonReader in) throws java.io.IOException { - if (in.peek() == com.google.gson.stream.JsonToken.NULL) { - in.nextNull(); - return null; - } + private static class JSONRPCErrorTypeAdapter extends TypeAdapter { - Integer code = null; - String message = null; - Object data = null; + private final Gson gson; - in.beginObject(); - while (in.hasNext()) { - String fieldName = in.nextName(); - switch (fieldName) { - case CODE_FIELD -> - code = in.nextInt(); - case MESSAGE_FIELD -> - message = in.nextString(); - case DATA_FIELD -> { - // Read data as a generic object (could be string, number, object, etc.) - data = readDataValue(in); + JSONRPCErrorTypeAdapter(Gson gson) { + this.gson = gson; + } + + @Override + public void write(JsonWriter out, JSONRPCError_v0_3 value) throws java.io.IOException { + if (value == null) { + out.nullValue(); + return; + } + out.beginObject(); + out.name(CODE_FIELD).value(value.getCode()); + out.name(MESSAGE_FIELD).value(value.getMessage()); + if (value.getData() != null) { + out.name(DATA_FIELD); + if (value.getData() instanceof Throwable throwable) { + THROWABLE_ADAPTER.write(out, throwable); + } else { + gson.toJson(value.getData(), Object.class, out); } - default -> - in.skipValue(); } + out.endObject(); } - in.endObject(); - // Create the appropriate subclass based on the error code - return createErrorInstance(code, message, data); - } - - /** - * Reads the data field value, which can be of any JSON type. - */ - private @Nullable - Object readDataValue(JsonReader in) throws java.io.IOException { - return switch (in.peek()) { - case STRING -> - in.nextString(); - case NUMBER -> - in.nextDouble(); - case BOOLEAN -> - in.nextBoolean(); - case NULL -> { + @Override + public @Nullable JSONRPCError_v0_3 read(JsonReader in) throws java.io.IOException { + if (in.peek() == com.google.gson.stream.JsonToken.NULL) { in.nextNull(); - yield null; + return null; } - case BEGIN_OBJECT -> { - // Parse as JsonElement to check if it's a Throwable - com.google.gson.JsonElement element = com.google.gson.JsonParser.parseReader(in); - if (element.isJsonObject()) { - com.google.gson.JsonObject obj = element.getAsJsonObject(); - // Check if it has the structure of a serialized Throwable (type + message) - if (obj.has(TYPE_FIELD) && obj.has(MESSAGE_FIELD) && obj.has(THROWABLE_MARKER_FIELD)) { - // Deserialize as Throwable using ThrowableTypeAdapter - yield THROWABLE_ADAPTER.read(new JsonReader(new StringReader(element.toString()))); - } + + Integer code = null; + String message = null; + Object data = null; + + in.beginObject(); + while (in.hasNext()) { + String fieldName = in.nextName(); + switch (fieldName) { + case CODE_FIELD -> + code = in.nextInt(); + case MESSAGE_FIELD -> + message = in.nextString(); + case DATA_FIELD -> + data = readDataValue(in); + default -> + in.skipValue(); } - // Otherwise, deserialize as generic object - yield OBJECT_MAPPER.fromJson(element, Object.class); - } - case BEGIN_ARRAY -> - // For arrays, read as raw JSON using Gson - OBJECT_MAPPER.fromJson(in, Object.class); - default -> { - in.skipValue(); - yield null; } - }; - } + in.endObject(); - /** - * Creates the appropriate JSONRPCError subclass based on the error code. - */ - private JSONRPCError_v0_3 createErrorInstance(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - if (code == null) { - throw new JsonSyntaxException("JSONRPCError must have a code field"); + return createErrorInstance(code, message, data); } - return switch (code) { - case JSON_PARSE_ERROR_CODE -> - new JSONParseError_v0_3(code, message, data); - case INVALID_REQUEST_ERROR_CODE -> - new InvalidRequestError_v0_3(code, message, data); - case METHOD_NOT_FOUND_ERROR_CODE -> - new MethodNotFoundError_v0_3(code, message, data); - case INVALID_PARAMS_ERROR_CODE -> - new InvalidParamsError_v0_3(code, message, data); - case INTERNAL_ERROR_CODE -> - new InternalError_v0_3(code, message, data); - case TASK_NOT_FOUND_ERROR_CODE -> - new TaskNotFoundError_v0_3(code, message, data); - case TASK_NOT_CANCELABLE_ERROR_CODE -> - new TaskNotCancelableError_v0_3(code, message, data); - case PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE -> - new PushNotificationNotSupportedError_v0_3(code, message, data); - case UNSUPPORTED_OPERATION_ERROR_CODE -> - new UnsupportedOperationError_v0_3(code, message, data); - case CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE -> - new ContentTypeNotSupportedError_v0_3(code, message, data); - case INVALID_AGENT_RESPONSE_ERROR_CODE -> - new InvalidAgentResponseError_v0_3(code, message, data); - default -> - new JSONRPCError_v0_3(code, message, data); - }; + private @Nullable Object readDataValue(JsonReader in) throws java.io.IOException { + return switch (in.peek()) { + case STRING -> + in.nextString(); + case NUMBER -> + in.nextDouble(); + case BOOLEAN -> + in.nextBoolean(); + case NULL -> { + in.nextNull(); + yield null; + } + case BEGIN_OBJECT -> { + com.google.gson.JsonElement element = com.google.gson.JsonParser.parseReader(in); + if (element.isJsonObject()) { + com.google.gson.JsonObject obj = element.getAsJsonObject(); + if (obj.has(TYPE_FIELD) && obj.has(MESSAGE_FIELD) && obj.has(THROWABLE_MARKER_FIELD)) { + yield THROWABLE_ADAPTER.fromJsonTree(element); + } + } + yield gson.fromJson(element, Object.class); + } + case BEGIN_ARRAY -> + gson.fromJson(in, Object.class); + default -> { + in.skipValue(); + yield null; + } + }; + } + + private static JSONRPCError_v0_3 createErrorInstance(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + if (code == null) { + throw new JsonSyntaxException("JSONRPCError must have a code field"); + } + + return switch (code) { + case JSON_PARSE_ERROR_CODE -> + new JSONParseError_v0_3(code, message, data); + case INVALID_REQUEST_ERROR_CODE -> + new InvalidRequestError_v0_3(code, message, data); + case METHOD_NOT_FOUND_ERROR_CODE -> + new MethodNotFoundError_v0_3(code, message, data); + case INVALID_PARAMS_ERROR_CODE -> + new InvalidParamsError_v0_3(code, message, data); + case INTERNAL_ERROR_CODE -> + new InternalError_v0_3(code, message, data); + case TASK_NOT_FOUND_ERROR_CODE -> + new TaskNotFoundError_v0_3(code, message, data); + case TASK_NOT_CANCELABLE_ERROR_CODE -> + new TaskNotCancelableError_v0_3(code, message, data); + case PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE -> + new PushNotificationNotSupportedError_v0_3(code, message, data); + case UNSUPPORTED_OPERATION_ERROR_CODE -> + new UnsupportedOperationError_v0_3(code, message, data); + case CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE -> + new ContentTypeNotSupportedError_v0_3(code, message, data); + case INVALID_AGENT_RESPONSE_ERROR_CODE -> + new InvalidAgentResponseError_v0_3(code, message, data); + case AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED_ERROR_CODE -> + new AuthenticatedExtendedCardNotConfiguredError_v0_3(code, message, data); + default -> + new JSONRPCError_v0_3(code, message, data); + }; + } } } + /** * Gson TypeAdapter for serializing and deserializing {@link TaskState_v0_3} enum. *

            @@ -1003,15 +1027,7 @@ public void write(JsonWriter out, T value) throws java.io.IOException { out.beginObject(); out.name("jsonrpc").value(response.getJsonrpc()); - Object id = response.getId(); - out.name("id"); - if (id == null) { - out.nullValue(); - } else if (id instanceof Number n) { - out.value(n.longValue()); - } else { - out.value(id.toString()); - } + writeJsonRpcId(out, response.getId()); JSONRPCError_v0_3 error = response.getError(); if (error != null) { diff --git a/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java index a564905d4..c031e8a4f 100644 --- a/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java +++ b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java @@ -862,8 +862,7 @@ public void testOnGetPushNotificationNoPushNotifierConfig() { internalExecutor, internalExecutor); // Wrap in v0.3 conversion handler - Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(); - handlerWithoutPushConfig.v10Handler = v10Handler; + Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(v10Handler); AgentCard_v0_3 card = createAgentCard(false, true, false); JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(card, internalExecutor, handlerWithoutPushConfig); @@ -890,8 +889,7 @@ public void testOnSetPushNotificationNoPushNotifierConfig() { internalExecutor, internalExecutor); // Wrap in v0.3 conversion handler - Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(); - handlerWithoutPushConfig.v10Handler = v10Handler; + Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(v10Handler); AgentCard_v0_3 card = createAgentCard(false, true, false); JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(card, internalExecutor, handlerWithoutPushConfig); @@ -958,8 +956,7 @@ public void testDeletePushNotificationConfigNoPushConfigStore() { internalExecutor, internalExecutor); // Wrap in v0.3 conversion handler - Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(); - handlerWithoutPushConfig.v10Handler = v10Handler; + Convert_v0_3_To10RequestHandler handlerWithoutPushConfig = new Convert_v0_3_To10RequestHandler(v10Handler); JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, handlerWithoutPushConfig); diff --git a/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtil.java index 8b63981a4..01666237f 100644 --- a/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/json/JsonUtil.java @@ -148,6 +148,25 @@ public static String toJson(Object data) throws JsonProcessingException { } } + /** + * Writes a JSON-RPC {@code id} field. Handles null, String, and Number values, + * preserving fractional precision for non-integer numeric IDs. + */ + public static void writeJsonRpcId(JsonWriter out, @Nullable Object id) throws java.io.IOException { + out.name("id"); + if (id == null) { + out.nullValue(); + } else if (id instanceof Number n) { + if (id instanceof Long || id instanceof Integer || id instanceof Short || id instanceof Byte) { + out.value(n.longValue()); + } else { + out.value(n); + } + } else { + out.value(id.toString()); + } + } + /** * Gson TypeAdapter for serializing and deserializing {@link OffsetDateTime} to/from ISO-8601 format. *

            diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java index adbdd87ff..966c998cc 100644 --- a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java @@ -81,6 +81,8 @@ import static org.a2aproject.sdk.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; import static org.a2aproject.sdk.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; + /** * Utilities for converting between JSON-RPC 2.0 messages and Protocol Buffer objects. *

            @@ -580,17 +582,11 @@ public static String toJsonRPCRequest(@Nullable String requestId, String method, } } - public static String toJsonRPCResultResponse(Object requestId, com.google.protobuf.MessageOrBuilder builder) { + public static String toJsonRPCResultResponse(@Nullable Object requestId, com.google.protobuf.MessageOrBuilder builder) { try (StringWriter result = new StringWriter(); JsonWriter output = GSON.newJsonWriter(result)) { output.beginObject(); output.name("jsonrpc").value("2.0"); - if (requestId != null) { - if (requestId instanceof String string) { - output.name("id").value(string); - } else if (requestId instanceof Number number) { - output.name("id").value(number.longValue()); - } - } + JsonUtil.writeJsonRpcId(output, requestId); String resultValue = JsonFormat.printer().alwaysPrintFieldsWithNoPresence().omittingInsignificantWhitespace().print(builder); output.name("result").jsonValue(resultValue); output.endObject(); @@ -602,17 +598,11 @@ public static String toJsonRPCResultResponse(Object requestId, com.google.protob } } - public static String toJsonRPCErrorResponse(Object requestId, A2AError error) { + public static String toJsonRPCErrorResponse(@Nullable Object requestId, A2AError error) { try (StringWriter result = new StringWriter(); JsonWriter output = GSON.newJsonWriter(result)) { output.beginObject(); output.name("jsonrpc").value("2.0"); - if (requestId != null) { - if (requestId instanceof String string) { - output.name("id").value(string); - } else if (requestId instanceof Number number) { - output.name("id").value(number.longValue()); - } - } + JsonUtil.writeJsonRpcId(output, requestId); output.name("error"); output.beginObject(); output.name("code").value(error.getCode()); diff --git a/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java index ec578b641..84442cc8d 100644 --- a/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java +++ b/transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java @@ -224,7 +224,6 @@ public RestHandler(AgentCard agentCard, AgentCardCacheMetadata cacheMetadata, * @see RequestHandler#onMessageSend(org.a2aproject.sdk.spec.MessageSendParams, ServerCallContext) */ public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, String body) { - log.warning("DEBUG: Received request body: " + body); try { A2AVersionValidator.validateProtocolVersion(agentCard, context); A2AExtensions.validateRequiredExtensions(agentCard, context); From 7a174a939115a057fcc2d66c3e761ad8880dc193 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 1 May 2026 11:55:27 +0100 Subject: [PATCH 145/192] feat: add VersionRouter utility and auto-detect v1.0 for agent card multiplexing Add VersionRouter in reference-common that resolves A2A protocol version from the A2A-Version header or query param. Per spec Section 3.6.2, missing/empty version defaults to 0.3 for backward compatibility. Add PublicAgentCard.Literal for programmatic CDI lookup. Modify both v0.3 A2AServerRoutes_v0_3 (JSON-RPC and REST) to skip registering /.well-known/agent-card.json when a non-@DefaultBean v1.0 AgentCard producer is present, so v1.0 takes precedence in dual-version mode. Co-Authored-By: Claude Opus 4.6 --- .../apps/quarkus/A2AServerRoutes_v0_3.java | 46 +++++++++---- .../rest/quarkus/A2AServerRoutes_v0_3.java | 28 ++++++-- reference/common/pom.xml | 10 +++ .../server/common/quarkus/VersionRouter.java | 47 ++++++++++++++ .../common/quarkus/VersionRouterTest.java | 64 +++++++++++++++++++ .../sdk/server/PublicAgentCard.java | 5 ++ 6 files changed, 181 insertions(+), 19 deletions(-) create mode 100644 reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VersionRouter.java create mode 100644 reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/VersionRouterTest.java diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java index 8de1e304f..ef4a5fa6d 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -61,11 +61,13 @@ import org.a2aproject.sdk.compat03.spec.UnsupportedOperationError_v0_3; import org.a2aproject.sdk.compat03.transport.jsonrpc.handler.JSONRPCHandler_v0_3; import org.a2aproject.sdk.compat03.util.Utils_v0_3; +import org.a2aproject.sdk.server.PublicAgentCard; import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.UnauthenticatedUser; import org.a2aproject.sdk.server.auth.User; import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.spec.AgentCard; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -103,20 +105,36 @@ void setupRoutes(@Observes Router router) { } }); - // Agent card endpoint: GET /.well-known/agent-card.json - router.get("/.well-known/agent-card.json") - .produces(APPLICATION_JSON) - .handler(ctx -> { - try { - String agentCard = JsonUtil_v0_3.toJson(jsonRpcHandler.getAgentCard()); - ctx.response() - .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) - .end(agentCard); - } catch (JsonProcessingException_v0_3 e) { - ctx.response().setStatusCode(500).end("Internal Server Error"); - } - }); + // Only register v0.3 agent card if no real v1.0 agent card producer exists. + // DefaultProducers provides a @DefaultBean AgentCard fallback that is always + // present, so we must exclude it and only check for non-default beans. + if (!hasNonDefaultV10AgentCard()) { + router.get("/.well-known/agent-card.json") + .produces(APPLICATION_JSON) + .handler(ctx -> { + try { + String agentCard = JsonUtil_v0_3.toJson(jsonRpcHandler.getAgentCard()); + ctx.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(agentCard); + } catch (JsonProcessingException_v0_3 e) { + ctx.response().setStatusCode(500).end("Internal Server Error"); + } + }); + } + } + + private static boolean hasNonDefaultV10AgentCard() { + for (io.quarkus.arc.InstanceHandle handle : + io.quarkus.arc.Arc.container() + .select(AgentCard.class, PublicAgentCard.Literal.INSTANCE) + .handles()) { + if (!handle.getBean().isDefaultBean()) { + return true; + } + } + return false; } @Authenticated diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java index aec3da7f5..7ef264a8c 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -48,11 +48,13 @@ import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3; import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3.HTTPRestResponse; import org.a2aproject.sdk.compat03.transport.rest.handler.RestHandler_v0_3.HTTPRestStreamingResponse; +import org.a2aproject.sdk.server.PublicAgentCard; import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.UnauthenticatedUser; import org.a2aproject.sdk.server.auth.User; import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.server.extensions.A2AExtensions; +import org.a2aproject.sdk.spec.AgentCard; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -126,11 +128,15 @@ void setupRouter(@Observes @Priority(10) Router router) { .order(1) .blockingHandler(authenticated(this::deleteTaskPushNotificationConfiguration)); - // GET /.well-known/agent-card.json - public - router.get("/.well-known/agent-card.json") - .order(1) - .produces(APPLICATION_JSON) - .handler(this::getAgentCard); + // Only register v0.3 agent card if no real v1.0 agent card producer exists. + // DefaultProducers provides a @DefaultBean AgentCard fallback that is always + // present, so we must exclude it and only check for non-default beans. + if (!hasNonDefaultV10AgentCard()) { + router.get("/.well-known/agent-card.json") + .order(1) + .produces(APPLICATION_JSON) + .handler(this::getAgentCard); + } // GET /v1/card - authenticated router.get("/v1/card") @@ -429,6 +435,18 @@ public String getUsername() { } } + private static boolean hasNonDefaultV10AgentCard() { + for (io.quarkus.arc.InstanceHandle handle : + io.quarkus.arc.Arc.container() + .select(AgentCard.class, PublicAgentCard.Literal.INSTANCE) + .handles()) { + if (!handle.getBean().isDefaultBean()) { + return true; + } + } + return false; + } + private static class MultiSseSupport { private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); diff --git a/reference/common/pom.xml b/reference/common/pom.xml index fe90bd1de..4a75519c9 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -72,6 +72,16 @@ junit-jupiter-api test + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + io.rest-assured rest-assured diff --git a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VersionRouter.java b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VersionRouter.java new file mode 100644 index 000000000..b5d690da6 --- /dev/null +++ b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VersionRouter.java @@ -0,0 +1,47 @@ +package org.a2aproject.sdk.server.common.quarkus; + +import io.vertx.ext.web.RoutingContext; +import org.a2aproject.sdk.common.A2AHeaders; + +public final class VersionRouter { + + public static final String VERSION_1_0 = "1.0"; + public static final String VERSION_0_3 = "0.3"; + + private VersionRouter() { + } + + /** + * Resolves the protocol version from the request. + * + * @return {@link #VERSION_1_0}, {@link #VERSION_0_3}, or the raw version string + * if it matches neither (caller should reject as unsupported) + */ + public static String resolveVersion(RoutingContext rc) { + String version = rc.request().getHeader(A2AHeaders.A2A_VERSION); + if (version == null || version.isBlank()) { + version = rc.request().getParam(A2AHeaders.A2A_VERSION); + } + + if (version == null || version.isBlank()) { + return VERSION_0_3; + } + + String trimmed = version.trim(); + if (trimmed.equals(VERSION_1_0)) { + return VERSION_1_0; + } + if (trimmed.equals(VERSION_0_3)) { + return VERSION_0_3; + } + return trimmed; + } + + public static boolean isV10(String resolvedVersion) { + return VERSION_1_0.equals(resolvedVersion); + } + + public static boolean isV03(String resolvedVersion) { + return VERSION_0_3.equals(resolvedVersion); + } +} diff --git a/reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/VersionRouterTest.java b/reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/VersionRouterTest.java new file mode 100644 index 000000000..75c0afb22 --- /dev/null +++ b/reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/VersionRouterTest.java @@ -0,0 +1,64 @@ +package org.a2aproject.sdk.server.common.quarkus; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import io.vertx.core.http.HttpServerRequest; +import io.vertx.ext.web.RoutingContext; +import org.a2aproject.sdk.common.A2AHeaders; +import org.junit.jupiter.api.Test; + +class VersionRouterTest { + + @Test + void missingHeaderDefaultsTo03() { + RoutingContext rc = mockRc(null, null); + assertEquals(VersionRouter.VERSION_0_3, VersionRouter.resolveVersion(rc)); + } + + @Test + void emptyHeaderDefaultsTo03() { + RoutingContext rc = mockRc("", null); + assertEquals(VersionRouter.VERSION_0_3, VersionRouter.resolveVersion(rc)); + } + + @Test + void explicitV10() { + RoutingContext rc = mockRc("1.0", null); + assertEquals(VersionRouter.VERSION_1_0, VersionRouter.resolveVersion(rc)); + } + + @Test + void explicitV03() { + RoutingContext rc = mockRc("0.3", null); + assertEquals(VersionRouter.VERSION_0_3, VersionRouter.resolveVersion(rc)); + } + + @Test + void queryParamFallback() { + RoutingContext rc = mockRc(null, "1.0"); + assertEquals(VersionRouter.VERSION_1_0, VersionRouter.resolveVersion(rc)); + } + + @Test + void headerTakesPrecedenceOverQueryParam() { + RoutingContext rc = mockRc("0.3", "1.0"); + assertEquals(VersionRouter.VERSION_0_3, VersionRouter.resolveVersion(rc)); + } + + @Test + void unsupportedVersionPassedThrough() { + RoutingContext rc = mockRc("2.0", null); + assertEquals("2.0", VersionRouter.resolveVersion(rc)); + } + + private RoutingContext mockRc(String headerValue, String queryParamValue) { + RoutingContext rc = mock(RoutingContext.class); + HttpServerRequest request = mock(HttpServerRequest.class); + when(rc.request()).thenReturn(request); + when(request.getHeader(A2AHeaders.A2A_VERSION)).thenReturn(headerValue); + when(request.getParam(A2AHeaders.A2A_VERSION)).thenReturn(queryParamValue); + return rc; + } +} diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/PublicAgentCard.java b/server-common/src/main/java/org/a2aproject/sdk/server/PublicAgentCard.java index 72d19b3af..b32e84c9e 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/PublicAgentCard.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/PublicAgentCard.java @@ -9,10 +9,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; +import jakarta.enterprise.util.AnnotationLiteral; import jakarta.inject.Qualifier; @Qualifier @Retention(RUNTIME) @Target({FIELD, TYPE, METHOD, PARAMETER}) public @interface PublicAgentCard { + + final class Literal extends AnnotationLiteral implements PublicAgentCard { + public static final Literal INSTANCE = new Literal(); + } } From 6f8bb9e3a3377d96ff7f7fe07db2f917dd876bf3 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 1 May 2026 15:07:37 +0100 Subject: [PATCH 146/192] feat: add production multiversion modules for JSON-RPC and REST Create reference/multiversion-jsonrpc with MultiVersionJSONRPCRoutes and reference/multiversion-rest with MultiVersionRestRoutes. These are reusable production modules that provide version-dispatching routes for dual v1.0/v0.3 deployments. JSON-RPC uses Vert.x route order(-1) to intercept POST / before the standalone v1.0 and v0.3 handlers, dispatching based on A2A-Version header. REST intercepts /v1/... paths that overlap between v0.3 literal routes and v1.0 regex routes, with path param bridging between naming conventions. Both include proper VersionNotSupportedError handling. Co-Authored-By: Claude Opus 4.6 --- boms/reference/pom.xml | 12 + .../src/it/reference-usage-test/pom.xml | 10 + pom.xml | 4 + reference/multiversion-jsonrpc/pom.xml | 40 ++++ .../jsonrpc/MultiVersionJSONRPCRoutes.java | 68 ++++++ reference/multiversion-rest/pom.xml | 40 ++++ .../rest/MultiVersionRestRoutes.java | 225 ++++++++++++++++++ 7 files changed, 399 insertions(+) create mode 100644 reference/multiversion-jsonrpc/pom.xml create mode 100644 reference/multiversion-jsonrpc/src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/MultiVersionJSONRPCRoutes.java create mode 100644 reference/multiversion-rest/pom.xml create mode 100644 reference/multiversion-rest/src/main/java/org/a2aproject/sdk/server/multiversion/rest/MultiVersionRestRoutes.java diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 8243b6250..304a6bc36 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -59,6 +59,18 @@ ${project.version} + + + ${project.groupId} + a2a-java-sdk-reference-multiversion-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-reference-multiversion-rest + ${project.version} + + ${project.groupId} diff --git a/boms/reference/src/it/reference-usage-test/pom.xml b/boms/reference/src/it/reference-usage-test/pom.xml index 89c335295..0503b53d2 100644 --- a/boms/reference/src/it/reference-usage-test/pom.xml +++ b/boms/reference/src/it/reference-usage-test/pom.xml @@ -56,6 +56,16 @@ a2a-java-sdk-reference-rest + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-rest + + org.a2aproject.sdk diff --git a/pom.xml b/pom.xml index d2174f424..b44d1299f 100644 --- a/pom.xml +++ b/pom.xml @@ -592,6 +592,10 @@ compat-0.3 + + reference/multiversion-jsonrpc + reference/multiversion-rest + boms/extras boms/reference diff --git a/reference/multiversion-jsonrpc/pom.xml b/reference/multiversion-jsonrpc/pom.xml new file mode 100644 index 000000000..4b9a17cf1 --- /dev/null +++ b/reference/multiversion-jsonrpc/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.0.Beta2-SNAPSHOT + ../../pom.xml + + a2a-java-sdk-reference-multiversion-jsonrpc + + jar + + Java A2A SDK Reference Multiversion JSON-RPC + Version-dispatching routes for dual v1.0/v0.3 JSON-RPC deployment + + + + ${project.groupId} + a2a-java-sdk-reference-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-reference-common + + + io.quarkus + quarkus-vertx-http + + + diff --git a/reference/multiversion-jsonrpc/src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/MultiVersionJSONRPCRoutes.java b/reference/multiversion-jsonrpc/src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/MultiVersionJSONRPCRoutes.java new file mode 100644 index 000000000..2bf044c72 --- /dev/null +++ b/reference/multiversion-jsonrpc/src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/MultiVersionJSONRPCRoutes.java @@ -0,0 +1,68 @@ +package org.a2aproject.sdk.server.multiversion.jsonrpc; + +import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; + +import jakarta.enterprise.event.Observes; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.BodyHandler; +import org.a2aproject.sdk.compat03.server.apps.quarkus.A2AServerRoutes_v0_3; +import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; +import org.a2aproject.sdk.server.apps.quarkus.A2AServerRoutes; +import org.a2aproject.sdk.server.common.quarkus.VersionRouter; +import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.VersionNotSupportedError; + +import io.quarkus.security.ForbiddenException; +import io.quarkus.security.UnauthorizedException; + +@Singleton +public class MultiVersionJSONRPCRoutes { + + @Inject + A2AServerRoutes v10Routes; + + @Inject + A2AServerRoutes_v0_3 v03Routes; + + @Inject + VertxSecurityHelper vertxSecurityHelper; + + void setupRoutes(@Observes Router router) { + router.post("/") + .order(-1) + .consumes("application/json") + .handler(BodyHandler.create()) + .blockingHandler(ctx -> { + try { + vertxSecurityHelper.runInRequestContext(ctx, () -> { + String version = VersionRouter.resolveVersion(ctx); + String body = ctx.body().asString(); + + if (VersionRouter.isV10(version)) { + v10Routes.invokeJSONRPCHandler(body, ctx); + } else if (VersionRouter.isV03(version)) { + v03Routes.invokeJSONRPCHandler(body, ctx); + } else { + throw new VersionNotSupportedError( + null, + "Protocol version '" + version + "' is not supported. Supported versions: [1.0, 0.3]", + null); + } + }); + } catch (UnauthorizedException | ForbiddenException e) { + VertxSecurityHelper.handleAuthError(ctx, e); + } catch (A2AError e) { + ctx.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, "application/json") + .end(JSONRPCUtils.toJsonRPCErrorResponse(null, e)); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }); + } +} diff --git a/reference/multiversion-rest/pom.xml b/reference/multiversion-rest/pom.xml new file mode 100644 index 000000000..3ad916b7d --- /dev/null +++ b/reference/multiversion-rest/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.0.Beta2-SNAPSHOT + ../../pom.xml + + a2a-java-sdk-reference-multiversion-rest + + jar + + Java A2A SDK Reference Multiversion REST + Version-dispatching routes for dual v1.0/v0.3 REST deployment + + + + ${project.groupId} + a2a-java-sdk-reference-rest + ${project.version} + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-rest + ${project.version} + + + ${project.groupId} + a2a-java-sdk-reference-common + + + io.quarkus + quarkus-vertx-http + + + diff --git a/reference/multiversion-rest/src/main/java/org/a2aproject/sdk/server/multiversion/rest/MultiVersionRestRoutes.java b/reference/multiversion-rest/src/main/java/org/a2aproject/sdk/server/multiversion/rest/MultiVersionRestRoutes.java new file mode 100644 index 000000000..d62f94d08 --- /dev/null +++ b/reference/multiversion-rest/src/main/java/org/a2aproject/sdk/server/multiversion/rest/MultiVersionRestRoutes.java @@ -0,0 +1,225 @@ +package org.a2aproject.sdk.server.multiversion.rest; + +import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import jakarta.annotation.Priority; +import jakarta.enterprise.event.Observes; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import com.google.gson.JsonObject; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; +import org.a2aproject.sdk.server.common.quarkus.VersionRouter; +import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; +import org.a2aproject.sdk.server.rest.quarkus.A2AServerRoutes; +import org.a2aproject.sdk.compat03.server.rest.quarkus.A2AServerRoutes_v0_3; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.A2AErrorCodes; +import org.a2aproject.sdk.spec.VersionNotSupportedError; + +import io.quarkus.security.ForbiddenException; +import io.quarkus.security.UnauthorizedException; + +@Singleton +public class MultiVersionRestRoutes { + + @Inject + A2AServerRoutes v10Routes; + + @Inject + A2AServerRoutes_v0_3 v03Routes; + + @Inject + VertxSecurityHelper vertxSecurityHelper; + + void setupRoutes(@Observes @Priority(5) Router router) { + // POST /v1/message:send + router.postWithRegex("^\\/v1\\/message:send$") + .order(-1) + .handler(BodyHandler.create()) + .blockingHandler(versionDispatch( + MultiVersionRestRoutes::bridgeTenant, + (body, ctx) -> v10Routes.sendMessage(body, ctx), + (body, ctx) -> v03Routes.sendMessage(body, ctx))); + + // POST /v1/message:stream + router.postWithRegex("^\\/v1\\/message:stream$") + .order(-1) + .handler(BodyHandler.create()) + .blockingHandler(versionDispatch( + MultiVersionRestRoutes::bridgeTenant, + (body, ctx) -> v10Routes.sendMessageStreaming(body, ctx), + (body, ctx) -> v03Routes.sendMessageStreaming(body, ctx))); + + // GET /v1/tasks/{taskId} + router.getWithRegex("^\\/v1\\/tasks\\/(?[^:^/]+)$") + .order(-1) + .blockingHandler(versionDispatchNoBody( + ctx -> { bridgeTenant(ctx); bridgeTaskId(ctx); }, + ctx -> v10Routes.getTask(ctx), + ctx -> v03Routes.getTask(ctx))); + + // POST /v1/tasks/{taskId}:cancel + router.postWithRegex("^\\/v1\\/tasks\\/(?[^/]+):cancel$") + .order(-1) + .handler(BodyHandler.create()) + .blockingHandler(versionDispatch( + ctx -> { bridgeTenant(ctx); bridgeTaskId(ctx); }, + (body, ctx) -> v10Routes.cancelTask(body, ctx), + (body, ctx) -> v03Routes.cancelTask(ctx))); + + // POST /v1/tasks/{taskId}:subscribe + router.postWithRegex("^\\/v1\\/tasks\\/(?[^/]+):subscribe$") + .order(-1) + .blockingHandler(versionDispatchNoBody( + ctx -> { bridgeTenant(ctx); bridgeTaskId(ctx); }, + ctx -> v10Routes.subscribeToTask(ctx), + ctx -> v03Routes.resubscribeTask(ctx))); + + // POST /v1/tasks/{taskId}/pushNotificationConfigs + router.postWithRegex("^\\/v1\\/tasks\\/(?[^/]+)\\/pushNotificationConfigs$") + .order(-1) + .handler(BodyHandler.create()) + .blockingHandler(versionDispatch( + ctx -> { bridgeTenant(ctx); bridgeTaskId(ctx); }, + (body, ctx) -> v10Routes.createTaskPushNotificationConfiguration(body, ctx), + (body, ctx) -> v03Routes.setTaskPushNotificationConfiguration(body, ctx))); + + // GET /v1/tasks/{taskId}/pushNotificationConfigs/{configId} + router.getWithRegex("^\\/v1\\/tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^\\/]+)") + .order(-1) + .blockingHandler(versionDispatchNoBody( + ctx -> { bridgeTenant(ctx); bridgeTaskId(ctx); }, + ctx -> v10Routes.getTaskPushNotificationConfiguration(ctx), + ctx -> v03Routes.getTaskPushNotificationConfiguration(ctx))); + + // GET /v1/tasks/{taskId}/pushNotificationConfigs + router.getWithRegex("^\\/v1\\/tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/?$") + .order(-1) + .blockingHandler(versionDispatchNoBody( + ctx -> { bridgeTenant(ctx); bridgeTaskId(ctx); }, + ctx -> v10Routes.listTaskPushNotificationConfigurations(ctx), + ctx -> v03Routes.listTaskPushNotificationConfigurations(ctx))); + + // DELETE /v1/tasks/{taskId}/pushNotificationConfigs/{configId} + router.deleteWithRegex("^\\/v1\\/tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^/]+)") + .order(-1) + .blockingHandler(versionDispatchNoBody( + ctx -> { bridgeTenant(ctx); bridgeTaskId(ctx); }, + ctx -> v10Routes.deleteTaskPushNotificationConfiguration(ctx), + ctx -> v03Routes.deleteTaskPushNotificationConfiguration(ctx))); + + // GET /v1/card — v0.3 only (v1.0 uses /{tenant}/extendedAgentCard) + router.get("/v1/card") + .order(-1) + .produces("application/json") + .blockingHandler(ctx -> { + try { + vertxSecurityHelper.runInRequestContext(ctx, + () -> v03Routes.getAuthenticatedExtendedCard(ctx)); + } catch (UnauthorizedException | ForbiddenException e) { + VertxSecurityHelper.handleAuthError(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }); + } + + private static void bridgeTenant(RoutingContext ctx) { + ctx.pathParams().put("tenant", "v1"); + } + + private static void bridgeTaskId(RoutingContext ctx) { + String taskId = ctx.pathParam("taskId"); + if (taskId != null) { + ctx.pathParams().put("id", taskId); + ctx.pathParams().put("param0", taskId); + } + } + + private io.vertx.core.Handler versionDispatch( + Consumer paramBridger, + BiConsumer v10Handler, + BiConsumer v03Handler) { + return ctx -> { + try { + vertxSecurityHelper.runInRequestContext(ctx, () -> { + String version = VersionRouter.resolveVersion(ctx); + paramBridger.accept(ctx); + String body = ctx.body().asString(); + if (body == null) { + body = ""; + } + if (VersionRouter.isV10(version)) { + v10Handler.accept(body, ctx); + } else if (VersionRouter.isV03(version)) { + v03Handler.accept(body, ctx); + } else { + throw new VersionNotSupportedError( + null, + "Protocol version '" + version + "' is not supported. Supported versions: [1.0, 0.3]", + null); + } + }); + } catch (UnauthorizedException | ForbiddenException e) { + VertxSecurityHelper.handleAuthError(ctx, e); + } catch (A2AError e) { + sendA2AErrorResponse(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }; + } + + private io.vertx.core.Handler versionDispatchNoBody( + Consumer paramBridger, + Consumer v10Handler, + Consumer v03Handler) { + return ctx -> { + try { + vertxSecurityHelper.runInRequestContext(ctx, () -> { + String version = VersionRouter.resolveVersion(ctx); + paramBridger.accept(ctx); + if (VersionRouter.isV10(version)) { + v10Handler.accept(ctx); + } else if (VersionRouter.isV03(version)) { + v03Handler.accept(ctx); + } else { + throw new VersionNotSupportedError( + null, + "Protocol version '" + version + "' is not supported. Supported versions: [1.0, 0.3]", + null); + } + }); + } catch (UnauthorizedException | ForbiddenException e) { + VertxSecurityHelper.handleAuthError(ctx, e); + } catch (A2AError e) { + sendA2AErrorResponse(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }; + } + + private static void sendA2AErrorResponse(RoutingContext ctx, A2AError error) { + A2AErrorCodes errorCode = A2AErrorCodes.fromCode(error.getCode()); + int httpStatus = errorCode != null ? errorCode.httpCode() : 400; + + JsonObject errorObj = new JsonObject(); + errorObj.addProperty("code", error.getCode()); + errorObj.addProperty("message", error.getMessage()); + + JsonObject response = new JsonObject(); + response.add("error", errorObj); + + ctx.response() + .setStatusCode(httpStatus) + .putHeader(CONTENT_TYPE, "application/json") + .end(response.toString()); + } +} From 43218a0ff2beb2f88dae76369f80d92a18ac57c8 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 1 May 2026 16:08:59 +0100 Subject: [PATCH 147/192] feat: add dual-version JSON-RPC test module and A2A-Version header support Add tests/reference/jsonrpc module that verifies v1.0 and v0.3 JSON-RPC clients both work when both protocol versions are provisioned on the same server. Version routing uses A2A-Version header per spec Section 3.6.1. Also adds A2A-Version: 1.0 header to all v1.0 client transports (JSON-RPC, REST, gRPC) per spec requirement that clients MUST send this header. This is needed for multiversion routing and is a spec-compliance fix. Other changes: - Add META-INF/beans.xml to multiversion modules for CDI discovery - Make setStreamingMultiSseSupportSubscribedRunnable public in both v1.0 and v0.3 route classes for cross-bean access Co-Authored-By: Claude Opus 4.6 --- .../client/transport/grpc/GrpcTransport.java | 2 + .../transport/jsonrpc/JSONRPCTransport.java | 2 + .../client/transport/rest/RestTransport.java | 45 ++-- .../apps/quarkus/A2AServerRoutes_v0_3.java | 2 +- pom.xml | 3 + .../server/apps/quarkus/A2AServerRoutes.java | 2 +- .../src/main/resources/META-INF/beans.xml | 0 .../src/main/resources/META-INF/beans.xml | 0 tests/reference/jsonrpc/pom.xml | 126 +++++++++ .../multiversion/jsonrpc/A2ATestRoutes.java | 244 ++++++++++++++++++ .../multiversion/jsonrpc/AuthTestProfile.java | 27 ++ .../jsonrpc/MultiVersionJSONRPCTest.java | 39 +++ .../MultiVersionJSONRPCWithAuthTest.java | 54 ++++ .../MultiVersionJSONRPC_v0_3_Test.java | 39 +++ ...MultiVersionJSONRPC_v0_3_WithAuthTest.java | 53 ++++ .../jsonrpc/TestIdentityProvider.java | 29 +++ .../a2a-requesthandler-test.properties | 1 + .../src/test/resources/application.properties | 17 ++ .../compat-0.3-requesthandler-test.properties | 1 + .../apps/common/AbstractA2AServerTest.java | 5 +- 20 files changed, 660 insertions(+), 31 deletions(-) create mode 100644 reference/multiversion-jsonrpc/src/main/resources/META-INF/beans.xml create mode 100644 reference/multiversion-rest/src/main/resources/META-INF/beans.xml create mode 100644 tests/reference/jsonrpc/pom.xml create mode 100644 tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java create mode 100644 tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java create mode 100644 tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java create mode 100644 tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java create mode 100644 tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java create mode 100644 tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java create mode 100644 tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java create mode 100644 tests/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties create mode 100644 tests/reference/jsonrpc/src/test/resources/application.properties create mode 100644 tests/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties diff --git a/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransport.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransport.java index f7f07b0f9..2a57fec64 100644 --- a/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransport.java +++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcTransport.java @@ -33,6 +33,7 @@ import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; import org.a2aproject.sdk.spec.A2AClientException; import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; import org.a2aproject.sdk.spec.CancelTaskParams; import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; import org.a2aproject.sdk.spec.EventKind; @@ -388,6 +389,7 @@ private org.a2aproject.sdk.grpc.SendMessageRequest createGrpcSendMessageRequest( */ private Metadata createGrpcMetadata(@Nullable ClientCallContext context, @Nullable PayloadAndHeaders payloadAndHeaders) { Metadata metadata = new Metadata(); + metadata.put(VERSION_KEY, AgentInterface.CURRENT_PROTOCOL_VERSION); if (context != null && context.getHeaders() != null) { // Set a2a-version and a2a-extensions headers if present, ignoring case diff --git a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java index bc7844084..27b3f917c 100644 --- a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java @@ -23,6 +23,7 @@ import com.google.protobuf.MessageOrBuilder; import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.common.A2AHeaders; import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.client.http.A2AHttpResponse; import org.a2aproject.sdk.client.transport.jsonrpc.sse.SSEEventListener; @@ -336,6 +337,7 @@ private A2AHttpClient.PostBuilder createPostBuilder(String url, PayloadAndHeader A2AHttpClient.PostBuilder postBuilder = httpClient.createPost() .url(url) .addHeader("Content-Type", "application/json") + .addHeader(A2AHeaders.A2A_VERSION, AgentInterface.CURRENT_PROTOCOL_VERSION) .body(JSONRPCUtils.toJsonRPCRequest(null, method, (MessageOrBuilder) payloadAndHeaders.getPayload())); if (payloadAndHeaders.getHeaders() != null) { diff --git a/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java index 0768a3bf9..02b43e2d7 100644 --- a/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java @@ -30,6 +30,7 @@ import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.common.A2AHeaders; import org.a2aproject.sdk.client.transport.rest.sse.SSEEventListener; import org.a2aproject.sdk.client.transport.spi.ClientTransport; import org.a2aproject.sdk.client.transport.spi.interceptors.ClientCallContext; @@ -143,11 +144,7 @@ public Task getTask(TaskQueryParams taskQueryParams, @Nullable ClientCallContext url.append(String.format("/tasks/%1s", taskQueryParams.id())); } A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url.toString()); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } + addStandardHeaders(getBuilder, payloadAndHeaders); A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper.mapRestError(response); @@ -218,11 +215,7 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo } A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(urlBuilder.toString()); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } + addStandardHeaders(getBuilder, payloadAndHeaders); A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper.mapRestError(response); @@ -305,11 +298,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu agentCard, context); try { A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url.toString()); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } + addStandardHeaders(getBuilder, payloadAndHeaders); A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper.mapRestError(response); @@ -336,11 +325,7 @@ public ListTaskPushNotificationConfigsResult listTaskPushNotificationConfigurati try { String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs", request.id()); A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } + addStandardHeaders(getBuilder, payloadAndHeaders); A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper.mapRestError(response); @@ -365,11 +350,7 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC try { String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs/%2s", request.taskId(), request.id()); A2AHttpClient.DeleteBuilder deleteBuilder = httpClient.createDelete().url(url); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - deleteBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } + addStandardHeaders(deleteBuilder, payloadAndHeaders); A2AHttpResponse response = deleteBuilder.delete(); if (!response.success()) { throw RestErrorMapper.mapRestError(response); @@ -415,9 +396,7 @@ public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullab PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, null, agentCard, context); String url = Utils.buildBaseUrl(agentInterface, params.tenant()) + "/extendedAgentCard"; A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } + addStandardHeaders(getBuilder, payloadAndHeaders); A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper.mapRestError(response); @@ -463,6 +442,7 @@ private A2AHttpClient.PostBuilder createPostBuilder(String url, PayloadAndHeader A2AHttpClient.PostBuilder postBuilder = httpClient.createPost() .url(url) .addHeader("Content-Type", "application/json") + .addHeader(A2AHeaders.A2A_VERSION, AgentInterface.CURRENT_PROTOCOL_VERSION) .body(JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); if (payloadAndHeaders.getHeaders() != null) { @@ -473,6 +453,15 @@ private A2AHttpClient.PostBuilder createPostBuilder(String url, PayloadAndHeader return postBuilder; } + private static > void addStandardHeaders(T builder, PayloadAndHeaders payloadAndHeaders) { + builder.addHeader(A2AHeaders.A2A_VERSION, AgentInterface.CURRENT_PROTOCOL_VERSION); + if (payloadAndHeaders.getHeaders() != null) { + for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { + builder.addHeader(entry.getKey(), entry.getValue()); + } + } + } + private Map getHttpHeaders(@Nullable ClientCallContext context) { return context != null ? context.getHeaders() : Collections.emptyMap(); } diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java index ef4a5fa6d..1ee3e53a9 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -293,7 +293,7 @@ private JSONRPCResponse_v0_3 generateErrorResponse(JSONRPCRequest_v0_3 req return new JSONRPCErrorResponse_v0_3(request.getId(), error); } - static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { + public static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { streamingMultiSseSupportSubscribedRunnable = runnable; } diff --git a/pom.xml b/pom.xml index b44d1299f..f0beff065 100644 --- a/pom.xml +++ b/pom.xml @@ -596,6 +596,9 @@ reference/multiversion-jsonrpc reference/multiversion-rest + + tests/reference/jsonrpc + boms/extras boms/reference diff --git a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index aadcc5d12..35f63b7e7 100644 --- a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -526,7 +526,7 @@ private A2AResponse generateErrorResponse(A2ARequest request, A2AError err * * @param runnable the callback to invoke on subscription */ - static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { + public static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { streamingMultiSseSupportSubscribedRunnable = runnable; } diff --git a/reference/multiversion-jsonrpc/src/main/resources/META-INF/beans.xml b/reference/multiversion-jsonrpc/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..e69de29bb diff --git a/reference/multiversion-rest/src/main/resources/META-INF/beans.xml b/reference/multiversion-rest/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..e69de29bb diff --git a/tests/reference/jsonrpc/pom.xml b/tests/reference/jsonrpc/pom.xml new file mode 100644 index 000000000..4d2666a41 --- /dev/null +++ b/tests/reference/jsonrpc/pom.xml @@ -0,0 +1,126 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.0.Beta2-SNAPSHOT + ../../../pom.xml + + a2a-java-sdk-tests-multiversion-jsonrpc + + jar + + Java A2A SDK Tests Dual-Version JSON-RPC + Tests for dual v1.0/v0.3 JSON-RPC deployment + + + + + ${project.groupId} + a2a-java-sdk-reference-multiversion-jsonrpc + ${project.version} + + + + + ${project.groupId} + a2a-java-sdk-tests-server-common + provided + + + ${project.groupId} + a2a-java-sdk-tests-server-common + test-jar + test + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + ${project.version} + test-jar + test + + + + + ${project.groupId} + a2a-java-sdk-http-client-vertx + test + + + ${project.groupId} + a2a-java-sdk-client-transport-jsonrpc + test + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + ${project.version} + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + ${project.version} + test + + + + + io.quarkus + quarkus-junit5 + test + + + io.quarkus + quarkus-rest-client + test + + + org.junit.jupiter + junit-jupiter-api + test + + + io.rest-assured + rest-assured + test + + + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + + + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java new file mode 100644 index 000000000..313d4e834 --- /dev/null +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java @@ -0,0 +1,244 @@ +package org.a2aproject.sdk.tests.multiversion.jsonrpc; + +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; + +import java.util.concurrent.atomic.AtomicInteger; + +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.event.Observes; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.apps.common.TestUtilsBean; +import org.a2aproject.sdk.server.apps.quarkus.A2AServerRoutes; +import org.a2aproject.sdk.compat03.server.apps.quarkus.A2AServerRoutes_v0_3; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; + +@Singleton +public class A2ATestRoutes { + @Inject + TestUtilsBean testUtilsBean; + + @Inject + A2AServerRoutes a2AServerRoutes; + + @Inject + A2AServerRoutes_v0_3 a2AServerRoutes_v0_3; + + AtomicInteger streamingSubscribedCount = new AtomicInteger(0); + + @PostConstruct + public void init() { + Runnable callback = () -> streamingSubscribedCount.incrementAndGet(); + A2AServerRoutes.setStreamingMultiSseSupportSubscribedRunnable(callback); + A2AServerRoutes_v0_3.setStreamingMultiSseSupportSubscribedRunnable(callback); + } + + void setupRoutes(@Observes Router router) { + router.post("/test/task") + .consumes(APPLICATION_JSON) + .blockingHandler(ctx -> { + String body = ctx.body().asString(); + saveTask(body, ctx); + }); + + router.get("/test/task/:taskId") + .produces(APPLICATION_JSON) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getTask(taskId, ctx); + }); + + router.delete("/test/task/:taskId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + deleteTask(taskId, ctx); + }); + + router.post("/test/queue/ensure/:taskId") + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + ensureTaskQueue(taskId, ctx); + }); + + router.post("/test/queue/enqueueTaskStatusUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + enqueueTaskStatusUpdateEvent(taskId, body, ctx); + }); + + router.post("/test/queue/enqueueTaskArtifactUpdateEvent/:taskId") + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + enqueueTaskArtifactUpdateEvent(taskId, body, ctx); + }); + + router.get("/test/streamingSubscribedCount") + .produces(TEXT_PLAIN) + .handler(ctx -> getStreamingSubscribedCount(ctx)); + + router.get("/test/queue/childCount/:taskId") + .produces(TEXT_PLAIN) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getChildQueueCount(taskId, ctx); + }); + + router.delete("/test/task/:taskId/config/:configId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String configId = ctx.pathParam("configId"); + deleteTaskPushNotificationConfig(taskId, configId, ctx); + }); + + router.post("/test/task/:taskId") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + saveTaskPushNotificationConfig(taskId, body, ctx); + }); + + router.post("/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs") + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String expectedCount = ctx.pathParam("expectedCount"); + String timeoutMs = ctx.pathParam("timeoutMs"); + awaitChildQueueCountStable(taskId, expectedCount, timeoutMs, ctx); + }); + } + + public void saveTask(String body, RoutingContext rc) { + try { + Task task = JsonUtil.fromJson(body, Task.class); + testUtilsBean.saveTask(task); + rc.response().setStatusCode(200).end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void getTask(String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response().setStatusCode(404).end(); + return; + } + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(JsonUtil.toJson(task)); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void deleteTask(String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response().setStatusCode(404).end(); + return; + } + testUtilsBean.deleteTask(taskId); + rc.response().setStatusCode(200).end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void ensureTaskQueue(String taskId, RoutingContext rc) { + try { + testUtilsBean.ensureQueue(taskId); + rc.response().setStatusCode(200).end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void enqueueTaskStatusUpdateEvent(String taskId, String body, RoutingContext rc) { + try { + TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response().setStatusCode(200).end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void enqueueTaskArtifactUpdateEvent(String taskId, String body, RoutingContext rc) { + try { + TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response().setStatusCode(200).end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void getStreamingSubscribedCount(RoutingContext rc) { + rc.response().setStatusCode(200).end(String.valueOf(streamingSubscribedCount.get())); + } + + public void getChildQueueCount(String taskId, RoutingContext rc) { + int count = testUtilsBean.getChildQueueCount(taskId); + rc.response().setStatusCode(200).end(String.valueOf(count)); + } + + public void deleteTaskPushNotificationConfig(String taskId, String configId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response().setStatusCode(404).end(); + return; + } + testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); + rc.response().setStatusCode(200).end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void saveTaskPushNotificationConfig(String taskId, String body, RoutingContext rc) { + try { + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); + if (notificationConfig == null) { + rc.response().setStatusCode(404).end(); + return; + } + testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); + rc.response().setStatusCode(200).end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void awaitChildQueueCountStable(String taskId, String expectedCountStr, String timeoutMsStr, RoutingContext rc) { + try { + int expectedCount = Integer.parseInt(expectedCountStr); + long timeoutMs = Long.parseLong(timeoutMsStr); + boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); + rc.response().setStatusCode(200).end(String.valueOf(stable)); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + private void errorResponse(Throwable t, RoutingContext rc) { + t.printStackTrace(); + rc.response().setStatusCode(500).putHeader(CONTENT_TYPE, TEXT_PLAIN).end(); + } +} diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java new file mode 100644 index 000000000..15c480c51 --- /dev/null +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java @@ -0,0 +1,27 @@ +package org.a2aproject.sdk.tests.multiversion.jsonrpc; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class AuthTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + Map.entry("test.identity.auto-auth", "false"), + Map.entry("test.agent.security.enabled", "true"), + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + Map.entry("quarkus.http.auth.basic", "true"), + Map.entry("quarkus.http.auth.proactive", "true") + ); + } + + @Override + public String getConfigProfile() { + return "test"; + } +} diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java new file mode 100644 index 000000000..6c9a2789e --- /dev/null +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java @@ -0,0 +1,39 @@ +package org.a2aproject.sdk.tests.multiversion.jsonrpc; + +import io.quarkus.test.junit.QuarkusTest; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerTest; +import org.a2aproject.sdk.spec.TransportProtocol; + +@QuarkusTest +public class MultiVersionJSONRPCTest extends AbstractA2AServerTest { + + @Inject + Vertx vertx; + + public MultiVersionJSONRPCTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(JSONRPCTransport.class, + new JSONRPCTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx))); + } +} diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java new file mode 100644 index 000000000..d04c5461a --- /dev/null +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java @@ -0,0 +1,54 @@ +package org.a2aproject.sdk.tests.multiversion.jsonrpc; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.spec.TransportProtocol; + +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class MultiVersionJSONRPCWithAuthTest extends AbstractA2AServerWithAuthTest { + + @Inject + Vertx vertx; + + public MultiVersionJSONRPCWithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(JSONRPCTransport.class, + new JSONRPCTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx)) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(JSONRPCTransport.class, + new JSONRPCTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx))); + } +} diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java new file mode 100644 index 000000000..0e6fca443 --- /dev/null +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java @@ -0,0 +1,39 @@ +package org.a2aproject.sdk.tests.multiversion.jsonrpc; + +import io.quarkus.test.junit.QuarkusTest; +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class MultiVersionJSONRPC_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { + + public MultiVersionJSONRPC_v0_3_Test() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); + } + + @Test + @Override + @Disabled("Agent card is v1.0 format in dual-version mode") + public void testGetAgentCard() { + } +} diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java new file mode 100644 index 000000000..3bf088d92 --- /dev/null +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java @@ -0,0 +1,53 @@ +package org.a2aproject.sdk.tests.multiversion.jsonrpc; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class MultiVersionJSONRPC_v0_3_WithAuthTest extends AbstractA2AServerWithAuthTest_v0_3 { + + public MultiVersionJSONRPC_v0_3_WithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3() + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); + } + + @Test + @Override + @Disabled("Agent card is v1.0 format in dual-version mode") + public void testGetAgentCardIsPublic() { + } +} diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java new file mode 100644 index 000000000..45a8c301a --- /dev/null +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java @@ -0,0 +1,29 @@ +package org.a2aproject.sdk.tests.multiversion.jsonrpc; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.quarkus.arc.Unremovable; +import io.quarkus.arc.properties.IfBuildProperty; +import io.quarkus.security.identity.AuthenticationRequestContext; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.identity.SecurityIdentityAugmentor; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; + +@ApplicationScoped +@Unremovable +@IfBuildProperty(name = "test.identity.auto-auth", stringValue = "true", enableIfMissing = true) +public class TestIdentityProvider implements SecurityIdentityAugmentor { + + @Override + public Uni augment(SecurityIdentity identity, AuthenticationRequestContext context) { + if (identity.isAnonymous()) { + return Uni.createFrom().item(QuarkusSecurityIdentity.builder() + .setPrincipal(() -> "testuser") + .addRole("user") + .setAnonymous(false) + .build()); + } + return Uni.createFrom().item(identity); + } +} diff --git a/tests/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties b/tests/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties new file mode 100644 index 000000000..2d2582df3 --- /dev/null +++ b/tests/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=JSONRPC diff --git a/tests/reference/jsonrpc/src/test/resources/application.properties b/tests/reference/jsonrpc/src/test/resources/application.properties new file mode 100644 index 000000000..c37fd6a00 --- /dev/null +++ b/tests/reference/jsonrpc/src/test/resources/application.properties @@ -0,0 +1,17 @@ +# Index the v0.3 server-conversion test-jar for CDI bean discovery +quarkus.index-dependency.server-conversion.group-id=org.a2aproject.sdk +quarkus.index-dependency.server-conversion.artifact-id=a2a-java-sdk-compat-0.3-server-conversion +quarkus.index-dependency.server-conversion.classifier=tests + +quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttpClient,org.a2aproject.sdk.compat03.conversion.TestHttpClient_v0_3 + +# Exclude v0.3 AgentExecutorProducer to avoid CDI ambiguity with the v1.0 one +quarkus.arc.exclude-types=org.a2aproject.sdk.compat03.conversion.AgentExecutorProducer_v0_3 + +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG + +%test.quarkus.test-security.test-enabled=true +%test.quarkus.test-security.user=testuser +%test.quarkus.test-security.roles=user diff --git a/tests/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties b/tests/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties new file mode 100644 index 000000000..2d94ad8ab --- /dev/null +++ b/tests/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=jsonrpc diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index c2e5a4781..da46e8d61 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -38,6 +38,7 @@ import io.restassured.config.ObjectMapperConfig; import io.restassured.specification.RequestSpecification; import org.a2aproject.sdk.client.Client; +import org.a2aproject.sdk.common.A2AHeaders; import org.a2aproject.sdk.client.ClientBuilder; import org.a2aproject.sdk.client.ClientEvent; import org.a2aproject.sdk.client.MessageEvent; @@ -130,6 +131,7 @@ public abstract class AbstractA2AServerTest { public static RequestSpecification given() { return RestAssured.given() + .header(A2AHeaders.A2A_VERSION, AgentInterface.CURRENT_PROTOCOL_VERSION) .config(RestAssured.config() .objectMapperConfig(new ObjectMapperConfig(A2AGsonObjectMapper.INSTANCE))); } @@ -2340,7 +2342,8 @@ private CompletableFuture>> initialiseStreamingReque HttpRequest.Builder builder = HttpRequest.newBuilder() .uri(URI.create("http://localhost:" + serverPort + "/")) .POST(HttpRequest.BodyPublishers.ofString(body)) - .header("Content-Type", APPLICATION_JSON); + .header("Content-Type", APPLICATION_JSON) + .header(A2AHeaders.A2A_VERSION, AgentInterface.CURRENT_PROTOCOL_VERSION); if (mediaType != null) { builder.header("Accept", mediaType); } From bcecfd6c58c9e6818852072c0038c8e7e03951ec Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 1 May 2026 17:10:12 +0100 Subject: [PATCH 148/192] feat: add dual-version REST and gRPC test modules Add test modules at tests/reference/rest/ and tests/reference/grpc/ that verify both v1.0 and v0.3 protocol clients work simultaneously against a single server instance. Each module includes v1.0 tests (AbstractA2AServerTest), v0.3 tests (AbstractA2AServerServerTest_v0_3), and authentication test variants for both versions. The REST streaming callback method setStreamingMultiSseSupportSubscribedRunnable is made public in both A2AServerRoutes and A2AServerRoutes_v0_3 so the multiversion test infrastructure can register callbacks from a different package. Co-Authored-By: Claude Opus 4.6 --- .../rest/quarkus/A2AServerRoutes_v0_3.java | 2 +- pom.xml | 2 + .../server/rest/quarkus/A2AServerRoutes.java | 2 +- tests/reference/grpc/pom.xml | 141 ++++++++ .../multiversion/grpc/A2ATestResource.java | 178 ++++++++++ .../multiversion/grpc/AuthTestProfile.java | 47 +++ .../grpc/MultiVersionGrpcTest.java | 58 ++++ .../grpc/MultiVersionGrpcWithAuthTest.java | 113 ++++++ .../grpc/MultiVersion_v0_3_GrpcTest.java | 53 +++ .../MultiVersion_v0_3_GrpcWithAuthTest.java | 101 ++++++ .../grpc/TestAuthorizationController.java | 34 ++ .../a2a-requesthandler-test.properties | 1 + .../src/test/resources/application.properties | 21 ++ .../compat-0.3-requesthandler-test.properties | 1 + tests/reference/rest/pom.xml | 133 ++++++++ .../multiversion/rest/A2ATestRoutes.java | 321 ++++++++++++++++++ .../multiversion/rest/AuthTestProfile.java | 27 ++ .../rest/MultiVersionRestTest.java | 39 +++ .../rest/MultiVersionRestWithAuthTest.java | 68 ++++ .../rest/MultiVersion_v0_3_RestTest.java | 39 +++ .../MultiVersion_v0_3_RestWithAuthTest.java | 66 ++++ .../rest/TestIdentityProvider.java | 29 ++ .../a2a-requesthandler-test.properties | 1 + .../src/test/resources/application.properties | 17 + .../compat-0.3-requesthandler-test.properties | 1 + 25 files changed, 1493 insertions(+), 2 deletions(-) create mode 100644 tests/reference/grpc/pom.xml create mode 100644 tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java create mode 100644 tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java create mode 100644 tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java create mode 100644 tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java create mode 100644 tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java create mode 100644 tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java create mode 100644 tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java create mode 100644 tests/reference/grpc/src/test/resources/a2a-requesthandler-test.properties create mode 100644 tests/reference/grpc/src/test/resources/application.properties create mode 100644 tests/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties create mode 100644 tests/reference/rest/pom.xml create mode 100644 tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java create mode 100644 tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java create mode 100644 tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java create mode 100644 tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java create mode 100644 tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java create mode 100644 tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java create mode 100644 tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java create mode 100644 tests/reference/rest/src/test/resources/a2a-requesthandler-test.properties create mode 100644 tests/reference/rest/src/test/resources/application.properties create mode 100644 tests/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java index 7ef264a8c..26c3d8092 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -387,7 +387,7 @@ private static String formatSseEvent(String data, long id) { return "data: " + data + "\nid: " + id + "\n\n"; } - static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { + public static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { streamingMultiSseSupportSubscribedRunnable = runnable; } diff --git a/pom.xml b/pom.xml index f0beff065..7c8bc76ec 100644 --- a/pom.xml +++ b/pom.xml @@ -598,6 +598,8 @@ tests/reference/jsonrpc + tests/reference/rest + tests/reference/grpc boms/extras diff --git a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java index a563f20a9..339a29ecc 100644 --- a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java @@ -836,7 +836,7 @@ public void methodNotFoundMessage(RoutingContext rc) { sendResponse(rc, response); } - static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { + public static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { streamingMultiSseSupportSubscribedRunnable = runnable; } diff --git a/tests/reference/grpc/pom.xml b/tests/reference/grpc/pom.xml new file mode 100644 index 000000000..40369c8ab --- /dev/null +++ b/tests/reference/grpc/pom.xml @@ -0,0 +1,141 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.0.Beta2-SNAPSHOT + ../../../pom.xml + + a2a-java-sdk-tests-multiversion-grpc + + jar + + Java A2A SDK Tests Dual-Version gRPC + Tests for dual v1.0/v0.3 gRPC deployment + + + + + ${project.groupId} + a2a-java-sdk-reference-grpc + ${project.version} + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-reference-grpc + ${project.version} + + + + + ${project.groupId} + a2a-java-sdk-reference-common + + + + + ${project.groupId} + a2a-java-sdk-tests-server-common + provided + + + ${project.groupId} + a2a-java-sdk-tests-server-common + test-jar + test + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + ${project.version} + test-jar + test + + + + + ${project.groupId} + a2a-java-sdk-client-transport-grpc + test + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + ${project.version} + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-grpc + ${project.version} + test + + + + + io.quarkus + quarkus-grpc + + + + io.quarkus + quarkus-rest + test + + + + + io.quarkus + quarkus-junit5 + test + + + org.junit.jupiter + junit-jupiter-api + test + + + io.rest-assured + rest-assured + test + + + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + + + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java new file mode 100644 index 000000000..b5ac86735 --- /dev/null +++ b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java @@ -0,0 +1,178 @@ +package org.a2aproject.sdk.tests.multiversion.grpc; + +import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; + +import java.util.concurrent.atomic.AtomicInteger; + +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import org.a2aproject.sdk.compat03.transport.grpc.handler.GrpcHandler_v0_3; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.apps.common.TestUtilsBean; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.transport.grpc.handler.GrpcHandler; + +@Path("/test") +@ApplicationScoped +public class A2ATestResource { + @Inject + TestUtilsBean testUtilsBean; + + private final AtomicInteger streamingSubscribedCount = new AtomicInteger(0); + + @PostConstruct + public void init() { + Runnable callback = streamingSubscribedCount::incrementAndGet; + GrpcHandler.setStreamingSubscribedRunnable(callback); + GrpcHandler_v0_3.setStreamingSubscribedRunnable(callback); + } + + @POST + @Path("/task") + @Consumes(MediaType.APPLICATION_JSON) + public Response saveTask(String body) throws Exception { + Task task = JsonUtil.fromJson(body, Task.class); + testUtilsBean.saveTask(task); + return Response.ok().build(); + } + + @GET + @Path("/task/{taskId}") + public Response getTask(@PathParam("taskId") String taskId) throws Exception { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + return Response.status(404).build(); + } + return Response.ok() + .entity(JsonUtil.toJson(task)) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .build(); + } + + @DELETE + @Path("/task/{taskId}") + public Response deleteTask(@PathParam("taskId") String taskId) { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + return Response.status(404).build(); + } + testUtilsBean.deleteTask(taskId); + return Response.ok() + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .build(); + } + + @POST + @Path("/queue/ensure/{taskId}") + public Response ensureQueue(@PathParam("taskId") String taskId) { + testUtilsBean.ensureQueue(taskId); + return Response.ok().build(); + } + + @POST + @Path("/queue/enqueueTaskStatusUpdateEvent/{taskId}") + public Response enqueueTaskStatusUpdateEvent(@PathParam("taskId") String taskId, String body) throws Exception { + TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + return Response.ok().build(); + } + + @POST + @Path("/queue/enqueueTaskArtifactUpdateEvent/{taskId}") + public Response enqueueTaskArtifactUpdateEvent(@PathParam("taskId") String taskId, String body) throws Exception { + TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + return Response.ok().build(); + } + + @GET + @Path("/streamingSubscribedCount") + @Produces(TEXT_PLAIN) + public Response getStreamingSubscribedCount() { + return Response.ok(String.valueOf(streamingSubscribedCount.get()), TEXT_PLAIN).build(); + } + + @GET + @Path("/queue/childCount/{taskId}") + @Produces(TEXT_PLAIN) + public Response getChildQueueCount(@PathParam("taskId") String taskId) { + int count = testUtilsBean.getChildQueueCount(taskId); + return Response.ok(String.valueOf(count), TEXT_PLAIN).build(); + } + + @DELETE + @Path("/task/{taskId}/config/{configId}") + public Response deleteTaskPushNotificationConfig(@PathParam("taskId") String taskId, @PathParam("configId") String configId) { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + return Response.status(404).build(); + } + testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); + return Response.ok() + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .build(); + } + + @POST + @Path("/task/{taskId}") + @Consumes(MediaType.APPLICATION_JSON) + public Response savePushNotificationConfigInStore(@PathParam("taskId") String taskId, String body) throws Exception { + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); + if (notificationConfig == null) { + return Response.status(404).build(); + } + testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); + return Response.ok().build(); + } + + /** + * REST endpoint to wait for queue poller to start. + * Waits for the EventConsumer polling loop to start for the specified task's queue, + * ensuring the queue is ready to receive and process events. + * + * @param taskId the task ID whose queue poller to wait for + * @return HTTP 200 response when poller has started + * @throws InterruptedException if interrupted while waiting + */ + @POST + @Path("/queue/awaitPollerStart/{taskId}") + public Response awaitQueuePollerStart(@PathParam("taskId") String taskId) throws InterruptedException { + testUtilsBean.awaitQueuePollerStart(taskId); + return Response.ok().build(); + } + + /** + * REST endpoint to wait for child queue count to stabilize. + * Waits for the specified task's child queue count to match expectedCount for 3 consecutive + * checks (150ms total), ensuring EventConsumer polling loops have started. + * + * @param taskId the task ID whose child queues to monitor + * @param expectedCount the expected number of active child queues + * @param timeoutMs maximum time to wait in milliseconds + * @return HTTP 200 response with "true" if count stabilized, "false" if timeout occurred + * @throws InterruptedException if interrupted while waiting + */ + @POST + @Path("/queue/awaitChildCountStable/{taskId}/{expectedCount}/{timeoutMs}") + public Response awaitChildQueueCountStable(@PathParam("taskId") String taskId, + @PathParam("expectedCount") int expectedCount, + @PathParam("timeoutMs") long timeoutMs) throws InterruptedException { + boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); + return Response.ok(String.valueOf(stable), TEXT_PLAIN).build(); + } +} diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java new file mode 100644 index 000000000..8ce1da4d9 --- /dev/null +++ b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java @@ -0,0 +1,47 @@ +package org.a2aproject.sdk.tests.multiversion.grpc; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +/** + * Quarkus test profile that enables security for authentication tests. + *

            + * This profile: + *

              + *
            • Enables embedded user store with a test user
            • + *
            • Configures HTTP Basic authentication
            • + *
            • Provides test credentials: username=testuser, password=testpass
            • + *
            + */ +public class AuthTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + // Disable test security (injected test user) - we want REAL authentication + Map.entry("quarkus.test.security.auth.enabled", "false"), + + // Enable embedded user store + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + + // Enable security in agent card + Map.entry("test.agent.security.enabled", "true"), + + // Enable authorization so @Authenticated is enforced + Map.entry("test.authorization.enabled", "true"), + + // Enable HTTP Basic authentication + Map.entry("quarkus.http.auth.basic", "true") + ); + } + + @Override + public String getConfigProfile() { + // Use "test" profile to ensure test beans are active + return "test"; + } +} diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java new file mode 100644 index 000000000..32d1f7722 --- /dev/null +++ b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java @@ -0,0 +1,58 @@ +package org.a2aproject.sdk.tests.multiversion.grpc; + +import java.util.concurrent.TimeUnit; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.quarkus.test.junit.QuarkusTest; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransport; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransportConfigBuilder; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerTest; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.junit.jupiter.api.AfterAll; + +@QuarkusTest +public class MultiVersionGrpcTest extends AbstractA2AServerTest { + + private static ManagedChannel channel; + + public MultiVersionGrpcTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.GRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder().channelFactory(target -> { + channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build(); + return channel; + })); + } + + @AfterAll + public static void closeChannel() { + if (channel != null) { + channel.shutdownNow(); + try { + channel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + @Override + public void testAgentCardHeaders() { + // Skip - gRPC doesn't use HTTP caching headers for Agent Card + } +} diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java new file mode 100644 index 000000000..887a1572c --- /dev/null +++ b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java @@ -0,0 +1,113 @@ +package org.a2aproject.sdk.tests.multiversion.grpc; + +import java.util.concurrent.TimeUnit; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import jakarta.inject.Inject; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransport; +import org.a2aproject.sdk.client.transport.grpc.GrpcTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class MultiVersionGrpcWithAuthTest extends AbstractA2AServerWithAuthTest { + + @Inject + @PublicAgentCard + AgentCard agentCard; + + private static ManagedChannel authenticatedChannel; + private static ManagedChannel unauthenticatedChannel; + + public MultiVersionGrpcWithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.GRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder() + .channelFactory(target -> { + authenticatedChannel = ManagedChannelBuilder + .forTarget(target) + .usePlaintext() + .build(); + return authenticatedChannel; + }) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder().channelFactory(target -> { + unauthenticatedChannel = ManagedChannelBuilder + .forTarget(target) + .usePlaintext() + .build(); + return unauthenticatedChannel; + })); + } + + @AfterAll + public static void closeChannels() { + if (authenticatedChannel != null) { + authenticatedChannel.shutdownNow(); + try { + authenticatedChannel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + if (unauthenticatedChannel != null) { + unauthenticatedChannel.shutdownNow(); + try { + unauthenticatedChannel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + @Override + protected AgentCard fetchAgentCardFromServer() { + return agentCard; + } + + @Test + @Override + @Disabled + public void testGetAgentCardIsPublic() { + // Skip - gRPC doesn't have /.well-known/agent-card.json endpoint + } + + @Test + @Override + @Disabled + public void testBasicAuthWorksViaHttp() { + // Skip - HTTP-specific test + } +} diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java new file mode 100644 index 000000000..de1acebf2 --- /dev/null +++ b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java @@ -0,0 +1,53 @@ +package org.a2aproject.sdk.tests.multiversion.grpc; + +import java.util.concurrent.TimeUnit; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.quarkus.test.junit.QuarkusTest; +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import org.junit.jupiter.api.AfterAll; + +@QuarkusTest +public class MultiVersion_v0_3_GrpcTest extends AbstractA2AServerServerTest_v0_3 { + + private static ManagedChannel channel; + + public MultiVersion_v0_3_GrpcTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.GRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(GrpcTransport_v0_3.class, new GrpcTransportConfigBuilder_v0_3().channelFactory(target -> { + channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build(); + return channel; + })); + } + + @AfterAll + public static void closeChannel() { + if (channel != null) { + channel.shutdownNow(); + try { + channel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } +} diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java new file mode 100644 index 000000000..70dc46c7b --- /dev/null +++ b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java @@ -0,0 +1,101 @@ +package org.a2aproject.sdk.tests.multiversion.grpc; + +import java.util.concurrent.TimeUnit; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class MultiVersion_v0_3_GrpcWithAuthTest extends AbstractA2AServerWithAuthTest_v0_3 { + + private static ManagedChannel authenticatedChannel; + private static ManagedChannel unauthenticatedChannel; + + public MultiVersion_v0_3_GrpcWithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.GRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(GrpcTransport_v0_3.class, new GrpcTransportConfigBuilder_v0_3() + .channelFactory(target -> { + authenticatedChannel = ManagedChannelBuilder + .forTarget(target) + .usePlaintext() + .build(); + return authenticatedChannel; + }) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(GrpcTransport_v0_3.class, new GrpcTransportConfigBuilder_v0_3().channelFactory(target -> { + unauthenticatedChannel = ManagedChannelBuilder + .forTarget(target) + .usePlaintext() + .build(); + return unauthenticatedChannel; + })); + } + + @AfterAll + public static void closeChannels() { + if (authenticatedChannel != null) { + authenticatedChannel.shutdownNow(); + try { + authenticatedChannel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + if (unauthenticatedChannel != null) { + unauthenticatedChannel.shutdownNow(); + try { + unauthenticatedChannel.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + @Test + @Override + @Disabled + public void testGetAgentCardIsPublic() { + // Skip - gRPC doesn't have /.well-known/agent-card.json endpoint + } + + @Test + @Override + @Disabled + public void testBasicAuthWorksViaHttp() { + // Skip - HTTP-specific test + } +} diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java new file mode 100644 index 000000000..ceed3df67 --- /dev/null +++ b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java @@ -0,0 +1,34 @@ +package org.a2aproject.sdk.tests.multiversion.grpc; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.Alternative; +import jakarta.inject.Singleton; +import jakarta.interceptor.Interceptor; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import io.quarkus.security.spi.runtime.AuthorizationController; + +/** + * Disables authorization for regular gRPC tests. + *

            + * The {@code @Authenticated} CDI interceptor checks {@link AuthorizationController#isAuthorizationEnabled()} + * before enforcing. When disabled, {@code @Authenticated} becomes a no-op, allowing + * regular tests to run without credentials. + *

            + * {@link AuthTestProfile} sets {@code test.authorization.enabled=true} to enforce + * real authentication for auth-specific tests. + */ +@Alternative +@Priority(Interceptor.Priority.LIBRARY_AFTER + 1) +@Singleton +public class TestAuthorizationController extends AuthorizationController { + + @ConfigProperty(name = "test.authorization.enabled", defaultValue = "false") + boolean enabled; + + @Override + public boolean isAuthorizationEnabled() { + return enabled; + } +} diff --git a/tests/reference/grpc/src/test/resources/a2a-requesthandler-test.properties b/tests/reference/grpc/src/test/resources/a2a-requesthandler-test.properties new file mode 100644 index 000000000..a8f637a17 --- /dev/null +++ b/tests/reference/grpc/src/test/resources/a2a-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=GRPC diff --git a/tests/reference/grpc/src/test/resources/application.properties b/tests/reference/grpc/src/test/resources/application.properties new file mode 100644 index 000000000..cbcd8fdd9 --- /dev/null +++ b/tests/reference/grpc/src/test/resources/application.properties @@ -0,0 +1,21 @@ +# gRPC server configuration - use main HTTP port (not separate port) +quarkus.grpc.server.use-separate-server=false +quarkus.http.port=8081 + +# Index the v0.3 server-conversion test-jar for CDI bean discovery +quarkus.index-dependency.server-conversion.group-id=org.a2aproject.sdk +quarkus.index-dependency.server-conversion.artifact-id=a2a-java-sdk-compat-0.3-server-conversion +quarkus.index-dependency.server-conversion.classifier=tests + +quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttpClient,org.a2aproject.sdk.compat03.conversion.TestHttpClient_v0_3 + +# Exclude v0.3 AgentExecutorProducer to avoid CDI ambiguity with the v1.0 one +quarkus.arc.exclude-types=org.a2aproject.sdk.compat03.conversion.AgentExecutorProducer_v0_3 + +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG + +%test.quarkus.test-security.test-enabled=true +%test.quarkus.test-security.user=testuser +%test.quarkus.test-security.roles=user diff --git a/tests/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties b/tests/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties new file mode 100644 index 000000000..941770fb9 --- /dev/null +++ b/tests/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=grpc diff --git a/tests/reference/rest/pom.xml b/tests/reference/rest/pom.xml new file mode 100644 index 000000000..24dfe1651 --- /dev/null +++ b/tests/reference/rest/pom.xml @@ -0,0 +1,133 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.0.Beta2-SNAPSHOT + ../../../pom.xml + + a2a-java-sdk-tests-multiversion-rest + + jar + + Java A2A SDK Tests Dual-Version REST + Tests for dual v1.0/v0.3 REST deployment + + + + + ${project.groupId} + a2a-java-sdk-reference-multiversion-rest + ${project.version} + + + + + ${project.groupId} + a2a-java-sdk-tests-server-common + provided + + + ${project.groupId} + a2a-java-sdk-tests-server-common + test-jar + test + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-server-conversion + ${project.version} + test-jar + test + + + + + ${project.groupId} + a2a-java-sdk-http-client-vertx + test + + + ${project.groupId} + a2a-java-sdk-client-transport-rest + test + + + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client + ${project.version} + test + + + ${project.groupId} + a2a-java-sdk-compat-0.3-client-transport-rest + ${project.version} + test + + + + + com.google.protobuf + protobuf-java-util + test + + + + + io.quarkus + quarkus-junit5 + test + + + io.quarkus + quarkus-rest-client + test + + + org.junit.jupiter + junit-jupiter-api + test + + + io.rest-assured + rest-assured + test + + + + + io.quarkus + quarkus-security + test + + + io.quarkus + quarkus-elytron-security-properties-file + test + + + io.quarkus + quarkus-test-security + test + + + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java new file mode 100644 index 000000000..950699473 --- /dev/null +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java @@ -0,0 +1,321 @@ +package org.a2aproject.sdk.tests.multiversion.rest; + +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; + +import java.util.concurrent.atomic.AtomicInteger; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Priority; +import jakarta.enterprise.event.Observes; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; +import org.a2aproject.sdk.compat03.server.rest.quarkus.A2AServerRoutes_v0_3; +import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.apps.common.TestUtilsBean; +import org.a2aproject.sdk.server.rest.quarkus.A2AServerRoutes; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; + +/** + * Exposes the {@link TestUtilsBean} via REST using the Vert.x Web Router + */ +@Singleton +public class A2ATestRoutes { + @Inject + TestUtilsBean testUtilsBean; + + @Inject + A2AServerRoutes a2AServerRoutes; + + @Inject + A2AServerRoutes_v0_3 a2AServerRoutes_v0_3; + + AtomicInteger streamingSubscribedCount = new AtomicInteger(0); + + @PostConstruct + public void init() { + Runnable callback = () -> streamingSubscribedCount.incrementAndGet(); + A2AServerRoutes.setStreamingMultiSseSupportSubscribedRunnable(callback); + A2AServerRoutes_v0_3.setStreamingMultiSseSupportSubscribedRunnable(callback); + } + + void setupRouter(@Observes @Priority(1) Router router) { + // Test routes - no authentication required (these are test utilities) + // Don't add global BodyHandler - it interferes with other routes + // Instead, add BodyHandler per-route below + + // POST /test/task - Save task + router.post("/test/task") + .order(0) + .consumes(APPLICATION_JSON) + .handler(BodyHandler.create()) + .blockingHandler(ctx -> { + String body = ctx.body().asString(); + if (body == null) { + body = ""; + } + saveTask(body, ctx); + }); + + // GET /test/task/:taskId - Get task + router.get("/test/task/:taskId") + .order(0) + .produces(APPLICATION_JSON) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getTask(taskId, ctx); + }); + + // DELETE /test/task/:taskId - Delete task + router.delete("/test/task/:taskId") + .order(0) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + deleteTask(taskId, ctx); + }); + + // POST /test/queue/ensure/:taskId - Ensure task queue + router.post("/test/queue/ensure/:taskId") + .order(0) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + ensureTaskQueue(taskId, ctx); + }); + + // POST /test/queue/enqueueTaskStatusUpdateEvent/:taskId + router.post("/test/queue/enqueueTaskStatusUpdateEvent/:taskId") + .order(0) + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + if (body == null) { + body = ""; + } + enqueueTaskStatusUpdateEvent(taskId, body, ctx); + }); + + // POST /test/queue/enqueueTaskArtifactUpdateEvent/:taskId + router.post("/test/queue/enqueueTaskArtifactUpdateEvent/:taskId") + .order(0) + .handler(BodyHandler.create()) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + if (body == null) { + body = ""; + } + enqueueTaskArtifactUpdateEvent(taskId, body, ctx); + }); + + // GET /test/streamingSubscribedCount + router.get("/test/streamingSubscribedCount") + .order(0) + .produces(TEXT_PLAIN) + .handler(ctx -> { + getStreamingSubscribedCount(ctx); + }); + + // GET /test/queue/childCount/:taskId + router.get("/test/queue/childCount/:taskId") + .order(0) + .produces(TEXT_PLAIN) + .handler(ctx -> { + String taskId = ctx.pathParam("taskId"); + getChildQueueCount(taskId, ctx); + }); + + // DELETE /test/task/:taskId/config/:configId + router.delete("/test/task/:taskId/config/:configId") + .order(0) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String configId = ctx.pathParam("configId"); + deleteTaskPushNotificationConfig(taskId, configId, ctx); + }); + + // POST /test/task/:taskId - Save task push notification config + router.post("/test/task/:taskId") + .order(0) + .handler(BodyHandler.create()) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String body = ctx.body().asString(); + if (body == null) { + body = ""; + } + saveTaskPushNotificationConfig(taskId, body, ctx); + }); + + // POST /test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs + router.post("/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs") + .order(0) + .blockingHandler(ctx -> { + String taskId = ctx.pathParam("taskId"); + String expectedCountStr = ctx.pathParam("expectedCount"); + String timeoutMsStr = ctx.pathParam("timeoutMs"); + awaitChildQueueCountStable(taskId, expectedCountStr, timeoutMsStr, ctx); + }); + } + + public void saveTask(String body, RoutingContext rc) { + try { + Task task = JsonUtil.fromJson(body, Task.class); + testUtilsBean.saveTask(task); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void getTask(String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + rc.response() + .setStatusCode(200) + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .end(JsonUtil.toJson(task)); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void deleteTask(String taskId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.deleteTask(taskId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void ensureTaskQueue(String taskId, RoutingContext rc) { + try { + testUtilsBean.ensureQueue(taskId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void enqueueTaskStatusUpdateEvent(String taskId, String body, RoutingContext rc) { + try { + TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void enqueueTaskArtifactUpdateEvent(String taskId, String body, RoutingContext rc) { + try { + TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); + testUtilsBean.enqueueEvent(taskId, event); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void getStreamingSubscribedCount(RoutingContext rc) { + rc.response() + .setStatusCode(200) + .end(String.valueOf(streamingSubscribedCount.get())); + } + + public void getChildQueueCount(String taskId, RoutingContext rc) { + int count = testUtilsBean.getChildQueueCount(taskId); + rc.response() + .setStatusCode(200) + .end(String.valueOf(count)); + } + + public void deleteTaskPushNotificationConfig(String taskId, String configId, RoutingContext rc) { + try { + Task task = testUtilsBean.getTask(taskId); + if (task == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void saveTaskPushNotificationConfig(String taskId, String body, RoutingContext rc) { + try { + TaskPushNotificationConfig notificationConfig = JsonUtil.fromJson(body, TaskPushNotificationConfig.class); + if (notificationConfig == null) { + rc.response() + .setStatusCode(404) + .end(); + return; + } + testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); + rc.response() + .setStatusCode(200) + .end(); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + public void awaitChildQueueCountStable(String taskId, String expectedCountStr, String timeoutMsStr, RoutingContext rc) { + try { + int expectedCount = Integer.parseInt(expectedCountStr); + long timeoutMs = Long.parseLong(timeoutMsStr); + boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); + rc.response() + .setStatusCode(200) + .end(String.valueOf(stable)); + } catch (Throwable t) { + errorResponse(t, rc); + } + } + + private void errorResponse(Throwable t, RoutingContext rc) { + t.printStackTrace(); + rc.response() + .setStatusCode(500) + .putHeader(CONTENT_TYPE, TEXT_PLAIN) + .end(); + } +} diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java new file mode 100644 index 000000000..710fc9a08 --- /dev/null +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java @@ -0,0 +1,27 @@ +package org.a2aproject.sdk.tests.multiversion.rest; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class AuthTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.ofEntries( + Map.entry("test.identity.auto-auth", "false"), + Map.entry("test.agent.security.enabled", "true"), + Map.entry("quarkus.security.users.embedded.enabled", "true"), + Map.entry("quarkus.security.users.embedded.plain-text", "true"), + Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), + Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), + Map.entry("quarkus.http.auth.basic", "true"), + Map.entry("quarkus.http.auth.proactive", "true") + ); + } + + @Override + public String getConfigProfile() { + return "test"; + } +} diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java new file mode 100644 index 000000000..2644c89d0 --- /dev/null +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java @@ -0,0 +1,39 @@ +package org.a2aproject.sdk.tests.multiversion.rest; + +import io.quarkus.test.junit.QuarkusTest; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerTest; +import org.a2aproject.sdk.spec.TransportProtocol; + +@QuarkusTest +public class MultiVersionRestTest extends AbstractA2AServerTest { + + @Inject + Vertx vertx; + + public MultiVersionRestTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx))); + } +} diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java new file mode 100644 index 000000000..e47913545 --- /dev/null +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java @@ -0,0 +1,68 @@ +package org.a2aproject.sdk.tests.multiversion.rest; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.spec.TransportProtocol; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class MultiVersionRestWithAuthTest extends AbstractA2AServerWithAuthTest { + + @Inject + Vertx vertx; + + public MultiVersionRestWithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx)) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new VertxA2AHttpClient(vertx))); + } + + @Test + @Override + public void testBasicAuthWorksViaHttp() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .get("/tasks/" + MINIMAL_TASK.id()) + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.id()); + } +} diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java new file mode 100644 index 000000000..44017451e --- /dev/null +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java @@ -0,0 +1,39 @@ +package org.a2aproject.sdk.tests.multiversion.rest; + +import io.quarkus.test.junit.QuarkusTest; +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class MultiVersion_v0_3_RestTest extends AbstractA2AServerServerTest_v0_3 { + + public MultiVersion_v0_3_RestTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); + } + + @Test + @Override + @Disabled("Agent card is v1.0 format in dual-version mode") + public void testGetAgentCard() { + } +} diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java new file mode 100644 index 000000000..bc804c5ed --- /dev/null +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java @@ -0,0 +1,66 @@ +package org.a2aproject.sdk.tests.multiversion.rest; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class MultiVersion_v0_3_RestWithAuthTest extends AbstractA2AServerWithAuthTest_v0_3 { + + public MultiVersion_v0_3_RestWithAuthTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3() + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); + } + + @Test + @Override + @Disabled("Agent card is v1.0 format in dual-version mode") + public void testGetAgentCardIsPublic() { + } + + @Test + @Override + public void testBasicAuthWorksViaHttp() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .get("/v1/tasks/" + MINIMAL_TASK.getId()) + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } +} diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java new file mode 100644 index 000000000..7a34c1278 --- /dev/null +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java @@ -0,0 +1,29 @@ +package org.a2aproject.sdk.tests.multiversion.rest; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.quarkus.arc.Unremovable; +import io.quarkus.arc.properties.IfBuildProperty; +import io.quarkus.security.identity.AuthenticationRequestContext; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.identity.SecurityIdentityAugmentor; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; + +@ApplicationScoped +@Unremovable +@IfBuildProperty(name = "test.identity.auto-auth", stringValue = "true", enableIfMissing = true) +public class TestIdentityProvider implements SecurityIdentityAugmentor { + + @Override + public Uni augment(SecurityIdentity identity, AuthenticationRequestContext context) { + if (identity.isAnonymous()) { + return Uni.createFrom().item(QuarkusSecurityIdentity.builder() + .setPrincipal(() -> "testuser") + .addRole("user") + .setAnonymous(false) + .build()); + } + return Uni.createFrom().item(identity); + } +} diff --git a/tests/reference/rest/src/test/resources/a2a-requesthandler-test.properties b/tests/reference/rest/src/test/resources/a2a-requesthandler-test.properties new file mode 100644 index 000000000..61696e179 --- /dev/null +++ b/tests/reference/rest/src/test/resources/a2a-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=HTTP+JSON diff --git a/tests/reference/rest/src/test/resources/application.properties b/tests/reference/rest/src/test/resources/application.properties new file mode 100644 index 000000000..c37fd6a00 --- /dev/null +++ b/tests/reference/rest/src/test/resources/application.properties @@ -0,0 +1,17 @@ +# Index the v0.3 server-conversion test-jar for CDI bean discovery +quarkus.index-dependency.server-conversion.group-id=org.a2aproject.sdk +quarkus.index-dependency.server-conversion.artifact-id=a2a-java-sdk-compat-0.3-server-conversion +quarkus.index-dependency.server-conversion.classifier=tests + +quarkus.arc.selected-alternatives=org.a2aproject.sdk.server.apps.common.TestHttpClient,org.a2aproject.sdk.compat03.conversion.TestHttpClient_v0_3 + +# Exclude v0.3 AgentExecutorProducer to avoid CDI ambiguity with the v1.0 one +quarkus.arc.exclude-types=org.a2aproject.sdk.compat03.conversion.AgentExecutorProducer_v0_3 + +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG + +%test.quarkus.test-security.test-enabled=true +%test.quarkus.test-security.user=testuser +%test.quarkus.test-security.roles=user diff --git a/tests/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties b/tests/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties new file mode 100644 index 000000000..51b04b93c --- /dev/null +++ b/tests/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties @@ -0,0 +1 @@ +preferred-transport=http From 301aab81e4162158077a211650a4b472406adf4d Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 1 May 2026 17:30:01 +0100 Subject: [PATCH 149/192] fix: default missing A2A-Version to 0.3 per spec Section 3.6.2 The spec requires that agents interpret empty/missing A2A-Version as 0.3 for backward compatibility. Previously defaulted to the current protocol version (1.0). All transport handler tests updated to explicitly pass version "1.0" in their test contexts. Co-Authored-By: Claude Opus 4.6 --- .../server/version/A2AVersionValidator.java | 8 ++-- .../version/A2AVersionValidatorTest.java | 48 +++++++++++++++---- .../grpc/handler/GrpcHandlerTest.java | 29 +++++++---- .../jsonrpc/handler/JSONRPCHandlerTest.java | 32 ++++++++----- .../rest/handler/RestHandlerTest.java | 24 ++++++---- 5 files changed, 97 insertions(+), 44 deletions(-) diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java b/server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java index 2afb2d9cf..2019ffceb 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java @@ -17,8 +17,8 @@ *

          • Minor versions are compatible (1.0 client can talk to 1.1 server and vice versa)
          • * * - *

            If the client does not specify a version, the current protocol version - * ({@link AgentInterface#CURRENT_PROTOCOL_VERSION}) is assumed as the default. + *

            Per A2A spec Section 3.6.2, if the client does not specify a version, + * version "0.3" is assumed for backward compatibility. */ public class A2AVersionValidator { @@ -34,9 +34,9 @@ public static void validateProtocolVersion(AgentCard agentCard, ServerCallContex throws VersionNotSupportedError { String requestedVersion = context.getRequestedProtocolVersion(); - // If client didn't specify a version, default to current version + // Per spec Section 3.6.2: empty/missing A2A-Version defaults to 0.3 if (requestedVersion == null || requestedVersion.trim().isEmpty()) { - requestedVersion = AgentInterface.CURRENT_PROTOCOL_VERSION; + requestedVersion = "0.3"; } // Collect all unique protocol versions from all supported interfaces diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java index 9079a9773..8901137d1 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java @@ -50,22 +50,46 @@ public void testIsVersionCompatible_InvalidFormat() { } @Test - public void testValidateProtocolVersion_NoVersionProvided_DefaultsTo1_0() { - // When no version is provided, should default to 1.0 and succeed + public void testValidateProtocolVersion_NoVersionProvided_DefaultsTo0_3() { + // Per spec Section 3.6.2: missing A2A-Version defaults to 0.3 + // A v1.0-only server should reject this AgentCard agentCard = createAgentCard("1.0"); ServerCallContext context = createContext(null); - // Should not throw - defaults to 1.0 which matches - assertDoesNotThrow(() -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); + VersionNotSupportedError error = assertThrows(VersionNotSupportedError.class, + () -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); + assertTrue(error.getMessage().contains("0.3")); + assertTrue(error.getMessage().contains("not supported")); } @Test - public void testValidateProtocolVersion_EmptyVersionProvided_DefaultsTo1_0() { - // When empty version is provided, should default to 1.0 and succeed + public void testValidateProtocolVersion_EmptyVersionProvided_DefaultsTo0_3() { + // Per spec Section 3.6.2: empty A2A-Version defaults to 0.3 + // A v1.0-only server should reject this AgentCard agentCard = createAgentCard("1.0"); ServerCallContext context = createContext(""); - // Should not throw - defaults to 1.0 which matches + VersionNotSupportedError error = assertThrows(VersionNotSupportedError.class, + () -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); + assertTrue(error.getMessage().contains("0.3")); + assertTrue(error.getMessage().contains("not supported")); + } + + @Test + public void testValidateProtocolVersion_NoVersionProvided_DualVersionServer() { + // A server supporting both 1.0 and 0.3 should accept missing version (defaults to 0.3) + AgentCard agentCard = createAgentCardWithVersions("1.0", "0.3"); + ServerCallContext context = createContext(null); + + assertDoesNotThrow(() -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); + } + + @Test + public void testValidateProtocolVersion_NoVersionProvided_V03OnlyServer() { + // A v0.3-only server should accept missing version (defaults to 0.3) + AgentCard agentCard = createAgentCard("0.3"); + ServerCallContext context = createContext(null); + assertDoesNotThrow(() -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); } @@ -141,10 +165,18 @@ public void testValidateProtocolVersion_InvalidVersionFormat() { } private AgentCard createAgentCard(String protocolVersion) { + return createAgentCardWithVersions(protocolVersion); + } + + private AgentCard createAgentCardWithVersions(String... protocolVersions) { + List interfaces = new java.util.ArrayList<>(); + for (String version : protocolVersions) { + interfaces.add(new AgentInterface("GRPC", "http://localhost:9999", "", version)); + } return AgentCard.builder() .name("test-card") .description("Test card") - .supportedInterfaces(List.of(new AgentInterface("GRPC", "http://localhost:9999", "", protocolVersion))) + .supportedInterfaces(interfaces) .version("1.0.0") .capabilities(AgentCapabilities.builder() .streaming(false) diff --git a/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java index a3f281b3b..8a0b13530 100644 --- a/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java +++ b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java @@ -942,7 +942,8 @@ public ServerCallContext create(StreamObserver streamObserver) { return new ServerCallContext( UnauthenticatedUser.INSTANCE, Map.of("grpc_response_observer", streamObserver), - requestedExtensions + requestedExtensions, + "1.0" ); } }; @@ -1109,8 +1110,8 @@ public ServerCallContext create(StreamObserver streamObserver) { } @Test - public void testNoVersionDefaultsToCurrentVersionSuccess() throws Exception { - // Create AgentCard with protocol version 1.0 (current version) + public void testNoVersionDefaultsTo0_3_RejectedByV10OnlyServer() throws Exception { + // Per spec Section 3.6.2: missing A2A-Version defaults to 0.3 AgentCard agentCard = AgentCard.builder() .name("test-card") .description("Test card with version 1.0") @@ -1125,7 +1126,7 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() throws Exception { .skills(List.of()) .build(); - // Create handler that provides null version (should default to 1.0) + // Create handler that provides null version — defaults to 0.3, incompatible with v1.0-only GrpcHandler handler = new TestGrpcHandler(agentCard, requestHandler, internalExecutor) { @Override protected CallContextFactory getCallContextFactory() { @@ -1136,7 +1137,7 @@ public ServerCallContext create(StreamObserver streamObserver) { UnauthenticatedUser.INSTANCE, Map.of("grpc_response_observer", streamObserver), new HashSet<>(), - null // No version - should default to 1.0 + null ); } }; @@ -1155,9 +1156,9 @@ public ServerCallContext create(StreamObserver streamObserver) { handler.sendMessage(request, streamRecorder); streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - // Should succeed without error (defaults to 1.0) - Assertions.assertNull(streamRecorder.getError()); - Assertions.assertFalse(streamRecorder.getValues().isEmpty()); + // Should fail with VersionNotSupportedError (0.3 is not supported by v1.0-only server) + Assertions.assertNotNull(streamRecorder.getError()); + Assertions.assertInstanceOf(io.grpc.StatusRuntimeException.class, streamRecorder.getError()); } private StreamRecorder sendMessageRequest(GrpcHandler handler) throws Exception { @@ -1308,7 +1309,17 @@ protected AgentCard getExtendedAgentCard() { @Override protected CallContextFactory getCallContextFactory() { - return null; + return new CallContextFactory() { + @Override + public ServerCallContext create(StreamObserver streamObserver) { + return new ServerCallContext( + UnauthenticatedUser.INSTANCE, + Map.of("grpc_response_observer", streamObserver), + new HashSet<>(), + "1.0" + ); + } + }; } @Override diff --git a/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java b/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java index f8d4cf74d..9aa8fbccb 100644 --- a/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java +++ b/transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java @@ -2,6 +2,7 @@ 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.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -91,7 +92,7 @@ @Timeout(value = 1, unit = TimeUnit.MINUTES) public class JSONRPCHandlerTest extends AbstractA2ARequestHandlerTest { - private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>(), "1.0"); private static MessageSendConfiguration defaultConfiguration() { return MessageSendConfiguration.builder() @@ -998,7 +999,7 @@ public void testOnSubscribeNoExistingTaskError() { TaskNotFoundError.class, () -> handler.onSubscribeToTask(request, callContext)); - Assertions.assertNotNull(thrown); + assertNotNull(thrown); } @Test @@ -1135,7 +1136,7 @@ public void testOnGetPushNotificationNoPushNotifierConfig() { MINIMAL_TASK.id(),"c295ea44-7543-4f78-b524-7a38915ad6e4")); GetTaskPushNotificationConfigResponse response = handler.getPushNotificationConfig(request, callContext); - Assertions.assertNotNull(response.getError()); + assertNotNull(response.getError()); assertInstanceOf(UnsupportedOperationError.class, response.getError()); assertEquals("This operation is not supported", response.getError().getMessage()); } @@ -1742,7 +1743,8 @@ public void testRequiredExtensionProvidedSuccess() { ServerCallContext contextWithExtension = new ServerCallContext( UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), - requestedExtensions + requestedExtensions, + "1.0" ); agentExecutorExecute = (context, agentEmitter) -> { @@ -1921,8 +1923,8 @@ public void testCompatibleVersionSuccess() { } @Test - public void testNoVersionDefaultsToCurrentVersionSuccess() { - // Create AgentCard with protocol version 1.0 (current version) + public void testNoVersionDefaultsTo0_3_RejectedByV10OnlyServer() { + // Per spec Section 3.6.2: missing A2A-Version defaults to 0.3 AgentCard agentCard = AgentCard.builder() .name("test-card") .description("Test card with version 1.0") @@ -1940,21 +1942,25 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { JSONRPCHandler handler = new JSONRPCHandler(agentCard, requestHandler, internalExecutor); taskStore.save(MINIMAL_TASK, false); - // Use default callContext (no version - should default to 1.0) agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); }; + // Context with no version — defaults to 0.3, which is incompatible with v1.0-only server + ServerCallContext noVersionContext = new ServerCallContext( + UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + Message message = Message.builder(MESSAGE) .taskId(MINIMAL_TASK.id()) .contextId(MINIMAL_TASK.contextId()) .build(); SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, callContext); + SendMessageResponse response = handler.onMessageSend(request, noVersionContext); - // Should succeed without error (defaults to 1.0) - assertNull(response.getError()); - Assertions.assertSame(message, response.getResult()); + // Should return VersionNotSupportedError + assertNotNull(response.getError()); + assertInstanceOf(VersionNotSupportedError.class, response.getError()); + assertTrue(response.getError().getMessage().contains("0.3")); } @Test @@ -1972,8 +1978,8 @@ public void testListTasksEmptyResultIncludesAllFields() { // Should return success with all fields present (not null) assertNull(response.getError()); ListTasksResult result = response.getResult(); - Assertions.assertNotNull(result); - Assertions.assertNotNull(result.tasks(), "tasks field should not be null"); + assertNotNull(result); + assertNotNull(result.tasks(), "tasks field should not be null"); assertEquals(0, result.tasks().size(), "tasks should be empty list"); assertEquals(0, result.totalSize(), "totalSize should be 0"); assertEquals(0, result.pageSize(), "pageSize should be 0"); diff --git a/transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java b/transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java index 5cd00114f..8be11c609 100644 --- a/transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java +++ b/transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java @@ -35,7 +35,7 @@ @Timeout(value = 1, unit = TimeUnit.MINUTES) public class RestHandlerTest extends AbstractA2ARequestHandlerTest { - private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>(), "1.0"); private static AgentCardCacheMetadata createCacheMetadata() { return createCacheMetadata(CARD); @@ -722,7 +722,8 @@ public void testRequiredExtensionProvidedSuccess() { ServerCallContext contextWithExtension = new ServerCallContext( UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), - requestedExtensions + requestedExtensions, + "1.0" ); agentExecutorExecute = (context, agentEmitter) -> { @@ -955,8 +956,8 @@ public void testCompatibleVersionSuccess() { } @Test - public void testNoVersionDefaultsToCurrentVersionSuccess() { - // Create AgentCard with protocol version 1.0 (current version) + public void testNoVersionDefaultsTo0_3_RejectedByV10OnlyServer() { + // Per spec Section 3.6.2: missing A2A-Version defaults to 0.3 AgentCard agentCard = AgentCard.builder() .name("test-card") .description("Test card with version 1.0") @@ -973,11 +974,14 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { RestHandler handler = new RestHandler(agentCard, createCacheMetadata(agentCard), requestHandler, internalExecutor); - // Use default callContext (no version - should default to 1.0) agentExecutorExecute = (context, agentEmitter) -> { agentEmitter.sendMessage(context.getMessage()); }; + // Context with no version — defaults to 0.3, incompatible with v1.0-only server + ServerCallContext noVersionContext = new ServerCallContext( + UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + String requestBody = """ { "message": { @@ -994,12 +998,12 @@ public void testNoVersionDefaultsToCurrentVersionSuccess() { } }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); + RestHandler.HTTPRestResponse response = handler.sendMessage(noVersionContext, "", requestBody); - // Should succeed without error (defaults to 1.0) - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals(APPLICATION_JSON, response.getContentType()); - Assertions.assertNotNull(response.getBody()); + // Should return error (0.3 is not supported by v1.0-only server) + Assertions.assertEquals(400, response.getStatusCode()); + Assertions.assertTrue(response.getBody().contains("0.3")); + Assertions.assertTrue(response.getBody().contains("not supported")); } @Test From 4164b868b1bdb1225badd989fe2d81d6fb6453fb Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 5 May 2026 14:36:53 +0100 Subject: [PATCH 150/192] fix: Align Compat VertX Web usage with lastest changes in main code --- .../grpc/quarkus/AuthTestProfile_v0_3.java | 36 ------------------ .../QuarkusA2AGrpc_v0_3_WithAuthTest.java | 1 + .../apps/quarkus/A2AServerRoutes_v0_3.java | 2 +- .../QuarkusA2AJSONRPC_v0_3_WithAuthTest.java | 1 + .../rest/quarkus/A2AServerRoutes_v0_3.java | 13 ++++--- .../rest/quarkus/AuthTestProfile_v0_3.java | 37 ------------------- .../QuarkusA2ARest_v0_3_WithAuthTest.java | 1 + .../quarkus/TestIdentityProvider_v0_3.java | 29 --------------- compat-0.3/server-conversion/pom.xml | 14 +++++++ .../conversion}/AuthTestProfile_v0_3.java | 10 ++++- .../TestIdentityProvider_v0_3.java | 2 +- .../rest/handler/RestHandler_v0_3.java | 13 ++++++- .../jsonrpc/MultiVersionJSONRPCRoutes.java | 3 +- .../rest/MultiVersionRestRoutes.java | 6 +-- .../multiversion/grpc/AuthTestProfile.java | 22 +++++++---- 15 files changed, 65 insertions(+), 125 deletions(-) delete mode 100644 compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/AuthTestProfile_v0_3.java delete mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/AuthTestProfile_v0_3.java delete mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/TestIdentityProvider_v0_3.java rename compat-0.3/{reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus => server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion}/AuthTestProfile_v0_3.java (75%) rename compat-0.3/{reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus => server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion}/TestIdentityProvider_v0_3.java (95%) diff --git a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/AuthTestProfile_v0_3.java b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/AuthTestProfile_v0_3.java deleted file mode 100644 index 29a137595..000000000 --- a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/AuthTestProfile_v0_3.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.a2aproject.sdk.compat03.server.grpc.quarkus; - -import java.util.Map; - -import io.quarkus.test.junit.QuarkusTestProfile; - -public class AuthTestProfile_v0_3 implements QuarkusTestProfile { - - @Override - public Map getConfigOverrides() { - return Map.ofEntries( - // Disable test security (injected test user) - we want REAL authentication - Map.entry("quarkus.test.security.auth.enabled", "false"), - - // Enable embedded user store - Map.entry("quarkus.security.users.embedded.enabled", "true"), - Map.entry("quarkus.security.users.embedded.plain-text", "true"), - Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), - Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), - - // Enable security in agent card - Map.entry("test.agent.security.enabled", "true"), - - // Enable authorization so @Authenticated is enforced - Map.entry("test.authorization.enabled", "true"), - - // Enable HTTP Basic authentication - Map.entry("quarkus.http.auth.basic", "true") - ); - } - - @Override - public String getConfigProfile() { - return "test"; - } -} diff --git a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_WithAuthTest.java b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_WithAuthTest.java index f14470efd..bb23598e9 100644 --- a/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_WithAuthTest.java +++ b/compat-0.3/reference/grpc/src/test/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusA2AGrpc_v0_3_WithAuthTest.java @@ -7,6 +7,7 @@ import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java index 1ee3e53a9..5e268ca9c 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -99,7 +99,7 @@ void setupRoutes(@Observes Router router) { invokeJSONRPCHandler(ctx.body().asString(), ctx); }); } catch (UnauthorizedException | ForbiddenException e) { - VertxSecurityHelper.handleAuthError(ctx, e); + vertxSecurityHelper.handleAuthError(ctx, e); } catch (Exception e) { VertxSecurityHelper.handleGenericError(ctx); } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java index 1ef8b516f..ba0818924 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java @@ -5,6 +5,7 @@ import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java index 26c3d8092..bc76641cf 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -150,7 +150,7 @@ private Handler authenticated(Consumer action) { try { vertxSecurityHelper.runInRequestContext(ctx, () -> action.accept(ctx)); } catch (UnauthorizedException | ForbiddenException e) { - VertxSecurityHelper.handleAuthError(ctx, e); + vertxSecurityHelper.handleAuthError(ctx, e); } catch (Exception e) { VertxSecurityHelper.handleGenericError(ctx); } @@ -253,10 +253,13 @@ public void cancelTask(RoutingContext rc) { private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response) { if (response != null) { - rc.response() + var httpResponse = rc.response() .setStatusCode(response.getStatusCode()) - .putHeader(CONTENT_TYPE, response.getContentType()) - .end(response.getBody()); + .putHeader(CONTENT_TYPE, response.getContentType()); + + response.getHeaders().forEach(httpResponse::putHeader); + + httpResponse.end(response.getBody()); } else { rc.response().end(); } @@ -466,7 +469,7 @@ public void onSubscribe(Flow.Subscription subscription) { this.upstream.request(1); response.closeHandler(v -> { - logger.info("REST SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); + logger.debug("REST SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); context.invokeEventConsumerCancelCallback(); subscription.cancel(); }); diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/AuthTestProfile_v0_3.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/AuthTestProfile_v0_3.java deleted file mode 100644 index 30fc51072..000000000 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/AuthTestProfile_v0_3.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.a2aproject.sdk.compat03.server.rest.quarkus; - -import java.util.Map; - -import io.quarkus.test.junit.QuarkusTestProfile; - -public class AuthTestProfile_v0_3 implements QuarkusTestProfile { - - @Override - public Map getConfigOverrides() { - return Map.ofEntries( - // Disable test security (injected test user) - we want REAL authentication - Map.entry("quarkus.test.security.auth.enabled", "false"), - - // Disable TestIdentityProvider auto-authentication - Map.entry("test.identity.auto-auth", "false"), - - // Enable security in agent card - Map.entry("test.agent.security.enabled", "true"), - - // Enable embedded user store - Map.entry("quarkus.security.users.embedded.enabled", "true"), - Map.entry("quarkus.security.users.embedded.plain-text", "true"), - Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), - Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), - - // Enable HTTP Basic authentication - Map.entry("quarkus.http.auth.basic", "true"), - Map.entry("quarkus.http.auth.proactive", "true") - ); - } - - @Override - public String getConfigProfile() { - return "test"; - } -} diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java index 9109d5fbb..4cc5d54a4 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java @@ -5,6 +5,7 @@ import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/TestIdentityProvider_v0_3.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/TestIdentityProvider_v0_3.java deleted file mode 100644 index a8576b71d..000000000 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/TestIdentityProvider_v0_3.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.a2aproject.sdk.compat03.server.rest.quarkus; - -import jakarta.enterprise.context.ApplicationScoped; - -import io.quarkus.arc.Unremovable; -import io.quarkus.arc.properties.IfBuildProperty; -import io.quarkus.security.identity.AuthenticationRequestContext; -import io.quarkus.security.identity.SecurityIdentity; -import io.quarkus.security.identity.SecurityIdentityAugmentor; -import io.quarkus.security.runtime.QuarkusSecurityIdentity; -import io.smallrye.mutiny.Uni; - -@ApplicationScoped -@Unremovable -@IfBuildProperty(name = "test.identity.auto-auth", stringValue = "true", enableIfMissing = true) -public class TestIdentityProvider_v0_3 implements SecurityIdentityAugmentor { - - @Override - public Uni augment(SecurityIdentity identity, AuthenticationRequestContext context) { - if (identity.isAnonymous()) { - return Uni.createFrom().item(QuarkusSecurityIdentity.builder() - .setPrincipal(() -> "testuser") - .addRole("user") - .setAnonymous(false) - .build()); - } - return Uni.createFrom().item(identity); - } -} diff --git a/compat-0.3/server-conversion/pom.xml b/compat-0.3/server-conversion/pom.xml index 9f5f3c174..811c6adb6 100644 --- a/compat-0.3/server-conversion/pom.xml +++ b/compat-0.3/server-conversion/pom.xml @@ -107,6 +107,20 @@ test + + + io.quarkus + quarkus-security + test + + + + + io.quarkus + quarkus-junit5 + test + + io.rest-assured diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/AuthTestProfile_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AuthTestProfile_v0_3.java similarity index 75% rename from compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/AuthTestProfile_v0_3.java rename to compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AuthTestProfile_v0_3.java index 348dffa3f..6e8e181d1 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/AuthTestProfile_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AuthTestProfile_v0_3.java @@ -1,4 +1,4 @@ -package org.a2aproject.sdk.compat03.server.apps.quarkus; +package org.a2aproject.sdk.compat03.conversion; import java.util.Map; @@ -9,12 +9,18 @@ public class AuthTestProfile_v0_3 implements QuarkusTestProfile { @Override public Map getConfigOverrides() { return Map.ofEntries( - // Disable the TestIdentityProvider - we want real authentication + // Disable TestIdentityProvider auto-authentication Map.entry("test.identity.auto-auth", "false"), + // Disable Quarkus test security + Map.entry("quarkus.test.security.auth.enabled", "false"), + // Enable security in AgentCard (server advertises Basic Auth support) Map.entry("test.agent.security.enabled", "true"), + // Enable authorization so @Authenticated is enforced (used by gRPC) + Map.entry("test.authorization.enabled", "true"), + // Enable embedded user store Map.entry("quarkus.security.users.embedded.enabled", "true"), Map.entry("quarkus.security.users.embedded.plain-text", "true"), diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/TestIdentityProvider_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestIdentityProvider_v0_3.java similarity index 95% rename from compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/TestIdentityProvider_v0_3.java rename to compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestIdentityProvider_v0_3.java index 40ff22620..ad582aa6c 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/TestIdentityProvider_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestIdentityProvider_v0_3.java @@ -1,4 +1,4 @@ -package org.a2aproject.sdk.compat03.server.apps.quarkus; +package org.a2aproject.sdk.compat03.conversion; import jakarta.enterprise.context.ApplicationScoped; diff --git a/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3.java b/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3.java index 39be61aee..8b08c6952 100644 --- a/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3.java +++ b/compat-0.3/transport/rest/src/main/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3.java @@ -11,6 +11,7 @@ import jakarta.inject.Inject; import java.util.List; +import java.util.Map; import java.util.concurrent.Flow; import org.a2aproject.sdk.server.ExtendedAgentCard; @@ -389,11 +390,17 @@ public static class HTTPRestResponse { private final int statusCode; private final String contentType; private final String body; + private final Map headers; public HTTPRestResponse(int statusCode, String contentType, String body) { + this(statusCode, contentType, body, Map.of()); + } + + public HTTPRestResponse(int statusCode, String contentType, String body, Map headers) { this.statusCode = statusCode; this.contentType = contentType; this.body = body; + this.headers = Map.copyOf(headers); } public int getStatusCode() { @@ -408,9 +415,13 @@ public String getBody() { return body; } + public Map getHeaders() { + return headers; + } + @Override public String toString() { - return "HTTPRestResponse{" + "statusCode=" + statusCode + ", contentType=" + contentType + ", body=" + body + '}'; + return "HTTPRestResponse{" + "statusCode=" + statusCode + ", contentType=" + contentType + ", body=" + body + ", headers=" + headers + '}'; } } diff --git a/reference/multiversion-jsonrpc/src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/MultiVersionJSONRPCRoutes.java b/reference/multiversion-jsonrpc/src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/MultiVersionJSONRPCRoutes.java index 2bf044c72..e8bc6c405 100644 --- a/reference/multiversion-jsonrpc/src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/MultiVersionJSONRPCRoutes.java +++ b/reference/multiversion-jsonrpc/src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/MultiVersionJSONRPCRoutes.java @@ -53,8 +53,7 @@ void setupRoutes(@Observes Router router) { null); } }); - } catch (UnauthorizedException | ForbiddenException e) { - VertxSecurityHelper.handleAuthError(ctx, e); + } catch (UnauthorizedException | ForbiddenException e) {vertxSecurityHelper.handleAuthError(ctx, e); } catch (A2AError e) { ctx.response() .setStatusCode(200) diff --git a/reference/multiversion-rest/src/main/java/org/a2aproject/sdk/server/multiversion/rest/MultiVersionRestRoutes.java b/reference/multiversion-rest/src/main/java/org/a2aproject/sdk/server/multiversion/rest/MultiVersionRestRoutes.java index d62f94d08..f607d0437 100644 --- a/reference/multiversion-rest/src/main/java/org/a2aproject/sdk/server/multiversion/rest/MultiVersionRestRoutes.java +++ b/reference/multiversion-rest/src/main/java/org/a2aproject/sdk/server/multiversion/rest/MultiVersionRestRoutes.java @@ -123,7 +123,7 @@ void setupRoutes(@Observes @Priority(5) Router router) { vertxSecurityHelper.runInRequestContext(ctx, () -> v03Routes.getAuthenticatedExtendedCard(ctx)); } catch (UnauthorizedException | ForbiddenException e) { - VertxSecurityHelper.handleAuthError(ctx, e); + vertxSecurityHelper.handleAuthError(ctx, e); } catch (Exception e) { VertxSecurityHelper.handleGenericError(ctx); } @@ -167,7 +167,7 @@ private io.vertx.core.Handler versionDispatch( } }); } catch (UnauthorizedException | ForbiddenException e) { - VertxSecurityHelper.handleAuthError(ctx, e); + vertxSecurityHelper.handleAuthError(ctx, e); } catch (A2AError e) { sendA2AErrorResponse(ctx, e); } catch (Exception e) { @@ -197,7 +197,7 @@ private io.vertx.core.Handler versionDispatchNoBody( } }); } catch (UnauthorizedException | ForbiddenException e) { - VertxSecurityHelper.handleAuthError(ctx, e); + vertxSecurityHelper.handleAuthError(ctx, e); } catch (A2AError e) { sendA2AErrorResponse(ctx, e); } catch (Exception e) { diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java index 8ce1da4d9..df13d0dd5 100644 --- a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java +++ b/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java @@ -19,23 +19,29 @@ public class AuthTestProfile implements QuarkusTestProfile { @Override public Map getConfigOverrides() { return Map.ofEntries( - // Disable test security (injected test user) - we want REAL authentication + // Disable TestIdentityProvider auto-authentication + Map.entry("test.identity.auto-auth", "false"), + + // Disable Quarkus test security Map.entry("quarkus.test.security.auth.enabled", "false"), + // Enable security in AgentCard (server advertises Basic Auth support) + Map.entry("test.agent.security.enabled", "true"), + + // Enable authorization so @Authenticated is enforced (used by gRPC) + Map.entry("test.authorization.enabled", "true"), + // Enable embedded user store Map.entry("quarkus.security.users.embedded.enabled", "true"), Map.entry("quarkus.security.users.embedded.plain-text", "true"), Map.entry("quarkus.security.users.embedded.users.testuser", "testpass"), Map.entry("quarkus.security.users.embedded.roles.testuser", "user"), - // Enable security in agent card - Map.entry("test.agent.security.enabled", "true"), - - // Enable authorization so @Authenticated is enforced - Map.entry("test.authorization.enabled", "true"), - // Enable HTTP Basic authentication - Map.entry("quarkus.http.auth.basic", "true") + Map.entry("quarkus.http.auth.basic", "true"), + + // Enable proactive authentication - authenticate at HTTP layer before route handler + Map.entry("quarkus.http.auth.proactive", "true") ); } From b835e9ff81d532dce7d543681f615b8186473300 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 11 May 2026 13:04:13 +0100 Subject: [PATCH 151/192] docs: document v0.3 compatibility layer and standardize terminology (#859) * docs: document v0.3 compatibility layer and standardize terminology - Update architecture doc (compatibility_0.3.md) to reflect current state: multi-version deployment is implemented, remove historical planning artifacts, add VersionRouter and multi-version module docs - Add README sections for serving v0.3 clients (standalone and multi-version) and communicating with v0.3 agents using Client_v0_3 - Standardize terminology from "dual-version" to "multi-version" across POM descriptions, @Disabled annotations, and test names - Add AGENTS.md reference to compatibility architecture doc This fixes #856 Co-Authored-By: Claude Opus 4.6 * review fixes --------- Co-authored-by: Claude Opus 4.6 --- .claude/architecture/compatibility_0.3.md | 200 +++++++++--------- AGENTS.md | 2 + README.md | 126 +++++++++++ pom.xml | 2 +- reference/multiversion-jsonrpc/pom.xml | 2 +- reference/multiversion-rest/pom.xml | 2 +- .../version/A2AVersionValidatorTest.java | 2 +- tests/reference/grpc/pom.xml | 4 +- tests/reference/jsonrpc/pom.xml | 4 +- .../MultiVersionJSONRPC_v0_3_Test.java | 2 +- ...MultiVersionJSONRPC_v0_3_WithAuthTest.java | 2 +- tests/reference/rest/pom.xml | 4 +- .../rest/MultiVersion_v0_3_RestTest.java | 2 +- .../MultiVersion_v0_3_RestWithAuthTest.java | 2 +- 14 files changed, 240 insertions(+), 116 deletions(-) diff --git a/.claude/architecture/compatibility_0.3.md b/.claude/architecture/compatibility_0.3.md index 5316027f9..c4406bca0 100644 --- a/.claude/architecture/compatibility_0.3.md +++ b/.claude/architecture/compatibility_0.3.md @@ -1,6 +1,6 @@ -# PRD: A2A Protocol 0.3 Backward Compatibility Layer +# A2A Protocol 0.3 Backward Compatibility Layer -> **Goal**: Allow the A2A Java SDK (v1.0) to interoperate with agents running protocol v0.3 through a dedicated compatibility layer. +> The A2A Java SDK (v1.0) interoperates with agents running protocol v0.3 through a dedicated compatibility layer. --- @@ -24,6 +24,8 @@ The A2A protocol evolved from v0.3 to v1.0 with significant breaking changes. Ex - TCK conformance tests for v0.3 - Integration test infrastructure (test-jar) for validating conversion layer - Inclusion in the SDK BOM as separate optional dependencies +- Multi-version server deployment: `reference/multiversion-jsonrpc` and `reference/multiversion-rest` modules that dispatch requests to v1.0 or v0.3 handlers based on `A2A-Version` header via `VersionRouter` +- Multi-version integration tests under `tests/reference/{jsonrpc,rest,grpc}` (package `org.a2aproject.sdk.tests.multiversion`) ### Out of Scope @@ -32,12 +34,6 @@ The A2A protocol evolved from v0.3 to v1.0 with significant breaking changes. Ex - Extras modules (OpenTelemetry, JPA stores, etc.) for v0.3 - v0.3 format agent card (v0.3 clients must be able to parse v1.0 agent card format) -### Deferred - -- **Dual-version server deployment**: Running both v1.0 and v0.3 transports simultaneously in a single server instance with a unified agent card - - **Current state**: v0.3 reference servers work standalone; need integration pattern for dual deployment - - **Remaining work**: Define CDI qualifier pattern, path prefix strategy, and unified agent card production - --- ## Breaking Changes: v0.3 → v1.0 @@ -245,6 +241,30 @@ compat-0.3/ └── pom.xml ``` +### Multi-Version Reference Modules + +These top-level modules provide version-dispatching routes that serve both v1.0 and v0.3 requests from a single server instance: + +``` +reference/ +├── common/ # Shared utilities +│ └── src/main/java/org/a2aproject/sdk/server/common/quarkus/ +│ └── VersionRouter.java # Resolves protocol version from A2A-Version header +├── multiversion-jsonrpc/ # Version-dispatching JSON-RPC routes +│ └── src/main/java/org/a2aproject/sdk/server/multiversion/jsonrpc/ +│ └── MultiVersionJSONRPCRoutes.java +└── multiversion-rest/ # Version-dispatching REST routes + └── src/main/java/org/a2aproject/sdk/server/multiversion/rest/ + └── MultiVersionRestRoutes.java + +tests/reference/ # Multi-version integration tests +├── jsonrpc/ # JSON-RPC multi-version tests +├── rest/ # REST multi-version tests +└── grpc/ # gRPC multi-version tests +``` + +**Note**: gRPC version dispatch is handled by protobuf package namespace (`a2a.v1` for v0.3 vs `lf.a2a.v1` for v1.0), so no `multiversion-grpc` module is needed. + ### Java Package Convention All compat-0.3 code uses the `org.a2aproject.sdk.compat03` package root: @@ -312,6 +332,32 @@ The `ErrorConverter_v0_3` class centralizes error translation between v0.3 and v **Location**: `compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/ErrorConverter_v0_3.java` +### Version Routing: `VersionRouter` + +The `VersionRouter` class in `reference/common` resolves the protocol version for incoming requests: + +**Location**: `reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VersionRouter.java` + +**Resolution Logic** (in `VersionRouter.resolveVersion()`): +1. Check the `A2A-Version` HTTP header +2. If absent, check the `A2A-Version` query parameter +3. If neither is present, default to `"0.3"` (backward compatibility with clients that don't send a version header) + +The caller then dispatches based on the resolved version: +```java +String version = VersionRouter.resolveVersion(routingContext); +if (VersionRouter.isV10(version)) { + // delegate to v1.0 handler +} else if (VersionRouter.isV03(version)) { + // delegate to v0.3 handler +} else { + // unrecognized version string — reject + throw new VersionNotSupportedError(...); +} +``` + +The multi-version route classes (`MultiVersionJSONRPCRoutes`, `MultiVersionRestRoutes`) use this pattern to dispatch every endpoint to the appropriate version handler. + --- ## Test Infrastructure @@ -378,27 +424,22 @@ The `server-conversion` module produces a test-jar containing shared test infras ``` -**2. Check the agent card and choose the right client:** +**2. Find the v0.3 interface and create the client:** ```java AgentCard card = // ... fetch agent card from /.well-known/agent-card.json -for (AgentInterface iface : card.supportedInterfaces()) { - if ("0.3".equals(iface.protocolVersion())) { - // Use the compat client for v0.3 agents - Client_v0_3 client = ClientBuilder_v0_3.forUrl(iface.url()) - .transport("JSONRPC") - .build(); - } else if ("1.0".equals(iface.protocolVersion())) { - // Use the standard client for v1.0 agents - Client client = ClientBuilder.forUrl(iface.url()) - .transport("JSONRPC") - .build(); - } -} -``` +// Find the v0.3 interface from the agent card +AgentInterface v03Interface = card.supportedInterfaces().stream() + .filter(iface -> "0.3".equals(iface.protocolVersion())) + .findFirst() + .orElseThrow(); -**3. Use the v0.3 client API:** +// Create the v0.3 compatibility client +Client_v0_3 client = ClientBuilder_v0_3.forUrl(v03Interface.url()) + .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()) + .build(); +``` `Client_v0_3` exposes only operations available in v0.3. Return types are v0.3 `org.a2aproject.sdk.compat03.spec` domain objects. @@ -433,76 +474,44 @@ public AgentCard_v0_3 agentCard() { The existing `AgentExecutor` implementation works unchanged. The compat reference module registers v0.3 transport endpoints via Quarkus CDI auto-discovery and delegates to the same `AgentExecutor` through the v1.0 server pipeline. -### Server: Serving Both v0.3 and v1.0 (Deferred) - -**Status**: Architecture is in place but dual-version deployment pattern is not yet defined. - -**Remaining work:** -- Define CDI qualifier pattern to differentiate v0.3 and v1.0 beans -- Establish path prefix strategy (e.g., `/v0.3` for compat endpoints) -- Unified agent card production with multiple `AgentInterface` entries -- Integration testing for dual-version scenarios - -**Recommended approach:** -1. Use separate URLs per protocol version (e.g., `http://localhost:9999` for v1.0, `http://localhost:9999/v0.3` for v0.3) -2. Declare both in the v1.0 agent card with different `protocolVersion` values -3. Register both transport handlers via Quarkus CDI with path-based routing - ---- - -## Implementation Summary - -The implementation was completed in phases: +### Server: Serving Multiple Protocol Versions -### Phase 1: Foundation -- Set up module structure and POMs -- Port v0.3 spec types to `compat-0.3/spec` -- Generate v0.3 gRPC classes in `compat-0.3/spec-grpc` -- Apply `_v0_3` suffix naming convention +To serve multiple protocol versions from the same server, add the compat reference module for each version you want to support alongside the v1.0 reference module. For example, to serve both v1.0 and v0.3 over JSON-RPC: -### Phase 2: Conversion Layer -- Create `server-conversion` module -- Implement `Convert_v0_3_To10RequestHandler` -- Build MapStruct mappers (params, domain, result) -- Centralize error conversion in `ErrorConverter_v0_3` -- Export test infrastructure via test-jar - -### Phase 3: Transport Handlers -- Implement server-side transport handlers (JSONRPC, gRPC, REST) -- Wire each transport to `Convert_v0_3_To10RequestHandler` -- Test with v1.0 backend via `AbstractA2ARequestHandlerTest_v0_3` - -### Phase 4: Client -- Implement `Client_v0_3` API -- Build client transports (JSONRPC, gRPC, REST) -- Validate against v0.3 spec constraints - -### Phase 5: Reference Servers -- Port Quarkus reference servers (JSONRPC, gRPC, REST) -- Integrate with test infrastructure -- Run integration tests using v0.3 client against v0.3 reference servers - -### Phase 6: Testing & Validation -- Port transport handler tests (37+ tests across 3 transports) -- Port streaming tests (Flow.Publisher, SSE, gRPC) -- Port reference server tests (125+ integration tests passing) -- Enable TCK module - ---- - -## Key Differences from Original Plan +```xml + + org.a2aproject.sdk + a2a-java-sdk-reference-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-jsonrpc + +``` -1. **Conversion layer as separate module**: Original plan embedded mapping in `spec-grpc`; implementation uses dedicated `server-conversion` module with `Convert_v0_3_To10RequestHandler` +For JSON-RPC and REST, multi-version convenience modules are also available that bundle all supported protocol versions with version-dispatching routes: -2. **`_v0_3` suffix naming**: Not in original plan; adopted to eliminate IDE naming conflicts (233 out of 284 classes had conflicts) +```xml + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-jsonrpc + -3. **No `reference/common` module**: Each reference server is standalone; no shared reference base + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-rest + +``` -4. **Test-jar pattern**: Test infrastructure exported from `server-conversion` module rather than reference common +**Version routing:** +- **JSON-RPC and REST**: Clients indicate their protocol version via the `A2A-Version` header (or query parameter). If absent, the server defaults to v0.3 for backward compatibility. +- **gRPC**: Version dispatch is handled by protobuf package namespace (`a2a.v1` vs `lf.a2a.v1`), so both v1.0 and v0.3 gRPC services are registered on the same port without a dedicated multi-version module. -5. **Package migration during implementation**: The main codebase migrated from `io.a2a` to `org.a2aproject.sdk` while this work was in progress (PRs #750, #786) +**Agent card**: The agent card is served in v1.0 format only. Older clients must be able to parse the v1.0 agent card format to discover their endpoint. -6. **Implementation order**: Test infrastructure built early; tests ported incrementally to validate conversion layer +**Integration tests**: Multi-version scenarios are tested under `tests/reference/{jsonrpc,rest,grpc}` using both v1.0 and v0.3 clients against a single server instance. --- @@ -522,23 +531,10 @@ The implementation was completed in phases: ## Status -✅ **Complete:** -- Module structure and POMs -- v0.3 spec types and gRPC generation -- Server conversion layer with all mappers -- Server-side transport handlers (JSONRPC, gRPC, REST) -- Client API and transports -- Reference servers (JSONRPC, gRPC, REST) -- Test infrastructure (test-jar pattern) -- Core integration tests (125+ passing) -- TCK module enabled +The v0.3 compatibility layer is fully implemented: spec types, gRPC generation, conversion layer, all three transport handlers (JSON-RPC, gRPC, REST), client API and transports, reference servers, multi-version deployment, test infrastructure, 125+ integration tests, and TCK module are all in place. -🔲 **Deferred:** -- Dual v1.0/v0.3 server deployment pattern -- Push notification test porting (requires TestHttpClient) +🔲 **Outstanding:** +- Push notification test porting (requires TestHttpClient; version-aware push notifications in PR #857) - Test metadata classes (classpath scanning) - -🧹 **Nice-to-have cleanup:** - Replace FQNs with imports (97 occurrences in 34 files) - Unify AgentCard producers across reference modules -- Remove obsolete TODOs diff --git a/AGENTS.md b/AGENTS.md index 2a4cf6586..9e325fb3f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -82,6 +82,8 @@ For detailed architectural documentation: - **[Queue Lifecycle](.claude/architecture/eventqueue/LIFECYCLE.md)**: Two-level protection, fire-and-forget, late reconnections - **[Request Flows](.claude/architecture/eventqueue/FLOWS.md)**: Non-streaming vs streaming, cleanup patterns - **[Usage Scenarios](.claude/architecture/eventqueue/SCENARIOS.md)**: Real-world patterns and common pitfalls +- **Compatibility with previous protocol versions**: + - 0.3 protocol compatibility layer: `.claude/architecture/compatibility_0.3.md` > 💡 Deep-dive docs are loaded on-demand when working in related areas. diff --git a/README.md b/README.md index f026731b9..8f21b8837 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,83 @@ a2a.blocking.consumption.timeout.seconds=5 **Note:** The reference server implementations (Quarkus-based) automatically include the MicroProfile Config integration, so properties work out of the box in `application.properties`. +### Serving Older Protocol Versions (Backward Compatibility) + +The A2A Java SDK includes compatibility layers that allow your server to accept requests from clients using older protocol versions. Each compatibility layer is a separate set of modules that you add to your project as needed. **No changes to your `AgentExecutor` are needed** — the compatibility layer converts older protocol requests to v1.0 internally before delegating to your agent. + +#### Adding v0.3 Protocol Support + +To enable v0.3 support, add the v0.3 compat reference module for your chosen transport alongside (or instead of) the v1.0 reference module: + +```xml + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-jsonrpc + + ${org.a2aproject.sdk.version} + + + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-rest + ${org.a2aproject.sdk.version} + + + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-grpc + ${org.a2aproject.sdk.version} + +``` + +For example, a server that supports **v1.0 and v0.3 over JSON-RPC** would include both: + +```xml + + org.a2aproject.sdk + a2a-java-sdk-reference-jsonrpc + ${org.a2aproject.sdk.version} + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-jsonrpc + ${org.a2aproject.sdk.version} + +``` + +A server that only needs to support **v0.3** would include only the compat dependency. + +#### Multi-Version Convenience Modules + +For JSON-RPC and REST, multi-version modules are provided that bundle all supported protocol versions together with version-dispatching routes: + +```xml + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-jsonrpc + ${org.a2aproject.sdk.version} + + + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-rest + ${org.a2aproject.sdk.version} + +``` + +These are a convenience — they transitively include all the individual compat reference modules. + +#### How Version Routing Works + +- **JSON-RPC and REST**: When serving multiple protocol versions, version routing inspects the `A2A-Version` HTTP header on each request. If the header is `"1.0"`, the request is routed to the v1.0 handler. If it is `"0.3"` or absent, the request is routed to the v0.3 handler. +- **gRPC**: Version dispatch is implicit — v0.3 clients use the `a2a.v1` protobuf package and v1.0 clients use `lf.a2a.v1`, so requests are routed to the correct service automatically. +- **Agent card**: The agent card is served in v1.0 format only. Older clients must be able to parse the v1.0 agent card. + ## A2A Client The A2A Java SDK provides a Java client implementation of the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/), allowing communication with A2A servers. The Java client implementation supports the following transports: @@ -636,6 +713,55 @@ client.subscribeToTask(taskIdParams, clientCallContext); AgentCard serverAgentCard = client.getAgentCard(); ``` +### Communicating with v0.3 Agents + +If you need to communicate with an agent that only supports protocol v0.3, use the compatibility client `Client_v0_3`. + +#### 1. Add the v0.3 client dependency + +```xml + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client + + ${org.a2aproject.sdk.version} + +``` + +#### 2. Add a v0.3 client transport dependency + +```xml + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + ${org.a2aproject.sdk.version} + +``` + +gRPC and REST transports are also available: +- `a2a-java-sdk-compat-0.3-client-transport-grpc` +- `a2a-java-sdk-compat-0.3-client-transport-rest` + +#### 3. Create the v0.3 client + +```java +AgentCard card = new A2ACardResolver("http://localhost:1234").getAgentCard(); + +// Find the v0.3 interface from the agent card +AgentInterface v03Interface = card.supportedInterfaces().stream() + .filter(iface -> "0.3".equals(iface.protocolVersion())) + .findFirst() + .orElseThrow(); + +// Create the v0.3 compatibility client +Client_v0_3 client = ClientBuilder_v0_3.forUrl(v03Interface.url()) + .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()) + .build(); +``` + +**Note:** `Client_v0_3` exposes only operations available in protocol v0.3. For example, `listTasks()` is not available (it was added in v1.0). Return types use v0.3 domain objects from the `org.a2aproject.sdk.compat03.spec` package. + ## Additional Examples ### Hello World Client Example diff --git a/pom.xml b/pom.xml index 73b84937c..6cbcf1285 100644 --- a/pom.xml +++ b/pom.xml @@ -596,7 +596,7 @@ reference/multiversion-jsonrpc reference/multiversion-rest - + tests/reference/jsonrpc tests/reference/rest tests/reference/grpc diff --git a/reference/multiversion-jsonrpc/pom.xml b/reference/multiversion-jsonrpc/pom.xml index 4b9a17cf1..35000e9ee 100644 --- a/reference/multiversion-jsonrpc/pom.xml +++ b/reference/multiversion-jsonrpc/pom.xml @@ -15,7 +15,7 @@ jar Java A2A SDK Reference Multiversion JSON-RPC - Version-dispatching routes for dual v1.0/v0.3 JSON-RPC deployment + Version-dispatching routes for multi-version v1.0/v0.3 JSON-RPC deployment diff --git a/reference/multiversion-rest/pom.xml b/reference/multiversion-rest/pom.xml index 3ad916b7d..bfd1f9a6d 100644 --- a/reference/multiversion-rest/pom.xml +++ b/reference/multiversion-rest/pom.xml @@ -15,7 +15,7 @@ jar Java A2A SDK Reference Multiversion REST - Version-dispatching routes for dual v1.0/v0.3 REST deployment + Version-dispatching routes for multi-version v1.0/v0.3 REST deployment diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java index 8901137d1..be8058b17 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/version/A2AVersionValidatorTest.java @@ -76,7 +76,7 @@ public void testValidateProtocolVersion_EmptyVersionProvided_DefaultsTo0_3() { } @Test - public void testValidateProtocolVersion_NoVersionProvided_DualVersionServer() { + public void testValidateProtocolVersion_NoVersionProvided_MultiVersionServer() { // A server supporting both 1.0 and 0.3 should accept missing version (defaults to 0.3) AgentCard agentCard = createAgentCardWithVersions("1.0", "0.3"); ServerCallContext context = createContext(null); diff --git a/tests/reference/grpc/pom.xml b/tests/reference/grpc/pom.xml index 40369c8ab..db09657af 100644 --- a/tests/reference/grpc/pom.xml +++ b/tests/reference/grpc/pom.xml @@ -14,8 +14,8 @@ jar - Java A2A SDK Tests Dual-Version gRPC - Tests for dual v1.0/v0.3 gRPC deployment + Java A2A SDK Tests Multi-Version gRPC + Tests for multi-version v1.0/v0.3 gRPC deployment diff --git a/tests/reference/jsonrpc/pom.xml b/tests/reference/jsonrpc/pom.xml index 4d2666a41..ef78c49cc 100644 --- a/tests/reference/jsonrpc/pom.xml +++ b/tests/reference/jsonrpc/pom.xml @@ -14,8 +14,8 @@ jar - Java A2A SDK Tests Dual-Version JSON-RPC - Tests for dual v1.0/v0.3 JSON-RPC deployment + Java A2A SDK Tests Multi-Version JSON-RPC + Tests for multi-version v1.0/v0.3 JSON-RPC deployment diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java index 0e6fca443..be70577cd 100644 --- a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java @@ -33,7 +33,7 @@ protected void configureTransport(ClientBuilder_v0_3 builder) { @Test @Override - @Disabled("Agent card is v1.0 format in dual-version mode") + @Disabled("Agent card is v1.0 format in multi-version mode") public void testGetAgentCard() { } } diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java index 3bf088d92..5cfe96ef4 100644 --- a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java @@ -47,7 +47,7 @@ protected void configureTransport(ClientBuilder_v0_3 builder) { @Test @Override - @Disabled("Agent card is v1.0 format in dual-version mode") + @Disabled("Agent card is v1.0 format in multi-version mode") public void testGetAgentCardIsPublic() { } } diff --git a/tests/reference/rest/pom.xml b/tests/reference/rest/pom.xml index 24dfe1651..3e4127db1 100644 --- a/tests/reference/rest/pom.xml +++ b/tests/reference/rest/pom.xml @@ -14,8 +14,8 @@ jar - Java A2A SDK Tests Dual-Version REST - Tests for dual v1.0/v0.3 REST deployment + Java A2A SDK Tests Multi-Version REST + Tests for multi-version v1.0/v0.3 REST deployment diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java index 44017451e..ee2623ba1 100644 --- a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java @@ -33,7 +33,7 @@ protected void configureTransport(ClientBuilder_v0_3 builder) { @Test @Override - @Disabled("Agent card is v1.0 format in dual-version mode") + @Disabled("Agent card is v1.0 format in multi-version mode") public void testGetAgentCard() { } } diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java index bc804c5ed..a9a496780 100644 --- a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java @@ -47,7 +47,7 @@ protected void configureTransport(ClientBuilder_v0_3 builder) { @Test @Override - @Disabled("Agent card is v1.0 format in dual-version mode") + @Disabled("Agent card is v1.0 format in multi-version mode") public void testGetAgentCardIsPublic() { } From f17c451145c5ba16408e5a0df6468d5218259260 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 11 May 2026 17:12:54 +0200 Subject: [PATCH 152/192] chore: add back tck modules (#861) Copy the generated code from a2a-tck/sut/a2a-java Signed-off-by: Jeff Mesnil --- .github/workflows/run-tck.yml | 11 +- pom.xml | 4 + tck/pom.xml | 66 ++++++++ .../sdk/sut/TckAgentCardProducer.java | 60 ++++++++ .../sdk/sut/TckAgentExecutorProducer.java | 144 ++++++++++++++++++ tck/src/main/resources/application.properties | 22 +++ 6 files changed, 297 insertions(+), 10 deletions(-) create mode 100644 tck/pom.xml create mode 100644 tck/src/main/java/org/a2aproject/sdk/sut/TckAgentCardProducer.java create mode 100644 tck/src/main/java/org/a2aproject/sdk/sut/TckAgentExecutorProducer.java create mode 100644 tck/src/main/resources/application.properties diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index 8184cdc2b..9c6533ab3 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -38,12 +38,6 @@ jobs: cache: maven - name: Build a2a-java SDK run: mvn -B install -DskipTests - - name: Extract a2a-java version - id: extract-version - run: | - A2A_JAVA_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) - echo "version=$A2A_JAVA_VERSION" >> $GITHUB_OUTPUT - echo "Detected a2a-java version: $A2A_JAVA_VERSION" - name: Checkout a2a-tck uses: actions/checkout@v6 with: @@ -59,12 +53,9 @@ jobs: pip install uv uv pip install -e . working-directory: a2a-tck - - name: Generate a2a-java SUT - run: A2A_JAVA_SDK_VERSION=${{ steps.extract-version.outputs.version }} make codegen-a2a-java-sut - working-directory: a2a-tck - name: Start SUT run: mvn -B quarkus:dev -Dquarkus.console.enabled=false & - working-directory: a2a-tck/sut/a2a-java + working-directory: tck - name: Wait for SUT to start run: | URL="${{ env.SUT_URL }}/.well-known/agent-card.json" diff --git a/pom.xml b/pom.xml index 6cbcf1285..18f3bea9e 100644 --- a/pom.xml +++ b/pom.xml @@ -605,6 +605,10 @@ boms/extras boms/reference boms/sdk + + + tck + diff --git a/tck/pom.xml b/tck/pom.xml new file mode 100644 index 000000000..41eaec905 --- /dev/null +++ b/tck/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.0.Beta2-SNAPSHOT + + a2a-java-sdk-tck-sut + A2A Java SDK: SUT for TCK + + + + org.a2aproject.sdk + a2a-java-sdk-client + + + org.a2aproject.sdk + a2a-java-sdk-reference-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-grpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-rest + + + jakarta.enterprise + jakarta.enterprise.cdi-api + provided + + + jakarta.ws.rs + jakarta.ws.rs-api + + + org.a2aproject.sdk + a2a-java-sdk-server-common + + + + + + + + io.quarkus.platform + quarkus-maven-plugin + true + + + + build + generate-code + generate-code-tests + + + + + + + diff --git a/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentCardProducer.java b/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentCardProducer.java new file mode 100644 index 000000000..f6c53705f --- /dev/null +++ b/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentCardProducer.java @@ -0,0 +1,60 @@ +package org.a2aproject.sdk.sut; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.TransportProtocol; + +/** + * CDI producer for the TCK agent card. + * + *

            Generated from Gherkin scenarios — do not edit by hand. + */ +@ApplicationScoped +public class TckAgentCardProducer { + + private static final String host = getEnvOrDefault("SUT_HOST", "localhost:9999"); + + @Produces + @PublicAgentCard + public AgentCard agentCard() { + String sutJsonRpcUrl = String.format("http://%s", host); + String sutRestUrl = sutJsonRpcUrl; + String sutGrpcUrl = host; + + return AgentCard.builder() + .name("A2A Java SDK System Under Test (SUT)") + .description("Auto-generated System Under Test for A2A TCK conformance") + .version("1.0.0") + .supportedInterfaces(List.of( + new AgentInterface(TransportProtocol.JSONRPC.asString(), sutJsonRpcUrl), + new AgentInterface(TransportProtocol.GRPC.asString(), sutGrpcUrl), + new AgentInterface(TransportProtocol.HTTP_JSON.asString(), sutRestUrl))) + .capabilities(AgentCapabilities.builder() + .streaming(true) + .pushNotifications(true) + .build()) + .defaultInputModes(List.of("text")) + .defaultOutputModes(List.of("text")) + .skills(List.of( + AgentSkill.builder() + .id("tck") + .name("TCK Conformance") + .description("Handles TCK conformance test messages") + .tags(List.of("tck")) + .build())) + .build(); + } + + private static String getEnvOrDefault(String envVar, String defaultValue) { + String value = System.getenv(envVar); + return value == null || value.isBlank() ? defaultValue : value; + } +} diff --git a/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentExecutorProducer.java b/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentExecutorProducer.java new file mode 100644 index 000000000..0889b9a08 --- /dev/null +++ b/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentExecutorProducer.java @@ -0,0 +1,144 @@ +package org.a2aproject.sdk.sut; + +import java.util.List; +import java.util.Map; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import org.a2aproject.sdk.A2A; +import org.a2aproject.sdk.server.agentexecution.AgentExecutor; +import org.a2aproject.sdk.server.agentexecution.RequestContext; +import org.a2aproject.sdk.server.tasks.AgentEmitter; +import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.spec.DataPart; +import org.a2aproject.sdk.spec.FileWithBytes; +import org.a2aproject.sdk.spec.FileWithUri; +import org.a2aproject.sdk.spec.FilePart; +import org.a2aproject.sdk.spec.TaskNotCancelableError; +import org.a2aproject.sdk.spec.TextPart; + +/** + * CDI producer for the TCK agent executor. + * + *

            Generated from Gherkin scenarios — do not edit by hand. + */ +@ApplicationScoped +public class TckAgentExecutorProducer { + + @Produces + public AgentExecutor agentExecutor() { + return new AgentExecutor() { + @Override + public void execute(RequestContext context, AgentEmitter emitter) throws A2AError { + String messageId = context.getMessage().messageId(); + + if (messageId.startsWith("tck-stream-artifact-chunked")) { + emitter.startWork(); + emitter.addArtifact(List.of(new TextPart("chunk-1 ")), null, null, null, true, false); + emitter.addArtifact(List.of(new TextPart("chunk-2")), null, null, null, true, true); + emitter.complete(); + return; + } + + if (messageId.startsWith("test-resubscribe-message-id")) { + emitter.startWork(); + try { Thread.sleep(4000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-stream-artifact-text")) { + emitter.startWork(); + emitter.addArtifact(List.of(new TextPart("Streamed text content")), null, null, null); + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-stream-artifact-file")) { + emitter.startWork(); + emitter.addArtifact(List.of(new FilePart(new FileWithBytes("text/plain", "output.txt", "dGNr"))), null, null, null); + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-stream-ordering-001")) { + emitter.startWork(); + emitter.addArtifact(List.of(new TextPart("Ordered output")), null, null, null); + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-artifact-file-url")) { + emitter.addArtifact(List.of(new FilePart(new FileWithUri("text/plain", "output.txt", "https://example.com/output.txt"))), null, null, null); + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-message-response")) { + emitter.sendMessage(List.of(new TextPart("Direct message response"))); + return; + } + + if (messageId.startsWith("tck-input-required")) { + emitter.requiresInput(); + return; + } + + if (messageId.startsWith("tck-complete-task")) { + emitter.complete(A2A.toAgentMessage("Hello from TCK")); + return; + } + + if (messageId.startsWith("tck-artifact-text")) { + emitter.addArtifact(List.of(new TextPart("Generated text content")), null, null, null); + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-artifact-file")) { + emitter.addArtifact(List.of(new FilePart(new FileWithBytes("text/plain", "output.txt", "dGNr"))), null, null, null); + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-artifact-data")) { + emitter.addArtifact(List.of(DataPart.fromJson("{\"key\": \"value\", \"count\": 42}")), null, null, null); + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-reject-task")) { + throw new A2AError(-1, "rejected", null); + } + + if (messageId.startsWith("tck-stream-001")) { + emitter.startWork(); + emitter.addArtifact(List.of(new TextPart("Stream hello from TCK")), null, null, null); + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-stream-002")) { + emitter.complete(); + return; + } + + if (messageId.startsWith("tck-stream-003")) { + emitter.startWork(); + emitter.addArtifact(List.of(new TextPart("Stream task lifecycle")), null, null, null); + emitter.complete(); + return; + } + + // Default: complete the task with an echo response + emitter.complete(A2A.toAgentMessage("Unhandled messageId prefix: " + messageId)); + } + + @Override + public void cancel(RequestContext context, AgentEmitter emitter) throws A2AError { + emitter.cancel(); + } + }; + } +} diff --git a/tck/src/main/resources/application.properties b/tck/src/main/resources/application.properties new file mode 100644 index 000000000..f94efb46b --- /dev/null +++ b/tck/src/main/resources/application.properties @@ -0,0 +1,22 @@ +# Generated by A2A TCK code generator — do not edit by hand. + +quarkus.http.port=9999 +quarkus.grpc.server.use-separate-server=false + +# Thread pool configuration for TCK testing +# Limit max threads to prevent resource exhaustion in CI environments +a2a.executor.core-pool-size=5 +a2a.executor.max-pool-size=15 +a2a.executor.keep-alive-seconds=60 + +# Enable debug logging for troubleshooting TCK failures +quarkus.log.category."org.a2aproject.sdk.server.requesthandlers".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.events".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.tasks".level=DEBUG +quarkus.log.category."org.a2aproject.sdk.server.diagnostics.ThreadStats".level=DEBUG + +# Log to file for analysis +quarkus.log.file.enable=true +quarkus.log.file.path=../../reports/a2a-java-sut.log +quarkus.log.file.level=DEBUG +quarkus.log.console.level=INFO \ No newline at end of file From c98c1e66243e7d5a539a245c3885c8b02ce2b528 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 03:49:18 +0000 Subject: [PATCH 153/192] chore: bump org.assertj:assertj-core from 3.25.3 to 3.27.7 Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.25.3 to 3.27.7. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.25.3...assertj-build-3.27.7) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-version: 3.27.7 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- compat-0.3/reference/grpc/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compat-0.3/reference/grpc/pom.xml b/compat-0.3/reference/grpc/pom.xml index 446b63c86..dddbbe6dc 100644 --- a/compat-0.3/reference/grpc/pom.xml +++ b/compat-0.3/reference/grpc/pom.xml @@ -77,7 +77,7 @@ org.assertj assertj-core - 3.25.3 + 3.27.7 test diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index 74240053a..f2ffbba0c 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -70,7 +70,7 @@ org.assertj assertj-core - 3.25.3 + 3.27.7 test From 841c30289f0da9a959749af4a1e83b6b448a98ba Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 12 May 2026 10:47:34 +0200 Subject: [PATCH 154/192] fix(test): stabilize KafkaReplicationIntegrationTest by waiting for first SSE event (#864) Replace `awaitQueuePollerStart` (unreliable after re-subscription) with a `CountDownLatch` that fires when the client receives its first event, ensuring the HTTP/SSE connection is fully established before sending the QueueClosedEvent. Signed-off-by: Emmanuel Hugonnet --- .../KafkaReplicationIntegrationTest.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java index c8b7adb78..c5b74c0b6 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java @@ -30,9 +30,7 @@ import org.a2aproject.sdk.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; import org.a2aproject.sdk.server.PublicAgentCard; -import org.a2aproject.sdk.server.events.EventQueue; import org.a2aproject.sdk.server.events.QueueClosedEvent; -import org.a2aproject.sdk.server.events.QueueManager; import org.a2aproject.sdk.spec.A2AClientException; import org.a2aproject.sdk.spec.AgentCard; import org.a2aproject.sdk.spec.Message; @@ -73,9 +71,6 @@ public class KafkaReplicationIntegrationTest { @Channel("replicated-events-out") Emitter testEmitter; - @Inject - QueueManager queueManager; - private Client streamingClient; private Client nonStreamingClient; private Client pollingClient; @@ -342,19 +337,23 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { // Set up streaming resubscription to listen for the QueueClosedEvent CountDownLatch streamCompletedLatch = new CountDownLatch(1); + CountDownLatch firstEventLatch = new CountDownLatch(1); AtomicBoolean streamCompleted = new AtomicBoolean(false); AtomicBoolean streamErrored = new AtomicBoolean(false); AtomicReference errorRef = new AtomicReference<>(); - // Create consumer - we expect the stream to complete when QueueClosedEvent arrives + // Create consumer - signal when the first event arrives (proves HTTP connection is live), + // then ignore subsequent events while waiting for the stream to complete BiConsumer consumer = (event, agentCard) -> { - // We might receive some events before the stream completes, that's fine - // The important thing is that the stream eventually completes + if (firstEventLatch.getCount() > 0) { + assertInstanceOf(TaskEvent.class, event, "First event on subscribe MUST be TaskEvent (A2A spec 3.1.6)"); + } + firstEventLatch.countDown(); }; // Create error handler that captures completion Consumer errorHandler = error -> { - if (error == null) { + if (error == null || isStreamClosedError(error)) { // null error means stream completed normally streamCompleted.set(true); } else { @@ -367,11 +366,13 @@ public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { // Subscribe to the task - this creates a streaming subscription streamingClient.subscribeToTask(new TaskIdParams(taskId), List.of(consumer), errorHandler); - // Wait for the EventConsumer to start polling (replaces unreliable Thread.sleep) - // This ensures the consumer is ready to receive the QueueClosedEvent - EventQueue queue = queueManager.get(taskId); - assertNotNull(queue, "Queue should exist for task " + taskId); - queueManager.awaitQueuePollerStart(queue); + // Wait until the subscription delivers its first event (the initial task snapshot). + // This proves the HTTP/SSE connection is fully established from the client's perspective + // before we send the QueueClosedEvent. Using awaitQueuePollerStart(mainQueue) is not + // reliable here because the MainQueue's one-time latch was already fired by the first + // subscription (from pollingClient.sendMessage), so it returns immediately. + assertTrue(firstEventLatch.await(15, TimeUnit.SECONDS), + "Should receive initial task snapshot from subscription"); // Now manually send a QueueClosedEvent to Kafka to simulate queue closure on another node QueueClosedEvent closedEvent = new QueueClosedEvent(taskId); From d44c7c4e16db212eec39c625b91ac0819461226f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 13:43:43 +0100 Subject: [PATCH 155/192] chore: bump org.codehaus.mojo:exec-maven-plugin from 3.6.2 to 3.6.3 (#869) Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.6.2 to 3.6.3. - [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases) - [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/3.6.2...3.6.3) --- updated-dependencies: - dependency-name: org.codehaus.mojo:exec-maven-plugin dependency-version: 3.6.3 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/helloworld/client/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index a04d72a45..bcd19c5bf 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -91,7 +91,7 @@ org.codehaus.mojo exec-maven-plugin - 3.6.2 + 3.6.3 org.a2aproject.sdk.examples.helloworld.HelloWorldClient From e69300575884a08c0c63d07f3d90960a8a1480c5 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 12 May 2026 16:07:40 +0200 Subject: [PATCH 156/192] feat(http-client): introduce ServerSentEvent type and spec-compliant SSE parser (#853) * feat(http-client): introduce ServerSentEvent type and spec-compliant SSE parser Replace raw string SSE callbacks with a structured ServerSentEvent record across all HTTP client implementations (JDK, Vert.x, Android). Add ServerSentEventParser with full SSE spec compliance (multi-line data, event id/type, retry, DoS limits). Expand integration tests for typed SSE events and add Android transport variants for existing JSONRPC and REST reference tests. This fixes #839 Signed-off-by: Emmanuel Hugonnet * fix(http-client): preserve blank lines in JDK non-SSE response bodies Co-Authored-By: Claude Opus 4.6 --------- Signed-off-by: Emmanuel Hugonnet Co-authored-by: Kabir Khan Co-authored-by: Claude Opus 4.6 --- .../transport/jsonrpc/JSONRPCTransport.java | 4 +- .../jsonrpc/sse/SSEEventListener.java | 5 +- .../jsonrpc/sse/SSEEventListenerTest.java | 15 +- .../client/transport/rest/RestTransport.java | 4 +- .../transport/rest/sse/SSEEventListener.java | 9 +- .../rest/sse/SSEEventListenerTest.java | 17 +- client/transport/spi/pom.xml | 5 + .../spi/sse/AbstractSSEEventListener.java | 5 +- .../spi/sse/SSEEventListenerTest.java | 13 +- compat-0.3/reference/jsonrpc/pom.xml | 10 + .../QuarkusA2AJSONRPC_v0_3_AndroidTest.java | 17 + .../QuarkusA2AJSONRPC_v0_3_JdkTest.java | 17 + .../quarkus/QuarkusA2AJSONRPC_v0_3_Test.java | 10 +- .../QuarkusA2AJSONRPC_v0_3_VertxTest.java | 22 + ...usA2AJSONRPC_v0_3_WithAuthAndroidTest.java | 49 ++ .../QuarkusA2AJSONRPC_v0_3_WithAuthTest.java | 5 +- ...rkusA2AJSONRPC_v0_3_WithAuthVertxTest.java | 54 ++ compat-0.3/reference/rest/pom.xml | 10 + .../QuarkusA2ARest_v0_3_AndroidTest.java | 17 + .../quarkus/QuarkusA2ARest_v0_3_JdkTest.java | 17 + .../quarkus/QuarkusA2ARest_v0_3_Test.java | 10 +- .../QuarkusA2ARest_v0_3_VertxTest.java | 22 + ...arkusA2ARest_v0_3_WithAuthAndroidTest.java | 63 +++ .../QuarkusA2ARest_v0_3_WithAuthTest.java | 5 +- ...QuarkusA2ARest_v0_3_WithAuthVertxTest.java | 68 +++ compat-0.3/server-conversion/pom.xml | 15 + .../AbstractA2ARequestHandlerTest_v0_3.java | 3 +- .../AbstractA2AServerServerTest_v0_3.java | 12 + .../conversion/AndroidA2AHttpClient_v0_3.java | 108 ++++ .../conversion/TestHttpClient_v0_3.java | 3 +- .../conversion/VertxA2AHttpClient_v0_3.java | 113 ++++ .../sdk/client/http/AndroidA2AHttpClient.java | 60 +- extras/http-client-vertx/pom.xml | 6 + .../sdk/client/http/VertxA2AHttpClient.java | 77 +-- .../http/VertxA2AHttpClientSSETest.java | 253 +-------- .../sdk/client/http/A2AHttpClient.java | 10 +- .../sdk/client/http/JdkA2AHttpClient.java | 97 ++-- .../sdk/client/http/ServerSentEvent.java | 32 ++ .../client/http/ServerSentEventParser.java | 195 +++++++ .../sdk/client/http/A2ACardResolverTest.java | 2 +- .../http/AbstractA2AHttpClientSSETest.java | 139 ++++- .../http/ServerSentEventParserTest.java | 513 ++++++++++++++++++ reference/jsonrpc/pom.xml | 5 + .../server/apps/quarkus/A2AServerRoutes.java | 3 +- .../quarkus/QuarkusA2AJSONRPCAndroidTest.java | 16 + .../QuarkusA2AJSONRPCWithAuthAndroidTest.java | 56 ++ reference/rest/pom.xml | 5 + .../server/rest/quarkus/A2AServerRoutes.java | 26 +- .../quarkus/QuarkusA2ARestAndroidTest.java | 16 + .../QuarkusA2ARestWithAuthAndroidTest.java | 67 +++ .../AbstractA2ARequestHandlerTest.java | 3 +- .../tasks/PushNotificationSenderTest.java | 3 +- .../server/apps/common/TestHttpClient.java | 3 +- 53 files changed, 1880 insertions(+), 434 deletions(-) create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_AndroidTest.java create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_JdkTest.java create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_VertxTest.java create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest.java create mode 100644 compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest.java create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_AndroidTest.java create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_JdkTest.java create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_VertxTest.java create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java create mode 100644 compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AndroidA2AHttpClient_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/VertxA2AHttpClient_v0_3.java create mode 100644 http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEvent.java create mode 100644 http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEventParser.java create mode 100644 http-client/src/test/java/org/a2aproject/sdk/client/http/ServerSentEventParserTest.java create mode 100644 reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCAndroidTest.java create mode 100644 reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthAndroidTest.java create mode 100644 reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestAndroidTest.java create mode 100644 reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthAndroidTest.java diff --git a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java index 27b3f917c..5e8778bb6 100644 --- a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/JSONRPCTransport.java @@ -122,7 +122,7 @@ public void sendMessageStreaming(MessageSendParams request, Consumer sseEventListener.onMessage(msg, ref.get()), + event -> sseEventListener.onMessage(event, ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), () -> { // Signal normal stream completion to error handler (null error means success) @@ -272,7 +272,7 @@ public void subscribeToTask(TaskIdParams request, Consumer e try { A2AHttpClient.PostBuilder builder = createPostBuilder(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SUBSCRIBE_TO_TASK_METHOD); ref.set(builder.postAsyncSSE( - msg -> sseEventListener.onMessage(msg, ref.get()), + event -> sseEventListener.onMessage(event, ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), () -> { // Signal normal stream completion to error handler (null error means success) diff --git a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListener.java b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListener.java index 9afb5dec3..347b442b6 100644 --- a/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListener.java +++ b/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListener.java @@ -4,6 +4,7 @@ import java.util.function.Consumer; import java.util.logging.Logger; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.client.transport.spi.sse.AbstractSSEEventListener; import org.a2aproject.sdk.grpc.StreamResponse; import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; @@ -28,8 +29,8 @@ public SSEEventListener(Consumer eventHandler, } @Override - public void onMessage(String message, @Nullable Future completableFuture) { - parseAndHandleMessage(message, completableFuture); + public void onMessage(ServerSentEvent event, @Nullable Future completableFuture) { + parseAndHandleMessage(event.data(), completableFuture); } public void onComplete() { diff --git a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java index 4f8efc50b..a256f253c 100644 --- a/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java +++ b/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/client/transport/jsonrpc/sse/SSEEventListenerTest.java @@ -13,6 +13,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.client.transport.jsonrpc.JsonStreamingMessages; import org.a2aproject.sdk.spec.A2AError; import org.a2aproject.sdk.spec.Artifact; @@ -42,7 +43,7 @@ public void testOnEventWithTaskResult() throws Exception { JsonStreamingMessages.STREAMING_TASK_EVENT.indexOf("{")); // Call the onEvent method directly - listener.onMessage(eventData, null); + listener.onMessage(new ServerSentEvent(eventData), null); // Verify the event was processed correctly assertNotNull(receivedEvent.get()); @@ -67,7 +68,7 @@ public void testOnEventWithMessageResult() throws Exception { JsonStreamingMessages.STREAMING_MESSAGE_EVENT.indexOf("{")); // Call onEvent method - listener.onMessage(eventData, null); + listener.onMessage(new ServerSentEvent(eventData), null); // Verify the event was processed correctly assertNotNull(receivedEvent.get()); @@ -95,7 +96,7 @@ public void testOnEventWithTaskStatusUpdateEventEvent() throws Exception { JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT.indexOf("{")); // Call onEvent method - listener.onMessage(eventData, null); + listener.onMessage(new ServerSentEvent(eventData), null); // Verify the event was processed correctly assertNotNull(receivedEvent.get()); @@ -121,7 +122,7 @@ public void testOnEventWithTaskArtifactUpdateEventEvent() throws Exception { JsonStreamingMessages.STREAMING_ARTIFACT_UPDATE_EVENT.indexOf("{")); // Call onEvent method - listener.onMessage(eventData, null); + listener.onMessage(new ServerSentEvent(eventData), null); // Verify the event was processed correctly assertNotNull(receivedEvent.get()); @@ -153,7 +154,7 @@ public void testOnEventWithError() throws Exception { JsonStreamingMessages.STREAMING_ERROR_EVENT.indexOf("{")); // Call onEvent method - listener.onMessage(eventData, null); + listener.onMessage(new ServerSentEvent(eventData), null); // Verify the error was processed correctly assertNotNull(receivedError.get()); @@ -205,7 +206,7 @@ public void testFinalTaskStatusUpdateEventCancels() { // Call onMessage with a cancellable future CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onMessage(eventData, future); + listener.onMessage(new ServerSentEvent(eventData), future); // Verify the event was received and processed assertNotNull(receivedEvent.get()); @@ -232,7 +233,7 @@ public void testOnEventWithFinalTaskStatusUpdateEventEventCancels() throws Excep // Call onEvent method CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onMessage(eventData, future); + listener.onMessage(new ServerSentEvent(eventData), future); // Verify the event was processed correctly assertNotNull(receivedEvent.get()); diff --git a/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java index 02b43e2d7..b716fc934 100644 --- a/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/RestTransport.java @@ -116,7 +116,7 @@ public void sendMessageStreaming(MessageSendParams messageSendParams, Consumer sseEventListener.onMessage(msg, ref.get()), + event -> sseEventListener.onMessage(event, ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), () -> { // We don't need to do anything special on completion @@ -376,7 +376,7 @@ public void subscribeToTask(TaskIdParams request, Consumer e String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s:subscribe", request.id()); A2AHttpClient.PostBuilder postBuilder = createPostBuilder(url, payloadAndHeaders); ref.set(postBuilder.postAsyncSSE( - msg -> sseEventListener.onMessage(msg, ref.get()), + event -> sseEventListener.onMessage(event, ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), () -> { // We don't need to do anything special on completion diff --git a/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListener.java b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListener.java index 850a8718f..a8265d5b4 100644 --- a/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListener.java +++ b/client/transport/rest/src/main/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListener.java @@ -6,6 +6,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.client.transport.spi.sse.AbstractSSEEventListener; import org.a2aproject.sdk.client.transport.rest.RestErrorMapper; import org.a2aproject.sdk.grpc.StreamResponse; @@ -27,15 +28,15 @@ public SSEEventListener(Consumer eventHandler, } @Override - public void onMessage(String message, @Nullable Future completableFuture) { + public void onMessage(ServerSentEvent event, @Nullable Future completableFuture) { try { - log.fine("Streaming message received: " + message); + log.fine("Streaming message received: " + event.data()); org.a2aproject.sdk.grpc.StreamResponse.Builder builder = org.a2aproject.sdk.grpc.StreamResponse.newBuilder(); - JsonFormat.parser().merge(message, builder); + JsonFormat.parser().merge(event.data(), builder); parseAndHandleMessage(builder.build(), completableFuture); } catch (InvalidProtocolBufferException e) { if (getErrorHandler() != null) { - getErrorHandler().accept(RestErrorMapper.mapRestError(message, 500)); + getErrorHandler().accept(RestErrorMapper.mapRestError(event.data(), 500)); } } } diff --git a/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListenerTest.java b/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListenerTest.java index 1fc2683e8..65ada80b1 100644 --- a/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListenerTest.java +++ b/client/transport/rest/src/test/java/org/a2aproject/sdk/client/transport/rest/sse/SSEEventListenerTest.java @@ -9,6 +9,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.spec.Message; import org.a2aproject.sdk.spec.StreamingEventKind; import org.a2aproject.sdk.spec.Task; @@ -83,7 +84,7 @@ public void testOnMessageWithTaskResult() { """; // Call the onMessage method - listener.onMessage(jsonMessage, null); + listener.onMessage(new ServerSentEvent(jsonMessage), null); // Verify the event was processed correctly assertNotNull(receivedEvent.get()); @@ -120,7 +121,7 @@ public void testOnMessageWithMessageResult() { """; // Call onMessage method - listener.onMessage(jsonMessage, null); + listener.onMessage(new ServerSentEvent(jsonMessage), null); // Verify the event was processed correctly assertNotNull(receivedEvent.get()); @@ -157,7 +158,7 @@ public void testOnMessageWithStatusUpdateEvent() { """; // Call onMessage method - listener.onMessage(jsonMessage, null); + listener.onMessage(new ServerSentEvent(jsonMessage), null); // Verify the event was processed correctly assertNotNull(receivedEvent.get()); @@ -193,7 +194,7 @@ public void testOnMessageWithFinalStatusUpdateEventCancels() { // Call onMessage with a cancellable future CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onMessage(jsonMessage, future); + listener.onMessage(new ServerSentEvent(jsonMessage), future); // Verify the event was received and processed assertNotNull(receivedEvent.get()); @@ -230,7 +231,7 @@ public void testOnMessageWithCompletedTaskCancels() { // Call onMessage with a cancellable future CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onMessage(jsonMessage, future); + listener.onMessage(new ServerSentEvent(jsonMessage), future); // Verify the event was received assertNotNull(receivedEvent.get()); @@ -255,7 +256,7 @@ public void testOnMessageWithInvalidJsonCallsErrorHandler() { String invalidJson = "{ invalid json }"; // Call onMessage - listener.onMessage(invalidJson, null); + listener.onMessage(new ServerSentEvent(invalidJson), null); // Verify error handler was called assertNotNull(receivedError.get()); @@ -274,7 +275,7 @@ public void testOnMessageWithInvalidPayloadCaseCallsErrorHandler() { String jsonMessage = "{}"; // Call onMessage - listener.onMessage(jsonMessage, null); + listener.onMessage(new ServerSentEvent(jsonMessage), null); // Verify error handler was called assertNotNull(receivedError.get()); @@ -335,7 +336,7 @@ public void testOnMessageWithNullErrorHandler() { String invalidJson = "{ invalid json }"; // Call onMessage - should not throw even with null error handler - listener.onMessage(invalidJson, null); + listener.onMessage(new ServerSentEvent(invalidJson), null); // No exception thrown means test passes } diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index 867cdf58f..78d94b858 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -21,6 +21,11 @@ org.a2aproject.sdk a2a-java-sdk-spec + + ${project.groupId} + a2a-java-sdk-http-client + ${project.version} + ${project.groupId} a2a-java-sdk-jsonrpc-common diff --git a/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/AbstractSSEEventListener.java b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/AbstractSSEEventListener.java index 994dc5874..b587fdb5d 100644 --- a/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/AbstractSSEEventListener.java +++ b/client/transport/spi/src/main/java/org/a2aproject/sdk/client/transport/spi/sse/AbstractSSEEventListener.java @@ -4,6 +4,7 @@ import java.util.function.Consumer; import java.util.logging.Logger; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.spec.StreamingEventKind; import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.TaskState; @@ -59,10 +60,10 @@ protected Consumer getEventHandler() { * Handles incoming SSE messages. Subclasses must implement the specific * parsing logic for their transport protocol. * - * @param message The raw message string from the SSE stream + * @param event The parsed SSE event from the stream * @param completableFuture Optional future for controlling the SSE connection */ - public abstract void onMessage(String message, @Nullable Future completableFuture); + public abstract void onMessage(ServerSentEvent event, @Nullable Future completableFuture); /** * Handles errors that occur during SSE streaming. diff --git a/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java index b40ee0f51..7f1c4dc2a 100644 --- a/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java +++ b/client/transport/spi/src/test/java/org/a2aproject/sdk/client/transport/spi/sse/SSEEventListenerTest.java @@ -11,6 +11,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.spec.Message; import org.a2aproject.sdk.spec.StreamingEventKind; import org.a2aproject.sdk.spec.Task; @@ -47,7 +48,7 @@ public TestSSEEventListener(Consumer eventHandler, } @Override - public void onMessage(String message, @Nullable Future completableFuture) { + public void onMessage(ServerSentEvent event, @Nullable Future completableFuture) { if (eventToHandle != null) { handleEvent(eventToHandle, completableFuture); } @@ -145,7 +146,7 @@ public void testHandleEventCallsEventHandler() { Message message = createMessage(Message.Role.ROLE_USER); listener.setEventToHandle(message); - listener.onMessage(TEST_TEXT, null); + listener.onMessage(new ServerSentEvent(TEST_TEXT), null); assertNotNull(receivedEvent.get()); assertEquals(message, receivedEvent.get()); @@ -159,7 +160,7 @@ public void testHandleEventWithNullErrorHandler() { Task task = createTask(TaskState.TASK_STATE_WORKING); listener.setEventToHandle(task); - listener.onMessage(TEST_TEXT, null); + listener.onMessage(new ServerSentEvent(TEST_TEXT), null); assertNotNull(receivedEvent.get()); } @@ -254,7 +255,7 @@ public void testAutoCloseCancelsFutureForFinalEvent() { CancelCapturingFuture future = new CancelCapturingFuture(); listener.setEventToHandle(finalEvent); - listener.onMessage(TEST_TEXT, future); + listener.onMessage(new ServerSentEvent(TEST_TEXT), future); assertNotNull(receivedEvent.get()); assertEquals(finalEvent, receivedEvent.get()); @@ -270,7 +271,7 @@ public void testAutoCloseDoesNotCancelFutureForNonFinalEvent() { CancelCapturingFuture future = new CancelCapturingFuture(); listener.setEventToHandle(message); - listener.onMessage(TEST_TEXT, future); + listener.onMessage(new ServerSentEvent(TEST_TEXT), future); assertNotNull(receivedEvent.get()); assertFalse(future.wasCancelled()); @@ -285,7 +286,7 @@ public void testAutoCloseWithNullFuture() { // Should not throw with null future listener.setEventToHandle(finalEvent); - listener.onMessage(TEST_TEXT, null); + listener.onMessage(new ServerSentEvent(TEST_TEXT), null); assertNotNull(receivedEvent.get()); } diff --git a/compat-0.3/reference/jsonrpc/pom.xml b/compat-0.3/reference/jsonrpc/pom.xml index 34876a7a6..ec4befc37 100644 --- a/compat-0.3/reference/jsonrpc/pom.xml +++ b/compat-0.3/reference/jsonrpc/pom.xml @@ -48,6 +48,16 @@ a2a-java-sdk-compat-0.3-client-transport-jsonrpc test + + ${project.groupId} + a2a-java-sdk-http-client-android + test + + + ${project.groupId} + a2a-java-sdk-http-client-vertx + test + ${project.groupId} a2a-java-sdk-reference-common diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_AndroidTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_AndroidTest.java new file mode 100644 index 000000000..aac980bc8 --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_AndroidTest.java @@ -0,0 +1,17 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.AndroidA2AHttpClient_v0_3; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusA2AJSONRPC_v0_3_AndroidTest extends QuarkusA2AJSONRPC_v0_3_Test { + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient_v0_3())); + } +} diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_JdkTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_JdkTest.java new file mode 100644 index 000000000..831e73dea --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_JdkTest.java @@ -0,0 +1,17 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusA2AJSONRPC_v0_3_JdkTest extends QuarkusA2AJSONRPC_v0_3_Test { + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient_v0_3())); + } +} diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_Test.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_Test.java index 65683ce9a..bb46dad92 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_Test.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_Test.java @@ -1,14 +1,10 @@ package org.a2aproject.sdk.compat03.server.apps.quarkus; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; -import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; -import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; -import io.quarkus.test.junit.QuarkusTest; -@QuarkusTest -public class QuarkusA2AJSONRPC_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { +public abstract class QuarkusA2AJSONRPC_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { public QuarkusA2AJSONRPC_v0_3_Test() { super(8081); @@ -25,7 +21,5 @@ protected String getTransportUrl() { } @Override - protected void configureTransport(ClientBuilder_v0_3 builder) { - builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); - } + protected abstract void configureTransport(ClientBuilder_v0_3 builder); } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_VertxTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_VertxTest.java new file mode 100644 index 000000000..bd7d2f5a4 --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_VertxTest.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.VertxA2AHttpClient_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; + +@QuarkusTest +public class QuarkusA2AJSONRPC_v0_3_VertxTest extends QuarkusA2AJSONRPC_v0_3_Test { + + @Inject + Vertx vertx; + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient_v0_3(vertx))); + } +} diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest.java new file mode 100644 index 000000000..45e8fbeee --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest.java @@ -0,0 +1,49 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.AndroidA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +@QuarkusTest +@TestProfile(AuthTestProfile_v0_3.class) +public class QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest extends AbstractA2AServerWithAuthTest_v0_3 { + + public QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3() + .httpClient(new AndroidA2AHttpClient_v0_3()) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient_v0_3())); + } +} diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java index ba0818924..e158c28c2 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java @@ -1,6 +1,7 @@ package org.a2aproject.sdk.compat03.server.apps.quarkus; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; @@ -36,11 +37,13 @@ protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3() + .httpClient(new JdkA2AHttpClient_v0_3()) .addInterceptor(authInterceptor)); } @Override protected void configureTransport(ClientBuilder_v0_3 builder) { - builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient_v0_3())); } } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest.java new file mode 100644 index 000000000..ba37d6b9b --- /dev/null +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest.java @@ -0,0 +1,54 @@ +package org.a2aproject.sdk.compat03.server.apps.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; +import org.a2aproject.sdk.compat03.conversion.VertxA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; + +@QuarkusTest +@TestProfile(AuthTestProfile_v0_3.class) +public class QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest extends AbstractA2AServerWithAuthTest_v0_3 { + + @Inject + Vertx vertx; + + public QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3() + .httpClient(new VertxA2AHttpClient_v0_3(vertx)) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(JSONRPCTransport_v0_3.class, + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient_v0_3(vertx))); + } +} diff --git a/compat-0.3/reference/rest/pom.xml b/compat-0.3/reference/rest/pom.xml index 061583d8d..3bac16a15 100644 --- a/compat-0.3/reference/rest/pom.xml +++ b/compat-0.3/reference/rest/pom.xml @@ -44,6 +44,16 @@ a2a-java-sdk-compat-0.3-client-transport-rest test + + ${project.groupId} + a2a-java-sdk-http-client-android + test + + + ${project.groupId} + a2a-java-sdk-http-client-vertx + test + com.google.protobuf protobuf-java-util diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_AndroidTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_AndroidTest.java new file mode 100644 index 000000000..6d1f5cfdd --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_AndroidTest.java @@ -0,0 +1,17 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.AndroidA2AHttpClient_v0_3; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusA2ARest_v0_3_AndroidTest extends QuarkusA2ARest_v0_3_Test { + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient_v0_3())); + } +} diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_JdkTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_JdkTest.java new file mode 100644 index 000000000..8ec2191ba --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_JdkTest.java @@ -0,0 +1,17 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusA2ARest_v0_3_JdkTest extends QuarkusA2ARest_v0_3_Test { + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient_v0_3())); + } +} diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_Test.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_Test.java index c371eb538..58e8d6952 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_Test.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_Test.java @@ -6,17 +6,13 @@ import java.net.http.HttpResponse; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; -import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; -import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; -import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -@QuarkusTest -public class QuarkusA2ARest_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { +public abstract class QuarkusA2ARest_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { public QuarkusA2ARest_v0_3_Test() { super(8081); @@ -33,9 +29,7 @@ protected String getTransportUrl() { } @Override - protected void configureTransport(ClientBuilder_v0_3 builder) { - builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); - } + protected abstract void configureTransport(ClientBuilder_v0_3 builder); @Test public void testMethodNotFound() throws Exception { diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_VertxTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_VertxTest.java new file mode 100644 index 000000000..410c80feb --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_VertxTest.java @@ -0,0 +1,22 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.conversion.VertxA2AHttpClient_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; + +@QuarkusTest +public class QuarkusA2ARest_v0_3_VertxTest extends QuarkusA2ARest_v0_3_Test { + + @Inject + Vertx vertx; + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient_v0_3(vertx))); + } +} diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java new file mode 100644 index 000000000..b17ec5e57 --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java @@ -0,0 +1,63 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.AndroidA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile_v0_3.class) +public class QuarkusA2ARest_v0_3_WithAuthAndroidTest extends AbstractA2AServerWithAuthTest_v0_3 { + + public QuarkusA2ARest_v0_3_WithAuthAndroidTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3() + .httpClient(new AndroidA2AHttpClient_v0_3()) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient_v0_3())); + } + + @Test + @Override + public void testBasicAuthWorksViaHttp() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .get("/v1/tasks/" + MINIMAL_TASK.getId()) + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } +} diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java index 4cc5d54a4..984850d2b 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java @@ -1,6 +1,7 @@ package org.a2aproject.sdk.compat03.server.rest.quarkus; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; @@ -37,12 +38,14 @@ protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3() + .httpClient(new JdkA2AHttpClient_v0_3()) .addInterceptor(authInterceptor)); } @Override protected void configureTransport(ClientBuilder_v0_3 builder) { - builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient_v0_3())); } @Test diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java new file mode 100644 index 000000000..087b30535 --- /dev/null +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java @@ -0,0 +1,68 @@ +package org.a2aproject.sdk.compat03.server.rest.quarkus; + +import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; +import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; +import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; +import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; +import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; +import org.a2aproject.sdk.compat03.conversion.VertxA2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.vertx.core.Vertx; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@TestProfile(AuthTestProfile_v0_3.class) +public class QuarkusA2ARest_v0_3_WithAuthVertxTest extends AbstractA2AServerWithAuthTest_v0_3 { + + @Inject + Vertx vertx; + + public QuarkusA2ARest_v0_3_WithAuthVertxTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol_v0_3.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { + AuthInterceptor_v0_3 authInterceptor = new AuthInterceptor_v0_3( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3() + .httpClient(new VertxA2AHttpClient_v0_3(vertx)) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder_v0_3 builder) { + builder.withTransport(RestTransport_v0_3.class, + new RestTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient_v0_3(vertx))); + } + + @Test + @Override + public void testBasicAuthWorksViaHttp() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .get("/v1/tasks/" + MINIMAL_TASK.getId()) + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.getId()); + } +} diff --git a/compat-0.3/server-conversion/pom.xml b/compat-0.3/server-conversion/pom.xml index 811c6adb6..aa0108c91 100644 --- a/compat-0.3/server-conversion/pom.xml +++ b/compat-0.3/server-conversion/pom.xml @@ -70,6 +70,21 @@ a2a-java-sdk-http-client test + + ${project.groupId} + a2a-java-sdk-http-client-android + test + + + ${project.groupId} + a2a-java-sdk-http-client-vertx + test + + + io.quarkus + quarkus-vertx + test + diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java index 9e4c3b692..088ae9d8f 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java @@ -15,6 +15,7 @@ import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; import org.a2aproject.sdk.server.agentexecution.AgentExecutor; @@ -260,7 +261,7 @@ public String body() { } @Override - public CompletableFuture postAsyncSSE(Consumer messageConsumer, + public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java index b881c0cc0..7ad8b45c0 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java @@ -1080,9 +1080,21 @@ public void testNonBlockingWithMultipleMessages() throws Exception { } }; + // Wait for the server to register the new SSE subscription before the agent emits events. + // Without this guard there is a race: the server can finish processing message2 and emit + // events to the task queue before the streaming subscriber from sendMessage is registered, + // causing those events to be silently dropped (sendMessage streaming starts from the + // current queue position, unlike resubscribe which replays from an earlier point). + CountDownLatch streamSubscriptionLatch = new CountDownLatch(1); + awaitStreamingSubscription() + .whenComplete((unused, throwable) -> streamSubscriptionLatch.countDown()); + // Streaming message adds artifact-2 and completes task getClient().sendMessage(message2, List.of(streamConsumer), null); + assertTrue(streamSubscriptionLatch.await(15, TimeUnit.SECONDS), + "Stream subscription should be established before agent emits events"); + // 4. Verify both consumers received artifact-2 and completion assertTrue(resubEventLatch.await(10, TimeUnit.SECONDS)); assertTrue(streamEventLatch.await(10, TimeUnit.SECONDS)); diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AndroidA2AHttpClient_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AndroidA2AHttpClient_v0_3.java new file mode 100644 index 000000000..778d42fd7 --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AndroidA2AHttpClient_v0_3.java @@ -0,0 +1,108 @@ +package org.a2aproject.sdk.compat03.conversion; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; + +/** + * Adapts {@link AndroidA2AHttpClient} to the {@link A2AHttpClient_v0_3} interface, + * bridging the v0.3 SSE callback ({@code Consumer}) to the v1.0 SSE callback + * ({@code Consumer}) by extracting the event data payload. + */ +public class AndroidA2AHttpClient_v0_3 implements A2AHttpClient_v0_3 { + + private final AndroidA2AHttpClient delegate = new AndroidA2AHttpClient(); + + @Override + public GetBuilder createGet() { + return new GetBuilderAdapter(delegate.createGet()); + } + + @Override + public PostBuilder createPost() { + return new PostBuilderAdapter(delegate.createPost()); + } + + @Override + public DeleteBuilder createDelete() { + return new DeleteBuilderAdapter(delegate.createDelete()); + } + + private static A2AHttpResponse_v0_3 adapt(org.a2aproject.sdk.client.http.A2AHttpResponse r) { + return new A2AHttpResponse_v0_3() { + @Override public int status() { return r.status(); } + @Override public boolean success() { return r.success(); } + @Override public String body() { return r.body(); } + }; + } + + private static class GetBuilderAdapter implements GetBuilder { + private final A2AHttpClient.GetBuilder delegate; + + GetBuilderAdapter(A2AHttpClient.GetBuilder delegate) { + this.delegate = delegate; + } + + @Override public GetBuilder url(String s) { delegate.url(s); return this; } + @Override public GetBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } + @Override public GetBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } + + @Override + public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { + return adapt(delegate.get()); + } + + @Override + public CompletableFuture getAsyncSSE(Consumer mc, Consumer ec, Runnable cr) + throws IOException, InterruptedException { + return delegate.getAsyncSSE(event -> mc.accept(event.data()), ec, cr); + } + } + + private static class PostBuilderAdapter implements PostBuilder { + private final A2AHttpClient.PostBuilder delegate; + + PostBuilderAdapter(A2AHttpClient.PostBuilder delegate) { + this.delegate = delegate; + } + + @Override public PostBuilder url(String s) { delegate.url(s); return this; } + @Override public PostBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } + @Override public PostBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } + @Override public PostBuilder body(String body) { delegate.body(body); return this; } + + @Override + public A2AHttpResponse_v0_3 post() throws IOException, InterruptedException { + return adapt(delegate.post()); + } + + @Override + public CompletableFuture postAsyncSSE(Consumer mc, Consumer ec, Runnable cr) + throws IOException, InterruptedException { + return delegate.postAsyncSSE(event -> mc.accept(event.data()), ec, cr); + } + } + + private static class DeleteBuilderAdapter implements DeleteBuilder { + private final A2AHttpClient.DeleteBuilder delegate; + + DeleteBuilderAdapter(A2AHttpClient.DeleteBuilder delegate) { + this.delegate = delegate; + } + + @Override public DeleteBuilder url(String s) { delegate.url(s); return this; } + @Override public DeleteBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } + @Override public DeleteBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } + + @Override + public A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException { + return adapt(delegate.delete()); + } + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestHttpClient_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestHttpClient_v0_3.java index f95fb723d..a99f49da2 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestHttpClient_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/TestHttpClient_v0_3.java @@ -14,6 +14,7 @@ import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; import org.a2aproject.sdk.spec.Task; @@ -84,7 +85,7 @@ public String body() { } @Override - public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { + public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { return null; } diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/VertxA2AHttpClient_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/VertxA2AHttpClient_v0_3.java new file mode 100644 index 000000000..24fac7060 --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/VertxA2AHttpClient_v0_3.java @@ -0,0 +1,113 @@ +package org.a2aproject.sdk.compat03.conversion; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; +import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; +import io.vertx.core.Vertx; + +/** + * Adapts {@link VertxA2AHttpClient} to the {@link A2AHttpClient_v0_3} interface, + * bridging the v0.3 SSE callback ({@code Consumer}) to the v1.0 SSE callback + * ({@code Consumer}) by extracting the event data payload. + */ +public class VertxA2AHttpClient_v0_3 implements A2AHttpClient_v0_3 { + + private final VertxA2AHttpClient delegate; + + public VertxA2AHttpClient_v0_3(Vertx vertx) { + this.delegate = new VertxA2AHttpClient(vertx); + } + + @Override + public GetBuilder createGet() { + return new GetBuilderAdapter(delegate.createGet()); + } + + @Override + public PostBuilder createPost() { + return new PostBuilderAdapter(delegate.createPost()); + } + + @Override + public DeleteBuilder createDelete() { + return new DeleteBuilderAdapter(delegate.createDelete()); + } + + private static A2AHttpResponse_v0_3 adapt(org.a2aproject.sdk.client.http.A2AHttpResponse r) { + return new A2AHttpResponse_v0_3() { + @Override public int status() { return r.status(); } + @Override public boolean success() { return r.success(); } + @Override public String body() { return r.body(); } + }; + } + + private static class GetBuilderAdapter implements GetBuilder { + private final A2AHttpClient.GetBuilder delegate; + + GetBuilderAdapter(A2AHttpClient.GetBuilder delegate) { + this.delegate = delegate; + } + + @Override public GetBuilder url(String s) { delegate.url(s); return this; } + @Override public GetBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } + @Override public GetBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } + + @Override + public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { + return adapt(delegate.get()); + } + + @Override + public CompletableFuture getAsyncSSE(Consumer mc, Consumer ec, Runnable cr) + throws IOException, InterruptedException { + return delegate.getAsyncSSE(event -> mc.accept(event.data()), ec, cr); + } + } + + private static class PostBuilderAdapter implements PostBuilder { + private final A2AHttpClient.PostBuilder delegate; + + PostBuilderAdapter(A2AHttpClient.PostBuilder delegate) { + this.delegate = delegate; + } + + @Override public PostBuilder url(String s) { delegate.url(s); return this; } + @Override public PostBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } + @Override public PostBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } + @Override public PostBuilder body(String body) { delegate.body(body); return this; } + + @Override + public A2AHttpResponse_v0_3 post() throws IOException, InterruptedException { + return adapt(delegate.post()); + } + + @Override + public CompletableFuture postAsyncSSE(Consumer mc, Consumer ec, Runnable cr) + throws IOException, InterruptedException { + return delegate.postAsyncSSE(event -> mc.accept(event.data()), ec, cr); + } + } + + private static class DeleteBuilderAdapter implements DeleteBuilder { + private final A2AHttpClient.DeleteBuilder delegate; + + DeleteBuilderAdapter(A2AHttpClient.DeleteBuilder delegate) { + this.delegate = delegate; + } + + @Override public DeleteBuilder url(String s) { delegate.url(s); return this; } + @Override public DeleteBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } + @Override public DeleteBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } + + @Override + public A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException { + return adapt(delegate.delete()); + } + } +} diff --git a/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClient.java b/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClient.java index 21e585398..fa6aae288 100644 --- a/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClient.java +++ b/extras/http-client-android/src/main/java/org/a2aproject/sdk/client/http/AndroidA2AHttpClient.java @@ -122,6 +122,12 @@ protected static String readStreamWithLimit(InputStream is) throws IOException { protected A2AHttpResponse execute(HttpURLConnection connection) throws IOException { int status = connection.getResponseCode(); + if (status == HTTP_UNAUTHORIZED) { + throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); + } else if (status == HTTP_FORBIDDEN) { + throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); + } + String body = ""; try (InputStream is = (status >= HTTP_OK && status < HTTP_MULT_CHOICE) @@ -130,23 +136,17 @@ protected A2AHttpResponse execute(HttpURLConnection connection) throws IOExcepti body = readStreamWithLimit(is); } - if (status == HTTP_UNAUTHORIZED) { - throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); - } else if (status == HTTP_FORBIDDEN) { - throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); - } - return new AndroidHttpResponse(status, body); } protected void processSSEResponse( HttpURLConnection connection, - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) { try { int status = connection.getResponseCode(); - if (status != HTTP_OK) { + if (!(status >= HTTP_OK && status < HTTP_MULT_CHOICE)) { if (status == HTTP_UNAUTHORIZED) { errorConsumer.accept(new IOException(A2AErrorMessages.AUTHENTICATION_FAILED)); return; @@ -159,21 +159,45 @@ protected void processSSEResponse( try (InputStream es = connection.getErrorStream()) { errorBody = readStreamWithLimit(es); } - errorConsumer.accept( - new IOException("Request failed with status " + status + ":" + errorBody)); + // Pass the error body through messageConsumer so higher-level listeners + // (e.g. RestErrorMapper in SSEEventListener) can produce a typed error. + // Do not also call errorConsumer here — the messageConsumer path is responsible + // for signalling the error, matching the async JDK client's behaviour. + if (!errorBody.isEmpty()) { + messageConsumer.accept(new ServerSentEvent(errorBody)); + } else { + errorConsumer.accept( + new IOException("Request failed with status " + status)); + } return; } + String contentType = connection.getContentType(); + boolean isSse = contentType != null && contentType.contains(EVENT_STREAM); + try (InputStream is = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { String line; - while ((line = reader.readLine()) != null) { - if (line.startsWith("data:")) { - String data = line.substring(5).trim(); - if (!data.isEmpty()) { - messageConsumer.accept(data); + if (isSse) { + ServerSentEventParser sseParser = new ServerSentEventParser(messageConsumer, errorConsumer); + while ((line = reader.readLine()) != null) { + sseParser.processLine(line); + } + sseParser.flush(); + } else { + StringBuilder bodyBuffer = new StringBuilder(); + while ((line = reader.readLine()) != null) { + if (!line.isEmpty()) { + if (bodyBuffer.length() > 0) { + bodyBuffer.append('\n'); + } + bodyBuffer.append(line); } } + String body = bodyBuffer.toString(); + if (!body.isEmpty()) { + messageConsumer.accept(new ServerSentEvent(body)); + } } completeRunnable.run(); } @@ -186,7 +210,7 @@ protected void processSSEResponse( protected CompletableFuture executeAsyncSSE( HttpURLConnection connection, - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) { return CompletableFuture.runAsync( @@ -209,7 +233,7 @@ public A2AHttpResponse get() throws IOException { @Override public CompletableFuture getAsyncSSE( - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException { @@ -245,7 +269,7 @@ public A2AHttpResponse post() throws IOException { @Override public CompletableFuture postAsyncSSE( - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException { diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index cec470583..3f97abf89 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -22,6 +22,12 @@ ${project.groupId} a2a-java-sdk-http-client + + ${project.groupId} + a2a-java-sdk-http-client + test-jar + test + io.vertx vertx-web-client diff --git a/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java b/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java index 8daf859d0..9793de216 100644 --- a/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java +++ b/extras/http-client-vertx/src/main/java/org/a2aproject/sdk/client/http/VertxA2AHttpClient.java @@ -116,7 +116,7 @@ * CompletableFuture future = client.createGet() * .url("https://api.example.com/stream") * .getAsyncSSE( - * message -> System.out.println("Received: " + message), + * event -> System.out.println("Received: " + event.data()), * error -> error.printStackTrace(), * () -> System.out.println("Stream complete") * ); @@ -366,7 +366,7 @@ private CompletableFuture executeAsyncSSE( String url, Map headers, @Nullable Buffer bodyBuffer, - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) { @@ -403,13 +403,15 @@ private CompletableFuture executeAsyncSSE( && contentType != null && contentType.contains(EVENT_STREAM); if (isSse) { BodyCodec.sseStream(readStream -> - readStream.handler(event -> { - String data = event.data(); - if (data != null) { - data = data.trim(); - if (!data.isEmpty()) { - messageConsumer.accept(data); - } + readStream.handler(sseEvent -> { + String data = sseEvent.data(); + if (data != null && !data.isEmpty()) { + String eventType = sseEvent.event() != null ? sseEvent.event() : ServerSentEvent.DEFAULT_EVENT_TYPE; + // Vert.x SseEvent.retry() defaults to 0 when no retry field is present, so + // retry:0 (a valid SSE directive meaning "reconnect immediately") is + // indistinguishable from "not set" and is silently treated as absent. + Long retry = sseEvent.retry() != 0 ? (long) sseEvent.retry() : null; + messageConsumer.accept(new ServerSentEvent(data, eventType, sseEvent.id(), retry)); } }) ).create(ar -> { @@ -440,6 +442,7 @@ private CompletableFuture executeAsyncSSE( response.pipe().to(new PlainBodyWriteStream(messageConsumer)) .onSuccess(v -> { if (futureCompleted.compareAndSet(false, true)) { + completeRunnable.run(); future.complete(null); } }) @@ -486,7 +489,7 @@ public A2AHttpResponse get() throws IOException, InterruptedException { @Override public CompletableFuture getAsyncSSE( - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { @@ -528,7 +531,7 @@ public A2AHttpResponse post() throws IOException, InterruptedException { @Override public CompletableFuture postAsyncSSE( - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { @@ -563,10 +566,9 @@ public A2AHttpResponse delete() throws IOException, InterruptedException { /** * A {@link WriteStream} that handles plain (non-SSE) response bodies, e.g. JSON error - * responses returned when the stream never opens. Accumulates raw bytes, splits into lines - * on {@code \n} (decoding complete lines as UTF-8 to correctly handle multi-byte characters - * that may be split across consecutive write calls), and forwards each non-empty line to the - * message consumer so the SSEEventListener can parse the typed error. + * responses returned when the stream never opens. Accumulates all bytes and emits the + * entire body as a single {@link ServerSentEvent} on {@link #end} so that multi-line or + * pretty-printed JSON is delivered as one parseable unit to the SSEEventListener. * *

            A hard cap of {@value #MAX_BUFFER_BYTES} bytes is enforced on the internal buffer * to prevent Denial-of-Service via {@link OutOfMemoryError} for arbitrarily large inputs. @@ -575,48 +577,14 @@ private static class PlainBodyWriteStream implements WriteStream { /** Maximum number of raw bytes that may be buffered before further writes are rejected. */ private static final int MAX_BUFFER_BYTES = 1024 * 1024; // 1 MB - private final Consumer messageConsumer; - /** - * Raw bytes waiting for a complete line delimiter. We buffer raw bytes — rather than - * decoded characters — so that multi-byte UTF-8 sequences split across consecutive - * {@link #write} calls are never decoded prematurely. - */ + private final Consumer messageConsumer; private Buffer rawBuffer = Buffer.buffer(); private @Nullable Handler exceptionHandler; - PlainBodyWriteStream(Consumer messageConsumer) { + PlainBodyWriteStream(Consumer messageConsumer) { this.messageConsumer = messageConsumer; } - /** - * Scans {@link #rawBuffer} for {@code '\n'} bytes (0x0A, which never appears as a - * continuation byte in UTF-8), decodes each complete line as UTF-8, trims whitespace, - * and forwards non-empty lines to the message consumer. Unconsumed bytes are retained - * in the buffer for the next write. - */ - private void processLines() { - int start = 0; - int len = rawBuffer.length(); - while (true) { - int nlIdx = -1; - for (int i = start; i < len; i++) { - if (rawBuffer.getByte(i) == '\n') { - nlIdx = i; - break; - } - } - if (nlIdx < 0) break; - String line = new String(rawBuffer.getBytes(start, nlIdx), StandardCharsets.UTF_8).trim(); - start = nlIdx + 1; - if (!line.isEmpty()) { - messageConsumer.accept(line); - } - } - if (start > 0) { - rawBuffer = rawBuffer.getBuffer(start, len); - } - } - @Override public Future write(Buffer data) { if (rawBuffer.length() + data.length() > MAX_BUFFER_BYTES) { @@ -629,7 +597,6 @@ public Future write(Buffer data) { return Future.failedFuture(ex); } rawBuffer.appendBuffer(data); - processLines(); return Future.succeededFuture(); } @@ -644,10 +611,10 @@ public void write(Buffer data, Handler> handler) { @Override public void end(Handler> handler) { if (rawBuffer.length() > 0) { - String remaining = rawBuffer.toString(StandardCharsets.UTF_8).trim(); + String body = rawBuffer.toString(StandardCharsets.UTF_8).trim(); rawBuffer = Buffer.buffer(); - if (!remaining.isEmpty()) { - messageConsumer.accept(remaining); + if (!body.isEmpty()) { + messageConsumer.accept(new ServerSentEvent(body)); } } if (handler != null) { diff --git a/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientSSETest.java b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientSSETest.java index 2daefde1e..a0be1c299 100644 --- a/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientSSETest.java +++ b/extras/http-client-vertx/src/test/java/org/a2aproject/sdk/client/http/VertxA2AHttpClientSSETest.java @@ -1,253 +1,40 @@ package org.a2aproject.sdk.client.http; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import org.a2aproject.sdk.common.A2AErrorMessages; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.mockserver.integration.ClientAndServer; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -public class VertxA2AHttpClientSSETest { +public class VertxA2AHttpClientSSETest extends AbstractA2AHttpClientSSETest { - private ClientAndServer mockServer; - private VertxA2AHttpClient client; + private VertxA2AHttpClient vertxClient; - @BeforeEach - public void setup() { - mockServer = ClientAndServer.startClientAndServer(0); // Use random port - client = new VertxA2AHttpClient(); + @Override + protected A2AHttpClient createClient() { + vertxClient = new VertxA2AHttpClient(); + return vertxClient; } @AfterEach - public void teardown() { - if (client != null) { - client.close(); - } - if (mockServer != null) { - mockServer.stop(); + public void closeVertxClient() { + if (vertxClient != null) { + vertxClient.close(); } } - private String getBaseUrl() { - return "http://localhost:" + mockServer.getPort(); - } - - @Test - public void testGetAsyncSSE() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: event1\n\ndata: event2\n\ndata: event3\n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS), "Expected completion handler to be called"); - assertNull(error.get(), "Expected no errors"); - assertFalse(events.isEmpty(), "Expected to receive events"); - assertTrue(events.contains("event1"), "Expected event1"); - assertTrue(events.contains("event2"), "Expected event2"); - assertTrue(events.contains("event3"), "Expected event3"); - } - - @Test - public void testPostAsyncSSE() throws Exception { - mockServer - .when(request() - .withMethod("POST") - .withPath("/sse") - .withBody("{\"subscribe\":true}")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: message1\n\ndata: message2\n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createPost() - .url(getBaseUrl() + "/sse") - .body("{\"subscribe\":true}") - .postAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS), "Expected completion handler to be called"); - assertNull(error.get(), "Expected no errors"); - assertFalse(events.isEmpty(), "Expected to receive events"); - assertTrue(events.contains("message1"), "Expected message1"); - assertTrue(events.contains("message2"), "Expected message2"); - } - - @Test - public void testSSEDataPrefixStripping() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: content here\n\ndata:no space\n\ndata: extra spaces \n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS)); - assertNull(error.get()); - assertTrue(events.contains("content here"), "Should have stripped 'data: ' prefix"); - assertTrue(events.contains("no space"), "Should handle 'data:' without space"); - assertTrue(events.contains("extra spaces"), "Should trim whitespace"); - } - - @Test - public void testSSEAuthenticationError() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response().withStatusCode(401)); - - CountDownLatch errorLatch = new CountDownLatch(1); - AtomicReference error = new AtomicReference<>(); - AtomicBoolean completed = new AtomicBoolean(false); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - msg -> {}, - e -> { - error.set(e); - errorLatch.countDown(); - }, - () -> completed.set(true) - ); - - assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Expected error handler to be called"); - assertNotNull(error.get(), "Expected an error"); - assertTrue(error.get() instanceof IOException, "Expected IOException"); - assertTrue(error.get().getMessage().contains("Authentication failed"), - "Expected authentication error message but got: " + error.get().getMessage()); - assertFalse(completed.get(), "Should not call completion handler on error"); - } - - @Test - public void testSSEAuthorizationError() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response().withStatusCode(403)); - - CountDownLatch errorLatch = new CountDownLatch(1); - AtomicReference error = new AtomicReference<>(); - AtomicBoolean completed = new AtomicBoolean(false); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - msg -> {}, - e -> { - error.set(e); - errorLatch.countDown(); - }, - () -> completed.set(true) - ); - - assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Expected error handler to be called"); - assertNotNull(error.get(), "Expected an error"); - assertTrue(error.get() instanceof IOException, "Expected IOException"); - assertTrue(error.get().getMessage().contains("Authorization failed"), - "Expected authorization error message but got: " + error.get().getMessage()); - assertFalse(completed.get(), "Should not call completion handler on error"); - } + // The two tests below expose gaps in the Vert.x SSE path: it delegates to + // Vert.x's built-in BodyCodec.sseStream() rather than ServerSentEventParser, + // so last-event-id propagation and end-of-stream flush() are not supported. + // These will be fixed when the Vert.x path is migrated to ServerSentEventParser. + @Override @Test - public void testSSEEmptyLinesIgnored() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: first\n\n\n\ndata: second\n\ndata: \n\ndata: third\n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS)); - assertNull(error.get()); - assertEquals(3, events.size(), "Should have received 3 non-empty events"); - assertTrue(events.contains("first")); - assertTrue(events.contains("second")); - assertTrue(events.contains("third")); + @Disabled("Vert.x BodyCodec.sseStream() does not propagate last event ID to subsequent events") + public void testSSEEventIdAndLastEventId() { } + @Override @Test - public void testSSEHeaderPropagation() throws Exception { - mockServer - .when(request() - .withMethod("GET") - .withPath("/sse") - .withHeader("Accept", "text/event-stream") - .withHeader("Authorization", "Bearer token")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: authenticated\n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .addHeader("Authorization", "Bearer token") - .getAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS)); - assertNull(error.get()); - assertTrue(events.contains("authenticated")); + @Disabled("Vert.x BodyCodec.sseStream() has no flush() equivalent for streams ending without a trailing blank line") + public void testSSEStreamEndingWithoutTrailingEmptyLine() { } } diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClient.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClient.java index 652bc2451..71c425797 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClient.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClient.java @@ -33,7 +33,7 @@ * .url("http://localhost:9999/message:stream") * .body(jsonBody) * .postAsyncSSE( - * message -> System.out.println("Event: " + message), + * event -> System.out.println("Event: " + event.data()), * error -> System.err.println("Error: " + error), * () -> System.out.println("Stream complete") * ); @@ -45,9 +45,9 @@ public interface A2AHttpClient { /** HTTP Content-Type header name. */ - String CONTENT_TYPE= "Content-Type"; + String CONTENT_TYPE = "Content-Type"; /** JSON content type value. */ - String APPLICATION_JSON= "application/json"; + String APPLICATION_JSON = "application/json"; /** HTTP Accept header name. */ String ACCEPT = "Accept"; /** SSE event stream content type. */ @@ -135,7 +135,7 @@ interface GetBuilder extends Builder { * @throws InterruptedException if the operation is interrupted */ CompletableFuture getAsyncSSE( - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException; } @@ -177,7 +177,7 @@ interface PostBuilder extends Builder { * @throws InterruptedException if the operation is interrupted */ CompletableFuture postAsyncSSE( - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException; } diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java index 7f530e2e0..7499d52ac 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/JdkA2AHttpClient.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Flow; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import org.jspecify.annotations.Nullable; @@ -135,15 +136,17 @@ protected HttpRequest.Builder createRequestBuilder() throws IOException { protected CompletableFuture asyncRequest( HttpRequest request, - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable ) { + ServerSentEventParser sseParser = new ServerSentEventParser(messageConsumer, errorConsumer); + AtomicBoolean useSseParser = new AtomicBoolean(false); + AtomicBoolean errorNotified = new AtomicBoolean(false); + StringBuilder nonSseBodyBuffer = new StringBuilder(); + Flow.Subscriber subscriber = new Flow.Subscriber() { private Flow.@Nullable Subscription subscription; - private volatile boolean errorRaised = false; - private boolean isSseStream = false; - private boolean firstMeaningfulLineSeen = false; @Override public void onSubscribe(Flow.Subscription subscription) { @@ -153,24 +156,15 @@ public void onSubscribe(Flow.Subscription subscription) { @Override public void onNext(String item) { - if (item != null && !item.isEmpty()) { - if (!firstMeaningfulLineSeen) { - firstMeaningfulLineSeen = true; - isSseStream = item.startsWith("data:") || item.startsWith(":") - || item.startsWith("event:") || item.startsWith("id:") - || item.startsWith("retry:"); - } - if (isSseStream) { - if (item.startsWith("data:")) { - String data = item.substring(5).trim(); - if (!data.isEmpty()) { - messageConsumer.accept(data); - } - } - // Other SSE control lines (event:, id:, retry:, :) are ignored + if (item != null) { + if (useSseParser.get()) { + sseParser.processLine(item); } else { - // Plain error body: deliver so SSEEventListener can parse the typed error - messageConsumer.accept(item); + // Preserve blank lines so JSON string values containing literal newlines survive intact + if (nonSseBodyBuffer.length() > 0) { + nonSseBodyBuffer.append('\n'); + } + nonSseBodyBuffer.append(item); } } if (subscription != null) { @@ -180,8 +174,7 @@ public void onNext(String item) { @Override public void onError(Throwable throwable) { - if (!errorRaised) { - errorRaised = true; + if (errorNotified.compareAndSet(false, true)) { errorConsumer.accept(throwable); } if (subscription != null) { @@ -191,7 +184,15 @@ public void onError(Throwable throwable) { @Override public void onComplete() { - if (!errorRaised) { + if (!errorNotified.get()) { + if (useSseParser.get()) { + sseParser.flush(); + } else { + String body = nonSseBodyBuffer.toString(); + if (!body.isEmpty()) { + messageConsumer.accept(new ServerSentEvent(body)); + } + } completeRunnable.run(); } if (subscription != null) { @@ -200,7 +201,7 @@ public void onComplete() { } }; - // Create a custom body handler that checks status before processing body + // Create a custom body handler that checks status and Content-Type before processing body BodyHandler bodyHandler = responseInfo -> { // Check for authentication/authorization errors only if (responseInfo.statusCode() == HTTP_UNAUTHORIZED || responseInfo.statusCode() == HTTP_FORBIDDEN) { @@ -216,37 +217,42 @@ public void onComplete() { public void onSubscribe(Flow.Subscription subscription) { subscriber.onError(new IOException(errorMessage)); } - + @Override public void onNext(List item) { // Should not be called } - + @Override public void onError(Throwable throwable) { // Should not be called } - + @Override public void onComplete() { // Should not be called } }); - } else { - // For all other status codes (including other errors), proceed with normal line subscriber - return BodyHandlers.fromLineSubscriber(subscriber).apply(responseInfo); } + // Use SSE parser only for actual SSE responses; plain body lines are forwarded directly + String contentType = responseInfo.headers().firstValue("Content-Type").orElse(""); + boolean isSse = JdkHttpResponse.success(responseInfo.statusCode()) + && contentType.contains(EVENT_STREAM); + useSseParser.set(isSse); + return BodyHandlers.fromLineSubscriber(subscriber).apply(responseInfo); }; // Send the response async, and let the subscriber handle the lines. + // handle() catches failures before the body handler is reached (e.g. connection + // errors, DNS failures) and routes them to errorConsumer, then always completes + // normally — consistent with the Vert.x and Android implementations. return httpClient.sendAsync(request, bodyHandler) - .thenAccept(response -> { - // Handle non-authentication/non-authorization errors here - if (!isSuccessStatus(response.statusCode()) && - response.statusCode() != HTTP_UNAUTHORIZED && - response.statusCode() != HTTP_FORBIDDEN) { - subscriber.onError(new IOException("Request failed with status " + response.statusCode() + ":" + response.body())); + .handle((response, throwable) -> { + if (throwable != null && errorNotified.compareAndSet(false, true)) { + Throwable cause = throwable.getCause() != null ? throwable.getCause() : throwable; + errorConsumer.accept(cause); } + return null; }); } } @@ -279,7 +285,7 @@ public A2AHttpResponse get() throws IOException, InterruptedException { @Override public CompletableFuture getAsyncSSE( - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { HttpRequest request = createRequestBuilder(true) @@ -344,7 +350,7 @@ public A2AHttpResponse post() throws IOException, InterruptedException { @Override public CompletableFuture postAsyncSSE( - Consumer messageConsumer, + Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { HttpRequest request = createRequestBuilder(true) @@ -361,12 +367,12 @@ public int status() { } @Override - public boolean success() {// Send the request and get the response - return success(response); + public boolean success() { + return success(response.statusCode()); } - static boolean success(HttpResponse response) { - return response.statusCode() >= HTTP_OK && response.statusCode() < HTTP_MULT_CHOICE; + static boolean success(int statusCode) { + return statusCode >= HTTP_OK && statusCode < HTTP_MULT_CHOICE; } @Override @@ -374,8 +380,5 @@ public String body() { return response.body(); } } - - private static boolean isSuccessStatus(int statusCode) { - return statusCode >= HTTP_OK && statusCode < HTTP_MULT_CHOICE; - } } + diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEvent.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEvent.java new file mode 100644 index 000000000..2bbb1d4c2 --- /dev/null +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEvent.java @@ -0,0 +1,32 @@ +package org.a2aproject.sdk.client.http; + +import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; + +/** + * Represents a parsed Server-Sent Event (SSE). + *

            + * Each instance carries the fields defined by the SSE specification: + *

              + *
            • {@code data} — the event payload, already concatenated from one or more {@code data:} lines
            • + *
            • {@code eventType} — the event type from the {@code event:} field; never null, defaults to {@code "message"}
            • + *
            • {@code id} — the event ID from the {@code id:} field; null if absent
            • + *
            • {@code retry} — the reconnection interval in milliseconds from the {@code retry:} field; null if absent
            • + *
            + */ +public record ServerSentEvent(String data, String eventType, @Nullable String id, @Nullable Long retry) { + + /** + * Default event type per the SSE specification when no {@code event:} field is present. + */ + public static final String DEFAULT_EVENT_TYPE = "message"; + + public ServerSentEvent { + Assert.checkNotNullParam("data", data); + Assert.checkNotNullParam("eventType", eventType); + } + + public ServerSentEvent(String data) { + this(data, DEFAULT_EVENT_TYPE, null, null); + } +} diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEventParser.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEventParser.java new file mode 100644 index 000000000..24dabbf37 --- /dev/null +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEventParser.java @@ -0,0 +1,195 @@ +package org.a2aproject.sdk.client.http; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.logging.Logger; +import org.jspecify.annotations.Nullable; + +/** + * Streaming parser for Server-Sent Events (SSE). + *

            + * Feed lines one at a time via {@link #processLine}; call {@link #flush} when the stream ends. + * Not thread-safe — each connection should use its own instance. + */ +public class ServerSentEventParser { + private static final Logger log = Logger.getLogger(ServerSentEventParser.class.getName()); + + private static final int MAX_BUFFER_SIZE = 1000; + private static final int MAX_BUFFER_CHARS = 1024 * 1024; // 1 MB (Java chars, so up to 2 MB in UTF-16; actual UTF-8 bytes may differ) + private static final int MAX_LINE_LENGTH = 65536; // 64 KB + + private final Consumer eventConsumer; + private final @Nullable Consumer errorConsumer; + private final List dataBuffer = new ArrayList<>(); + private int dataBufferChars = 0; + private @Nullable String eventType; + // currentEventId: the spec's "event ID buffer" — persists across events, overwritten by each "id:" field. + // lastEventId: the spec's "last event ID string" — copied from currentEventId only at dispatch (empty line), + // so a skipped/corrupt event block cannot advance it. Returned to callers as the reconnect Last-Event-ID. + private @Nullable String currentEventId; + private @Nullable String lastEventId; + private @Nullable Long retry; + // Set when the current event block is corrupt (line too long, buffer overflow). + // All further fields are ignored until the next empty-line boundary. + private boolean skippingCurrentEvent = false; + + public ServerSentEventParser(Consumer eventConsumer) { + this(eventConsumer, null); + } + + public ServerSentEventParser(Consumer eventConsumer, @Nullable Consumer errorConsumer) { + this.eventConsumer = eventConsumer; + this.errorConsumer = errorConsumer; + } + + /** + * Processes a single line from the SSE stream. An empty line dispatches any buffered event. + * A {@code null} line is routed to the error consumer (or logged) without affecting the current event block. + */ + public void processLine(@Nullable String line) { + if (line == null) { + handleError(new IllegalArgumentException("Line cannot be null")); + return; + } + + // Check line length to prevent DoS; corrupt the current event so it is not dispatched + if (line.length() > MAX_LINE_LENGTH) { + handleError(new IllegalArgumentException("Line exceeds maximum length of " + MAX_LINE_LENGTH + " characters")); + skippingCurrentEvent = true; + dataBuffer.clear(); + dataBufferChars = 0; + return; + } + + if (skippingCurrentEvent && !line.isEmpty()) { + return; + } + + // Empty line - dispatch the buffered event + if (line.isEmpty()) { + dispatchEvent(); + return; + } + + // Comment line - ignore + if (line.startsWith(":")) { + return; + } + + // Parse field and value + int colonIndex = line.indexOf(':'); + if (colonIndex == -1) { + // Field with no value + processField(line, ""); + } else { + String field = line.substring(0, colonIndex); + String value = line.substring(colonIndex + 1); + + // Remove optional leading space from value + if (value.startsWith(" ")) { + value = value.substring(1); + } + + processField(field, value); + } + } + + private void processField(String field, String value) { + switch (field) { + case "data" -> { + // Check line count to prevent DoS; corrupt and skip the rest of this event block + if (dataBuffer.size() >= MAX_BUFFER_SIZE) { + handleError(new IllegalStateException("SSE data buffer exceeded maximum size of " + MAX_BUFFER_SIZE + " lines")); + skippingCurrentEvent = true; + dataBuffer.clear(); + dataBufferChars = 0; + return; + } + // Check total char count to prevent OOM on large streams + if (dataBufferChars + value.length() > MAX_BUFFER_CHARS) { + handleError(new IllegalStateException("SSE data buffer exceeded maximum size of " + MAX_BUFFER_CHARS + " chars")); + skippingCurrentEvent = true; + dataBuffer.clear(); + dataBufferChars = 0; + return; + } + dataBuffer.add(value); + dataBufferChars += value.length(); + } + case "event" -> eventType = value; + case "id" -> { + // Per SSE spec: ignore the id field if the value contains a U+0000 NULL character. + // An empty value is valid and clears the last event ID buffer on dispatch. + if (value.indexOf('\0') == -1) { + currentEventId = value; + } + } + case "retry" -> { + // Per SSE spec: ignore the retry field unless the value consists entirely of ASCII digits. + if (!value.isEmpty() && value.chars().allMatch(c -> c >= '0' && c <= '9')) { + try { + retry = Long.parseLong(value); + } catch (NumberFormatException e) { + // Value is all digits but too large for long; log and ignore per spec. + log.fine("Ignoring retry value out of long range: " + value); + } + } else { + log.fine("Ignoring non-digit retry value: " + value); + } + } + default -> { + // Unknown field - ignore per spec + log.fine("Ignoring unknown SSE field: " + field); + } + } + } + + private void dispatchEvent() { + // Per SSE spec: update lastEventId before checking data, so ID-only events (e.g. heartbeats) are tracked + if (currentEventId != null) { + lastEventId = currentEventId; + } + + String data = String.join("\n", dataBuffer); + String type = eventType; + String id = currentEventId; + + // Always reset at event boundary, regardless of whether an event is dispatched + dataBuffer.clear(); + dataBufferChars = 0; + eventType = null; + skippingCurrentEvent = false; + // currentEventId is NOT reset — it persists per the SSE specification + + // Per SSE spec: don't dispatch if data is empty (also covers limit-violation blocks, whose buffer was cleared) + if (data.isEmpty()) { + return; + } + + eventConsumer.accept(new ServerSentEvent(data, type != null ? type : ServerSentEvent.DEFAULT_EVENT_TYPE, id, retry)); + } + + /** Dispatches any buffered data not yet followed by an empty line. Call when the stream ends. */ + public void flush() { + dispatchEvent(); + } + + /** Returns the last event ID received, or {@code null} if none. */ + public @Nullable String getLastEventId() { + return lastEventId; + } + + /** Returns the reconnection interval in milliseconds from the last {@code retry:} field, or {@code null} if none. */ + public @Nullable Long getRetry() { + return retry; + } + + private void handleError(Throwable error) { + if (errorConsumer != null) { + errorConsumer.accept(error); + } else { + log.warning("SSE parsing error: " + error.getMessage()); + } + } +} diff --git a/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java index 19c91ded8..b89476185 100644 --- a/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java @@ -166,7 +166,7 @@ public String body() { } @Override - public CompletableFuture getAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { + public CompletableFuture getAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { return null; } diff --git a/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientSSETest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientSSETest.java index 30a9a244f..63644fd1b 100644 --- a/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientSSETest.java +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/AbstractA2AHttpClientSSETest.java @@ -62,7 +62,7 @@ public void testGetAsyncSSE() throws Exception { client.createGet() .url(getBaseUrl() + "/sse") .getAsyncSSE( - events::add, + event -> events.add(event.data()), error::set, latch::countDown ); @@ -95,7 +95,7 @@ public void testPostAsyncSSE() throws Exception { .url(getBaseUrl() + "/sse") .body("{\"subscribe\":true}") .postAsyncSSE( - events::add, + event -> events.add(event.data()), error::set, latch::countDown ); @@ -114,7 +114,7 @@ public void testSSEDataPrefixStripping() throws Exception { .respond(response() .withStatusCode(200) .withHeader("Content-Type", "text/event-stream") - .withBody("data: content here\n\ndata:no space\n\ndata: extra spaces \n\n")); + .withBody("data: content here\n\ndata:no space\n\ndata: extra spaces \n\n")); CountDownLatch latch = new CountDownLatch(1); List events = new ArrayList<>(); @@ -123,7 +123,7 @@ public void testSSEDataPrefixStripping() throws Exception { client.createGet() .url(getBaseUrl() + "/sse") .getAsyncSSE( - events::add, + event -> events.add(event.data()), error::set, latch::countDown ); @@ -132,7 +132,8 @@ public void testSSEDataPrefixStripping() throws Exception { assertNull(error.get()); assertTrue(events.contains("content here"), "Should have stripped 'data: ' prefix"); assertTrue(events.contains("no space"), "Should handle 'data:' without space"); - assertTrue(events.contains("extra spaces"), "Should trim whitespace"); + // SSE spec: only first space after colon is removed, rest is preserved + assertTrue(events.contains(" extra spaces "), "Should preserve whitespace after first space"); } @Test @@ -209,7 +210,7 @@ public void testSSEEmptyLinesIgnored() throws Exception { client.createGet() .url(getBaseUrl() + "/sse") .getAsyncSSE( - events::add, + event -> events.add(event.data()), error::set, latch::countDown ); @@ -243,7 +244,7 @@ public void testSSEHeaderPropagation() throws Exception { .url(getBaseUrl() + "/sse") .addHeader("Authorization", "Bearer token") .getAsyncSSE( - events::add, + event -> events.add(event.data()), error::set, latch::countDown ); @@ -252,4 +253,128 @@ public void testSSEHeaderPropagation() throws Exception { assertNull(error.get()); assertTrue(events.contains("authenticated")); } + + @Test + public void testSSETypedEvents() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("event: update\ndata: payload1\n\nevent: delete\ndata: payload2\n\ndata: no-type\n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE(events::add, error::set, latch::countDown); + + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertNull(error.get()); + assertEquals(3, events.size()); + assertEquals("update", events.get(0).eventType()); + assertEquals("payload1", events.get(0).data()); + assertEquals("delete", events.get(1).eventType()); + assertEquals("payload2", events.get(1).data()); + assertEquals("message", events.get(2).eventType(), "Event without 'event:' field should default to 'message'"); + } + + @Test + public void testSSEEventIdAndLastEventId() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("id: 42\ndata: identified\n\ndata: no-id\n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE(events::add, error::set, latch::countDown); + + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertNull(error.get()); + assertEquals(2, events.size()); + assertEquals("42", events.get(0).id()); + assertEquals("42", events.get(1).id(), "Event without 'id:' field inherits last event ID per SSE spec"); + } + + @Test + public void testSSEMultiLineData() throws Exception { + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("data: line1\ndata: line2\ndata: line3\n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE(events::add, error::set, latch::countDown); + + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertNull(error.get()); + assertEquals(1, events.size()); + assertEquals("line1\nline2\nline3", events.get(0).data()); + } + + @Test + public void testSSEStreamEndingWithoutTrailingEmptyLine() throws Exception { + // Stream ends mid-event with no terminal empty line — flush() must dispatch the buffered data + mockServer + .when(request().withMethod("GET").withPath("/sse")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("data: flushed-event")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createGet() + .url(getBaseUrl() + "/sse") + .getAsyncSSE(events::add, error::set, latch::countDown); + + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertNull(error.get()); + assertEquals(1, events.size(), "Buffered event must be dispatched on stream end"); + assertEquals("flushed-event", events.get(0).data()); + } + + @Test + public void testPostSSETypedEvents() throws Exception { + mockServer + .when(request().withMethod("POST").withPath("/sse")) + .respond(response() + .withStatusCode(200) + .withHeader("Content-Type", "text/event-stream") + .withBody("event: result\nid: 99\ndata: done\n\n")); + + CountDownLatch latch = new CountDownLatch(1); + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + + client.createPost() + .url(getBaseUrl() + "/sse") + .body("{}") + .postAsyncSSE(events::add, error::set, latch::countDown); + + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertNull(error.get()); + assertEquals(1, events.size()); + assertEquals("result", events.get(0).eventType()); + assertEquals("99", events.get(0).id()); + assertEquals("done", events.get(0).data()); + } } diff --git a/http-client/src/test/java/org/a2aproject/sdk/client/http/ServerSentEventParserTest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/ServerSentEventParserTest.java new file mode 100644 index 000000000..0492d1152 --- /dev/null +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/ServerSentEventParserTest.java @@ -0,0 +1,513 @@ +package org.a2aproject.sdk.client.http; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +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.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.Test; + +public class ServerSentEventParserTest { + + @Test + public void testSimpleDataEvent() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("data: Hello World"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("Hello World", events.get(0).data()); + assertEquals("message", events.get(0).eventType()); + assertNull(events.get(0).id()); + assertNull(events.get(0).retry()); + } + + @Test + public void testMultiLineDataEvent() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("data: First line"); + parser.processLine("data: Second line"); + parser.processLine("data: Third line"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("First line\nSecond line\nThird line", events.get(0).data()); + } + + @Test + public void testEventWithType() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("event: custom"); + parser.processLine("data: Custom event data"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("Custom event data", events.get(0).data()); + assertEquals("custom", events.get(0).eventType()); + } + + @Test + public void testEventWithId() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("id: 123"); + parser.processLine("data: Event with ID"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("Event with ID", events.get(0).data()); + assertEquals("123", events.get(0).id()); + assertEquals("123", parser.getLastEventId()); + } + + @Test + public void testEventWithRetry() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("retry: 5000"); + parser.processLine("data: Event with retry"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("Event with retry", events.get(0).data()); + assertEquals(5000L, events.get(0).retry()); + assertEquals(5000L, parser.getRetry()); + } + + @Test + public void testCompleteEvent() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("event: notification"); + parser.processLine("id: msg-001"); + parser.processLine("retry: 3000"); + parser.processLine("data: Complete event"); + parser.processLine(""); + + assertEquals(1, events.size()); + ServerSentEvent event = events.get(0); + assertEquals("Complete event", event.data()); + assertEquals("notification", event.eventType()); + assertEquals("msg-001", event.id()); + assertEquals(3000L, event.retry()); + } + + @Test + public void testMultipleEvents() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + // First event + parser.processLine("event: type1"); + parser.processLine("data: First"); + parser.processLine(""); + + // Second event + parser.processLine("event: type2"); + parser.processLine("data: Second"); + parser.processLine(""); + + assertEquals(2, events.size()); + assertEquals("First", events.get(0).data()); + assertEquals("type1", events.get(0).eventType()); + assertEquals("Second", events.get(1).data()); + assertEquals("type2", events.get(1).eventType()); + } + + @Test + public void testEmptyIdClearsLastEventId() { + // Per WHATWG SSE spec: id: with an empty value sets lastEventId to "" (clears it). + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("id: initial"); + parser.processLine("data: First"); + parser.processLine(""); + + parser.processLine("id:"); + parser.processLine("data: Second"); + parser.processLine(""); + + assertEquals(2, events.size()); + assertEquals("initial", events.get(0).id()); + assertEquals("", events.get(1).id(), "Empty id: should set currentEventId to empty string"); + assertEquals("", parser.getLastEventId(), "Empty id: should clear lastEventId to empty string"); + } + + @Test + public void testInvalidRetryIsIgnored() { + // Per SSE spec: non-digit retry values are silently ignored; the event is still dispatched. + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + assertDoesNotThrow(() -> parser.processLine("retry: not-a-number")); + assertDoesNotThrow(() -> parser.processLine("retry: +100")); + assertDoesNotThrow(() -> parser.processLine("retry: -1")); + assertDoesNotThrow(() -> parser.processLine("retry: 1.5")); + parser.processLine("data: Test"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertNull(events.get(0).retry(), "Retry should remain null after invalid values"); + } + + @Test + public void testCommentLinesIgnored() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine(": This is a comment"); + parser.processLine("data: Real data"); + parser.processLine(": Another comment"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("Real data", events.get(0).data()); + } + + @Test + public void testDataPrefixStripping() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("data: with space"); + parser.processLine(""); + parser.processLine("data:no space"); + parser.processLine(""); + parser.processLine("data: extra spaces "); + parser.processLine(""); + + assertEquals(3, events.size()); + assertEquals("with space", events.get(0).data()); + assertEquals("no space", events.get(1).data()); + // SSE spec: remove only the first space after colon, preserve the rest + assertEquals(" extra spaces ", events.get(2).data()); + } + + @Test + public void testEmptyDataFieldIgnored() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("data:"); + parser.processLine(""); + + assertEquals(0, events.size(), "Empty data field should not dispatch event"); + } + + @Test + public void testMultipleEmptyLinesIgnored() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("data: first"); + parser.processLine(""); + parser.processLine(""); + parser.processLine(""); + parser.processLine("data: second"); + parser.processLine(""); + + assertEquals(2, events.size()); + assertEquals("first", events.get(0).data()); + assertEquals("second", events.get(1).data()); + } + + @Test + public void testFieldWithoutColon() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("data"); + parser.processLine(""); + + assertEquals(0, events.size(), "Field without value should result in empty data"); + } + + @Test + public void testFlush() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("data: Unflushed"); + assertEquals(0, events.size(), "Event should not be dispatched yet"); + + parser.flush(); + assertEquals(1, events.size(), "Flush should dispatch buffered event"); + assertEquals("Unflushed", events.get(0).data()); + } + + @Test + public void testNullLineIgnored() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine(null); + parser.processLine("data: Valid"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("Valid", events.get(0).data()); + } + + @Test + public void testEventTypeResetBetweenEvents() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("event: custom"); + parser.processLine("data: First"); + parser.processLine(""); + + parser.processLine("data: Second"); + parser.processLine(""); + + assertEquals(2, events.size()); + assertEquals("custom", events.get(0).eventType()); + assertEquals("message", events.get(1).eventType(), "Event type should reset to 'message' after dispatch"); + } + + @Test + public void testIdPersistsAcrossEvents() { + // Per SSE spec, the "last event ID buffer" is never reset between events; + // it persists until explicitly changed by another id: field. + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("id: 100"); + parser.processLine("data: First"); + parser.processLine(""); + + parser.processLine("data: Second"); + parser.processLine(""); + + assertEquals(2, events.size()); + assertEquals("100", events.get(0).id()); + assertEquals("100", events.get(1).id(), "ID should carry over to subsequent events per SSE spec"); + assertEquals("100", parser.getLastEventId(), "lastEventId should persist"); + } + + @Test + public void testIdWithNullCharacterIsIgnored() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + // id containing U+0000 must be ignored per SSE spec + parser.processLine("id: before"); + parser.processLine("data: First"); + parser.processLine(""); + + parser.processLine("id: invalidid"); + parser.processLine("data: Second"); + parser.processLine(""); + + assertEquals(2, events.size()); + assertEquals("before", events.get(0).id()); + // The null-containing id is ignored; currentEventId stays "before" (it persists) + assertEquals("before", events.get(1).id()); + // lastEventId should still be "before" since the null id was discarded + assertEquals("before", parser.getLastEventId()); + } + + @Test + public void testRetryPersistsAcrossEvents() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("retry: 2000"); + parser.processLine("data: First"); + parser.processLine(""); + + parser.processLine("data: Second"); + parser.processLine(""); + + assertEquals(2, events.size()); + assertEquals(2000L, events.get(0).retry()); + assertEquals(2000L, events.get(1).retry()); + assertEquals(2000L, parser.getRetry(), "Retry should persist"); + } + + @Test + public void testUnknownFieldIgnored() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("unknown: field"); + parser.processLine("data: Valid"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("Valid", events.get(0).data()); + } + + // --- errorConsumer tests --- + + @Test + public void testErrorConsumerCalledForNullLine() { + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add, error::set); + + parser.processLine(null); + + assertNotNull(error.get(), "errorConsumer should be called for null line"); + assertEquals(IllegalArgumentException.class, error.get().getClass()); + assertEquals(0, events.size(), "No events should be dispatched"); + } + + @Test + public void testErrorConsumerCalledForLineTooLong() { + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add, error::set); + + // Oversized line mid-event: the whole event block is discarded + parser.processLine("data: before overflow"); + String longLine = "data: " + "x".repeat(65537); + parser.processLine(longLine); + // Subsequent lines in the same block are skipped + parser.processLine("data: should be skipped"); + parser.processLine(""); // end of corrupted block — nothing dispatched + + assertNotNull(error.get(), "errorConsumer should be called for oversized line"); + assertEquals(IllegalArgumentException.class, error.get().getClass()); + assertNotNull(error.get().getMessage()); + assertEquals(0, events.size(), "Corrupted event block must not be dispatched"); + + // Parser recovers cleanly at the next event boundary + parser.processLine("data: recovered"); + parser.processLine(""); + assertEquals(1, events.size(), "Parser should recover after oversized line"); + assertEquals("recovered", events.get(0).data()); + } + + @Test + public void testErrorConsumerCalledForBufferOverflow() { + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add, error::set); + + for (int i = 0; i < 1000; i++) { + parser.processLine("data: line" + i); + } + assertNull(error.get(), "No error expected before limit"); + + parser.processLine("data: overflow"); + assertNotNull(error.get(), "errorConsumer should be called when buffer limit exceeded"); + assertEquals(IllegalStateException.class, error.get().getClass()); + + // Lines in the same event block after the overflow are skipped + parser.processLine("data: skipped in same block"); + parser.processLine(""); // end of corrupted block — nothing dispatched + assertEquals(0, events.size(), "Corrupted event block must not be dispatched"); + + // Parser recovers cleanly at the next event boundary + parser.processLine("data: recovered"); + parser.processLine(""); + assertEquals(1, events.size(), "Parser should recover after buffer overflow"); + assertEquals("recovered", events.get(0).data()); + } + + @Test + public void testErrorConsumerCalledForBufferByteOverflow() { + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add, error::set); + + // Value is 65530 chars so the full line ("data: " + value = 65536) stays within the per-line + // limit; 17 such lines (17 * 65530 = 1,114,010 bytes) exceed the 1MB buffer byte limit. + String bigValue = "x".repeat(65530); + for (int i = 0; i < 17; i++) { + parser.processLine("data: " + bigValue); + } + + assertNotNull(error.get(), "errorConsumer should be called when byte limit exceeded"); + assertEquals(IllegalStateException.class, error.get().getClass()); + + // Lines in the same event block after the overflow are skipped + parser.processLine("data: skipped in same block"); + parser.processLine(""); // end of corrupted block — nothing dispatched + assertEquals(0, events.size(), "Corrupted event block must not be dispatched"); + + // Parser recovers cleanly at the next event boundary + parser.processLine("data: recovered"); + parser.processLine(""); + assertEquals(1, events.size(), "Parser should recover after byte overflow"); + assertEquals("recovered", events.get(0).data()); + } + + @Test + public void testInvalidRetryDoesNotCallErrorConsumer() { + // Per SSE spec: non-digit retry values are silently ignored, not errors. + List events = new ArrayList<>(); + AtomicReference error = new AtomicReference<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add, error::set); + + parser.processLine("retry: not-a-number"); + parser.processLine("retry: +100"); + parser.processLine("data: Test"); + parser.processLine(""); + + assertNull(error.get(), "errorConsumer must not be called for non-digit retry values"); + assertEquals(1, events.size(), "Event should still be dispatched"); + assertNull(events.get(0).retry(), "Retry should remain null"); + } + + @Test + public void testProcessingContinuesAfterErrorConsumerInvocation() { + List events = new ArrayList<>(); + List errors = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add, errors::add); + + parser.processLine(null); + parser.processLine("data: recovered"); + parser.processLine(""); + + assertEquals(1, errors.size(), "Should have one error from null line"); + assertEquals(1, events.size(), "Should still dispatch the event after error"); + assertEquals("recovered", events.get(0).data()); + } + + @Test + public void testNullLineWithoutErrorConsumerLogsAndContinues() { + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + // Without errorConsumer: null is logged, not thrown + assertDoesNotThrow(() -> parser.processLine(null)); + + parser.processLine("data: still works"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("still works", events.get(0).data()); + } + + @Test + public void testCRLFLineTerminatorsPreservedInValue() { + // SSEParser processes individual lines after line-splitting by the HTTP client. + // Callers (e.g., BufferedReader.readLine()) strip the \r\n terminator before passing + // the line here, so processLine never receives a bare \r from a CRLF stream. + // If a caller passes a line with a trailing \r (e.g., a non-standard source), it is + // preserved in the data value — stripping is the caller's responsibility. + List events = new ArrayList<>(); + ServerSentEventParser parser = new ServerSentEventParser(events::add); + + parser.processLine("data: value\r"); + parser.processLine(""); + + assertEquals(1, events.size()); + assertEquals("value\r", events.get(0).data()); + } +} diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index d82c52ab6..292c68e5e 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -40,6 +40,11 @@ a2a-java-sdk-http-client-vertx test + + ${project.groupId} + a2a-java-sdk-http-client-android + test + ${project.groupId} a2a-java-sdk-tests-server-common diff --git a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index 35f63b7e7..492e2517d 100644 --- a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -208,6 +208,7 @@ void setupRoutes(@Observes Router router) { router.route().handler(BodyHandler.create()); // Main JSON-RPC endpoint: POST / + // ordered=false: delegation via Vert.x WebClient can share the same event loop context as the outer request; ordered=true would serialize them, causing a 30s deadlock. router.post("/") .consumes(APPLICATION_JSON) .blockingHandler(ctx -> { @@ -220,7 +221,7 @@ void setupRoutes(@Observes Router router) { } catch (Exception e) { VertxSecurityHelper.handleGenericError(ctx); } - }); + }, false); // Agent card endpoint: GET /.well-known/agent-card.json router.get("/.well-known/agent-card.json") diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCAndroidTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCAndroidTest.java new file mode 100644 index 000000000..f973913be --- /dev/null +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCAndroidTest.java @@ -0,0 +1,16 @@ +package org.a2aproject.sdk.server.apps.quarkus; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusA2AJSONRPCAndroidTest extends QuarkusA2AJSONRPCTest { + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder().httpClient(new AndroidA2AHttpClient())); + } +} diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthAndroidTest.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthAndroidTest.java new file mode 100644 index 000000000..70e4baa37 --- /dev/null +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/QuarkusA2AJSONRPCWithAuthAndroidTest.java @@ -0,0 +1,56 @@ +package org.a2aproject.sdk.server.apps.quarkus; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransport; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfig; +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.server.apps.common.AuthTestProfile; +import org.a2aproject.sdk.spec.TransportProtocol; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +/** + * Authentication tests for JSON-RPC transport with Android HTTP client. + */ +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class QuarkusA2AJSONRPCWithAuthAndroidTest extends AbstractA2AServerWithAuthTest { + + public QuarkusA2AJSONRPCWithAuthAndroidTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.JSONRPC.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder() + .httpClient(new AndroidA2AHttpClient()) + .addInterceptor(authInterceptor) + .build(); + + builder.withTransport(JSONRPCTransport.class, config); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(JSONRPCTransport.class, + new JSONRPCTransportConfigBuilder() + .httpClient(new AndroidA2AHttpClient())); + } +} diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index deef848fd..2c57eaed1 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -40,6 +40,11 @@ a2a-java-sdk-http-client-vertx test + + ${project.groupId} + a2a-java-sdk-http-client-android + test + ${project.groupId} a2a-java-sdk-client-transport-rest diff --git a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java index 339a29ecc..170aab63f 100644 --- a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java @@ -165,13 +165,17 @@ void setupRouter(@Observes @Priority(10) Router router) { // Message Routes + // ordered=false on all blocking handlers: A2A requests are independent, and agent + // delegation via Vert.x WebClient can land on the same event loop context as the outer + // request. ordered=true would serialize them, causing a 30s deadlock. + // POST /{tenant}/message:send - Non-streaming message send router.postWithRegex("^\\/(?[^\\/]*\\/?)message:send$") .handler(BodyHandler.create()) .blockingHandler(authenticated(ctx -> { String body = extractBody(ctx); sendMessage(body, ctx); - })); + }), false); // POST /{tenant}/message:stream - Streaming message with SSE router.postWithRegex("^\\/(?[^\\/]*\\/?)message:stream$") @@ -179,19 +183,19 @@ void setupRouter(@Observes @Priority(10) Router router) { .blockingHandler(authenticated(ctx -> { String body = extractBody(ctx); sendMessageStreaming(body, ctx); - })); + }), false); // Task Routes // GET /{tenant}/tasks - List tasks with query params router.getWithRegex("^\\/(?[^\\/]*\\/?)tasks\\??") .order(0) - .blockingHandler(authenticated(this::listTasks)); + .blockingHandler(authenticated(this::listTasks), false); // GET /{tenant}/tasks/{taskId} - Get specific task router.getWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^:^/]+)$") .order(1) - .blockingHandler(authenticated(this::getTask)); + .blockingHandler(authenticated(this::getTask), false); // POST /{tenant}/tasks/{taskId}:cancel - Cancel task router.postWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):cancel$") @@ -200,12 +204,12 @@ void setupRouter(@Observes @Priority(10) Router router) { .blockingHandler(authenticated(ctx -> { String body = extractBody(ctx); cancelTask(body, ctx); - })); + }), false); // POST /{tenant}/tasks/{taskId}:subscribe - Subscribe to task updates (SSE) router.postWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):subscribe$") .order(1) - .blockingHandler(authenticated(this::subscribeToTask)); + .blockingHandler(authenticated(this::subscribeToTask), false); // Push Notification Routes @@ -216,22 +220,22 @@ void setupRouter(@Observes @Priority(10) Router router) { .blockingHandler(authenticated(ctx -> { String body = extractBody(ctx); createTaskPushNotificationConfiguration(body, ctx); - })); + }), false); // GET /{tenant}/tasks/{taskId}/pushNotificationConfigs/{configId} router.getWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^\\/]+)") .order(2) - .blockingHandler(authenticated(this::getTaskPushNotificationConfiguration)); + .blockingHandler(authenticated(this::getTaskPushNotificationConfiguration), false); // GET /{tenant}/tasks/{taskId}/pushNotificationConfigs router.getWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/?$") .order(3) - .blockingHandler(authenticated(this::listTaskPushNotificationConfigurations)); + .blockingHandler(authenticated(this::listTaskPushNotificationConfigurations), false); // DELETE /{tenant}/tasks/{taskId}/pushNotificationConfigs/{configId} router.deleteWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^/]+)") .order(1) - .blockingHandler(authenticated(this::deleteTaskPushNotificationConfiguration)); + .blockingHandler(authenticated(this::deleteTaskPushNotificationConfiguration), false); // Discovery Routes @@ -245,7 +249,7 @@ void setupRouter(@Observes @Priority(10) Router router) { router.getWithRegex("^\\/(?[^\\/]*\\/?)extendedAgentCard$") .order(1) .produces(APPLICATION_JSON) - .blockingHandler(authenticated(this::getExtendedAgentCard)); + .blockingHandler(authenticated(this::getExtendedAgentCard), false); } private Handler authenticated(Consumer action) { diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestAndroidTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestAndroidTest.java new file mode 100644 index 000000000..10dc1b682 --- /dev/null +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestAndroidTest.java @@ -0,0 +1,16 @@ +package org.a2aproject.sdk.server.rest.quarkus; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusA2ARestAndroidTest extends QuarkusA2ARestTest { + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(RestTransport.class, new RestTransportConfigBuilder().httpClient(new AndroidA2AHttpClient())); + } +} diff --git a/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthAndroidTest.java b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthAndroidTest.java new file mode 100644 index 000000000..ede590ebd --- /dev/null +++ b/reference/rest/src/test/java/org/a2aproject/sdk/server/rest/quarkus/QuarkusA2ARestWithAuthAndroidTest.java @@ -0,0 +1,67 @@ +package org.a2aproject.sdk.server.rest.quarkus; + +import org.a2aproject.sdk.client.ClientBuilder; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; +import org.a2aproject.sdk.client.transport.rest.RestTransport; +import org.a2aproject.sdk.client.transport.rest.RestTransportConfigBuilder; +import org.a2aproject.sdk.client.transport.spi.interceptors.auth.AuthInterceptor; +import org.a2aproject.sdk.server.apps.common.AbstractA2AServerWithAuthTest; +import org.a2aproject.sdk.server.apps.common.AuthTestProfile; +import org.a2aproject.sdk.spec.TransportProtocol; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.junit.jupiter.api.Test; + +/** + * Authentication tests for REST (HTTP JSON) transport with Android HTTP client. + */ +@QuarkusTest +@TestProfile(AuthTestProfile.class) +public class QuarkusA2ARestWithAuthAndroidTest extends AbstractA2AServerWithAuthTest { + + public QuarkusA2ARestWithAuthAndroidTest() { + super(8081); + } + + @Override + protected String getTransportProtocol() { + return TransportProtocol.HTTP_JSON.asString(); + } + + @Override + protected String getTransportUrl() { + return "http://localhost:8081"; + } + + @Override + protected void configureTransportWithAuth(ClientBuilder builder) { + AuthInterceptor authInterceptor = new AuthInterceptor( + (schemeName, context) -> BASIC_AUTH_SCHEME_NAME.equals(schemeName) ? getEncodedCredentials() : null + ); + + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new AndroidA2AHttpClient()) + .addInterceptor(authInterceptor)); + } + + @Override + protected void configureTransport(ClientBuilder builder) { + builder.withTransport(RestTransport.class, + new RestTransportConfigBuilder() + .httpClient(new AndroidA2AHttpClient())); + } + + @Test + @Override + public void testBasicAuthWorksViaHttp() throws Exception { + saveTaskInTaskStore(MINIMAL_TASK); + + givenAuthenticated() + .get("/tasks/" + MINIMAL_TASK.id()) + .then() + .statusCode(200); + + deleteTaskInTaskStore(MINIMAL_TASK.id()); + } +} diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java index 7ee97b094..7544d4f9f 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java @@ -19,6 +19,7 @@ import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; import org.a2aproject.sdk.server.agentexecution.AgentExecutor; @@ -249,7 +250,7 @@ public String body() { } @Override - public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { + public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { return null; } diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java index 979a95a9f..27b54f310 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java @@ -18,6 +18,7 @@ import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.common.A2AHeaders; import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; @@ -121,7 +122,7 @@ public String body() { } @Override - public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { + public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { return null; } diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestHttpClient.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestHttpClient.java index 2bb905bb1..82b6de8e6 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestHttpClient.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/TestHttpClient.java @@ -14,6 +14,7 @@ import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; import org.a2aproject.sdk.spec.Task; @@ -77,7 +78,7 @@ public String body() { } @Override - public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { + public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { return null; } From 7d9e22a88f824f069f5d2cdeb9ab58e569998d2c Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 12 May 2026 15:50:06 +0100 Subject: [PATCH 157/192] fix: unify HTTP clients The compat-0.3 modules can use the main HTTP client. Co-Authored-By: Claude Opus 4.6 --- boms/sdk/pom.xml | 7 - boms/sdk/src/it/sdk-usage-test/pom.xml | 6 - compat-0.3/client/base/pom.xml | 2 +- .../org/a2aproject/sdk/compat03/A2A_v0_3.java | 12 +- .../client/ClientBuilder_v0_3_Test.java | 4 +- compat-0.3/client/transport/jsonrpc/pom.xml | 2 +- .../JSONRPCTransportConfigBuilder_v0_3.java | 14 +- .../jsonrpc/JSONRPCTransportConfig_v0_3.java | 10 +- .../JSONRPCTransportProvider_v0_3.java | 4 +- .../jsonrpc/JSONRPCTransport_v0_3.java | 29 +- compat-0.3/client/transport/rest/pom.xml | 2 +- .../transport/rest/RestErrorMapper_v0_3.java | 4 +- .../rest/RestTransportConfigBuilder_v0_3.java | 14 +- .../rest/RestTransportConfig_v0_3.java | 10 +- .../rest/RestTransportProvider_v0_3.java | 9 +- .../transport/rest/RestTransport_v0_3.java | 49 +-- compat-0.3/client/transport/spi/pom.xml | 4 + .../client/http/A2ACardResolver_v0_3.java | 19 +- .../http/A2ACardResolver_v0_3_Test.java | 15 +- .../client/http/JsonMessages_v0_3.java | 2 +- compat-0.3/http-client/pom.xml | 39 --- .../client/http/A2AHttpClient_v0_3.java | 42 --- .../client/http/A2AHttpResponse_v0_3.java | 9 - .../client/http/JdkA2AHttpClient_v0_3.java | 330 ------------------ .../compat03/client/http/package-info.java | 5 - compat-0.3/pom.xml | 8 - .../QuarkusA2AJSONRPC_v0_3_AndroidTest.java | 4 +- .../QuarkusA2AJSONRPC_v0_3_JdkTest.java | 4 +- .../QuarkusA2AJSONRPC_v0_3_VertxTest.java | 4 +- ...usA2AJSONRPC_v0_3_WithAuthAndroidTest.java | 6 +- .../QuarkusA2AJSONRPC_v0_3_WithAuthTest.java | 6 +- ...rkusA2AJSONRPC_v0_3_WithAuthVertxTest.java | 6 +- .../QuarkusA2ARest_v0_3_AndroidTest.java | 4 +- .../quarkus/QuarkusA2ARest_v0_3_JdkTest.java | 4 +- .../QuarkusA2ARest_v0_3_VertxTest.java | 4 +- ...arkusA2ARest_v0_3_WithAuthAndroidTest.java | 6 +- .../QuarkusA2ARest_v0_3_WithAuthTest.java | 6 +- ...QuarkusA2ARest_v0_3_WithAuthVertxTest.java | 6 +- .../conversion/AndroidA2AHttpClient_v0_3.java | 108 ------ .../conversion/VertxA2AHttpClient_v0_3.java | 113 ------ 40 files changed, 138 insertions(+), 794 deletions(-) rename compat-0.3/{http-client => client/transport/spi}/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java (83%) rename compat-0.3/{http-client => client/transport/spi}/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java (91%) rename compat-0.3/{http-client => client/transport/spi}/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java (99%) delete mode 100644 compat-0.3/http-client/pom.xml delete mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpClient_v0_3.java delete mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpResponse_v0_3.java delete mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java delete mode 100644 compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/package-info.java delete mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AndroidA2AHttpClient_v0_3.java delete mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/VertxA2AHttpClient_v0_3.java diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index 149ebd6d3..e85d715e2 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -120,13 +120,6 @@ ${project.version} - - - ${project.groupId} - a2a-java-sdk-compat-0.3-http-client - ${project.version} - - ${project.groupId} diff --git a/boms/sdk/src/it/sdk-usage-test/pom.xml b/boms/sdk/src/it/sdk-usage-test/pom.xml index 851f98ea9..1f73494e9 100644 --- a/boms/sdk/src/it/sdk-usage-test/pom.xml +++ b/boms/sdk/src/it/sdk-usage-test/pom.xml @@ -113,12 +113,6 @@ a2a-java-sdk-compat-0.3-spec-grpc - - - org.a2aproject.sdk - a2a-java-sdk-compat-0.3-http-client - - org.a2aproject.sdk diff --git a/compat-0.3/client/base/pom.xml b/compat-0.3/client/base/pom.xml index 6fa0036ff..5fd78bdbe 100644 --- a/compat-0.3/client/base/pom.xml +++ b/compat-0.3/client/base/pom.xml @@ -20,7 +20,7 @@ ${project.groupId} - a2a-java-sdk-compat-0.3-http-client + a2a-java-sdk-http-client ${project.groupId} diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A_v0_3.java index 2be60b7ad..dfbc37386 100644 --- a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A_v0_3.java +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A_v0_3.java @@ -4,9 +4,9 @@ import java.util.List; import java.util.Map; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.compat03.client.http.A2ACardResolver_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientJSONError_v0_3; import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; @@ -138,7 +138,7 @@ private static Message_v0_3 toMessage(List> parts, Message_v0_3.Rol * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema */ public static AgentCard_v0_3 getAgentCard(String agentUrl) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { - return getAgentCard(new JdkA2AHttpClient_v0_3(), agentUrl); + return getAgentCard(A2AHttpClientFactory.create(), agentUrl); } /** @@ -150,7 +150,7 @@ public static AgentCard_v0_3 getAgentCard(String agentUrl) throws A2AClientError * @throws A2AClientError_v0_3 If an HTTP error occurs fetching the card * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema */ - public static AgentCard_v0_3 getAgentCard(A2AHttpClient_v0_3 httpClient, String agentUrl) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { + public static AgentCard_v0_3 getAgentCard(A2AHttpClient httpClient, String agentUrl) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { return getAgentCard(httpClient, agentUrl, null, null); } @@ -166,7 +166,7 @@ public static AgentCard_v0_3 getAgentCard(A2AHttpClient_v0_3 httpClient, String * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema */ public static AgentCard_v0_3 getAgentCard(String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { - return getAgentCard(new JdkA2AHttpClient_v0_3(), agentUrl, relativeCardPath, authHeaders); + return getAgentCard(A2AHttpClientFactory.create(), agentUrl, relativeCardPath, authHeaders); } /** @@ -181,7 +181,7 @@ public static AgentCard_v0_3 getAgentCard(String agentUrl, String relativeCardPa * @throws A2AClientError_v0_3 If an HTTP error occurs fetching the card * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema */ - public static AgentCard_v0_3 getAgentCard(A2AHttpClient_v0_3 httpClient, String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { + public static AgentCard_v0_3 getAgentCard(A2AHttpClient httpClient, String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(httpClient, agentUrl, relativeCardPath, authHeaders); return resolver.getAgentCard(); } diff --git a/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3_Test.java b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3_Test.java index 4b4e31d0b..fa910f041 100644 --- a/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3_Test.java +++ b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/client/ClientBuilder_v0_3_Test.java @@ -1,7 +1,7 @@ package org.a2aproject.sdk.compat03.client; import org.a2aproject.sdk.compat03.client.config.ClientConfig_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.grpc.GrpcTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; @@ -88,7 +88,7 @@ public void shouldCreateClient_differentConfigurations() throws A2AClientExcepti Client_v0_3 client = Client_v0_3 .builder(card) .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()) - .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfig_v0_3(new JdkA2AHttpClient_v0_3())) + .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfig_v0_3(new JdkA2AHttpClient())) .build(); Assertions.assertNotNull(client); diff --git a/compat-0.3/client/transport/jsonrpc/pom.xml b/compat-0.3/client/transport/jsonrpc/pom.xml index fd099d2d0..af1121c5f 100644 --- a/compat-0.3/client/transport/jsonrpc/pom.xml +++ b/compat-0.3/client/transport/jsonrpc/pom.xml @@ -19,7 +19,7 @@ ${project.groupId} - a2a-java-sdk-compat-0.3-http-client + a2a-java-sdk-http-client ${project.groupId} diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfigBuilder_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfigBuilder_v0_3.java index be9d95608..557832b97 100644 --- a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfigBuilder_v0_3.java +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfigBuilder_v0_3.java @@ -1,14 +1,14 @@ package org.a2aproject.sdk.compat03.client.transport.jsonrpc; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfigBuilder_v0_3; public class JSONRPCTransportConfigBuilder_v0_3 extends ClientTransportConfigBuilder_v0_3 { - private A2AHttpClient_v0_3 httpClient; + private A2AHttpClient httpClient; - public JSONRPCTransportConfigBuilder_v0_3 httpClient(A2AHttpClient_v0_3 httpClient) { + public JSONRPCTransportConfigBuilder_v0_3 httpClient(A2AHttpClient httpClient) { this.httpClient = httpClient; return this; @@ -16,13 +16,13 @@ public JSONRPCTransportConfigBuilder_v0_3 httpClient(A2AHttpClient_v0_3 httpClie @Override public JSONRPCTransportConfig_v0_3 build() { - // No HTTP client provided, fallback to the default one (JDK-based implementation) + // No HTTP client provided, fallback to the default one if (httpClient == null) { - httpClient = new JdkA2AHttpClient_v0_3(); + httpClient = A2AHttpClientFactory.create(); } JSONRPCTransportConfig_v0_3 config = new JSONRPCTransportConfig_v0_3(httpClient); config.setInterceptors(this.interceptors); return config; } -} \ No newline at end of file +} diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfig_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfig_v0_3.java index 7e01e3e56..9e67e4640 100644 --- a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfig_v0_3.java +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportConfig_v0_3.java @@ -1,21 +1,21 @@ package org.a2aproject.sdk.compat03.client.transport.jsonrpc; +import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfig_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; public class JSONRPCTransportConfig_v0_3 extends ClientTransportConfig_v0_3 { - private final A2AHttpClient_v0_3 httpClient; + private final A2AHttpClient httpClient; public JSONRPCTransportConfig_v0_3() { this.httpClient = null; } - public JSONRPCTransportConfig_v0_3(A2AHttpClient_v0_3 httpClient) { + public JSONRPCTransportConfig_v0_3(A2AHttpClient httpClient) { this.httpClient = httpClient; } - public A2AHttpClient_v0_3 getHttpClient() { + public A2AHttpClient getHttpClient() { return httpClient; } -} \ No newline at end of file +} diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportProvider_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportProvider_v0_3.java index afe66dadf..3787bf117 100644 --- a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportProvider_v0_3.java +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportProvider_v0_3.java @@ -1,6 +1,6 @@ package org.a2aproject.sdk.compat03.client.transport.jsonrpc; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; @@ -11,7 +11,7 @@ public class JSONRPCTransportProvider_v0_3 implements ClientTransportProvider_v0 @Override public JSONRPCTransport_v0_3 create(JSONRPCTransportConfig_v0_3 clientTransportConfig, AgentCard_v0_3 agentCard, String agentUrl) throws A2AClientException_v0_3 { if (clientTransportConfig == null) { - clientTransportConfig = new JSONRPCTransportConfig_v0_3(new JdkA2AHttpClient_v0_3()); + clientTransportConfig = new JSONRPCTransportConfig_v0_3(A2AHttpClientFactory.create()); } return new JSONRPCTransport_v0_3(clientTransportConfig.getHttpClient(), agentCard, agentUrl, clientTransportConfig.getInterceptors()); diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3.java index d379277cd..e7ee7eb47 100644 --- a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3.java +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3.java @@ -10,13 +10,14 @@ import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.compat03.client.http.A2ACardResolver_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallInterceptor_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.PayloadAndHeaders_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransport_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; @@ -69,7 +70,7 @@ public class JSONRPCTransport_v0_3 implements ClientTransport_v0_3 { private static final Class DELETE_TASK_PUSH_NOTIFICATION_CONFIG_RESPONSE_REFERENCE = DeleteTaskPushNotificationConfigResponse_v0_3.class; private static final Class GET_AUTHENTICATED_EXTENDED_CARD_RESPONSE_REFERENCE = GetAuthenticatedExtendedCardResponse_v0_3.class; - private final A2AHttpClient_v0_3 httpClient; + private final A2AHttpClient httpClient; private final String agentUrl; private final List interceptors; private AgentCard_v0_3 agentCard; @@ -83,9 +84,9 @@ public JSONRPCTransport_v0_3(AgentCard_v0_3 agentCard) { this(null, agentCard, agentCard.url(), null); } - public JSONRPCTransport_v0_3(A2AHttpClient_v0_3 httpClient, AgentCard_v0_3 agentCard, + public JSONRPCTransport_v0_3(A2AHttpClient httpClient, AgentCard_v0_3 agentCard, String agentUrl, List interceptors) { - this.httpClient = httpClient == null ? new JdkA2AHttpClient_v0_3() : httpClient; + this.httpClient = httpClient == null ? A2AHttpClientFactory.create() : httpClient; this.agentCard = agentCard; this.agentUrl = agentUrl; this.interceptors = interceptors; @@ -133,9 +134,9 @@ public void sendMessageStreaming(MessageSendParams_v0_3 request, Consumer sseEventListener.onMessage(msg, ref.get()), + event -> sseEventListener.onMessage(event.data(), ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), () -> { // Signal normal stream completion to error handler (null error means success) @@ -314,9 +315,9 @@ public void resubscribe(TaskIdParams_v0_3 request, Consumer sseEventListener.onMessage(msg, ref.get()), + event -> sseEventListener.onMessage(event.data(), ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), () -> { // Signal normal stream completion to error handler (null error means success) @@ -385,16 +386,16 @@ private PayloadAndHeaders_v0_3 applyInterceptors(String methodName, Object paylo } private String sendPostRequest(PayloadAndHeaders_v0_3 payloadAndHeaders) throws IOException, InterruptedException, JsonProcessingException_v0_3 { - A2AHttpClient_v0_3.PostBuilder builder = createPostBuilder(payloadAndHeaders); - A2AHttpResponse_v0_3 response = builder.post(); + A2AHttpClient.PostBuilder builder = createPostBuilder(payloadAndHeaders); + A2AHttpResponse response = builder.post(); if (!response.success()) { throw new IOException("Request failed " + response.status()); } return response.body(); } - private A2AHttpClient_v0_3.PostBuilder createPostBuilder(PayloadAndHeaders_v0_3 payloadAndHeaders) throws JsonProcessingException_v0_3 { - A2AHttpClient_v0_3.PostBuilder postBuilder = httpClient.createPost() + private A2AHttpClient.PostBuilder createPostBuilder(PayloadAndHeaders_v0_3 payloadAndHeaders) throws JsonProcessingException_v0_3 { + A2AHttpClient.PostBuilder postBuilder = httpClient.createPost() .url(agentUrl) .addHeader("Content-Type", "application/json") .body(JsonUtil_v0_3.toJson(payloadAndHeaders.getPayload())); diff --git a/compat-0.3/client/transport/rest/pom.xml b/compat-0.3/client/transport/rest/pom.xml index 2539152af..0b101ed9e 100644 --- a/compat-0.3/client/transport/rest/pom.xml +++ b/compat-0.3/client/transport/rest/pom.xml @@ -35,7 +35,7 @@ ${project.groupId} - a2a-java-sdk-compat-0.3-http-client + a2a-java-sdk-http-client com.google.protobuf diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java index d6732726e..d9b6d1368 100644 --- a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestErrorMapper_v0_3.java @@ -4,7 +4,7 @@ import com.google.gson.JsonObject; import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; +import org.a2aproject.sdk.client.http.A2AHttpResponse; import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; import org.a2aproject.sdk.compat03.spec.AuthenticatedExtendedCardNotConfiguredError_v0_3; import org.a2aproject.sdk.compat03.spec.ContentTypeNotSupportedError_v0_3; @@ -26,7 +26,7 @@ */ public class RestErrorMapper_v0_3 { - public static A2AClientException_v0_3 mapRestError(A2AHttpResponse_v0_3 response) { + public static A2AClientException_v0_3 mapRestError(A2AHttpResponse response) { return RestErrorMapper_v0_3.mapRestError(response.body(), response.status()); } diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfigBuilder_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfigBuilder_v0_3.java index 13794ee3f..cab5e3a82 100644 --- a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfigBuilder_v0_3.java +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfigBuilder_v0_3.java @@ -1,28 +1,28 @@ package org.a2aproject.sdk.compat03.client.transport.rest; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfigBuilder_v0_3; import org.jspecify.annotations.Nullable; public class RestTransportConfigBuilder_v0_3 extends ClientTransportConfigBuilder_v0_3 { - private @Nullable A2AHttpClient_v0_3 httpClient; + private @Nullable A2AHttpClient httpClient; - public RestTransportConfigBuilder_v0_3 httpClient(A2AHttpClient_v0_3 httpClient) { + public RestTransportConfigBuilder_v0_3 httpClient(A2AHttpClient httpClient) { this.httpClient = httpClient; return this; } @Override public RestTransportConfig_v0_3 build() { - // No HTTP client provided, fallback to the default one (JDK-based implementation) + // No HTTP client provided, fallback to the default one if (httpClient == null) { - httpClient = new JdkA2AHttpClient_v0_3(); + httpClient = A2AHttpClientFactory.create(); } RestTransportConfig_v0_3 config = new RestTransportConfig_v0_3(httpClient); config.setInterceptors(this.interceptors); return config; } -} \ No newline at end of file +} diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfig_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfig_v0_3.java index 0d6b1f859..16428649b 100644 --- a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfig_v0_3.java +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportConfig_v0_3.java @@ -1,22 +1,22 @@ package org.a2aproject.sdk.compat03.client.transport.rest; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; +import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportConfig_v0_3; import org.jspecify.annotations.Nullable; public class RestTransportConfig_v0_3 extends ClientTransportConfig_v0_3 { - private final @Nullable A2AHttpClient_v0_3 httpClient; + private final @Nullable A2AHttpClient httpClient; public RestTransportConfig_v0_3() { this.httpClient = null; } - public RestTransportConfig_v0_3(A2AHttpClient_v0_3 httpClient) { + public RestTransportConfig_v0_3(A2AHttpClient httpClient) { this.httpClient = httpClient; } - public @Nullable A2AHttpClient_v0_3 getHttpClient() { + public @Nullable A2AHttpClient getHttpClient() { return httpClient; } -} \ No newline at end of file +} diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportProvider_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportProvider_v0_3.java index 87dcdf5ce..46cf3fa1b 100644 --- a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportProvider_v0_3.java +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransportProvider_v0_3.java @@ -1,6 +1,6 @@ package org.a2aproject.sdk.compat03.client.transport.rest; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransportProvider_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientException_v0_3; import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; @@ -15,11 +15,10 @@ public String getTransportProtocol() { @Override public RestTransport_v0_3 create(RestTransportConfig_v0_3 clientTransportConfig, AgentCard_v0_3 agentCard, String agentUrl) throws A2AClientException_v0_3 { - RestTransportConfig_v0_3 transportConfig = clientTransportConfig; - if (transportConfig == null) { - transportConfig = new RestTransportConfig_v0_3(new JdkA2AHttpClient_v0_3()); + if (clientTransportConfig == null) { + clientTransportConfig = new RestTransportConfig_v0_3(A2AHttpClientFactory.create()); } - return new RestTransport_v0_3(clientTransportConfig.getHttpClient(), agentCard, agentUrl, transportConfig.getInterceptors()); + return new RestTransport_v0_3(clientTransportConfig.getHttpClient(), agentCard, agentUrl, clientTransportConfig.getInterceptors()); } @Override diff --git a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java index 7dc0b40fb..6ff2d560d 100644 --- a/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java +++ b/compat-0.3/client/transport/rest/src/main/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3.java @@ -6,10 +6,11 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.util.JsonFormat; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.compat03.client.http.A2ACardResolver_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.sse.RestSSEEventListener_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.ClientTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.ClientCallContext_v0_3; @@ -58,7 +59,7 @@ public class RestTransport_v0_3 implements ClientTransport_v0_3 { private static final Logger log = Logger.getLogger(RestTransport_v0_3.class.getName()); - private final A2AHttpClient_v0_3 httpClient; + private final A2AHttpClient httpClient; private final String agentUrl; private @Nullable final List interceptors; private AgentCard_v0_3 agentCard; @@ -68,9 +69,9 @@ public RestTransport_v0_3(AgentCard_v0_3 agentCard) { this(null, agentCard, agentCard.url(), null); } - public RestTransport_v0_3(@Nullable A2AHttpClient_v0_3 httpClient, AgentCard_v0_3 agentCard, + public RestTransport_v0_3(@Nullable A2AHttpClient httpClient, AgentCard_v0_3 agentCard, String agentUrl, @Nullable List interceptors) { - this.httpClient = httpClient == null ? new JdkA2AHttpClient_v0_3() : httpClient; + this.httpClient = httpClient == null ? A2AHttpClientFactory.create() : httpClient; this.agentCard = agentCard; this.agentUrl = agentUrl.endsWith("/") ? agentUrl.substring(0, agentUrl.length() - 1) : agentUrl; this.interceptors = interceptors; @@ -110,9 +111,9 @@ public void sendMessageStreaming(MessageSendParams_v0_3 messageSendParams, Consu AtomicReference> ref = new AtomicReference<>(); RestSSEEventListener_v0_3 sseEventListener = new RestSSEEventListener_v0_3(eventConsumer, errorConsumer); try { - A2AHttpClient_v0_3.PostBuilder postBuilder = createPostBuilder(agentUrl + "/v1/message:stream", payloadAndHeaders); + A2AHttpClient.PostBuilder postBuilder = createPostBuilder(agentUrl + "/v1/message:stream", payloadAndHeaders); ref.set(postBuilder.postAsyncSSE( - msg -> sseEventListener.onMessage(msg, ref.get()), + event -> sseEventListener.onMessage(event.data(), ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), () -> { // We don't need to do anything special on completion @@ -140,13 +141,13 @@ public Task_v0_3 getTask(TaskQueryParams_v0_3 taskQueryParams, @Nullable ClientC } else { url = agentUrl + String.format("/v1/tasks/%1s", taskQueryParams.id()); } - A2AHttpClient_v0_3.GetBuilder getBuilder = httpClient.createGet().url(url); + A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); if (payloadAndHeaders.getHeaders() != null) { for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { getBuilder.addHeader(entry.getKey(), entry.getValue()); } } - A2AHttpResponse_v0_3 response = getBuilder.get(); + A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper_v0_3.mapRestError(response); } @@ -213,13 +214,13 @@ public TaskPushNotificationConfig_v0_3 getTaskPushNotificationConfiguration(GetT agentCard, context); try { String url = agentUrl + String.format("/v1/tasks/%1s/pushNotificationConfigs/%2s", request.id(), configId); - A2AHttpClient_v0_3.GetBuilder getBuilder = httpClient.createGet().url(url); + A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); if (payloadAndHeaders.getHeaders() != null) { for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { getBuilder.addHeader(entry.getKey(), entry.getValue()); } } - A2AHttpResponse_v0_3 response = getBuilder.get(); + A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper_v0_3.mapRestError(response); } @@ -243,13 +244,13 @@ public List listTaskPushNotificationConfigurati agentCard, context); try { String url = agentUrl + String.format("/v1/tasks/%1s/pushNotificationConfigs", request.id()); - A2AHttpClient_v0_3.GetBuilder getBuilder = httpClient.createGet().url(url); + A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); if (payloadAndHeaders.getHeaders() != null) { for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { getBuilder.addHeader(entry.getKey(), entry.getValue()); } } - A2AHttpResponse_v0_3 response = getBuilder.get(); + A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper_v0_3.mapRestError(response); } @@ -272,13 +273,13 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC agentCard, context); try { String url = agentUrl + String.format("/v1/tasks/%1s/pushNotificationConfigs/%2s", request.id(), request.pushNotificationConfigId()); - A2AHttpClient_v0_3.DeleteBuilder deleteBuilder = httpClient.createDelete().url(url); + A2AHttpClient.DeleteBuilder deleteBuilder = httpClient.createDelete().url(url); if (payloadAndHeaders.getHeaders() != null) { for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { deleteBuilder.addHeader(entry.getKey(), entry.getValue()); } } - A2AHttpResponse_v0_3 response = deleteBuilder.delete(); + A2AHttpResponse response = deleteBuilder.delete(); if (!response.success()) { throw RestErrorMapper_v0_3.mapRestError(response); } @@ -301,9 +302,9 @@ public void resubscribe(TaskIdParams_v0_3 request, Consumer sseEventListener.onMessage(msg, ref.get()), + event -> sseEventListener.onMessage(event.data(), ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), () -> { // We don't need to do anything special on completion @@ -332,13 +333,13 @@ public AgentCard_v0_3 getAgentCard(@Nullable ClientCallContext_v0_3 context) thr PayloadAndHeaders_v0_3 payloadAndHeaders = applyInterceptors(GetAuthenticatedExtendedCardRequest_v0_3.METHOD, null, agentCard, context); String url = agentUrl + String.format("/v1/card"); - A2AHttpClient_v0_3.GetBuilder getBuilder = httpClient.createGet().url(url); + A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); if (payloadAndHeaders.getHeaders() != null) { for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { getBuilder.addHeader(entry.getKey(), entry.getValue()); } } - A2AHttpResponse_v0_3 response = getBuilder.get(); + A2AHttpResponse response = getBuilder.get(); if (!response.success()) { throw RestErrorMapper_v0_3.mapRestError(response); } @@ -371,8 +372,8 @@ private PayloadAndHeaders_v0_3 applyInterceptors(String methodName, @Nullable Me } private String sendPostRequest(String url, PayloadAndHeaders_v0_3 payloadAndHeaders) throws IOException, InterruptedException, JsonProcessingException_v0_3 { - A2AHttpClient_v0_3.PostBuilder builder = createPostBuilder(url, payloadAndHeaders); - A2AHttpResponse_v0_3 response = builder.post(); + A2AHttpClient.PostBuilder builder = createPostBuilder(url, payloadAndHeaders); + A2AHttpResponse response = builder.post(); if (!response.success()) { log.fine("Error on POST processing " + JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); throw RestErrorMapper_v0_3.mapRestError(response); @@ -380,9 +381,9 @@ private String sendPostRequest(String url, PayloadAndHeaders_v0_3 payloadAndHead return response.body(); } - private A2AHttpClient_v0_3.PostBuilder createPostBuilder(String url, PayloadAndHeaders_v0_3 payloadAndHeaders) throws JsonProcessingException_v0_3, InvalidProtocolBufferException { + private A2AHttpClient.PostBuilder createPostBuilder(String url, PayloadAndHeaders_v0_3 payloadAndHeaders) throws JsonProcessingException_v0_3, InvalidProtocolBufferException { log.fine(JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); - A2AHttpClient_v0_3.PostBuilder postBuilder = httpClient.createPost() + A2AHttpClient.PostBuilder postBuilder = httpClient.createPost() .url(url) .addHeader("Content-Type", "application/json") .body(JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); diff --git a/compat-0.3/client/transport/spi/pom.xml b/compat-0.3/client/transport/spi/pom.xml index b8e8d1730..d4b7c9bb3 100644 --- a/compat-0.3/client/transport/spi/pom.xml +++ b/compat-0.3/client/transport/spi/pom.xml @@ -17,6 +17,10 @@ Java SDK for the Agent2Agent Protocol (A2A) - Client Transport SPI + + ${project.groupId} + a2a-java-sdk-http-client + ${project.groupId} a2a-java-sdk-compat-0.3-spec diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java similarity index 83% rename from compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java rename to compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java index af554f978..2d91eb195 100644 --- a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java @@ -5,6 +5,9 @@ import java.net.URISyntaxException; import java.util.Map; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpClientFactory; +import org.a2aproject.sdk.client.http.A2AHttpResponse; import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; @@ -13,7 +16,7 @@ import org.jspecify.annotations.Nullable; public class A2ACardResolver_v0_3 { - private final A2AHttpClient_v0_3 httpClient; + private final A2AHttpClient httpClient; private final String url; private final @Nullable Map authHeaders; @@ -21,13 +24,13 @@ public class A2ACardResolver_v0_3 { /** * Get the agent card for an A2A agent. - * The {@code JdkA2AHttpClient} will be used to fetch the agent card. + * The HTTP client will be auto-selected via {@link A2AHttpClientFactory}. * * @param baseUrl the base URL for the agent whose agent card we want to retrieve * @throws A2AClientError_v0_3 if the URL for the agent is invalid */ public A2ACardResolver_v0_3(String baseUrl) throws A2AClientError_v0_3 { - this(new JdkA2AHttpClient_v0_3(), baseUrl, null, null); + this(A2AHttpClientFactory.create(), baseUrl, null, null); } /** @@ -37,7 +40,7 @@ public A2ACardResolver_v0_3(String baseUrl) throws A2AClientError_v0_3 { * @param baseUrl the base URL for the agent whose agent card we want to retrieve * @throws A2AClientError_v0_3 if the URL for the agent is invalid */ - public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl) throws A2AClientError_v0_3 { + public A2ACardResolver_v0_3(A2AHttpClient httpClient, String baseUrl) throws A2AClientError_v0_3 { this(httpClient, baseUrl, null, null); } @@ -48,7 +51,7 @@ public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl) throw * agent URL, defaults to ".well-known/agent-card.json" * @throws A2AClientError_v0_3 if the URL for the agent is invalid */ - public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl, String agentCardPath) throws A2AClientError_v0_3 { + public A2ACardResolver_v0_3(A2AHttpClient httpClient, String baseUrl, String agentCardPath) throws A2AClientError_v0_3 { this(httpClient, baseUrl, agentCardPath, null); } @@ -60,7 +63,7 @@ public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl, Strin * @param authHeaders the HTTP authentication headers to use. May be {@code null} * @throws A2AClientError_v0_3 if the URL for the agent is invalid */ - public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl, @Nullable String agentCardPath, + public A2ACardResolver_v0_3(A2AHttpClient httpClient, String baseUrl, @Nullable String agentCardPath, @Nullable Map authHeaders) throws A2AClientError_v0_3 { this.httpClient = httpClient; String effectiveAgentCardPath = agentCardPath == null || agentCardPath.isEmpty() ? DEFAULT_AGENT_CARD_PATH : agentCardPath; @@ -80,7 +83,7 @@ public A2ACardResolver_v0_3(A2AHttpClient_v0_3 httpClient, String baseUrl, @Null * @throws A2AClientJSONError_v0_3 If the response body cannot be decoded as JSON or validated against the AgentCard schema */ public AgentCard_v0_3 getAgentCard() throws A2AClientError_v0_3, A2AClientJSONError_v0_3 { - A2AHttpClient_v0_3.GetBuilder builder = httpClient.createGet() + A2AHttpClient.GetBuilder builder = httpClient.createGet() .url(url) .addHeader("Content-Type", "application/json"); @@ -92,7 +95,7 @@ public AgentCard_v0_3 getAgentCard() throws A2AClientError_v0_3, A2AClientJSONEr String body; try { - A2AHttpResponse_v0_3 response = builder.get(); + A2AHttpResponse response = builder.get(); if (!response.success()) { throw new A2AClientError_v0_3("Failed to obtain agent card: " + response.status()); } diff --git a/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java similarity index 91% rename from compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java rename to compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java index f632d3e22..658b0f49d 100644 --- a/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java +++ b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java @@ -5,14 +5,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; +import org.a2aproject.sdk.client.http.A2AHttpClient; +import org.a2aproject.sdk.client.http.A2AHttpResponse; +import org.a2aproject.sdk.client.http.ServerSentEvent; import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientJSONError_v0_3; import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; -import java.util.Map; import org.junit.jupiter.api.Test; public class A2ACardResolver_v0_3_Test { @@ -109,7 +112,7 @@ public void testGetAgentCardRequestError() throws Exception { assertTrue(msg.contains("503")); } - private static class TestHttpClient implements A2AHttpClient_v0_3 { + private static class TestHttpClient implements A2AHttpClient { int status = 200; String body; String url; @@ -129,11 +132,11 @@ public DeleteBuilder createDelete() { return null; } - class TestGetBuilder implements A2AHttpClient_v0_3.GetBuilder { + class TestGetBuilder implements A2AHttpClient.GetBuilder { @Override - public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { - return new A2AHttpResponse_v0_3() { + public A2AHttpResponse get() throws IOException, InterruptedException { + return new A2AHttpResponse() { @Override public int status() { return status; @@ -152,7 +155,7 @@ public String body() { } @Override - public CompletableFuture getAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { + public CompletableFuture getAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { return null; } diff --git a/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java similarity index 99% rename from compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java rename to compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java index 751dadf6c..54ea3f41e 100644 --- a/compat-0.3/http-client/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java +++ b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java @@ -161,4 +161,4 @@ public class JsonMessages_v0_3 { }"""; -} \ No newline at end of file +} diff --git a/compat-0.3/http-client/pom.xml b/compat-0.3/http-client/pom.xml deleted file mode 100644 index 61fb8bd3a..000000000 --- a/compat-0.3/http-client/pom.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - 4.0.0 - - - org.a2aproject.sdk - a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT - .. - - a2a-java-sdk-compat-0.3-http-client - - jar - - Java SDK A2A Compat 0.3 HTTP Client - Java SDK for the Agent2Agent Protocol (A2A) - HTTP Client (0.3 compat) - - - - ${project.groupId} - a2a-java-sdk-compat-0.3-spec - - - - org.junit.jupiter - junit-jupiter-api - test - - - - org.mock-server - mockserver-netty - test - - - - diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpClient_v0_3.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpClient_v0_3.java deleted file mode 100644 index 2387e725e..000000000 --- a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpClient_v0_3.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.a2aproject.sdk.compat03.client.http; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - -public interface A2AHttpClient_v0_3 { - - GetBuilder createGet(); - - PostBuilder createPost(); - - DeleteBuilder createDelete(); - - interface Builder> { - T url(String s); - T addHeaders(Map headers); - T addHeader(String name, String value); - } - - interface GetBuilder extends Builder { - A2AHttpResponse_v0_3 get() throws IOException, InterruptedException; - CompletableFuture getAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException; - } - - interface PostBuilder extends Builder { - PostBuilder body(String body); - A2AHttpResponse_v0_3 post() throws IOException, InterruptedException; - CompletableFuture postAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException; - } - - interface DeleteBuilder extends Builder { - A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException; - } -} diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpResponse_v0_3.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpResponse_v0_3.java deleted file mode 100644 index fe082648d..000000000 --- a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/A2AHttpResponse_v0_3.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.a2aproject.sdk.compat03.client.http; - -public interface A2AHttpResponse_v0_3 { - int status(); - - boolean success(); - - String body(); -} diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java deleted file mode 100644 index 2d1838b86..000000000 --- a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/JdkA2AHttpClient_v0_3.java +++ /dev/null @@ -1,330 +0,0 @@ -package org.a2aproject.sdk.compat03.client.http; - -import static java.net.HttpURLConnection.HTTP_FORBIDDEN; -import static java.net.HttpURLConnection.HTTP_MULT_CHOICE; -import static java.net.HttpURLConnection.HTTP_OK; -import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; - -import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.net.http.HttpResponse.BodyHandler; -import java.net.http.HttpResponse.BodyHandlers; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Flow; -import java.util.function.Consumer; -import org.jspecify.annotations.Nullable; - -import org.a2aproject.sdk.common.A2AErrorMessages; - -public class JdkA2AHttpClient_v0_3 implements A2AHttpClient_v0_3 { - - private final HttpClient httpClient; - - public JdkA2AHttpClient_v0_3() { - httpClient = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .followRedirects(HttpClient.Redirect.NORMAL) - .build(); - } - - @Override - public GetBuilder createGet() { - return new JdkGetBuilder(); - } - - @Override - public PostBuilder createPost() { - return new JdkPostBuilder(); - } - - @Override - public DeleteBuilder createDelete() { - return new JdkDeleteBuilder(); - } - - private abstract class JdkBuilder> implements Builder { - private String url = ""; - private Map headers = new HashMap<>(); - - @Override - public T url(String url) { - this.url = url; - return self(); - } - - @Override - public T addHeader(String name, String value) { - headers.put(name, value); - return self(); - } - - @Override - public T addHeaders(Map headers) { - if(headers != null && ! headers.isEmpty()) { - for (Map.Entry entry : headers.entrySet()) { - addHeader(entry.getKey(), entry.getValue()); - } - } - return self(); - } - - @SuppressWarnings("unchecked") - T self() { - return (T) this; - } - - protected HttpRequest.Builder createRequestBuilder() throws IOException { - HttpRequest.Builder builder = HttpRequest.newBuilder() - .uri(URI.create(url)); - for (Map.Entry headerEntry : headers.entrySet()) { - builder.header(headerEntry.getKey(), headerEntry.getValue()); - } - return builder; - } - - protected CompletableFuture asyncRequest( - HttpRequest request, - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable - ) { - Flow.Subscriber subscriber = new Flow.Subscriber() { - private Flow.@Nullable Subscription subscription; - private volatile boolean errorRaised = false; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - this.subscription.request(1); - } - - @Override - public void onNext(String item) { - // SSE messages sometimes start with "data:". Strip that off - if (item != null && item.startsWith("data:")) { - item = item.substring(5).trim(); - if (!item.isEmpty()) { - messageConsumer.accept(item); - } - } - if (subscription != null) { - subscription.request(1); - } - } - - @Override - public void onError(Throwable throwable) { - if (!errorRaised) { - errorRaised = true; - errorConsumer.accept(throwable); - } - if (subscription != null) { - subscription.cancel(); - } - } - - @Override - public void onComplete() { - if (!errorRaised) { - completeRunnable.run(); - } - if (subscription != null) { - subscription.cancel(); - } - } - }; - - // Create a custom body handler that checks status before processing body - BodyHandler bodyHandler = responseInfo -> { - // Check for authentication/authorization errors only - if (responseInfo.statusCode() == HTTP_UNAUTHORIZED || responseInfo.statusCode() == HTTP_FORBIDDEN) { - final String errorMessage; - if (responseInfo.statusCode() == HTTP_UNAUTHORIZED) { - errorMessage = A2AErrorMessages.AUTHENTICATION_FAILED; - } else { - errorMessage = A2AErrorMessages.AUTHORIZATION_FAILED; - } - // Return a body subscriber that immediately signals error - return BodySubscribers.fromSubscriber(new Flow.Subscriber>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscriber.onError(new IOException(errorMessage)); - } - - @Override - public void onNext(List item) { - // Should not be called - } - - @Override - public void onError(Throwable throwable) { - // Should not be called - } - - @Override - public void onComplete() { - // Should not be called - } - }); - } else { - // For all other status codes (including other errors), proceed with normal line subscriber - return BodyHandlers.fromLineSubscriber(subscriber).apply(responseInfo); - } - }; - - // Send the response async, and let the subscriber handle the lines. - return httpClient.sendAsync(request, bodyHandler) - .thenAccept(response -> { - // Handle non-authentication/non-authorization errors here - if (!isSuccessStatus(response.statusCode()) && - response.statusCode() != HTTP_UNAUTHORIZED && - response.statusCode() != HTTP_FORBIDDEN) { - subscriber.onError(new IOException("Request failed with status " + response.statusCode() + ":" + response.body())); - } - }) - .exceptionally(throwable -> { - // Handle network errors (timeouts, connection failures, etc.) - subscriber.onError(throwable); - return null; - }); - } - } - - private class JdkGetBuilder extends JdkBuilder implements A2AHttpClient_v0_3.GetBuilder { - - private HttpRequest.Builder createRequestBuilder(boolean SSE) throws IOException { - HttpRequest.Builder builder = super.createRequestBuilder().GET(); - if (SSE) { - builder.header("Accept", "text/event-stream"); - } - return builder; - } - - @Override - public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { - HttpRequest request = createRequestBuilder(false) - .build(); - HttpResponse response = - httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); - - if (response.statusCode() == HTTP_UNAUTHORIZED) { - throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); - } else if (response.statusCode() == HTTP_FORBIDDEN) { - throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); - } - - return new JdkHttpResponse(response); - } - - @Override - public CompletableFuture getAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException { - HttpRequest request = createRequestBuilder(true) - .build(); - return super.asyncRequest(request, messageConsumer, errorConsumer, completeRunnable); - } - - } - - private class JdkDeleteBuilder extends JdkBuilder implements A2AHttpClient_v0_3.DeleteBuilder { - - @Override - public A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException { - HttpRequest request = super.createRequestBuilder().DELETE().build(); - HttpResponse response = - httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); - - if (response.statusCode() == HTTP_UNAUTHORIZED) { - throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); - } else if (response.statusCode() == HTTP_FORBIDDEN) { - throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); - } - - return new JdkHttpResponse(response); - } - - } - - private class JdkPostBuilder extends JdkBuilder implements A2AHttpClient_v0_3.PostBuilder { - String body = ""; - - @Override - public PostBuilder body(String body) { - this.body = body; - return self(); - } - - private HttpRequest.Builder createRequestBuilder(boolean SSE) throws IOException { - HttpRequest.Builder builder = super.createRequestBuilder() - .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)); - if (SSE) { - builder.header("Accept", "text/event-stream"); - } - return builder; - } - - @Override - public A2AHttpResponse_v0_3 post() throws IOException, InterruptedException { - HttpRequest request = createRequestBuilder(false) - .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)) - .build(); - HttpResponse response = - httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); - - if (response.statusCode() == HTTP_UNAUTHORIZED) { - throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); - } else if (response.statusCode() == HTTP_FORBIDDEN) { - throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); - } - - return new JdkHttpResponse(response); - } - - @Override - public CompletableFuture postAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException { - HttpRequest request = createRequestBuilder(true) - .build(); - return super.asyncRequest(request, messageConsumer, errorConsumer, completeRunnable); - } - } - - private record JdkHttpResponse(HttpResponse response) implements A2AHttpResponse_v0_3 { - - @Override - public int status() { - return response.statusCode(); - } - - @Override - public boolean success() {// Send the request and get the response - return success(response); - } - - static boolean success(HttpResponse response) { - return response.statusCode() >= HTTP_OK && response.statusCode() < HTTP_MULT_CHOICE; - } - - @Override - public String body() { - return response.body(); - } - } - - private static boolean isSuccessStatus(int statusCode) { - return statusCode >= HTTP_OK && statusCode < HTTP_MULT_CHOICE; - } -} diff --git a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/package-info.java b/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/package-info.java deleted file mode 100644 index 035bf5a62..000000000 --- a/compat-0.3/http-client/src/main/java/org/a2aproject/sdk/compat03/client/http/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package org.a2aproject.sdk.compat03.client.http; - -import org.jspecify.annotations.NullMarked; - diff --git a/compat-0.3/pom.xml b/compat-0.3/pom.xml index 9e7af13ae..e3c90533c 100644 --- a/compat-0.3/pom.xml +++ b/compat-0.3/pom.xml @@ -29,11 +29,6 @@ a2a-java-sdk-compat-0.3-spec-grpc ${project.version} - - ${project.groupId} - a2a-java-sdk-compat-0.3-http-client - ${project.version} - ${project.groupId} a2a-java-sdk-compat-0.3-client @@ -118,9 +113,6 @@ spec spec-grpc - - http-client - server-conversion diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_AndroidTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_AndroidTest.java index aac980bc8..86ddaa549 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_AndroidTest.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_AndroidTest.java @@ -1,9 +1,9 @@ package org.a2aproject.sdk.compat03.server.apps.quarkus; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; -import org.a2aproject.sdk.compat03.conversion.AndroidA2AHttpClient_v0_3; import io.quarkus.test.junit.QuarkusTest; @QuarkusTest @@ -12,6 +12,6 @@ public class QuarkusA2AJSONRPC_v0_3_AndroidTest extends QuarkusA2AJSONRPC_v0_3_T @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, - new JSONRPCTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient_v0_3())); + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient())); } } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_JdkTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_JdkTest.java index 831e73dea..6c096b069 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_JdkTest.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_JdkTest.java @@ -1,7 +1,7 @@ package org.a2aproject.sdk.compat03.server.apps.quarkus; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; import io.quarkus.test.junit.QuarkusTest; @@ -12,6 +12,6 @@ public class QuarkusA2AJSONRPC_v0_3_JdkTest extends QuarkusA2AJSONRPC_v0_3_Test @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, - new JSONRPCTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient_v0_3())); + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient())); } } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_VertxTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_VertxTest.java index bd7d2f5a4..beda8276a 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_VertxTest.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_VertxTest.java @@ -1,9 +1,9 @@ package org.a2aproject.sdk.compat03.server.apps.quarkus; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; -import org.a2aproject.sdk.compat03.conversion.VertxA2AHttpClient_v0_3; import io.quarkus.test.junit.QuarkusTest; import io.vertx.core.Vertx; import jakarta.inject.Inject; @@ -17,6 +17,6 @@ public class QuarkusA2AJSONRPC_v0_3_VertxTest extends QuarkusA2AJSONRPC_v0_3_Tes @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, - new JSONRPCTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient_v0_3(vertx))); + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient(vertx))); } } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest.java index 45e8fbeee..5085bb276 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthAndroidTest.java @@ -1,11 +1,11 @@ package org.a2aproject.sdk.compat03.server.apps.quarkus; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; -import org.a2aproject.sdk.compat03.conversion.AndroidA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; import io.quarkus.test.junit.QuarkusTest; @@ -37,13 +37,13 @@ protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3() - .httpClient(new AndroidA2AHttpClient_v0_3()) + .httpClient(new AndroidA2AHttpClient()) .addInterceptor(authInterceptor)); } @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, - new JSONRPCTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient_v0_3())); + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient())); } } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java index e158c28c2..2122bfff8 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthTest.java @@ -1,7 +1,7 @@ package org.a2aproject.sdk.compat03.server.apps.quarkus; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; @@ -37,13 +37,13 @@ protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3() - .httpClient(new JdkA2AHttpClient_v0_3()) + .httpClient(new JdkA2AHttpClient()) .addInterceptor(authInterceptor)); } @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, - new JSONRPCTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient_v0_3())); + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient())); } } diff --git a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest.java b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest.java index ba37d6b9b..d836c6fe2 100644 --- a/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest.java +++ b/compat-0.3/reference/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/server/apps/quarkus/QuarkusA2AJSONRPC_v0_3_WithAuthVertxTest.java @@ -1,12 +1,12 @@ package org.a2aproject.sdk.compat03.server.apps.quarkus; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; -import org.a2aproject.sdk.compat03.conversion.VertxA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; @@ -42,13 +42,13 @@ protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3() - .httpClient(new VertxA2AHttpClient_v0_3(vertx)) + .httpClient(new VertxA2AHttpClient(vertx)) .addInterceptor(authInterceptor)); } @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, - new JSONRPCTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient_v0_3(vertx))); + new JSONRPCTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient(vertx))); } } diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_AndroidTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_AndroidTest.java index 6d1f5cfdd..4b70e86ca 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_AndroidTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_AndroidTest.java @@ -1,9 +1,9 @@ package org.a2aproject.sdk.compat03.server.rest.quarkus; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; -import org.a2aproject.sdk.compat03.conversion.AndroidA2AHttpClient_v0_3; import io.quarkus.test.junit.QuarkusTest; @QuarkusTest @@ -12,6 +12,6 @@ public class QuarkusA2ARest_v0_3_AndroidTest extends QuarkusA2ARest_v0_3_Test { @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, - new RestTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient_v0_3())); + new RestTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient())); } } diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_JdkTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_JdkTest.java index 8ec2191ba..fc6c578a2 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_JdkTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_JdkTest.java @@ -1,7 +1,7 @@ package org.a2aproject.sdk.compat03.server.rest.quarkus; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; import io.quarkus.test.junit.QuarkusTest; @@ -12,6 +12,6 @@ public class QuarkusA2ARest_v0_3_JdkTest extends QuarkusA2ARest_v0_3_Test { @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, - new RestTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient_v0_3())); + new RestTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient())); } } diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_VertxTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_VertxTest.java index 410c80feb..599738c3b 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_VertxTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_VertxTest.java @@ -1,9 +1,9 @@ package org.a2aproject.sdk.compat03.server.rest.quarkus; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; -import org.a2aproject.sdk.compat03.conversion.VertxA2AHttpClient_v0_3; import io.quarkus.test.junit.QuarkusTest; import io.vertx.core.Vertx; import jakarta.inject.Inject; @@ -17,6 +17,6 @@ public class QuarkusA2ARest_v0_3_VertxTest extends QuarkusA2ARest_v0_3_Test { @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, - new RestTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient_v0_3(vertx))); + new RestTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient(vertx))); } } diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java index b17ec5e57..6a339e7c4 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java @@ -1,11 +1,11 @@ package org.a2aproject.sdk.compat03.server.rest.quarkus; +import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; -import org.a2aproject.sdk.compat03.conversion.AndroidA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; import io.quarkus.test.junit.QuarkusTest; @@ -38,14 +38,14 @@ protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3() - .httpClient(new AndroidA2AHttpClient_v0_3()) + .httpClient(new AndroidA2AHttpClient()) .addInterceptor(authInterceptor)); } @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, - new RestTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient_v0_3())); + new RestTransportConfigBuilder_v0_3().httpClient(new AndroidA2AHttpClient())); } @Test diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java index 984850d2b..5ab5f5b75 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java @@ -1,7 +1,7 @@ package org.a2aproject.sdk.compat03.server.rest.quarkus; +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; -import org.a2aproject.sdk.compat03.client.http.JdkA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; @@ -38,14 +38,14 @@ protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3() - .httpClient(new JdkA2AHttpClient_v0_3()) + .httpClient(new JdkA2AHttpClient()) .addInterceptor(authInterceptor)); } @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, - new RestTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient_v0_3())); + new RestTransportConfigBuilder_v0_3().httpClient(new JdkA2AHttpClient())); } @Test diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java index 087b30535..f5d4e1c58 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java @@ -1,12 +1,12 @@ package org.a2aproject.sdk.compat03.server.rest.quarkus; +import org.a2aproject.sdk.client.http.VertxA2AHttpClient; import org.a2aproject.sdk.compat03.client.ClientBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransport_v0_3; import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; import org.a2aproject.sdk.compat03.conversion.AuthTestProfile_v0_3; -import org.a2aproject.sdk.compat03.conversion.VertxA2AHttpClient_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; @@ -43,14 +43,14 @@ protected void configureTransportWithAuth(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3() - .httpClient(new VertxA2AHttpClient_v0_3(vertx)) + .httpClient(new VertxA2AHttpClient(vertx)) .addInterceptor(authInterceptor)); } @Override protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, - new RestTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient_v0_3(vertx))); + new RestTransportConfigBuilder_v0_3().httpClient(new VertxA2AHttpClient(vertx))); } @Test diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AndroidA2AHttpClient_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AndroidA2AHttpClient_v0_3.java deleted file mode 100644 index 778d42fd7..000000000 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AndroidA2AHttpClient_v0_3.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.a2aproject.sdk.compat03.conversion; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - -import org.a2aproject.sdk.client.http.A2AHttpClient; -import org.a2aproject.sdk.client.http.AndroidA2AHttpClient; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; - -/** - * Adapts {@link AndroidA2AHttpClient} to the {@link A2AHttpClient_v0_3} interface, - * bridging the v0.3 SSE callback ({@code Consumer}) to the v1.0 SSE callback - * ({@code Consumer}) by extracting the event data payload. - */ -public class AndroidA2AHttpClient_v0_3 implements A2AHttpClient_v0_3 { - - private final AndroidA2AHttpClient delegate = new AndroidA2AHttpClient(); - - @Override - public GetBuilder createGet() { - return new GetBuilderAdapter(delegate.createGet()); - } - - @Override - public PostBuilder createPost() { - return new PostBuilderAdapter(delegate.createPost()); - } - - @Override - public DeleteBuilder createDelete() { - return new DeleteBuilderAdapter(delegate.createDelete()); - } - - private static A2AHttpResponse_v0_3 adapt(org.a2aproject.sdk.client.http.A2AHttpResponse r) { - return new A2AHttpResponse_v0_3() { - @Override public int status() { return r.status(); } - @Override public boolean success() { return r.success(); } - @Override public String body() { return r.body(); } - }; - } - - private static class GetBuilderAdapter implements GetBuilder { - private final A2AHttpClient.GetBuilder delegate; - - GetBuilderAdapter(A2AHttpClient.GetBuilder delegate) { - this.delegate = delegate; - } - - @Override public GetBuilder url(String s) { delegate.url(s); return this; } - @Override public GetBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } - @Override public GetBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } - - @Override - public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { - return adapt(delegate.get()); - } - - @Override - public CompletableFuture getAsyncSSE(Consumer mc, Consumer ec, Runnable cr) - throws IOException, InterruptedException { - return delegate.getAsyncSSE(event -> mc.accept(event.data()), ec, cr); - } - } - - private static class PostBuilderAdapter implements PostBuilder { - private final A2AHttpClient.PostBuilder delegate; - - PostBuilderAdapter(A2AHttpClient.PostBuilder delegate) { - this.delegate = delegate; - } - - @Override public PostBuilder url(String s) { delegate.url(s); return this; } - @Override public PostBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } - @Override public PostBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } - @Override public PostBuilder body(String body) { delegate.body(body); return this; } - - @Override - public A2AHttpResponse_v0_3 post() throws IOException, InterruptedException { - return adapt(delegate.post()); - } - - @Override - public CompletableFuture postAsyncSSE(Consumer mc, Consumer ec, Runnable cr) - throws IOException, InterruptedException { - return delegate.postAsyncSSE(event -> mc.accept(event.data()), ec, cr); - } - } - - private static class DeleteBuilderAdapter implements DeleteBuilder { - private final A2AHttpClient.DeleteBuilder delegate; - - DeleteBuilderAdapter(A2AHttpClient.DeleteBuilder delegate) { - this.delegate = delegate; - } - - @Override public DeleteBuilder url(String s) { delegate.url(s); return this; } - @Override public DeleteBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } - @Override public DeleteBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } - - @Override - public A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException { - return adapt(delegate.delete()); - } - } -} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/VertxA2AHttpClient_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/VertxA2AHttpClient_v0_3.java deleted file mode 100644 index 24fac7060..000000000 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/VertxA2AHttpClient_v0_3.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.a2aproject.sdk.compat03.conversion; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - -import org.a2aproject.sdk.client.http.A2AHttpClient; -import org.a2aproject.sdk.client.http.VertxA2AHttpClient; -import org.a2aproject.sdk.compat03.client.http.A2AHttpClient_v0_3; -import org.a2aproject.sdk.compat03.client.http.A2AHttpResponse_v0_3; -import io.vertx.core.Vertx; - -/** - * Adapts {@link VertxA2AHttpClient} to the {@link A2AHttpClient_v0_3} interface, - * bridging the v0.3 SSE callback ({@code Consumer}) to the v1.0 SSE callback - * ({@code Consumer}) by extracting the event data payload. - */ -public class VertxA2AHttpClient_v0_3 implements A2AHttpClient_v0_3 { - - private final VertxA2AHttpClient delegate; - - public VertxA2AHttpClient_v0_3(Vertx vertx) { - this.delegate = new VertxA2AHttpClient(vertx); - } - - @Override - public GetBuilder createGet() { - return new GetBuilderAdapter(delegate.createGet()); - } - - @Override - public PostBuilder createPost() { - return new PostBuilderAdapter(delegate.createPost()); - } - - @Override - public DeleteBuilder createDelete() { - return new DeleteBuilderAdapter(delegate.createDelete()); - } - - private static A2AHttpResponse_v0_3 adapt(org.a2aproject.sdk.client.http.A2AHttpResponse r) { - return new A2AHttpResponse_v0_3() { - @Override public int status() { return r.status(); } - @Override public boolean success() { return r.success(); } - @Override public String body() { return r.body(); } - }; - } - - private static class GetBuilderAdapter implements GetBuilder { - private final A2AHttpClient.GetBuilder delegate; - - GetBuilderAdapter(A2AHttpClient.GetBuilder delegate) { - this.delegate = delegate; - } - - @Override public GetBuilder url(String s) { delegate.url(s); return this; } - @Override public GetBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } - @Override public GetBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } - - @Override - public A2AHttpResponse_v0_3 get() throws IOException, InterruptedException { - return adapt(delegate.get()); - } - - @Override - public CompletableFuture getAsyncSSE(Consumer mc, Consumer ec, Runnable cr) - throws IOException, InterruptedException { - return delegate.getAsyncSSE(event -> mc.accept(event.data()), ec, cr); - } - } - - private static class PostBuilderAdapter implements PostBuilder { - private final A2AHttpClient.PostBuilder delegate; - - PostBuilderAdapter(A2AHttpClient.PostBuilder delegate) { - this.delegate = delegate; - } - - @Override public PostBuilder url(String s) { delegate.url(s); return this; } - @Override public PostBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } - @Override public PostBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } - @Override public PostBuilder body(String body) { delegate.body(body); return this; } - - @Override - public A2AHttpResponse_v0_3 post() throws IOException, InterruptedException { - return adapt(delegate.post()); - } - - @Override - public CompletableFuture postAsyncSSE(Consumer mc, Consumer ec, Runnable cr) - throws IOException, InterruptedException { - return delegate.postAsyncSSE(event -> mc.accept(event.data()), ec, cr); - } - } - - private static class DeleteBuilderAdapter implements DeleteBuilder { - private final A2AHttpClient.DeleteBuilder delegate; - - DeleteBuilderAdapter(A2AHttpClient.DeleteBuilder delegate) { - this.delegate = delegate; - } - - @Override public DeleteBuilder url(String s) { delegate.url(s); return this; } - @Override public DeleteBuilder addHeader(String n, String v) { delegate.addHeader(n, v); return this; } - @Override public DeleteBuilder addHeaders(Map h) { delegate.addHeaders(h); return this; } - - @Override - public A2AHttpResponse_v0_3 delete() throws IOException, InterruptedException { - return adapt(delegate.delete()); - } - } -} From 9ec5f92c13128eac5945091cb429a8d3c78f2d09 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 13 May 2026 14:18:10 +0200 Subject: [PATCH 158/192] feat: add url and preferredTransport fields to AgentCard for v0.3 compatibility Signed-off-by: Emmanuel Hugonnet --- .../http/A2ACardResolver_v0_3_Test.java | 33 ++++++++++++ .../client/http/JsonMessages_v0_3.java | 50 +++++++++++++++++++ .../sdk/client/http/A2ACardResolver.java | 2 +- .../sdk/grpc/mapper/AgentCardMapper.java | 2 + .../sdk/grpc/utils/JSONRPCUtils.java | 7 ++- .../org/a2aproject/sdk/spec/AgentCard.java | 50 +++++++++++++------ .../server/apps/common/AgentCardProducer.java | 4 +- 7 files changed, 129 insertions(+), 19 deletions(-) diff --git a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java index 658b0f49d..1b6e2736e 100644 --- a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java +++ b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; @@ -96,6 +97,38 @@ public void testGetAgentCardJsonDecodeError() throws Exception { } + @Test + public void testParseV1AgentCardWithUrlAndPreferredTransport() throws Exception { + TestHttpClient client = new TestHttpClient(); + client.body = JsonMessages_v0_3.V1_AGENT_CARD; + + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(client, "http://example.com/"); + AgentCard_v0_3 card = resolver.getAgentCard(); + + assertEquals("Test Agent", card.name()); + assertEquals("A test agent", card.description()); + assertEquals("1.0.0", card.version()); + assertEquals("https://agent.example.com/a2a", card.url()); + assertEquals("JSONRPC", card.preferredTransport()); + assertTrue(card.capabilities().streaming()); + } + + @Test + public void testParseV1AgentCardDefaultsPreferredTransportWhenAbsent() throws Exception { + TestHttpClient client = new TestHttpClient(); + client.body = JsonMessages_v0_3.V1_AGENT_CARD_NO_PREFERRED_TRANSPORT; + + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(client, "http://example.com/"); + AgentCard_v0_3 card = resolver.getAgentCard(); + + assertEquals("Minimal Agent", card.name()); + assertEquals("https://agent.example.com/a2a", card.url()); + // v0.3 compact constructor defaults null preferredTransport to "JSONRPC" + assertEquals("JSONRPC", card.preferredTransport()); + // v1.0-only fields such as supportedInterfaces are unknown to v0.3 and must be ignored + assertNull(card.additionalInterfaces()); + } + @Test public void testGetAgentCardRequestError() throws Exception { TestHttpClient client = new TestHttpClient(); diff --git a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java index 54ea3f41e..9b9a4ec0c 100644 --- a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java +++ b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/JsonMessages_v0_3.java @@ -83,6 +83,56 @@ public class JsonMessages_v0_3 { ] }"""; + /** + * A v1.0 format agent card returned by a current server. Contains the new {@code supportedInterfaces} + * and {@code securityRequirements} fields (v1.0-only), plus the backward-compat {@code url} and + * {@code preferredTransport} fields that the v0.3 client relies on. + */ + static final String V1_AGENT_CARD = """ + { + "name": "Test Agent", + "description": "A test agent", + "url": "https://agent.example.com/a2a", + "preferredTransport": "JSONRPC", + "version": "1.0.0", + "supportedInterfaces": [ + {"protocolBinding": "JSONRPC", "url": "https://agent.example.com/a2a"}, + {"protocolBinding": "GRPC", "url": "grpc://agent.example.com:9090"} + ], + "capabilities": { + "streaming": true, + "pushNotifications": false, + "stateTransitionHistory": false + }, + "defaultInputModes": ["text/plain"], + "defaultOutputModes": ["text/plain"], + "skills": [], + "securityRequirements": [{"oauth2": ["read"]}] + }"""; + + /** + * A v1.0 format agent card without an explicit {@code preferredTransport}. The v0.3 client must + * fall back to the default transport ("JSONRPC"). + */ + static final String V1_AGENT_CARD_NO_PREFERRED_TRANSPORT = """ + { + "name": "Minimal Agent", + "description": "Minimal agent card", + "url": "https://agent.example.com/a2a", + "version": "2.0.0", + "supportedInterfaces": [ + {"protocolBinding": "JSONRPC", "url": "https://agent.example.com/a2a"} + ], + "capabilities": { + "streaming": false, + "pushNotifications": false, + "stateTransitionHistory": false + }, + "defaultInputModes": ["text/plain"], + "defaultOutputModes": ["text/plain"], + "skills": [] + }"""; + static final String AUTHENTICATION_EXTENDED_AGENT_CARD = """ { "name": "GeoSpatial Route Planner Agent Extended", diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java index d1edf49b8..e8ee10397 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java @@ -184,7 +184,7 @@ public AgentCard getAgentCard() throws A2AClientError, A2AClientJSONError { try { org.a2aproject.sdk.grpc.AgentCard.Builder agentCardBuilder = org.a2aproject.sdk.grpc.AgentCard.newBuilder(); - JSONRPCUtils.parseJsonString(body, agentCardBuilder, ""); + JSONRPCUtils.parseJsonString(body, agentCardBuilder, "", true); return ProtoUtils.FromProto.agentCard(agentCardBuilder); } catch (A2AError | JsonProcessingException e) { throw new A2AClientJSONError("Could not unmarshal agent card response", e); diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java index df9be2b6d..565d6255c 100644 --- a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java @@ -30,5 +30,7 @@ public interface AgentCardMapper { @Mapping(target = "provider", source = "provider", conditionExpression = "java(proto.hasProvider())") @Mapping(target = "documentationUrl", source = "documentationUrl", conditionExpression = "java(!proto.getDocumentationUrl().isEmpty())") @Mapping(target = "iconUrl", source = "iconUrl", conditionExpression = "java(!proto.getIconUrl().isEmpty())") + @Mapping(target = "url", ignore = true) + @Mapping(target = "preferredTransport", ignore = true) org.a2aproject.sdk.spec.AgentCard fromProto(org.a2aproject.sdk.grpc.AgentCard proto); } diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java index 966c998cc..7af14fa5c 100644 --- a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java @@ -439,8 +439,13 @@ protected static void parseRequestBody(JsonElement jsonRpc, com.google.protobuf. } public static void parseJsonString(String body, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException { + parseJsonString(body, builder, id, false); + } + + public static void parseJsonString(String body, com.google.protobuf.Message.Builder builder, Object id, boolean ignoringUnknownFields) throws JsonProcessingException { try { - JsonFormat.parser().merge(body, builder); + JsonFormat.Parser parser = ignoringUnknownFields ? JsonFormat.parser().ignoringUnknownFields() : JsonFormat.parser(); + parser.merge(body, builder); } catch (InvalidProtocolBufferException e) { log.log(Level.FINE, "Protocol buffer parsing failed for JSON: {0}", body); log.log(Level.FINE, "Proto parsing error details", e); diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java index af9a9ce2b..b3aaa2275 100644 --- a/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java @@ -56,7 +56,9 @@ public record AgentCard( @Nullable List securityRequirements, @Nullable String iconUrl, List supportedInterfaces, - @Nullable List signatures) { + @Nullable List signatures, + @Nullable String url, + @Nullable String preferredTransport) { /** * Compact constructor that validates required fields. @@ -156,6 +158,8 @@ public static class Builder { private @Nullable String iconUrl; private @Nullable List supportedInterfaces; private @Nullable List signatures; + private @Nullable String url; + private @Nullable String preferredTransport; /** * Creates a new Builder with all fields unset. @@ -172,20 +176,22 @@ private Builder() { * @param card the AgentCard to copy values from */ private Builder(AgentCard card) { - this.name = card.name; - this.description = card.description; - this.provider = card.provider; - this.version = card.version; - this.documentationUrl = card.documentationUrl; - this.capabilities = card.capabilities; - this.defaultInputModes = card.defaultInputModes != null ? new ArrayList<>(card.defaultInputModes) : Collections.emptyList(); - this.defaultOutputModes = card.defaultOutputModes != null ? new ArrayList<>(card.defaultOutputModes) : Collections.emptyList(); - this.skills = card.skills != null ? new ArrayList<>(card.skills) : Collections.emptyList(); - this.securitySchemes = card.securitySchemes != null ? Map.copyOf(card.securitySchemes) : Collections.emptyMap(); - this.securityRequirements = card.securityRequirements != null ? new ArrayList<>(card.securityRequirements) : Collections.emptyList(); - this.iconUrl = card.iconUrl; - this.supportedInterfaces = card.supportedInterfaces != null ? new ArrayList<>(card.supportedInterfaces) : Collections.emptyList(); - this.signatures = card.signatures != null ? new ArrayList<>(card.signatures) : null; + this.name = card.name(); + this.description = card.description(); + this.provider = card.provider(); + this.version = card.version(); + this.documentationUrl = card.documentationUrl(); + this.capabilities = card.capabilities(); + this.defaultInputModes = card.defaultInputModes() != null ? new ArrayList<>(card.defaultInputModes()) : Collections.emptyList(); + this.defaultOutputModes = card.defaultOutputModes() != null ? new ArrayList<>(card.defaultOutputModes()) : Collections.emptyList(); + this.skills = card.skills() != null ? new ArrayList<>(card.skills()) : Collections.emptyList(); + this.securitySchemes = card.securitySchemes() != null ? Map.copyOf(card.securitySchemes()) : Collections.emptyMap(); + this.securityRequirements = card.securityRequirements() != null ? new ArrayList<>(card.securityRequirements()) : Collections.emptyList(); + this.iconUrl = card.iconUrl(); + this.supportedInterfaces = card.supportedInterfaces() != null ? new ArrayList<>(card.supportedInterfaces()) : Collections.emptyList(); + this.signatures = card.signatures() != null ? new ArrayList<>(card.signatures()) : null; + this.url = card.url(); + this.preferredTransport= card.preferredTransport(); } /** @@ -376,6 +382,16 @@ public Builder signatures(List signatures) { return this; } + public Builder preferredTransport(String preferredTransport) { + this.preferredTransport = preferredTransport; + return this; + } + + public Builder url(String url) { + this.url = url; + return this; + } + /** * Builds an immutable {@link AgentCard} from the current builder state. *

            @@ -399,7 +415,9 @@ public AgentCard build() { securityRequirements, iconUrl, Assert.checkNotNullParam("supportedInterfaces", supportedInterfaces), - signatures); + signatures, + url, + preferredTransport == null ? "JSONRPC" : preferredTransport); } } } diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java index fa90cbfd8..d6d76dcca 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java @@ -58,7 +58,9 @@ public AgentCard agentCard() { .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) .skills(new ArrayList<>()) - .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, transportUrl))); + .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, transportUrl))) + .url(transportUrl) + .preferredTransport(preferredTransport); // Add security configuration if enabled (for authentication tests) if (securityEnabled) { From ed39e5a4006fa9cb3c330ee7cac6e474bcf02e06 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 13 May 2026 16:00:00 +0100 Subject: [PATCH 159/192] chore: Disclaimer about longevity of data stored in JPA (#860) * chore: Disclaimer about longevity of data stored in JPA * Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../README.md | 8 ++++++++ extras/task-store-database-jpa/README.md | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/extras/push-notification-config-store-database-jpa/README.md b/extras/push-notification-config-store-database-jpa/README.md index 6ace61d08..89392ea35 100644 --- a/extras/push-notification-config-store-database-jpa/README.md +++ b/extras/push-notification-config-store-database-jpa/README.md @@ -4,6 +4,14 @@ This module provides a JPA-based implementation of the `PushNotificationConfigSt The persistence is done with the Jakarta Persistence API, so this should be suitable for any JPA 3.0+ provider and Jakarta EE application server. +> **NOTE:** +> +> The `PushNotificationConfig` instances stored in the JPA Database `PushNotificationConfigStore` are simply serialized to JSON before storing in the database, and serialized from JSON when loading from the database. This is done according to the current A2A specification version's format of `PushNotificationConfig`. +> +> Future versions of the specification might use a different format. This is not intended to be a long-term store; its usage is meant to be for the lifetime of the associated `Task` in order to have access to the `PushNotificationConfig` when running in a load-balanced environment. +> +> If you wish to keep the `PushNotificationConfig` instances stored between protocol versions, you might have to implement some migration of the stored data. + ## Quick Start ### 1. Add Dependency diff --git a/extras/task-store-database-jpa/README.md b/extras/task-store-database-jpa/README.md index 42a5865af..d8f02c7e0 100644 --- a/extras/task-store-database-jpa/README.md +++ b/extras/task-store-database-jpa/README.md @@ -4,6 +4,16 @@ This module provides a JPA-based implementation of the `TaskStore` interface tha The persistence is done with the Jakarta Persistence API, so this should be suitable for any JPA 3.0+ provider and Jakarta EE application server. + +> **NOTE:** +> +> The `Task` instances stored in the JPA Database `TaskStore` are simply serialized to JSON before storing in the database, and serialized from JSON when loading from the database. This is done according to the current A2A specification version's format of `Task`. +> +> Future versions of the specification might use a different format. This is not intended to be a long-term store; its usage is meant to be for the lifetime of the `Task` in order to have access to the `Task` when running in a load-balanced environment. +> +> If you wish to keep the `Task` instances stored between protocol versions, you might have to implement some migration of the stored data. + + ## Quick Start ### 1. Add Dependency From ad37e52772230d6d1d5c019c591e31926480ca9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 12:36:22 +0100 Subject: [PATCH 160/192] chore: bump groovy.version from 5.0.5 to 5.0.6 (#867) Bumps `groovy.version` from 5.0.5 to 5.0.6. Updates `org.apache.groovy:groovy` from 5.0.5 to 5.0.6 - [Commits](https://github.com/apache/groovy/commits) Updates `org.apache.groovy:groovy-ant` from 5.0.5 to 5.0.6 - [Commits](https://github.com/apache/groovy/commits) --- updated-dependencies: - dependency-name: org.apache.groovy:groovy dependency-version: 5.0.6 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.groovy:groovy-ant dependency-version: 5.0.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 18f3bea9e..8b048e162 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 3.2.8 4.2.1 0.10.0 - 5.0.5 + 5.0.6 2.14.0 4.1.0 2.0.1 From 87bd30ffd67f0bb0feac9ccc1fe4be0b58ef26c0 Mon Sep 17 00:00:00 2001 From: Yukina Date: Thu, 14 May 2026 19:37:31 +0800 Subject: [PATCH 161/192] fix: guard against JsonNull when parsing response error field (#858) * fix: guard against JsonNull when parsing JSONRPC error field * Refactor error handling in JSONRPCUtils --- .../java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java index 7af14fa5c..2abbe0190 100644 --- a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtils.java @@ -306,8 +306,9 @@ public static A2AResponse parseResponseBody(String body, String method) throw String version = getAndValidateJsonrpc(jsonRpc); Object id = getAndValidateId(jsonRpc); JsonElement paramsNode = jsonRpc.get("result"); - if (jsonRpc.has("error")) { - return parseError(jsonRpc.getAsJsonObject("error"), id, method); + JsonElement errorNode = jsonRpc.get("error"); + if (errorNode != null && !errorNode.isJsonNull()) { + return parseError(errorNode.getAsJsonObject(), id, method); } switch (method) { case GET_TASK_METHOD -> { From 1cc03d3f1762dc060b05bedaa70b3ad500a5d0b2 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 14 May 2026 13:03:59 +0100 Subject: [PATCH 162/192] fix: Fixes for Jakarta (#874) - Don't use TCCL to initialise the Http Client - Default 1.0 gRPC version to 1.0 if not found by interceptor (haven't worked out how to register this in WildFly) --- .../org/a2aproject/sdk/client/http/A2AHttpClientFactory.java | 5 +++-- .../a2aproject/sdk/transport/grpc/handler/GrpcHandler.java | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java index 068a47046..e781a31e5 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2AHttpClientFactory.java @@ -45,7 +45,7 @@ public final class A2AHttpClientFactory { private static final List PROVIDERS; static { - PROVIDERS = StreamSupport.stream(ServiceLoader.load(A2AHttpClientProvider.class).spliterator(), false) + PROVIDERS = StreamSupport.stream(ServiceLoader.load(A2AHttpClientProvider.class, A2AHttpClientProvider.class.getClassLoader()).spliterator(), false) .collect(Collectors.toList()); } @@ -85,7 +85,8 @@ public static A2AHttpClient create(String providerName) { throw new IllegalArgumentException("Provider name must not be null or empty"); } - ServiceLoader loader = ServiceLoader.load(A2AHttpClientProvider.class); + ServiceLoader loader = + ServiceLoader.load(A2AHttpClientProvider.class, A2AHttpClientProvider.class.getClassLoader()); return StreamSupport.stream(loader.spliterator(), false) .filter(provider -> providerName.equals(provider.name())) diff --git a/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java index 90e99e848..306c8655c 100644 --- a/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java +++ b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java @@ -56,6 +56,7 @@ import org.a2aproject.sdk.spec.TaskNotFoundError; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskQueryParams; +import org.a2aproject.sdk.spec.AgentInterface; import org.a2aproject.sdk.spec.TransportProtocol; import org.a2aproject.sdk.spec.A2AErrorCodes; import org.a2aproject.sdk.spec.UnsupportedOperationError; @@ -686,7 +687,11 @@ private ServerCallContext createCallContext(StreamObserver responseObserv } // Extract requested protocol version from gRPC context (set by interceptor) + // Default to current version since gRPC only handles 1.0 protocol String requestedVersion = getVersionFromContext(); + if (requestedVersion == null) { + requestedVersion = AgentInterface.CURRENT_PROTOCOL_VERSION; + } // Extract requested extensions from gRPC context (set by interceptor) Set requestedExtensions = new HashSet<>(); From b272136abb3466d02d1eb4754b44942aa6ef669a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 16:51:35 +0100 Subject: [PATCH 163/192] chore: bump org.codehaus.gmavenplus:gmavenplus-plugin from 4.2.1 to 4.3.1 (#835) chore: bump org.codehaus.gmavenplus:gmavenplus-plugin Bumps [org.codehaus.gmavenplus:gmavenplus-plugin](https://github.com/groovy/GMavenPlus) from 4.2.1 to 4.3.1. - [Release notes](https://github.com/groovy/GMavenPlus/releases) - [Commits](https://github.com/groovy/GMavenPlus/compare/4.2.1...4.3.1) --- updated-dependencies: - dependency-name: org.codehaus.gmavenplus:gmavenplus-plugin dependency-version: 4.3.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8b048e162..5201ccd30 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 3.5.5 3.12.0 3.2.8 - 4.2.1 + 4.3.1 0.10.0 5.0.6 2.14.0 From d941ec1f8db4fba6c75a27dc476d2af9456ba578 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 14 May 2026 16:58:19 +0100 Subject: [PATCH 164/192] feat: enable multi-mode protocol testing for both TCKs (#875) Add CI for 0.3 TCK, and multi-mode testing (v1.0 + v0.3 together) for both TCK servers. - Add Legacy_0_3_AgentInterface and additionalInterfaces to AgentCard so v1.0 cards are parsable by v0.3 clients - Add DerivedAgentCardProducer in compat-0.3/tck to convert v0.3 AgentCard to v1.0 format for multi-mode - Add multiversion dispatcher deps to both TCK multi-mode profiles - Fix global BodyHandler consuming gRPC request bodies by moving to per-route BodyHandler in A2AServerRoutes - Ignore additionalInterfaces in gRPC AgentCardMapper - Add Compat03Fields utility to selectively add v0.3 fields to v1.0 AgentCard producers when running in a multi-version setup - Enable previously @Disabled multiversion agent card tests - Allow Long JSON-RPC request ids Co-authored-by: Claude Opus 4.6 --- .claude/architecture/compatibility_0.3.md | 25 ++-- .github/workflows/run-tck.yml | 111 +++++++++++++++++- README.md | 28 ++++- .../java/org/a2aproject/sdk/util/Assert.java | 6 +- .../compat03/spec/CancelTaskRequest_v0_3.java | 2 +- ...askPushNotificationConfigRequest_v0_3.java | 2 +- ...AuthenticatedExtendedCardRequest_v0_3.java | 2 +- ...askPushNotificationConfigRequest_v0_3.java | 2 +- .../compat03/spec/GetTaskRequest_v0_3.java | 2 +- .../compat03/spec/JSONRPCRequest_v0_3.java | 2 +- .../compat03/spec/JSONRPCResponse_v0_3.java | 2 +- ...askPushNotificationConfigRequest_v0_3.java | 2 +- .../spec/SendMessageRequest_v0_3.java | 4 +- .../SendStreamingMessageRequest_v0_3.java | 4 +- ...askPushNotificationConfigRequest_v0_3.java | 2 +- compat-0.3/tck/pom.xml | 50 ++++++++ .../tck/server/DerivedAgentCardProducer.java | 66 +++++++++++ .../opentelemetry/it/A2ATestRoutes.java | 1 + .../jsonrpc/common/wrappers/A2ARequest.java | 2 +- .../jsonrpc/common/wrappers/A2AResponse.java | 2 +- pom.xml | 10 ++ .../server/apps/quarkus/A2AServerRoutes.java | 5 +- .../server/apps/quarkus/A2ATestRoutes.java | 2 + .../sdk/grpc/mapper/AgentCardMapper.java | 1 + .../org/a2aproject/sdk/spec/AgentCard.java | 13 +- .../a2aproject/sdk/spec/Compat03Fields.java | 35 ++++++ .../sdk/spec/Legacy_0_3_AgentInterface.java | 24 ++++ tck/pom.xml | 53 +++++++++ .../sdk/sut/StubAgentCardProducer_v0_3.java | 43 +++++++ .../multiversion/jsonrpc/A2ATestRoutes.java | 2 + .../MultiVersionJSONRPC_v0_3_Test.java | 8 -- ...MultiVersionJSONRPC_v0_3_WithAuthTest.java | 7 -- .../rest/MultiVersion_v0_3_RestTest.java | 8 -- .../MultiVersion_v0_3_RestWithAuthTest.java | 7 -- .../server/apps/common/AgentCardProducer.java | 10 +- 35 files changed, 474 insertions(+), 71 deletions(-) create mode 100644 compat-0.3/tck/src/multi-mode/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java create mode 100644 spec/src/main/java/org/a2aproject/sdk/spec/Compat03Fields.java create mode 100644 spec/src/main/java/org/a2aproject/sdk/spec/Legacy_0_3_AgentInterface.java create mode 100644 tck/src/multi-mode/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java diff --git a/.claude/architecture/compatibility_0.3.md b/.claude/architecture/compatibility_0.3.md index c4406bca0..7020ecdb2 100644 --- a/.claude/architecture/compatibility_0.3.md +++ b/.claude/architecture/compatibility_0.3.md @@ -32,7 +32,7 @@ The A2A protocol evolved from v0.3 to v1.0 with significant breaking changes. Ex - Changes to existing v1.0 modules (no regressions, no API changes) - Automatic protocol version detection (client must explicitly choose API version) - Extras modules (OpenTelemetry, JPA stores, etc.) for v0.3 -- v0.3 format agent card (v0.3 clients must be able to parse v1.0 agent card format) +- Serving a separate v0.3-format agent card (the v1.0 card is served, with optional v0.3-compatible fields added by the user) --- @@ -149,19 +149,24 @@ v0.3 Client Response `TASK_STATE_REJECTED` (v1.0-only) is mapped to `TASK_STATE_FAILED` when converting to v0.3 wire format. The original state is preserved in metadata (`"original_state": "REJECTED"`) so information is not entirely lost. Both are terminal states, so v0.3 clients can handle the result correctly. -### Agent Card: v1.0 Only +### Agent Card Precedence in Multi-Version Mode -The agent card (`/.well-known/agent-card.json`) is produced only using the v1.0 format. The compat layer does not produce a v0.3-format agent card. +When both v1.0 and v0.3 protocol support are enabled, a single agent card is served at `/.well-known/agent-card.json`: -A server that supports both versions should advertise this via a single v1.0 agent card containing multiple `AgentInterface` entries — one per version — each with its own URL and `protocolVersion` field. v0.3 clients must be able to parse the v1.0 agent card format to discover their endpoint. +- **Both v1.0 and v0.3 enabled**: The v1.0 `AgentCard` takes precedence. The v0.3 `AgentCard_v0_3` is ignored. +- **Only v0.3 enabled**: The v0.3 `AgentCard_v0_3` is used. +- **Only v1.0 enabled**: The v1.0 `AgentCard` is used as-is. -**Pros:** -- **Single source of truth**: one agent card at one well-known URL describes all supported versions and transports -- **Simpler server implementation**: no need for separate v0.3 agent card endpoint, serializer, or CDI producer -- **Forward-looking**: encourages v0.3 clients to understand the v1.0 discovery format +### Making the v1.0 Agent Card Parsable by v0.3 Clients -**Cons:** -- **v0.3 clients must parse v1.0 agent card**: pure v0.3 clients that only understand the v0.3 structure need updating +Existing v0.3 client implementations (across all languages) expect specific fields in the agent card that don't exist in the v1.0 format. Since we cannot control what external v0.3 clients can parse, the v1.0 `AgentCard` must include backward-compatible fields when serving both protocol versions: + +- `url` and `preferredTransport` — top-level fields that v0.3 clients use to discover the primary endpoint +- `additionalInterfaces` — a list of `Legacy_0_3_AgentInterface(transport, url)` entries using v0.3 field names (`transport` instead of v1.0's `protocolBinding`) + +These fields coexist alongside the v1.0 `supportedInterfaces` field. v1.0 clients use `supportedInterfaces`; v0.3 clients use `url`, `preferredTransport`, and `additionalInterfaces`. + +`Legacy_0_3_AgentInterface` is a separate record from `AgentInterface` because they serialize to different JSON field names (`transport`/`url` vs `protocolBinding`/`url`/`tenant`). --- diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index 9c6533ab3..c04eba168 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -12,9 +12,12 @@ on: env: # Tag/branch of the TCK TCK_VERSION: 1.0-dev + TCK_VERSION_0_3: 0.3.0.beta4 # Tells uv to not need a venv, and instead use system UV_SYSTEM_PYTHON: 1 SUT_URL: http://localhost:9999 + # Slow system on CI + TCK_STREAMING_TIMEOUT_0_3: 5.0 # Only run the latest job concurrency: @@ -27,6 +30,7 @@ jobs: strategy: matrix: java-version: [17] + profile: ['', 'multi-mode'] steps: - name: Checkout a2a-java uses: actions/checkout@v6 @@ -54,7 +58,7 @@ jobs: uv pip install -e . working-directory: a2a-tck - name: Start SUT - run: mvn -B quarkus:dev -Dquarkus.console.enabled=false & + run: mvn -B quarkus:dev ${{ matrix.profile && format('-P{0}', matrix.profile) || '' }} -Dquarkus.console.enabled=false & working-directory: tck - name: Wait for SUT to start run: | @@ -97,7 +101,7 @@ jobs: # Extract everything after the first ═══ separator line SUMMARY=$(sed -n '/^═══/,$p' a2a-tck/tck-output.log) if [ -n "$SUMMARY" ]; then - echo '### TCK Results (Java ${{ matrix.java-version }})' >> $GITHUB_STEP_SUMMARY + echo '### TCK 1.0 Results (Java ${{ matrix.java-version }}${{ matrix.profile && format(', {0}', matrix.profile) || '' }})' >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo "$SUMMARY" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY @@ -112,7 +116,106 @@ jobs: if: always() uses: actions/upload-artifact@v7 with: - name: tck-reports-java-${{ matrix.java-version }} + name: tck-reports-java-${{ matrix.java-version }}${{ matrix.profile && format('-{0}', matrix.profile) || '' }} path: a2a-tck/reports/ retention-days: 14 - if-no-files-found: warn \ No newline at end of file + if-no-files-found: warn + + tck-test-0-3: + runs-on: ubuntu-latest + strategy: + matrix: + java-version: [17] + profile: ['', 'multi-mode'] + steps: + - name: Checkout a2a-java + uses: actions/checkout@v6 + - name: Set up JDK ${{ matrix.java-version }} + uses: actions/setup-java@v5 + with: + java-version: ${{ matrix.java-version }} + distribution: 'temurin' + cache: maven + - name: Build a2a-java SDK + run: mvn -B install -DskipTests + - name: Checkout a2a-tck + uses: actions/checkout@v6 + with: + repository: a2aproject/a2a-tck + path: a2a-tck + ref: ${{ env.TCK_VERSION_0_3 }} + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version-file: "a2a-tck/pyproject.toml" + - name: Install uv and Python dependencies + run: | + pip install uv + uv pip install -e . + working-directory: a2a-tck + - name: Start SUT + run: mvn -B quarkus:dev ${{ matrix.profile && format('-P{0}', matrix.profile) || '' }} -Dquarkus.console.enabled=false & + working-directory: compat-0.3/tck + - name: Wait for SUT to start + run: | + URL="${{ env.SUT_URL }}/.well-known/agent-card.json" + EXPECTED_STATUS=200 + TIMEOUT=120 + RETRY_INTERVAL=2 + START_TIME=$(date +%s) + + while true; do + CURRENT_TIME=$(date +%s) + ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) + + if [ "$ELAPSED_TIME" -ge "$TIMEOUT" ]; then + echo "Timeout: Server did not respond with status $EXPECTED_STATUS within $TIMEOUT seconds." + exit 1 + fi + + HTTP_STATUS=$(curl --output /dev/null --silent --write-out "%{http_code}" "$URL") || true + + if [ "$HTTP_STATUS" -eq "$EXPECTED_STATUS" ]; then + echo "Server is up! Received status $HTTP_STATUS after $ELAPSED_TIME seconds." + break; + fi + + echo "Server not ready (status: $HTTP_STATUS). Retrying in $RETRY_INTERVAL seconds..." + sleep "$RETRY_INTERVAL" + done + - name: Run TCK + id: run-tck + timeout-minutes: 5 + env: + TCK_STREAMING_TIMEOUT: ${{ env.TCK_STREAMING_TIMEOUT_0_3 }} + run: | + set -o pipefail + ./run_tck.py --sut-url ${{ env.SUT_URL }} --category all --transports jsonrpc,grpc,rest --compliance-report report.json 2>&1 | tee tck-output.log + working-directory: a2a-tck + - name: TCK Summary + if: always() && steps.run-tck.outcome != 'skipped' + run: | + if [ -f a2a-tck/tck-output.log ]; then + SUMMARY=$(sed -n '/^═══/,$p' a2a-tck/tck-output.log) + if [ -n "$SUMMARY" ]; then + echo '### TCK 0.3 Results (Java ${{ matrix.java-version }}${{ matrix.profile && format(', {0}', matrix.profile) || '' }})' >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "$SUMMARY" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + fi + fi + - name: Stop SUT + if: always() + run: | + pkill -f "quarkus:dev" || true + sleep 2 + - name: Upload TCK Reports + if: always() + uses: actions/upload-artifact@v7 + with: + name: tck-0.3-reports-java-${{ matrix.java-version }}${{ matrix.profile && format('-{0}', matrix.profile) || '' }} + path: | + a2a-tck/reports/ + a2a-tck/report.json + retention-days: 14 + if-no-files-found: warn diff --git a/README.md b/README.md index 8f21b8837..25bb8813d 100644 --- a/README.md +++ b/README.md @@ -345,7 +345,33 @@ These are a convenience — they transitively include all the individual compat - **JSON-RPC and REST**: When serving multiple protocol versions, version routing inspects the `A2A-Version` HTTP header on each request. If the header is `"1.0"`, the request is routed to the v1.0 handler. If it is `"0.3"` or absent, the request is routed to the v0.3 handler. - **gRPC**: Version dispatch is implicit — v0.3 clients use the `a2a.v1` protobuf package and v1.0 clients use `lf.a2a.v1`, so requests are routed to the correct service automatically. -- **Agent card**: The agent card is served in v1.0 format only. Older clients must be able to parse the v1.0 agent card. +- **Agent card**: When both v1.0 and v0.3 are enabled, the v1.0 `AgentCard` takes precedence and is served at `/.well-known/agent-card.json`. The v0.3 `AgentCard_v0_3` is ignored. If only v0.3 is enabled, the v0.3 agent card is used. If only v1.0 is enabled, the v1.0 agent card is used as-is. + +#### Making the v1.0 Agent Card Compatible with v0.3 Clients + +When serving both protocol versions, you need to ensure the v1.0 agent card contains fields that v0.3 clients expect. Existing v0.3 client implementations (in any language) look for `url`, `preferredTransport`, and `additionalInterfaces` with `transport`/`url` entries — fields that don't exist in the v1.0 format by default. + +To make your v1.0 `AgentCard` parsable by v0.3 clients, set these fields on the builder: + +```java +AgentCard card = AgentCard.builder() + .name("My Agent") + // ... other v1.0 fields ... + .supportedInterfaces(List.of( + new AgentInterface("jsonrpc", "http://localhost:9999"))) + // v0.3 backward-compatibility fields: + .url("http://localhost:9999") + .preferredTransport("jsonrpc") + .additionalInterfaces(List.of( + new Legacy_0_3_AgentInterface("jsonrpc", "http://localhost:9999"))) + .build(); +``` + +The two interface lists serve different clients: + +- `supportedInterfaces` — used by **v1.0 clients** to discover endpoints (uses `AgentInterface` with `protocolBinding`/`url`/`tenant` fields) +- `additionalInterfaces` — used by **v0.3 clients** to discover endpoints (uses `Legacy_0_3_AgentInterface` with v0.3 field names: `transport`/`url`) +- `url` and `preferredTransport` — top-level fields that v0.3 clients use to discover the primary endpoint ## A2A Client diff --git a/common/src/main/java/org/a2aproject/sdk/util/Assert.java b/common/src/main/java/org/a2aproject/sdk/util/Assert.java index f7a92d63e..2d2739013 100644 --- a/common/src/main/java/org/a2aproject/sdk/util/Assert.java +++ b/common/src/main/java/org/a2aproject/sdk/util/Assert.java @@ -27,9 +27,9 @@ private static void checkNotNullParamChecked(final String name, final @Nulla } } - public static void isNullOrStringOrInteger(@Nullable Object value) { - if (! (value == null || value instanceof String || value instanceof Integer)) { - throw new IllegalArgumentException("Id must be null, a String, or an Integer"); + public static void isValidJsonRpcId(@Nullable Object value) { + if (! (value == null || value instanceof String || value instanceof Number)) { + throw new IllegalArgumentException("JSON-RPC id must be null, a String, or a Number"); } } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskRequest_v0_3.java index 2aa02e9fe..adad0aefc 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/CancelTaskRequest_v0_3.java @@ -23,7 +23,7 @@ public CancelTaskRequest_v0_3(String jsonrpc, Object id, String method, TaskIdPa throw new IllegalArgumentException("Invalid CancelTaskRequest method"); } Assert.checkNotNullParam("params", params); - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigRequest_v0_3.java index a90894e54..132de62b9 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DeleteTaskPushNotificationConfigRequest_v0_3.java @@ -20,7 +20,7 @@ public DeleteTaskPushNotificationConfigRequest_v0_3(String jsonrpc, Object id, S if (! method.equals(METHOD)) { throw new IllegalArgumentException("Invalid DeleteTaskPushNotificationConfigRequest method"); } - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = Utils_v0_3.defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardRequest_v0_3.java index 55a95d4a8..f6b14e6a4 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetAuthenticatedExtendedCardRequest_v0_3.java @@ -21,7 +21,7 @@ public GetAuthenticatedExtendedCardRequest_v0_3(String jsonrpc, Object id, Strin if (! method.equals(METHOD)) { throw new IllegalArgumentException("Invalid GetAuthenticatedExtendedCardRequest method"); } - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = Utils_v0_3.defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigRequest_v0_3.java index 536423fe8..5252f29c4 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskPushNotificationConfigRequest_v0_3.java @@ -20,7 +20,7 @@ public GetTaskPushNotificationConfigRequest_v0_3(String jsonrpc, Object id, Stri if (! method.equals(METHOD)) { throw new IllegalArgumentException("Invalid GetTaskPushNotificationRequest method"); } - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = Utils_v0_3.defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskRequest_v0_3.java index ac097bdcb..561ef5037 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/GetTaskRequest_v0_3.java @@ -23,7 +23,7 @@ public GetTaskRequest_v0_3(String jsonrpc, Object id, String method, TaskQueryPa throw new IllegalArgumentException("Invalid GetTaskRequest method"); } Assert.checkNotNullParam("params", params); - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCRequest_v0_3.java index fc5fc58bf..9a337a6ca 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCRequest_v0_3.java @@ -20,7 +20,7 @@ public JSONRPCRequest_v0_3() { public JSONRPCRequest_v0_3(String jsonrpc, Object id, String method, T params) { Assert.checkNotNullParam("jsonrpc", jsonrpc); Assert.checkNotNullParam("method", method); - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCResponse_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCResponse_v0_3.java index 58822eea1..009db94d4 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCResponse_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/JSONRPCResponse_v0_3.java @@ -30,7 +30,7 @@ public JSONRPCResponse_v0_3(String jsonrpc, Object id, T result, JSONRPCError_v0 if (error == null && result == null && ! Void.class.equals(resultType)) { throw new IllegalArgumentException("Invalid JSON-RPC success response"); } - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.result = result; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigRequest_v0_3.java index f8c1b597e..5b5657394 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/ListTaskPushNotificationConfigRequest_v0_3.java @@ -20,7 +20,7 @@ public ListTaskPushNotificationConfigRequest_v0_3(String jsonrpc, Object id, Str if (! method.equals(METHOD)) { throw new IllegalArgumentException("Invalid ListTaskPushNotificationConfigRequest method"); } - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = Utils_v0_3.defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageRequest_v0_3.java index c57a6cba9..6fd4a08ed 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendMessageRequest_v0_3.java @@ -37,7 +37,7 @@ public SendMessageRequest_v0_3(String jsonrpc, Object id, String method, Message throw new IllegalArgumentException("Invalid SendMessageRequest method"); } Assert.checkNotNullParam("params", params); - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; @@ -56,7 +56,7 @@ public void check() { throw new IllegalArgumentException("Invalid SendMessageRequest method"); } Assert.checkNotNullParam("params", params); - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); params.check(); } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageRequest_v0_3.java index 91e7f3260..b6f7fb2ea 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SendStreamingMessageRequest_v0_3.java @@ -22,7 +22,7 @@ public SendStreamingMessageRequest_v0_3(String jsonrpc, Object id, String method throw new IllegalArgumentException("Invalid SendStreamingMessageRequest method"); } Assert.checkNotNullParam("params", params); - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; @@ -38,7 +38,7 @@ public void check() { throw new IllegalArgumentException("Invalid SendStreamingMessageRequest method"); } Assert.checkNotNullParam("params", params); - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); params.check(); } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigRequest_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigRequest_v0_3.java index 130831b0e..2c08dc7fe 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigRequest_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SetTaskPushNotificationConfigRequest_v0_3.java @@ -22,7 +22,7 @@ public SetTaskPushNotificationConfigRequest_v0_3(String jsonrpc, Object id, Stri throw new IllegalArgumentException("Invalid SetTaskPushNotificationRequest method"); } Assert.checkNotNullParam("params", params); - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.method = method; diff --git a/compat-0.3/tck/pom.xml b/compat-0.3/tck/pom.xml index b0cb5c5c8..8622a6a37 100644 --- a/compat-0.3/tck/pom.xml +++ b/compat-0.3/tck/pom.xml @@ -49,6 +49,56 @@ + + + multi-mode + + + org.a2aproject.sdk + a2a-java-sdk-reference-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-grpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-rest + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-rest + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-multi-mode-source + generate-sources + + add-source + + + + src/multi-mode/java + + + + + + + + + + diff --git a/compat-0.3/tck/src/multi-mode/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java b/compat-0.3/tck/src/multi-mode/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java new file mode 100644 index 000000000..4f4beb28e --- /dev/null +++ b/compat-0.3/tck/src/multi-mode/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java @@ -0,0 +1,66 @@ +package org.a2aproject.sdk.compat03.tck.server; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; + +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.server.PublicAgentCard; +import org.a2aproject.sdk.spec.AgentCapabilities; +import org.a2aproject.sdk.spec.AgentCard; +import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.AgentSkill; +import org.a2aproject.sdk.spec.Compat03Fields; + +/** + * Produces a v1.0 {@link AgentCard} derived from the v0.3 {@link AgentCard_v0_3} + * when the multi-mode profile adds v1.0 reference dependencies to the classpath. + * Overrides the {@code @DefaultBean} in {@code DefaultProducers}. + */ +@ApplicationScoped +public class DerivedAgentCardProducer { + + @Inject + @PublicAgentCard + AgentCard_v0_3 v03Card; + + @Produces + @PublicAgentCard + public AgentCard createDerivedAgentCard() { + List interfaces = v03Card.additionalInterfaces().stream() + .map(iface -> new AgentInterface(iface.transport(), iface.url())) + .toList(); + + AgentCard.Builder builder = AgentCard.builder() + .name(v03Card.name()) + .description(v03Card.description()) + .version(v03Card.version()) + .capabilities(AgentCapabilities.builder() + .streaming(v03Card.capabilities().streaming()) + .pushNotifications(v03Card.capabilities().pushNotifications()) + .build()) + .defaultInputModes(v03Card.defaultInputModes()) + .defaultOutputModes(v03Card.defaultOutputModes()) + .skills(v03Card.skills().stream() + .map(DerivedAgentCardProducer::toSkill10) + .toList()) + .supportedInterfaces(interfaces); + + Compat03Fields.addCompat03FieldsIfAvailable(builder, interfaces, v03Card.url(), v03Card.preferredTransport()); + + return builder.build(); + } + + private static AgentSkill toSkill10(AgentSkill_v0_3 skill) { + return AgentSkill.builder() + .id(skill.id()) + .name(skill.name()) + .description(skill.description()) + .tags(skill.tags()) + .examples(skill.examples() != null ? skill.examples() : List.of()) + .build(); + } +} diff --git a/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java index ac3952d4b..4c37b5c5d 100644 --- a/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java +++ b/extras/opentelemetry/integration-tests/src/main/java/org/a2aproject/sdk/extras/opentelemetry/it/A2ATestRoutes.java @@ -51,6 +51,7 @@ public class A2ATestRoutes { void setupRoutes(@Observes Router router) { router.post("/test/task") .consumes(APPLICATION_JSON) + .handler(BodyHandler.create()) .blockingHandler(ctx -> saveTask(ctx.body().asString(), ctx)); router.get("/test/task/:taskId") diff --git a/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2ARequest.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2ARequest.java index cbafe613d..b9b714ff3 100644 --- a/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2ARequest.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2ARequest.java @@ -98,7 +98,7 @@ protected void validateAndSetJsonParameters(String jsonrpc, String method, Objec } Assert.checkNotNullParam("method", method); this.method = method; - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.id = id; if (paramsIsRequired) { Assert.checkNotNullParam("params", params); diff --git a/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AResponse.java b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AResponse.java index 1c2b1c649..427021949 100644 --- a/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AResponse.java +++ b/jsonrpc-common/src/main/java/org/a2aproject/sdk/jsonrpc/common/wrappers/A2AResponse.java @@ -46,7 +46,7 @@ public A2AResponse(String jsonrpc, Object id, T result, A2AError error, Class if (error == null && result == null && ! Void.class.equals(resultType)) { throw new IllegalArgumentException("Invalid JSON-RPC success response"); } - Assert.isNullOrStringOrInteger(id); + Assert.isValidJsonRpcId(id); this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); this.id = id; this.result = result; diff --git a/pom.xml b/pom.xml index 5201ccd30..204ce2483 100644 --- a/pom.xml +++ b/pom.xml @@ -202,6 +202,16 @@ a2a-java-sdk-reference-rest ${project.version} + + ${project.groupId} + a2a-java-sdk-reference-multiversion-jsonrpc + ${project.version} + + + ${project.groupId} + a2a-java-sdk-reference-multiversion-rest + ${project.version} + org.a2aproject.sdk a2a-java-sdk-opentelemetry diff --git a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index 492e2517d..e9df1bf06 100644 --- a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -204,13 +204,12 @@ public class A2AServerRoutes { * @param router the Vert.x Web Router instance to configure */ void setupRoutes(@Observes Router router) { - // Add BodyHandler to parse request bodies - router.route().handler(BodyHandler.create()); - // Main JSON-RPC endpoint: POST / + // BodyHandler is per-route (not global) to avoid interfering with gRPC routes // ordered=false: delegation via Vert.x WebClient can share the same event loop context as the outer request; ordered=true would serialize them, causing a 30s deadlock. router.post("/") .consumes(APPLICATION_JSON) + .handler(BodyHandler.create()) .blockingHandler(ctx -> { try { vertxSecurityHelper.runInRequestContext(ctx, () -> { diff --git a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java index 17be340f8..6b86e5ed4 100644 --- a/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java +++ b/reference/jsonrpc/src/test/java/org/a2aproject/sdk/server/apps/quarkus/A2ATestRoutes.java @@ -43,6 +43,7 @@ void setupRoutes(@Observes Router router) { // Save task: POST /test/task router.post("/test/task") .consumes(APPLICATION_JSON) + .handler(BodyHandler.create()) .blockingHandler(ctx -> { String body = ctx.body().asString(); saveTask(body, ctx); @@ -113,6 +114,7 @@ void setupRoutes(@Observes Router router) { // Save task push notification config: POST /test/task/:taskId router.post("/test/task/:taskId") + .handler(BodyHandler.create()) .blockingHandler(ctx -> { String taskId = ctx.pathParam("taskId"); String body = ctx.body().asString(); diff --git a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java index 565d6255c..9b6a72dce 100644 --- a/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java +++ b/spec-grpc/src/main/java/org/a2aproject/sdk/grpc/mapper/AgentCardMapper.java @@ -32,5 +32,6 @@ public interface AgentCardMapper { @Mapping(target = "iconUrl", source = "iconUrl", conditionExpression = "java(!proto.getIconUrl().isEmpty())") @Mapping(target = "url", ignore = true) @Mapping(target = "preferredTransport", ignore = true) + @Mapping(target = "additionalInterfaces", ignore = true) org.a2aproject.sdk.spec.AgentCard fromProto(org.a2aproject.sdk.grpc.AgentCard proto); } diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java index b3aaa2275..a119bc7d5 100644 --- a/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java +++ b/spec/src/main/java/org/a2aproject/sdk/spec/AgentCard.java @@ -58,7 +58,8 @@ public record AgentCard( List supportedInterfaces, @Nullable List signatures, @Nullable String url, - @Nullable String preferredTransport) { + @Nullable String preferredTransport, + @Nullable List additionalInterfaces) { /** * Compact constructor that validates required fields. @@ -160,6 +161,7 @@ public static class Builder { private @Nullable List signatures; private @Nullable String url; private @Nullable String preferredTransport; + private @Nullable List additionalInterfaces; /** * Creates a new Builder with all fields unset. @@ -192,6 +194,7 @@ private Builder(AgentCard card) { this.signatures = card.signatures() != null ? new ArrayList<>(card.signatures()) : null; this.url = card.url(); this.preferredTransport= card.preferredTransport(); + this.additionalInterfaces = card.additionalInterfaces() != null ? new ArrayList<>(card.additionalInterfaces()) : null; } /** @@ -392,6 +395,11 @@ public Builder url(String url) { return this; } + public Builder additionalInterfaces(List additionalInterfaces) { + this.additionalInterfaces = additionalInterfaces; + return this; + } + /** * Builds an immutable {@link AgentCard} from the current builder state. *

            @@ -417,7 +425,8 @@ public AgentCard build() { Assert.checkNotNullParam("supportedInterfaces", supportedInterfaces), signatures, url, - preferredTransport == null ? "JSONRPC" : preferredTransport); + preferredTransport == null ? "JSONRPC" : preferredTransport, + additionalInterfaces); } } } diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/Compat03Fields.java b/spec/src/main/java/org/a2aproject/sdk/spec/Compat03Fields.java new file mode 100644 index 000000000..20f49d0fc --- /dev/null +++ b/spec/src/main/java/org/a2aproject/sdk/spec/Compat03Fields.java @@ -0,0 +1,35 @@ +package org.a2aproject.sdk.spec; + +import java.util.List; + +public final class Compat03Fields { + + private static final boolean COMPAT_03_AVAILABLE; + + static { + boolean available; + try { + Class.forName("org.a2aproject.sdk.compat03.spec.AgentCard_v0_3"); + available = true; + } catch (ClassNotFoundException e) { + available = false; + } + COMPAT_03_AVAILABLE = available; + } + + private Compat03Fields() { + } + + public static void addCompat03FieldsIfAvailable(AgentCard.Builder builder, + List supportedInterfaces, String url, String preferredTransport) { + if (!COMPAT_03_AVAILABLE) { + return; + } + builder.url(url) + .preferredTransport(preferredTransport) + .additionalInterfaces( + supportedInterfaces.stream() + .map(iface -> new Legacy_0_3_AgentInterface(iface.protocolBinding(), iface.url())) + .toList()); + } +} diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/Legacy_0_3_AgentInterface.java b/spec/src/main/java/org/a2aproject/sdk/spec/Legacy_0_3_AgentInterface.java new file mode 100644 index 000000000..686f3ecb6 --- /dev/null +++ b/spec/src/main/java/org/a2aproject/sdk/spec/Legacy_0_3_AgentInterface.java @@ -0,0 +1,24 @@ +package org.a2aproject.sdk.spec; + +import org.a2aproject.sdk.util.Assert; + +/** + * A legacy (v0.3) representation of an agent interface, using the v0.3 field names + * ({@code transport} and {@code url}) for backward compatibility with older clients. + *

            + * When included in the {@link AgentCard#additionalInterfaces()} field, this record + * serializes with the JSON shape expected by v0.3 clients: + *

            + * {"transport": "GRPC", "url": "http://localhost:9999"}
            + * 
            + * + * @param transport the transport protocol (e.g., "JSONRPC", "GRPC", "HTTP+JSON") + * @param url the endpoint URL + */ +public record Legacy_0_3_AgentInterface(String transport, String url) { + + public Legacy_0_3_AgentInterface { + Assert.checkNotNullParam("transport", transport); + Assert.checkNotNullParam("url", url); + } +} diff --git a/tck/pom.xml b/tck/pom.xml index 41eaec905..7e6256dd4 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -45,6 +45,59 @@ + + + multi-mode + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-jsonrpc + ${project.version} + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-grpc + ${project.version} + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-rest + ${project.version} + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-rest + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-multi-mode-source + generate-sources + + add-source + + + + src/multi-mode/java + + + + + + + + + + diff --git a/tck/src/multi-mode/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java b/tck/src/multi-mode/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java new file mode 100644 index 000000000..780aa3277 --- /dev/null +++ b/tck/src/multi-mode/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java @@ -0,0 +1,43 @@ +package org.a2aproject.sdk.sut; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import io.quarkus.arc.DefaultBean; + +import org.a2aproject.sdk.compat03.spec.AgentCapabilities_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.compat03.spec.AgentSkill_v0_3; +import org.a2aproject.sdk.server.PublicAgentCard; + +/** + * Stub producer that satisfies the v0.3 handler CDI requirements when the + * multi-mode profile adds compat-0.3 dependencies to the classpath. + * This will be replaced by a proper translation layer in the future. + */ +@ApplicationScoped +public class StubAgentCardProducer_v0_3 { + + @Produces + @PublicAgentCard + @DefaultBean + public AgentCard_v0_3 createStubAgentCard() { + return new AgentCard_v0_3.Builder() + .name("stub") + .description("Stub agent card for multi-mode testing") + .url("http://localhost:9999") + .version("0.0.0") + .capabilities(new AgentCapabilities_v0_3.Builder().build()) + .defaultInputModes(List.of("text")) + .defaultOutputModes(List.of("text")) + .skills(List.of(new AgentSkill_v0_3.Builder() + .id("stub") + .name("stub") + .description("stub") + .tags(List.of()) + .build())) + .build(); + } +} diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java index 313d4e834..82870a693 100644 --- a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java @@ -46,6 +46,7 @@ public void init() { void setupRoutes(@Observes Router router) { router.post("/test/task") .consumes(APPLICATION_JSON) + .handler(BodyHandler.create()) .blockingHandler(ctx -> { String body = ctx.body().asString(); saveTask(body, ctx); @@ -105,6 +106,7 @@ void setupRoutes(@Observes Router router) { }); router.post("/test/task/:taskId") + .handler(BodyHandler.create()) .blockingHandler(ctx -> { String taskId = ctx.pathParam("taskId"); String body = ctx.body().asString(); diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java index be70577cd..bd3f46d82 100644 --- a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java @@ -6,8 +6,6 @@ import org.a2aproject.sdk.compat03.client.transport.jsonrpc.JSONRPCTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; @QuarkusTest public class MultiVersionJSONRPC_v0_3_Test extends AbstractA2AServerServerTest_v0_3 { @@ -30,10 +28,4 @@ protected String getTransportUrl() { protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); } - - @Test - @Override - @Disabled("Agent card is v1.0 format in multi-version mode") - public void testGetAgentCard() { - } } diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java index 5cfe96ef4..07e8f8144 100644 --- a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java +++ b/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java @@ -8,8 +8,6 @@ import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; @QuarkusTest @TestProfile(AuthTestProfile.class) @@ -45,9 +43,4 @@ protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()); } - @Test - @Override - @Disabled("Agent card is v1.0 format in multi-version mode") - public void testGetAgentCardIsPublic() { - } } diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java index ee2623ba1..d3250580c 100644 --- a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java @@ -6,8 +6,6 @@ import org.a2aproject.sdk.compat03.client.transport.rest.RestTransportConfigBuilder_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerServerTest_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; @QuarkusTest public class MultiVersion_v0_3_RestTest extends AbstractA2AServerServerTest_v0_3 { @@ -30,10 +28,4 @@ protected String getTransportUrl() { protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); } - - @Test - @Override - @Disabled("Agent card is v1.0 format in multi-version mode") - public void testGetAgentCard() { - } } diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java index a9a496780..81462ee01 100644 --- a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java +++ b/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java @@ -8,7 +8,6 @@ import org.a2aproject.sdk.compat03.client.transport.spi.interceptors.auth.AuthInterceptor_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2AServerWithAuthTest_v0_3; import org.a2aproject.sdk.compat03.spec.TransportProtocol_v0_3; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @QuarkusTest @@ -45,12 +44,6 @@ protected void configureTransport(ClientBuilder_v0_3 builder) { builder.withTransport(RestTransport_v0_3.class, new RestTransportConfigBuilder_v0_3()); } - @Test - @Override - @Disabled("Agent card is v1.0 format in multi-version mode") - public void testGetAgentCardIsPublic() { - } - @Test @Override public void testBasicAuthWorksViaHttp() throws Exception { diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java index d6d76dcca..710f8bae3 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentCardProducer.java @@ -7,6 +7,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Properties; import jakarta.enterprise.context.ApplicationScoped; @@ -18,6 +19,7 @@ import org.a2aproject.sdk.spec.AgentCapabilities; import org.a2aproject.sdk.spec.AgentCard; import org.a2aproject.sdk.spec.AgentInterface; +import org.a2aproject.sdk.spec.Compat03Fields; import org.a2aproject.sdk.spec.HTTPAuthSecurityScheme; import org.a2aproject.sdk.spec.SecurityRequirement; import org.eclipse.microprofile.config.inject.ConfigProperty; @@ -45,6 +47,8 @@ public AgentCard agentCard() { String preferredTransport = loadPreferredTransportFromProperties(); String transportUrl = GRPC.toString().equals(preferredTransport) ? "localhost:" + port : "http://localhost:" + port; + List interfaces = Collections.singletonList(new AgentInterface(preferredTransport, transportUrl)); + AgentCard.Builder builder = AgentCard.builder() .name("test-card") .description("A test agent card") @@ -58,9 +62,9 @@ public AgentCard agentCard() { .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) .skills(new ArrayList<>()) - .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, transportUrl))) - .url(transportUrl) - .preferredTransport(preferredTransport); + .supportedInterfaces(interfaces); + + Compat03Fields.addCompat03FieldsIfAvailable(builder, interfaces, transportUrl, preferredTransport); // Add security configuration if enabled (for authentication tests) if (securityEnabled) { From c1a898a8656e69dd8e6597795a2077f804ad560c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 17:32:06 +0100 Subject: [PATCH 165/192] chore: bump io.grpc:grpc-bom from 1.79.0 to 1.81.0 in the grpc group across 1 directory (#865) chore: bump io.grpc:grpc-bom in the grpc group across 1 directory Bumps the grpc group with 1 update in the / directory: [io.grpc:grpc-bom](https://github.com/grpc/grpc-java). Updates `io.grpc:grpc-bom` from 1.79.0 to 1.81.0 - [Release notes](https://github.com/grpc/grpc-java/releases) - [Commits](https://github.com/grpc/grpc-java/compare/v1.79.0...v1.81.0) --- updated-dependencies: - dependency-name: io.grpc:grpc-bom dependency-version: 1.81.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: grpc ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 204ce2483..a88a4514d 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ - 1.79.0 + 1.81.0 UTF-8 3.5.0 3.15.0 From fac0a82a1aa86c124ab6f0ff6696c49b177d9dc0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 16:32:23 +0000 Subject: [PATCH 166/192] chore: bump org.apache.maven.plugins:maven-invoker-plugin Bumps the maven-plugins group with 1 update in the / directory: [org.apache.maven.plugins:maven-invoker-plugin](https://github.com/apache/maven-invoker-plugin). Updates `org.apache.maven.plugins:maven-invoker-plugin` from 3.10.0 to 3.10.1 - [Release notes](https://github.com/apache/maven-invoker-plugin/releases) - [Commits](https://github.com/apache/maven-invoker-plugin/compare/maven-invoker-plugin-3.10.0...maven-invoker-plugin-3.10.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-invoker-plugin dependency-version: 3.10.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: maven-plugins ... Signed-off-by: dependabot[bot] --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 2e36f899d..5b8a6e4a4 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -102,7 +102,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.10.0 + 3.10.1 ${project.build.directory}/it ${project.build.directory}/local-repo diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 304a6bc36..7006e7c64 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -112,7 +112,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.10.0 + 3.10.1 ${project.build.directory}/it ${project.build.directory}/local-repo diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index e85d715e2..b28fca59b 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -291,7 +291,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.10.0 + 3.10.1 ${project.build.directory}/it ${project.build.directory}/local-repo From 4710d2ae2bffd8c2fcb2282783594e3bfc3c6ff3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 17:32:33 +0100 Subject: [PATCH 167/192] chore: bump the testing group across 1 directory with 2 updates (#852) Bumps the testing group with 2 updates in the / directory: [io.rest-assured:rest-assured](https://github.com/rest-assured/rest-assured) and [org.mockito:mockito-core](https://github.com/mockito/mockito). Updates `io.rest-assured:rest-assured` from 5.5.1 to 6.0.0 - [Changelog](https://github.com/rest-assured/rest-assured/blob/master/changelog.txt) - [Commits](https://github.com/rest-assured/rest-assured/compare/rest-assured-5.5.1...rest-assured-6.0.0) Updates `org.mockito:mockito-core` from 5.17.0 to 5.23.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.17.0...v5.23.0) --- updated-dependencies: - dependency-name: io.rest-assured:rest-assured dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: testing - dependency-name: org.mockito:mockito-core dependency-version: 5.23.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: testing ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a88a4514d..1c21f8b58 100644 --- a/pom.xml +++ b/pom.xml @@ -59,14 +59,14 @@ 6.0.3 1.6.3 1.52.0 - 5.17.0 + 5.23.0 5.15.0 1.1.1 1.7.1 4.33.2 0.6.1 3.35.2 - 5.5.1 + 6.0.0 2.0.17 1.5.18 2.0.5 From 046fcf8ca91bf0748679da9be7044852750b98e3 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 14 May 2026 17:36:54 +0100 Subject: [PATCH 168/192] fix: Standardise on multi-version (vs multi-mode) (#876) More tests/reference to tests/multiversion since that is what these tests are --- .claude/architecture/compatibility_0.3.md | 6 +++--- .github/workflows/run-tck.yml | 4 ++-- compat-0.3/tck/pom.xml | 6 +++--- .../sdk/compat03/tck/server/DerivedAgentCardProducer.java | 2 +- pom.xml | 6 +++--- tck/pom.xml | 6 +++--- .../org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java | 4 ++-- tests/{reference => multiversion}/grpc/pom.xml | 0 .../sdk/tests/multiversion/grpc/A2ATestResource.java | 0 .../sdk/tests/multiversion/grpc/AuthTestProfile.java | 0 .../sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java | 0 .../multiversion/grpc/MultiVersionGrpcWithAuthTest.java | 0 .../tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java | 0 .../grpc/MultiVersion_v0_3_GrpcWithAuthTest.java | 0 .../multiversion/grpc/TestAuthorizationController.java | 0 .../src/test/resources/a2a-requesthandler-test.properties | 0 .../grpc/src/test/resources/application.properties | 0 .../resources/compat-0.3-requesthandler-test.properties | 0 tests/{reference => multiversion}/jsonrpc/pom.xml | 0 .../sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java | 0 .../sdk/tests/multiversion/jsonrpc/AuthTestProfile.java | 0 .../tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java | 0 .../jsonrpc/MultiVersionJSONRPCWithAuthTest.java | 0 .../multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java | 0 .../jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java | 0 .../tests/multiversion/jsonrpc/TestIdentityProvider.java | 0 .../src/test/resources/a2a-requesthandler-test.properties | 0 .../jsonrpc/src/test/resources/application.properties | 0 .../resources/compat-0.3-requesthandler-test.properties | 0 tests/{reference => multiversion}/rest/pom.xml | 0 .../sdk/tests/multiversion/rest/A2ATestRoutes.java | 0 .../sdk/tests/multiversion/rest/AuthTestProfile.java | 0 .../sdk/tests/multiversion/rest/MultiVersionRestTest.java | 0 .../multiversion/rest/MultiVersionRestWithAuthTest.java | 0 .../tests/multiversion/rest/MultiVersion_v0_3_RestTest.java | 0 .../rest/MultiVersion_v0_3_RestWithAuthTest.java | 0 .../sdk/tests/multiversion/rest/TestIdentityProvider.java | 0 .../src/test/resources/a2a-requesthandler-test.properties | 0 .../rest/src/test/resources/application.properties | 0 .../resources/compat-0.3-requesthandler-test.properties | 0 40 files changed, 17 insertions(+), 17 deletions(-) rename compat-0.3/tck/src/{multi-mode => multi-version}/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java (96%) rename tck/src/{multi-mode => multi-version}/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java (90%) rename tests/{reference => multiversion}/grpc/pom.xml (100%) rename tests/{reference => multiversion}/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java (100%) rename tests/{reference => multiversion}/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java (100%) rename tests/{reference => multiversion}/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java (100%) rename tests/{reference => multiversion}/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java (100%) rename tests/{reference => multiversion}/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java (100%) rename tests/{reference => multiversion}/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java (100%) rename tests/{reference => multiversion}/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java (100%) rename tests/{reference => multiversion}/grpc/src/test/resources/a2a-requesthandler-test.properties (100%) rename tests/{reference => multiversion}/grpc/src/test/resources/application.properties (100%) rename tests/{reference => multiversion}/grpc/src/test/resources/compat-0.3-requesthandler-test.properties (100%) rename tests/{reference => multiversion}/jsonrpc/pom.xml (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/resources/a2a-requesthandler-test.properties (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/resources/application.properties (100%) rename tests/{reference => multiversion}/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties (100%) rename tests/{reference => multiversion}/rest/pom.xml (100%) rename tests/{reference => multiversion}/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java (100%) rename tests/{reference => multiversion}/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java (100%) rename tests/{reference => multiversion}/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java (100%) rename tests/{reference => multiversion}/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java (100%) rename tests/{reference => multiversion}/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java (100%) rename tests/{reference => multiversion}/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java (100%) rename tests/{reference => multiversion}/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java (100%) rename tests/{reference => multiversion}/rest/src/test/resources/a2a-requesthandler-test.properties (100%) rename tests/{reference => multiversion}/rest/src/test/resources/application.properties (100%) rename tests/{reference => multiversion}/rest/src/test/resources/compat-0.3-requesthandler-test.properties (100%) diff --git a/.claude/architecture/compatibility_0.3.md b/.claude/architecture/compatibility_0.3.md index 7020ecdb2..d6430724d 100644 --- a/.claude/architecture/compatibility_0.3.md +++ b/.claude/architecture/compatibility_0.3.md @@ -25,7 +25,7 @@ The A2A protocol evolved from v0.3 to v1.0 with significant breaking changes. Ex - Integration test infrastructure (test-jar) for validating conversion layer - Inclusion in the SDK BOM as separate optional dependencies - Multi-version server deployment: `reference/multiversion-jsonrpc` and `reference/multiversion-rest` modules that dispatch requests to v1.0 or v0.3 handlers based on `A2A-Version` header via `VersionRouter` -- Multi-version integration tests under `tests/reference/{jsonrpc,rest,grpc}` (package `org.a2aproject.sdk.tests.multiversion`) +- Multi-version integration tests under `tests/multiversion/{jsonrpc,rest,grpc}` (package `org.a2aproject.sdk.tests.multiversion`) ### Out of Scope @@ -262,7 +262,7 @@ reference/ └── src/main/java/org/a2aproject/sdk/server/multiversion/rest/ └── MultiVersionRestRoutes.java -tests/reference/ # Multi-version integration tests +tests/multiversion/ # Multi-version integration tests ├── jsonrpc/ # JSON-RPC multi-version tests ├── rest/ # REST multi-version tests └── grpc/ # gRPC multi-version tests @@ -516,7 +516,7 @@ For JSON-RPC and REST, multi-version convenience modules are also available that **Agent card**: The agent card is served in v1.0 format only. Older clients must be able to parse the v1.0 agent card format to discover their endpoint. -**Integration tests**: Multi-version scenarios are tested under `tests/reference/{jsonrpc,rest,grpc}` using both v1.0 and v0.3 clients against a single server instance. +**Integration tests**: Multi-version scenarios are tested under `tests/multiversion/{jsonrpc,rest,grpc}` using both v1.0 and v0.3 clients against a single server instance. --- diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index c04eba168..18bdf29e9 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -30,7 +30,7 @@ jobs: strategy: matrix: java-version: [17] - profile: ['', 'multi-mode'] + profile: ['', 'multi-version'] steps: - name: Checkout a2a-java uses: actions/checkout@v6 @@ -126,7 +126,7 @@ jobs: strategy: matrix: java-version: [17] - profile: ['', 'multi-mode'] + profile: ['', 'multi-version'] steps: - name: Checkout a2a-java uses: actions/checkout@v6 diff --git a/compat-0.3/tck/pom.xml b/compat-0.3/tck/pom.xml index 8622a6a37..bcdaf37c0 100644 --- a/compat-0.3/tck/pom.xml +++ b/compat-0.3/tck/pom.xml @@ -51,7 +51,7 @@ - multi-mode + multi-version org.a2aproject.sdk @@ -81,14 +81,14 @@ build-helper-maven-plugin - add-multi-mode-source + add-multi-version-source generate-sources add-source - src/multi-mode/java + src/multi-version/java diff --git a/compat-0.3/tck/src/multi-mode/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java b/compat-0.3/tck/src/multi-version/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java similarity index 96% rename from compat-0.3/tck/src/multi-mode/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java rename to compat-0.3/tck/src/multi-version/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java index 4f4beb28e..053aced7f 100644 --- a/compat-0.3/tck/src/multi-mode/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java +++ b/compat-0.3/tck/src/multi-version/java/org/a2aproject/sdk/compat03/tck/server/DerivedAgentCardProducer.java @@ -17,7 +17,7 @@ /** * Produces a v1.0 {@link AgentCard} derived from the v0.3 {@link AgentCard_v0_3} - * when the multi-mode profile adds v1.0 reference dependencies to the classpath. + * when the multi-version profile adds v1.0 reference dependencies to the classpath. * Overrides the {@code @DefaultBean} in {@code DefaultProducers}. */ @ApplicationScoped diff --git a/pom.xml b/pom.xml index 1c21f8b58..ca640de38 100644 --- a/pom.xml +++ b/pom.xml @@ -607,9 +607,9 @@ reference/multiversion-rest - tests/reference/jsonrpc - tests/reference/rest - tests/reference/grpc + tests/multiversion/jsonrpc + tests/multiversion/rest + tests/multiversion/grpc boms/extras diff --git a/tck/pom.xml b/tck/pom.xml index 7e6256dd4..aae651d26 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -47,7 +47,7 @@ - multi-mode + multi-version org.a2aproject.sdk @@ -80,14 +80,14 @@ build-helper-maven-plugin - add-multi-mode-source + add-multi-version-source generate-sources add-source - src/multi-mode/java + src/multi-version/java diff --git a/tck/src/multi-mode/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java b/tck/src/multi-version/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java similarity index 90% rename from tck/src/multi-mode/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java rename to tck/src/multi-version/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java index 780aa3277..ef5fb0f7f 100644 --- a/tck/src/multi-mode/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java +++ b/tck/src/multi-version/java/org/a2aproject/sdk/sut/StubAgentCardProducer_v0_3.java @@ -14,7 +14,7 @@ /** * Stub producer that satisfies the v0.3 handler CDI requirements when the - * multi-mode profile adds compat-0.3 dependencies to the classpath. + * multi-version profile adds compat-0.3 dependencies to the classpath. * This will be replaced by a proper translation layer in the future. */ @ApplicationScoped @@ -26,7 +26,7 @@ public class StubAgentCardProducer_v0_3 { public AgentCard_v0_3 createStubAgentCard() { return new AgentCard_v0_3.Builder() .name("stub") - .description("Stub agent card for multi-mode testing") + .description("Stub agent card for multi-version testing") .url("http://localhost:9999") .version("0.0.0") .capabilities(new AgentCapabilities_v0_3.Builder().build()) diff --git a/tests/reference/grpc/pom.xml b/tests/multiversion/grpc/pom.xml similarity index 100% rename from tests/reference/grpc/pom.xml rename to tests/multiversion/grpc/pom.xml diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java b/tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java similarity index 100% rename from tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java rename to tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/A2ATestResource.java diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java b/tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java similarity index 100% rename from tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java rename to tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/AuthTestProfile.java diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java b/tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java similarity index 100% rename from tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java rename to tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcTest.java diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java b/tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java similarity index 100% rename from tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java rename to tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersionGrpcWithAuthTest.java diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java b/tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java similarity index 100% rename from tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java rename to tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcTest.java diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java b/tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java similarity index 100% rename from tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java rename to tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/MultiVersion_v0_3_GrpcWithAuthTest.java diff --git a/tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java b/tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java similarity index 100% rename from tests/reference/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java rename to tests/multiversion/grpc/src/test/java/org/a2aproject/sdk/tests/multiversion/grpc/TestAuthorizationController.java diff --git a/tests/reference/grpc/src/test/resources/a2a-requesthandler-test.properties b/tests/multiversion/grpc/src/test/resources/a2a-requesthandler-test.properties similarity index 100% rename from tests/reference/grpc/src/test/resources/a2a-requesthandler-test.properties rename to tests/multiversion/grpc/src/test/resources/a2a-requesthandler-test.properties diff --git a/tests/reference/grpc/src/test/resources/application.properties b/tests/multiversion/grpc/src/test/resources/application.properties similarity index 100% rename from tests/reference/grpc/src/test/resources/application.properties rename to tests/multiversion/grpc/src/test/resources/application.properties diff --git a/tests/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties b/tests/multiversion/grpc/src/test/resources/compat-0.3-requesthandler-test.properties similarity index 100% rename from tests/reference/grpc/src/test/resources/compat-0.3-requesthandler-test.properties rename to tests/multiversion/grpc/src/test/resources/compat-0.3-requesthandler-test.properties diff --git a/tests/reference/jsonrpc/pom.xml b/tests/multiversion/jsonrpc/pom.xml similarity index 100% rename from tests/reference/jsonrpc/pom.xml rename to tests/multiversion/jsonrpc/pom.xml diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java b/tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java similarity index 100% rename from tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java rename to tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/A2ATestRoutes.java diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java b/tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java similarity index 100% rename from tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java rename to tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/AuthTestProfile.java diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java b/tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java similarity index 100% rename from tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java rename to tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCTest.java diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java b/tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java similarity index 100% rename from tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java rename to tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPCWithAuthTest.java diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java b/tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java similarity index 100% rename from tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java rename to tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_Test.java diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java b/tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java similarity index 100% rename from tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java rename to tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/MultiVersionJSONRPC_v0_3_WithAuthTest.java diff --git a/tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java b/tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java similarity index 100% rename from tests/reference/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java rename to tests/multiversion/jsonrpc/src/test/java/org/a2aproject/sdk/tests/multiversion/jsonrpc/TestIdentityProvider.java diff --git a/tests/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties b/tests/multiversion/jsonrpc/src/test/resources/a2a-requesthandler-test.properties similarity index 100% rename from tests/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties rename to tests/multiversion/jsonrpc/src/test/resources/a2a-requesthandler-test.properties diff --git a/tests/reference/jsonrpc/src/test/resources/application.properties b/tests/multiversion/jsonrpc/src/test/resources/application.properties similarity index 100% rename from tests/reference/jsonrpc/src/test/resources/application.properties rename to tests/multiversion/jsonrpc/src/test/resources/application.properties diff --git a/tests/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties b/tests/multiversion/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties similarity index 100% rename from tests/reference/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties rename to tests/multiversion/jsonrpc/src/test/resources/compat-0.3-requesthandler-test.properties diff --git a/tests/reference/rest/pom.xml b/tests/multiversion/rest/pom.xml similarity index 100% rename from tests/reference/rest/pom.xml rename to tests/multiversion/rest/pom.xml diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java similarity index 100% rename from tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java rename to tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/A2ATestRoutes.java diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java similarity index 100% rename from tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java rename to tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/AuthTestProfile.java diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java similarity index 100% rename from tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java rename to tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestTest.java diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java similarity index 100% rename from tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java rename to tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersionRestWithAuthTest.java diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java similarity index 100% rename from tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java rename to tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestTest.java diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java similarity index 100% rename from tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java rename to tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java diff --git a/tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java similarity index 100% rename from tests/reference/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java rename to tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/TestIdentityProvider.java diff --git a/tests/reference/rest/src/test/resources/a2a-requesthandler-test.properties b/tests/multiversion/rest/src/test/resources/a2a-requesthandler-test.properties similarity index 100% rename from tests/reference/rest/src/test/resources/a2a-requesthandler-test.properties rename to tests/multiversion/rest/src/test/resources/a2a-requesthandler-test.properties diff --git a/tests/reference/rest/src/test/resources/application.properties b/tests/multiversion/rest/src/test/resources/application.properties similarity index 100% rename from tests/reference/rest/src/test/resources/application.properties rename to tests/multiversion/rest/src/test/resources/application.properties diff --git a/tests/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties b/tests/multiversion/rest/src/test/resources/compat-0.3-requesthandler-test.properties similarity index 100% rename from tests/reference/rest/src/test/resources/compat-0.3-requesthandler-test.properties rename to tests/multiversion/rest/src/test/resources/compat-0.3-requesthandler-test.properties From 02c58edaf41855a1f9428bf37a744f24b53c9689 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 15 May 2026 09:30:14 +0100 Subject: [PATCH 169/192] feat: add version-aware push notification support (#857) * feat: add version-aware push notification support The protocol version used when creating a TaskPushNotificationConfig dictates the wire format of subsequent push notifications. v0.3 configs receive plain Task payloads; v1.0 configs receive StreamResponse-wrapped events. Key changes: - PushNotificationPayloadFormatter SPI for version-specific serialization - Protocol version tracked in PushNotificationConfigStore alongside configs - BasePushNotificationSender resolves formatter per config at dispatch time - JPA store persists protocol_version column Co-Authored-By: Claude Opus 4.6 * Review fixes * Review fixes * Update docs with pushnotification mechanism, and use constant for '0.3' in code * Review fix * Pull in latest TCK tests --------- Co-authored-by: Claude Opus 4.6 --- .claude/architecture/compatibility_0.3.md | 18 +- .github/workflows/run-tck.yml | 2 +- README.md | 6 +- .../apps/quarkus/A2AServerRoutes_v0_3.java | 3 +- .../apps/quarkus/CallContextFactory_v0_3.java | 7 + .../rest/quarkus/A2AServerRoutes_v0_3.java | 3 +- .../rest/quarkus/CallContextFactory_v0_3.java | 7 + .../compat03/conversion/A2AProtocol_v0_3.java | 9 + ...PushNotificationPayloadFormatter_v0_3.java | 44 ++++ .../AbstractA2ARequestHandlerTest_v0_3.java | 4 +- ...otificationPayloadFormatter_v0_3_Test.java | 94 ++++++++ .../grpc/handler/CallContextFactory_v0_3.java | 4 + .../grpc/handler/GrpcHandler_v0_3.java | 3 +- .../grpc/handler/GrpcHandler_v0_3_Test.java | 3 +- .../handler/JSONRPCHandler_v0_3_Test.java | 3 +- .../rest/handler/RestHandler_v0_3_Test.java | 3 +- ...paDatabasePushNotificationConfigStore.java | 34 ++- .../jpa/JpaPushNotificationConfig.java | 17 +- ...otificationConfigStoreIntegrationTest.java | 2 +- .../JpaPushNotificationConfigStoreTest.java | 6 +- .../jpa/MockPushNotificationSender.java | 2 +- .../core/ReplicatedQueueManagerTest.java | 2 +- .../server/events/MainEventBusProcessor.java | 24 +- .../DefaultRequestHandler.java | 13 +- .../tasks/BasePushNotificationSender.java | 87 +++++-- .../InMemoryPushNotificationConfigStore.java | 30 ++- .../tasks/PushNotificationConfigStore.java | 45 ++++ .../PushNotificationPayloadFormatter.java | 12 + .../server/tasks/PushNotificationSender.java | 36 +-- .../sdk/server/tasks/TaskManager.java | 38 ++- .../sdk/server/events/EventConsumerTest.java | 2 +- .../sdk/server/events/EventQueueTest.java | 2 +- .../events/InMemoryQueueManagerTest.java | 2 +- .../MainEventBusProcessorExceptionTest.java | 2 +- .../AbstractA2ARequestHandlerTest.java | 2 +- .../DefaultRequestHandlerTest.java | 219 +++++++++++++++++- .../sdk/server/tasks/AgentEmitterTest.java | 2 +- ...MemoryPushNotificationConfigStoreTest.java | 44 +++- .../tasks/PushNotificationSenderTest.java | 84 ++++++- .../server/tasks/ResultAggregatorTest.java | 10 +- .../server/tasks/TaskManagerSnapshotTest.java | 75 ++++++ 41 files changed, 907 insertions(+), 98 deletions(-) create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/A2AProtocol_v0_3.java create mode 100644 compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/PushNotificationPayloadFormatter_v0_3.java create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/PushNotificationPayloadFormatter_v0_3_Test.java create mode 100644 server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationPayloadFormatter.java create mode 100644 server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerSnapshotTest.java diff --git a/.claude/architecture/compatibility_0.3.md b/.claude/architecture/compatibility_0.3.md index d6430724d..8347a2769 100644 --- a/.claude/architecture/compatibility_0.3.md +++ b/.claude/architecture/compatibility_0.3.md @@ -168,6 +168,18 @@ These fields coexist alongside the v1.0 `supportedInterfaces` field. v1.0 client `Legacy_0_3_AgentInterface` is a separate record from `AgentInterface` because they serialize to different JSON field names (`transport`/`url` vs `protocolBinding`/`url`/`tenant`). +### Version-Aware Push Notifications + +Push notification payloads are formatted according to the protocol version used when the push notification configuration was registered. The v0.3 transport handlers pass `A2AProtocol_v0_3.PROTOCOL_VERSION` when constructing the `ServerCallContext`, which propagates through to `PushNotificationConfigStore.setInfo()`. When a notification is later sent: + +1. `BasePushNotificationSender` retrieves the protocol version stored alongside each push notification configuration +2. It looks up a `PushNotificationPayloadFormatter` matching that version (discovered via CDI) +3. The formatter serializes the payload in the appropriate wire format: + - **v0.3** (`PushNotificationPayloadFormatter_v0_3`): sends a v0.3 `Task` JSON object, skipping `Message` events (not supported in v0.3 push notifications) + - **v1.0** (default): sends a `StreamResponse` wrapper containing the event + +If no protocol version is stored (e.g., for configurations created before this feature), the version defaults to `AgentInterface.CURRENT_PROTOCOL_VERSION` (`"1.0"`). + --- ## Module Structure @@ -436,7 +448,7 @@ AgentCard card = // ... fetch agent card from /.well-known/agent-card.json // Find the v0.3 interface from the agent card AgentInterface v03Interface = card.supportedInterfaces().stream() - .filter(iface -> "0.3".equals(iface.protocolVersion())) + .filter(iface -> A2AProtocol_v0_3.PROTOCOL_VERSION.equals(iface.protocolVersion())) .findFirst() .orElseThrow(); @@ -536,10 +548,10 @@ For JSON-RPC and REST, multi-version convenience modules are also available that ## Status -The v0.3 compatibility layer is fully implemented: spec types, gRPC generation, conversion layer, all three transport handlers (JSON-RPC, gRPC, REST), client API and transports, reference servers, multi-version deployment, test infrastructure, 125+ integration tests, and TCK module are all in place. +The v0.3 compatibility layer is fully implemented: spec types, gRPC generation, conversion layer, all three transport handlers (JSON-RPC, gRPC, REST), client API and transports, reference servers, multi-version deployment, version-aware push notifications, test infrastructure, 125+ integration tests, and TCK module are all in place. 🔲 **Outstanding:** -- Push notification test porting (requires TestHttpClient; version-aware push notifications in PR #857) +- Push notification test porting (requires TestHttpClient) - Test metadata classes (classpath scanning) - Replace FQNs with imports (97 occurrences in 34 files) - Unify AgentCard producers across reference modules diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index 18bdf29e9..4ad20c420 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -12,7 +12,7 @@ on: env: # Tag/branch of the TCK TCK_VERSION: 1.0-dev - TCK_VERSION_0_3: 0.3.0.beta4 + TCK_VERSION_0_3: 0.3.x # Tells uv to not need a venv, and instead use system UV_SYSTEM_PYTHON: 1 SUT_URL: http://localhost:9999 diff --git a/README.md b/README.md index 25bb8813d..ac751cc98 100644 --- a/README.md +++ b/README.md @@ -373,6 +373,10 @@ The two interface lists serve different clients: - `additionalInterfaces` — used by **v0.3 clients** to discover endpoints (uses `Legacy_0_3_AgentInterface` with v0.3 field names: `transport`/`url`) - `url` and `preferredTransport` — top-level fields that v0.3 clients use to discover the primary endpoint +#### Push Notification Behavior + +Push notification payloads are automatically formatted to match the protocol version used when the push notification configuration was registered. When a v0.3 client registers a push notification configuration (via any transport), the server records the protocol version alongside the configuration. When a notification is later sent to that webhook, the payload is formatted as a v0.3 Task object. Configurations registered by v1.0 clients receive v1.0 `StreamResponse` payloads as usual. This happens transparently — no additional configuration is needed beyond adding the compat reference module. + ## A2A Client The A2A Java SDK provides a Java client implementation of the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/), allowing communication with A2A servers. The Java client implementation supports the following transports: @@ -776,7 +780,7 @@ AgentCard card = new A2ACardResolver("http://localhost:1234").getAgentCard(); // Find the v0.3 interface from the agent card AgentInterface v03Interface = card.supportedInterfaces().stream() - .filter(iface -> "0.3".equals(iface.protocolVersion())) + .filter(iface -> A2AProtocol_v0_3.PROTOCOL_VERSION.equals(iface.protocolVersion())) .findFirst() .orElseThrow(); diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java index 5e268ca9c..56ffc021f 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -33,6 +33,7 @@ import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.BodyHandler; import org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3; +import org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3; import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; @@ -327,7 +328,7 @@ public String getUsername() { List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders_v0_3.X_A2A_EXTENSIONS); Set requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues); - return new ServerCallContext(user, state, requestedExtensions); + return new ServerCallContext(user, state, requestedExtensions, A2AProtocol_v0_3.PROTOCOL_VERSION); } else { CallContextFactory_v0_3 builder = callContextFactory.get(); return builder.build(rc); diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java index f00bce4db..b2bf3ef27 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java @@ -3,6 +3,13 @@ import org.a2aproject.sdk.server.ServerCallContext; import io.vertx.ext.web.RoutingContext; +/** + * Factory interface for creating ServerCallContext from a Vert.x RoutingContext. + * + *

            Implementations MUST pass {@link org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3#PROTOCOL_VERSION} + * as the protocol version when constructing {@link ServerCallContext} so that push notification + * payloads are formatted correctly.

            + */ public interface CallContextFactory_v0_3 { ServerCallContext build(RoutingContext rc); } diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java index bc76641cf..505685ed5 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -33,6 +33,7 @@ import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.BodyHandler; import org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3; +import org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3; import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3; import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3; import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3; @@ -431,7 +432,7 @@ public String getUsername() { List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders_v0_3.X_A2A_EXTENSIONS); Set requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues); - return new ServerCallContext(user, state, requestedExtensions); + return new ServerCallContext(user, state, requestedExtensions, A2AProtocol_v0_3.PROTOCOL_VERSION); } else { CallContextFactory_v0_3 builder = callContextFactory.get(); return builder.build(rc); diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java index a1f3922c2..b9bc05697 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java @@ -3,6 +3,13 @@ import org.a2aproject.sdk.server.ServerCallContext; import io.vertx.ext.web.RoutingContext; +/** + * Factory interface for creating ServerCallContext from a Vert.x RoutingContext. + * + *

            Implementations MUST pass {@link org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3#PROTOCOL_VERSION} + * as the protocol version when constructing {@link ServerCallContext} so that push notification + * payloads are formatted correctly.

            + */ public interface CallContextFactory_v0_3 { ServerCallContext build(RoutingContext rc); } diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/A2AProtocol_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/A2AProtocol_v0_3.java new file mode 100644 index 000000000..d7c61edf5 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/A2AProtocol_v0_3.java @@ -0,0 +1,9 @@ +package org.a2aproject.sdk.compat03.conversion; + +public final class A2AProtocol_v0_3 { + + public static final String PROTOCOL_VERSION = "0.3"; + + private A2AProtocol_v0_3() { + } +} diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/PushNotificationPayloadFormatter_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/PushNotificationPayloadFormatter_v0_3.java new file mode 100644 index 000000000..3c91c0e92 --- /dev/null +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/PushNotificationPayloadFormatter_v0_3.java @@ -0,0 +1,44 @@ +package org.a2aproject.sdk.compat03.conversion; + +import jakarta.enterprise.context.ApplicationScoped; + +import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; +import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3; +import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3; +import org.a2aproject.sdk.compat03.spec.Task_v0_3; +import org.a2aproject.sdk.server.tasks.PushNotificationPayloadFormatter; +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ApplicationScoped +public class PushNotificationPayloadFormatter_v0_3 implements PushNotificationPayloadFormatter { + + private static final Logger LOGGER = LoggerFactory.getLogger(PushNotificationPayloadFormatter_v0_3.class); + + @Override + public String targetVersion() { + return A2AProtocol_v0_3.PROTOCOL_VERSION; + } + + @Override + public @Nullable String formatPayload(StreamingEventKind event, @Nullable Task taskSnapshot) { + if (event instanceof Message) { + return null; + } + if (taskSnapshot == null) { + LOGGER.warn("Cannot format v0.3 push notification: no task snapshot available"); + return null; + } + Task_v0_3 v03Task = TaskMapper_v0_3.INSTANCE.fromV10(taskSnapshot); + try { + return JsonUtil_v0_3.toJson(v03Task); + } catch (JsonProcessingException_v0_3 e) { + LOGGER.error("Failed to serialize v0.3 task for push notification", e); + return null; + } + } +} diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java index 088ae9d8f..3862b4ac9 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2ARequestHandlerTest_v0_3.java @@ -84,7 +84,7 @@ public abstract class AbstractA2ARequestHandlerTest_v0_3 { .parts(new TextPart_v0_3("test message")) .build(); - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; // V1.0 backend infrastructure protected AgentExecutor agentExecutor; @@ -183,7 +183,7 @@ protected static AgentCard_v0_3 createAgentCard(boolean streaming, boolean pushN .defaultOutputModes(new ArrayList<>()) .preferredTransport("jsonrpc") .skills(new ArrayList<>()) - .protocolVersion("0.3") + .protocolVersion(A2AProtocol_v0_3.PROTOCOL_VERSION) .build(); } diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/PushNotificationPayloadFormatter_v0_3_Test.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/PushNotificationPayloadFormatter_v0_3_Test.java new file mode 100644 index 000000000..22bb542dc --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/PushNotificationPayloadFormatter_v0_3_Test.java @@ -0,0 +1,94 @@ +package org.a2aproject.sdk.compat03.conversion; + +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 static org.junit.jupiter.api.Assertions.assertTrue; + +import org.a2aproject.sdk.spec.Message; +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.a2aproject.sdk.spec.TextPart; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class PushNotificationPayloadFormatter_v0_3_Test { + + private PushNotificationPayloadFormatter_v0_3 formatter; + + @BeforeEach + void setUp() { + formatter = new PushNotificationPayloadFormatter_v0_3(); + } + + @Test + void targetVersionIs03() { + assertEquals(A2AProtocol_v0_3.PROTOCOL_VERSION, formatter.targetVersion()); + } + + @Test + void formatsTaskEventAsV03Task() { + Task task = Task.builder() + .id("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) + .build(); + + String payload = formatter.formatPayload(task, task); + + assertNotNull(payload); + assertTrue(payload.contains("\"kind\":\"task\"")); + assertTrue(payload.contains("\"id\":\"t1\"")); + assertTrue(payload.contains("\"status\"")); + } + + @Test + void formatsStatusUpdateUsingTaskSnapshot() { + Task snapshot = Task.builder() + .id("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) + .build(); + + TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() + .taskId("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) + .build(); + + String payload = formatter.formatPayload(event, snapshot); + + assertNotNull(payload); + assertTrue(payload.contains("\"kind\":\"task\"")); + assertTrue(payload.contains("\"id\":\"t1\"")); + } + + @Test + void skipsMessageEvents() { + Task snapshot = Task.builder() + .id("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) + .build(); + + Message message = Message.builder() + .messageId("m1") + .role(Message.Role.ROLE_AGENT) + .parts(new TextPart("hello")) + .build(); + + String payload = formatter.formatPayload(message, snapshot); + + assertNull(payload); + } + + @Test + void returnsNullWhenSnapshotIsNull() { + Task task = Task.builder() + .id("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) + .build(); + + String payload = formatter.formatPayload(task, null); + + assertNull(payload); + } +} diff --git a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/CallContextFactory_v0_3.java b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/CallContextFactory_v0_3.java index c5dc184cc..829c92d96 100644 --- a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/CallContextFactory_v0_3.java +++ b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/CallContextFactory_v0_3.java @@ -6,6 +6,10 @@ /** * Factory interface for creating ServerCallContext from gRPC StreamObserver. * Implementations can provide custom context creation logic. + * + *

            Implementations MUST pass {@link org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3#PROTOCOL_VERSION} + * as the protocol version when constructing {@link ServerCallContext} so that push notification + * payloads are formatted correctly.

            */ public interface CallContextFactory_v0_3 { ServerCallContext create(StreamObserver responseObserver); diff --git a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java index 12694af91..2f3795a81 100644 --- a/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java +++ b/compat-0.3/transport/grpc/src/main/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3.java @@ -12,6 +12,7 @@ import java.util.concurrent.Flow; import com.google.protobuf.Empty; +import org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3; import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; import org.a2aproject.sdk.compat03.conversion.ErrorConverter_v0_3; import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; @@ -363,7 +364,7 @@ private ServerCallContext createCallContext(StreamObserver responseObserv Map state = new HashMap<>(); state.put("grpc_response_observer", responseObserver); Set requestedExtensions = new HashSet<>(); - return new ServerCallContext(user, state, requestedExtensions); + return new ServerCallContext(user, state, requestedExtensions, A2AProtocol_v0_3.PROTOCOL_VERSION); } else { return factory.create(responseObserver); } diff --git a/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java b/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java index 5a422c3bd..a9703878a 100644 --- a/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java +++ b/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.concurrent.TimeUnit; +import org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2ARequestHandlerTest_v0_3; import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; @@ -65,7 +66,7 @@ public class GrpcHandler_v0_3_Test extends AbstractA2ARequestHandlerTest_v0_3 { .build(); private final ServerCallContext callContext = new ServerCallContext( - UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>(), A2AProtocol_v0_3.PROTOCOL_VERSION); // ======================================== // GetTask Tests diff --git a/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java index c031e8a4f..93f01d2ea 100644 --- a/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java +++ b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java @@ -19,6 +19,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2ARequestHandlerTest_v0_3; import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskArtifactUpdateEventMapper_v0_3; @@ -85,7 +86,7 @@ public class JSONRPCHandler_v0_3_Test extends AbstractA2ARequestHandlerTest_v0_3 { private final ServerCallContext callContext = new ServerCallContext( - UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>(), A2AProtocol_v0_3.PROTOCOL_VERSION); // ======================================== // GetTask Tests diff --git a/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java b/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java index a76f2259d..2b195a47f 100644 --- a/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java +++ b/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java @@ -3,6 +3,7 @@ import java.util.HashSet; import java.util.Map; +import org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3; import org.a2aproject.sdk.compat03.conversion.AbstractA2ARequestHandlerTest_v0_3; import org.a2aproject.sdk.compat03.conversion.Convert_v0_3_To10RequestHandler; import org.a2aproject.sdk.compat03.conversion.mappers.domain.TaskMapper_v0_3; @@ -32,7 +33,7 @@ public class RestHandler_v0_3_Test extends AbstractA2ARequestHandlerTest_v0_3 { private final ServerCallContext callContext = new ServerCallContext( - UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); + UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>(), A2AProtocol_v0_3.PROTOCOL_VERSION); // ======================================== // GetTask Tests diff --git a/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java b/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java index 43adeac31..28f476d2a 100644 --- a/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java +++ b/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java @@ -18,6 +18,7 @@ import org.a2aproject.sdk.util.Assert; import org.a2aproject.sdk.util.PageToken; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,6 +37,12 @@ public class JpaDatabasePushNotificationConfigStore implements PushNotificationC @Transactional @Override public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificationConfig) { + return setInfo(notificationConfig, null); + } + + @Transactional + @Override + public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificationConfig, @Nullable String protocolVersion) { String taskId = Assert.checkNotNullParam("taskId", notificationConfig.taskId()); // Ensure config has an ID - default to taskId if not provided (mirroring InMemoryPushNotificationConfigStore behavior) if (notificationConfig.id().isEmpty()) { @@ -44,6 +51,7 @@ public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificatio notificationConfig = TaskPushNotificationConfig.builder(notificationConfig).id(taskId).build(); } + String resolvedVersion = PushNotificationConfigStore.resolveProtocolVersion(protocolVersion); LOGGER.debug("Saving PushNotificationConfig for Task '{}' with ID: {}", taskId, notificationConfig.id()); try { TaskConfigId configId = new TaskConfigId(taskId, notificationConfig.id()); @@ -54,11 +62,12 @@ public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificatio if (existingJpaConfig != null) { // Update existing entity existingJpaConfig.setConfig(notificationConfig); + existingJpaConfig.setProtocolVersion(resolvedVersion); LOGGER.debug("Updated existing PushNotificationConfig for Task '{}' with ID: {}", taskId, notificationConfig.id()); } else { // Create new entity - JpaPushNotificationConfig jpaConfig = JpaPushNotificationConfig.createFromConfig(taskId, notificationConfig); + JpaPushNotificationConfig jpaConfig = JpaPushNotificationConfig.createFromConfig(taskId, notificationConfig, resolvedVersion); em.persist(jpaConfig); LOGGER.debug("Persisted new PushNotificationConfig for Task '{}' with ID: {}", taskId, notificationConfig.id()); @@ -164,4 +173,27 @@ public void deleteInfo(String taskId, String configId) { } } + @Transactional + @Override + public String getProtocolVersion(String taskId, String configId) { + JpaPushNotificationConfig jpaConfig = em.find(JpaPushNotificationConfig.class, + new TaskConfigId(taskId, configId)); + return jpaConfig != null ? jpaConfig.getProtocolVersion() : PushNotificationConfigStore.resolveProtocolVersion(null); + } + + @Transactional + @Override + public java.util.Map getProtocolVersions(String taskId) { + List results = em.createQuery( + "SELECT c.id.configId, c.protocolVersion FROM JpaPushNotificationConfig c " + + "WHERE c.id.taskId = :taskId AND c.protocolVersion IS NOT NULL", Object[].class) + .setParameter("taskId", taskId) + .getResultList(); + java.util.Map versions = new java.util.HashMap<>(); + for (Object[] row : results) { + versions.put((String) row[0], (String) row[1]); + } + return versions; + } + } diff --git a/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java b/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java index 5d513c0f8..8867c50f2 100644 --- a/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java +++ b/extras/push-notification-config-store-database-jpa/src/main/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java @@ -9,7 +9,10 @@ import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; +import org.a2aproject.sdk.server.tasks.PushNotificationConfigStore; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.jspecify.annotations.Nullable; + import java.time.Instant; @Entity @@ -21,6 +24,9 @@ public class JpaPushNotificationConfig { @Column(name = "task_data", columnDefinition = "TEXT", nullable = false) private String configJson; + @Column(name = "protocol_version") + private String protocolVersion; + @Column(name = "created_at") private Instant createdAt; @@ -79,11 +85,20 @@ public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - static JpaPushNotificationConfig createFromConfig(String taskId, TaskPushNotificationConfig config) throws JsonProcessingException { + public String getProtocolVersion() { + return PushNotificationConfigStore.resolveProtocolVersion(protocolVersion); + } + + public void setProtocolVersion(String protocolVersion) { + this.protocolVersion = protocolVersion; + } + + static JpaPushNotificationConfig createFromConfig(String taskId, TaskPushNotificationConfig config, @Nullable String protocolVersion) throws JsonProcessingException { String json = JsonUtil.toJson(config); JpaPushNotificationConfig jpaPushNotificationConfig = new JpaPushNotificationConfig(new TaskConfigId(taskId, config.id()), json); jpaPushNotificationConfig.config = config; + jpaPushNotificationConfig.protocolVersion = protocolVersion; return jpaPushNotificationConfig; } } diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java index 3fc330215..4ff600268 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java @@ -91,7 +91,7 @@ public void testDirectNotificationTrigger() { .build(); // Directly trigger the mock - mockPushNotificationSender.sendNotification(testTask); + mockPushNotificationSender.sendNotification(testTask, null); // Verify it was captured Queue captured = mockPushNotificationSender.getCapturedTasks(); diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java index 1ae2bfe9d..057dc304a 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java @@ -249,7 +249,7 @@ public void testSendNotificationSuccess() throws Exception { when(mockPostBuilder.post()).thenReturn(mockHttpResponse); when(mockHttpResponse.success()).thenReturn(true); - notificationSender.sendNotification(task); + notificationSender.sendNotification(task, null); // Verify HTTP client was called ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); @@ -281,7 +281,7 @@ public void testSendNotificationWithToken() throws Exception { when(mockPostBuilder.post()).thenReturn(mockHttpResponse); when(mockHttpResponse.success()).thenReturn(true); - notificationSender.sendNotification(task); + notificationSender.sendNotification(task, null); // TODO: Once token authentication is implemented, verify that: // 1. The token is included in request headers (e.g., X-A2A-Notification-Token) @@ -307,7 +307,7 @@ public void testSendNotificationNoConfig() throws Exception { String taskId = "task_send_no_config"; Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - notificationSender.sendNotification(task); + notificationSender.sendNotification(task, null); // Verify HTTP client was never called verify(mockHttpClient, never()).createPost(); diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java index 7e0edca46..d431f934c 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/org/a2aproject/sdk/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java @@ -23,7 +23,7 @@ public class MockPushNotificationSender implements PushNotificationSender { private final Queue capturedEvents = new ConcurrentLinkedQueue<>(); @Override - public void sendNotification(StreamingEventKind event) { + public void sendNotification(StreamingEventKind event, Task taskSnapshot) { capturedEvents.add(event); } diff --git a/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java b/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java index 8998c2195..926b9497d 100644 --- a/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java +++ b/extras/queue-manager-replicated/core/src/test/java/org/a2aproject/sdk/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java @@ -44,7 +44,7 @@ class ReplicatedQueueManagerTest { private StreamingEventKind testEvent; private MainEventBus mainEventBus; private MainEventBusProcessor mainEventBusProcessor; - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; @BeforeEach void setUp() { diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java index 9bb9b9c26..eab991ff7 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/MainEventBusProcessor.java @@ -1,6 +1,7 @@ package org.a2aproject.sdk.server.events; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; import jakarta.annotation.Nullable; import jakarta.annotation.PostConstruct; @@ -16,8 +17,8 @@ import org.a2aproject.sdk.spec.A2AError; import org.a2aproject.sdk.spec.Event; import org.a2aproject.sdk.spec.InternalError; -import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.slf4j.Logger; @@ -58,6 +59,8 @@ public class MainEventBusProcessor implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(MainEventBusProcessor.class); + private record UpdateResult(boolean isFinal, @Nullable Task taskSnapshot) {} + /** * Callback for testing synchronization with async event processing. * Default is NOOP to avoid null checks in production code. @@ -200,13 +203,15 @@ private void processEvent(MainEventBusContext context) { taskId, event.getClass().getSimpleName()); Event eventToDistribute = null; + UpdateResult updateResult = null; boolean isReplicated = context.eventQueueItem().isReplicated(); try { // Step 1: Update TaskStore FIRST (persistence before clients see it) // If this throws, we distribute an error to ensure "persist before client visibility" try { - boolean isFinal = updateTaskStore(taskId, event, isReplicated); + updateResult = updateTaskStore(taskId, event, isReplicated); + boolean isFinal = updateResult.isFinal(); eventToDistribute = event; // Success - distribute original event @@ -237,9 +242,9 @@ private void processEvent(MainEventBusContext context) { // Skip push notifications for replicated events to avoid duplicate notifications in multi-instance deployments // Push notifications are sent for all StreamingEventKind events (Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent) // per A2A spec section 4.3.3 - if (!isReplicated && event instanceof StreamingEventKind streamingEvent) { + if (!isReplicated && eventToDistribute == event && event instanceof StreamingEventKind streamingEvent) { // Send the streaming event directly - it will be wrapped in StreamResponse format by PushNotificationSender - sendPushNotification(taskId, streamingEvent); + sendPushNotification(taskId, streamingEvent, updateResult != null ? updateResult.taskSnapshot() : null); } // Step 3: Then distribute to ChildQueues (clients see either event or error AFTER persistence attempt) @@ -293,7 +298,7 @@ private void processEvent(MainEventBusContext context) { * @return true if the task reached a final state, false otherwise * @throws InternalError if persistence fails */ - private boolean updateTaskStore(String taskId, Event event, boolean isReplicated) throws InternalError { + private UpdateResult updateTaskStore(String taskId, Event event, boolean isReplicated) throws InternalError { try { // Extract contextId from event (all relevant events have it) String contextId = extractContextId(event); @@ -302,10 +307,11 @@ private boolean updateTaskStore(String taskId, Event event, boolean isReplicated TaskManager taskManager = new TaskManager(taskId, contextId, taskStore, null); // Use TaskManager.process() - handles all event types with existing logic - boolean isFinal = taskManager.process(event, isReplicated); + AtomicReference taskSnapshot = new AtomicReference<>(); + boolean isFinal = taskManager.process(event, isReplicated, taskSnapshot); LOGGER.debug("TaskStore updated via TaskManager.process() for task {}: {} (final: {}, replicated: {})", taskId, event.getClass().getSimpleName(), isFinal, isReplicated); - return isFinal; + return new UpdateResult(isFinal, taskSnapshot.get()); } catch (TaskSerializationException e) { // Data corruption or schema mismatch - ALWAYS permanent @@ -362,12 +368,12 @@ private boolean updateTaskStore(String taskId, Event event, boolean isReplicated * @param taskId the task ID * @param event the streaming event to send (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent) */ - private void sendPushNotification(String taskId, StreamingEventKind event) { + private void sendPushNotification(String taskId, StreamingEventKind event, @Nullable Task taskSnapshot) { Runnable pushTask = () -> { try { if (event != null) { LOGGER.debug("Sending push notification for task {}", taskId); - pushSender.sendNotification(event); + pushSender.sendNotification(event, taskSnapshot); } else { LOGGER.debug("Skipping push notification - event is null for task {}", taskId); } diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java index b81cc22c7..d2c3aa028 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandler.java @@ -504,8 +504,9 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte if (mss.task() == null && kind instanceof Task createdTask && shouldAddPushInfo(params)) { LOGGER.debug("Storing push notification config for new task {} (original taskId from params: {})", createdTask.id(), params.message().taskId()); + String version = context != null ? context.getRequestedProtocolVersion() : null; pushConfigStore.setInfo(TaskPushNotificationConfig.builder(params.configuration().taskPushNotificationConfig()) - .taskId(createdTask.id()).build()); + .taskId(createdTask.id()).build(), version); } // Check if task requires immediate return (AUTH_REQUIRED) @@ -662,8 +663,9 @@ public Flow.Publisher onMessageSendStream( Objects.requireNonNull(taskId.get(), "taskId was null"); LOGGER.debug("Storing push notification config for new streaming task {} EARLY (original taskId from params: {})", taskId.get(), params.message().taskId()); + String version = context != null ? context.getRequestedProtocolVersion() : null; pushConfigStore.setInfo(TaskPushNotificationConfig.builder(params.configuration().taskPushNotificationConfig()) - .taskId(taskId.get()).build()); + .taskId(taskId.get()).build(), version); } ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); @@ -796,7 +798,9 @@ public TaskPushNotificationConfig onCreateTaskPushNotificationConfig( throw new TaskNotFoundError(); } - return pushConfigStore.setInfo(params); + String version = context != null ? context.getRequestedProtocolVersion() : null; + TaskPushNotificationConfig result = pushConfigStore.setInfo(params, version); + return result; } @Override @@ -1051,8 +1055,9 @@ private MessageSendSetup initMessageSend(MessageSendParams params, ServerCallCon if (pushConfigStore != null && params.configuration() != null && params.configuration().taskPushNotificationConfig() != null) { LOGGER.debug("Adding push info"); + String version = context != null ? context.getRequestedProtocolVersion() : null; pushConfigStore.setInfo(TaskPushNotificationConfig.builder(params.configuration().taskPushNotificationConfig()) - .taskId(task.id()).build()); + .taskId(task.id()).build(), version); } requestContext = requestContextBuilder.get() diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java index 53f1a38d3..5605c9001 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/BasePushNotificationSender.java @@ -4,17 +4,18 @@ import static org.a2aproject.sdk.client.http.A2AHttpClient.CONTENT_TYPE; import static org.a2aproject.sdk.common.A2AHeaders.X_A2A_NOTIFICATION_TOKEN; -import jakarta.annotation.Nullable; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; - import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.jsonrpc.common.json.JsonUtil; @@ -26,6 +27,7 @@ import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +42,7 @@ public class BasePushNotificationSender implements PushNotificationSender { // final, is not proxyable in all runtimes private A2AHttpClient httpClient; private PushNotificationConfigStore configStore; + private Map formattersByVersion; /** @@ -52,21 +55,44 @@ protected BasePushNotificationSender() { // For CDI proxy creation this.httpClient = null; this.configStore = null; + this.formattersByVersion = Map.of(); } - @Inject public BasePushNotificationSender(PushNotificationConfigStore configStore) { this.httpClient = A2AHttpClientFactory.create(); this.configStore = configStore; + this.formattersByVersion = Map.of(); + } + + @Inject + public BasePushNotificationSender(PushNotificationConfigStore configStore, + Instance formatters) { + this.httpClient = A2AHttpClientFactory.create(); + this.configStore = configStore; + this.formattersByVersion = new HashMap<>(); + for (PushNotificationPayloadFormatter f : formatters) { + this.formattersByVersion.put(f.targetVersion(), f); + } } public BasePushNotificationSender(PushNotificationConfigStore configStore, A2AHttpClient httpClient) { this.configStore = configStore; this.httpClient = httpClient; + this.formattersByVersion = Map.of(); + } + + public BasePushNotificationSender(PushNotificationConfigStore configStore, A2AHttpClient httpClient, + List formatters) { + this.configStore = configStore; + this.httpClient = httpClient; + this.formattersByVersion = new HashMap<>(); + for (PushNotificationPayloadFormatter f : formatters) { + formattersByVersion.put(f.targetVersion(), f); + } } @Override - public void sendNotification(StreamingEventKind event) { + public void sendNotification(StreamingEventKind event, @Nullable Task taskSnapshot) { String taskId = extractTaskId(event); if (taskId == null) { LOGGER.warn("Cannot send push notification: event does not contain taskId"); @@ -84,9 +110,11 @@ public void sendNotification(StreamingEventKind event) { nextPageToken = pageResult.nextPageToken(); } while (nextPageToken != null); + Map versionsByConfigId = configStore.getProtocolVersions(taskId); + List> dispatchResults = configs .stream() - .map(pushConfig -> dispatch(event, pushConfig)) + .map(pushConfig -> dispatch(event, taskSnapshot, pushConfig, versionsByConfigId)) .toList(); CompletableFuture allFutures = CompletableFuture.allOf(dispatchResults.toArray(new CompletableFuture[0])); CompletableFuture dispatchResult = allFutures.thenApply(v -> dispatchResults.stream() @@ -123,14 +151,47 @@ public void sendNotification(StreamingEventKind event) { throw new IllegalStateException("Unknown StreamingEventKind: " + event); } - private CompletableFuture dispatch(StreamingEventKind event, TaskPushNotificationConfig pushInfo) { - return CompletableFuture.supplyAsync(() -> dispatchNotification(event, pushInfo)); + private CompletableFuture dispatch(StreamingEventKind event, + @Nullable Task taskSnapshot, + TaskPushNotificationConfig pushInfo, + Map versionsByConfigId) { + return CompletableFuture.supplyAsync(() -> dispatchNotification(event, taskSnapshot, pushInfo, versionsByConfigId)); } - private boolean dispatchNotification(StreamingEventKind event, TaskPushNotificationConfig pushInfo) { + private boolean dispatchNotification(StreamingEventKind event, + @Nullable Task taskSnapshot, + TaskPushNotificationConfig pushInfo, + Map versionsByConfigId) { String url = pushInfo.url(); String token = pushInfo.token(); + String version = versionsByConfigId.get(pushInfo.id()); + PushNotificationPayloadFormatter formatter = version != null + ? formattersByVersion.get(version) : null; + + String body; + if (formatter != null) { + try { + body = formatter.formatPayload(event, taskSnapshot); + } catch (Throwable throwable) { + LOGGER.error("Error formatting payload with {} formatter: {}", + version, throwable.getMessage(), throwable); + return false; + } + if (body == null) { + LOGGER.debug("Formatter for version {} returned null, skipping notification for {}", + version, url); + return true; + } + } else { + try { + body = JsonUtil.toJson(event); + } catch (Throwable throwable) { + LOGGER.error("Error serializing StreamingEventKind to JSON: {}", throwable.getMessage(), throwable); + return false; + } + } + A2AHttpClient.PostBuilder postBuilder = httpClient.createPost(); if (token != null && !token.isBlank()) { postBuilder.addHeader(X_A2A_NOTIFICATION_TOKEN, token); @@ -140,16 +201,6 @@ private boolean dispatchNotification(StreamingEventKind event, TaskPushNotificat pushInfo.authentication().scheme() + " " + pushInfo.authentication().credentials()); } - String body; - try { - // JsonUtil.toJson automatically wraps StreamingEventKind in StreamResponse format - // (task/message/statusUpdate/artifactUpdate) per A2A spec section 4.3.3 - body = JsonUtil.toJson(event); - } catch (Throwable throwable) { - LOGGER.error("Error serializing StreamingEventKind to JSON: {}", throwable.getMessage(), throwable); - return false; - } - try { postBuilder .url(url) diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStore.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStore.java index cd02cf5d6..0d239758f 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStore.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStore.java @@ -10,10 +10,11 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.a2aproject.sdk.util.Assert; import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * In-memory implementation of the PushNotificationConfigStore interface. @@ -24,6 +25,7 @@ public class InMemoryPushNotificationConfigStore implements PushNotificationConfigStore { private final Map> pushNotificationInfos = Collections.synchronizedMap(new HashMap<>()); + private final Map protocolVersions = Collections.synchronizedMap(new HashMap<>()); @Inject public InMemoryPushNotificationConfigStore() { @@ -52,6 +54,13 @@ public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificatio return notificationConfig; } + @Override + public TaskPushNotificationConfig setInfo(TaskPushNotificationConfig config, @Nullable String protocolVersion) { + TaskPushNotificationConfig result = setInfo(config); + protocolVersions.put(result.taskId() + ":" + result.id(), PushNotificationConfigStore.resolveProtocolVersion(protocolVersion)); + return result; + } + @Override public ListTaskPushNotificationConfigsResult getInfo(ListTaskPushNotificationConfigsParams params) { List configs = pushNotificationInfos.get(params.id()); @@ -106,8 +115,27 @@ public void deleteInfo(String taskId, String configId) { break; } } + protocolVersions.remove(taskId + ":" + configId); if (notificationConfigList.isEmpty()) { pushNotificationInfos.remove(taskId); } } + + @Override + public String getProtocolVersion(String taskId, String configId) { + String version = protocolVersions.get(taskId + ":" + configId); + return PushNotificationConfigStore.resolveProtocolVersion(version); + } + + @Override + public Map getProtocolVersions(String taskId) { + String prefix = taskId + ":"; + Map result = new HashMap<>(); + protocolVersions.forEach((key, version) -> { + if (key.startsWith(prefix)) { + result.put(key.substring(prefix.length()), version); + } + }); + return result; + } } diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationConfigStore.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationConfigStore.java index fd1460b9a..5d2bf3392 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationConfigStore.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationConfigStore.java @@ -3,6 +3,7 @@ import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; import org.a2aproject.sdk.spec.TaskPushNotificationConfig; +import org.jspecify.annotations.Nullable; /** * Interface for storing and retrieving push notification configurations for tasks. @@ -81,6 +82,29 @@ public interface PushNotificationConfigStore { */ TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificationConfig); + /** + * Sets or updates the push notification configuration for a task, along with the + * protocol version that registered it. + *

            + * This merged method ensures the protocol version is stored using the normalized + * config ID (after {@link #setInfo(TaskPushNotificationConfig)} applies defaults). + *

            + * + * @param notificationConfig the task push notification configuration + * @param protocolVersion the protocol version string, or null to use {@link org.a2aproject.sdk.spec.AgentInterface#CURRENT_PROTOCOL_VERSION} + * @return the potentially updated configuration (with ID set if it was null) + */ + default TaskPushNotificationConfig setInfo(TaskPushNotificationConfig notificationConfig, @Nullable String protocolVersion) { + return setInfo(notificationConfig); + } + + /** + * Resolves the protocol version, defaulting null to the current protocol version. + */ + static String resolveProtocolVersion(@Nullable String protocolVersion) { + return protocolVersion != null ? protocolVersion : org.a2aproject.sdk.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; + } + /** * Retrieves push notification configurations for a task with pagination support. *

            @@ -119,4 +143,25 @@ public interface PushNotificationConfigStore { */ void deleteInfo(String taskId, String configId); + /** + * Gets the protocol version associated with a push notification configuration. + * + * @param taskId the task ID + * @param configId the push notification configuration ID + * @return the protocol version string, defaults to the current protocol version if not set + */ + default String getProtocolVersion(String taskId, String configId) { + return resolveProtocolVersion(null); + } + + /** + * Gets all protocol versions for a task's push notification configurations in a single call. + * + * @param taskId the task ID + * @return a map of config ID to protocol version (only includes configs with a version set) + */ + default java.util.Map getProtocolVersions(String taskId) { + return java.util.Map.of(); + } + } diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationPayloadFormatter.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationPayloadFormatter.java new file mode 100644 index 000000000..6a75a96a7 --- /dev/null +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationPayloadFormatter.java @@ -0,0 +1,12 @@ +package org.a2aproject.sdk.server.tasks; + +import org.a2aproject.sdk.spec.StreamingEventKind; +import org.a2aproject.sdk.spec.Task; +import org.jspecify.annotations.Nullable; + +public interface PushNotificationPayloadFormatter { + + String targetVersion(); + + @Nullable String formatPayload(StreamingEventKind event, @Nullable Task taskSnapshot); +} diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationSender.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationSender.java index 304fed683..19d2886d0 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationSender.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/PushNotificationSender.java @@ -2,6 +2,7 @@ import org.a2aproject.sdk.spec.StreamingEventKind; import org.a2aproject.sdk.spec.Task; +import org.jspecify.annotations.Nullable; /** * Interface for delivering push notifications containing task state updates to external systems. @@ -28,8 +29,10 @@ * {@link BasePushNotificationSender} provides HTTP webhook delivery: *

              *
            • Retrieves webhook URLs from {@link PushNotificationConfigStore}
            • - *
            • Wraps events in StreamResponse format (per A2A spec section 4.3.3)
            • - *
            • Sends HTTP POST requests with StreamResponse JSON payload
            • + *
            • Formats payloads according to the protocol version stored with each configuration + * (v1.0 StreamResponse by default; version-specific formatters via + * {@link PushNotificationPayloadFormatter} SPI)
            • + *
            • Sends HTTP POST requests with the formatted JSON payload
            • *
            • Logs errors but doesn't fail the request
            • *
            * @@ -52,7 +55,7 @@ * KafkaProducer producer; * * @Override - * public void sendNotification(StreamingEventKind event) { + * public void sendNotification(StreamingEventKind event, Task taskSnapshot) { * String taskId = extractTaskId(event); * producer.send("task-updates", taskId, event); * } @@ -82,27 +85,34 @@ public interface PushNotificationSender { /** * Sends a push notification containing a streaming event. *

            - * Called after the event has been persisted to {@link TaskStore}. The event is wrapped - * in a StreamResponse format (per A2A spec section 4.3.3) with the appropriate oneof - * field set (task, message, statusUpdate, or artifactUpdate). - *

            + * Called after the event has been persisted to {@link TaskStore}. The payload format + * depends on the protocol version used to register the push notification configuration. + *
              + *
            • v1.0 (default): The event is wrapped in a StreamResponse format (per A2A spec section 4.3.3) + * with the appropriate oneof field set (task, message, statusUpdate, or artifactUpdate).
            • + *
            • v0.3: The payload is a v0.3 {@code Task} JSON object, using the provided {@code taskSnapshot}. + * {@code Message} events are skipped.
            • + *
            *

            * Retrieve push notification URLs or messaging configurations from * {@link PushNotificationConfigStore} using the task ID extracted from the event. *

            * Supported event types: *
              - *
            • {@link Task} - wrapped in StreamResponse.task
            • - *
            • {@link org.a2aproject.sdk.spec.Message} - wrapped in StreamResponse.message
            • - *
            • {@link org.a2aproject.sdk.spec.TaskStatusUpdateEvent} - wrapped in StreamResponse.statusUpdate
            • - *
            • {@link org.a2aproject.sdk.spec.TaskArtifactUpdateEvent} - wrapped in StreamResponse.artifactUpdate
            • + *
            • {@link Task}
            • + *
            • {@link org.a2aproject.sdk.spec.Message}
            • + *
            • {@link org.a2aproject.sdk.spec.TaskStatusUpdateEvent}
            • + *
            • {@link org.a2aproject.sdk.spec.TaskArtifactUpdateEvent}
            • *
            *

            * Error Handling: Log errors but don't throw exceptions. Notifications are * best-effort and should not fail the primary request. *

            * - * @param event the streaming event to send (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent) + * @param event the streaming event to send. + * @param taskSnapshot the current state of the task after the event has been applied. + * Used by formatters for older protocol versions that require + * the full task state in notifications. */ - void sendNotification(StreamingEventKind event); + void sendNotification(StreamingEventKind event, @Nullable Task taskSnapshot); } diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskManager.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskManager.java index 53c929c26..0bbd399b9 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskManager.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/TaskManager.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; import org.a2aproject.sdk.spec.A2AError; import org.a2aproject.sdk.spec.A2AServerException; @@ -62,12 +63,25 @@ public TaskManager(@Nullable String taskId, @Nullable String contextId, TaskStor } boolean saveTaskEvent(Task task, boolean isReplicated) throws A2AServerException { + return saveTaskEvent(task, isReplicated, null); + } + + boolean saveTaskEvent(Task task, boolean isReplicated, @Nullable AtomicReference taskSnapshot) + throws A2AServerException { checkIdsAndUpdateIfNecessary(task.id(), task.contextId()); Task savedTask = saveTask(task, isReplicated); + if (taskSnapshot != null) { + taskSnapshot.set(savedTask); + } return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); } boolean saveTaskEvent(TaskStatusUpdateEvent event, boolean isReplicated) throws A2AServerException { + return saveTaskEvent(event, isReplicated, null); + } + + boolean saveTaskEvent(TaskStatusUpdateEvent event, boolean isReplicated, @Nullable AtomicReference taskSnapshot) + throws A2AServerException { checkIdsAndUpdateIfNecessary(event.taskId(), event.contextId()); Task task = ensureTask(event.taskId(), event.contextId()); @@ -90,10 +104,18 @@ boolean saveTaskEvent(TaskStatusUpdateEvent event, boolean isReplicated) throws task = builder.build(); Task savedTask = saveTask(task, isReplicated); + if (taskSnapshot != null) { + taskSnapshot.set(savedTask); + } return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); } boolean saveTaskEvent(TaskArtifactUpdateEvent event, boolean isReplicated) throws A2AServerException { + return saveTaskEvent(event, isReplicated, null); + } + + boolean saveTaskEvent(TaskArtifactUpdateEvent event, boolean isReplicated, @Nullable AtomicReference taskSnapshot) + throws A2AServerException { checkIdsAndUpdateIfNecessary(event.taskId(), event.contextId()); Task task = ensureTask(event.taskId(), event.contextId()); // taskId is guaranteed to be non-null after checkIdsAndUpdateIfNecessary @@ -103,17 +125,25 @@ boolean saveTaskEvent(TaskArtifactUpdateEvent event, boolean isReplicated) throw } task = appendArtifactToTask(task, event, nonNullTaskId); Task savedTask = saveTask(task, isReplicated); + if (taskSnapshot != null) { + taskSnapshot.set(savedTask); + } return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); } public boolean process(Event event, boolean isReplicated) throws A2AServerException { + return process(event, isReplicated, null); + } + + public boolean process(Event event, boolean isReplicated, @Nullable AtomicReference taskSnapshot) + throws A2AServerException { boolean isFinal = false; if (event instanceof Task task) { - isFinal = saveTaskEvent(task, isReplicated); + isFinal = saveTaskEvent(task, isReplicated, taskSnapshot); } else if (event instanceof TaskStatusUpdateEvent taskStatusUpdateEvent) { - isFinal = saveTaskEvent(taskStatusUpdateEvent, isReplicated); + isFinal = saveTaskEvent(taskStatusUpdateEvent, isReplicated, taskSnapshot); } else if (event instanceof TaskArtifactUpdateEvent taskArtifactUpdateEvent) { - isFinal = saveTaskEvent(taskArtifactUpdateEvent, isReplicated); + isFinal = saveTaskEvent(taskArtifactUpdateEvent, isReplicated, taskSnapshot); } else if (event instanceof A2AError) { // A2AError events trigger automatic transition to FAILED state // Error details are NOT persisted in TaskStore (client-specific) @@ -144,7 +174,7 @@ public boolean process(Event event, boolean isReplicated) throws A2AServerExcept .contextId(errorContextId) .status(new TaskStatus(TASK_STATE_FAILED)) .build(); - isFinal = saveTaskEvent(failedEvent, isReplicated); + isFinal = saveTaskEvent(failedEvent, isReplicated, taskSnapshot); } else { // Can't update status without contextId, but error is still terminal LOGGER.debug("A2AError event for task {} without contextId - skipping state update", taskId); diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/events/EventConsumerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventConsumerTest.java index eee402df5..41389c3ec 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/events/EventConsumerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventConsumerTest.java @@ -35,7 +35,7 @@ public class EventConsumerTest { - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; private static final String TASK_ID = "123"; // Must match MINIMAL_TASK id private EventQueue eventQueue; diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueTest.java index 11fade0a2..3b49f6524 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/EventQueueTest.java @@ -55,7 +55,7 @@ public class EventQueueTest { } """; - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; @BeforeEach public void init() { diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/events/InMemoryQueueManagerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/InMemoryQueueManagerTest.java index 3f2be111e..71dbaa868 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/events/InMemoryQueueManagerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/InMemoryQueueManagerTest.java @@ -28,7 +28,7 @@ public class InMemoryQueueManagerTest { private InMemoryTaskStore taskStore; private MainEventBus mainEventBus; private MainEventBusProcessor mainEventBusProcessor; - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; @BeforeEach public void setUp() { diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java index 986958a14..23264977b 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java @@ -45,7 +45,7 @@ */ public class MainEventBusProcessorExceptionTest { - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; private static final String TASK_ID = "test-task-123"; private MainEventBus mainEventBus; diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java index 7544d4f9f..e3d7add5a 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/AbstractA2ARequestHandlerTest.java @@ -70,7 +70,7 @@ public class AbstractA2ARequestHandlerTest { private static final String PREFERRED_TRANSPORT = "preferred-transport"; private static final String A2A_REQUESTHANDLER_TEST_PROPERTIES = "/a2a-requesthandler-test.properties"; - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; protected AgentExecutor executor; protected TaskStore taskStore; diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandlerTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandlerTest.java index 8914586f5..be84073ba 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandlerTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/requesthandlers/DefaultRequestHandlerTest.java @@ -8,9 +8,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import java.util.concurrent.Flow; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -36,9 +39,11 @@ import org.a2aproject.sdk.spec.Message; import org.a2aproject.sdk.spec.MessageSendConfiguration; import org.a2aproject.sdk.spec.MessageSendParams; +import org.a2aproject.sdk.spec.StreamingEventKind; import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; import org.a2aproject.sdk.spec.TaskNotFoundError; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskState; import org.a2aproject.sdk.spec.TaskStatus; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; @@ -72,11 +77,12 @@ public class DefaultRequestHandlerTest { .parts(new TextPart("test message")) .build(); - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; // Test infrastructure components protected AgentExecutor executor; protected TaskStore taskStore; + protected PushNotificationConfigStore pushConfigStore; protected RequestHandler requestHandler; protected InMemoryQueueManager queueManager; protected MainEventBus mainEventBus; @@ -109,7 +115,7 @@ public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2A InMemoryTaskStore inMemoryTaskStore = new InMemoryTaskStore(); taskStore = inMemoryTaskStore; - PushNotificationConfigStore pushConfigStore = new InMemoryPushNotificationConfigStore(); + pushConfigStore = new InMemoryPushNotificationConfigStore(); // Create MainEventBus and MainEventBusProcessor mainEventBus = new MainEventBus(); @@ -905,4 +911,213 @@ void testSendMessage_FollowUpWithTaskIdOnly_PreservesOriginalContextId() throws // Cleanup: release the first agent releaseFirstAgent.countDown(); } + + // ── Protocol version propagation tests ────────────────────────────────────── + + private static ServerCallContext contextWithVersion(String version) { + return new ServerCallContext(null, Map.of(), Set.of(), version); + } + + /** + * Verify that onCreateTaskPushNotificationConfig stores the protocol version + * from the ServerCallContext in the PushNotificationConfigStore. + */ + @Test + void testVersionStored_OnCreateTaskPushNotificationConfig() throws Exception { + // Arrange: create a task directly in the store so the handler can find it + String taskId = "version-test-task-1"; + Task task = new Task( + taskId, + "ctx-1", + new TaskStatus(TaskState.TASK_STATE_WORKING), + null, + null, + null + ); + taskStore.save(task, false); + + TaskPushNotificationConfig pushConfig = TaskPushNotificationConfig.builder() + .id("") + .taskId(taskId) + .url("http://example.com/webhook") + .build(); + + // Act + requestHandler.onCreateTaskPushNotificationConfig(pushConfig, contextWithVersion("1.0")); + + // Assert: version is stored; configId defaults to taskId when id is empty + assertEquals("1.0", pushConfigStore.getProtocolVersion(taskId, taskId), + "Protocol version should be stored for the push notification config"); + } + + /** + * Verify that onMessageSend stores the protocol version when the request + * includes a push notification config (new task path). + */ + @Test + void testVersionStored_OnMessageSend_NewTask() throws Exception { + // Arrange: agent completes immediately + agentExecutorExecute = (context, emitter) -> emitter.complete(); + + TaskPushNotificationConfig pushConfig = TaskPushNotificationConfig.builder() + .id("") + .url("http://example.com/webhook") + .build(); + MessageSendConfiguration config = MessageSendConfiguration.builder() + .returnImmediately(true) + .acceptedOutputModes(List.of()) + .taskPushNotificationConfig(pushConfig) + .build(); + MessageSendParams params = MessageSendParams.builder() + .message(MESSAGE) + .configuration(config) + .build(); + + // Act + EventKind eventKind = requestHandler.onMessageSend(params, contextWithVersion("1.0")); + + // Assert + assertInstanceOf(Task.class, eventKind); + Task result = (Task) eventKind; + String taskId = result.id(); + + assertEquals("1.0", pushConfigStore.getProtocolVersion(taskId, taskId), + "Protocol version should be stored when push config is provided via onMessageSend"); + } + + /** + * Verify that onMessageSend stores the protocol version when the request + * includes a push notification config on a follow-up to an existing task. + */ + @Test + void testVersionStored_OnMessageSend_ExistingTask() throws Exception { + // Arrange: create an initial task (no push config) — agent stays active + CountDownLatch agentStarted = new CountDownLatch(1); + CountDownLatch agentRelease = new CountDownLatch(1); + + agentExecutorExecute = (context, emitter) -> { + emitter.startWork(); + agentStarted.countDown(); + try { + agentRelease.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + emitter.complete(); + }; + + MessageSendParams initialParams = MessageSendParams.builder() + .message(MESSAGE) + .configuration(DEFAULT_CONFIG) + .build(); + + EventKind initialResult = requestHandler.onMessageSend(initialParams, NULL_CONTEXT); + assertInstanceOf(Task.class, initialResult); + Task existingTask = (Task) initialResult; + assertTrue(agentStarted.await(5, TimeUnit.SECONDS), "Agent should start"); + + try { + // Now set up agent for the follow-up + agentExecutorExecute = (context, emitter) -> emitter.complete(); + + // Follow-up message WITH push config and version context + TaskPushNotificationConfig pushConfig = TaskPushNotificationConfig.builder() + .id("") + .url("http://example.com/webhook") + .build(); + MessageSendConfiguration followUpConfig = MessageSendConfiguration.builder() + .returnImmediately(true) + .acceptedOutputModes(List.of()) + .taskPushNotificationConfig(pushConfig) + .build(); + Message followUpMsg = Message.builder() + .messageId("follow-up-version-test") + .role(Message.Role.ROLE_USER) + .taskId(existingTask.id()) + .parts(new TextPart("follow up")) + .build(); + MessageSendParams followUpParams = MessageSendParams.builder() + .message(followUpMsg) + .configuration(followUpConfig) + .build(); + + // Act + EventKind result = requestHandler.onMessageSend(followUpParams, contextWithVersion("1.0")); + + // Assert + assertInstanceOf(Task.class, result); + String taskId = existingTask.id(); + assertEquals("1.0", pushConfigStore.getProtocolVersion(taskId, taskId), + "Protocol version should be stored for push config on existing task"); + } finally { + agentRelease.countDown(); + } + } + + /** + * Verify that onMessageSendStream stores the protocol version when the request + * includes a push notification config (new task, streaming path). + */ + @Test + void testVersionStored_OnMessageSendStream_NewTask() throws Exception { + // Arrange: agent completes immediately + agentExecutorExecute = (context, emitter) -> emitter.complete(); + + TaskPushNotificationConfig pushConfig = TaskPushNotificationConfig.builder() + .id("") + .url("http://example.com/webhook") + .build(); + MessageSendConfiguration config = MessageSendConfiguration.builder() + .returnImmediately(true) + .acceptedOutputModes(List.of()) + .taskPushNotificationConfig(pushConfig) + .build(); + MessageSendParams params = MessageSendParams.builder() + .message(MESSAGE) + .configuration(config) + .build(); + + // Act + Flow.Publisher publisher = requestHandler.onMessageSendStream( + params, contextWithVersion("1.0")); + + AtomicReference taskIdRef = new AtomicReference<>(); + CountDownLatch streamDone = new CountDownLatch(1); + publisher.subscribe(new Flow.Subscriber<>() { + Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription s) { + subscription = s; + s.request(Long.MAX_VALUE); + } + + @Override + public void onNext(StreamingEventKind item) { + if (item instanceof Task t) { + taskIdRef.set(t.id()); + } else if (item instanceof TaskStatusUpdateEvent e) { + taskIdRef.set(e.taskId()); + } + } + + @Override + public void onError(Throwable t) { + streamDone.countDown(); + } + + @Override + public void onComplete() { + streamDone.countDown(); + } + }); + + assertTrue(streamDone.await(5, TimeUnit.SECONDS), "Stream should complete"); + String taskId = taskIdRef.get(); + assertNotNull(taskId, "Should have received a task ID from the stream"); + + // Assert + assertEquals("1.0", pushConfigStore.getProtocolVersion(taskId, taskId), + "Protocol version should be stored when push config is provided via onMessageSendStream"); + } } diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterTest.java index e69863286..b63f9b54c 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/AgentEmitterTest.java @@ -43,7 +43,7 @@ public class AgentEmitterTest { private static final List> SAMPLE_PARTS = List.of(new TextPart("Test message")); - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; + private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = (event, snapshot) -> {}; EventQueue eventQueue; private MainEventBus mainEventBus; diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStoreTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStoreTest.java index b407c9f33..110168603 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStoreTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/InMemoryPushNotificationConfigStoreTest.java @@ -16,6 +16,7 @@ import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpResponse; import org.a2aproject.sdk.common.A2AHeaders; +import org.a2aproject.sdk.spec.AgentInterface; import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsParams; import org.a2aproject.sdk.spec.ListTaskPushNotificationConfigsResult; import org.a2aproject.sdk.spec.Task; @@ -249,7 +250,7 @@ public void testSendNotificationSuccess() throws Exception { // Mock successful HTTP response setupBasicMockHttpResponse(); - notificationSender.sendNotification(task); + notificationSender.sendNotification(task, null); // Verify HTTP client was called ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); @@ -279,7 +280,7 @@ public void testSendNotificationWithToken() throws Exception { when(mockPostBuilder.post()).thenReturn(mockHttpResponse); when(mockHttpResponse.success()).thenReturn(true); - notificationSender.sendNotification(task); + notificationSender.sendNotification(task, null); // Verify HTTP client was called with proper authentication ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); @@ -301,7 +302,7 @@ public void testSendNotificationNoConfig() throws Exception { String taskId = "task_send_no_config"; Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - notificationSender.sendNotification(task); + notificationSender.sendNotification(task, null); // Verify HTTP client was never called verify(mockHttpClient, never()).createPost(); @@ -315,7 +316,7 @@ public void testSendNotificationWithEmptyToken() throws Exception { configStore.setInfo(config); setupBasicMockHttpResponse(); - notificationSender.sendNotification(task); + notificationSender.sendNotification(task, null); verifyHttpCallWithoutToken(config, task, ""); } @@ -327,7 +328,7 @@ public void testSendNotificationWithBlankToken() throws Exception { configStore.setInfo(config); setupBasicMockHttpResponse(); - notificationSender.sendNotification(task); + notificationSender.sendNotification(task, null); verifyHttpCallWithoutToken(config, task, " "); } @@ -593,6 +594,39 @@ public void testPaginationEmptyTaskWithPageSize() { assertNull(result.nextPageToken(), "Should not have nextPageToken for empty result"); } + @Test + public void testSetAndGetProtocolVersion() { + String taskId = "task1"; + String configId = "cfg1"; + TaskPushNotificationConfig config = TaskPushNotificationConfig.builder() + .id(configId).taskId(taskId).url("http://example.com/hook").build(); + configStore.setInfo(config); + + assertEquals(AgentInterface.CURRENT_PROTOCOL_VERSION, configStore.getProtocolVersion(taskId, configId)); + + configStore.setInfo(config, "0.3"); + assertEquals("0.3", configStore.getProtocolVersion(taskId, configId)); + } + + @Test + public void testDeleteInfoCleansUpProtocolVersion() { + String taskId = "task1"; + String configId = "cfg1"; + TaskPushNotificationConfig config = TaskPushNotificationConfig.builder() + .id(configId).taskId(taskId).url("http://example.com/hook").build(); + configStore.setInfo(config, "0.3"); + + assertEquals("0.3", configStore.getProtocolVersion(taskId, configId)); + + configStore.deleteInfo(taskId, configId); + assertEquals(AgentInterface.CURRENT_PROTOCOL_VERSION, configStore.getProtocolVersion(taskId, configId)); + } + + @Test + public void testGetProtocolVersionReturnsDefaultForUnknownConfig() { + assertEquals(AgentInterface.CURRENT_PROTOCOL_VERSION, configStore.getProtocolVersion("nonexistent", "nonexistent")); + } + @Test public void testPaginationFullIteration() { String taskId = "task_pagination_full"; diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java index 27b54f310..87226524d 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/PushNotificationSenderTest.java @@ -25,13 +25,14 @@ import org.a2aproject.sdk.spec.Artifact; import org.a2aproject.sdk.spec.Message; import org.a2aproject.sdk.spec.StreamingEventKind; -import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.TaskArtifactUpdateEvent; +import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskState; import org.a2aproject.sdk.spec.TaskStatus; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; import org.a2aproject.sdk.spec.TextPart; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -164,7 +165,7 @@ private void testSendNotificationWithInvalidToken(String token, String testName) // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); - sender.sendNotification(taskData); + sender.sendNotification(taskData, null); // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); @@ -218,7 +219,7 @@ public void testSendNotificationSuccess() throws InterruptedException { // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); - sender.sendNotification(taskData); + sender.sendNotification(taskData, null); // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); @@ -249,7 +250,7 @@ public void testSendNotificationWithTokenSuccess() throws InterruptedException { // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); - sender.sendNotification(taskData); + sender.sendNotification(taskData, null); // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); @@ -279,7 +280,7 @@ public void testSendNotificationNoConfig() { Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); // Don't set any configuration in the store - sender.sendNotification(taskData); + sender.sendNotification(taskData, null); // Verify no HTTP calls were made assertEquals(0, testHttpClient.events.size()); @@ -309,7 +310,7 @@ public void testSendNotificationMultipleConfigs() throws InterruptedException { // Set up latch to wait for async completion (2 calls expected) testHttpClient.latch = new CountDownLatch(2); - sender.sendNotification(taskData); + sender.sendNotification(taskData, null); // Wait for the async operations to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP calls should complete within 5 seconds"); @@ -342,7 +343,7 @@ public void testSendNotificationHttpError() { testHttpClient.shouldThrowException = true; // This should not throw an exception - errors should be handled gracefully - sender.sendNotification(taskData); + sender.sendNotification(taskData, null); // Verify no events were successfully processed due to the error assertEquals(0, testHttpClient.events.size()); @@ -364,7 +365,7 @@ public void testSendNotificationMessage() throws InterruptedException { // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); - sender.sendNotification(message); + sender.sendNotification(message, null); // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); @@ -397,7 +398,7 @@ public void testSendNotificationTaskStatusUpdate() throws InterruptedException { // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); - sender.sendNotification(statusUpdate); + sender.sendNotification(statusUpdate, null); // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); @@ -436,7 +437,7 @@ public void testSendNotificationTaskArtifactUpdate() throws InterruptedException // Set up latch to wait for async completion testHttpClient.latch = new CountDownLatch(1); - sender.sendNotification(artifactUpdate); + sender.sendNotification(artifactUpdate, null); // Wait for the async operation to complete assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); @@ -452,4 +453,67 @@ public void testSendNotificationTaskArtifactUpdate() throws InterruptedException String rawBody = testHttpClient.rawBodies.get(0); assertTrue(rawBody.contains("\"artifactUpdate\""), "Raw body should contain 'artifactUpdate' discriminator for StreamResponse"); } + + @Test + public void testSendNotificationUsesFormatterForVersionedConfig() throws InterruptedException { + String taskId = "task_formatter_test"; + Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); + + TaskPushNotificationConfig config = TaskPushNotificationConfig.builder() + .url("http://notify.me/here") + .id("cfg1") + .taskId(taskId) + .build(); + configStore.setInfo(config, "0.3"); + + PushNotificationPayloadFormatter formatter = new PushNotificationPayloadFormatter() { + @Override + public String targetVersion() { return "0.3"; } + + @Override + public @Nullable String formatPayload(StreamingEventKind event, @Nullable Task snapshot) { + return "{\"id\":\"" + taskId + "\",\"kind\":\"task\",\"formatted\":true}"; + } + }; + + BasePushNotificationSender formatterSender = new BasePushNotificationSender( + configStore, testHttpClient, List.of(formatter)); + testHttpClient.latch = new CountDownLatch(1); + + formatterSender.sendNotification(taskData, taskData); + + assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS)); + assertEquals(1, testHttpClient.rawBodies.size()); + assertTrue(testHttpClient.rawBodies.get(0).contains("\"formatted\":true")); + } + + @Test + public void testSendNotificationSkipsWhenFormatterReturnsNull() throws InterruptedException { + String taskId = "task_formatter_skip"; + Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); + + TaskPushNotificationConfig config = TaskPushNotificationConfig.builder() + .url("http://notify.me/here") + .id("cfg1") + .taskId(taskId) + .build(); + configStore.setInfo(config, "0.3"); + + PushNotificationPayloadFormatter formatter = new PushNotificationPayloadFormatter() { + @Override + public String targetVersion() { return "0.3"; } + + @Override + public @Nullable String formatPayload(StreamingEventKind event, @Nullable Task snapshot) { + return null; + } + }; + + BasePushNotificationSender formatterSender = new BasePushNotificationSender( + configStore, testHttpClient, List.of(formatter)); + + formatterSender.sendNotification(taskData, taskData); + + assertTrue(testHttpClient.rawBodies.isEmpty()); + } } diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java index e641c5631..7b206e01a 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/ResultAggregatorTest.java @@ -248,7 +248,7 @@ void testConsumeAndBreakNonBlocking() throws Exception { InMemoryTaskStore taskStore = new InMemoryTaskStore(); InMemoryQueueManager queueManager = new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); - MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, (event, snapshot) -> {}, queueManager); EventQueueUtil.start(processor); EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); @@ -296,7 +296,7 @@ void testConsumeAndBreakOnAuthRequired_Blocking() throws Exception { InMemoryTaskStore taskStore = new InMemoryTaskStore(); InMemoryQueueManager queueManager = new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); - MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, (event, snapshot) -> {}, queueManager); EventQueueUtil.start(processor); EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); @@ -338,7 +338,7 @@ void testConsumeAndBreakOnAuthRequired_NonBlocking() throws Exception { InMemoryTaskStore taskStore = new InMemoryTaskStore(); InMemoryQueueManager queueManager = new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); - MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, (event, snapshot) -> {}, queueManager); EventQueueUtil.start(processor); EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); @@ -385,7 +385,7 @@ void testAuthRequiredWithTaskStatusUpdateEvent() throws Exception { InMemoryTaskStore taskStore = new InMemoryTaskStore(); InMemoryQueueManager queueManager = new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); - MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, (event, snapshot) -> {}, queueManager); EventQueueUtil.start(processor); EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); @@ -431,7 +431,7 @@ void testAuthRequiredWithTaskEvent() throws Exception { InMemoryTaskStore taskStore = new InMemoryTaskStore(); InMemoryQueueManager queueManager = new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); - MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); + MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, (event, snapshot) -> {}, queueManager); EventQueueUtil.start(processor); EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerSnapshotTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerSnapshotTest.java new file mode 100644 index 000000000..0e54caf8f --- /dev/null +++ b/server-common/src/test/java/org/a2aproject/sdk/server/tasks/TaskManagerSnapshotTest.java @@ -0,0 +1,75 @@ +package org.a2aproject.sdk.server.tasks; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.concurrent.atomic.AtomicReference; + +import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.spec.TaskState; +import org.a2aproject.sdk.spec.TaskStatus; +import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TaskManagerSnapshotTest { + + private InMemoryTaskStore taskStore; + + @BeforeEach + void setUp() { + taskStore = new InMemoryTaskStore(); + } + + @Test + void snapshotCapturedForTaskEvent() throws Exception { + Task task = Task.builder() + .id("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) + .build(); + + AtomicReference snapshot = new AtomicReference<>(); + TaskManager tm = new TaskManager("t1", "c1", taskStore, null); + tm.process(task, false, snapshot); + + assertNotNull(snapshot.get()); + assertEquals("t1", snapshot.get().id()); + } + + @Test + void snapshotCapturedForStatusUpdateEvent() throws Exception { + // Seed a task first + Task task = Task.builder() + .id("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) + .build(); + taskStore.save(task, false); + + TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() + .taskId("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) + .build(); + + AtomicReference snapshot = new AtomicReference<>(); + TaskManager tm = new TaskManager("t1", "c1", taskStore, null); + tm.process(event, false, snapshot); + + assertNotNull(snapshot.get()); + assertEquals(TaskState.TASK_STATE_WORKING, snapshot.get().status().state()); + } + + @Test + void snapshotNullWhenNotProvided() throws Exception { + Task task = Task.builder() + .id("t1").contextId("c1") + .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) + .build(); + + TaskManager tm = new TaskManager("t1", "c1", taskStore, null); + // Old signature still works, no snapshot + tm.process(task, false); + + // Just confirm the old method doesn't crash + assertNotNull(taskStore.get("t1")); + } +} From ececaab02adf0ea84bbaca98ce41a2e4e89557f6 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Fri, 15 May 2026 14:18:43 +0100 Subject: [PATCH 170/192] fix: Need to be able to specify different host for gRPC in TCK (#877) --- .../java/org/a2aproject/sdk/sut/TckAgentCardProducer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentCardProducer.java b/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentCardProducer.java index f6c53705f..3119f6f9b 100644 --- a/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentCardProducer.java +++ b/tck/src/main/java/org/a2aproject/sdk/sut/TckAgentCardProducer.java @@ -19,15 +19,15 @@ */ @ApplicationScoped public class TckAgentCardProducer { - - private static final String host = getEnvOrDefault("SUT_HOST", "localhost:9999"); + private static final String HOST = getEnvOrDefault("SUT_HOST", "localhost:9999"); + private static final String GRPC_HOST = getEnvOrDefault("SUT_GRPC_HOST", HOST); @Produces @PublicAgentCard public AgentCard agentCard() { - String sutJsonRpcUrl = String.format("http://%s", host); + String sutJsonRpcUrl = String.format("http://%s", HOST); String sutRestUrl = sutJsonRpcUrl; - String sutGrpcUrl = host; + String sutGrpcUrl = GRPC_HOST; return AgentCard.builder() .name("A2A Java SDK System Under Test (SUT)") From a1dd596ca4388c90039c496b59b7c10ab5a903a5 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 18 May 2026 11:18:40 +0100 Subject: [PATCH 171/192] fix: Remove unneeded grpc version workaround (#878) --- .../org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java index 306c8655c..178a32adf 100644 --- a/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java +++ b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java @@ -689,9 +689,6 @@ private ServerCallContext createCallContext(StreamObserver responseObserv // Extract requested protocol version from gRPC context (set by interceptor) // Default to current version since gRPC only handles 1.0 protocol String requestedVersion = getVersionFromContext(); - if (requestedVersion == null) { - requestedVersion = AgentInterface.CURRENT_PROTOCOL_VERSION; - } // Extract requested extensions from gRPC context (set by interceptor) Set requestedExtensions = new HashSet<>(); From 045a352ff58075eba678b5ee8204cfc7a2204300 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 18 May 2026 13:22:25 +0100 Subject: [PATCH 172/192] chore: Use tagged versions of the TCK (#879) --- .github/workflows/run-tck.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index 4ad20c420..839ad8524 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -11,8 +11,8 @@ on: env: # Tag/branch of the TCK - TCK_VERSION: 1.0-dev - TCK_VERSION_0_3: 0.3.x + TCK_VERSION: 1.0.0.alpha1 + TCK_VERSION_0_3: 0.3.0.beta5 # Tells uv to not need a venv, and instead use system UV_SYSTEM_PYTHON: 1 SUT_URL: http://localhost:9999 From 7e7c1d2da52c31fcf22c6b1e051eade337c47652 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 18 May 2026 13:53:45 +0100 Subject: [PATCH 173/192] chore: Prepare 1.0.0.CR1 release (#880) --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- compat-0.3/client/base/pom.xml | 2 +- compat-0.3/client/transport/grpc/pom.xml | 2 +- compat-0.3/client/transport/jsonrpc/pom.xml | 2 +- compat-0.3/client/transport/rest/pom.xml | 2 +- compat-0.3/client/transport/spi/pom.xml | 2 +- compat-0.3/pom.xml | 2 +- compat-0.3/reference/grpc/pom.xml | 2 +- compat-0.3/reference/jsonrpc/pom.xml | 2 +- compat-0.3/reference/rest/pom.xml | 2 +- compat-0.3/server-conversion/pom.xml | 2 +- compat-0.3/spec-grpc/pom.xml | 2 +- compat-0.3/spec/pom.xml | 2 +- compat-0.3/tck/pom.xml | 2 +- compat-0.3/transport/grpc/pom.xml | 2 +- compat-0.3/transport/jsonrpc/pom.xml | 2 +- compat-0.3/transport/rest/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../sdk/examples/helloworld/HelloWorldRunner.java | 12 ++++++------ examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-android/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- extras/opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 2 +- .../tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- .../tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/multiversion-jsonrpc/pom.xml | 2 +- reference/multiversion-rest/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 2 +- test-utils-docker/pom.xml | 2 +- tests/multiversion/grpc/pom.xml | 2 +- tests/multiversion/jsonrpc/pom.xml | 2 +- tests/multiversion/rest/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 73 files changed, 78 insertions(+), 78 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 5b8a6e4a4..1fb36f0a9 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 7006e7c64..3421e35d5 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index b28fca59b..63f00e954 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 7576207ed..4060515a3 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index 9b6fb9670..271479ee0 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 2186c985c..b000f5401 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 7de354428..ba9b0e638 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index 97b77613b..ce70484b6 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index 78d94b858..830217962 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index b02dddbfe..4c169a5bd 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-common diff --git a/compat-0.3/client/base/pom.xml b/compat-0.3/client/base/pom.xml index 5fd78bdbe..4a418bab7 100644 --- a/compat-0.3/client/base/pom.xml +++ b/compat-0.3/client/base/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../.. a2a-java-sdk-compat-0.3-client diff --git a/compat-0.3/client/transport/grpc/pom.xml b/compat-0.3/client/transport/grpc/pom.xml index 97c24e11a..99551abc1 100644 --- a/compat-0.3/client/transport/grpc/pom.xml +++ b/compat-0.3/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../.. a2a-java-sdk-compat-0.3-client-transport-grpc diff --git a/compat-0.3/client/transport/jsonrpc/pom.xml b/compat-0.3/client/transport/jsonrpc/pom.xml index af1121c5f..81cb2649c 100644 --- a/compat-0.3/client/transport/jsonrpc/pom.xml +++ b/compat-0.3/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../.. a2a-java-sdk-compat-0.3-client-transport-jsonrpc diff --git a/compat-0.3/client/transport/rest/pom.xml b/compat-0.3/client/transport/rest/pom.xml index 0b101ed9e..d7e158704 100644 --- a/compat-0.3/client/transport/rest/pom.xml +++ b/compat-0.3/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../.. a2a-java-sdk-compat-0.3-client-transport-rest diff --git a/compat-0.3/client/transport/spi/pom.xml b/compat-0.3/client/transport/spi/pom.xml index d4b7c9bb3..8cb55697e 100644 --- a/compat-0.3/client/transport/spi/pom.xml +++ b/compat-0.3/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../.. a2a-java-sdk-compat-0.3-client-transport-spi diff --git a/compat-0.3/pom.xml b/compat-0.3/pom.xml index e3c90533c..d11960ecc 100644 --- a/compat-0.3/pom.xml +++ b/compat-0.3/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-compat-0.3-parent diff --git a/compat-0.3/reference/grpc/pom.xml b/compat-0.3/reference/grpc/pom.xml index dddbbe6dc..182493e98 100644 --- a/compat-0.3/reference/grpc/pom.xml +++ b/compat-0.3/reference/grpc/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/compat-0.3/reference/jsonrpc/pom.xml b/compat-0.3/reference/jsonrpc/pom.xml index ec4befc37..c8e4ae502 100644 --- a/compat-0.3/reference/jsonrpc/pom.xml +++ b/compat-0.3/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-compat-0.3-reference-jsonrpc diff --git a/compat-0.3/reference/rest/pom.xml b/compat-0.3/reference/rest/pom.xml index 3bac16a15..d885f4a70 100644 --- a/compat-0.3/reference/rest/pom.xml +++ b/compat-0.3/reference/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-compat-0.3-reference-rest diff --git a/compat-0.3/server-conversion/pom.xml b/compat-0.3/server-conversion/pom.xml index aa0108c91..ef107858d 100644 --- a/compat-0.3/server-conversion/pom.xml +++ b/compat-0.3/server-conversion/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 .. a2a-java-sdk-compat-0.3-server-conversion diff --git a/compat-0.3/spec-grpc/pom.xml b/compat-0.3/spec-grpc/pom.xml index 6021f6820..5b87ab7f2 100644 --- a/compat-0.3/spec-grpc/pom.xml +++ b/compat-0.3/spec-grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 .. a2a-java-sdk-compat-0.3-spec-grpc diff --git a/compat-0.3/spec/pom.xml b/compat-0.3/spec/pom.xml index 045ebaa50..75bae0a6f 100644 --- a/compat-0.3/spec/pom.xml +++ b/compat-0.3/spec/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 .. a2a-java-sdk-compat-0.3-spec diff --git a/compat-0.3/tck/pom.xml b/compat-0.3/tck/pom.xml index bcdaf37c0..908e8307f 100644 --- a/compat-0.3/tck/pom.xml +++ b/compat-0.3/tck/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 .. diff --git a/compat-0.3/transport/grpc/pom.xml b/compat-0.3/transport/grpc/pom.xml index 7ad780db3..f7b45c080 100644 --- a/compat-0.3/transport/grpc/pom.xml +++ b/compat-0.3/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../.. a2a-java-sdk-compat-0.3-transport-grpc diff --git a/compat-0.3/transport/jsonrpc/pom.xml b/compat-0.3/transport/jsonrpc/pom.xml index fc5b918b3..9eba8e0fb 100644 --- a/compat-0.3/transport/jsonrpc/pom.xml +++ b/compat-0.3/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../.. a2a-java-sdk-compat-0.3-transport-jsonrpc diff --git a/compat-0.3/transport/rest/pom.xml b/compat-0.3/transport/rest/pom.xml index fe31a68fb..fffa3691c 100644 --- a/compat-0.3/transport/rest/pom.xml +++ b/compat-0.3/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../.. a2a-java-sdk-compat-0.3-transport-rest diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index 7d334401d..eb558b31f 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index bcd19c5bf..ea131ebf0 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-examples-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java index 32b14361c..99563140e 100644 --- a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Beta2-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Beta2-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.Beta2-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.Beta2-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.Beta2-SNAPSHOT -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Beta2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.CR1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.CR1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.CR1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.CR1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.CR1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.CR1 //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 4a4ee2d71..4e855d896 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index eb8b72ce1..4f7fbdbb6 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-examples-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index e0acd1961..886c2e5c8 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/extras/http-client-android/pom.xml b/extras/http-client-android/pom.xml index 6964df341..e309690f3 100644 --- a/extras/http-client-android/pom.xml +++ b/extras/http-client-android/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-http-client-android diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 3f97abf89..9fe115eae 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index c1692cc9b..ff7e9636c 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-opentelemetry-client-propagation diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index dcd3a7c68..0288b7173 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-opentelemetry-client diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index 0d2a689c4..c185d1177 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-opentelemetry-common diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index c9085d121..0130daf0b 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-opentelemetry-integration-tests diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 390293310..75fece2cf 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index e335a3a45..d68402770 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-opentelemetry-server diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index fcc1c47fa..25ec1cd34 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 019507c91..23c53c259 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 3dcf5e5cb..1ed237159 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 621dc1a9e..78aec8f8c 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index c80f72dae..ca689a9ab 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index 9857d400b..b208d307b 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index 9bf5c7e05..c99f1706b 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index 9471b7773..04691bca6 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index 7c00ebbe6..b74988104 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index 3297eaf07..b16e0bd1c 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 49c434ceb..15857366e 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index 468432f9d..f678b58fb 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 1c9d07758..7594e4176 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index 2b126e4b2..ec18e7891 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index ca640de38..fd55af76d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index 4a75519c9..f723702c4 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index f2ffbba0c..7762528dd 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 292c68e5e..1f4205225 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/multiversion-jsonrpc/pom.xml b/reference/multiversion-jsonrpc/pom.xml index 35000e9ee..2910039bb 100644 --- a/reference/multiversion-jsonrpc/pom.xml +++ b/reference/multiversion-jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-reference-multiversion-jsonrpc diff --git a/reference/multiversion-rest/pom.xml b/reference/multiversion-rest/pom.xml index bfd1f9a6d..f5015bd3d 100644 --- a/reference/multiversion-rest/pom.xml +++ b/reference/multiversion-rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-reference-multiversion-rest diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index 2c57eaed1..d2d21d034 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index 0bdff9805..da1d52a13 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index 090a28a62..7c33db060 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index 4c982f996..d981beb90 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-spec diff --git a/tck/pom.xml b/tck/pom.xml index aae651d26..674862bce 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 a2a-java-sdk-tck-sut A2A Java SDK: SUT for TCK diff --git a/test-utils-docker/pom.xml b/test-utils-docker/pom.xml index 7f22cd7a0..5ac16792b 100644 --- a/test-utils-docker/pom.xml +++ b/test-utils-docker/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../pom.xml diff --git a/tests/multiversion/grpc/pom.xml b/tests/multiversion/grpc/pom.xml index db09657af..f3e0873f6 100644 --- a/tests/multiversion/grpc/pom.xml +++ b/tests/multiversion/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../../pom.xml a2a-java-sdk-tests-multiversion-grpc diff --git a/tests/multiversion/jsonrpc/pom.xml b/tests/multiversion/jsonrpc/pom.xml index ef78c49cc..7f235f088 100644 --- a/tests/multiversion/jsonrpc/pom.xml +++ b/tests/multiversion/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../../pom.xml a2a-java-sdk-tests-multiversion-jsonrpc diff --git a/tests/multiversion/rest/pom.xml b/tests/multiversion/rest/pom.xml index 3e4127db1..f07916595 100644 --- a/tests/multiversion/rest/pom.xml +++ b/tests/multiversion/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../../pom.xml a2a-java-sdk-tests-multiversion-rest diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index 3c688564e..3ac04127f 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index e19859b9a..da51eb47a 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index 270566b2f..914c3f656 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 24991513b..3a0ce691a 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.Beta2-SNAPSHOT + 1.0.0.CR1 ../../pom.xml a2a-java-sdk-transport-rest From 548ccd25b8d8375e77d6ab388938662f08c6e8e2 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Tue, 19 May 2026 11:36:48 +0200 Subject: [PATCH 174/192] chore: use the `main` branch for TCK 1.0 (#887) Signed-off-by: Jeff Mesnil --- .github/workflows/run-tck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml index 839ad8524..744ff8082 100644 --- a/.github/workflows/run-tck.yml +++ b/.github/workflows/run-tck.yml @@ -11,7 +11,7 @@ on: env: # Tag/branch of the TCK - TCK_VERSION: 1.0.0.alpha1 + TCK_VERSION: main TCK_VERSION_0_3: 0.3.0.beta5 # Tells uv to not need a venv, and instead use system UV_SYSTEM_PYTHON: 1 From 0b867d0de4fae60c3420dfbdc8496f4cb1022da4 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 19 May 2026 15:52:38 +0100 Subject: [PATCH 175/192] chore: Bump to next SNAPSHOT version (#881) --- boms/extras/pom.xml | 2 +- boms/reference/pom.xml | 2 +- boms/sdk/pom.xml | 2 +- boms/test-utils/pom.xml | 2 +- client/base/pom.xml | 2 +- client/transport/grpc/pom.xml | 2 +- client/transport/jsonrpc/pom.xml | 2 +- client/transport/rest/pom.xml | 2 +- client/transport/spi/pom.xml | 2 +- common/pom.xml | 2 +- compat-0.3/client/base/pom.xml | 2 +- compat-0.3/client/transport/grpc/pom.xml | 2 +- compat-0.3/client/transport/jsonrpc/pom.xml | 2 +- compat-0.3/client/transport/rest/pom.xml | 2 +- compat-0.3/client/transport/spi/pom.xml | 2 +- compat-0.3/pom.xml | 2 +- compat-0.3/reference/grpc/pom.xml | 2 +- compat-0.3/reference/jsonrpc/pom.xml | 2 +- compat-0.3/reference/rest/pom.xml | 2 +- compat-0.3/server-conversion/pom.xml | 2 +- compat-0.3/spec-grpc/pom.xml | 2 +- compat-0.3/spec/pom.xml | 2 +- compat-0.3/tck/pom.xml | 2 +- compat-0.3/transport/grpc/pom.xml | 2 +- compat-0.3/transport/jsonrpc/pom.xml | 2 +- compat-0.3/transport/rest/pom.xml | 2 +- examples/cloud-deployment/server/pom.xml | 2 +- examples/helloworld/client/pom.xml | 2 +- .../sdk/examples/helloworld/HelloWorldRunner.java | 12 ++++++------ examples/helloworld/pom.xml | 2 +- examples/helloworld/server/pom.xml | 2 +- extras/common/pom.xml | 2 +- extras/http-client-android/pom.xml | 2 +- extras/http-client-vertx/pom.xml | 2 +- extras/opentelemetry/client-propagation/pom.xml | 2 +- extras/opentelemetry/client/pom.xml | 2 +- extras/opentelemetry/common/pom.xml | 2 +- extras/opentelemetry/integration-tests/pom.xml | 2 +- extras/opentelemetry/pom.xml | 2 +- extras/opentelemetry/server/pom.xml | 2 +- .../pom.xml | 2 +- extras/queue-manager-replicated/core/pom.xml | 2 +- extras/queue-manager-replicated/pom.xml | 2 +- .../replication-mp-reactive/pom.xml | 2 +- .../tests-multi-instance/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-1/pom.xml | 2 +- .../tests-multi-instance/quarkus-app-2/pom.xml | 2 +- .../tests-multi-instance/quarkus-common/pom.xml | 2 +- .../tests-multi-instance/tests/pom.xml | 2 +- .../tests-single-instance/pom.xml | 2 +- extras/task-store-database-jpa/pom.xml | 2 +- http-client/pom.xml | 2 +- integrations/microprofile-config/pom.xml | 2 +- jsonrpc-common/pom.xml | 2 +- pom.xml | 2 +- reference/common/pom.xml | 2 +- reference/grpc/pom.xml | 2 +- reference/jsonrpc/pom.xml | 2 +- reference/multiversion-jsonrpc/pom.xml | 2 +- reference/multiversion-rest/pom.xml | 2 +- reference/rest/pom.xml | 2 +- server-common/pom.xml | 2 +- spec-grpc/pom.xml | 2 +- spec/pom.xml | 2 +- tck/pom.xml | 2 +- test-utils-docker/pom.xml | 2 +- tests/multiversion/grpc/pom.xml | 2 +- tests/multiversion/jsonrpc/pom.xml | 2 +- tests/multiversion/rest/pom.xml | 2 +- tests/server-common/pom.xml | 2 +- transport/grpc/pom.xml | 2 +- transport/jsonrpc/pom.xml | 2 +- transport/rest/pom.xml | 2 +- 73 files changed, 78 insertions(+), 78 deletions(-) diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml index 1fb36f0a9..01f268991 100644 --- a/boms/extras/pom.xml +++ b/boms/extras/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml index 3421e35d5..3624bca7b 100644 --- a/boms/reference/pom.xml +++ b/boms/reference/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index 63f00e954..d8601278a 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml index 4060515a3..118497001 100644 --- a/boms/test-utils/pom.xml +++ b/boms/test-utils/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/client/base/pom.xml b/client/base/pom.xml index 271479ee0..584c21764 100644 --- a/client/base/pom.xml +++ b/client/base/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-client diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index b000f5401..9aa92a364 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-grpc diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index ba9b0e638..ba73b2306 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-jsonrpc diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index ce70484b6..663f5dfcf 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-rest diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index 830217962..2a691d45f 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../../pom.xml a2a-java-sdk-client-transport-spi diff --git a/common/pom.xml b/common/pom.xml index 4c169a5bd..cd8b57559 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-common diff --git a/compat-0.3/client/base/pom.xml b/compat-0.3/client/base/pom.xml index 4a418bab7..fc8fb52f3 100644 --- a/compat-0.3/client/base/pom.xml +++ b/compat-0.3/client/base/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../.. a2a-java-sdk-compat-0.3-client diff --git a/compat-0.3/client/transport/grpc/pom.xml b/compat-0.3/client/transport/grpc/pom.xml index 99551abc1..dc14f97f6 100644 --- a/compat-0.3/client/transport/grpc/pom.xml +++ b/compat-0.3/client/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../.. a2a-java-sdk-compat-0.3-client-transport-grpc diff --git a/compat-0.3/client/transport/jsonrpc/pom.xml b/compat-0.3/client/transport/jsonrpc/pom.xml index 81cb2649c..75d91eaf3 100644 --- a/compat-0.3/client/transport/jsonrpc/pom.xml +++ b/compat-0.3/client/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../.. a2a-java-sdk-compat-0.3-client-transport-jsonrpc diff --git a/compat-0.3/client/transport/rest/pom.xml b/compat-0.3/client/transport/rest/pom.xml index d7e158704..6c6f759d8 100644 --- a/compat-0.3/client/transport/rest/pom.xml +++ b/compat-0.3/client/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../.. a2a-java-sdk-compat-0.3-client-transport-rest diff --git a/compat-0.3/client/transport/spi/pom.xml b/compat-0.3/client/transport/spi/pom.xml index 8cb55697e..f186e815d 100644 --- a/compat-0.3/client/transport/spi/pom.xml +++ b/compat-0.3/client/transport/spi/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../.. a2a-java-sdk-compat-0.3-client-transport-spi diff --git a/compat-0.3/pom.xml b/compat-0.3/pom.xml index d11960ecc..a8d75df65 100644 --- a/compat-0.3/pom.xml +++ b/compat-0.3/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-compat-0.3-parent diff --git a/compat-0.3/reference/grpc/pom.xml b/compat-0.3/reference/grpc/pom.xml index 182493e98..4d77d3bf4 100644 --- a/compat-0.3/reference/grpc/pom.xml +++ b/compat-0.3/reference/grpc/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/compat-0.3/reference/jsonrpc/pom.xml b/compat-0.3/reference/jsonrpc/pom.xml index c8e4ae502..2a3bd7f6a 100644 --- a/compat-0.3/reference/jsonrpc/pom.xml +++ b/compat-0.3/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-compat-0.3-reference-jsonrpc diff --git a/compat-0.3/reference/rest/pom.xml b/compat-0.3/reference/rest/pom.xml index d885f4a70..bcc9e882d 100644 --- a/compat-0.3/reference/rest/pom.xml +++ b/compat-0.3/reference/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-compat-0.3-reference-rest diff --git a/compat-0.3/server-conversion/pom.xml b/compat-0.3/server-conversion/pom.xml index ef107858d..388d434d0 100644 --- a/compat-0.3/server-conversion/pom.xml +++ b/compat-0.3/server-conversion/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT .. a2a-java-sdk-compat-0.3-server-conversion diff --git a/compat-0.3/spec-grpc/pom.xml b/compat-0.3/spec-grpc/pom.xml index 5b87ab7f2..e2b9e7d8d 100644 --- a/compat-0.3/spec-grpc/pom.xml +++ b/compat-0.3/spec-grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT .. a2a-java-sdk-compat-0.3-spec-grpc diff --git a/compat-0.3/spec/pom.xml b/compat-0.3/spec/pom.xml index 75bae0a6f..513a218a3 100644 --- a/compat-0.3/spec/pom.xml +++ b/compat-0.3/spec/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT .. a2a-java-sdk-compat-0.3-spec diff --git a/compat-0.3/tck/pom.xml b/compat-0.3/tck/pom.xml index 908e8307f..86b2da231 100644 --- a/compat-0.3/tck/pom.xml +++ b/compat-0.3/tck/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT .. diff --git a/compat-0.3/transport/grpc/pom.xml b/compat-0.3/transport/grpc/pom.xml index f7b45c080..4246c443f 100644 --- a/compat-0.3/transport/grpc/pom.xml +++ b/compat-0.3/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../.. a2a-java-sdk-compat-0.3-transport-grpc diff --git a/compat-0.3/transport/jsonrpc/pom.xml b/compat-0.3/transport/jsonrpc/pom.xml index 9eba8e0fb..bc6e46248 100644 --- a/compat-0.3/transport/jsonrpc/pom.xml +++ b/compat-0.3/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../.. a2a-java-sdk-compat-0.3-transport-jsonrpc diff --git a/compat-0.3/transport/rest/pom.xml b/compat-0.3/transport/rest/pom.xml index fffa3691c..6cb198672 100644 --- a/compat-0.3/transport/rest/pom.xml +++ b/compat-0.3/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-compat-0.3-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../.. a2a-java-sdk-compat-0.3-transport-rest diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml index eb558b31f..b584e70da 100644 --- a/examples/cloud-deployment/server/pom.xml +++ b/examples/cloud-deployment/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../../pom.xml diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index ea131ebf0..040165ac2 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-examples-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-examples-client diff --git a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java index 99563140e..c54b23c0b 100644 --- a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java +++ b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldRunner.java @@ -1,12 +1,12 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? -//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.CR1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.CR1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.CR1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.CR1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.CR1 -//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.CR1 +//DEPS org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.CR2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.CR2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-grpc:1.0.0.CR2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-client-transport-rest:1.0.0.CR2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client:1.0.0.CR2-SNAPSHOT +//DEPS org.a2aproject.sdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.CR2-SNAPSHOT //DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 //DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml index 4e855d896..17ab8350d 100644 --- a/examples/helloworld/pom.xml +++ b/examples/helloworld/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml index 4f7fbdbb6..2b652064f 100644 --- a/examples/helloworld/server/pom.xml +++ b/examples/helloworld/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-examples-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-examples-server diff --git a/extras/common/pom.xml b/extras/common/pom.xml index 886c2e5c8..16d66e4a1 100644 --- a/extras/common/pom.xml +++ b/extras/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/extras/http-client-android/pom.xml b/extras/http-client-android/pom.xml index e309690f3..dab11a4ee 100644 --- a/extras/http-client-android/pom.xml +++ b/extras/http-client-android/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-http-client-android diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml index 9fe115eae..2013ed1fa 100644 --- a/extras/http-client-vertx/pom.xml +++ b/extras/http-client-vertx/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-http-client-vertx diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml index ff7e9636c..6b94aff33 100644 --- a/extras/opentelemetry/client-propagation/pom.xml +++ b/extras/opentelemetry/client-propagation/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-opentelemetry-client-propagation diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml index 0288b7173..e2c50a94f 100644 --- a/extras/opentelemetry/client/pom.xml +++ b/extras/opentelemetry/client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-opentelemetry-client diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml index c185d1177..56d459b90 100644 --- a/extras/opentelemetry/common/pom.xml +++ b/extras/opentelemetry/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-opentelemetry-common diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml index 0130daf0b..73ad8a41d 100644 --- a/extras/opentelemetry/integration-tests/pom.xml +++ b/extras/opentelemetry/integration-tests/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-opentelemetry-integration-tests diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index 75fece2cf..f696b09ad 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index d68402770..cea8b2f69 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-opentelemetry-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-opentelemetry-server diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 25ec1cd34..c7cbd3d6b 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-extras-push-notification-config-store-database-jpa diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index 23c53c259..4e8c8ccde 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml index 1ed237159..da4c25fb1 100644 --- a/extras/queue-manager-replicated/pom.xml +++ b/extras/queue-manager-replicated/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 78aec8f8c..1d9fbef12 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml index ca689a9ab..aecfd8bed 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml index b208d307b..69298985e 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml index c99f1706b..77db61dae 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml index 04691bca6..588a217a4 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml index b74988104..7f70bd619 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index b16e0bd1c..64051c805 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-queue-manager-replicated-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 15857366e..fc5042f77 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-extras-task-store-database-jpa diff --git a/http-client/pom.xml b/http-client/pom.xml index f678b58fb..d6f5264cc 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-http-client diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml index 7594e4176..3ca61bc97 100644 --- a/integrations/microprofile-config/pom.xml +++ b/integrations/microprofile-config/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-microprofile-config diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml index ec18e7891..2f97f16ec 100644 --- a/jsonrpc-common/pom.xml +++ b/jsonrpc-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-jsonrpc-common diff --git a/pom.xml b/pom.xml index fd55af76d..9b50089ba 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT pom diff --git a/reference/common/pom.xml b/reference/common/pom.xml index f723702c4..f0b8c5426 100644 --- a/reference/common/pom.xml +++ b/reference/common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-common diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index 7762528dd..2d479b555 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -6,7 +6,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 1f4205225..3a5abc472 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-jsonrpc diff --git a/reference/multiversion-jsonrpc/pom.xml b/reference/multiversion-jsonrpc/pom.xml index 2910039bb..38a1a51bc 100644 --- a/reference/multiversion-jsonrpc/pom.xml +++ b/reference/multiversion-jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-multiversion-jsonrpc diff --git a/reference/multiversion-rest/pom.xml b/reference/multiversion-rest/pom.xml index f5015bd3d..2211fc9a5 100644 --- a/reference/multiversion-rest/pom.xml +++ b/reference/multiversion-rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-multiversion-rest diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index d2d21d034..4673d3f12 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-reference-rest diff --git a/server-common/pom.xml b/server-common/pom.xml index da1d52a13..fe6d7377a 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-server-common diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index 7c33db060..d3f2651cf 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-spec-grpc diff --git a/spec/pom.xml b/spec/pom.xml index d981beb90..0d0f97772 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-spec diff --git a/tck/pom.xml b/tck/pom.xml index 674862bce..74dd7c7cf 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT a2a-java-sdk-tck-sut A2A Java SDK: SUT for TCK diff --git a/test-utils-docker/pom.xml b/test-utils-docker/pom.xml index 5ac16792b..a29991a3d 100644 --- a/test-utils-docker/pom.xml +++ b/test-utils-docker/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../pom.xml diff --git a/tests/multiversion/grpc/pom.xml b/tests/multiversion/grpc/pom.xml index f3e0873f6..b3ae01059 100644 --- a/tests/multiversion/grpc/pom.xml +++ b/tests/multiversion/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../../pom.xml a2a-java-sdk-tests-multiversion-grpc diff --git a/tests/multiversion/jsonrpc/pom.xml b/tests/multiversion/jsonrpc/pom.xml index 7f235f088..d440be044 100644 --- a/tests/multiversion/jsonrpc/pom.xml +++ b/tests/multiversion/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../../pom.xml a2a-java-sdk-tests-multiversion-jsonrpc diff --git a/tests/multiversion/rest/pom.xml b/tests/multiversion/rest/pom.xml index f07916595..2f8b0ee24 100644 --- a/tests/multiversion/rest/pom.xml +++ b/tests/multiversion/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../../pom.xml a2a-java-sdk-tests-multiversion-rest diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index 3ac04127f..1cf8b02ff 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-tests-server-common diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index da51eb47a..d836d257c 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-grpc diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index 914c3f656..e7937722f 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-jsonrpc diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 3a0ce691a..4c0e5a4c6 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -7,7 +7,7 @@ org.a2aproject.sdk a2a-java-sdk-parent - 1.0.0.CR1 + 1.0.0.CR2-SNAPSHOT ../../pom.xml a2a-java-sdk-transport-rest From 50327b40f4b3b039aa2c7ebebcaf91789e21e54b Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 26 May 2026 11:45:56 +0100 Subject: [PATCH 176/192] fix: Propagate CDI context to AgentExecutor thread --- compat-0.3/reference/grpc/pom.xml | 4 ++ .../AbstractA2AServerServerTest_v0_3.java | 38 ++++++++++++++++ .../AgentExecutorProducer_v0_3.java | 13 ++++++ .../conversion/RequestScopedBean_v0_3.java | 11 +++++ extras/opentelemetry/pom.xml | 1 - extras/opentelemetry/server/pom.xml | 6 --- .../AsyncManagedExecutorProducer.java | 36 ++++++---------- .../AsyncManagedExecutorProducerTest.java | 23 +++++----- .../apps/common/AbstractA2AServerTest.java | 43 +++++++++++++++++++ .../apps/common/AgentExecutorProducer.java | 12 ++++++ .../server/apps/common/RequestScopedBean.java | 11 +++++ 11 files changed, 158 insertions(+), 40 deletions(-) create mode 100644 compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java rename {extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry => reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus}/AsyncManagedExecutorProducer.java (59%) rename {extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry => reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus}/AsyncManagedExecutorProducerTest.java (89%) create mode 100644 tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/RequestScopedBean.java diff --git a/compat-0.3/reference/grpc/pom.xml b/compat-0.3/reference/grpc/pom.xml index 4d77d3bf4..ad834439e 100644 --- a/compat-0.3/reference/grpc/pom.xml +++ b/compat-0.3/reference/grpc/pom.xml @@ -31,6 +31,10 @@ ${project.groupId} a2a-java-sdk-compat-0.3-transport-grpc
            + + ${project.groupId} + a2a-java-sdk-reference-common + ${project.groupId} a2a-java-sdk-server-common diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java index 7ad8b45c0..016f361b8 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java @@ -301,6 +301,44 @@ public void testSendMessageNewMessageSuccess() throws Exception { assertEquals("test message", ((TextPart_v0_3) part).getText()); } + @Test + public void testRequestScopedBeanAvailableOnAgentExecutorThread() throws Exception { + Message_v0_3 message = new Message_v0_3.Builder() + .messageId("request-scoped-test") + .role(Message_v0_3.Role.USER) + .parts(new TextPart_v0_3("request-scoped:test")) + .build(); + + CountDownLatch latch = new CountDownLatch(1); + AtomicReference receivedTask = new AtomicReference<>(); + AtomicReference errorRef = new AtomicReference<>(); + + getNonStreamingClient().sendMessage(message, List.of((event, agentCard) -> { + if (event instanceof TaskEvent_v0_3 te) { + receivedTask.set(te.getTask()); + if (te.getTask().getStatus().state() == TaskState_v0_3.COMPLETED) { + latch.countDown(); + } + } + }), error -> { + errorRef.set(error); + latch.countDown(); + }); + + assertTrue(latch.await(10, TimeUnit.SECONDS), "Request should complete within timeout"); + assertNull(errorRef.get(), "Should not have received an error"); + + Task_v0_3 task = receivedTask.get(); + assertNotNull(task, "Should have received a task"); + assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); + assertNotNull(task.getArtifacts()); + assertFalse(task.getArtifacts().isEmpty()); + + Part_v0_3 part = task.getArtifacts().get(0).parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); + assertEquals("request-scoped:request-scoped-value", ((TextPart_v0_3) part).getText()); + } + @Test public void testSendMessageExistingTaskSuccess() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java index 2a684f391..1e06f9b47 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java @@ -4,6 +4,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; import org.a2aproject.sdk.server.agentexecution.AgentExecutor; import org.a2aproject.sdk.server.agentexecution.RequestContext; @@ -17,6 +18,9 @@ @IfBuildProfile("test") public class AgentExecutorProducer_v0_3 { + @Inject + RequestScopedBean_v0_3 requestScopedBean; + @Produces public AgentExecutor agentExecutor() { return new AgentExecutor() { @@ -25,6 +29,15 @@ public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2 String taskId = context.getTaskId(); String input = context.getMessage() != null ? extractTextFromMessage(context.getMessage()) : ""; + // Request-scoped bean test: verify CDI request context propagation + if (input.startsWith("request-scoped:")) { + agentEmitter.startWork(); + String value = requestScopedBean.getValue(); + agentEmitter.addArtifact(List.of(new TextPart("request-scoped:" + value))); + agentEmitter.complete(); + return; + } + // Special handling for multi-event test (routed by message content) if (input.startsWith("multi-event:first")) { agentEmitter.startWork(); diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java new file mode 100644 index 000000000..825735f8f --- /dev/null +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java @@ -0,0 +1,11 @@ +package org.a2aproject.sdk.compat03.conversion; + +import jakarta.enterprise.context.RequestScoped; + +@RequestScoped +public class RequestScopedBean_v0_3 { + + public String getValue() { + return "request-scoped-value"; + } +} diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml index f696b09ad..7fd2576e1 100644 --- a/extras/opentelemetry/pom.xml +++ b/extras/opentelemetry/pom.xml @@ -19,7 +19,6 @@ 2.0.1 - 1.3 diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml index cea8b2f69..ab450dffc 100644 --- a/extras/opentelemetry/server/pom.xml +++ b/extras/opentelemetry/server/pom.xml @@ -39,12 +39,6 @@ pom provided - - org.eclipse.microprofile.context-propagation - microprofile-context-propagation-api - ${version.org.eclipse.microprofile.context-propagation} - provided - jakarta.enterprise jakarta.enterprise.cdi-api diff --git a/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducer.java b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/AsyncManagedExecutorProducer.java similarity index 59% rename from extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducer.java rename to reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/AsyncManagedExecutorProducer.java index b3dccf38c..e1f9ad291 100644 --- a/extras/opentelemetry/server/src/main/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducer.java +++ b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/AsyncManagedExecutorProducer.java @@ -1,37 +1,28 @@ -package org.a2aproject.sdk.extras.opentelemetry; +package org.a2aproject.sdk.server.common.quarkus; + +import java.util.concurrent.Executor; -import org.a2aproject.sdk.server.util.async.Internal; import jakarta.annotation.PostConstruct; import jakarta.annotation.Priority; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Alternative; import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; -import java.util.concurrent.Executor; + +import org.a2aproject.sdk.server.util.async.Internal; import org.eclipse.microprofile.context.ManagedExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Alternative executor producer that provides a ManagedExecutor with OpenTelemetry context propagation. + * Alternative executor producer that provides a ManagedExecutor with CDI context propagation. *

            - * This producer replaces the default {@code AsyncExecutorProducer} when the OpenTelemetry extras module - * is included in the application. The ManagedExecutor ensures that OpenTelemetry trace context is - * properly propagated across asynchronous boundaries. + * This producer replaces the default {@code AsyncExecutorProducer} so that CDI request context + * (and any other registered thread context types) are propagated to the agent executor thread. + * This allows {@code @RequestScoped} beans to be injected and used inside + * {@link org.a2aproject.sdk.server.agentexecution.AgentExecutor#execute}. *

            * Priority 20 ensures this alternative takes precedence over the default producer (priority 10). - * - *

            Configuration

            - * The ManagedExecutor is container-managed and injected via CDI. Its configuration depends on the - * runtime environment: - *
              - *
            • Quarkus: Configure via {@code quarkus.thread-pool.*} properties
            • - *
            • Other runtimes: Consult your MicroProfile Context Propagation implementation documentation
            • - *
            - *

            - * Unlike the default {@code AsyncExecutorProducer}, this producer does not use the {@code a2a.executor.*} - * configuration properties. The executor pool sizing and behavior are controlled by the container's - * ManagedExecutor configuration. * * @see org.eclipse.microprofile.context.ManagedExecutor */ @@ -40,13 +31,13 @@ @Priority(20) public class AsyncManagedExecutorProducer { private static final Logger LOGGER = LoggerFactory.getLogger(AsyncManagedExecutorProducer.class); - + @Inject ManagedExecutor managedExecutor; @PostConstruct public void init() { - LOGGER.info("Initializing OpenTelemetry-aware ManagedExecutor for async operations"); + LOGGER.info("Initializing ManagedExecutor for async operations with CDI context propagation"); if (managedExecutor == null) { LOGGER.warn("ManagedExecutor not available - context propagation may not work correctly"); } @@ -55,11 +46,10 @@ public void init() { @Produces @Internal public Executor produce() { - LOGGER.debug("Using ManagedExecutor for async operations with OpenTelemetry context propagation"); + LOGGER.debug("Using ManagedExecutor for async operations with CDI context propagation"); if (managedExecutor == null) { throw new IllegalStateException("ManagedExecutor not injected - ensure MicroProfile Context Propagation is available"); } return managedExecutor; } - } diff --git a/extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducerTest.java b/reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/AsyncManagedExecutorProducerTest.java similarity index 89% rename from extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducerTest.java rename to reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/AsyncManagedExecutorProducerTest.java index 0921e3d03..056047e5f 100644 --- a/extras/opentelemetry/server/src/test/java/org/a2aproject/sdk/extras/opentelemetry/AsyncManagedExecutorProducerTest.java +++ b/reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/AsyncManagedExecutorProducerTest.java @@ -1,9 +1,18 @@ -package org.a2aproject.sdk.extras.opentelemetry; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +package org.a2aproject.sdk.server.common.quarkus; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +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 static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import java.util.concurrent.Executor; + import org.eclipse.microprofile.context.ManagedExecutor; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -39,7 +48,6 @@ void init_withValidManagedExecutor_logsSuccessfully() { void init_withNullManagedExecutor_logsWarning() { producer.managedExecutor = null; - // Should not throw, just log warning assertDoesNotThrow(() -> producer.init()); assertNull(producer.managedExecutor); } @@ -88,21 +96,18 @@ void produce_returnsSameInstanceOnMultipleCalls() { class CDIIntegrationTests { @Test void producer_hasCorrectAnnotations() { - // Verify class has @ApplicationScoped assertTrue( AsyncManagedExecutorProducer.class.isAnnotationPresent( jakarta.enterprise.context.ApplicationScoped.class ) ); - // Verify class has @Alternative assertTrue( AsyncManagedExecutorProducer.class.isAnnotationPresent( jakarta.enterprise.inject.Alternative.class ) ); - // Verify class has @Priority with value 20 assertTrue( AsyncManagedExecutorProducer.class.isAnnotationPresent( jakarta.annotation.Priority.class @@ -120,12 +125,10 @@ void producer_hasCorrectAnnotations() { void produceMethod_hasCorrectAnnotations() throws NoSuchMethodException { var method = AsyncManagedExecutorProducer.class.getMethod("produce"); - // Verify method has @Produces assertTrue( method.isAnnotationPresent(jakarta.enterprise.inject.Produces.class) ); - // Verify method has @Internal assertTrue( method.isAnnotationPresent(org.a2aproject.sdk.server.util.async.Internal.class) ); diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index da46e8d61..110708d96 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -504,6 +504,49 @@ public void testSendMessageNewMessageSuccess() throws Exception { assertEquals("test message", ((TextPart) part).text()); } + @Test + public void testRequestScopedBeanAvailableOnAgentExecutorThread() throws Exception { + Message message = Message.builder() + .messageId("request-scoped-test") + .role(Message.Role.ROLE_USER) + .parts(new TextPart("request-scoped:test")) + .build(); + + CountDownLatch latch = new CountDownLatch(1); + AtomicReference receivedTask = new AtomicReference<>(); + AtomicReference errorRef = new AtomicReference<>(); + + getNonStreamingClient().sendMessage(message, List.of((event, agentCard) -> { + if (event instanceof TaskEvent te) { + receivedTask.set(te.getTask()); + if (te.getTask().status().state() == TaskState.TASK_STATE_COMPLETED) { + latch.countDown(); + } + } else if (event instanceof TaskUpdateEvent tue) { + receivedTask.set(tue.getTask()); + if (tue.getTask().status().state() == TaskState.TASK_STATE_COMPLETED) { + latch.countDown(); + } + } + }), error -> { + errorRef.set(error); + latch.countDown(); + }); + + assertTrue(latch.await(10, TimeUnit.SECONDS), "Request should complete within timeout"); + assertNull(errorRef.get(), "Should not have received an error"); + + Task task = receivedTask.get(); + assertNotNull(task, "Should have received a task"); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); + assertNotNull(task.artifacts()); + assertFalse(task.artifacts().isEmpty()); + + Part part = task.artifacts().get(0).parts().get(0); + assertInstanceOf(TextPart.class, part); + assertEquals("request-scoped:request-scoped-value", ((TextPart) part).text()); + } + @Test public void testSendMessageExistingTaskSuccess() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java index ba9ce0676..b46519e30 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AgentExecutorProducer.java @@ -42,6 +42,9 @@ public class AgentExecutorProducer { @PublicAgentCard AgentCard agentCard; + @Inject + RequestScopedBean requestScopedBean; + @Produces public AgentExecutor agentExecutor() { return new AgentExecutor() { @@ -56,6 +59,15 @@ public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2 return; } + // Request-scoped bean test: verify CDI request context propagation + if (input.startsWith("request-scoped:")) { + agentEmitter.startWork(); + String value = requestScopedBean.getValue(); + agentEmitter.addArtifact(List.of(new TextPart("request-scoped:" + value))); + agentEmitter.complete(); + return; + } + // Special handling for multi-event test (routed by message content) if (input.startsWith("multi-event:first")) { agentEmitter.startWork(); diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/RequestScopedBean.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/RequestScopedBean.java new file mode 100644 index 000000000..0d6db4695 --- /dev/null +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/RequestScopedBean.java @@ -0,0 +1,11 @@ +package org.a2aproject.sdk.server.apps.common; + +import jakarta.enterprise.context.RequestScoped; + +@RequestScoped +public class RequestScopedBean { + + public String getValue() { + return "request-scoped-value"; + } +} From 34f3b9c23c302e5a411347ede569e7fc97b2b13c Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 19 May 2026 15:52:55 +0100 Subject: [PATCH 177/192] feat!: Convert spec classes to records This became apparent since in non-Quarkus environments you have to set a bunch of JVM flags, and also introduce default constructors, which in turn means making fields non-final. Additionally, added default constructors for some CDI beans to work in stricter CDI environments than Quarkus --- .../client/ClientTaskManager_v0_3.java | 43 ++- .../sdk/compat03/A2A_v0_3_Test.java | 78 ++--- .../jsonrpc/sse/SSEEventListener_v0_3.java | 2 +- .../JSONRPCTransportStreaming_v0_3_Test.java | 16 +- .../jsonrpc/JSONRPCTransport_v0_3_Test.java | 126 ++++---- .../sse/SSEEventListener_v0_3_Test.java | 44 +-- .../rest/RestTransport_v0_3_Test.java | 116 +++---- .../auth/AuthInterceptor_v0_3.java | 4 +- .../auth/AuthInterceptor_v0_3_Test.java | 6 +- .../grpc/quarkus/QuarkusGrpcHandler_v0_3.java | 14 + ...arkusA2ARest_v0_3_WithAuthAndroidTest.java | 4 +- .../QuarkusA2ARest_v0_3_WithAuthTest.java | 4 +- ...QuarkusA2ARest_v0_3_WithAuthVertxTest.java | 4 +- .../Convert_v0_3_To10RequestHandler.java | 6 + .../mappers/domain/MessageMapper_v0_3.java | 18 +- .../mappers/domain/PartMapper_v0_3.java | 10 +- .../TaskArtifactUpdateEventMapper_v0_3.java | 14 +- .../mappers/domain/TaskMapper_v0_3.java | 20 +- .../TaskStatusUpdateEventMapper_v0_3.java | 8 +- .../AbstractA2AServerServerTest_v0_3.java | 284 +++++++++--------- .../AbstractA2AServerWithAuthTest_v0_3.java | 14 +- .../mappers/domain/TaskMapper_v0_3_Test.java | 20 +- .../compat03/grpc/utils/ProtoUtils_v0_3.java | 130 ++++---- .../grpc/utils/ToProto_v0_3_Test.java | 2 +- .../sdk/compat03/json/JsonUtil_v0_3.java | 14 +- .../spec/APIKeySecurityScheme_v0_3.java | 44 +-- .../sdk/compat03/spec/DataPart_v0_3.java | 37 +-- .../sdk/compat03/spec/EventKind_v0_3.java | 2 +- .../sdk/compat03/spec/FilePart_v0_3.java | 38 +-- .../spec/HTTPAuthSecurityScheme_v0_3.java | 47 +-- .../compat03/spec/IntegerJsonrpcId_v0_3.java | 4 - .../compat03/spec/MessageSendParams_v0_3.java | 1 - .../sdk/compat03/spec/Message_v0_3.java | 119 ++------ .../spec/MutualTLSSecurityScheme_v0_3.java | 36 +-- .../spec/OAuth2SecurityScheme_v0_3.java | 47 +-- .../OpenIdConnectSecurityScheme_v0_3.java | 41 +-- .../sdk/compat03/spec/Part_v0_3.java | 13 +- .../compat03/spec/SecurityScheme_v0_3.java | 5 +- .../spec/StreamingEventKind_v0_3.java | 2 +- .../compat03/spec/StringJsonrpcId_v0_3.java | 4 - .../spec/TaskArtifactUpdateEvent_v0_3.java | 91 ++---- .../spec/TaskStatusUpdateEvent_v0_3.java | 82 ++--- .../sdk/compat03/spec/Task_v0_3.java | 80 ++--- .../sdk/compat03/spec/TextPart_v0_3.java | 37 +-- .../sdk/compat03/util/Utils_v0_3.java | 6 +- .../spec/SubTypeSerialization_v0_3_Test.java | 26 +- .../spec/TaskSerialization_v0_3_Test.java | 168 +++++------ .../grpc/handler/GrpcHandler_v0_3_Test.java | 38 +-- .../handler/JSONRPCHandler_v0_3_Test.java | 138 ++++----- .../rest/handler/RestHandler_v0_3_Test.java | 30 +- .../MultiVersion_v0_3_RestWithAuthTest.java | 4 +- 51 files changed, 936 insertions(+), 1205 deletions(-) delete mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IntegerJsonrpcId_v0_3.java delete mode 100644 compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StringJsonrpcId_v0_3.java diff --git a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientTaskManager_v0_3.java b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientTaskManager_v0_3.java index 0a29a0aa6..1d8bc1de7 100644 --- a/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientTaskManager_v0_3.java +++ b/compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/client/ClientTaskManager_v0_3.java @@ -52,10 +52,10 @@ public Task_v0_3 saveTaskEvent(Task_v0_3 task) throws A2AClientInvalidArgsError_ public Task_v0_3 saveTaskEvent(TaskStatusUpdateEvent_v0_3 taskStatusUpdateEvent) throws A2AClientError_v0_3 { if (taskId == null) { - taskId = taskStatusUpdateEvent.getTaskId(); + taskId = taskStatusUpdateEvent.taskId(); } if (contextId == null) { - contextId = taskStatusUpdateEvent.getContextId(); + contextId = taskStatusUpdateEvent.contextId(); } Task_v0_3 task = currentTask; if (task == null) { @@ -67,31 +67,27 @@ public Task_v0_3 saveTaskEvent(TaskStatusUpdateEvent_v0_3 taskStatusUpdateEvent) } Task_v0_3.Builder taskBuilder = new Task_v0_3.Builder(task); - if (taskStatusUpdateEvent.getStatus().message() != null) { - if (task.getHistory() == null) { - taskBuilder.history(taskStatusUpdateEvent.getStatus().message()); - } else { - List history = new ArrayList<>(task.getHistory()); - history.add(taskStatusUpdateEvent.getStatus().message()); - taskBuilder.history(history); - } + if (taskStatusUpdateEvent.status().message() != null) { + List history = new ArrayList<>(task.history()); + history.add(taskStatusUpdateEvent.status().message()); + taskBuilder.history(history); } - if (taskStatusUpdateEvent.getMetadata() != null) { - Map newMetadata = task.getMetadata() != null ? new HashMap<>(task.getMetadata()) : new HashMap<>(); - newMetadata.putAll(taskStatusUpdateEvent.getMetadata()); + if (taskStatusUpdateEvent.metadata() != null) { + Map newMetadata = task.metadata() != null ? new HashMap<>(task.metadata()) : new HashMap<>(); + newMetadata.putAll(taskStatusUpdateEvent.metadata()); taskBuilder.metadata(newMetadata); } - taskBuilder.status(taskStatusUpdateEvent.getStatus()); + taskBuilder.status(taskStatusUpdateEvent.status()); currentTask = taskBuilder.build(); return currentTask; } public Task_v0_3 saveTaskEvent(TaskArtifactUpdateEvent_v0_3 taskArtifactUpdateEvent) { if (taskId == null) { - taskId = taskArtifactUpdateEvent.getTaskId(); + taskId = taskArtifactUpdateEvent.taskId(); } if (contextId == null) { - contextId = taskArtifactUpdateEvent.getContextId(); + contextId = taskArtifactUpdateEvent.contextId(); } Task_v0_3 task = currentTask; if (task == null) { @@ -115,13 +111,10 @@ public Task_v0_3 saveTaskEvent(TaskArtifactUpdateEvent_v0_3 taskArtifactUpdateEv */ public Task_v0_3 updateWithMessage(Message_v0_3 message, Task_v0_3 task) { Task_v0_3.Builder taskBuilder = new Task_v0_3.Builder(task); - List history = task.getHistory(); - if (history == null) { - history = new ArrayList<>(); - } - if (task.getStatus().message() != null) { - history.add(task.getStatus().message()); - taskBuilder.status(new TaskStatus_v0_3(task.getStatus().state(), null, task.getStatus().timestamp())); + List history = new ArrayList<>(task.history()); + if (task.status().message() != null) { + history.add(task.status().message()); + taskBuilder.status(new TaskStatus_v0_3(task.status().state(), null, task.status().timestamp())); } history.add(message); taskBuilder.history(history); @@ -132,8 +125,8 @@ public Task_v0_3 updateWithMessage(Message_v0_3 message, Task_v0_3 task) { private void saveTask(Task_v0_3 task) { currentTask = task; if (taskId == null) { - taskId = currentTask.getId(); - contextId = currentTask.getContextId(); + taskId = currentTask.id(); + contextId = currentTask.contextId(); } } } \ No newline at end of file diff --git a/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/A2A_v0_3_Test.java b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/A2A_v0_3_Test.java index 1187518eb..f5a8ad5ef 100644 --- a/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/A2A_v0_3_Test.java +++ b/compat-0.3/client/base/src/test/java/org/a2aproject/sdk/compat03/A2A_v0_3_Test.java @@ -20,12 +20,12 @@ public void testToUserMessage() { String text = "Hello, world!"; Message_v0_3 message = A2A_v0_3.toUserMessage(text); - assertEquals(Message_v0_3.Role.USER, message.getRole()); - assertEquals(1, message.getParts().size()); - assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); - assertNotNull(message.getMessageId()); - assertNull(message.getContextId()); - assertNull(message.getTaskId()); + assertEquals(Message_v0_3.Role.USER, message.role()); + assertEquals(1, message.parts().size()); + assertEquals(text, ((TextPart_v0_3) message.parts().get(0)).text()); + assertNotNull(message.messageId()); + assertNull(message.contextId()); + assertNull(message.taskId()); } @Test @@ -34,8 +34,8 @@ public void testToUserMessageWithId() { String messageId = "test-message-id"; Message_v0_3 message = A2A_v0_3.toUserMessage(text, messageId); - assertEquals(Message_v0_3.Role.USER, message.getRole()); - assertEquals(messageId, message.getMessageId()); + assertEquals(Message_v0_3.Role.USER, message.role()); + assertEquals(messageId, message.messageId()); } @Test @@ -43,10 +43,10 @@ public void testToAgentMessage() { String text = "Hello, I'm an agent!"; Message_v0_3 message = A2A_v0_3.toAgentMessage(text); - assertEquals(Message_v0_3.Role.AGENT, message.getRole()); - assertEquals(1, message.getParts().size()); - assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); - assertNotNull(message.getMessageId()); + assertEquals(Message_v0_3.Role.AGENT, message.role()); + assertEquals(1, message.parts().size()); + assertEquals(text, ((TextPart_v0_3) message.parts().get(0)).text()); + assertNotNull(message.messageId()); } @Test @@ -55,8 +55,8 @@ public void testToAgentMessageWithId() { String messageId = "agent-message-id"; Message_v0_3 message = A2A_v0_3.toAgentMessage(text, messageId); - assertEquals(Message_v0_3.Role.AGENT, message.getRole()); - assertEquals(messageId, message.getMessageId()); + assertEquals(Message_v0_3.Role.AGENT, message.role()); + assertEquals(messageId, message.messageId()); } @Test @@ -67,14 +67,14 @@ public void testCreateUserTextMessage() { Message_v0_3 message = A2A_v0_3.createUserTextMessage(text, contextId, taskId); - assertEquals(Message_v0_3.Role.USER, message.getRole()); - assertEquals(contextId, message.getContextId()); - assertEquals(taskId, message.getTaskId()); - assertEquals(1, message.getParts().size()); - assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); - assertNotNull(message.getMessageId()); - assertNull(message.getMetadata()); - assertNull(message.getReferenceTaskIds()); + assertEquals(Message_v0_3.Role.USER, message.role()); + assertEquals(contextId, message.contextId()); + assertEquals(taskId, message.taskId()); + assertEquals(1, message.parts().size()); + assertEquals(text, ((TextPart_v0_3) message.parts().get(0)).text()); + assertNotNull(message.messageId()); + assertNull(message.metadata()); + assertNull(message.referenceTaskIds()); } @Test @@ -83,11 +83,11 @@ public void testCreateUserTextMessageWithNullParams() { Message_v0_3 message = A2A_v0_3.createUserTextMessage(text, null, null); - assertEquals(Message_v0_3.Role.USER, message.getRole()); - assertNull(message.getContextId()); - assertNull(message.getTaskId()); - assertEquals(1, message.getParts().size()); - assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); + assertEquals(Message_v0_3.Role.USER, message.role()); + assertNull(message.contextId()); + assertNull(message.taskId()); + assertEquals(1, message.parts().size()); + assertEquals(text, ((TextPart_v0_3) message.parts().get(0)).text()); } @Test @@ -98,12 +98,12 @@ public void testCreateAgentTextMessage() { Message_v0_3 message = A2A_v0_3.createAgentTextMessage(text, contextId, taskId); - assertEquals(Message_v0_3.Role.AGENT, message.getRole()); - assertEquals(contextId, message.getContextId()); - assertEquals(taskId, message.getTaskId()); - assertEquals(1, message.getParts().size()); - assertEquals(text, ((TextPart_v0_3) message.getParts().get(0)).getText()); - assertNotNull(message.getMessageId()); + assertEquals(Message_v0_3.Role.AGENT, message.role()); + assertEquals(contextId, message.contextId()); + assertEquals(taskId, message.taskId()); + assertEquals(1, message.parts().size()); + assertEquals(text, ((TextPart_v0_3) message.parts().get(0)).text()); + assertNotNull(message.messageId()); } @Test @@ -117,12 +117,12 @@ public void testCreateAgentPartsMessage() { Message_v0_3 message = A2A_v0_3.createAgentPartsMessage(parts, contextId, taskId); - assertEquals(Message_v0_3.Role.AGENT, message.getRole()); - assertEquals(contextId, message.getContextId()); - assertEquals(taskId, message.getTaskId()); - assertEquals(2, message.getParts().size()); - assertEquals("Part 1", ((TextPart_v0_3) message.getParts().get(0)).getText()); - assertEquals("Part 2", ((TextPart_v0_3) message.getParts().get(1)).getText()); + assertEquals(Message_v0_3.Role.AGENT, message.role()); + assertEquals(contextId, message.contextId()); + assertEquals(taskId, message.taskId()); + assertEquals(2, message.parts().size()); + assertEquals("Part 1", ((TextPart_v0_3) message.parts().get(0)).text()); + assertEquals("Part 2", ((TextPart_v0_3) message.parts().get(1)).text()); } @Test diff --git a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3.java b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3.java index 6ae5a944c..8ca9aa0ee 100644 --- a/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3.java +++ b/compat-0.3/client/transport/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3.java @@ -77,7 +77,7 @@ private void handleMessage(JsonObject jsonObject, Future future) throws Js String resultJson = jsonObject.get("result").toString(); StreamingEventKind_v0_3 event = JsonUtil_v0_3.fromJson(resultJson, StreamingEventKind_v0_3.class); eventHandler.accept(event); - if (event instanceof TaskStatusUpdateEvent_v0_3 && ((TaskStatusUpdateEvent_v0_3) event).isFinal()) { + if (event instanceof TaskStatusUpdateEvent_v0_3 tsue && tsue.isFinal()) { future.cancel(true); // close SSE channel } } else { diff --git a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportStreaming_v0_3_Test.java b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportStreaming_v0_3_Test.java index 914b92078..022012607 100644 --- a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportStreaming_v0_3_Test.java +++ b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransportStreaming_v0_3_Test.java @@ -74,8 +74,8 @@ public void testSendStreamingMessageParams() { assertNotNull(params); assertEquals(message, params.message()); assertEquals(configuration, params.configuration()); - assertEquals(Message_v0_3.Role.USER, params.message().getRole()); - assertEquals("test message", ((TextPart_v0_3) params.message().getParts().get(0)).getText()); + assertEquals(Message_v0_3.Role.USER, params.message().role()); + assertEquals("test message", ((TextPart_v0_3) params.message().parts().get(0)).text()); } @Test @@ -159,16 +159,16 @@ public void testA2AClientResubscribeToTask() throws Exception { assertNotNull(eventKind); assertInstanceOf(Task_v0_3.class, eventKind); Task_v0_3 task = (Task_v0_3) eventKind; - assertEquals("2", task.getId()); - assertEquals("context-1234", task.getContextId()); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - List artifacts = task.getArtifacts(); + assertEquals("2", task.id()); + assertEquals("context-1234", task.contextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + List artifacts = task.artifacts(); assertEquals(1, artifacts.size()); Artifact_v0_3 artifact = artifacts.get(0); assertEquals("artifact-1", artifact.artifactId()); assertEquals("joke", artifact.name()); Part_v0_3 part = artifact.parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).text()); } } \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3_Test.java b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3_Test.java index b3ca67f9e..2af1a8cf3 100644 --- a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3_Test.java +++ b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/JSONRPCTransport_v0_3_Test.java @@ -121,18 +121,18 @@ public void testA2AClientSendMessage() throws Exception { EventKind_v0_3 result = client.sendMessage(params, null); assertInstanceOf(Task_v0_3.class, result); Task_v0_3 task = (Task_v0_3) result; - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); - assertNotNull(task.getContextId()); - assertEquals(TaskState_v0_3.COMPLETED,task.getStatus().state()); - assertEquals(1, task.getArtifacts().size()); - Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); + assertNotNull(task.contextId()); + assertEquals(TaskState_v0_3.COMPLETED,task.status().state()); + assertEquals(1, task.artifacts().size()); + Artifact_v0_3 artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); assertEquals("joke", artifact.name()); assertEquals(1, artifact.parts().size()); Part_v0_3 part = artifact.parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); - assertTrue(task.getMetadata().isEmpty()); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).text()); + assertTrue(task.metadata().isEmpty()); } @Test @@ -169,11 +169,11 @@ public void testA2AClientSendMessageWithMessageResponse() throws Exception { EventKind_v0_3 result = client.sendMessage(params, null); assertInstanceOf(Message_v0_3.class, result); Message_v0_3 agentMessage = (Message_v0_3) result; - assertEquals(Message_v0_3.Role.AGENT, agentMessage.getRole()); - Part_v0_3 part = agentMessage.getParts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); - assertEquals("msg-456", agentMessage.getMessageId()); + assertEquals(Message_v0_3.Role.AGENT, agentMessage.role()); + Part_v0_3 part = agentMessage.parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).text()); + assertEquals("msg-456", agentMessage.messageId()); } @@ -234,39 +234,39 @@ public void testA2AClientGetTask() throws Exception { JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); Task_v0_3 task = client.getTask(new TaskQueryParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", 10), null); - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); - assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.getContextId()); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - assertEquals(1, task.getArtifacts().size()); - Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); + assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.contextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + assertEquals(1, task.artifacts().size()); + Artifact_v0_3 artifact = task.artifacts().get(0); assertEquals(1, artifact.parts().size()); assertEquals("artifact-1", artifact.artifactId()); Part_v0_3 part = artifact.parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); - assertTrue(task.getMetadata().isEmpty()); - List history = task.getHistory(); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).text()); + assertTrue(task.metadata().isEmpty()); + List history = task.history(); assertNotNull(history); assertEquals(1, history.size()); Message_v0_3 message = history.get(0); - assertEquals(Message_v0_3.Role.USER, message.getRole()); - List> parts = message.getParts(); + assertEquals(Message_v0_3.Role.USER, message.role()); + List> parts = message.parts(); assertNotNull(parts); assertEquals(3, parts.size()); part = parts.get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("tell me a joke", ((TextPart_v0_3)part).getText()); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("tell me a joke", ((TextPart_v0_3)part).text()); part = parts.get(1); - assertEquals(Part_v0_3.Kind.FILE, part.getKind()); - FileContent_v0_3 filePart = ((FilePart_v0_3) part).getFile(); + assertEquals(Part_v0_3.Kind.FILE, ((FilePart_v0_3) part).kind()); + FileContent_v0_3 filePart = ((FilePart_v0_3) part).file(); assertEquals("file:///path/to/file.txt", ((FileWithUri_v0_3) filePart).uri()); assertEquals("text/plain", filePart.mimeType()); part = parts.get(2); - assertEquals(Part_v0_3.Kind.FILE, part.getKind()); - filePart = ((FilePart_v0_3) part).getFile(); + assertEquals(Part_v0_3.Kind.FILE, ((FilePart_v0_3) part).kind()); + filePart = ((FilePart_v0_3) part).file(); assertEquals("aGVsbG8=", ((FileWithBytes_v0_3) filePart).bytes()); assertEquals("hello.txt", filePart.name()); - assertTrue(task.getMetadata().isEmpty()); + assertTrue(task.metadata().isEmpty()); } @Test @@ -287,10 +287,10 @@ public void testA2AClientCancelTask() throws Exception { JSONRPCTransport_v0_3 client = new JSONRPCTransport_v0_3("http://localhost:4001"); Task_v0_3 task = client.cancelTask(new TaskIdParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", new HashMap<>()), null); - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); - assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.getContextId()); - assertEquals(TaskState_v0_3.CANCELED, task.getStatus().state()); - assertTrue(task.getMetadata().isEmpty()); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); + assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.contextId()); + assertEquals(TaskState_v0_3.CANCELED, task.status().state()); + assertTrue(task.metadata().isEmpty()); } @Test @@ -380,8 +380,8 @@ public void testA2AClientGetAgentCard() throws Exception { Map securitySchemes = agentCard.securitySchemes(); assertNotNull(securitySchemes); OpenIdConnectSecurityScheme_v0_3 google = (OpenIdConnectSecurityScheme_v0_3) securitySchemes.get("google"); - assertEquals("openIdConnect", google.getType()); - assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.getOpenIdConnectUrl()); + assertEquals("openIdConnect", google.type()); + assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.openIdConnectUrl()); List>> security = agentCard.security(); assertEquals(1, security.size()); Map> securityMap = security.get(0); @@ -469,8 +469,8 @@ public void testA2AClientGetAuthenticatedExtendedAgentCard() throws Exception { Map securitySchemes = agentCard.securitySchemes(); assertNotNull(securitySchemes); OpenIdConnectSecurityScheme_v0_3 google = (OpenIdConnectSecurityScheme_v0_3) securitySchemes.get("google"); - assertEquals("openIdConnect", google.getType()); - assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.getOpenIdConnectUrl()); + assertEquals("openIdConnect", google.type()); + assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.openIdConnectUrl()); List>> security = agentCard.security(); assertEquals(1, security.size()); Map> securityMap = security.get(0); @@ -551,18 +551,18 @@ public void testA2AClientSendMessageWithFilePart() throws Exception { EventKind_v0_3 result = client.sendMessage(params, null); assertInstanceOf(Task_v0_3.class, result); Task_v0_3 task = (Task_v0_3) result; - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); - assertNotNull(task.getContextId()); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - assertEquals(1, task.getArtifacts().size()); - Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); + assertNotNull(task.contextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + assertEquals(1, task.artifacts().size()); + Artifact_v0_3 artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); assertEquals("image-analysis", artifact.name()); assertEquals(1, artifact.parts().size()); Part_v0_3 part = artifact.parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("This is an image of a cat sitting on a windowsill.", ((TextPart_v0_3) part).getText()); - assertTrue(task.getMetadata().isEmpty()); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("This is an image of a cat sitting on a windowsill.", ((TextPart_v0_3) part).text()); + assertTrue(task.metadata().isEmpty()); } @Test @@ -609,18 +609,18 @@ public void testA2AClientSendMessageWithDataPart() throws Exception { EventKind_v0_3 result = client.sendMessage(params, null); assertInstanceOf(Task_v0_3.class, result); Task_v0_3 task = (Task_v0_3) result; - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); - assertNotNull(task.getContextId()); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - assertEquals(1, task.getArtifacts().size()); - Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); + assertNotNull(task.contextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + assertEquals(1, task.artifacts().size()); + Artifact_v0_3 artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); assertEquals("data-analysis", artifact.name()); assertEquals(1, artifact.parts().size()); Part_v0_3 part = artifact.parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("Processed weather data: Temperature is 25.5°C, humidity is 60.2% in San Francisco.", ((TextPart_v0_3) part).getText()); - assertTrue(task.getMetadata().isEmpty()); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("Processed weather data: Temperature is 25.5°C, humidity is 60.2% in San Francisco.", ((TextPart_v0_3) part).text()); + assertTrue(task.metadata().isEmpty()); } @Test @@ -667,17 +667,17 @@ public void testA2AClientSendMessageWithMixedParts() throws Exception { EventKind_v0_3 result = client.sendMessage(params, null); assertInstanceOf(Task_v0_3.class, result); Task_v0_3 task = (Task_v0_3) result; - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); - assertNotNull(task.getContextId()); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - assertEquals(1, task.getArtifacts().size()); - Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); + assertNotNull(task.contextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + assertEquals(1, task.artifacts().size()); + Artifact_v0_3 artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); assertEquals("mixed-analysis", artifact.name()); assertEquals(1, artifact.parts().size()); Part_v0_3 part = artifact.parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("Analyzed chart image and data: Bar chart showing quarterly data with values [10, 20, 30, 40].", ((TextPart_v0_3) part).getText()); - assertTrue(task.getMetadata().isEmpty()); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("Analyzed chart image and data: Bar chart showing quarterly data with values [10, 20, 30, 40].", ((TextPart_v0_3) part).text()); + assertTrue(task.metadata().isEmpty()); } } \ No newline at end of file diff --git a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3_Test.java b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3_Test.java index b968c59ee..8db887db5 100644 --- a/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3_Test.java +++ b/compat-0.3/client/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/client/transport/jsonrpc/sse/SSEEventListener_v0_3_Test.java @@ -49,9 +49,9 @@ public void testOnEventWithTaskResult() throws Exception { assertNotNull(receivedEvent.get()); assertTrue(receivedEvent.get() instanceof Task_v0_3); Task_v0_3 task = (Task_v0_3) receivedEvent.get(); - assertEquals("task-123", task.getId()); - assertEquals("context-456", task.getContextId()); - assertEquals(TaskState_v0_3.WORKING, task.getStatus().state()); + assertEquals("task-123", task.id()); + assertEquals("context-456", task.contextId()); + assertEquals(TaskState_v0_3.WORKING, task.status().state()); } @Test @@ -74,12 +74,12 @@ public void testOnEventWithMessageResult() throws Exception { assertNotNull(receivedEvent.get()); assertTrue(receivedEvent.get() instanceof Message_v0_3); Message_v0_3 message = (Message_v0_3) receivedEvent.get(); - assertEquals(Message_v0_3.Role.AGENT, message.getRole()); - assertEquals("msg-123", message.getMessageId()); - assertEquals("context-456", message.getContextId()); - assertEquals(1, message.getParts().size()); - assertTrue(message.getParts().get(0) instanceof TextPart_v0_3); - assertEquals("Hello, world!", ((TextPart_v0_3) message.getParts().get(0)).getText()); + assertEquals(Message_v0_3.Role.AGENT, message.role()); + assertEquals("msg-123", message.messageId()); + assertEquals("context-456", message.contextId()); + assertEquals(1, message.parts().size()); + assertTrue(message.parts().get(0) instanceof TextPart_v0_3); + assertEquals("Hello, world!", ((TextPart_v0_3) message.parts().get(0)).text()); } @Test @@ -102,10 +102,10 @@ public void testOnEventWithTaskStatusUpdateEventEvent() throws Exception { assertNotNull(receivedEvent.get()); assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent_v0_3); TaskStatusUpdateEvent_v0_3 taskStatusUpdateEvent = (TaskStatusUpdateEvent_v0_3) receivedEvent.get(); - assertEquals("1", taskStatusUpdateEvent.getTaskId()); - assertEquals("2", taskStatusUpdateEvent.getContextId()); + assertEquals("1", taskStatusUpdateEvent.taskId()); + assertEquals("2", taskStatusUpdateEvent.contextId()); assertFalse(taskStatusUpdateEvent.isFinal()); - assertEquals(TaskState_v0_3.SUBMITTED, taskStatusUpdateEvent.getStatus().state()); + assertEquals(TaskState_v0_3.SUBMITTED, taskStatusUpdateEvent.status().state()); } @Test @@ -129,15 +129,15 @@ public void testOnEventWithTaskArtifactUpdateEventEvent() throws Exception { assertTrue(receivedEvent.get() instanceof TaskArtifactUpdateEvent_v0_3); TaskArtifactUpdateEvent_v0_3 taskArtifactUpdateEvent = (TaskArtifactUpdateEvent_v0_3) receivedEvent.get(); - assertEquals("1", taskArtifactUpdateEvent.getTaskId()); - assertEquals("2", taskArtifactUpdateEvent.getContextId()); - assertFalse(taskArtifactUpdateEvent.isAppend()); - assertTrue(taskArtifactUpdateEvent.isLastChunk()); - Artifact_v0_3 artifact = taskArtifactUpdateEvent.getArtifact(); + assertEquals("1", taskArtifactUpdateEvent.taskId()); + assertEquals("2", taskArtifactUpdateEvent.contextId()); + assertFalse(taskArtifactUpdateEvent.append()); + assertTrue(taskArtifactUpdateEvent.lastChunk()); + Artifact_v0_3 artifact = taskArtifactUpdateEvent.artifact(); assertEquals("artifact-1", artifact.artifactId()); assertEquals(1, artifact.parts().size()); - assertEquals(Part_v0_3.Kind.TEXT, artifact.parts().get(0).getKind()); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) artifact.parts().get(0)).getText()); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) artifact.parts().get(0)).kind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) artifact.parts().get(0)).text()); } @Test @@ -223,10 +223,10 @@ public void testOnEventWithFinalTaskStatusUpdateEventEventCancels() throws Excep assertNotNull(receivedEvent.get()); assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent_v0_3); TaskStatusUpdateEvent_v0_3 taskStatusUpdateEvent = (TaskStatusUpdateEvent_v0_3) receivedEvent.get(); - assertEquals("1", taskStatusUpdateEvent.getTaskId()); - assertEquals("2", taskStatusUpdateEvent.getContextId()); + assertEquals("1", taskStatusUpdateEvent.taskId()); + assertEquals("2", taskStatusUpdateEvent.contextId()); assertTrue(taskStatusUpdateEvent.isFinal()); - assertEquals(TaskState_v0_3.COMPLETED, taskStatusUpdateEvent.getStatus().state()); + assertEquals(TaskState_v0_3.COMPLETED, taskStatusUpdateEvent.status().state()); assertTrue(future.cancelHandlerCalled); } diff --git a/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3_Test.java b/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3_Test.java index 4d6b3b5c2..19beaad4a 100644 --- a/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3_Test.java +++ b/compat-0.3/client/transport/rest/src/test/java/org/a2aproject/sdk/compat03/client/transport/rest/RestTransport_v0_3_Test.java @@ -131,26 +131,26 @@ public void testSendMessage() throws Exception { RestTransport_v0_3 instance = new RestTransport_v0_3(CARD); EventKind_v0_3 result = instance.sendMessage(messageSendParams, context); - assertEquals("task", result.getKind()); + assertEquals("task", result.kind()); Task_v0_3 task = (Task_v0_3) result; - assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", task.getId()); - assertEquals("context-1234", task.getContextId()); - assertEquals(TaskState_v0_3.SUBMITTED, task.getStatus().state()); - assertNull(task.getStatus().message()); - assertNull(task.getMetadata()); - assertEquals(true, task.getArtifacts().isEmpty()); - assertEquals(1, task.getHistory().size()); - Message_v0_3 history = task.getHistory().get(0); - assertEquals("message", history.getKind()); - assertEquals(Message_v0_3.Role.USER, history.getRole()); - assertEquals("context-1234", history.getContextId()); - assertEquals("message-1234", history.getMessageId()); - assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", history.getTaskId()); - assertEquals(1, history.getParts().size()); - assertEquals(Kind.TEXT, history.getParts().get(0).getKind()); - assertEquals("tell me a joke", ((TextPart_v0_3) history.getParts().get(0)).getText()); - assertNull(history.getMetadata()); - assertNull(history.getReferenceTaskIds()); + assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", task.id()); + assertEquals("context-1234", task.contextId()); + assertEquals(TaskState_v0_3.SUBMITTED, task.status().state()); + assertNull(task.status().message()); + assertNull(task.metadata()); + assertEquals(true, task.artifacts().isEmpty()); + assertEquals(1, task.history().size()); + Message_v0_3 history = task.history().get(0); + assertEquals("message", history.kind()); + assertEquals(Message_v0_3.Role.USER, history.role()); + assertEquals("context-1234", history.contextId()); + assertEquals("message-1234", history.messageId()); + assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", history.taskId()); + assertEquals(1, history.parts().size()); + assertEquals(Kind.TEXT, ((TextPart_v0_3) history.parts().get(0)).kind()); + assertEquals("tell me a joke", ((TextPart_v0_3) history.parts().get(0)).text()); + assertNull(history.metadata()); + assertNull(history.referenceTaskIds()); } /** @@ -173,10 +173,10 @@ public void testCancelTask() throws Exception { RestTransport_v0_3 instance = new RestTransport_v0_3(CARD); Task_v0_3 task = instance.cancelTask(new TaskIdParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", new HashMap<>()), context); - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); - assertEquals(TaskState_v0_3.CANCELED, task.getStatus().state()); - assertNull(task.getStatus().message()); - assertNull(task.getMetadata()); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); + assertEquals(TaskState_v0_3.CANCELED, task.status().state()); + assertNull(task.status().message()); + assertNull(task.metadata()); } /** @@ -198,36 +198,36 @@ public void testGetTask() throws Exception { TaskQueryParams_v0_3 request = new TaskQueryParams_v0_3("de38c76d-d54c-436c-8b9f-4c2703648d64", 10); RestTransport_v0_3 instance = new RestTransport_v0_3(CARD); Task_v0_3 task = instance.getTask(request, context); - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.getId()); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - assertNull(task.getStatus().message()); - assertNull(task.getMetadata()); - assertEquals(false, task.getArtifacts().isEmpty()); - assertEquals(1, task.getArtifacts().size()); - Artifact_v0_3 artifact = task.getArtifacts().get(0); + assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + assertNull(task.status().message()); + assertNull(task.metadata()); + assertEquals(false, task.artifacts().isEmpty()); + assertEquals(1, task.artifacts().size()); + Artifact_v0_3 artifact = task.artifacts().get(0); assertEquals("artifact-1", artifact.artifactId()); assertEquals("", artifact.name()); assertEquals(false, artifact.parts().isEmpty()); - assertEquals(Kind.TEXT, artifact.parts().get(0).getKind()); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) artifact.parts().get(0)).getText()); - assertEquals(1, task.getHistory().size()); - Message_v0_3 history = task.getHistory().get(0); - assertEquals("message", history.getKind()); - assertEquals(Message_v0_3.Role.USER, history.getRole()); - assertEquals("message-123", history.getMessageId()); - assertEquals(3, history.getParts().size()); - assertEquals(Kind.TEXT, history.getParts().get(0).getKind()); - assertEquals("tell me a joke", ((TextPart_v0_3) history.getParts().get(0)).getText()); - assertEquals(Kind.FILE, history.getParts().get(1).getKind()); - FilePart_v0_3 part = (FilePart_v0_3) history.getParts().get(1); - assertEquals("text/plain", part.getFile().mimeType()); - assertEquals("file:///path/to/file.txt", ((FileWithUri_v0_3) part.getFile()).uri()); - part = (FilePart_v0_3) history.getParts().get(2); - assertEquals(Kind.FILE, part.getKind()); - assertEquals("text/plain", part.getFile().mimeType()); - assertEquals("hello", ((FileWithBytes_v0_3) part.getFile()).bytes()); - assertNull(history.getMetadata()); - assertNull(history.getReferenceTaskIds()); + assertEquals(Kind.TEXT, ((TextPart_v0_3) artifact.parts().get(0)).kind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) artifact.parts().get(0)).text()); + assertEquals(1, task.history().size()); + Message_v0_3 history = task.history().get(0); + assertEquals("message", history.kind()); + assertEquals(Message_v0_3.Role.USER, history.role()); + assertEquals("message-123", history.messageId()); + assertEquals(3, history.parts().size()); + assertEquals(Kind.TEXT, ((TextPart_v0_3) history.parts().get(0)).kind()); + assertEquals("tell me a joke", ((TextPart_v0_3) history.parts().get(0)).text()); + assertEquals(Kind.FILE, ((FilePart_v0_3) history.parts().get(1)).kind()); + FilePart_v0_3 part = (FilePart_v0_3) history.parts().get(1); + assertEquals("text/plain", part.file().mimeType()); + assertEquals("file:///path/to/file.txt", ((FileWithUri_v0_3) part.file()).uri()); + part = (FilePart_v0_3) history.parts().get(2); + assertEquals(Kind.FILE, part.kind()); + assertEquals("text/plain", part.file().mimeType()); + assertEquals("hello", ((FileWithBytes_v0_3) part.file()).bytes()); + assertNull(history.metadata()); + assertNull(history.referenceTaskIds()); } /** @@ -276,9 +276,9 @@ public void testSendMessageStreaming() throws Exception { boolean eventReceived = latch.await(10, TimeUnit.SECONDS); assertTrue(eventReceived); assertNotNull(receivedEvent.get()); - assertEquals("task", receivedEvent.get().getKind()); + assertEquals("task", receivedEvent.get().kind()); Task_v0_3 task = (Task_v0_3) receivedEvent.get(); - assertEquals("2", task.getId()); + assertEquals("2", task.id()); } /** @@ -437,16 +437,16 @@ public void testResubscribe() throws Exception { assertNotNull(eventKind); assertInstanceOf(Task_v0_3.class, eventKind); Task_v0_3 task = (Task_v0_3) eventKind; - assertEquals("2", task.getId()); - assertEquals("context-1234", task.getContextId()); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - List artifacts = task.getArtifacts(); + assertEquals("2", task.id()); + assertEquals("context-1234", task.contextId()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + List artifacts = task.artifacts(); assertEquals(1, artifacts.size()); Artifact_v0_3 artifact = artifacts.get(0); assertEquals("artifact-1", artifact.artifactId()); assertEquals("joke", artifact.name()); Part_v0_3 part = artifact.parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).getText()); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart_v0_3) part).text()); } } diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java index cf28b4f03..2e889951b 100644 --- a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3.java @@ -49,7 +49,7 @@ public PayloadAndHeaders_v0_3 intercept(String methodName, @Nullable Object payl continue; } if (securityScheme instanceof HTTPAuthSecurityScheme_v0_3 httpAuthSecurityScheme) { - String scheme = httpAuthSecurityScheme.getScheme().toLowerCase(Locale.ROOT); + String scheme = httpAuthSecurityScheme.scheme().toLowerCase(Locale.ROOT); if (scheme.equals(BEARER_SCHEME)) { updatedHeaders.put(AUTHORIZATION, getBearerValue(credential)); return new PayloadAndHeaders_v0_3(payload, updatedHeaders); @@ -62,7 +62,7 @@ public PayloadAndHeaders_v0_3 intercept(String methodName, @Nullable Object payl updatedHeaders.put(AUTHORIZATION, getBearerValue(credential)); return new PayloadAndHeaders_v0_3(payload, updatedHeaders); } else if (securityScheme instanceof APIKeySecurityScheme_v0_3 apiKeySecurityScheme) { - updatedHeaders.put(apiKeySecurityScheme.getName(), credential); + updatedHeaders.put(apiKeySecurityScheme.name(), credential); return new PayloadAndHeaders_v0_3(payload, updatedHeaders); } } diff --git a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3_Test.java b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3_Test.java index fda90973d..5027ce493 100644 --- a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3_Test.java +++ b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/transport/spi/interceptors/auth/AuthInterceptor_v0_3_Test.java @@ -77,7 +77,7 @@ public void testAPIKeySecurityScheme() { AuthTestCase authTestCase = new AuthTestCase( "http://agent.com/rpc", "session-id", - APIKeySecurityScheme_v0_3.API_KEY, + APIKeySecurityScheme_v0_3.TYPE, "secret-api-key", new APIKeySecurityScheme_v0_3("header", "x-api-key", "API Key authentication"), "x-api-key", @@ -91,7 +91,7 @@ public void testOAuth2SecurityScheme() { AuthTestCase authTestCase = new AuthTestCase( "http://agent.com/rpc", "session-id", - OAuth2SecurityScheme_v0_3.OAUTH2, + OAuth2SecurityScheme_v0_3.TYPE, "secret-oauth-access-token", new OAuth2SecurityScheme_v0_3(new OAuthFlows_v0_3.Builder().build(), "OAuth2 authentication", null), "Authorization", @@ -105,7 +105,7 @@ public void testOidcSecurityScheme() { AuthTestCase authTestCase = new AuthTestCase( "http://agent.com/rpc", "session-id", - OpenIdConnectSecurityScheme_v0_3.OPENID_CONNECT, + OpenIdConnectSecurityScheme_v0_3.TYPE, "secret-oidc-id-token", new OpenIdConnectSecurityScheme_v0_3("http://provider.com/.well-known/openid-configuration", "OIDC authentication"), "Authorization", diff --git a/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcHandler_v0_3.java b/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcHandler_v0_3.java index bd9c7b890..3364f72c9 100644 --- a/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcHandler_v0_3.java +++ b/compat-0.3/reference/grpc/src/main/java/org/a2aproject/sdk/compat03/server/grpc/quarkus/QuarkusGrpcHandler_v0_3.java @@ -24,6 +24,20 @@ public class QuarkusGrpcHandler_v0_3 extends GrpcHandler_v0_3 { private final Instance callContextFactoryInstance; private final Executor executor; + @SuppressWarnings("NullAway.Init") + public QuarkusGrpcHandler_v0_3() { + // No-args constructor needed for spec-compliant CDI environments + this.agentCard = null; + this.callContextFactoryInstance = null; + this.executor = null; + } + + public QuarkusGrpcHandler_v0_3(AgentCard_v0_3 agentCard, Instance callContextFactoryInstance, Executor executor) { + this.agentCard = agentCard; + this.callContextFactoryInstance = callContextFactoryInstance; + this.executor = executor; + } + @Inject public QuarkusGrpcHandler_v0_3(@PublicAgentCard AgentCard_v0_3 agentCard, Convert_v0_3_To10RequestHandler requestHandler, diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java index 6a339e7c4..a45c7cc16 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthAndroidTest.java @@ -54,10 +54,10 @@ public void testBasicAuthWorksViaHttp() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); givenAuthenticated() - .get("/v1/tasks/" + MINIMAL_TASK.getId()) + .get("/v1/tasks/" + MINIMAL_TASK.id()) .then() .statusCode(200); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java index 5ab5f5b75..64feaddf2 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthTest.java @@ -54,10 +54,10 @@ public void testBasicAuthWorksViaHttp() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); givenAuthenticated() - .get("/v1/tasks/" + MINIMAL_TASK.getId()) + .get("/v1/tasks/" + MINIMAL_TASK.id()) .then() .statusCode(200); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } diff --git a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java index f5d4e1c58..a1a2098b4 100644 --- a/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java +++ b/compat-0.3/reference/rest/src/test/java/org/a2aproject/sdk/compat03/server/rest/quarkus/QuarkusA2ARest_v0_3_WithAuthVertxTest.java @@ -59,10 +59,10 @@ public void testBasicAuthWorksViaHttp() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); givenAuthenticated() - .get("/v1/tasks/" + MINIMAL_TASK.getId()) + .get("/v1/tasks/" + MINIMAL_TASK.id()) .then() .statusCode(200); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java index a300b8044..7e7c5b11a 100644 --- a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/Convert_v0_3_To10RequestHandler.java @@ -72,6 +72,12 @@ public class Convert_v0_3_To10RequestHandler { */ private final RequestHandler v10Handler; + @SuppressWarnings("NullAway.Init") + public Convert_v0_3_To10RequestHandler() { + // No-args constructor needed for spec-compliant CDI environments + this.v10Handler = null; + } + @Inject public Convert_v0_3_To10RequestHandler(org.a2aproject.sdk.server.requesthandlers.RequestHandler v10Handler) { this.v10Handler = v10Handler; diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/MessageMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/MessageMapper_v0_3.java index 2c5a71528..b9973bc3f 100644 --- a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/MessageMapper_v0_3.java +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/MessageMapper_v0_3.java @@ -16,7 +16,7 @@ *

            * Key differences: *

              - *
            • v0.3: Message is a class with getter methods (e.g., {@code getRole()}, {@code getParts()})
            • + *
            • v0.3: Message is a record with accessor methods (e.g., {@code role()}, {@code parts()})
            • *
            • v1.0: Message is a record with accessor methods (e.g., {@code role()}, {@code parts()})
            • *
            • Role enum values have "ROLE_" prefix in v1.0
            • *
            • Part types (TextPart, FilePart, DataPart) changed from classes to records in v1.0
            • @@ -46,20 +46,20 @@ default Message toV10(Message_v0_3 v03) { return null; } - Message.Role role = RoleMapper_v0_3.INSTANCE.toV10(v03.getRole()); - List> parts = v03.getParts().stream() + Message.Role role = RoleMapper_v0_3.INSTANCE.toV10(v03.role()); + List> parts = v03.parts().stream() .map(PartMapper_v0_3.INSTANCE::toV10) .collect(Collectors.toList()); return new Message( role, parts, - v03.getMessageId(), - v03.getContextId(), - v03.getTaskId(), - v03.getReferenceTaskIds(), - v03.getMetadata(), - v03.getExtensions() + v03.messageId(), + v03.contextId(), + v03.taskId(), + v03.referenceTaskIds(), + v03.metadata(), + v03.extensions() ); } diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/PartMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/PartMapper_v0_3.java index 5da63952e..3cfa66a69 100644 --- a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/PartMapper_v0_3.java +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/PartMapper_v0_3.java @@ -25,7 +25,7 @@ *

              * Key differences: *

                - *
              • v0.3: Part types are classes with getter methods (e.g., {@code getText()}, {@code getMetadata()})
              • + *
              • v0.3: Part types are records with accessor methods (e.g., {@code text()}, {@code metadata()})
              • *
              • v1.0: Part types are records with accessor methods (e.g., {@code text()}, {@code metadata()})
              • *
              *

              @@ -54,14 +54,14 @@ default Part toV10(Part_v0_3 v03) { } if (v03 instanceof TextPart_v0_3 v03Text) { - return new TextPart(v03Text.getText(), v03Text.getMetadata()); + return new TextPart(v03Text.text(), v03Text.metadata()); } else if (v03 instanceof FilePart_v0_3 v03File) { return new FilePart( - FileContentMapper_v0_3.INSTANCE.toV10(v03File.getFile()), - v03File.getMetadata() + FileContentMapper_v0_3.INSTANCE.toV10(v03File.file()), + v03File.metadata() ); } else if (v03 instanceof DataPart_v0_3 v03Data) { - return new DataPart(v03Data.getData(), v03Data.getMetadata()); + return new DataPart(v03Data.data(), v03Data.metadata()); } throw new InvalidRequestError(null, "Unrecognized Part type: " + v03.getClass().getName(), null); diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskArtifactUpdateEventMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskArtifactUpdateEventMapper_v0_3.java index defde82ac..c4df3c83c 100644 --- a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskArtifactUpdateEventMapper_v0_3.java +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskArtifactUpdateEventMapper_v0_3.java @@ -11,7 +11,7 @@ *

              * Key differences: *

                - *
              • v0.3: TaskArtifactUpdateEvent is a class with getter methods (e.g., {@code getTaskId()}, {@code isAppend()})
              • + *
              • v0.3: TaskArtifactUpdateEvent is a record with accessor methods (e.g., {@code taskId()}, {@code append()})
              • *
              • v1.0: TaskArtifactUpdateEvent is a record with accessor methods (e.g., {@code taskId()}, {@code append()})
              • *
              *

              @@ -40,12 +40,12 @@ default TaskArtifactUpdateEvent toV10(TaskArtifactUpdateEvent_v0_3 v03) { } return new TaskArtifactUpdateEvent( - v03.getTaskId(), - ArtifactMapper_v0_3.INSTANCE.toV10(v03.getArtifact()), - v03.getContextId(), - v03.isAppend(), - v03.isLastChunk(), - v03.getMetadata() + v03.taskId(), + ArtifactMapper_v0_3.INSTANCE.toV10(v03.artifact()), + v03.contextId(), + v03.append(), + v03.lastChunk(), + v03.metadata() ); } diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3.java index 47d6a4e3c..6c9dd259f 100644 --- a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3.java +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3.java @@ -18,9 +18,9 @@ *

              * Key differences: *

                - *
              • v0.3: Task is a class with getter methods (e.g., {@code getId()}, {@code getStatus()})
              • + *
              • v0.3: Task is a record with accessor methods (e.g., {@code id()}, {@code status()})
              • *
              • v1.0: Task is a record with accessor methods (e.g., {@code id()}, {@code status()})
              • - *
              • v0.3 has a {@code kind} field with {@code getKind()} method
              • + *
              • v0.3 has a {@code kind} field with {@code kind()} method
              • *
              • v1.0 has a {@code kind()} method from the {@link org.a2aproject.sdk.spec.StreamingEventKind} interface
              • *
              *

              @@ -52,25 +52,25 @@ default Task toV10(Task_v0_3 v03) { return null; } - List artifacts = v03.getArtifacts() != null - ? v03.getArtifacts().stream() + List artifacts = v03.artifacts() != null + ? v03.artifacts().stream() .map(ArtifactMapper_v0_3.INSTANCE::toV10) .collect(Collectors.toList()) : null; - List history = v03.getHistory() != null - ? v03.getHistory().stream() + List history = v03.history() != null + ? v03.history().stream() .map(MessageMapper_v0_3.INSTANCE::toV10) .collect(Collectors.toList()) : null; return new Task( - v03.getId(), - v03.getContextId(), - TaskStatusMapper_v0_3.INSTANCE.toV10(v03.getStatus()), + v03.id(), + v03.contextId(), + TaskStatusMapper_v0_3.INSTANCE.toV10(v03.status()), artifacts, history, - v03.getMetadata() + v03.metadata() ); } diff --git a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusUpdateEventMapper_v0_3.java b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusUpdateEventMapper_v0_3.java index 8b90af2c0..92c6172ba 100644 --- a/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusUpdateEventMapper_v0_3.java +++ b/compat-0.3/server-conversion/src/main/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskStatusUpdateEventMapper_v0_3.java @@ -40,10 +40,10 @@ default TaskStatusUpdateEvent toV10(TaskStatusUpdateEvent_v0_3 v03) { } return new TaskStatusUpdateEvent( - v03.getTaskId(), - TaskStatusMapper_v0_3.INSTANCE.toV10(v03.getStatus()), - v03.getContextId(), - v03.getMetadata() + v03.taskId(), + TaskStatusMapper_v0_3.INSTANCE.toV10(v03.status()), + v03.contextId(), + v03.metadata() ); } diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java index 016f361b8..d1f622402 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerServerTest_v0_3.java @@ -181,13 +181,13 @@ protected AbstractA2AServerServerTest_v0_3(int serverPort) { public void testTaskStoreMethodsSanityTest() throws Exception { Task_v0_3 task = new Task_v0_3.Builder(MINIMAL_TASK).id("abcde").build(); saveTaskInTaskStore(task); - Task_v0_3 saved = getTaskFromTaskStore(task.getId()); - assertEquals(task.getId(), saved.getId()); - assertEquals(task.getContextId(), saved.getContextId()); - assertEquals(task.getStatus().state(), saved.getStatus().state()); + Task_v0_3 saved = getTaskFromTaskStore(task.id()); + assertEquals(task.id(), saved.id()); + assertEquals(task.contextId(), saved.contextId()); + assertEquals(task.status().state(), saved.status().state()); - deleteTaskInTaskStore(task.getId()); - Task_v0_3 saved2 = getTaskFromTaskStore(task.getId()); + deleteTaskInTaskStore(task.id()); + Task_v0_3 saved2 = getTaskFromTaskStore(task.id()); assertNull(saved2); } @@ -203,14 +203,14 @@ private void testGetTask() throws Exception { private void testGetTask(String mediaType) throws Exception { saveTaskInTaskStore(MINIMAL_TASK); try { - Task_v0_3 response = getClient().getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); - assertEquals("task-123", response.getId()); - assertEquals("session-xyz", response.getContextId()); - assertEquals(TaskState_v0_3.SUBMITTED, response.getStatus().state()); + Task_v0_3 response = getClient().getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.id())); + assertEquals("task-123", response.id()); + assertEquals("session-xyz", response.contextId()); + assertEquals(TaskState_v0_3.SUBMITTED, response.status().state()); } catch (A2AClientException_v0_3 e) { fail("Unexpected exception during getTask: " + e.getMessage(), e); } finally { - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -230,14 +230,14 @@ public void testGetTaskNotFound() throws Exception { public void testCancelTaskSuccess() throws Exception { saveTaskInTaskStore(CANCEL_TASK); try { - Task_v0_3 task = getClient().cancelTask(new TaskIdParams_v0_3(CANCEL_TASK.getId())); - assertEquals(CANCEL_TASK.getId(), task.getId()); - assertEquals(CANCEL_TASK.getContextId(), task.getContextId()); - assertEquals(TaskState_v0_3.CANCELED, task.getStatus().state()); + Task_v0_3 task = getClient().cancelTask(new TaskIdParams_v0_3(CANCEL_TASK.id())); + assertEquals(CANCEL_TASK.id(), task.id()); + assertEquals(CANCEL_TASK.contextId(), task.contextId()); + assertEquals(TaskState_v0_3.CANCELED, task.status().state()); } catch (A2AClientException_v0_3 e) { fail("Unexpected exception during cancel task: " + e.getMessage(), e); } finally { - deleteTaskInTaskStore(CANCEL_TASK.getId()); + deleteTaskInTaskStore(CANCEL_TASK.id()); } } @@ -245,13 +245,13 @@ public void testCancelTaskSuccess() throws Exception { public void testCancelTaskNotSupported() throws Exception { saveTaskInTaskStore(CANCEL_TASK_NOT_SUPPORTED); try { - getClient().cancelTask(new TaskIdParams_v0_3(CANCEL_TASK_NOT_SUPPORTED.getId())); + getClient().cancelTask(new TaskIdParams_v0_3(CANCEL_TASK_NOT_SUPPORTED.id())); fail("Expected A2AClientException for unsupported cancel operation"); } catch (A2AClientException_v0_3 e) { // Expected - the client should throw an exception for unsupported operations assertInstanceOf(UnsupportedOperationError_v0_3.class, e.getCause()); } finally { - deleteTaskInTaskStore(CANCEL_TASK_NOT_SUPPORTED.getId()); + deleteTaskInTaskStore(CANCEL_TASK_NOT_SUPPORTED.id()); } } @@ -294,11 +294,11 @@ public void testSendMessageNewMessageSuccess() throws Exception { assertFalse(wasUnexpectedEvent.get()); Message_v0_3 messageResponse = receivedMessage.get(); assertNotNull(messageResponse); - assertEquals(MESSAGE.getMessageId(), messageResponse.getMessageId()); - assertEquals(MESSAGE.getRole(), messageResponse.getRole()); - Part_v0_3 part = messageResponse.getParts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("test message", ((TextPart_v0_3) part).getText()); + assertEquals(MESSAGE.messageId(), messageResponse.messageId()); + assertEquals(MESSAGE.role(), messageResponse.role()); + Part_v0_3 part = messageResponse.parts().get(0); + assertInstanceOf(TextPart_v0_3.class, part); + assertEquals("test message", ((TextPart_v0_3) part).text()); } @Test @@ -316,7 +316,7 @@ public void testRequestScopedBeanAvailableOnAgentExecutorThread() throws Excepti getNonStreamingClient().sendMessage(message, List.of((event, agentCard) -> { if (event instanceof TaskEvent_v0_3 te) { receivedTask.set(te.getTask()); - if (te.getTask().getStatus().state() == TaskState_v0_3.COMPLETED) { + if (te.getTask().status().state() == TaskState_v0_3.COMPLETED) { latch.countDown(); } } @@ -330,13 +330,13 @@ public void testRequestScopedBeanAvailableOnAgentExecutorThread() throws Excepti Task_v0_3 task = receivedTask.get(); assertNotNull(task, "Should have received a task"); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - assertNotNull(task.getArtifacts()); - assertFalse(task.getArtifacts().isEmpty()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + assertNotNull(task.artifacts()); + assertFalse(task.artifacts().isEmpty()); - Part_v0_3 part = task.getArtifacts().get(0).parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("request-scoped:request-scoped-value", ((TextPart_v0_3) part).getText()); + Part_v0_3 part = task.artifacts().get(0).parts().get(0); + assertEquals(Part_v0_3.Kind.TEXT, ((TextPart_v0_3) part).kind()); + assertEquals("request-scoped:request-scoped-value", ((TextPart_v0_3) part).text()); } @Test @@ -344,8 +344,8 @@ public void testSendMessageExistingTaskSuccess() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); try { Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .build(); CountDownLatch latch = new CountDownLatch(1); @@ -370,15 +370,15 @@ public void testSendMessageExistingTaskSuccess() throws Exception { assertTrue(latch.await(10, TimeUnit.SECONDS)); Message_v0_3 messageResponse = receivedMessage.get(); assertNotNull(messageResponse); - assertEquals(MESSAGE.getMessageId(), messageResponse.getMessageId()); - assertEquals(MESSAGE.getRole(), messageResponse.getRole()); - Part_v0_3 part = messageResponse.getParts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("test message", ((TextPart_v0_3) part).getText()); + assertEquals(MESSAGE.messageId(), messageResponse.messageId()); + assertEquals(MESSAGE.role(), messageResponse.role()); + Part_v0_3 part = messageResponse.parts().get(0); + assertInstanceOf(TextPart_v0_3.class, part); + assertEquals("test message", ((TextPart_v0_3) part).text()); } catch (A2AClientException_v0_3 e) { fail("Unexpected exception during sendMessage: " + e.getMessage(), e); } finally { - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -388,15 +388,15 @@ public void testSetPushNotificationSuccess() throws Exception { try { TaskPushNotificationConfig_v0_3 taskPushConfig = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), new PushNotificationConfig_v0_3.Builder().url("http://example.com").build()); + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder().url("http://example.com").build()); TaskPushNotificationConfig_v0_3 config = getClient().setTaskPushNotificationConfiguration(taskPushConfig); - assertEquals(MINIMAL_TASK.getId(), config.taskId()); + assertEquals(MINIMAL_TASK.id(), config.taskId()); assertEquals("http://example.com", config.pushNotificationConfig().url()); } catch (A2AClientException_v0_3 e) { fail("Unexpected exception during set push notification test: " + e.getMessage(), e); } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), MINIMAL_TASK.id()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -406,20 +406,20 @@ public void testGetPushNotificationSuccess() throws Exception { try { TaskPushNotificationConfig_v0_3 taskPushConfig = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), new PushNotificationConfig_v0_3.Builder().url("http://example.com").build()); + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder().url("http://example.com").build()); TaskPushNotificationConfig_v0_3 setResult = getClient().setTaskPushNotificationConfiguration(taskPushConfig); assertNotNull(setResult); TaskPushNotificationConfig_v0_3 config = getClient().getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); - assertEquals(MINIMAL_TASK.getId(), config.taskId()); + new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id())); + assertEquals(MINIMAL_TASK.id(), config.taskId()); assertEquals("http://example.com", config.pushNotificationConfig().url()); } catch (A2AClientException_v0_3 e) { fail("Unexpected exception during get push notification test: " + e.getMessage(), e); } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), MINIMAL_TASK.id()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -428,8 +428,8 @@ public void testError() throws Exception { saveTaskInTaskStore(SEND_MESSAGE_NOT_SUPPORTED); try { Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(SEND_MESSAGE_NOT_SUPPORTED.getId()) - .contextId(SEND_MESSAGE_NOT_SUPPORTED.getContextId()) + .taskId(SEND_MESSAGE_NOT_SUPPORTED.id()) + .contextId(SEND_MESSAGE_NOT_SUPPORTED.contextId()) .build(); try { @@ -442,7 +442,7 @@ public void testError() throws Exception { assertInstanceOf(UnsupportedOperationError_v0_3.class, e.getCause()); } } finally { - deleteTaskInTaskStore(SEND_MESSAGE_NOT_SUPPORTED.getId()); + deleteTaskInTaskStore(SEND_MESSAGE_NOT_SUPPORTED.id()); } } @@ -480,7 +480,7 @@ public void testResubscribeExistingTaskSuccess() throws Exception { // attempting to send a streaming message instead of explicitly calling queueManager#createOrTap // does not work because after the message is sent, the queue becomes null but task resubscription // requires the queue to still be active - ensureQueueForTask(MINIMAL_TASK.getId()); + ensureQueueForTask(MINIMAL_TASK.id()); CountDownLatch eventLatch = new CountDownLatch(2); AtomicReference artifactUpdateEvent = new AtomicReference<>(); @@ -526,7 +526,7 @@ public void testResubscribeExistingTaskSuccess() throws Exception { .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); // Resubscribe to the task with specific consumer and error handler - getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.getId()), List.of(consumer), errorHandler); + getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.id()), List.of(consumer), errorHandler); // Wait for subscription to be established assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); @@ -534,16 +534,16 @@ public void testResubscribeExistingTaskSuccess() throws Exception { // Enqueue events on the server List events = List.of( new TaskArtifactUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .artifact(new Artifact_v0_3.Builder() .artifactId("11") .parts(new TextPart_v0_3("text")) .build()) .build(), new TaskStatusUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) .isFinal(true) .build()); @@ -560,21 +560,21 @@ public void testResubscribeExistingTaskSuccess() throws Exception { // Verify artifact update event TaskArtifactUpdateEvent_v0_3 receivedArtifactEvent = artifactUpdateEvent.get(); assertNotNull(receivedArtifactEvent); - assertEquals(MINIMAL_TASK.getId(), receivedArtifactEvent.getTaskId()); - assertEquals(MINIMAL_TASK.getContextId(), receivedArtifactEvent.getContextId()); - Part_v0_3 part = receivedArtifactEvent.getArtifact().parts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("text", ((TextPart_v0_3) part).getText()); + assertEquals(MINIMAL_TASK.id(), receivedArtifactEvent.taskId()); + assertEquals(MINIMAL_TASK.contextId(), receivedArtifactEvent.contextId()); + Part_v0_3 part = receivedArtifactEvent.artifact().parts().get(0); + assertInstanceOf(TextPart_v0_3.class, part); + assertEquals("text", ((TextPart_v0_3) part).text()); // Verify status update event TaskStatusUpdateEvent_v0_3 receivedStatusEvent = statusUpdateEvent.get(); assertNotNull(receivedStatusEvent); - assertEquals(MINIMAL_TASK.getId(), receivedStatusEvent.getTaskId()); - assertEquals(MINIMAL_TASK.getContextId(), receivedStatusEvent.getContextId()); - assertEquals(TaskState_v0_3.COMPLETED, receivedStatusEvent.getStatus().state()); - assertNotNull(receivedStatusEvent.getStatus().timestamp()); + assertEquals(MINIMAL_TASK.id(), receivedStatusEvent.taskId()); + assertEquals(MINIMAL_TASK.contextId(), receivedStatusEvent.contextId()); + assertEquals(TaskState_v0_3.COMPLETED, receivedStatusEvent.status().state()); + assertNotNull(receivedStatusEvent.status().timestamp()); } finally { - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -645,7 +645,7 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti saveTaskInTaskStore(MINIMAL_TASK); try { // 1. Ensure queue exists for the task - ensureQueueForTask(MINIMAL_TASK.getId()); + ensureQueueForTask(MINIMAL_TASK.id()); // 2. First consumer subscribes and receives initial event CountDownLatch firstConsumerLatch = new CountDownLatch(1); @@ -681,7 +681,7 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti awaitStreamingSubscription() .whenComplete((unused, throwable) -> firstSubscriptionLatch.countDown()); - getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.getId()), + getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.id()), List.of(firstConsumer), firstErrorHandler); @@ -689,8 +689,8 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti // Enqueue first event TaskArtifactUpdateEvent_v0_3 event1 = new TaskArtifactUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .artifact(new Artifact_v0_3.Builder() .artifactId("artifact-1") .parts(new TextPart_v0_3("First artifact")) @@ -705,7 +705,7 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti assertNotNull(firstConsumerEvent.get()); // Verify we have multiple child queues (ensureQueue + first resubscribe) - int childCountBeforeSecond = getChildQueueCount(MINIMAL_TASK.getId()); + int childCountBeforeSecond = getChildQueueCount(MINIMAL_TASK.id()); assertTrue(childCountBeforeSecond >= 2, "Should have at least 2 child queues"); // 3. Second consumer resubscribes while first is still active @@ -747,21 +747,21 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti // This should succeed with reference counting because MainQueue stays alive // while first consumer's ChildQueue exists - getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.getId()), + getClient().resubscribe(new TaskIdParams_v0_3(MINIMAL_TASK.id()), List.of(secondConsumer), secondErrorHandler); assertTrue(secondSubscriptionLatch.await(15, TimeUnit.SECONDS), "Second subscription should be established"); // Verify child queue count increased (now ensureQueue + first + second) - int childCountAfterSecond = getChildQueueCount(MINIMAL_TASK.getId()); + int childCountAfterSecond = getChildQueueCount(MINIMAL_TASK.id()); assertTrue(childCountAfterSecond > childCountBeforeSecond, "Child queue count should increase after second resubscription"); // 4. Enqueue second event - both consumers should receive it TaskArtifactUpdateEvent_v0_3 event2 = new TaskArtifactUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .artifact(new Artifact_v0_3.Builder() .artifactId("artifact-2") .parts(new TextPart_v0_3("Second artifact")) @@ -777,11 +777,11 @@ public void testMainQueueReferenceCountingWithMultipleConsumers() throws Excepti TaskArtifactUpdateEvent_v0_3 receivedEvent = secondConsumerEvent.get(); assertNotNull(receivedEvent); - assertEquals("artifact-2", receivedEvent.getArtifact().artifactId()); - assertEquals("Second artifact", ((TextPart_v0_3) receivedEvent.getArtifact().parts().get(0)).getText()); + assertEquals("artifact-2", receivedEvent.artifact().artifactId()); + assertEquals("Second artifact", ((TextPart_v0_3) receivedEvent.artifact().parts().get(0)).text()); } finally { - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -823,21 +823,21 @@ public void testListPushNotificationConfigWithConfigId() throws Exception { .url("http://example.com") .id("config2") .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); try { List result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id())); assertEquals(2, result.size()); - assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.getId(), notificationConfig1), result.get(0)); - assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.getId(), notificationConfig2), result.get(1)); + assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.id(), notificationConfig1), result.get(0)); + assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.id(), notificationConfig2), result.get(1)); } catch (Exception e) { fail(); } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config1"); - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config2"); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config1"); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config2"); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -852,26 +852,26 @@ public void testListPushNotificationConfigWithoutConfigId() throws Exception { new PushNotificationConfig_v0_3.Builder() .url("http://2.example.com") .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); // will overwrite the previous one - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); try { List result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id())); assertEquals(1, result.size()); PushNotificationConfig_v0_3 expectedNotificationConfig = new PushNotificationConfig_v0_3.Builder() .url("http://2.example.com") - .id(MINIMAL_TASK.getId()) + .id(MINIMAL_TASK.id()) .build(); - assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.getId(), expectedNotificationConfig), + assertEquals(new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.id(), expectedNotificationConfig), result.get(0)); } catch (Exception e) { fail(); } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), MINIMAL_TASK.id()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -891,12 +891,12 @@ public void testListPushNotificationConfigEmptyList() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); try { List result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id())); assertEquals(0, result.size()); } catch (Exception e) { fail(e.getMessage()); } finally { - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -919,18 +919,18 @@ public void testDeletePushNotificationConfigWithValidConfigId() throws Exception .url("http://example.com") .id("config2") .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); savePushNotificationConfigInStore("task-456", notificationConfig1); try { // specify the config ID to delete getClient().deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), "config1")); + new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id(), "config1")); // should now be 1 left List result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id())); assertEquals(1, result.size()); // should remain unchanged, this is a different task @@ -940,10 +940,10 @@ public void testDeletePushNotificationConfigWithValidConfigId() throws Exception } catch (Exception e) { fail(e.getMessage()); } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config1"); - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config2"); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config1"); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config2"); deletePushNotificationConfigInStore("task-456", "config1"); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); deleteTaskInTaskStore("task-456"); } } @@ -961,23 +961,23 @@ public void testDeletePushNotificationConfigWithNonExistingConfigId() throws Exc .url("http://example.com") .id("config2") .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); try { getClient().deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), "non-existent-config-id")); + new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id(), "non-existent-config-id")); // should remain unchanged List result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id())); assertEquals(2, result.size()); } catch (Exception e) { fail(); } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config1"); - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), "config2"); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config1"); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config2"); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -1004,24 +1004,24 @@ public void testDeletePushNotificationConfigSetWithoutConfigId() throws Exceptio new PushNotificationConfig_v0_3.Builder() .url("http://2.example.com") .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig1); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); // this one will overwrite the previous one - savePushNotificationConfigInStore(MINIMAL_TASK.getId(), notificationConfig2); + savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); try { getClient().deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), MINIMAL_TASK.getId())); + new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id(), MINIMAL_TASK.id())); // should now be 0 List result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId()), null); + new ListTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id()), null); assertEquals(0, result.size()); } catch (Exception e) { fail(); } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deletePushNotificationConfigInStore(MINIMAL_TASK.id(), MINIMAL_TASK.id()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -1041,10 +1041,10 @@ public void testNonBlockingWithMultipleMessages() throws Exception { BiConsumer firstMessageConsumer = (event, agentCard) -> { if (event instanceof TaskEvent_v0_3 te) { - taskIdRef.set(te.getTask().getId()); + taskIdRef.set(te.getTask().id()); firstTaskLatch.countDown(); } else if (event instanceof TaskUpdateEvent_v0_3 tue && tue.getUpdateEvent() instanceof TaskStatusUpdateEvent_v0_3 status) { - taskIdRef.set(status.getTaskId()); + taskIdRef.set(status.taskId()); firstTaskLatch.countDown(); } }; @@ -1174,18 +1174,18 @@ public void testNonBlockingWithMultipleMessages() throws Exception { .filter(e -> e instanceof TaskArtifactUpdateEvent_v0_3) .findFirst() .orElseThrow(); - assertEquals("artifact-2", resubArtifact.getArtifact().artifactId()); + assertEquals("artifact-2", resubArtifact.artifact().artifactId()); assertEquals("Second message artifact", - ((TextPart_v0_3) resubArtifact.getArtifact().parts().get(0)).getText()); + ((TextPart_v0_3) resubArtifact.artifact().parts().get(0)).text()); // Verify artifact-2 details from streaming TaskArtifactUpdateEvent_v0_3 streamArtifact = (TaskArtifactUpdateEvent_v0_3) streamReceivedEvents.stream() .filter(e -> e instanceof TaskArtifactUpdateEvent_v0_3) .findFirst() .orElseThrow(); - assertEquals("artifact-2", streamArtifact.getArtifact().artifactId()); + assertEquals("artifact-2", streamArtifact.artifact().artifactId()); assertEquals("Second message artifact", - ((TextPart_v0_3) streamArtifact.getArtifact().parts().get(0)).getText()); + ((TextPart_v0_3) streamArtifact.artifact().parts().get(0)).text()); } finally { String taskId = generatedTaskIdRef.get(); if (taskId != null) { @@ -1368,8 +1368,8 @@ private void testSendStreamingMessageWithHttpClient(String mediaType) throws Exc saveTaskInTaskStore(MINIMAL_TASK); try { Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .build(); SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( "1", new MessageSendParams_v0_3(message, null, null)); @@ -1389,11 +1389,11 @@ private void testSendStreamingMessageWithHttpClient(String mediaType) throws Exc if (jsonResponse != null) { assertNull(jsonResponse.getError()); Message_v0_3 messageResponse = (Message_v0_3) jsonResponse.getResult(); - assertEquals(MESSAGE.getMessageId(), messageResponse.getMessageId()); - assertEquals(MESSAGE.getRole(), messageResponse.getRole()); - Part_v0_3 part = messageResponse.getParts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("test message", ((TextPart_v0_3) part).getText()); + assertEquals(MESSAGE.messageId(), messageResponse.messageId()); + assertEquals(MESSAGE.role(), messageResponse.role()); + Part_v0_3 part = messageResponse.parts().get(0); + assertInstanceOf(TextPart_v0_3.class, part); + assertEquals("test message", ((TextPart_v0_3) part).text()); latch.countDown(); } } catch (JsonProcessingException_v0_3 e) { @@ -1413,7 +1413,7 @@ private void testSendStreamingMessageWithHttpClient(String mediaType) throws Exc Assertions.assertNull(errorRef.get()); } finally { - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } @@ -1424,7 +1424,7 @@ public void testSendStreamingMessage(boolean createTask) throws Exception { try { Message_v0_3.Builder messageBuilder = new Message_v0_3.Builder(MESSAGE); if (createTask) { - messageBuilder.taskId(MINIMAL_TASK.getId()).contextId(MINIMAL_TASK.getContextId()); + messageBuilder.taskId(MINIMAL_TASK.id()).contextId(MINIMAL_TASK.contextId()); } Message_v0_3 message = messageBuilder.build(); @@ -1460,16 +1460,16 @@ public void testSendStreamingMessage(boolean createTask) throws Exception { Message_v0_3 messageResponse = receivedMessage.get(); assertNotNull(messageResponse); - assertEquals(MESSAGE.getMessageId(), messageResponse.getMessageId()); - assertEquals(MESSAGE.getRole(), messageResponse.getRole()); - Part_v0_3 part = messageResponse.getParts().get(0); - assertEquals(Part_v0_3.Kind.TEXT, part.getKind()); - assertEquals("test message", ((TextPart_v0_3) part).getText()); + assertEquals(MESSAGE.messageId(), messageResponse.messageId()); + assertEquals(MESSAGE.role(), messageResponse.role()); + Part_v0_3 part = messageResponse.parts().get(0); + assertInstanceOf(TextPart_v0_3.class, part); + assertEquals("test message", ((TextPart_v0_3) part).text()); } catch (A2AClientException_v0_3 e) { fail("Unexpected exception during sendMessage: " + e.getMessage(), e); } finally { if (createTask) { - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } } @@ -1617,10 +1617,10 @@ protected void enqueueEventOnServer(Event_v0_3 event) throws Exception { Object v10Event; if (event instanceof TaskArtifactUpdateEvent_v0_3 e) { - path = "test/queue/enqueueTaskArtifactUpdateEvent/" + e.getTaskId(); + path = "test/queue/enqueueTaskArtifactUpdateEvent/" + e.taskId(); v10Event = TaskArtifactUpdateEventMapper_v0_3.INSTANCE.toV10(e); } else if (event instanceof TaskStatusUpdateEvent_v0_3 e) { - path = "test/queue/enqueueTaskStatusUpdateEvent/" + e.getTaskId(); + path = "test/queue/enqueueTaskStatusUpdateEvent/" + e.taskId(); v10Event = TaskStatusUpdateEventMapper_v0_3.INSTANCE.toV10(e); } else { throw new RuntimeException("Unknown event type " + event.getClass() + ". If you need the ability to" + @@ -1983,18 +1983,18 @@ public void testMainQueueClosesForFinalizedTasks() throws Exception { BiConsumer consumer = (event, agentCard) -> { if (event instanceof TaskEvent_v0_3 te) { - generatedTaskId.compareAndSet(null, te.getTask().getId()); + generatedTaskId.compareAndSet(null, te.getTask().id()); // Might get Task with final state - if (te.getTask().getStatus().state().isFinal()) { + if (te.getTask().status().state().isFinal()) { completionLatch.countDown(); } } else if (event instanceof MessageEvent_v0_3 me) { // Message is considered a final event - capture taskId from the message - generatedTaskId.compareAndSet(null, me.getMessage().getTaskId()); + generatedTaskId.compareAndSet(null, me.getMessage().taskId()); completionLatch.countDown(); } else if (event instanceof TaskUpdateEvent_v0_3 tue && tue.getUpdateEvent() instanceof TaskStatusUpdateEvent_v0_3 status) { - generatedTaskId.compareAndSet(null, status.getTaskId()); + generatedTaskId.compareAndSet(null, status.taskId()); if (status.isFinal()) { completionLatch.countDown(); } diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerWithAuthTest_v0_3.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerWithAuthTest_v0_3.java index 08540b61c..525dbb798 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerWithAuthTest_v0_3.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AbstractA2AServerWithAuthTest_v0_3.java @@ -195,14 +195,14 @@ public void testGetTaskRequiresAuthenticationUnauthenticated() throws Exception Client_v0_3 unauthClient = getUnauthenticatedClient(); A2AClientException_v0_3 error = assertThrows(A2AClientException_v0_3.class, () -> { - unauthClient.getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + unauthClient.getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.id())); }); assertTrue(error.getMessage().contains("Authentication failed") || error.getMessage().contains("401") || error.getMessage().contains("Unauthorized"), "Expected authentication error, got: " + error.getMessage()); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } @Test @@ -210,11 +210,11 @@ public void testGetTaskWithAuthentication() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); Client_v0_3 client = getAuthenticatedClient(); - Task_v0_3 result = client.getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + Task_v0_3 result = client.getTask(new TaskQueryParams_v0_3(MINIMAL_TASK.id())); assertNotNull(result); - assertEquals(MINIMAL_TASK.getId(), result.getId()); + assertEquals(MINIMAL_TASK.id(), result.id()); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } @Test @@ -231,11 +231,11 @@ public void testBasicAuthWorksViaHttp() throws Exception { givenAuthenticated() .contentType("application/json") - .body("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tasks/get\",\"params\":{\"id\":\"" + MINIMAL_TASK.getId() + "\"}}") + .body("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tasks/get\",\"params\":{\"id\":\"" + MINIMAL_TASK.id() + "\"}}") .post("/") .then() .statusCode(200); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3_Test.java b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3_Test.java index be1695469..1512f80d9 100644 --- a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3_Test.java +++ b/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/mappers/domain/TaskMapper_v0_3_Test.java @@ -125,14 +125,14 @@ void testFullyPopulatedTaskConversion() { // Verify round-trip conversion assertNotNull(v03TaskRoundTrip); - assertEquals("task-001", v03TaskRoundTrip.getId()); - assertEquals("ctx-001", v03TaskRoundTrip.getContextId()); - assertEquals(TaskState_v0_3.WORKING, v03TaskRoundTrip.getStatus().state()); - assertEquals("msg-001", v03TaskRoundTrip.getStatus().message().getMessageId()); - assertEquals(1, v03TaskRoundTrip.getArtifacts().size()); - assertEquals("artifact-001", v03TaskRoundTrip.getArtifacts().get(0).artifactId()); - assertEquals(1, v03TaskRoundTrip.getHistory().size()); - assertEquals("msg-002", v03TaskRoundTrip.getHistory().get(0).getMessageId()); + assertEquals("task-001", v03TaskRoundTrip.id()); + assertEquals("ctx-001", v03TaskRoundTrip.contextId()); + assertEquals(TaskState_v0_3.WORKING, v03TaskRoundTrip.status().state()); + assertEquals("msg-001", v03TaskRoundTrip.status().message().messageId()); + assertEquals(1, v03TaskRoundTrip.artifacts().size()); + assertEquals("artifact-001", v03TaskRoundTrip.artifacts().get(0).artifactId()); + assertEquals(1, v03TaskRoundTrip.history().size()); + assertEquals("msg-002", v03TaskRoundTrip.history().get(0).messageId()); } @Test @@ -173,8 +173,8 @@ void testMinimalTaskConversion() { // Round trip Task_v0_3 v03TaskRoundTrip = TaskMapper_v0_3.INSTANCE.fromV10(v10Task); assertNotNull(v03TaskRoundTrip); - assertEquals("task-minimal", v03TaskRoundTrip.getId()); - assertEquals(TaskState_v0_3.SUBMITTED, v03TaskRoundTrip.getStatus().state()); + assertEquals("task-minimal", v03TaskRoundTrip.id()); + assertEquals(TaskState_v0_3.SUBMITTED, v03TaskRoundTrip.status().state()); } @Test diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java index a69a376c8..cb94fa794 100644 --- a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java @@ -136,33 +136,33 @@ public static org.a2aproject.sdk.compat03.grpc.AgentCard agentCard(AgentCard_v0_ public static org.a2aproject.sdk.compat03.grpc.Task task(Task_v0_3 task) { org.a2aproject.sdk.compat03.grpc.Task.Builder builder = org.a2aproject.sdk.compat03.grpc.Task.newBuilder(); - builder.setId(task.getId()); - builder.setContextId(task.getContextId()); - builder.setStatus(taskStatus(task.getStatus())); - if (task.getArtifacts() != null) { - builder.addAllArtifacts(task.getArtifacts().stream().map(ToProto::artifact).collect(Collectors.toList())); + builder.setId(task.id()); + builder.setContextId(task.contextId()); + builder.setStatus(taskStatus(task.status())); + if (task.artifacts() != null) { + builder.addAllArtifacts(task.artifacts().stream().map(ToProto::artifact).collect(Collectors.toList())); } - if (task.getHistory() != null) { - builder.addAllHistory(task.getHistory().stream().map(ToProto::message).collect(Collectors.toList())); + if (task.history() != null) { + builder.addAllHistory(task.history().stream().map(ToProto::message).collect(Collectors.toList())); } - builder.setMetadata(struct(task.getMetadata())); + builder.setMetadata(struct(task.metadata())); return builder.build(); } public static org.a2aproject.sdk.compat03.grpc.Message message(Message_v0_3 message) { org.a2aproject.sdk.compat03.grpc.Message.Builder builder = org.a2aproject.sdk.compat03.grpc.Message.newBuilder(); - builder.setMessageId(message.getMessageId()); - if (message.getContextId() != null) { - builder.setContextId(message.getContextId()); + builder.setMessageId(message.messageId()); + if (message.contextId() != null) { + builder.setContextId(message.contextId()); } - if (message.getTaskId() != null) { - builder.setTaskId(message.getTaskId()); + if (message.taskId() != null) { + builder.setTaskId(message.taskId()); } - builder.setRole(role(message.getRole())); - if (message.getParts() != null) { - builder.addAllContent(message.getParts().stream().map(ToProto::part).collect(Collectors.toList())); + builder.setRole(role(message.role())); + if (message.parts() != null) { + builder.addAllContent(message.parts().stream().map(ToProto::part).collect(Collectors.toList())); } - builder.setMetadata(struct(message.getMetadata())); + builder.setMetadata(struct(message.metadata())); return builder.build(); } @@ -193,29 +193,29 @@ private static org.a2aproject.sdk.compat03.grpc.PushNotificationConfig pushNotif public static org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent taskArtifactUpdateEvent(TaskArtifactUpdateEvent_v0_3 event) { org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.Builder builder = org.a2aproject.sdk.compat03.grpc.TaskArtifactUpdateEvent.newBuilder(); - builder.setTaskId(event.getTaskId()); - builder.setContextId(event.getContextId()); - builder.setArtifact(artifact(event.getArtifact())); - if (event.isAppend() != null) { - builder.setAppend(event.isAppend()); + builder.setTaskId(event.taskId()); + builder.setContextId(event.contextId()); + builder.setArtifact(artifact(event.artifact())); + if (event.append() != null) { + builder.setAppend(event.append()); } - if (event.isLastChunk() != null) { - builder.setLastChunk(event.isLastChunk()); + if (event.lastChunk() != null) { + builder.setLastChunk(event.lastChunk()); } - if (event.getMetadata() != null) { - builder.setMetadata(struct(event.getMetadata())); + if (event.metadata() != null) { + builder.setMetadata(struct(event.metadata())); } return builder.build(); } public static org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent taskStatusUpdateEvent(TaskStatusUpdateEvent_v0_3 event) { org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.Builder builder = org.a2aproject.sdk.compat03.grpc.TaskStatusUpdateEvent.newBuilder(); - builder.setTaskId(event.getTaskId()); - builder.setContextId(event.getContextId()); - builder.setStatus(taskStatus(event.getStatus())); + builder.setTaskId(event.taskId()); + builder.setContextId(event.contextId()); + builder.setStatus(taskStatus(event.status())); builder.setFinal(event.isFinal()); - if (event.getMetadata() != null) { - builder.setMetadata(struct(event.getMetadata())); + if (event.metadata() != null) { + builder.setMetadata(struct(event.metadata())); } return builder.build(); } @@ -242,19 +242,19 @@ private static org.a2aproject.sdk.compat03.grpc.Artifact artifact(Artifact_v0_3 private static org.a2aproject.sdk.compat03.grpc.Part part(Part_v0_3 part) { org.a2aproject.sdk.compat03.grpc.Part.Builder builder = org.a2aproject.sdk.compat03.grpc.Part.newBuilder(); - if (part instanceof TextPart_v0_3) { - builder.setText(((TextPart_v0_3) part).getText()); - } else if (part instanceof FilePart_v0_3) { - builder.setFile(filePart((FilePart_v0_3) part)); - } else if (part instanceof DataPart_v0_3) { - builder.setData(dataPart((DataPart_v0_3) part)); + if (part instanceof TextPart_v0_3 textPart) { + builder.setText(textPart.text()); + } else if (part instanceof FilePart_v0_3 fp) { + builder.setFile(filePart(fp)); + } else if (part instanceof DataPart_v0_3 dp) { + builder.setData(dataPart(dp)); } return builder.build(); } private static org.a2aproject.sdk.compat03.grpc.FilePart filePart(FilePart_v0_3 filePart) { org.a2aproject.sdk.compat03.grpc.FilePart.Builder builder = org.a2aproject.sdk.compat03.grpc.FilePart.newBuilder(); - FileContent_v0_3 fileContent = filePart.getFile(); + FileContent_v0_3 fileContent = filePart.file(); if (fileContent instanceof FileWithBytes_v0_3) { builder.setFileWithBytes(ByteString.copyFrom(((FileWithBytes_v0_3) fileContent).bytes(), StandardCharsets.UTF_8)); } else if (fileContent instanceof FileWithUri_v0_3) { @@ -265,8 +265,8 @@ private static org.a2aproject.sdk.compat03.grpc.FilePart filePart(FilePart_v0_3 private static org.a2aproject.sdk.compat03.grpc.DataPart dataPart(DataPart_v0_3 dataPart) { org.a2aproject.sdk.compat03.grpc.DataPart.Builder builder = org.a2aproject.sdk.compat03.grpc.DataPart.newBuilder(); - if (dataPart.getData() != null) { - builder.setData(struct(dataPart.getData())); + if (dataPart.data() != null) { + builder.setData(struct(dataPart.data())); } return builder.build(); } @@ -458,42 +458,42 @@ private static org.a2aproject.sdk.compat03.grpc.SecurityScheme securityScheme(Se private static org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme apiKeySecurityScheme(APIKeySecurityScheme_v0_3 apiKeySecurityScheme) { org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.APIKeySecurityScheme.newBuilder(); - if (apiKeySecurityScheme.getDescription() != null) { - builder.setDescription(apiKeySecurityScheme.getDescription()); + if (apiKeySecurityScheme.description() != null) { + builder.setDescription(apiKeySecurityScheme.description()); } - if (apiKeySecurityScheme.getIn() != null) { - builder.setLocation(apiKeySecurityScheme.getIn()); + if (apiKeySecurityScheme.in() != null) { + builder.setLocation(apiKeySecurityScheme.in()); } - if (apiKeySecurityScheme.getName() != null) { - builder.setName(apiKeySecurityScheme.getName()); + if (apiKeySecurityScheme.name() != null) { + builder.setName(apiKeySecurityScheme.name()); } return builder.build(); } private static org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme httpAuthSecurityScheme(HTTPAuthSecurityScheme_v0_3 httpAuthSecurityScheme) { org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.HTTPAuthSecurityScheme.newBuilder(); - if (httpAuthSecurityScheme.getBearerFormat() != null) { - builder.setBearerFormat(httpAuthSecurityScheme.getBearerFormat()); + if (httpAuthSecurityScheme.bearerFormat() != null) { + builder.setBearerFormat(httpAuthSecurityScheme.bearerFormat()); } - if (httpAuthSecurityScheme.getDescription() != null) { - builder.setDescription(httpAuthSecurityScheme.getDescription()); + if (httpAuthSecurityScheme.description() != null) { + builder.setDescription(httpAuthSecurityScheme.description()); } - if (httpAuthSecurityScheme.getScheme() != null) { - builder.setScheme(httpAuthSecurityScheme.getScheme()); + if (httpAuthSecurityScheme.scheme() != null) { + builder.setScheme(httpAuthSecurityScheme.scheme()); } return builder.build(); } private static org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme oauthSecurityScheme(OAuth2SecurityScheme_v0_3 oauth2SecurityScheme) { org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.OAuth2SecurityScheme.newBuilder(); - if (oauth2SecurityScheme.getDescription() != null) { - builder.setDescription(oauth2SecurityScheme.getDescription()); + if (oauth2SecurityScheme.description() != null) { + builder.setDescription(oauth2SecurityScheme.description()); } - if (oauth2SecurityScheme.getFlows() != null) { - builder.setFlows(oauthFlows(oauth2SecurityScheme.getFlows())); + if (oauth2SecurityScheme.flows() != null) { + builder.setFlows(oauthFlows(oauth2SecurityScheme.flows())); } - if (oauth2SecurityScheme.getOauth2MetadataUrl() != null) { - builder.setOauth2MetadataUrl(oauth2SecurityScheme.getOauth2MetadataUrl()); + if (oauth2SecurityScheme.oauth2MetadataUrl() != null) { + builder.setOauth2MetadataUrl(oauth2SecurityScheme.oauth2MetadataUrl()); } return builder.build(); } @@ -584,19 +584,19 @@ private static org.a2aproject.sdk.compat03.grpc.PasswordOAuthFlow passwordOAuthF private static org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme openIdConnectSecurityScheme(OpenIdConnectSecurityScheme_v0_3 openIdConnectSecurityScheme) { org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.OpenIdConnectSecurityScheme.newBuilder(); - if (openIdConnectSecurityScheme.getDescription() != null) { - builder.setDescription(openIdConnectSecurityScheme.getDescription()); + if (openIdConnectSecurityScheme.description() != null) { + builder.setDescription(openIdConnectSecurityScheme.description()); } - if (openIdConnectSecurityScheme.getOpenIdConnectUrl() != null) { - builder.setOpenIdConnectUrl(openIdConnectSecurityScheme.getOpenIdConnectUrl()); + if (openIdConnectSecurityScheme.openIdConnectUrl() != null) { + builder.setOpenIdConnectUrl(openIdConnectSecurityScheme.openIdConnectUrl()); } return builder.build(); } private static org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme mutualTlsSecurityScheme(MutualTLSSecurityScheme_v0_3 mutualTlsSecurityScheme) { org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.Builder builder = org.a2aproject.sdk.compat03.grpc.MutualTlsSecurityScheme.newBuilder(); - if (mutualTlsSecurityScheme.getDescription() != null) { - builder.setDescription(mutualTlsSecurityScheme.getDescription()); + if (mutualTlsSecurityScheme.description() != null) { + builder.setDescription(mutualTlsSecurityScheme.description()); } return builder.build(); } @@ -612,7 +612,7 @@ private static org.a2aproject.sdk.compat03.grpc.AgentInterface agentInterface(Ag return builder.build(); } - public static Struct struct(Map map) { + public static Struct struct(@Nullable Map map) { Struct.Builder structBuilder = Struct.newBuilder(); if (map != null) { map.forEach((k, v) -> structBuilder.putFields(k, value(v))); diff --git a/compat-0.3/spec-grpc/src/test/java/org/a2aproject/sdk/compat03/grpc/utils/ToProto_v0_3_Test.java b/compat-0.3/spec-grpc/src/test/java/org/a2aproject/sdk/compat03/grpc/utils/ToProto_v0_3_Test.java index f4b7d9204..f17ae8896 100644 --- a/compat-0.3/spec-grpc/src/test/java/org/a2aproject/sdk/compat03/grpc/utils/ToProto_v0_3_Test.java +++ b/compat-0.3/spec-grpc/src/test/java/org/a2aproject/sdk/compat03/grpc/utils/ToProto_v0_3_Test.java @@ -284,7 +284,7 @@ public void convertTaskTimestampStatus() { org.a2aproject.sdk.compat03.grpc.Task grpcTask = ProtoUtils_v0_3.ToProto.task(task); task = ProtoUtils_v0_3.FromProto.task(grpcTask); - TaskStatus_v0_3 status = task.getStatus(); + TaskStatus_v0_3 status = task.status(); assertEquals(TaskState_v0_3.COMPLETED, status.state()); assertNotNull(status.timestamp()); assertEquals(expectedTimestamp, status.timestamp()); diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java index 5798b27bf..4239cd2e5 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/json/JsonUtil_v0_3.java @@ -705,8 +705,8 @@ public void write(JsonWriter out, EventKind_v0_3 value) throws java.io.IOExcepti String kind = kindElement.getAsString(); return switch (kind) { - case Task_v0_3.TASK -> delegateGson.fromJson(jsonElement, Task_v0_3.class); - case Message_v0_3.MESSAGE -> delegateGson.fromJson(jsonElement, Message_v0_3.class); + case Task_v0_3.KIND -> delegateGson.fromJson(jsonElement, Task_v0_3.class); + case Message_v0_3.KIND -> delegateGson.fromJson(jsonElement, Message_v0_3.class); default -> throw new JsonSyntaxException("Unknown EventKind kind: " + kind); }; } @@ -850,15 +850,15 @@ public void write(JsonWriter out, SecurityScheme_v0_3 value) throws java.io.IOEx String type = typeElement.getAsString(); return switch (type) { - case APIKeySecurityScheme_v0_3.API_KEY -> + case APIKeySecurityScheme_v0_3.TYPE -> delegateGson.fromJson(jsonElement, APIKeySecurityScheme_v0_3.class); - case HTTPAuthSecurityScheme_v0_3.HTTP -> + case HTTPAuthSecurityScheme_v0_3.TYPE -> delegateGson.fromJson(jsonElement, HTTPAuthSecurityScheme_v0_3.class); - case OAuth2SecurityScheme_v0_3.OAUTH2 -> + case OAuth2SecurityScheme_v0_3.TYPE -> delegateGson.fromJson(jsonElement, OAuth2SecurityScheme_v0_3.class); - case OpenIdConnectSecurityScheme_v0_3.OPENID_CONNECT -> + case OpenIdConnectSecurityScheme_v0_3.TYPE -> delegateGson.fromJson(jsonElement, OpenIdConnectSecurityScheme_v0_3.class); - case MutualTLSSecurityScheme_v0_3.MUTUAL_TLS -> + case MutualTLSSecurityScheme_v0_3.TYPE -> delegateGson.fromJson(jsonElement, MutualTLSSecurityScheme_v0_3.class); default -> throw new JsonSyntaxException("Unknown SecurityScheme type: " + type); diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java index 33fde3d61..8e425540d 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java @@ -1,17 +1,14 @@ package org.a2aproject.sdk.compat03.spec; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Defines a security scheme using an API key. */ -public final class APIKeySecurityScheme_v0_3 implements SecurityScheme_v0_3 { +public record APIKeySecurityScheme_v0_3(String in, String name, @Nullable String description, String type) implements SecurityScheme_v0_3 { - public static final String API_KEY = "apiKey"; - private final String in; - private final String name; - private final String type; - private final String description; + public static final String TYPE = "apiKey"; /** * Represents the location of the API key. @@ -47,40 +44,19 @@ public static Location fromString(String location) { } } - public APIKeySecurityScheme_v0_3(String in, String name, String description) { - this(in, name, description, API_KEY); - } - - public APIKeySecurityScheme_v0_3(String in, String name, - String description, String type) { + public APIKeySecurityScheme_v0_3 { Assert.checkNotNullParam("in", in); Assert.checkNotNullParam("name", name); - Assert.checkNotNullParam("type", type); - if (! type.equals(API_KEY)) { + if (type == null) { + type = TYPE; + } + if (!type.equals(TYPE)) { throw new IllegalArgumentException("Invalid type for APIKeySecurityScheme"); } - this.in = in; - this.name = name; - this.description = description; - this.type = type; - } - - @Override - public String getDescription() { - return description; - } - - - public String getIn() { - return in; - } - - public String getName() { - return name; } - public String getType() { - return type; + public APIKeySecurityScheme_v0_3(String in, String name, @Nullable String description) { + this(in, name, description, TYPE); } public static class Builder { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java index a53b55a60..de6ba65aa 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java @@ -3,41 +3,30 @@ import java.util.Map; import org.a2aproject.sdk.util.Assert; - +import org.jspecify.annotations.Nullable; /** * Represents a structured data segment (e.g., JSON) within a message or artifact. */ -public class DataPart_v0_3 extends Part_v0_3> { +public record DataPart_v0_3(Map data, @Nullable Map metadata, Kind kind) implements Part_v0_3> { public static final String DATA = "data"; - private final Map data; - private final Map metadata; - private final Kind kind; - - public DataPart_v0_3(Map data) { - this(data, null); - } - public DataPart_v0_3(Map data, Map metadata) { + public DataPart_v0_3 { Assert.checkNotNullParam("data", data); - this.data = data; - this.metadata = metadata; - this.kind = Kind.DATA; + if (kind == null) { + kind = Kind.DATA; + } + if (kind != Kind.DATA) { + throw new IllegalArgumentException("Invalid DataPart kind: " + kind); + } } - @Override - public Kind getKind() { - return kind; - } - - public Map getData() { - return data; + public DataPart_v0_3(Map data) { + this(data, null, Kind.DATA); } - @Override - public Map getMetadata() { - return metadata; + public DataPart_v0_3(Map data, @Nullable Map metadata) { + this(data, metadata, Kind.DATA); } - } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/EventKind_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/EventKind_v0_3.java index 374120a33..9b9f3af02 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/EventKind_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/EventKind_v0_3.java @@ -21,5 +21,5 @@ */ public interface EventKind_v0_3 { - String getKind(); + String kind(); } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java index bb2fba6ed..b957d2063 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java @@ -3,41 +3,31 @@ import java.util.Map; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a file segment within a message or artifact. The file content can be * provided either directly as bytes or as a URI. */ -public class FilePart_v0_3 extends Part_v0_3 { +public record FilePart_v0_3(FileContent_v0_3 file, @Nullable Map metadata, Kind kind) implements Part_v0_3 { public static final String FILE = "file"; - private final FileContent_v0_3 file; - private final Map metadata; - private final Kind kind; - public FilePart_v0_3(FileContent_v0_3 file) { - this(file, null); - } - - public FilePart_v0_3(FileContent_v0_3 file, Map metadata) { + public FilePart_v0_3 { Assert.checkNotNullParam("file", file); - this.file = file; - this.metadata = metadata; - this.kind = Kind.FILE; + if (kind == null) { + kind = Kind.FILE; + } + if (kind != Kind.FILE) { + throw new IllegalArgumentException("Invalid FilePart kind: " + kind); + } } - @Override - public Kind getKind() { - return kind; - } - - public FileContent_v0_3 getFile() { - return file; + public FilePart_v0_3(FileContent_v0_3 file) { + this(file, null, Kind.FILE); } - @Override - public Map getMetadata() { - return metadata; + public FilePart_v0_3(FileContent_v0_3 file, @Nullable Map metadata) { + this(file, metadata, Kind.FILE); } - -} \ No newline at end of file +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java index 15729a7d6..56d46625a 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java @@ -1,49 +1,32 @@ package org.a2aproject.sdk.compat03.spec; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Defines a security scheme using HTTP authentication. */ -public final class HTTPAuthSecurityScheme_v0_3 implements SecurityScheme_v0_3 { +public record HTTPAuthSecurityScheme_v0_3( + @Nullable String bearerFormat, + String scheme, + @Nullable String description, + String type +) implements SecurityScheme_v0_3 { - public static final String HTTP = "http"; - private final String bearerFormat; - private final String scheme; - private final String description; - private final String type; + public static final String TYPE = "http"; - public HTTPAuthSecurityScheme_v0_3(String bearerFormat, String scheme, String description) { - this(bearerFormat, scheme, description, HTTP); - } - - public HTTPAuthSecurityScheme_v0_3(String bearerFormat, String scheme, String description, String type) { + public HTTPAuthSecurityScheme_v0_3 { Assert.checkNotNullParam("scheme", scheme); - Assert.checkNotNullParam("type", type); - if (! HTTP.equals(type)) { + if (type == null) { + type = TYPE; + } + if (!TYPE.equals(type)) { throw new IllegalArgumentException("Invalid type for HTTPAuthSecurityScheme"); } - this.bearerFormat = bearerFormat; - this.scheme = scheme; - this.description = description; - this.type = type; - } - - @Override - public String getDescription() { - return description; - } - - public String getBearerFormat() { - return bearerFormat; - } - - public String getScheme() { - return scheme; } - public String getType() { - return type; + public HTTPAuthSecurityScheme_v0_3(@Nullable String bearerFormat, String scheme, @Nullable String description) { + this(bearerFormat, scheme, description, TYPE); } public static class Builder { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IntegerJsonrpcId_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IntegerJsonrpcId_v0_3.java deleted file mode 100644 index c84c65cac..000000000 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/IntegerJsonrpcId_v0_3.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.a2aproject.sdk.compat03.spec; - -public class IntegerJsonrpcId_v0_3 { -} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendParams_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendParams_v0_3.java index 3b5571c52..fff0204b0 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendParams_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MessageSendParams_v0_3.java @@ -17,7 +17,6 @@ public record MessageSendParams_v0_3(Message_v0_3 message, MessageSendConfigurat public void check() { Assert.checkNotNullParam("message", message); - message.check(); } public static class Builder { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java index 16dc0ad8e..15f4d49f2 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java @@ -5,110 +5,47 @@ import java.util.UUID; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a single message in the conversation between a user and an agent. */ -public final class Message_v0_3 implements EventKind_v0_3, StreamingEventKind_v0_3 { - - public static final String MESSAGE = "message"; - private final Role role; - private final List> parts; - private final String messageId; - private String contextId; - private String taskId; - private final Map metadata; - private final String kind; - private final List referenceTaskIds; - private final List extensions; - - public Message_v0_3(Role role, List> parts, String messageId, String contextId, String taskId, - List referenceTaskIds, Map metadata, List extensions) { - this(role, parts, messageId, contextId, taskId, referenceTaskIds, metadata, extensions, MESSAGE); - } - - public Message_v0_3(Role role, List> parts, - String messageId, String contextId, - String taskId, List referenceTaskIds, - Map metadata, List extensions, - String kind) { - Assert.checkNotNullParam("kind", kind); +public record Message_v0_3( + Role role, + List> parts, + String messageId, + @Nullable String contextId, + @Nullable String taskId, + @Nullable List referenceTaskIds, + @Nullable Map metadata, + @Nullable List extensions, + String kind +) implements EventKind_v0_3, StreamingEventKind_v0_3 { + + public static final String KIND = "message"; + + public Message_v0_3 { + Assert.checkNotNullParam("role", role); Assert.checkNotNullParam("parts", parts); + parts = List.copyOf(parts); if (parts.isEmpty()) { throw new IllegalArgumentException("Parts cannot be empty"); } - Assert.checkNotNullParam("role", role); - if (! kind.equals(MESSAGE)) { - throw new IllegalArgumentException("Invalid Message"); + if (messageId == null) { + messageId = UUID.randomUUID().toString(); } - Assert.checkNotNullParam("messageId", messageId); - this.role = role; - this.parts = parts; - this.messageId = messageId; - this.contextId = contextId; - this.taskId = taskId; - this.referenceTaskIds = referenceTaskIds; - this.metadata = metadata; - this.extensions = extensions; - this.kind = kind; - } - - public void check() { - Assert.checkNotNullParam("kind", kind); - Assert.checkNotNullParam("parts", parts); - if (parts.isEmpty()) { - throw new IllegalArgumentException("Parts cannot be empty"); + if (kind == null) { + kind = KIND; } - Assert.checkNotNullParam("role", role); - if (!kind.equals(MESSAGE)) { + if (!kind.equals(KIND)) { throw new IllegalArgumentException("Invalid Message"); } - Assert.checkNotNullParam("messageId", messageId); - } - - public Role getRole() { - return role; - } - - public List> getParts() { - return parts; - } - - public String getMessageId() { - return messageId; - } - - public String getContextId() { - return contextId; - } - - public String getTaskId() { - return taskId; - } - - public Map getMetadata() { - return metadata; - } - - public void setTaskId(String taskId) { - this.taskId = taskId; - } - - public void setContextId(String contextId) { - this.contextId = contextId; - } - - public List getReferenceTaskIds() { - return referenceTaskIds; - } - - public List getExtensions() { - return extensions; } - @Override - public String getKind() { - return kind; + public Message_v0_3(Role role, List> parts, String messageId, @Nullable String contextId, + @Nullable String taskId, @Nullable List referenceTaskIds, + @Nullable Map metadata, @Nullable List extensions) { + this(role, parts, messageId, contextId, taskId, referenceTaskIds, metadata, extensions, KIND); } public enum Role { @@ -166,7 +103,7 @@ public Builder parts(List> parts) { return this; } - public Builder parts(Part_v0_3...parts) { + public Builder parts(Part_v0_3... parts) { this.parts = List.of(parts); return this; } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java index dd7ca56ec..6fa813a89 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java @@ -1,40 +1,28 @@ package org.a2aproject.sdk.compat03.spec; -import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Defines a security scheme using mTLS authentication. */ -public final class MutualTLSSecurityScheme_v0_3 implements SecurityScheme_v0_3 { +public record MutualTLSSecurityScheme_v0_3(@Nullable String description, String type) implements SecurityScheme_v0_3 { - public static final String MUTUAL_TLS = "mutualTLS"; - private final String description; - private final String type; + public static final String TYPE = "mutualTLS"; - public MutualTLSSecurityScheme_v0_3(String description) { - this(description, MUTUAL_TLS); - } - - public MutualTLSSecurityScheme_v0_3() { - this(null, MUTUAL_TLS); - } - - public MutualTLSSecurityScheme_v0_3(String description, String type) { - Assert.checkNotNullParam("type", type); - if (!type.equals(MUTUAL_TLS)) { + public MutualTLSSecurityScheme_v0_3 { + if (type == null) { + type = TYPE; + } + if (!type.equals(TYPE)) { throw new IllegalArgumentException("Invalid type for MutualTLSSecurityScheme"); } - this.description = description; - this.type = type; } - @Override - public String getDescription() { - return description; + public MutualTLSSecurityScheme_v0_3(@Nullable String description) { + this(description, TYPE); } - public String getType() { - return type; + public MutualTLSSecurityScheme_v0_3() { + this(null, TYPE); } - } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java index c0f1de56e..332794e00 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java @@ -1,49 +1,32 @@ package org.a2aproject.sdk.compat03.spec; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Defines a security scheme using OAuth 2.0. */ -public final class OAuth2SecurityScheme_v0_3 implements SecurityScheme_v0_3 { +public record OAuth2SecurityScheme_v0_3( + OAuthFlows_v0_3 flows, + @Nullable String description, + @Nullable String oauth2MetadataUrl, + String type +) implements SecurityScheme_v0_3 { - public static final String OAUTH2 = "oauth2"; - private final OAuthFlows_v0_3 flows; - private final String description; - private final String type; - private final String oauth2MetadataUrl; + public static final String TYPE = "oauth2"; - public OAuth2SecurityScheme_v0_3(OAuthFlows_v0_3 flows, String description, String oauth2MetadataUrl) { - this(flows, description, oauth2MetadataUrl, OAUTH2); - } - - public OAuth2SecurityScheme_v0_3(OAuthFlows_v0_3 flows, String description, String oauth2MetadataUrl, String type) { + public OAuth2SecurityScheme_v0_3 { Assert.checkNotNullParam("flows", flows); - Assert.checkNotNullParam("type", type); - if (!type.equals(OAUTH2)) { + if (type == null) { + type = TYPE; + } + if (!type.equals(TYPE)) { throw new IllegalArgumentException("Invalid type for OAuth2SecurityScheme"); } - this.flows = flows; - this.description = description; - this.oauth2MetadataUrl = oauth2MetadataUrl; - this.type = type; - } - - @Override - public String getDescription() { - return description; - } - - public OAuthFlows_v0_3 getFlows() { - return flows; - } - - public String getType() { - return type; } - public String getOauth2MetadataUrl() { - return oauth2MetadataUrl; + public OAuth2SecurityScheme_v0_3(OAuthFlows_v0_3 flows, @Nullable String description, @Nullable String oauth2MetadataUrl) { + this(flows, description, oauth2MetadataUrl, TYPE); } public static class Builder { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OpenIdConnectSecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OpenIdConnectSecurityScheme_v0_3.java index 81cbcc4c4..5e7b06ad4 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OpenIdConnectSecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OpenIdConnectSecurityScheme_v0_3.java @@ -1,43 +1,31 @@ package org.a2aproject.sdk.compat03.spec; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Defines a security scheme using OpenID Connect. */ -public final class OpenIdConnectSecurityScheme_v0_3 implements SecurityScheme_v0_3 { +public record OpenIdConnectSecurityScheme_v0_3( + String openIdConnectUrl, + @Nullable String description, + String type +) implements SecurityScheme_v0_3 { - public static final String OPENID_CONNECT = "openIdConnect"; - private final String openIdConnectUrl; - private final String description; - private final String type; + public static final String TYPE = "openIdConnect"; - public OpenIdConnectSecurityScheme_v0_3(String openIdConnectUrl, String description) { - this(openIdConnectUrl, description, OPENID_CONNECT); - } - - public OpenIdConnectSecurityScheme_v0_3(String openIdConnectUrl, String description, String type) { - Assert.checkNotNullParam("type", type); + public OpenIdConnectSecurityScheme_v0_3 { Assert.checkNotNullParam("openIdConnectUrl", openIdConnectUrl); - if (!type.equals(OPENID_CONNECT)) { + if (type == null) { + type = TYPE; + } + if (!type.equals(TYPE)) { throw new IllegalArgumentException("Invalid type for OpenIdConnectSecurityScheme"); } - this.openIdConnectUrl = openIdConnectUrl; - this.description = description; - this.type = type; - } - - @Override - public String getDescription() { - return description; - } - - public String getOpenIdConnectUrl() { - return openIdConnectUrl; } - public String getType() { - return type; + public OpenIdConnectSecurityScheme_v0_3(String openIdConnectUrl, @Nullable String description) { + this(openIdConnectUrl, description, TYPE); } public static class Builder { @@ -58,5 +46,4 @@ public OpenIdConnectSecurityScheme_v0_3 build() { return new OpenIdConnectSecurityScheme_v0_3(openIdConnectUrl, description); } } - } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Part_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Part_v0_3.java index 79d3df4d7..c26f151a4 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Part_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Part_v0_3.java @@ -1,13 +1,11 @@ package org.a2aproject.sdk.compat03.spec; -import java.util.Map; - /** * A fundamental unit with a Message or Artifact. * @param the type of unit */ -public abstract class Part_v0_3 { - public enum Kind { +public sealed interface Part_v0_3 permits TextPart_v0_3, FilePart_v0_3, DataPart_v0_3 { + enum Kind { TEXT("text"), FILE("file"), DATA("data"); @@ -27,9 +25,4 @@ public String asString() { return this.kind; } } - - public abstract Kind getKind(); - - public abstract Map getMetadata(); - -} \ No newline at end of file +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SecurityScheme_v0_3.java index 36903e849..33885638c 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/SecurityScheme_v0_3.java @@ -7,5 +7,8 @@ public sealed interface SecurityScheme_v0_3 permits APIKeySecurityScheme_v0_3, HTTPAuthSecurityScheme_v0_3, OAuth2SecurityScheme_v0_3, OpenIdConnectSecurityScheme_v0_3, MutualTLSSecurityScheme_v0_3 { - String getDescription(); + @org.jspecify.annotations.Nullable + String description(); + + String type(); } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingEventKind_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingEventKind_v0_3.java index ffc40df0e..0ace23176 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingEventKind_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StreamingEventKind_v0_3.java @@ -31,5 +31,5 @@ */ public sealed interface StreamingEventKind_v0_3 extends Event_v0_3 permits Task_v0_3, Message_v0_3, TaskStatusUpdateEvent_v0_3, TaskArtifactUpdateEvent_v0_3 { - String getKind(); + String kind(); } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StringJsonrpcId_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StringJsonrpcId_v0_3.java deleted file mode 100644 index f4ced0850..000000000 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/StringJsonrpcId_v0_3.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.a2aproject.sdk.compat03.spec; - -public class StringJsonrpcId_v0_3 { -} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java index 397756a2b..e76de3bce 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java @@ -3,70 +3,40 @@ import java.util.Map; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * An event sent by the agent to notify the client that an artifact has been * generated or updated. This is typically used in streaming models. */ -public final class TaskArtifactUpdateEvent_v0_3 implements EventKind_v0_3, StreamingEventKind_v0_3, UpdateEvent_v0_3 { - - public static final String ARTIFACT_UPDATE = "artifact-update"; - private final String taskId; - private final Boolean append; - private final Boolean lastChunk; - private final Artifact_v0_3 artifact; - private final String contextId; - private final Map metadata; - private final String kind; - - public TaskArtifactUpdateEvent_v0_3(String taskId, Artifact_v0_3 artifact, String contextId, Boolean append, Boolean lastChunk, Map metadata) { - this(taskId, artifact, contextId, append, lastChunk, metadata, ARTIFACT_UPDATE); - } - - public TaskArtifactUpdateEvent_v0_3(String taskId, Artifact_v0_3 artifact, String contextId, Boolean append, Boolean lastChunk, Map metadata, String kind) { +public record TaskArtifactUpdateEvent_v0_3( + String taskId, + @Nullable Boolean append, + @Nullable Boolean lastChunk, + Artifact_v0_3 artifact, + String contextId, + @Nullable Map metadata, + String kind +) implements EventKind_v0_3, StreamingEventKind_v0_3, UpdateEvent_v0_3 { + + public static final String KIND = "artifact-update"; + + public TaskArtifactUpdateEvent_v0_3 { Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("artifact", artifact); Assert.checkNotNullParam("contextId", contextId); - Assert.checkNotNullParam("kind", kind); - if (! kind.equals(ARTIFACT_UPDATE)) { + if (kind == null) { + kind = KIND; + } + if (!kind.equals(KIND)) { throw new IllegalArgumentException("Invalid TaskArtifactUpdateEvent"); } - this.taskId = taskId; - this.artifact = artifact; - this.contextId = contextId; - this.append = append; - this.lastChunk = lastChunk; - this.metadata = metadata; - this.kind = kind; - } - - public String getTaskId() { - return taskId; - } - - public Artifact_v0_3 getArtifact() { - return artifact; - } - - public String getContextId() { - return contextId; - } - - public Boolean isAppend() { - return append; - } - - public Boolean isLastChunk() { - return lastChunk; - } - - public Map getMetadata() { - return metadata; } - @Override - public String getKind() { - return kind; + public TaskArtifactUpdateEvent_v0_3(String taskId, Artifact_v0_3 artifact, String contextId, + @Nullable Boolean append, @Nullable Boolean lastChunk, + @Nullable Map metadata) { + this(taskId, append, lastChunk, artifact, contextId, metadata, KIND); } public static class Builder { @@ -81,13 +51,13 @@ public static class Builder { public Builder() { } - public Builder(TaskArtifactUpdateEvent_v0_3 existingTaskArtifactUpdateEvent) { - this.taskId = existingTaskArtifactUpdateEvent.taskId; - this.artifact = existingTaskArtifactUpdateEvent.artifact; - this.contextId = existingTaskArtifactUpdateEvent.contextId; - this.append = existingTaskArtifactUpdateEvent.append; - this.lastChunk = existingTaskArtifactUpdateEvent.lastChunk; - this.metadata = existingTaskArtifactUpdateEvent.metadata; + public Builder(TaskArtifactUpdateEvent_v0_3 existing) { + this.taskId = existing.taskId; + this.artifact = existing.artifact; + this.contextId = existing.contextId; + this.append = existing.append; + this.lastChunk = existing.lastChunk; + this.metadata = existing.metadata; } public Builder taskId(String taskId) { @@ -111,11 +81,10 @@ public Builder append(Boolean append) { } public Builder lastChunk(Boolean lastChunk) { - this.lastChunk = lastChunk; + this.lastChunk = lastChunk; return this; } - public Builder metadata(Map metadata) { this.metadata = metadata; return this; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java index f337169f6..8510efbe9 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java @@ -4,67 +4,38 @@ import java.util.Map; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * An event sent by the agent to notify the client of a change in a task's status. * This is typically used in streaming or subscription models. */ -public final class TaskStatusUpdateEvent_v0_3 implements EventKind_v0_3, StreamingEventKind_v0_3, UpdateEvent_v0_3 { - - public static final String STATUS_UPDATE = "status-update"; - private final String taskId; - private final TaskStatus_v0_3 status; - private final String contextId; - @SerializedName("final") - private final boolean isFinal; - private final Map metadata; - private final String kind; - - - public TaskStatusUpdateEvent_v0_3(String taskId, TaskStatus_v0_3 status, String contextId, boolean isFinal, - Map metadata) { - this(taskId, status, contextId, isFinal, metadata, STATUS_UPDATE); - } - - public TaskStatusUpdateEvent_v0_3(String taskId, TaskStatus_v0_3 status, String contextId, boolean isFinal, Map metadata, String kind) { +public record TaskStatusUpdateEvent_v0_3( + String taskId, + TaskStatus_v0_3 status, + String contextId, + @SerializedName("final") boolean isFinal, + @Nullable Map metadata, + String kind +) implements EventKind_v0_3, StreamingEventKind_v0_3, UpdateEvent_v0_3 { + + public static final String KIND = "status-update"; + + public TaskStatusUpdateEvent_v0_3 { Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("status", status); Assert.checkNotNullParam("contextId", contextId); - Assert.checkNotNullParam("kind", kind); - if (! kind.equals(STATUS_UPDATE)) { + if (kind == null) { + kind = KIND; + } + if (!kind.equals(KIND)) { throw new IllegalArgumentException("Invalid TaskStatusUpdateEvent"); } - this.taskId = taskId; - this.status = status; - this.contextId = contextId; - this.isFinal = isFinal; - this.metadata = metadata; - this.kind = kind; } - public String getTaskId() { - return taskId; - } - - public TaskStatus_v0_3 getStatus() { - return status; - } - - public String getContextId() { - return contextId; - } - - public boolean isFinal() { - return isFinal; - } - - public Map getMetadata() { - return metadata; - } - - @Override - public String getKind() { - return kind; + public TaskStatusUpdateEvent_v0_3(String taskId, TaskStatus_v0_3 status, String contextId, boolean isFinal, + @Nullable Map metadata) { + this(taskId, status, contextId, isFinal, metadata, KIND); } public static class Builder { @@ -77,13 +48,14 @@ public static class Builder { public Builder() { } - public Builder(TaskStatusUpdateEvent_v0_3 existingTaskStatusUpdateEvent) { - this.taskId = existingTaskStatusUpdateEvent.taskId; - this.status = existingTaskStatusUpdateEvent.status; - this.contextId = existingTaskStatusUpdateEvent.contextId; - this.isFinal = existingTaskStatusUpdateEvent.isFinal; - this.metadata = existingTaskStatusUpdateEvent.metadata; + public Builder(TaskStatusUpdateEvent_v0_3 existing) { + this.taskId = existing.taskId; + this.status = existing.status; + this.contextId = existing.contextId; + this.isFinal = existing.isFinal; + this.metadata = existing.metadata; } + public Builder taskId(String id) { this.taskId = id; return this; diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java index 87e486013..52fa1dc35 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java @@ -4,72 +4,40 @@ import java.util.Map; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a single, stateful operation or conversation between a client and an agent. */ -public final class Task_v0_3 implements EventKind_v0_3, StreamingEventKind_v0_3 { - - public static final String TASK = "task"; - private final String id; - private final String contextId; - private final TaskStatus_v0_3 status; - private final List artifacts; - private final List history; - private final Map metadata; - private final String kind; - - public Task_v0_3(String id, String contextId, TaskStatus_v0_3 status, List artifacts, - List history, Map metadata) { - this(id, contextId, status, artifacts, history, metadata, TASK); - } - - public Task_v0_3(String id, String contextId, TaskStatus_v0_3 status, - List artifacts, List history, - Map metadata, String kind) { +public record Task_v0_3( + String id, + String contextId, + TaskStatus_v0_3 status, + List artifacts, + List history, + @Nullable Map metadata, + String kind +) implements EventKind_v0_3, StreamingEventKind_v0_3 { + + public static final String KIND = "task"; + + public Task_v0_3 { Assert.checkNotNullParam("id", id); Assert.checkNotNullParam("contextId", contextId); Assert.checkNotNullParam("status", status); - Assert.checkNotNullParam("kind", kind); - if (! kind.equals(TASK)) { + if (kind == null) { + kind = KIND; + } + if (!kind.equals(KIND)) { throw new IllegalArgumentException("Invalid Task"); } - this.id = id; - this.contextId = contextId; - this.status = status; - this.artifacts = artifacts != null ? List.copyOf(artifacts) : List.of(); - this.history = history != null ? List.copyOf(history) : List.of(); - this.metadata = metadata; - this.kind = kind; + artifacts = artifacts != null ? List.copyOf(artifacts) : List.of(); + history = history != null ? List.copyOf(history) : List.of(); } - public String getId() { - return id; - } - - public String getContextId() { - return contextId; - } - - public TaskStatus_v0_3 getStatus() { - return status; - } - - public List getArtifacts() { - return artifacts; - } - - public List getHistory() { - return history; - } - - public Map getMetadata() { - return metadata; - } - - @Override - public String getKind() { - return kind; + public Task_v0_3(String id, String contextId, TaskStatus_v0_3 status, List artifacts, + List history, @Nullable Map metadata) { + this(id, contextId, status, artifacts, history, metadata, KIND); } public static class Builder { @@ -81,7 +49,6 @@ public static class Builder { private Map metadata; public Builder() { - } public Builder(Task_v0_3 task) { @@ -91,7 +58,6 @@ public Builder(Task_v0_3 task) { artifacts = task.artifacts; history = task.history; metadata = task.metadata; - } public Builder id(String id) { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java index 4d5b604ce..1aa13cbb9 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java @@ -3,39 +3,30 @@ import java.util.Map; import org.a2aproject.sdk.util.Assert; +import org.jspecify.annotations.Nullable; /** * Represents a text segment within a message or artifact. */ -public class TextPart_v0_3 extends Part_v0_3 { +public record TextPart_v0_3(String text, @Nullable Map metadata, Kind kind) implements Part_v0_3 { public static final String TEXT = "text"; - private final String text; - private final Map metadata; - private final Kind kind; - public TextPart_v0_3(String text) { - this(text, null); - } - - public TextPart_v0_3(String text, Map metadata) { + public TextPart_v0_3 { Assert.checkNotNullParam("text", text); - this.text = text; - this.metadata = metadata; - this.kind = Kind.TEXT; + if (kind == null) { + kind = Kind.TEXT; + } + if (kind != Kind.TEXT) { + throw new IllegalArgumentException("Invalid TextPart kind: " + kind); + } } - @Override - public Kind getKind() { - return kind; - } - - public String getText() { - return text; + public TextPart_v0_3(String text) { + this(text, null, Kind.TEXT); } - @Override - public Map getMetadata() { - return metadata; + public TextPart_v0_3(String text, @Nullable Map metadata) { + this(text, metadata, Kind.TEXT); } -} \ No newline at end of file +} diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/util/Utils_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/util/Utils_v0_3.java index 38df3adfc..b2a936f00 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/util/Utils_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/util/Utils_v0_3.java @@ -97,11 +97,11 @@ public static void rethrow(Throwable t) throws T { */ public static Task_v0_3 appendArtifactToTask(Task_v0_3 task, TaskArtifactUpdateEvent_v0_3 event, String taskId) { // Append artifacts - List artifacts = task.getArtifacts() == null ? new ArrayList<>() : new ArrayList<>(task.getArtifacts()); + List artifacts = new ArrayList<>(task.artifacts()); - Artifact_v0_3 newArtifact = event.getArtifact(); + Artifact_v0_3 newArtifact = event.artifact(); String artifactId = newArtifact.artifactId(); - boolean appendParts = event.isAppend() != null && event.isAppend(); + boolean appendParts = event.append() != null && event.append(); Artifact_v0_3 existingArtifact = null; int existingArtifactIndex = -1; diff --git a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/SubTypeSerialization_v0_3_Test.java b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/SubTypeSerialization_v0_3_Test.java index 96c89c152..a55c54d67 100644 --- a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/SubTypeSerialization_v0_3_Test.java +++ b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/SubTypeSerialization_v0_3_Test.java @@ -32,24 +32,24 @@ private static Stream serializationTestCases() { return Stream.of( Arguments.of( new TaskStatusUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) .isFinal(true) - .build(), "kind", TaskStatusUpdateEvent_v0_3.STATUS_UPDATE + .build(), "kind", TaskStatusUpdateEvent_v0_3.KIND ), Arguments.of( new TaskArtifactUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .artifact(new Artifact_v0_3.Builder() .artifactId("11") .parts(new TextPart_v0_3("text")) .build()) - .build(), "kind", TaskArtifactUpdateEvent_v0_3.ARTIFACT_UPDATE + .build(), "kind", TaskArtifactUpdateEvent_v0_3.KIND ), Arguments.of( - MINIMAL_TASK, "kind", Task_v0_3.TASK + MINIMAL_TASK, "kind", Task_v0_3.KIND ), Arguments.of( new Message_v0_3.Builder() @@ -57,7 +57,7 @@ private static Stream serializationTestCases() { .parts(new TextPart_v0_3("tell me some jokes")) .contextId("context-1234") .messageId("message-1234") - .build(), "kind", Message_v0_3.MESSAGE + .build(), "kind", Message_v0_3.KIND ), Arguments.of( new TextPart_v0_3("text"), "kind", TextPart_v0_3.TEXT @@ -73,28 +73,28 @@ private static Stream serializationTestCases() { Arguments.of( new APIKeySecurityScheme_v0_3.Builder() .in("test").name("name").description("description").build(), - "type", APIKeySecurityScheme_v0_3.API_KEY + "type", APIKeySecurityScheme_v0_3.TYPE ), Arguments.of( new HTTPAuthSecurityScheme_v0_3.Builder() .scheme("basic").description("Basic Auth").build(), - "type", HTTPAuthSecurityScheme_v0_3.HTTP + "type", HTTPAuthSecurityScheme_v0_3.TYPE ), Arguments.of( new OAuth2SecurityScheme_v0_3.Builder() .flows(new OAuthFlows_v0_3.Builder().build()) .description("oAuth2SecurityScheme").build(), - "type", OAuth2SecurityScheme_v0_3.OAUTH2 + "type", OAuth2SecurityScheme_v0_3.TYPE ), Arguments.of( new OpenIdConnectSecurityScheme_v0_3.Builder() .openIdConnectUrl("https://accounts.google.com/.well-known/openid-configuration") .description("OpenId").build(), - "type", OpenIdConnectSecurityScheme_v0_3.OPENID_CONNECT + "type", OpenIdConnectSecurityScheme_v0_3.TYPE ), Arguments.of( new MutualTLSSecurityScheme_v0_3("mutual tls test"), - "type", MutualTLSSecurityScheme_v0_3.MUTUAL_TLS + "type", MutualTLSSecurityScheme_v0_3.TYPE ) ); } diff --git a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java index f1ed534a9..dbe7e0243 100644 --- a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java +++ b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java @@ -40,8 +40,8 @@ void testBasicTaskSerialization() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify deserialized task matches original - assertEquals(task.getId(), deserialized.getId()); - assertEquals(task.getStatus().state(), deserialized.getStatus().state()); + assertEquals(task.id(), deserialized.id()); + assertEquals(task.status().state(), deserialized.status().state()); } @Test @@ -61,8 +61,8 @@ void testTaskWithTimestamp() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify OffsetDateTime timestamp is preserved - assertNotNull(deserialized.getStatus().timestamp()); - assertEquals(task.getStatus().timestamp(), deserialized.getStatus().timestamp()); + assertNotNull(deserialized.status().timestamp()); + assertEquals(task.status().timestamp(), deserialized.status().timestamp()); } @Test @@ -96,10 +96,10 @@ void testTaskWithArtifacts() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify artifacts are preserved - assertNotNull(deserialized.getArtifacts()); - assertEquals(1, deserialized.getArtifacts().size()); - assertEquals("artifact-1", deserialized.getArtifacts().get(0).artifactId()); - assertEquals(2, deserialized.getArtifacts().get(0).parts().size()); + assertNotNull(deserialized.artifacts()); + assertEquals(1, deserialized.artifacts().size()); + assertEquals("artifact-1", deserialized.artifacts().get(0).artifactId()); + assertEquals(2, deserialized.artifacts().get(0).parts().size()); } @Test @@ -127,10 +127,10 @@ void testTaskWithHistory() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify history is preserved - assertNotNull(deserialized.getHistory()); - assertEquals(1, deserialized.getHistory().size()); - assertEquals(Message_v0_3.Role.USER, deserialized.getHistory().get(0).getRole()); - assertEquals(1, deserialized.getHistory().get(0).getParts().size()); + assertNotNull(deserialized.history()); + assertEquals(1, deserialized.history().size()); + assertEquals(Message_v0_3.Role.USER, deserialized.history().get(0).role()); + assertEquals(1, deserialized.history().get(0).parts().size()); } @Test @@ -167,14 +167,14 @@ void testTaskWithAllFields() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify all fields are preserved - assertEquals(task.getId(), deserialized.getId()); - assertEquals(task.getContextId(), deserialized.getContextId()); - assertEquals(task.getStatus().state(), deserialized.getStatus().state()); - assertEquals(task.getStatus().timestamp(), deserialized.getStatus().timestamp()); - assertEquals(task.getHistory().size(), deserialized.getHistory().size()); - assertEquals(task.getArtifacts().size(), deserialized.getArtifacts().size()); - assertNotNull(deserialized.getMetadata()); - assertEquals("value1", deserialized.getMetadata().get("key1")); + assertEquals(task.id(), deserialized.id()); + assertEquals(task.contextId(), deserialized.contextId()); + assertEquals(task.status().state(), deserialized.status().state()); + assertEquals(task.status().timestamp(), deserialized.status().timestamp()); + assertEquals(task.history().size(), deserialized.history().size()); + assertEquals(task.artifacts().size(), deserialized.artifacts().size()); + assertNotNull(deserialized.metadata()); + assertEquals("value1", deserialized.metadata().get("key1")); } @Test @@ -196,7 +196,7 @@ void testTaskWithDifferentStates() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify state is preserved - assertEquals(state, deserialized.getStatus().state()); + assertEquals(state, deserialized.status().state()); } } @@ -216,15 +216,15 @@ void testTaskWithNullOptionalFields() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify required fields are present - assertEquals("task-123", deserialized.getId()); - assertEquals("context-456", deserialized.getContextId()); - assertEquals(TaskState_v0_3.SUBMITTED, deserialized.getStatus().state()); + assertEquals("task-123", deserialized.id()); + assertEquals("context-456", deserialized.contextId()); + assertEquals(TaskState_v0_3.SUBMITTED, deserialized.status().state()); // Verify optional lists default to empty - assertNotNull(deserialized.getArtifacts()); - assertEquals(0, deserialized.getArtifacts().size()); - assertNotNull(deserialized.getHistory()); - assertEquals(0, deserialized.getHistory().size()); + assertNotNull(deserialized.artifacts()); + assertEquals(0, deserialized.artifacts().size()); + assertNotNull(deserialized.history()); + assertEquals(0, deserialized.history().size()); } @Test @@ -255,11 +255,11 @@ void testTaskWithFilePartBytes() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify file part is preserved - Part_v0_3 part = deserialized.getArtifacts().get(0).parts().get(0); + Part_v0_3 part = deserialized.artifacts().get(0).parts().get(0); assertTrue(part instanceof FilePart_v0_3); FilePart_v0_3 deserializedFilePart = (FilePart_v0_3) part; - assertTrue(deserializedFilePart.getFile() instanceof FileWithBytes_v0_3); - FileWithBytes_v0_3 fileWithBytes = (FileWithBytes_v0_3) deserializedFilePart.getFile(); + assertTrue(deserializedFilePart.file() instanceof FileWithBytes_v0_3); + FileWithBytes_v0_3 fileWithBytes = (FileWithBytes_v0_3) deserializedFilePart.file(); assertEquals("document.pdf", fileWithBytes.name()); assertEquals("application/pdf", fileWithBytes.mimeType()); } @@ -290,11 +290,11 @@ void testTaskWithFilePartUri() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify file part URI is preserved - Part_v0_3 part = deserialized.getArtifacts().get(0).parts().get(0); + Part_v0_3 part = deserialized.artifacts().get(0).parts().get(0); assertTrue(part instanceof FilePart_v0_3); FilePart_v0_3 deserializedFilePart = (FilePart_v0_3) part; - assertTrue(deserializedFilePart.getFile() instanceof FileWithUri_v0_3); - FileWithUri_v0_3 fileWithUri = (FileWithUri_v0_3) deserializedFilePart.getFile(); + assertTrue(deserializedFilePart.file() instanceof FileWithUri_v0_3); + FileWithUri_v0_3 fileWithUri = (FileWithUri_v0_3) deserializedFilePart.file(); assertEquals("https://example.com/photo.png", fileWithUri.uri()); } @@ -325,10 +325,10 @@ void testTaskWithDataPart() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify data part is preserved - Part_v0_3 part = deserialized.getArtifacts().get(0).parts().get(0); + Part_v0_3 part = deserialized.artifacts().get(0).parts().get(0); assertTrue(part instanceof DataPart_v0_3); DataPart_v0_3 deserializedDataPart = (DataPart_v0_3) part; - assertNotNull(deserializedDataPart.getData()); + assertNotNull(deserializedDataPart.data()); } @Test @@ -372,11 +372,11 @@ void testTaskRoundTrip() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized2 = JsonUtil_v0_3.fromJson(json2, Task_v0_3.class); // Verify multiple round-trips produce identical results - assertEquals(deserialized.getId(), deserialized2.getId()); - assertEquals(deserialized.getContextId(), deserialized2.getContextId()); - assertEquals(deserialized.getStatus().state(), deserialized2.getStatus().state()); - assertEquals(deserialized.getHistory().size(), deserialized2.getHistory().size()); - assertEquals(deserialized.getArtifacts().size(), deserialized2.getArtifacts().size()); + assertEquals(deserialized.id(), deserialized2.id()); + assertEquals(deserialized.contextId(), deserialized2.contextId()); + assertEquals(deserialized.status().state(), deserialized2.status().state()); + assertEquals(deserialized.history().size(), deserialized2.history().size()); + assertEquals(deserialized.artifacts().size(), deserialized2.artifacts().size()); } @Test @@ -403,10 +403,10 @@ void testTaskStatusWithMessage() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify status message is preserved - assertEquals(TaskState_v0_3.COMPLETED, deserialized.getStatus().state()); - assertNotNull(deserialized.getStatus().message()); - assertEquals(Message_v0_3.Role.AGENT, deserialized.getStatus().message().getRole()); - assertTrue(deserialized.getStatus().message().getParts().get(0) instanceof TextPart_v0_3); + assertEquals(TaskState_v0_3.COMPLETED, deserialized.status().state()); + assertNotNull(deserialized.status().message()); + assertEquals(Message_v0_3.Role.AGENT, deserialized.status().message().role()); + assertTrue(deserialized.status().message().parts().get(0) instanceof TextPart_v0_3); } @Test @@ -424,12 +424,12 @@ void testDeserializeTaskFromJson() throws JsonProcessingException_v0_3 { Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); - assertEquals("task-123", task.getId()); - assertEquals("context-456", task.getContextId()); - assertEquals(TaskState_v0_3.SUBMITTED, task.getStatus().state()); - assertNull(task.getStatus().message()); + assertEquals("task-123", task.id()); + assertEquals("context-456", task.contextId()); + assertEquals(TaskState_v0_3.SUBMITTED, task.status().state()); + assertNull(task.status().message()); // TaskStatus automatically sets timestamp to current time if not provided - assertNotNull(task.getStatus().timestamp()); + assertNotNull(task.status().timestamp()); } @Test @@ -459,14 +459,14 @@ void testDeserializeTaskWithArtifactsFromJson() throws JsonProcessingException_v Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); - assertEquals("task-123", task.getId()); - assertEquals(TaskState_v0_3.COMPLETED, task.getStatus().state()); - assertEquals(1, task.getArtifacts().size()); - assertEquals("artifact-1", task.getArtifacts().get(0).artifactId()); - assertEquals("Result", task.getArtifacts().get(0).name()); - assertEquals(1, task.getArtifacts().get(0).parts().size()); - assertTrue(task.getArtifacts().get(0).parts().get(0) instanceof TextPart_v0_3); - assertEquals("Hello World", ((TextPart_v0_3) task.getArtifacts().get(0).parts().get(0)).getText()); + assertEquals("task-123", task.id()); + assertEquals(TaskState_v0_3.COMPLETED, task.status().state()); + assertEquals(1, task.artifacts().size()); + assertEquals("artifact-1", task.artifacts().get(0).artifactId()); + assertEquals("Result", task.artifacts().get(0).name()); + assertEquals(1, task.artifacts().get(0).parts().size()); + assertTrue(task.artifacts().get(0).parts().get(0) instanceof TextPart_v0_3); + assertEquals("Hello World", ((TextPart_v0_3) task.artifacts().get(0).parts().get(0)).text()); } @Test @@ -499,13 +499,13 @@ void testDeserializeTaskWithFilePartBytesFromJson() throws JsonProcessingExcepti Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); - assertEquals("task-123", task.getId()); - assertEquals(1, task.getArtifacts().size()); - Part_v0_3 part = task.getArtifacts().get(0).parts().get(0); + assertEquals("task-123", task.id()); + assertEquals(1, task.artifacts().size()); + Part_v0_3 part = task.artifacts().get(0).parts().get(0); assertTrue(part instanceof FilePart_v0_3); FilePart_v0_3 filePart = (FilePart_v0_3) part; - assertTrue(filePart.getFile() instanceof FileWithBytes_v0_3); - FileWithBytes_v0_3 fileWithBytes = (FileWithBytes_v0_3) filePart.getFile(); + assertTrue(filePart.file() instanceof FileWithBytes_v0_3); + FileWithBytes_v0_3 fileWithBytes = (FileWithBytes_v0_3) filePart.file(); assertEquals("application/pdf", fileWithBytes.mimeType()); assertEquals("document.pdf", fileWithBytes.name()); assertEquals("base64encodeddata", fileWithBytes.bytes()); @@ -541,12 +541,12 @@ void testDeserializeTaskWithFilePartUriFromJson() throws JsonProcessingException Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); - assertEquals("task-123", task.getId()); - Part_v0_3 part = task.getArtifacts().get(0).parts().get(0); + assertEquals("task-123", task.id()); + Part_v0_3 part = task.artifacts().get(0).parts().get(0); assertTrue(part instanceof FilePart_v0_3); FilePart_v0_3 filePart = (FilePart_v0_3) part; - assertTrue(filePart.getFile() instanceof FileWithUri_v0_3); - FileWithUri_v0_3 fileWithUri = (FileWithUri_v0_3) filePart.getFile(); + assertTrue(filePart.file() instanceof FileWithUri_v0_3); + FileWithUri_v0_3 fileWithUri = (FileWithUri_v0_3) filePart.file(); assertEquals("image/png", fileWithUri.mimeType()); assertEquals("photo.png", fileWithUri.name()); assertEquals("https://example.com/photo.png", fileWithUri.uri()); @@ -581,11 +581,11 @@ void testDeserializeTaskWithDataPartFromJson() throws JsonProcessingException_v0 Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); - assertEquals("task-123", task.getId()); - Part_v0_3 part = task.getArtifacts().get(0).parts().get(0); + assertEquals("task-123", task.id()); + Part_v0_3 part = task.artifacts().get(0).parts().get(0); assertTrue(part instanceof DataPart_v0_3); DataPart_v0_3 dataPart = (DataPart_v0_3) part; - assertNotNull(dataPart.getData()); + assertNotNull(dataPart.data()); } @Test @@ -623,12 +623,12 @@ void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException_v0_ Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); - assertEquals("task-123", task.getId()); - assertEquals(2, task.getHistory().size()); - assertEquals(Message_v0_3.Role.USER, task.getHistory().get(0).getRole()); - assertEquals(Message_v0_3.Role.AGENT, task.getHistory().get(1).getRole()); - assertTrue(task.getHistory().get(0).getParts().get(0) instanceof TextPart_v0_3); - assertEquals("User message", ((TextPart_v0_3) task.getHistory().get(0).getParts().get(0)).getText()); + assertEquals("task-123", task.id()); + assertEquals(2, task.history().size()); + assertEquals(Message_v0_3.Role.USER, task.history().get(0).role()); + assertEquals(Message_v0_3.Role.AGENT, task.history().get(1).role()); + assertTrue(task.history().get(0).parts().get(0) instanceof TextPart_v0_3); + assertEquals("User message", ((TextPart_v0_3) task.history().get(0).parts().get(0)).text()); } @Test @@ -647,10 +647,10 @@ void testDeserializeTaskWithTimestampFromJson() throws JsonProcessingException_v Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); - assertEquals("task-123", task.getId()); - assertEquals(TaskState_v0_3.WORKING, task.getStatus().state()); - assertNotNull(task.getStatus().timestamp()); - assertEquals("2023-10-01T12:00:00.234-05:00", task.getStatus().timestamp().toString()); + assertEquals("task-123", task.id()); + assertEquals(TaskState_v0_3.WORKING, task.status().state()); + assertNotNull(task.status().timestamp()); + assertEquals("2023-10-01T12:00:00.234-05:00", task.status().timestamp().toString()); } @Test @@ -672,9 +672,9 @@ void testDeserializeTaskWithMetadataFromJson() throws JsonProcessingException_v0 Task_v0_3 task = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); - assertEquals("task-123", task.getId()); - assertNotNull(task.getMetadata()); - assertEquals("value1", task.getMetadata().get("key1")); + assertEquals("task-123", task.id()); + assertNotNull(task.metadata()); + assertEquals("value1", task.metadata().get("key1")); } @Test @@ -703,7 +703,7 @@ void testTaskWithMixedPartTypes() throws JsonProcessingException_v0_3 { Task_v0_3 deserialized = JsonUtil_v0_3.fromJson(json, Task_v0_3.class); // Verify all part types are preserved - List> parts = deserialized.getArtifacts().get(0).parts(); + List> parts = deserialized.artifacts().get(0).parts(); assertEquals(4, parts.size()); assertTrue(parts.get(0) instanceof TextPart_v0_3); assertTrue(parts.get(1) instanceof FilePart_v0_3); diff --git a/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java b/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java index a9703878a..588c82a23 100644 --- a/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java +++ b/compat-0.3/transport/grpc/src/test/java/org/a2aproject/sdk/compat03/transport/grpc/handler/GrpcHandler_v0_3_Test.java @@ -58,11 +58,11 @@ public class GrpcHandler_v0_3_Test extends AbstractA2ARequestHandlerTest_v0_3 { // gRPC Message fixture (protobuf format) private static final Message GRPC_MESSAGE = Message.newBuilder() - .setTaskId(MINIMAL_TASK.getId()) - .setContextId(MINIMAL_TASK.getContextId()) - .setMessageId(MESSAGE.getMessageId()) + .setTaskId(MINIMAL_TASK.id()) + .setContextId(MINIMAL_TASK.contextId()) + .setMessageId(MESSAGE.messageId()) .setRole(Role.ROLE_AGENT) - .addContent(Part.newBuilder().setText(((TextPart_v0_3) MESSAGE.getParts().get(0)).getText()).build()) + .addContent(Part.newBuilder().setText(((TextPart_v0_3) MESSAGE.parts().get(0)).text()).build()) .build(); private final ServerCallContext callContext = new ServerCallContext( @@ -80,7 +80,7 @@ public void testOnGetTaskSuccess() throws Exception { taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); GetTaskRequest request = GetTaskRequest.newBuilder() - .setName("tasks/" + MINIMAL_TASK.getId()) + .setName("tasks/" + MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -91,8 +91,8 @@ public void testOnGetTaskSuccess() throws Exception { List result = streamRecorder.getValues(); Assertions.assertEquals(1, result.size()); Task task = result.get(0); - assertEquals(MINIMAL_TASK.getId(), task.getId()); - assertEquals(MINIMAL_TASK.getContextId(), task.getContextId()); + assertEquals(MINIMAL_TASK.id(), task.getId()); + assertEquals(MINIMAL_TASK.contextId(), task.getContextId()); } @Test @@ -100,7 +100,7 @@ public void testOnGetTaskNotFound() throws Exception { TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); GetTaskRequest request = GetTaskRequest.newBuilder() - .setName("tasks/" + MINIMAL_TASK.getId()) + .setName("tasks/" + MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -127,7 +127,7 @@ public void testOnCancelTaskSuccess() throws Exception { }; CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setName("tasks/" + MINIMAL_TASK.getId()) + .setName("tasks/" + MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -138,8 +138,8 @@ public void testOnCancelTaskSuccess() throws Exception { List result = streamRecorder.getValues(); Assertions.assertEquals(1, result.size()); Task task = result.get(0); - assertEquals(MINIMAL_TASK.getId(), task.getId()); - assertEquals(MINIMAL_TASK.getContextId(), task.getContextId()); + assertEquals(MINIMAL_TASK.id(), task.getId()); + assertEquals(MINIMAL_TASK.contextId(), task.getContextId()); assertEquals(TaskState.TASK_STATE_CANCELLED, task.getStatus().getState()); } @@ -156,7 +156,7 @@ public void testOnCancelTaskNotSupported() throws Exception { }; CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setName("tasks/" + MINIMAL_TASK.getId()) + .setName("tasks/" + MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -171,7 +171,7 @@ public void testOnCancelTaskNotFound() throws Exception { TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setName("tasks/" + MINIMAL_TASK.getId()) + .setName("tasks/" + MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -304,7 +304,7 @@ public void testStreamingNotSupportedErrorOnResubscribeToTask() throws Exception TestGrpcHandler handler = new TestGrpcHandler(nonStreamingCard, convert03To10Handler, internalExecutor); TaskSubscriptionRequest request = TaskSubscriptionRequest.newBuilder() - .setName("tasks/" + MINIMAL_TASK.getId()) + .setName("tasks/" + MINIMAL_TASK.id()) .build(); StreamRecorder streamRecorder = StreamRecorder.create(); @@ -341,7 +341,7 @@ public void testOnMessageStreamInternalError() throws Exception { public void testSetPushNotificationConfigSuccess() throws Exception { TestGrpcHandler handler = new TestGrpcHandler(CARD, convert03To10Handler, internalExecutor); - String NAME = "tasks/" + MINIMAL_TASK.getId() + "/pushNotificationConfigs/config456"; + String NAME = "tasks/" + MINIMAL_TASK.id() + "/pushNotificationConfigs/config456"; StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); @@ -364,7 +364,7 @@ public void testGetPushNotificationConfigSuccess() throws Exception { agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); }; - String NAME = "tasks/" + MINIMAL_TASK.getId() + "/pushNotificationConfigs/config456"; + String NAME = "tasks/" + MINIMAL_TASK.id() + "/pushNotificationConfigs/config456"; // First set the task push notification config StreamRecorder streamRecorder = @@ -389,7 +389,7 @@ public void testPushNotificationsNotSupportedError() throws Exception { AgentCard_v0_3 card = createAgentCard(true, false, false); TestGrpcHandler handler = new TestGrpcHandler(card, convert03To10Handler, internalExecutor); - String NAME = "tasks/" + MINIMAL_TASK.getId() + "/pushNotificationConfigs/" + MINIMAL_TASK.getId(); + String NAME = "tasks/" + MINIMAL_TASK.id() + "/pushNotificationConfigs/" + MINIMAL_TASK.id(); StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, NAME); @@ -406,7 +406,7 @@ public void testDeletePushNotificationConfig() throws Exception { // Save task to v1.0 backend taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); - String NAME = "tasks/" + MINIMAL_TASK.getId() + "/pushNotificationConfigs/" + MINIMAL_TASK.getId(); + String NAME = "tasks/" + MINIMAL_TASK.id() + "/pushNotificationConfigs/" + MINIMAL_TASK.id(); org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest request = org.a2aproject.sdk.compat03.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder() .setName(NAME) @@ -428,7 +428,7 @@ public void testListPushNotificationConfig() throws Exception { // Save task to v1.0 backend taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); - String PARENT = "tasks/" + MINIMAL_TASK.getId(); + String PARENT = "tasks/" + MINIMAL_TASK.id(); org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest request = org.a2aproject.sdk.compat03.grpc.ListTaskPushNotificationConfigRequest.newBuilder() .setParent(PARENT) diff --git a/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java index 93f01d2ea..61c763873 100644 --- a/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java +++ b/compat-0.3/transport/jsonrpc/src/test/java/org/a2aproject/sdk/compat03/transport/jsonrpc/handler/JSONRPCHandler_v0_3_Test.java @@ -99,7 +99,7 @@ public void testOnGetTaskSuccess() throws Exception { // Save v0.3 task by converting to v1.0 for taskStore taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); - GetTaskRequest_v0_3 request = new GetTaskRequest_v0_3("1", new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + GetTaskRequest_v0_3 request = new GetTaskRequest_v0_3("1", new TaskQueryParams_v0_3(MINIMAL_TASK.id())); GetTaskResponse_v0_3 response = handler.onGetTask(request, callContext); assertEquals(request.getId(), response.getId()); @@ -107,15 +107,15 @@ public void testOnGetTaskSuccess() throws Exception { // Response should contain v0.3 task (converted back from v1.0) Task_v0_3 result = response.getResult(); - assertEquals(MINIMAL_TASK.getId(), result.getId()); - assertEquals(MINIMAL_TASK.getContextId(), result.getContextId()); + assertEquals(MINIMAL_TASK.id(), result.id()); + assertEquals(MINIMAL_TASK.contextId(), result.contextId()); } @Test public void testOnGetTaskNotFound() throws Exception { JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); - GetTaskRequest_v0_3 request = new GetTaskRequest_v0_3("1", new TaskQueryParams_v0_3(MINIMAL_TASK.getId())); + GetTaskRequest_v0_3 request = new GetTaskRequest_v0_3("1", new TaskQueryParams_v0_3(MINIMAL_TASK.id())); GetTaskResponse_v0_3 response = handler.onGetTask(request, callContext); assertEquals(request.getId(), response.getId()); @@ -140,7 +140,7 @@ public void testOnCancelTaskSuccess() throws Exception { emitter.cancel(); }; - CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("111", new TaskIdParams_v0_3(MINIMAL_TASK.getId())); + CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("111", new TaskIdParams_v0_3(MINIMAL_TASK.id())); CancelTaskResponse_v0_3 response = handler.onCancelTask(request, callContext); assertNull(response.getError()); @@ -148,9 +148,9 @@ public void testOnCancelTaskSuccess() throws Exception { // Verify task was canceled Task_v0_3 task = response.getResult(); - assertEquals(MINIMAL_TASK.getId(), task.getId()); - assertEquals(MINIMAL_TASK.getContextId(), task.getContextId()); - assertEquals(TaskState_v0_3.CANCELED, task.getStatus().state()); + assertEquals(MINIMAL_TASK.id(), task.id()); + assertEquals(MINIMAL_TASK.contextId(), task.contextId()); + assertEquals(TaskState_v0_3.CANCELED, task.status().state()); } @Test @@ -165,7 +165,7 @@ public void testOnCancelTaskNotSupported() { throw new org.a2aproject.sdk.spec.UnsupportedOperationError(); }; - CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.getId())); + CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.id())); CancelTaskResponse_v0_3 response = handler.onCancelTask(request, callContext); assertEquals(request.getId(), response.getId()); @@ -177,7 +177,7 @@ public void testOnCancelTaskNotSupported() { public void testOnCancelTaskNotFound() { JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(CARD, internalExecutor, convert03To10Handler); - CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.getId())); + CancelTaskRequest_v0_3 request = new CancelTaskRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.id())); CancelTaskResponse_v0_3 response = handler.onCancelTask(request, callContext); assertEquals(request.getId(), response.getId()); @@ -204,8 +204,8 @@ public void testOnMessageSendSuccess() { }; Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .build(); SendMessageRequest_v0_3 request = new SendMessageRequest_v0_3("1", new MessageSendParams_v0_3(message, null, null)); @@ -215,7 +215,7 @@ public void testOnMessageSendSuccess() { // Response should contain the message (converted back from v1.0) EventKind_v0_3 result = response.getResult(); if (result instanceof Message_v0_3) { - assertEquals(message.getMessageId(), ((Message_v0_3) result).getMessageId()); + assertEquals(message.messageId(), ((Message_v0_3) result).messageId()); } } @@ -233,8 +233,8 @@ public void testOnMessageSendWithExistingTaskSuccess() { }; Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .build(); SendMessageRequest_v0_3 request = new SendMessageRequest_v0_3("1", new MessageSendParams_v0_3(message, null, null)); @@ -243,7 +243,7 @@ public void testOnMessageSendWithExistingTaskSuccess() { assertNull(response.getError()); EventKind_v0_3 result = response.getResult(); if (result instanceof Message_v0_3) { - assertEquals(message.getMessageId(), ((Message_v0_3) result).getMessageId()); + assertEquals(message.messageId(), ((Message_v0_3) result).messageId()); } } @@ -260,8 +260,8 @@ public void testOnMessageSendError() { }; Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .build(); SendMessageRequest_v0_3 request = new SendMessageRequest_v0_3("1", new MessageSendParams_v0_3(message, null, null)); @@ -289,8 +289,8 @@ public void testOnMessageSendStreamSuccess() throws InterruptedException { }; Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .build(); SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( @@ -344,7 +344,7 @@ public void onComplete() { // Verify the event is the message (converted back from v1.0) Message_v0_3 receivedMessage = assertInstanceOf(Message_v0_3.class, results.get(0), "Event should be a Message"); - assertEquals(message.getMessageId(), receivedMessage.getMessageId()); + assertEquals(message.messageId(), receivedMessage.messageId()); } @Test @@ -360,8 +360,8 @@ public void testOnMessageSendStreamMultipleEventsSuccess() throws InterruptedExc .build(); TaskArtifactUpdateEvent_v0_3 v03ArtifactEvent = new TaskArtifactUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .artifact(new Artifact_v0_3.Builder() .artifactId("artifact-1") .parts(new TextPart_v0_3("Generated artifact content")) @@ -369,8 +369,8 @@ public void testOnMessageSendStreamMultipleEventsSuccess() throws InterruptedExc .build(); TaskStatusUpdateEvent_v0_3 v03StatusEvent = new TaskStatusUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) .isFinal(true) // Must be true for COMPLETED state in v1.0 .build(); @@ -385,8 +385,8 @@ public void testOnMessageSendStreamMultipleEventsSuccess() throws InterruptedExc }; Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .build(); SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( @@ -440,21 +440,21 @@ public void onComplete() { // Verify the first event is the task Task_v0_3 receivedTask = assertInstanceOf(Task_v0_3.class, results.get(0), "First event should be a Task"); - assertEquals(MINIMAL_TASK.getId(), receivedTask.getId()); - assertEquals(MINIMAL_TASK.getContextId(), receivedTask.getContextId()); - assertEquals(TaskState_v0_3.WORKING, receivedTask.getStatus().state()); + assertEquals(MINIMAL_TASK.id(), receivedTask.id()); + assertEquals(MINIMAL_TASK.contextId(), receivedTask.contextId()); + assertEquals(TaskState_v0_3.WORKING, receivedTask.status().state()); // Verify the second event is the artifact update TaskArtifactUpdateEvent_v0_3 receivedArtifact = assertInstanceOf(TaskArtifactUpdateEvent_v0_3.class, results.get(1), "Second event should be a TaskArtifactUpdateEvent"); - assertEquals(MINIMAL_TASK.getId(), receivedArtifact.getTaskId()); - assertEquals("artifact-1", receivedArtifact.getArtifact().artifactId()); + assertEquals(MINIMAL_TASK.id(), receivedArtifact.taskId()); + assertEquals("artifact-1", receivedArtifact.artifact().artifactId()); // Verify the third event is the status update TaskStatusUpdateEvent_v0_3 receivedStatus = assertInstanceOf(TaskStatusUpdateEvent_v0_3.class, results.get(2), "Third event should be a TaskStatusUpdateEvent"); - assertEquals(MINIMAL_TASK.getId(), receivedStatus.getTaskId()); - assertEquals(TaskState_v0_3.COMPLETED, receivedStatus.getStatus().state()); + assertEquals(MINIMAL_TASK.id(), receivedStatus.taskId()); + assertEquals(TaskState_v0_3.COMPLETED, receivedStatus.status().state()); } @Test @@ -474,8 +474,8 @@ public void testOnMessageSendStreamExistingTaskSuccess() throws InterruptedExcep taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(v03Task), false); Message_v0_3 message = new Message_v0_3.Builder(MESSAGE) - .taskId(v03Task.getId()) - .contextId(v03Task.getContextId()) + .taskId(v03Task.id()) + .contextId(v03Task.contextId()) .build(); SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3( @@ -531,8 +531,8 @@ public void onComplete() { // Verify the task was received assertEquals(1, results.size(), "Should have received exactly 1 event"); Task_v0_3 receivedTask = assertInstanceOf(Task_v0_3.class, results.get(0), "Event should be a Task"); - assertEquals(v03Task.getId(), receivedTask.getId()); - assertEquals(v03Task.getContextId(), receivedTask.getContextId()); + assertEquals(v03Task.id(), receivedTask.id()); + assertEquals(v03Task.contextId(), receivedTask.contextId()); // Note: v1.0 backend manages task history differently than v0.3 // The key assertion is that we received a Task event for the existing task } @@ -715,7 +715,7 @@ public void testStreamingNotSupportedErrorOnResubscribeToTask() { JSONRPCHandler_v0_3 handler = new JSONRPCHandler_v0_3(nonStreamingCard, internalExecutor, convert03To10Handler); - TaskResubscriptionRequest_v0_3 request = new TaskResubscriptionRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.getId())); + TaskResubscriptionRequest_v0_3 request = new TaskResubscriptionRequest_v0_3("1", new TaskIdParams_v0_3(MINIMAL_TASK.id())); Flow.Publisher response = handler.onResubscribeToTask(request, callContext); List results = new ArrayList<>(); @@ -771,7 +771,7 @@ public void testSetPushNotificationConfigSuccess() { TaskPushNotificationConfig_v0_3 taskPushConfig = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder() .url("http://example.com") .build()); @@ -783,10 +783,10 @@ public void testSetPushNotificationConfigSuccess() { TaskPushNotificationConfig_v0_3 taskPushConfigResult = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder() .url("http://example.com") - .id(MINIMAL_TASK.getId()) + .id(MINIMAL_TASK.id()) .build()); assertEquals(taskPushConfigResult, response.getResult()); } @@ -805,7 +805,7 @@ public void testGetPushNotificationConfigSuccess() { TaskPushNotificationConfig_v0_3 taskPushConfig = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder() .url("http://example.com") .build()); @@ -814,11 +814,11 @@ public void testGetPushNotificationConfigSuccess() { handler.setPushNotificationConfig(request, callContext); GetTaskPushNotificationConfigRequest_v0_3 getRequest = - new GetTaskPushNotificationConfigRequest_v0_3("111", new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + new GetTaskPushNotificationConfigRequest_v0_3("111", new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id())); GetTaskPushNotificationConfigResponse_v0_3 getResponse = handler.getPushNotificationConfig(getRequest, callContext); - TaskPushNotificationConfig_v0_3 expectedConfig = new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.getId(), - new PushNotificationConfig_v0_3.Builder().id(MINIMAL_TASK.getId()).url("http://example.com").build()); + TaskPushNotificationConfig_v0_3 expectedConfig = new TaskPushNotificationConfig_v0_3(MINIMAL_TASK.id(), + new PushNotificationConfig_v0_3.Builder().id(MINIMAL_TASK.id()).url("http://example.com").build()); assertEquals(expectedConfig, getResponse.getResult()); } @@ -836,16 +836,16 @@ public void testDeletePushNotificationConfig() { TaskPushNotificationConfig_v0_3 taskPushConfig = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder() .url("http://example.com") - .id(MINIMAL_TASK.getId()) + .id(MINIMAL_TASK.id()) .build()); SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); DeleteTaskPushNotificationConfigRequest_v0_3 deleteRequest = - new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), MINIMAL_TASK.getId())); + new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id(), MINIMAL_TASK.id())); DeleteTaskPushNotificationConfigResponse_v0_3 deleteResponse = handler.deletePushNotificationConfig(deleteRequest, callContext); @@ -873,7 +873,7 @@ public void testOnGetPushNotificationNoPushNotifierConfig() { taskStore.save(v10Task, false); GetTaskPushNotificationConfigRequest_v0_3 request = - new GetTaskPushNotificationConfigRequest_v0_3("id", new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId())); + new GetTaskPushNotificationConfigRequest_v0_3("id", new GetTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id())); GetTaskPushNotificationConfigResponse_v0_3 response = handler.getPushNotificationConfig(request, callContext); assertNotNull(response.getError()); @@ -901,7 +901,7 @@ public void testOnSetPushNotificationNoPushNotifierConfig() { TaskPushNotificationConfig_v0_3 config = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder() .url("http://example.com") .build()); @@ -930,16 +930,16 @@ public void testDeletePushNotificationConfigNotSupported() { TaskPushNotificationConfig_v0_3 taskPushConfig = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder() .url("http://example.com") - .id(MINIMAL_TASK.getId()) + .id(MINIMAL_TASK.id()) .build()); SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); DeleteTaskPushNotificationConfigRequest_v0_3 deleteRequest = - new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), MINIMAL_TASK.getId())); + new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id(), MINIMAL_TASK.id())); DeleteTaskPushNotificationConfigResponse_v0_3 deleteResponse = handler.deletePushNotificationConfig(deleteRequest, callContext); @@ -971,16 +971,16 @@ public void testDeletePushNotificationConfigNoPushConfigStore() { TaskPushNotificationConfig_v0_3 taskPushConfig = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder() .url("http://example.com") - .id(MINIMAL_TASK.getId()) + .id(MINIMAL_TASK.id()) .build()); SetTaskPushNotificationConfigRequest_v0_3 request = new SetTaskPushNotificationConfigRequest_v0_3("1", taskPushConfig); handler.setPushNotificationConfig(request, callContext); DeleteTaskPushNotificationConfigRequest_v0_3 deleteRequest = - new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.getId(), MINIMAL_TASK.getId())); + new DeleteTaskPushNotificationConfigRequest_v0_3("111", new DeleteTaskPushNotificationConfigParams_v0_3(MINIMAL_TASK.id(), MINIMAL_TASK.id())); DeleteTaskPushNotificationConfigResponse_v0_3 deleteResponse = handler.deletePushNotificationConfig(deleteRequest, callContext); @@ -1009,16 +1009,16 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex List events = List.of( MINIMAL_TASK, new TaskArtifactUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .artifact(new Artifact_v0_3.Builder() .artifactId("11") .parts(new TextPart_v0_3("text")) .build()) .build(), new TaskStatusUpdateEvent_v0_3.Builder() - .taskId(MINIMAL_TASK.getId()) - .contextId(MINIMAL_TASK.getContextId()) + .taskId(MINIMAL_TASK.id()) + .contextId(MINIMAL_TASK.contextId()) .status(new TaskStatus_v0_3(TaskState_v0_3.COMPLETED)) .isFinal(true) .build()); @@ -1038,7 +1038,7 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex // Set push notification config TaskPushNotificationConfig_v0_3 config = new TaskPushNotificationConfig_v0_3( - MINIMAL_TASK.getId(), + MINIMAL_TASK.id(), new PushNotificationConfig_v0_3.Builder().url("http://example.com").build()); SetTaskPushNotificationConfigRequest_v0_3 stpnRequest = new SetTaskPushNotificationConfigRequest_v0_3("1", config); SetTaskPushNotificationConfigResponse_v0_3 stpnResponse = handler.setPushNotificationConfig(stpnRequest, callContext); @@ -1046,7 +1046,7 @@ public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Ex // Send streaming message Message_v0_3 msg = new Message_v0_3.Builder(MESSAGE) - .taskId(MINIMAL_TASK.getId()) + .taskId(MINIMAL_TASK.id()) .build(); SendStreamingMessageRequest_v0_3 request = new SendStreamingMessageRequest_v0_3("1", new MessageSendParams_v0_3(msg, null, null)); Flow.Publisher response = handler.onMessageSendStream(request, callContext); @@ -1115,8 +1115,8 @@ public void onComplete() { org.a2aproject.sdk.spec.StreamingEventKind pushEvent0 = httpClient.events.get(0); assertTrue(pushEvent0 instanceof org.a2aproject.sdk.spec.Task); org.a2aproject.sdk.spec.Task v10PushedTask0 = (org.a2aproject.sdk.spec.Task) pushEvent0; - assertEquals(MINIMAL_TASK.getId(), v10PushedTask0.id()); - assertEquals(MINIMAL_TASK.getContextId(), v10PushedTask0.contextId()); + assertEquals(MINIMAL_TASK.id(), v10PushedTask0.id()); + assertEquals(MINIMAL_TASK.contextId(), v10PushedTask0.contextId()); // v0.3 SUBMITTED maps to v1.0 TASK_STATE_SUBMITTED assertEquals(org.a2aproject.sdk.spec.TaskState.TASK_STATE_SUBMITTED, v10PushedTask0.status().state()); assertTrue(v10PushedTask0.artifacts() == null || v10PushedTask0.artifacts().isEmpty()); @@ -1125,8 +1125,8 @@ public void onComplete() { org.a2aproject.sdk.spec.StreamingEventKind pushEvent1 = httpClient.events.get(1); assertTrue(pushEvent1 instanceof org.a2aproject.sdk.spec.TaskArtifactUpdateEvent); org.a2aproject.sdk.spec.TaskArtifactUpdateEvent v10ArtifactUpdate = (org.a2aproject.sdk.spec.TaskArtifactUpdateEvent) pushEvent1; - assertEquals(MINIMAL_TASK.getId(), v10ArtifactUpdate.taskId()); - assertEquals(MINIMAL_TASK.getContextId(), v10ArtifactUpdate.contextId()); + assertEquals(MINIMAL_TASK.id(), v10ArtifactUpdate.taskId()); + assertEquals(MINIMAL_TASK.contextId(), v10ArtifactUpdate.contextId()); assertNotNull(v10ArtifactUpdate.artifact()); assertEquals(1, v10ArtifactUpdate.artifact().parts().size()); assertEquals("text", ((org.a2aproject.sdk.spec.TextPart) v10ArtifactUpdate.artifact().parts().get(0)).text()); @@ -1135,8 +1135,8 @@ public void onComplete() { org.a2aproject.sdk.spec.StreamingEventKind pushEvent2 = httpClient.events.get(2); assertTrue(pushEvent2 instanceof org.a2aproject.sdk.spec.TaskStatusUpdateEvent); org.a2aproject.sdk.spec.TaskStatusUpdateEvent v10StatusUpdate = (org.a2aproject.sdk.spec.TaskStatusUpdateEvent) pushEvent2; - assertEquals(MINIMAL_TASK.getId(), v10StatusUpdate.taskId()); - assertEquals(MINIMAL_TASK.getContextId(), v10StatusUpdate.contextId()); + assertEquals(MINIMAL_TASK.id(), v10StatusUpdate.taskId()); + assertEquals(MINIMAL_TASK.contextId(), v10StatusUpdate.contextId()); assertEquals(org.a2aproject.sdk.spec.TaskState.TASK_STATE_COMPLETED, v10StatusUpdate.status().state()); } finally { // Reset push notification executor to async diff --git a/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java b/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java index 2b195a47f..2008d8d2e 100644 --- a/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java +++ b/compat-0.3/transport/rest/src/test/java/org/a2aproject/sdk/compat03/transport/rest/handler/RestHandler_v0_3_Test.java @@ -46,18 +46,18 @@ public void testGetTaskSuccess() { // Save v0.3 task by converting to v1.0 taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); - RestHandler_v0_3.HTTPRestResponse response = handler.getTask(MINIMAL_TASK.getId(), 0, callContext); + RestHandler_v0_3.HTTPRestResponse response = handler.getTask(MINIMAL_TASK.id(), 0, callContext); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.getId())); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); // Test with different version parameter - response = handler.getTask(MINIMAL_TASK.getId(), 2, callContext); + response = handler.getTask(MINIMAL_TASK.id(), 2, callContext); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.getId())); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @Test @@ -176,11 +176,11 @@ public void testCancelTaskSuccess() { emitter.cancel(); }; - RestHandler_v0_3.HTTPRestResponse response = handler.cancelTask(MINIMAL_TASK.getId(), callContext); + RestHandler_v0_3.HTTPRestResponse response = handler.cancelTask(MINIMAL_TASK.id(), callContext); Assertions.assertEquals(200, response.getStatusCode()); Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.getId())); + Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); } @Test @@ -291,9 +291,9 @@ public void testPushNotificationConfigSuccess() { } } } - }""".formatted(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); + }""".formatted(MINIMAL_TASK.id(), MINIMAL_TASK.id()); - RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), requestBody, callContext); + RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.id(), requestBody, callContext); assertEquals(201, response.getStatusCode(), response.toString()); assertEquals("application/json", response.getContentType()); @@ -312,9 +312,9 @@ public void testPushNotificationConfigNotSupported() { "url": "http://example.com" } } - """.formatted(MINIMAL_TASK.getId()); + """.formatted(MINIMAL_TASK.id()); - RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), requestBody, callContext); + RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.id(), requestBody, callContext); assertEquals(501, response.getStatusCode()); assertTrue(response.getBody().contains("PushNotificationNotSupportedError")); @@ -340,13 +340,13 @@ public void testGetPushNotificationConfig() { } } } - }""".formatted(MINIMAL_TASK.getId(), MINIMAL_TASK.getId()); - RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), createRequestBody, callContext); + }""".formatted(MINIMAL_TASK.id(), MINIMAL_TASK.id()); + RestHandler_v0_3.HTTPRestResponse response = handler.setTaskPushNotificationConfiguration(MINIMAL_TASK.id(), createRequestBody, callContext); assertEquals(201, response.getStatusCode(), response.toString()); assertEquals("application/json", response.getContentType()); // Now get it (using taskId as configId since that's the default) - response = handler.getTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), MINIMAL_TASK.getId(), callContext); + response = handler.getTaskPushNotificationConfiguration(MINIMAL_TASK.id(), MINIMAL_TASK.id(), callContext); assertEquals(200, response.getStatusCode(), response.toString()); assertEquals("application/json", response.getContentType()); } @@ -358,7 +358,7 @@ public void testDeletePushNotificationConfig() { // Save task to v1.0 backend taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); - RestHandler_v0_3.HTTPRestResponse response = handler.deleteTaskPushNotificationConfiguration(MINIMAL_TASK.getId(), MINIMAL_TASK.getId(), callContext); + RestHandler_v0_3.HTTPRestResponse response = handler.deleteTaskPushNotificationConfiguration(MINIMAL_TASK.id(), MINIMAL_TASK.id(), callContext); assertEquals(204, response.getStatusCode()); } @@ -369,7 +369,7 @@ public void testListPushNotificationConfigs() { // Save task to v1.0 backend taskStore.save(TaskMapper_v0_3.INSTANCE.toV10(MINIMAL_TASK), false); - RestHandler_v0_3.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(MINIMAL_TASK.getId(), callContext); + RestHandler_v0_3.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(MINIMAL_TASK.id(), callContext); assertEquals(200, response.getStatusCode()); assertEquals("application/json", response.getContentType()); diff --git a/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java index 81462ee01..dafd299a9 100644 --- a/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java +++ b/tests/multiversion/rest/src/test/java/org/a2aproject/sdk/tests/multiversion/rest/MultiVersion_v0_3_RestWithAuthTest.java @@ -50,10 +50,10 @@ public void testBasicAuthWorksViaHttp() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); givenAuthenticated() - .get("/v1/tasks/" + MINIMAL_TASK.getId()) + .get("/v1/tasks/" + MINIMAL_TASK.id()) .then() .statusCode(200); - deleteTaskInTaskStore(MINIMAL_TASK.getId()); + deleteTaskInTaskStore(MINIMAL_TASK.id()); } } From 7d2da1a4b4f47401abdd4de567612e6c8e32966d Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Wed, 27 May 2026 11:44:25 +0200 Subject: [PATCH 178/192] Fixing the constructors Signed-off-by: Emmanuel Hugonnet --- .../sdk/compat03/spec/Artifact_v0_3.java | 18 +++++++-------- .../sdk/compat03/spec/DataPart_v0_3.java | 8 +++---- .../sdk/compat03/spec/FilePart_v0_3.java | 10 ++++---- .../sdk/compat03/spec/Message_v0_3.java | 23 +++++++++++-------- .../spec/TaskArtifactUpdateEvent_v0_3.java | 17 +++++++++----- .../spec/TaskStatusUpdateEvent_v0_3.java | 16 ++++++++----- .../sdk/compat03/spec/Task_v0_3.java | 17 ++++++++------ .../sdk/compat03/spec/TextPart_v0_3.java | 10 ++++---- 8 files changed, 68 insertions(+), 51 deletions(-) diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Artifact_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Artifact_v0_3.java index a98a10074..e10c267c1 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Artifact_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Artifact_v0_3.java @@ -31,12 +31,12 @@ public Builder(){ } public Builder(Artifact_v0_3 existingArtifact) { - artifactId = existingArtifact.artifactId; - name = existingArtifact.name; - description = existingArtifact.description; - parts = existingArtifact.parts; - metadata = existingArtifact.metadata; - extensions = existingArtifact.extensions; + artifactId = existingArtifact.artifactId(); + name = existingArtifact.name(); + description = existingArtifact.description(); + parts = existingArtifact.parts(); + metadata = existingArtifact.metadata(); + extensions = existingArtifact.extensions(); } public Builder artifactId(String artifactId) { @@ -56,7 +56,7 @@ public Builder description(String description) { } public Builder parts(List> parts) { - this.parts = parts; + this.parts = List.copyOf(parts); return this; } @@ -66,12 +66,12 @@ public Builder parts(Part_v0_3... parts) { } public Builder metadata(Map metadata) { - this.metadata = metadata; + this.metadata = Map.copyOf(metadata); return this; } public Builder extensions(List extensions) { - this.extensions = (extensions == null) ? null : List.copyOf(extensions); + this.extensions = List.copyOf(extensions); return this; } diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java index de6ba65aa..f18d784a3 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/DataPart_v0_3.java @@ -12,14 +12,14 @@ public record DataPart_v0_3(Map data, @Nullable Map data, @Nullable Map metadata, Kind kind) { Assert.checkNotNullParam("data", data); - if (kind == null) { - kind = Kind.DATA; - } if (kind != Kind.DATA) { throw new IllegalArgumentException("Invalid DataPart kind: " + kind); } + this.data = Map.copyOf(data); + this.metadata = metadata == null ? Map.of() : Map.copyOf(metadata); + this.kind = kind; } public DataPart_v0_3(Map data) { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java index b957d2063..d3c89abdf 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/FilePart_v0_3.java @@ -9,18 +9,18 @@ * Represents a file segment within a message or artifact. The file content can be * provided either directly as bytes or as a URI. */ -public record FilePart_v0_3(FileContent_v0_3 file, @Nullable Map metadata, Kind kind) implements Part_v0_3 { +public record FilePart_v0_3(FileContent_v0_3 file, Map metadata, Kind kind) implements Part_v0_3 { public static final String FILE = "file"; - public FilePart_v0_3 { + public FilePart_v0_3 (FileContent_v0_3 file, @Nullable Map metadata, Kind kind){ Assert.checkNotNullParam("file", file); - if (kind == null) { - kind = Kind.FILE; - } if (kind != Kind.FILE) { throw new IllegalArgumentException("Invalid FilePart kind: " + kind); } + this.file = file; + this.metadata = metadata == null ? Map.of() : Map.copyOf(metadata); + this.kind = kind; } public FilePart_v0_3(FileContent_v0_3 file) { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java index 15f4d49f2..860437a60 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java @@ -1,5 +1,6 @@ package org.a2aproject.sdk.compat03.spec; + import java.util.List; import java.util.Map; import java.util.UUID; @@ -24,22 +25,26 @@ public record Message_v0_3( public static final String KIND = "message"; - public Message_v0_3 { + public Message_v0_3(Role role, List> parts, String messageId, @Nullable String contextId, + @Nullable String taskId, @Nullable List referenceTaskIds, + @Nullable Map metadata, @Nullable List extensions, String kind) { Assert.checkNotNullParam("role", role); Assert.checkNotNullParam("parts", parts); - parts = List.copyOf(parts); + this.role = role; if (parts.isEmpty()) { throw new IllegalArgumentException("Parts cannot be empty"); } - if (messageId == null) { - messageId = UUID.randomUUID().toString(); - } - if (kind == null) { - kind = KIND; - } - if (!kind.equals(KIND)) { + this.parts = List.copyOf(parts); + this.messageId = messageId == null ? UUID.randomUUID().toString() : messageId; + this.kind = kind != null ? kind : KIND; + if (!this.kind.equals(KIND)) { throw new IllegalArgumentException("Invalid Message"); } + this.contextId = contextId; + this.taskId = taskId; + this.referenceTaskIds = referenceTaskIds != null ? List.copyOf(referenceTaskIds) : null; + this.metadata = metadata != null ? Map.copyOf(metadata) : null; + this.extensions = extensions != null ? List.copyOf(extensions) : null; } public Message_v0_3(Role role, List> parts, String messageId, @Nullable String contextId, diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java index e76de3bce..64c8dc0c5 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskArtifactUpdateEvent_v0_3.java @@ -15,22 +15,27 @@ public record TaskArtifactUpdateEvent_v0_3( @Nullable Boolean lastChunk, Artifact_v0_3 artifact, String contextId, - @Nullable Map metadata, + Map metadata, String kind ) implements EventKind_v0_3, StreamingEventKind_v0_3, UpdateEvent_v0_3 { public static final String KIND = "artifact-update"; - public TaskArtifactUpdateEvent_v0_3 { + public TaskArtifactUpdateEvent_v0_3 (String taskId, @Nullable Boolean append, @Nullable Boolean lastChunk, + Artifact_v0_3 artifact, String contextId,@Nullable Map metadata, String kind){ Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("artifact", artifact); Assert.checkNotNullParam("contextId", contextId); - if (kind == null) { - kind = KIND; - } - if (!kind.equals(KIND)) { + this.kind = kind != null ? kind : KIND; + if (!KIND.equals(this.kind)) { throw new IllegalArgumentException("Invalid TaskArtifactUpdateEvent"); } + this.taskId = taskId; + this.append = append; + this.lastChunk = lastChunk; + this.artifact = artifact; + this.contextId = contextId; + this.metadata = metadata != null ? Map.copyOf(metadata) : null; } public TaskArtifactUpdateEvent_v0_3(String taskId, Artifact_v0_3 artifact, String contextId, diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java index 8510efbe9..d527815b3 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TaskStatusUpdateEvent_v0_3.java @@ -15,22 +15,26 @@ public record TaskStatusUpdateEvent_v0_3( TaskStatus_v0_3 status, String contextId, @SerializedName("final") boolean isFinal, - @Nullable Map metadata, + Map metadata, String kind ) implements EventKind_v0_3, StreamingEventKind_v0_3, UpdateEvent_v0_3 { public static final String KIND = "status-update"; - public TaskStatusUpdateEvent_v0_3 { + public TaskStatusUpdateEvent_v0_3 (String taskId, TaskStatus_v0_3 status, String contextId, boolean isFinal, + @Nullable Map metadata, String kind) { Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("status", status); Assert.checkNotNullParam("contextId", contextId); - if (kind == null) { - kind = KIND; - } - if (!kind.equals(KIND)) { + this.kind = kind != null ? kind : KIND; + if (!KIND.equals(this.kind)) { throw new IllegalArgumentException("Invalid TaskStatusUpdateEvent"); } + this.taskId = taskId; + this.status = status; + this.contextId = contextId; + this.isFinal = isFinal; + this.metadata = metadata != null ? Map.copyOf(metadata) : null; } public TaskStatusUpdateEvent_v0_3(String taskId, TaskStatus_v0_3 status, String contextId, boolean isFinal, diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java index 52fa1dc35..3b0a28cdc 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Task_v0_3.java @@ -21,18 +21,21 @@ public record Task_v0_3( public static final String KIND = "task"; - public Task_v0_3 { + public Task_v0_3 (String id, String contextId, TaskStatus_v0_3 status, List artifacts, + List history, @Nullable Map metadata, String kind){ Assert.checkNotNullParam("id", id); Assert.checkNotNullParam("contextId", contextId); Assert.checkNotNullParam("status", status); - if (kind == null) { - kind = KIND; - } - if (!kind.equals(KIND)) { + this.kind = kind != null ? kind : KIND; + if (!KIND.equals(this.kind)) { throw new IllegalArgumentException("Invalid Task"); } - artifacts = artifacts != null ? List.copyOf(artifacts) : List.of(); - history = history != null ? List.copyOf(history) : List.of(); + this.id = id; + this.contextId = contextId; + this.status = status; + this.artifacts = artifacts != null ? List.copyOf(artifacts) : List.of(); + this.history = history != null ? List.copyOf(history) : List.of(); + this.metadata = metadata != null ? Map.copyOf(metadata) : null; } public Task_v0_3(String id, String contextId, TaskStatus_v0_3 status, List artifacts, diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java index 1aa13cbb9..70f8563c7 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/TextPart_v0_3.java @@ -8,18 +8,18 @@ /** * Represents a text segment within a message or artifact. */ -public record TextPart_v0_3(String text, @Nullable Map metadata, Kind kind) implements Part_v0_3 { +public record TextPart_v0_3(String text, Map metadata, Kind kind) implements Part_v0_3 { public static final String TEXT = "text"; - public TextPart_v0_3 { + public TextPart_v0_3 (String text, @Nullable Map metadata, Kind kind){ Assert.checkNotNullParam("text", text); - if (kind == null) { - kind = Kind.TEXT; - } if (kind != Kind.TEXT) { throw new IllegalArgumentException("Invalid TextPart kind: " + kind); } + this.text = text; + this.metadata = metadata == null ? Map.of() : Map.copyOf(metadata); + this.kind = kind; } public TextPart_v0_3(String text) { From 2ddc972d1557e983eb42667b2f85af60fe55830d Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Wed, 27 May 2026 11:32:39 +0100 Subject: [PATCH 179/192] Fix more constructors --- .../sdk/compat03/spec/APIKeySecurityScheme_v0_3.java | 11 ++++++----- .../compat03/spec/HTTPAuthSecurityScheme_v0_3.java | 11 ++++++----- .../compat03/spec/MutualTLSSecurityScheme_v0_3.java | 9 ++++----- .../sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java | 11 ++++++----- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java index 8e425540d..7e4e818b8 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/APIKeySecurityScheme_v0_3.java @@ -44,15 +44,16 @@ public static Location fromString(String location) { } } - public APIKeySecurityScheme_v0_3 { + public APIKeySecurityScheme_v0_3(String in, String name, @Nullable String description, @Nullable String type) { Assert.checkNotNullParam("in", in); Assert.checkNotNullParam("name", name); - if (type == null) { - type = TYPE; - } - if (!type.equals(TYPE)) { + if (type != null && !type.equals(TYPE)) { throw new IllegalArgumentException("Invalid type for APIKeySecurityScheme"); } + this.in = in; + this.name = name; + this.description = description; + this.type = TYPE; } public APIKeySecurityScheme_v0_3(String in, String name, @Nullable String description) { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java index 56d46625a..0fa66d74a 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/HTTPAuthSecurityScheme_v0_3.java @@ -15,14 +15,15 @@ public record HTTPAuthSecurityScheme_v0_3( public static final String TYPE = "http"; - public HTTPAuthSecurityScheme_v0_3 { + public HTTPAuthSecurityScheme_v0_3(@Nullable String bearerFormat, String scheme, @Nullable String description, @Nullable String type) { Assert.checkNotNullParam("scheme", scheme); - if (type == null) { - type = TYPE; - } - if (!TYPE.equals(type)) { + if (type != null && !TYPE.equals(type)) { throw new IllegalArgumentException("Invalid type for HTTPAuthSecurityScheme"); } + this.bearerFormat = bearerFormat; + this.scheme = scheme; + this.description = description; + this.type = TYPE; } public HTTPAuthSecurityScheme_v0_3(@Nullable String bearerFormat, String scheme, @Nullable String description) { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java index 6fa813a89..65212a730 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/MutualTLSSecurityScheme_v0_3.java @@ -9,13 +9,12 @@ public record MutualTLSSecurityScheme_v0_3(@Nullable String description, String public static final String TYPE = "mutualTLS"; - public MutualTLSSecurityScheme_v0_3 { - if (type == null) { - type = TYPE; - } - if (!type.equals(TYPE)) { + public MutualTLSSecurityScheme_v0_3(@Nullable String description, @Nullable String type) { + if (type != null && !type.equals(TYPE)) { throw new IllegalArgumentException("Invalid type for MutualTLSSecurityScheme"); } + this.description = description; + this.type = TYPE; } public MutualTLSSecurityScheme_v0_3(@Nullable String description) { diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java index 332794e00..37e90378a 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/OAuth2SecurityScheme_v0_3.java @@ -15,14 +15,15 @@ public record OAuth2SecurityScheme_v0_3( public static final String TYPE = "oauth2"; - public OAuth2SecurityScheme_v0_3 { + public OAuth2SecurityScheme_v0_3(OAuthFlows_v0_3 flows, @Nullable String description, @Nullable String oauth2MetadataUrl, @Nullable String type) { Assert.checkNotNullParam("flows", flows); - if (type == null) { - type = TYPE; - } - if (!type.equals(TYPE)) { + if (type != null && !type.equals(TYPE)) { throw new IllegalArgumentException("Invalid type for OAuth2SecurityScheme"); } + this.flows = flows; + this.description = description; + this.oauth2MetadataUrl = oauth2MetadataUrl; + this.type = TYPE; } public OAuth2SecurityScheme_v0_3(OAuthFlows_v0_3 flows, @Nullable String description, @Nullable String oauth2MetadataUrl) { From 813c013bf86a7cdb2431b21fe2b3482d5a8d3dae Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 28 May 2026 09:17:50 +0200 Subject: [PATCH 180/192] refactor: extract AgentExecutorProducer_v0_3 into separate test module (#890) * refactor: extract AgentExecutorProducer_v0_3 into separate test module Move AgentExecutorProducer_v0_3 from compat-0.3/server-conversion test-jar into a new compat-0.3/tests/server-common module to fix CDI ambiguous dependency errors in downstream consumers that depend on both the v0.3 and v1.0 test-jars. Co-Authored-By: Claude Opus 4.6 * Avoiding creating an empty jar file Signed-off-by: Emmanuel Hugonnet --------- Signed-off-by: Emmanuel Hugonnet Co-authored-by: Claude Opus 4.6 Co-authored-by: Emmanuel Hugonnet --- .../sdk/test/ReferenceBomVerifier.java | 3 +- .../a2aproject/sdk/test/SdkBomVerifier.java | 13 ++--- compat-0.3/pom.xml | 8 +++ compat-0.3/reference/grpc/pom.xml | 7 ++- compat-0.3/reference/jsonrpc/pom.xml | 5 ++ compat-0.3/reference/rest/pom.xml | 5 ++ compat-0.3/tests/server-common/pom.xml | 53 +++++++++++++++++++ .../AgentExecutorProducer_v0_3.java | 0 .../conversion/RequestScopedBean_v0_3.java | 0 .../src/main/resources/META-INF/beans.xml | 7 +++ 10 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 compat-0.3/tests/server-common/pom.xml rename compat-0.3/{server-conversion/src/test => tests/server-common/src/main}/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java (100%) rename compat-0.3/{server-conversion/src/test => tests/server-common/src/main}/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java (100%) create mode 100644 compat-0.3/tests/server-common/src/main/resources/META-INF/beans.xml diff --git a/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java b/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java index 316cee850..acf1143a4 100644 --- a/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java +++ b/boms/reference/src/it/reference-usage-test/src/main/java/org/a2aproject/sdk/test/ReferenceBomVerifier.java @@ -19,7 +19,8 @@ public class ReferenceBomVerifier extends DynamicBomVerifier { "test-utils-docker/", // Test utilities for Docker-based tests "compat-0.3/client/", // Compat 0.3 client modules (part of SDK BOM) "compat-0.3/http-client/", // Compat 0.3 HTTP client (part of SDK BOM) - "compat-0.3/tck/" // Compat 0.3 TCK (not yet enabled) + "compat-0.3/tck/", // Compat 0.3 TCK (not yet enabled) + "compat-0.3/tests/" // Compat 0.3 test utilities // Note: reference/ and compat-0.3/reference/ are NOT excluded - we verify those classes load ); diff --git a/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java b/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java index 6fb7aefca..0d5631c7d 100644 --- a/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java +++ b/boms/sdk/src/it/sdk-usage-test/src/main/java/org/a2aproject/sdk/test/SdkBomVerifier.java @@ -12,13 +12,14 @@ public class SdkBomVerifier extends DynamicBomVerifier { private static final Set SDK_EXCLUSIONS = Set.of( - "boms/", // BOM test modules themselves - "examples/", // Example applications - "tck/", // TCK test suite - "compat-0.3/tck/", // Compat 0.3 TCK (not yet enabled) + "boms/", // BOM test modules themselves + "examples/", // Example applications + "tck/", // TCK test suite + "compat-0.3/tck/", // Compat 0.3 TCK (not yet enabled) "compat-0.3/reference/", // Compat 0.3 reference implementations (in reference BOM) - "tests/", // Integration tests - "test-utils-docker/" // Test utilities for Docker-based tests + "compat-0.3/tests/", // Compat 0.3 test utilities) + "tests/", // Integration tests + "test-utils-docker/" // Test utilities for Docker-based tests ); private static final Set SDK_FORBIDDEN = Set.of( diff --git a/compat-0.3/pom.xml b/compat-0.3/pom.xml index a8d75df65..0c1a7a852 100644 --- a/compat-0.3/pom.xml +++ b/compat-0.3/pom.xml @@ -105,6 +105,11 @@ test-jar ${project.version} + + ${project.groupId} + a2a-java-sdk-compat-0.3-tests-server-common + ${project.version} + @@ -116,6 +121,9 @@ server-conversion + + tests/server-common + client/base client/transport/spi diff --git a/compat-0.3/reference/grpc/pom.xml b/compat-0.3/reference/grpc/pom.xml index ad834439e..3652107dd 100644 --- a/compat-0.3/reference/grpc/pom.xml +++ b/compat-0.3/reference/grpc/pom.xml @@ -52,6 +52,11 @@ test-jar test + + ${project.groupId} + a2a-java-sdk-compat-0.3-tests-server-common + test + ${project.groupId} @@ -131,4 +136,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/compat-0.3/reference/jsonrpc/pom.xml b/compat-0.3/reference/jsonrpc/pom.xml index 2a3bd7f6a..0f1925aec 100644 --- a/compat-0.3/reference/jsonrpc/pom.xml +++ b/compat-0.3/reference/jsonrpc/pom.xml @@ -37,6 +37,11 @@ test-jar test + + ${project.groupId} + a2a-java-sdk-compat-0.3-tests-server-common + test + ${project.groupId} diff --git a/compat-0.3/reference/rest/pom.xml b/compat-0.3/reference/rest/pom.xml index bcc9e882d..d5857ddf5 100644 --- a/compat-0.3/reference/rest/pom.xml +++ b/compat-0.3/reference/rest/pom.xml @@ -33,6 +33,11 @@ test-jar test + + ${project.groupId} + a2a-java-sdk-compat-0.3-tests-server-common + test + ${project.groupId} diff --git a/compat-0.3/tests/server-common/pom.xml b/compat-0.3/tests/server-common/pom.xml new file mode 100644 index 000000000..70a85bd5a --- /dev/null +++ b/compat-0.3/tests/server-common/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-parent + 1.0.0.CR2-SNAPSHOT + ../../pom.xml + + a2a-java-sdk-compat-0.3-tests-server-common + + jar + + Java A2A Compat 0.3 Server Tests Common + Java SDK for the Agent2Agent Protocol (A2A) - Compat 0.3 Server Tests Common + + + + ${project.groupId} + a2a-java-sdk-spec + + + ${project.groupId} + a2a-java-sdk-server-common + + + jakarta.enterprise + jakarta.enterprise.cdi-api + provided + + + io.quarkus + quarkus-arc + provided + + + + + + + org.sonatype.central + central-publishing-maven-plugin + true + + true + + + + + diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java b/compat-0.3/tests/server-common/src/main/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java similarity index 100% rename from compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java rename to compat-0.3/tests/server-common/src/main/java/org/a2aproject/sdk/compat03/conversion/AgentExecutorProducer_v0_3.java diff --git a/compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java b/compat-0.3/tests/server-common/src/main/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java similarity index 100% rename from compat-0.3/server-conversion/src/test/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java rename to compat-0.3/tests/server-common/src/main/java/org/a2aproject/sdk/compat03/conversion/RequestScopedBean_v0_3.java diff --git a/compat-0.3/tests/server-common/src/main/resources/META-INF/beans.xml b/compat-0.3/tests/server-common/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..b708636eb --- /dev/null +++ b/compat-0.3/tests/server-common/src/main/resources/META-INF/beans.xml @@ -0,0 +1,7 @@ + + + From fc736e8a1b3ae105ef4527063e0a8dd978833bb0 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Thu, 21 May 2026 21:49:12 +0100 Subject: [PATCH 181/192] fix: Don't autogenerate message id (0.3 TCK has a test for a null one) Co-Authored-By: Claude Opus 4.6 --- .../sdk/compat03/grpc/utils/ProtoUtils_v0_3.java | 9 +++------ .../org/a2aproject/sdk/compat03/spec/Message_v0_3.java | 9 ++++----- .../sdk/compat03/spec/TaskSerialization_v0_3_Test.java | 2 ++ 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java index cb94fa794..c784afc48 100644 --- a/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java +++ b/compat-0.3/spec-grpc/src/main/java/org/a2aproject/sdk/compat03/grpc/utils/ProtoUtils_v0_3.java @@ -35,7 +35,6 @@ import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigParams_v0_3; import org.a2aproject.sdk.compat03.spec.HTTPAuthSecurityScheme_v0_3; import org.a2aproject.sdk.compat03.spec.ImplicitOAuthFlow_v0_3; -import org.a2aproject.sdk.compat03.spec.InvalidParamsError_v0_3; import org.a2aproject.sdk.compat03.spec.InvalidRequestError_v0_3; import org.a2aproject.sdk.compat03.spec.ListTaskPushNotificationConfigParams_v0_3; import org.a2aproject.sdk.compat03.spec.Message_v0_3; @@ -151,7 +150,9 @@ public static org.a2aproject.sdk.compat03.grpc.Task task(Task_v0_3 task) { public static org.a2aproject.sdk.compat03.grpc.Message message(Message_v0_3 message) { org.a2aproject.sdk.compat03.grpc.Message.Builder builder = org.a2aproject.sdk.compat03.grpc.Message.newBuilder(); - builder.setMessageId(message.messageId()); + if (message.messageId() != null) { + builder.setMessageId(message.messageId()); + } if (message.contextId() != null) { builder.setContextId(message.contextId()); } @@ -863,10 +864,6 @@ public static Task_v0_3 task(org.a2aproject.sdk.compat03.grpc.TaskOrBuilder task } public static Message_v0_3 message(org.a2aproject.sdk.compat03.grpc.MessageOrBuilder message) { - if (message.getMessageId().isEmpty()) { - throw new InvalidParamsError_v0_3(); - } - return new Message_v0_3( role(message.getRole()), message.getContentList().stream().map(item -> part(item)).collect(Collectors.toList()), diff --git a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java index 860437a60..474d47aff 100644 --- a/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java +++ b/compat-0.3/spec/src/main/java/org/a2aproject/sdk/compat03/spec/Message_v0_3.java @@ -1,6 +1,5 @@ package org.a2aproject.sdk.compat03.spec; - import java.util.List; import java.util.Map; import java.util.UUID; @@ -14,7 +13,7 @@ public record Message_v0_3( Role role, List> parts, - String messageId, + @Nullable String messageId, @Nullable String contextId, @Nullable String taskId, @Nullable List referenceTaskIds, @@ -25,7 +24,7 @@ public record Message_v0_3( public static final String KIND = "message"; - public Message_v0_3(Role role, List> parts, String messageId, @Nullable String contextId, + public Message_v0_3(Role role, List> parts, @Nullable String messageId, @Nullable String contextId, @Nullable String taskId, @Nullable List referenceTaskIds, @Nullable Map metadata, @Nullable List extensions, String kind) { Assert.checkNotNullParam("role", role); @@ -35,7 +34,7 @@ public Message_v0_3(Role role, List> parts, String messageId, @Null throw new IllegalArgumentException("Parts cannot be empty"); } this.parts = List.copyOf(parts); - this.messageId = messageId == null ? UUID.randomUUID().toString() : messageId; + this.messageId = messageId; this.kind = kind != null ? kind : KIND; if (!this.kind.equals(KIND)) { throw new IllegalArgumentException("Invalid Message"); @@ -47,7 +46,7 @@ public Message_v0_3(Role role, List> parts, String messageId, @Null this.extensions = extensions != null ? List.copyOf(extensions) : null; } - public Message_v0_3(Role role, List> parts, String messageId, @Nullable String contextId, + public Message_v0_3(Role role, List> parts, @Nullable String messageId, @Nullable String contextId, @Nullable String taskId, @Nullable List referenceTaskIds, @Nullable Map metadata, @Nullable List extensions) { this(role, parts, messageId, contextId, taskId, referenceTaskIds, metadata, extensions, KIND); diff --git a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java index dbe7e0243..927854a7a 100644 --- a/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java +++ b/compat-0.3/spec/src/test/java/org/a2aproject/sdk/compat03/spec/TaskSerialization_v0_3_Test.java @@ -599,6 +599,7 @@ void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException_v0_ }, "history": [ { + "messageId": "msg-001", "role": "user", "parts": [ { @@ -608,6 +609,7 @@ void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException_v0_ ] }, { + "messageId": "msg-002", "role": "agent", "parts": [ { From f09119e396fff86099b5e679bae8337e59ec8759 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 11:04:54 +0200 Subject: [PATCH 182/192] chore: bump the quarkus group across 1 directory with 2 updates (#882) Bumps the quarkus group with 2 updates in the / directory: [io.quarkus:quarkus-bom](https://github.com/quarkusio/quarkus) and io.quarkus:quarkus-maven-plugin. Updates `io.quarkus:quarkus-bom` from 3.35.2 to 3.36.0 - [Release notes](https://github.com/quarkusio/quarkus/releases) - [Commits](https://github.com/quarkusio/quarkus/compare/3.35.2...3.36.0) Updates `io.quarkus:quarkus-maven-plugin` from 3.35.2 to 3.36.0 Updates `io.quarkus:quarkus-maven-plugin` from 3.35.2 to 3.36.0 --- updated-dependencies: - dependency-name: io.quarkus:quarkus-bom dependency-version: 3.35.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: quarkus - dependency-name: io.quarkus:quarkus-maven-plugin dependency-version: 3.35.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: quarkus - dependency-name: io.quarkus:quarkus-maven-plugin dependency-version: 3.35.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: quarkus ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9b50089ba..dc8c0dd7a 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ 1.7.1 4.33.2 0.6.1 - 3.35.2 + 3.36.0 6.0.0 2.0.17 1.5.18 From 58fc36fa0ae6e395833e9798047a3dfc8a063146 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 11:05:14 +0200 Subject: [PATCH 183/192] chore: bump org.slf4j:slf4j-bom from 2.0.17 to 2.0.18 (#885) Bumps [org.slf4j:slf4j-bom](https://github.com/qos-ch/slf4j) from 2.0.17 to 2.0.18. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.17...v_2.0.18) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-bom dependency-version: 2.0.18 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dc8c0dd7a..214264a17 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ 0.6.1 3.36.0 6.0.0 - 2.0.17 + 2.0.18 1.5.18 2.0.5 2.49.0 From ea61e0f7111c28e5a8c7f8d6bd51e2ab5c814ed3 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 1 Jun 2026 09:07:38 +0200 Subject: [PATCH 184/192] fix: wait for child queue creation before enqueuing events in subscribe tests The subscribe tests were flaky because events were enqueued on the server before the EventConsumer polling loop had started. awaitStreamingSubscription() only guarantees transport-level subscription, not consumer readiness. The fix captures the child queue count before subscribing and waits for it to increment, confirming the subscription's EventConsumer is actively polling. This is more robust than awaitChildQueueCountStable with a fixed expected count, since ensureQueueForTask creates a child queue that remains in the count. Co-Authored-By: Claude Opus 4.6 --- .../apps/common/AbstractA2AServerTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index 110708d96..662dd6393 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -790,6 +790,9 @@ public void testSubscribeExistingTaskSuccess() throws Exception { eventLatch.countDown(); }; + // Capture child queue count before subscribing (ensureQueueForTask creates one) + int childCountBefore = getChildQueueCount(MINIMAL_TASK.id()); + // Count down when the streaming subscription is established CountDownLatch subscriptionLatch = new CountDownLatch(1); awaitStreamingSubscription() @@ -801,6 +804,11 @@ public void testSubscribeExistingTaskSuccess() throws Exception { // Wait for subscription to be established assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); + // Wait for EventConsumer polling loop to start (transport-level subscription + // does not guarantee the consumer is ready to receive events) + assertTrue(waitForChildQueueCountToBe(MINIMAL_TASK.id(), childCountBefore + 1, 15000), + "subscribeToTask child queue should be created"); + // Enqueue events on the server List events = List.of( TaskArtifactUpdateEvent.builder() @@ -908,6 +916,9 @@ public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Excepti Client clientWithConsumer = clientBuilder.build(); + // Capture child queue count before subscribing (ensureQueueForTask creates one) + int childCountBefore = getChildQueueCount(MINIMAL_TASK.id()); + // Count down when the streaming subscription is established CountDownLatch subscriptionLatch = new CountDownLatch(1); awaitStreamingSubscription() @@ -919,6 +930,11 @@ public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Excepti // Wait for subscription to be established assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); + // Wait for EventConsumer polling loop to start (transport-level subscription + // does not guarantee the consumer is ready to receive events) + assertTrue(waitForChildQueueCountToBe(MINIMAL_TASK.id(), childCountBefore + 1, 15000), + "subscribeToTask child queue should be created"); + // Enqueue events on the server List events = List.of( TaskArtifactUpdateEvent.builder() From 0217cfd08575f2cfbeebc10ff81cba251d7e034b Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 1 Jun 2026 10:06:44 +0200 Subject: [PATCH 185/192] Update tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../sdk/server/apps/common/AbstractA2AServerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index 662dd6393..240634f07 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -806,8 +806,8 @@ public void testSubscribeExistingTaskSuccess() throws Exception { // Wait for EventConsumer polling loop to start (transport-level subscription // does not guarantee the consumer is ready to receive events) - assertTrue(waitForChildQueueCountToBe(MINIMAL_TASK.id(), childCountBefore + 1, 15000), - "subscribeToTask child queue should be created"); + assertTrue(awaitChildQueueCountStable(MINIMAL_TASK.id(), childCountBefore + 1, 15000), + "subscribeToTask child queue should be created and stable"); // Enqueue events on the server List events = List.of( From d5c8d6be4f2828096188cedef4c39d89e9033301 Mon Sep 17 00:00:00 2001 From: Jeff Mesnil Date: Mon, 1 Jun 2026 10:06:58 +0200 Subject: [PATCH 186/192] Update tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../sdk/server/apps/common/AbstractA2AServerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index 240634f07..74c2497fb 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -932,8 +932,8 @@ public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Excepti // Wait for EventConsumer polling loop to start (transport-level subscription // does not guarantee the consumer is ready to receive events) - assertTrue(waitForChildQueueCountToBe(MINIMAL_TASK.id(), childCountBefore + 1, 15000), - "subscribeToTask child queue should be created"); + assertTrue(awaitChildQueueCountStable(MINIMAL_TASK.id(), childCountBefore + 1, 15000), + "subscribeToTask child queue should be created and stable"); // Enqueue events on the server List events = List.of( From dbe8f25a19e8fc6fd0821df2e08d4a9159e12d9f Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Mon, 1 Jun 2026 16:55:46 +0200 Subject: [PATCH 187/192] fix: defer CDI request context destruction for streaming requests (#904) * fix: defer CDI request context destruction for streaming requests Streaming (SSE) requests dispatch agent work to a background thread via ManagedExecutor and return immediately. The existing runInRequestContext() terminates the CDI request context in a finally block, destroying all @RequestScoped beans before the agent thread runs. This causes ContextNotActiveException when the agent accesses request-scoped beans (e.g. OIDC token propagation via @AccessToken). Add runInRequestContextDeferred() which deactivates the context (detaching it from the worker thread) but defers bean destruction to the HTTP response lifecycle via endHandler/closeHandler. This keeps all @RequestScoped beans alive for the duration of the streaming response. - JSONRPC routes: use runInRequestContextDeferred for the main handler (handles both streaming and non-streaming) - REST routes: add authenticatedStreaming() wrapper for message:stream and tasks/:subscribe endpoints - Apply same changes to compat-0.3 JSONRPC and REST routes - Add streaming variant of CDI propagation test --- .../apps/quarkus/A2AServerRoutes_v0_3.java | 2 +- .../rest/quarkus/A2AServerRoutes_v0_3.java | 16 +++- .../common/quarkus/VertxSecurityHelper.java | 80 ++++++++++++++++++- .../server/apps/quarkus/A2AServerRoutes.java | 2 +- .../server/rest/quarkus/A2AServerRoutes.java | 16 +++- .../apps/common/AbstractA2AServerTest.java | 50 +++++++++++- 6 files changed, 157 insertions(+), 9 deletions(-) diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java index 56ffc021f..de83415b8 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -96,7 +96,7 @@ void setupRoutes(@Observes Router router) { .handler(BodyHandler.create()) .blockingHandler(ctx -> { try { - vertxSecurityHelper.runInRequestContext(ctx, () -> { + vertxSecurityHelper.runInRequestContextDeferred(ctx, () -> { invokeJSONRPCHandler(ctx.body().asString(), ctx); }); } catch (UnauthorizedException | ForbiddenException e) { diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java index 505685ed5..9387024a9 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -87,7 +87,7 @@ void setupRouter(@Observes @Priority(10) Router router) { // POST /v1/message:stream router.postWithRegex("^\\/v1\\/message:stream$") .handler(BodyHandler.create()) - .blockingHandler(authenticated(ctx -> { + .blockingHandler(authenticatedStreaming(ctx -> { sendMessageStreaming(extractBody(ctx), ctx); })); @@ -104,7 +104,7 @@ void setupRouter(@Observes @Priority(10) Router router) { // POST /v1/tasks/{id}:subscribe router.postWithRegex("^\\/v1\\/tasks\\/([^/]+):subscribe$") .order(1) - .blockingHandler(authenticated(this::resubscribeTask)); + .blockingHandler(authenticatedStreaming(this::resubscribeTask)); // POST /v1/tasks/:id/pushNotificationConfigs router.post("/v1/tasks/:id/pushNotificationConfigs") @@ -158,6 +158,18 @@ private Handler authenticated(Consumer action) { }; } + private Handler authenticatedStreaming(Consumer action) { + return ctx -> { + try { + vertxSecurityHelper.runInRequestContextDeferred(ctx, () -> action.accept(ctx)); + } catch (UnauthorizedException | ForbiddenException e) { + vertxSecurityHelper.handleAuthError(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }; + } + @Authenticated public void sendMessage(String body, RoutingContext rc) { ServerCallContext context = createCallContext(rc, SendMessageRequest_v0_3.METHOD); diff --git a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java index 264c89688..bdb55f6d8 100644 --- a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java +++ b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/VertxSecurityHelper.java @@ -1,17 +1,20 @@ package org.a2aproject.sdk.server.common.quarkus; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import jakarta.inject.Singleton; import io.quarkus.arc.Arc; +import io.quarkus.arc.InjectableContext; import io.quarkus.arc.ManagedContext; import io.quarkus.security.identity.CurrentIdentityAssociation; import io.quarkus.vertx.http.runtime.security.ChallengeData; import io.quarkus.vertx.http.runtime.security.HttpAuthenticator; import io.vertx.core.Context; import io.vertx.ext.web.RoutingContext; -import java.util.Map; /** * CDI helper for integrating Quarkus security with Vert.x Web routes. @@ -122,6 +125,81 @@ public void runInRequestContext(RoutingContext ctx, Runnable task) { } } + /** + * Authenticates the request and executes a task, deferring CDI context destruction to the HTTP + * response lifecycle. + * + *

              Unlike {@link #runInRequestContext}, this method does not terminate the CDI request + * context when the task completes. Instead, it: + *

                + *
              1. Activates the CDI request context and captures its {@link InjectableContext.ContextState}
              2. + *
              3. Triggers HTTP authentication
              4. + *
              5. Executes the task
              6. + *
              7. Deactivates the context (detaches from the worker thread without destroying beans)
              8. + *
              9. Destroys the context state when the HTTP response ends or the connection closes
              10. + *
              + * + *

              This is required for streaming (SSE) requests where the task dispatches work to a background + * thread (via {@code CompletableFuture.runAsync} with a {@code ManagedExecutor}) and returns + * immediately. The {@code ManagedExecutor} captures the CDI context at submit time and propagates + * it to the agent thread — but only if the context hasn't been destroyed yet. By deferring + * destruction to the response lifecycle, the agent thread can access all {@code @RequestScoped} + * beans (including OIDC token credentials for token propagation). + * + *

              This method is also safe for non-streaming requests: {@code response.end()} is called + * synchronously inside the task, and the {@code endHandler} fires the cleanup shortly after. + * + * @param ctx the Vert.x routing context containing the HTTP request + * @param task the code to execute within the authenticated request context + * @throws io.quarkus.security.UnauthorizedException if authentication fails + * @throws io.quarkus.security.ForbiddenException if authorization fails + * @throws RuntimeException if the task throws an exception + */ + public void runInRequestContextDeferred(RoutingContext ctx, Runnable task) { + if (Context.isOnEventLoopThread()) { + throw new IllegalStateException( + "Cannot perform blocking authentication on event loop thread. Use blockingHandler()."); + } + ManagedContext requestContext = Arc.container().requestContext(); + boolean wasActive = requestContext.isActive(); + if (wasActive) { + if (!httpAuthenticator.isUnsatisfied()) { + var identity = httpAuthenticator.get().attemptAuthentication(ctx).await().indefinitely(); + currentIdentityAssociation.get().setIdentity(identity); + } + task.run(); + return; + } + + InjectableContext.ContextState state = requestContext.activate(); + + AtomicBoolean destroyed = new AtomicBoolean(false); + Runnable cleanup = () -> { + if (destroyed.compareAndSet(false, true)) { + requestContext.destroy(state); + } + }; + + ctx.response().endHandler(v -> cleanup.run()); + ctx.response().closeHandler(v -> cleanup.run()); + + try { + if (!httpAuthenticator.isUnsatisfied()) { + var identity = httpAuthenticator.get().attemptAuthentication(ctx).await().indefinitely(); + currentIdentityAssociation.get().setIdentity(identity); + } + task.run(); + } catch (Throwable t) { + // Destroy bean instances immediately on error. The subsequent deactivate() in the + // finally block is still needed to detach the (now-empty) context from the worker + // thread. destroy(state) only destroys beans — it does not deactivate the context. + cleanup.run(); + throw t; + } finally { + requestContext.deactivate(); + } + } + /** * Handles authentication or authorization errors by sending the appropriate HTTP error response. * diff --git a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index e9df1bf06..c313e450c 100644 --- a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -212,7 +212,7 @@ void setupRoutes(@Observes Router router) { .handler(BodyHandler.create()) .blockingHandler(ctx -> { try { - vertxSecurityHelper.runInRequestContext(ctx, () -> { + vertxSecurityHelper.runInRequestContextDeferred(ctx, () -> { invokeJSONRPCHandler(ctx.body().asString(), ctx); }); } catch (UnauthorizedException | ForbiddenException e) { diff --git a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java index 170aab63f..f033300fe 100644 --- a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java @@ -180,7 +180,7 @@ void setupRouter(@Observes @Priority(10) Router router) { // POST /{tenant}/message:stream - Streaming message with SSE router.postWithRegex("^\\/(?[^\\/]*\\/?)message:stream$") .handler(BodyHandler.create()) - .blockingHandler(authenticated(ctx -> { + .blockingHandler(authenticatedStreaming(ctx -> { String body = extractBody(ctx); sendMessageStreaming(body, ctx); }), false); @@ -209,7 +209,7 @@ void setupRouter(@Observes @Priority(10) Router router) { // POST /{tenant}/tasks/{taskId}:subscribe - Subscribe to task updates (SSE) router.postWithRegex("^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):subscribe$") .order(1) - .blockingHandler(authenticated(this::subscribeToTask), false); + .blockingHandler(authenticatedStreaming(this::subscribeToTask), false); // Push Notification Routes @@ -264,6 +264,18 @@ private Handler authenticated(Consumer action) { }; } + private Handler authenticatedStreaming(Consumer action) { + return ctx -> { + try { + vertxSecurityHelper.runInRequestContextDeferred(ctx, () -> action.accept(ctx)); + } catch (UnauthorizedException | ForbiddenException e) { + vertxSecurityHelper.handleAuthError(ctx, e); + } catch (Exception e) { + VertxSecurityHelper.handleGenericError(ctx); + } + }; + } + /** * Handles blocking message send requests. * diff --git a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java index 74c2497fb..c5ab7de4b 100644 --- a/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/org/a2aproject/sdk/server/apps/common/AbstractA2AServerTest.java @@ -547,6 +547,51 @@ public void testRequestScopedBeanAvailableOnAgentExecutorThread() throws Excepti assertEquals("request-scoped:request-scoped-value", ((TextPart) part).text()); } + @Test + public void testRequestScopedBeanAvailableOnAgentExecutorThreadStreaming() throws Exception { + Message message = Message.builder() + .messageId("request-scoped-streaming-test") + .role(Message.Role.ROLE_USER) + .parts(new TextPart("request-scoped:test")) + .build(); + + CountDownLatch latch = new CountDownLatch(1); + AtomicReference receivedTask = new AtomicReference<>(); + AtomicReference errorRef = new AtomicReference<>(); + + getClient().sendMessage(message, List.of((event, agentCard) -> { + if (event instanceof TaskEvent te) { + receivedTask.set(te.getTask()); + if (te.getTask().status().state() == TaskState.TASK_STATE_COMPLETED) { + latch.countDown(); + } + } else if (event instanceof TaskUpdateEvent tue) { + receivedTask.set(tue.getTask()); + if (tue.getTask().status().state() == TaskState.TASK_STATE_COMPLETED) { + latch.countDown(); + } + } + }), error -> { + if (!isStreamClosedError(error)) { + errorRef.set(error); + } + latch.countDown(); + }); + + assertTrue(latch.await(10, TimeUnit.SECONDS), "Request should complete within timeout"); + assertNull(errorRef.get(), "Should not have received an error"); + + Task task = receivedTask.get(); + assertNotNull(task, "Should have received a task"); + assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); + assertNotNull(task.artifacts()); + assertFalse(task.artifacts().isEmpty()); + + Part part = task.artifacts().get(0).parts().get(0); + assertInstanceOf(TextPart.class, part); + assertEquals("request-scoped:request-scoped-value", ((TextPart) part).text()); + } + @Test public void testSendMessageExistingTaskSuccess() throws Exception { saveTaskInTaskStore(MINIMAL_TASK); @@ -2429,16 +2474,17 @@ private static String extractSseData(String line) { } protected boolean isStreamClosedError(Throwable throwable) { - // Unwrap the CompletionException Throwable cause = throwable; while (cause != null) { if (cause instanceof EOFException) { return true; } + if (cause instanceof java.util.concurrent.CancellationException) { + return true; + } if (cause instanceof IOException && cause.getMessage() != null && cause.getMessage().contains("cancelled")) { - // stream is closed upon cancellation return true; } cause = cause.getCause(); From 32c5324f3f924db219bbb4051f7220c9b249bbaa Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 2 Jun 2026 12:47:54 +0200 Subject: [PATCH 188/192] fix: Bom verification needs to take Windows into account (#907) * fix: Bom verification needs to take Windows into account Enhance CI to run Windows build/tests on JDK 17 * BOM suggestion --- .github/workflows/build-and-test.yml | 12 ++++++++---- .../a2aproject/sdk/bom/test/DynamicBomVerifier.java | 10 ++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 78cd467f3..8854ad9eb 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -13,10 +13,14 @@ concurrency: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: matrix: + os: [ubuntu-latest] java-version: ['17', '21', '25'] + include: + - os: windows-latest + java-version: '17' steps: - uses: actions/checkout@v6 - name: Set up JDK ${{ matrix.java-version }} @@ -26,12 +30,12 @@ jobs: distribution: 'temurin' cache: maven - name: Build with Maven and run tests - run: mvn -B package --file pom.xml -fae + run: mvn -B package --file pom.xml -fae ${{ matrix.os == 'windows-latest' && '-DskipDockerTests=true' || '' }} - name: Upload Test Reports if: failure() uses: actions/upload-artifact@v7 with: - name: surefire-reports-java-${{ matrix.java-version }} + name: surefire-reports-${{ matrix.os }}-java-${{ matrix.java-version }} path: | **/target/surefire-reports/ **/target/failsafe-reports/ @@ -41,7 +45,7 @@ jobs: if: failure() uses: actions/upload-artifact@v7 with: - name: build-logs-java-${{ matrix.java-version }} + name: build-logs-${{ matrix.os }}-java-${{ matrix.java-version }} path: | **/target/*.log **/target/quarkus.log diff --git a/boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/DynamicBomVerifier.java b/boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/DynamicBomVerifier.java index 8fbc1fa84..da092d4a6 100644 --- a/boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/DynamicBomVerifier.java +++ b/boms/test-utils/src/main/java/org/a2aproject/sdk/bom/test/DynamicBomVerifier.java @@ -156,8 +156,10 @@ private Set discoverClasses(Path projectRoot, java.util.function.Predica try (Stream paths = Files.walk(projectRoot)) { paths.filter(Files::isRegularFile) .filter(p -> p.toString().endsWith(".java")) - .filter(p -> p.toString().contains("/src/main/java/")) - .filter(p -> pathFilter.test(projectRoot.relativize(p).toString())) + .filter(p -> { + String relativePath = toForwardSlash(projectRoot.relativize(p).toString()); + return relativePath.contains("/src/main/java/") && pathFilter.test(relativePath); + }) .forEach(javaFile -> { try { String className = extractClassName(javaFile); @@ -181,6 +183,10 @@ private boolean isForbidden(String relativePath) { return forbiddenPaths.stream().anyMatch(relativePath::startsWith); } + private static String toForwardSlash(String path) { + return path.replace('\\', '/'); + } + private static @Nullable String extractClassName(Path javaFile) throws IOException { // Extract simple class name from filename String fileName = javaFile.getFileName().toString(); From b2d78e4feb642e86f0ab47c9e314f297b9a4f098 Mon Sep 17 00:00:00 2001 From: Kabir Khan Date: Tue, 2 Jun 2026 15:41:31 +0200 Subject: [PATCH 189/192] fix: Update to new name of Jakarta SDK, a2a-jakarta (#908) --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ac751cc98..37e4e8be1 100644 --- a/README.md +++ b/README.md @@ -833,9 +833,8 @@ The following list contains community contributed integrations with various Java To contribute an integration, please see [CONTRIBUTING_INTEGRATIONS.md](CONTRIBUTING_INTEGRATIONS.md). -* [reference/jsonrpc/README.md](reference/jsonrpc/README.md) - JSON-RPC 2.0 Reference implementation, based on Quarkus. -* [reference/grpc/README.md](reference/grpc/README.md) - gRPC Reference implementation, based on Quarkus. -* https://github.com/wildfly-extras/a2a-java-sdk-server-jakarta - This integration is based on Jakarta EE, and should work in all runtimes supporting the [Jakarta EE Web Profile](https://jakarta.ee/specifications/webprofile/). +* This project contains integration with Quarkus and has the reference implementations for the JSON-RPC, gRPC, and HTTP+JSON (REST) transports. +* https://github.com/wildfly-extras/a2a-jakarta - This integration is based on Jakarta EE, and should work in all runtimes supporting the [Jakarta EE Web Profile](https://jakarta.ee/specifications/webprofile/). # Extras See the [`extras`](./extras/README.md) folder for extra functionality not provided by the SDK itself! From 3ced57f8c0cda10260c14d7d988644c5e54b6898 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Tue, 2 Jun 2026 15:44:00 +0200 Subject: [PATCH 190/192] fix: support complete agent card URL in A2ACardResolver (#837) feat!: support complete agent card URL in A2ACardResolver URI.resolve() silently drops intermediate path segments when the resolved path starts with '/', producing wrong URLs for agents under a path prefix. Replace with direct concatenation and add a guard when the supplied URL already includes the agent card path. Signed-off-by: Emmanuel Hugonnet --- README.md | 4 +- .../src/main/java/org/a2aproject/sdk/A2A.java | 7 +- .../client/http/A2ACardResolver_v0_3.java | 24 +- .../http/A2ACardResolver_v0_3_Test.java | 37 ++ .../examples/helloworld/HelloWorldClient.java | 2 +- extras/http-client-vertx/README.md | 4 +- http-client/pom.xml | 5 + .../sdk/client/http/A2ACardResolver.java | 285 +++++++++------ .../sdk/client/http/package-info.java | 2 +- .../sdk/client/http/A2ACardResolverTest.java | 336 ++++++++++++++---- .../sdk/grpc/utils/JSONRPCUtilsTest.java | 7 +- .../java/org/a2aproject/sdk/util/Utils.java | 75 +++- .../org/a2aproject/sdk/util/UtilsTest.java | 118 +++++- 13 files changed, 709 insertions(+), 197 deletions(-) diff --git a/README.md b/README.md index 37e4e8be1..1880c02be 100644 --- a/README.md +++ b/README.md @@ -436,7 +436,7 @@ If you want to use the HTTP+JSON/REST transport, you'll need to add a relevant d ```java // First, get the agent card for the A2A server agent you want to connect to -AgentCard agentCard = new A2ACardResolver("http://localhost:1234").getAgentCard(); +AgentCard agentCard = A2ACardResolver.builder().baseUrl("http://localhost:1234").build().getAgentCard(); // Specify configuration for the ClientBuilder ClientConfig clientConfig = new ClientConfig.Builder() @@ -776,7 +776,7 @@ gRPC and REST transports are also available: #### 3. Create the v0.3 client ```java -AgentCard card = new A2ACardResolver("http://localhost:1234").getAgentCard(); +AgentCard card = A2ACardResolver.builder().baseUrl("http://localhost:1234").build().getAgentCard(); // Find the v0.3 interface from the agent card AgentInterface v03Interface = card.supportedInterfaces().stream() diff --git a/client/base/src/main/java/org/a2aproject/sdk/A2A.java b/client/base/src/main/java/org/a2aproject/sdk/A2A.java index 48e40fb15..d5643d305 100644 --- a/client/base/src/main/java/org/a2aproject/sdk/A2A.java +++ b/client/base/src/main/java/org/a2aproject/sdk/A2A.java @@ -393,7 +393,12 @@ public static AgentCard getAgentCard(String agentUrl, String relativeCardPath, M * @throws org.a2aproject.sdk.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema */ public static AgentCard getAgentCard(A2AHttpClient httpClient, String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError, A2AClientJSONError { - A2ACardResolver resolver = new A2ACardResolver(httpClient, agentUrl, "", relativeCardPath, authHeaders); + A2ACardResolver resolver = A2ACardResolver.builder() + .httpClient(httpClient) + .baseUrl(agentUrl) + .agentCardPath(relativeCardPath) + .authHeaders(authHeaders) + .build(); return resolver.getAgentCard(); } } diff --git a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java index 2d91eb195..a0334307f 100644 --- a/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java +++ b/compat-0.3/client/transport/spi/src/main/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3.java @@ -1,10 +1,11 @@ package org.a2aproject.sdk.compat03.client.http; import java.io.IOException; -import java.net.URI; import java.net.URISyntaxException; import java.util.Map; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + import org.a2aproject.sdk.client.http.A2AHttpClient; import org.a2aproject.sdk.client.http.A2AHttpClientFactory; import org.a2aproject.sdk.client.http.A2AHttpResponse; @@ -13,6 +14,7 @@ import org.a2aproject.sdk.compat03.spec.A2AClientError_v0_3; import org.a2aproject.sdk.compat03.spec.A2AClientJSONError_v0_3; import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; public class A2ACardResolver_v0_3 { @@ -20,8 +22,6 @@ public class A2ACardResolver_v0_3 { private final String url; private final @Nullable Map authHeaders; - private static final String DEFAULT_AGENT_CARD_PATH = "/.well-known/agent-card.json"; - /** * Get the agent card for an A2A agent. * The HTTP client will be auto-selected via {@link A2AHttpClientFactory}. @@ -65,14 +65,17 @@ public A2ACardResolver_v0_3(A2AHttpClient httpClient, String baseUrl, String age */ public A2ACardResolver_v0_3(A2AHttpClient httpClient, String baseUrl, @Nullable String agentCardPath, @Nullable Map authHeaders) throws A2AClientError_v0_3 { + checkNotNullParam("httpClient", httpClient); + checkNotNullParam("baseUrl", baseUrl); this.httpClient = httpClient; - String effectiveAgentCardPath = agentCardPath == null || agentCardPath.isEmpty() ? DEFAULT_AGENT_CARD_PATH : agentCardPath; + String effectiveAgentCardPath = agentCardPath == null || agentCardPath.isEmpty() ? Utils.DEFAULT_AGENT_CARD_PATH : agentCardPath; try { - this.url = new URI(baseUrl).resolve(effectiveAgentCardPath).toString(); + Utils.validateAbsoluteUrl(baseUrl); + this.url = Utils.buildCardUrl(Utils.stripWellKnownSuffix(baseUrl), effectiveAgentCardPath); } catch (URISyntaxException e) { throw new A2AClientError_v0_3("Invalid agent URL", e); } - this.authHeaders = authHeaders; + this.authHeaders = authHeaders != null ? Map.copyOf(authHeaders) : null; } /** @@ -88,9 +91,7 @@ public AgentCard_v0_3 getAgentCard() throws A2AClientError_v0_3, A2AClientJSONEr .addHeader("Content-Type", "application/json"); if (authHeaders != null) { - for (Map.Entry entry : authHeaders.entrySet()) { - builder.addHeader(entry.getKey(), entry.getValue()); - } + builder.addHeaders(authHeaders); } String body; @@ -100,7 +101,10 @@ public AgentCard_v0_3 getAgentCard() throws A2AClientError_v0_3, A2AClientJSONEr throw new A2AClientError_v0_3("Failed to obtain agent card: " + response.status()); } body = response.body(); - } catch (IOException | InterruptedException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new A2AClientError_v0_3("Failed to obtain agent card", e); + } catch (IOException e) { throw new A2AClientError_v0_3("Failed to obtain agent card", e); } diff --git a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java index 1b6e2736e..1575d67a2 100644 --- a/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java +++ b/compat-0.3/client/transport/spi/src/test/java/org/a2aproject/sdk/compat03/client/http/A2ACardResolver_v0_3_Test.java @@ -62,8 +62,45 @@ public void testConstructorStripsSlashes() throws Exception { card = resolver.getAgentCard(); assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); + + // baseUrl with sub-path and trailing slash — the original URI.resolve() bug silently + // dropped the sub-path, producing http://example.com/.well-known/agent-card.json instead + resolver = new A2ACardResolver_v0_3(client, "http://example.com/jsonrpc/", AGENT_CARD_PATH); + card = resolver.getAgentCard(); + + assertEquals("http://example.com/jsonrpc" + AGENT_CARD_PATH, client.url); + + // baseUrl with sub-path, no trailing slash + resolver = new A2ACardResolver_v0_3(client, "http://example.com/jsonrpc", AGENT_CARD_PATH); + card = resolver.getAgentCard(); + + assertEquals("http://example.com/jsonrpc" + AGENT_CARD_PATH, client.url); + } + + + @Test + public void testBaseUrl_alreadyContainsWellKnownPath() throws Exception { + TestHttpClient client = new TestHttpClient(); + client.body = JsonMessages_v0_3.AGENT_CARD; + + String fullUrl = "https://example.com/spec03" + AGENT_CARD_PATH; + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3(client, fullUrl); + resolver.getAgentCard(); + + assertEquals(fullUrl, client.url); } + @Test + public void testFullWellKnownUrlWithCustomAgentCardPath() throws Exception { + TestHttpClient client = new TestHttpClient(); + client.body = JsonMessages_v0_3.AGENT_CARD; + + A2ACardResolver_v0_3 resolver = new A2ACardResolver_v0_3( + client, "https://example.com/spec03" + AGENT_CARD_PATH, "/custom/card.json"); + resolver.getAgentCard(); + + assertEquals("https://example.com/spec03/custom/card.json", client.url); + } @Test public void testGetAgentCardSuccess() throws Exception { diff --git a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldClient.java b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldClient.java index d948c2e7c..4cee9b612 100644 --- a/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldClient.java +++ b/examples/helloworld/client/src/main/java/org/a2aproject/sdk/examples/helloworld/HelloWorldClient.java @@ -53,7 +53,7 @@ public class HelloWorldClient { public static void main(String[] args) { OpenTelemetrySdk openTelemetrySdk = null; try { - AgentCard publicAgentCard = new A2ACardResolver(SERVER_URL).getAgentCard(); + AgentCard publicAgentCard = A2ACardResolver.builder().baseUrl(SERVER_URL).build().getAgentCard(); System.out.println("Successfully fetched public agent card:"); System.out.println(JsonUtil.toJson(publicAgentCard)); System.out.println("Using public agent card for client initialization (default)."); diff --git a/extras/http-client-vertx/README.md b/extras/http-client-vertx/README.md index b1d22a54c..274a404c3 100644 --- a/extras/http-client-vertx/README.md +++ b/extras/http-client-vertx/README.md @@ -85,7 +85,7 @@ The Vert.x HTTP client is automatically discovered via **Java SPI (Service Provi ```java // No changes needed - A2A SDK automatically uses VertxA2AHttpClient -A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999"); +A2ACardResolver resolver = A2ACardResolver.builder().baseUrl("http://localhost:9999").build(); AgentCard card = resolver.getAgentCard(); // Uses Vert.x under the hood // Client creation also uses Vert.x automatically @@ -112,7 +112,7 @@ The module works out-of-the-box with sensible defaults: // With vertx-http-client on the classpath, it automatically uses VertxA2AHttpClient // Example 1: Fetching agent card -A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999"); +A2ACardResolver resolver = A2ACardResolver.builder().baseUrl("http://localhost:9999").build(); AgentCard card = resolver.getAgentCard(); // Example 2: Using REST transport (uses HTTP client internally) diff --git a/http-client/pom.xml b/http-client/pom.xml index d6f5264cc..33a23753b 100644 --- a/http-client/pom.xml +++ b/http-client/pom.xml @@ -30,6 +30,11 @@ protobuf-java-util + + org.slf4j + slf4j-api + + org.junit.jupiter junit-jupiter-api diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java index e8ee10397..d5024dac3 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/A2ACardResolver.java @@ -1,184 +1,259 @@ package org.a2aproject.sdk.client.http; - import java.io.IOException; -import java.net.URI; import java.net.URISyntaxException; +import java.util.HashMap; import java.util.Map; +import static org.a2aproject.sdk.util.Assert.checkNotNullParam; + import org.a2aproject.sdk.grpc.utils.JSONRPCUtils; import org.a2aproject.sdk.grpc.utils.ProtoUtils; import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException; import org.a2aproject.sdk.spec.A2AClientError; import org.a2aproject.sdk.spec.A2AClientJSONError; import org.a2aproject.sdk.spec.AgentCard; -import org.a2aproject.sdk.spec.A2AError; +import org.a2aproject.sdk.util.Utils; import org.jspecify.annotations.Nullable; - -import static org.a2aproject.sdk.util.Assert.checkNotNullParam; - -import org.a2aproject.sdk.spec.AgentInterface; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Utility for fetching agent cards from A2A agents. * - *

              Retrieves agent cards from the standard {@code /.well-known/agent-card.json} endpoint + *

              + * Retrieves agent cards from the standard {@code /.well-known/agent-card.json} endpoint * with support for tenant-specific paths and authentication headers. * *

              Features

              *
                - *
              • Standard agent card endpoint discovery ({@code /.well-known/agent-card.json})
              • - *
              • Tenant-specific path support ({@code /tenant/.well-known/agent-card.json})
              • - *
              • Custom authentication header injection
              • - *
              • Pluggable HTTP client via {@link A2AHttpClientFactory}
              • - *
              • Support for both public and extended agent cards
              • + *
              • Standard agent card endpoint discovery ({@code /.well-known/agent-card.json})
              • + *
              • Tenant-specific path support ({@code /tenant/.well-known/agent-card.json})
              • + *
              • Custom card path support for non-standard agent card locations
              • + *
              • Custom authentication header injection
              • + *
              • Pluggable HTTP client via {@link A2AHttpClientFactory}
              • *
              * *

              Usage Examples

              *
              {@code
              - * // Basic usage - fetch agent card
              - * A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999");
              + * // Basic usage - fetch the agent card from a base URL
              + * A2ACardResolver resolver = A2ACardResolver.builder()
              + *     .baseUrl("http://localhost:9999")
              + *     .build();
                * AgentCard card = resolver.getAgentCard();
                *
                * // With tenant path
              - * A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999", "my-tenant");
              + * A2ACardResolver resolver = A2ACardResolver.builder()
              + *     .baseUrl("http://localhost:9999")
              + *     .tenant("my-tenant")
              + *     .build();
                * AgentCard card = resolver.getAgentCard();
                *
              - * // With custom HTTP client
              + * // With custom HTTP client and authentication
                * A2AHttpClient httpClient = A2AHttpClientFactory.create();
              - * A2ACardResolver resolver = new A2ACardResolver(httpClient, "http://localhost:9999", "my-tenant");
              + * A2ACardResolver resolver = A2ACardResolver.builder()
              + *     .httpClient(httpClient)
              + *     .baseUrl("http://localhost:9999")
              + *     .tenant("my-tenant")
              + *     .authHeader("Authorization", "Bearer token")
              + *     .build();
                * AgentCard card = resolver.getAgentCard();
                *
              - * // With authentication headers
              - * A2AHttpClient httpClient = A2AHttpClientFactory.create();
              - * Map authHeaders = Map.of("Authorization", "Bearer token");
              - * A2ACardResolver resolver = new A2ACardResolver(
              - *     httpClient,
              - *     "http://localhost:9999",
              - *     "my-tenant",
              - *     null,  // use default agent card path
              - *     authHeaders
              - * );
              + * // With a custom agent card path
              + * A2ACardResolver resolver = A2ACardResolver.builder()
              + *     .baseUrl("http://localhost:9999")
              + *     .agentCardPath("/custom/agent.json")
              + *     .build();
                * AgentCard card = resolver.getAgentCard();
                *
              - * // Fetch extended agent card (if available)
              - * AgentCard extendedCard = resolver.getExtendedAgentCard();
              + * // Using a complete URL (e.g., with path prefix like /spec03)
              + * A2ACardResolver resolver = A2ACardResolver.builder()
              + *     .baseUrl("https://example.com/spec03")
              + *     .build();
              + * AgentCard card = resolver.getAgentCard();
                * }
              * * @see AgentCard * @see A2AHttpClient */ public class A2ACardResolver { + + private static final Logger LOGGER = LoggerFactory.getLogger(A2ACardResolver.class); + private final A2AHttpClient httpClient; - private final String url; + private final String cardUrl; private final @Nullable Map authHeaders; - private static final String DEFAULT_AGENT_CARD_PATH = "/.well-known/agent-card.json"; - - /** - * Creates an agent card resolver. An HTTP client will be auto-selected via {@link A2AHttpClientFactory}. - * - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if baseUrl is null - */ - public A2ACardResolver(String baseUrl) throws A2AClientError { - this(A2AHttpClientFactory.create(), baseUrl, null, null); + private A2ACardResolver(A2AHttpClient httpClient, String baseUrl, @Nullable String tenant, @Nullable String agentCardPath, @Nullable Map authHeaders) throws A2AClientError { + checkNotNullParam("httpClient", httpClient); + checkNotNullParam("baseUrl", baseUrl); + this.httpClient = httpClient; + try { + // Strip any well-known suffix from baseUrl before appending the tenant, + // so that a full card URL like https://host/.well-known/agent-card.json + tenant + // doesn't produce a malformed path. + String cleanBase = Utils.stripWellKnownSuffix(baseUrl); + String baseUrlWithTenant = Utils.buildBaseUrl(cleanBase, tenant); + Utils.validateAbsoluteUrl(baseUrlWithTenant); + this.cardUrl = (agentCardPath == null || agentCardPath.isEmpty()) + ? Utils.buildCardUrl(baseUrlWithTenant, Utils.DEFAULT_AGENT_CARD_PATH) + : Utils.buildCardUrl(baseUrlWithTenant, agentCardPath); + } catch (URISyntaxException e) { + throw new A2AClientError("Invalid agent URL", e); + } + this.authHeaders = authHeaders != null ? Map.copyOf(authHeaders) : null; + LOGGER.debug("Initialized A2ACardResolver with cardUrl={}", cardUrl); } /** - * Get the agent card for an A2A agent. An HTTP client will be auto-selected via {@link A2AHttpClientFactory}. + * Creates a new builder for constructing an A2ACardResolver. * - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @param tenant the tenant path to use when fetching the agent card, may be null for no tenant - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if baseUrl is null + * @return a new builder instance */ - public A2ACardResolver(String baseUrl, @Nullable String tenant) throws A2AClientError { - this(A2AHttpClientFactory.create(), baseUrl, tenant, null); + public static Builder builder() { + return new Builder(); } /** - * Constructs an A2ACardResolver with a specific HTTP client and base URL. - * - * @param httpClient the HTTP client to use for fetching the agent card, must not be null - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @param tenant the tenant path to use when fetching the agent card, may be null for no tenant - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if httpClient or baseUrl is null + * Builder for creating A2ACardResolver instances with a fluent API. */ - public A2ACardResolver(A2AHttpClient httpClient, String baseUrl, @Nullable String tenant) throws A2AClientError { - this(httpClient, baseUrl, tenant, null); - } + public static class Builder { - /** - * Constructs an A2ACardResolver with a specific HTTP client, base URL, and custom agent card path. - * - * @param httpClient the HTTP client to use for fetching the agent card, must not be null - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @param tenant the tenant path to use when fetching the agent card, may be null for no tenant - * @param agentCardPath optional path to the agent card endpoint relative to the base - * agent URL, defaults to "/.well-known/agent-card.json" if null or empty - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if httpClient or baseUrl is null - */ - public A2ACardResolver(A2AHttpClient httpClient, String baseUrl, @Nullable String tenant, @Nullable String agentCardPath) throws A2AClientError { - this(httpClient, baseUrl, tenant, agentCardPath, null); - } + private @Nullable A2AHttpClient httpClient; + private @Nullable String baseUrl; + private @Nullable String tenant; + private @Nullable String agentCardPath; + private @Nullable Map authHeaders; - /** - * Constructs an A2ACardResolver with full configuration including authentication headers. - * - * @param httpClient the HTTP client to use for fetching the agent card, must not be null - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @param tenant the tenant path to use when fetching the agent card, may be null for no tenant - * @param agentCardPath optional path to the agent card endpoint relative to the base - * agent URL, defaults to "/.well-known/agent-card.json" if null or empty - * @param authHeaders the HTTP authentication headers to use, may be null - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if httpClient or baseUrl is null - */ - public A2ACardResolver(A2AHttpClient httpClient, String baseUrl, @Nullable String tenant, @Nullable String agentCardPath, - @Nullable Map authHeaders) throws A2AClientError { - checkNotNullParam("httpClient", httpClient); - checkNotNullParam("baseUrl", baseUrl); + private Builder() { + } - this.httpClient = httpClient; - String effectiveAgentCardPath = (agentCardPath == null || agentCardPath.isEmpty()) ? DEFAULT_AGENT_CARD_PATH : agentCardPath; - try { - this.url = new URI(org.a2aproject.sdk.util.Utils.buildBaseUrl(new AgentInterface("JSONRPC", baseUrl, ""), tenant)).resolve(effectiveAgentCardPath).toString(); - } catch (URISyntaxException e) { - throw new A2AClientError("Invalid agent URL", e); + /** + * Sets the HTTP client to use for fetching agent cards. + * If not called, a default client is created via {@link A2AHttpClientFactory#create()}. + * + * @param httpClient the HTTP client to use + * @return this builder + */ + public Builder httpClient(A2AHttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Sets the base URL for the agent. + * + * @param baseUrl the base URL, must not be null + * @return this builder + */ + public Builder baseUrl(String baseUrl) { + this.baseUrl = baseUrl; + return this; + } + + /** + * Sets the tenant path to use when fetching the agent card. + * + * @param tenant the tenant path, may be null for no tenant + * @return this builder + */ + public Builder tenant(@Nullable String tenant) { + this.tenant = tenant; + return this; + } + + /** + * Sets a custom agent card path relative to the base URL. + * + * @param agentCardPath the custom agent card path; if null or empty, defaults to + * {@code /.well-known/agent-card.json} + * @return this builder + */ + public Builder agentCardPath(@Nullable String agentCardPath) { + this.agentCardPath = agentCardPath; + return this; + } + + /** + * Sets the authentication headers to use when fetching the agent card. + * + * @param authHeaders the authentication headers, may be null + * @return this builder + */ + public Builder authHeaders(@Nullable Map authHeaders) { + if (authHeaders != null) { + this.authHeaders = new HashMap<>(authHeaders); + } + return this; + } + + /** + * Adds a single authentication header. + * + * @param name the header name + * @param value the header value + * @return this builder + */ + public Builder authHeader(String name, String value) { + if (this.authHeaders == null) { + this.authHeaders = new HashMap<>(); + } + this.authHeaders.put(name, value); + return this; + } + + /** + * Builds the A2ACardResolver instance. + * + * @return a new A2ACardResolver + * @throws A2AClientError if the configuration is invalid + * @throws IllegalArgumentException if baseUrl is null + */ + public A2ACardResolver build() throws A2AClientError { + A2AHttpClient client = httpClient != null ? httpClient : A2AHttpClientFactory.create(); + if (baseUrl == null) { + throw new IllegalArgumentException("baseUrl must not be null"); + } + return new A2ACardResolver(client, baseUrl, tenant, agentCardPath, authHeaders); } - this.authHeaders = authHeaders; } /** - * Get the agent card for the configured A2A agent. + * Fetches the agent card for this resolver's configured agent. + * + *

              Fetches from the custom {@code agentCardPath} when one was supplied, otherwise fetches + * from the standard {@code /.well-known/agent-card.json} endpoint. No automatic fallback + * is performed; errors are propagated directly to the caller. * * @return the agent card - * @throws A2AClientError If an HTTP error occurs fetching the card - * @throws A2AClientJSONError If the response body cannot be decoded as JSON or validated against the AgentCard schema + * @throws A2AClientError If an HTTP or network error occurs fetching the card + * @throws A2AClientJSONError If the response body cannot be decoded as JSON or validated + * against the AgentCard schema */ public AgentCard getAgentCard() throws A2AClientError, A2AClientJSONError { + LOGGER.debug("Fetching agent card from URL: {}", cardUrl); + A2AHttpClient.GetBuilder builder = httpClient.createGet() - .url(url) + .url(cardUrl) .addHeader("Content-Type", "application/json"); if (authHeaders != null) { - for (Map.Entry entry : authHeaders.entrySet()) { - builder.addHeader(entry.getKey(), entry.getValue()); - } + builder.addHeaders(authHeaders); } String body; try { A2AHttpResponse response = builder.get(); if (!response.success()) { + LOGGER.debug("Failed to fetch agent card from {}, status: {}", cardUrl, response.status()); throw new A2AClientError("Failed to obtain agent card: " + response.status()); } body = response.body(); - } catch (IOException | InterruptedException e) { + LOGGER.debug("Successfully fetched agent card from {}", cardUrl); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new A2AClientError("Failed to obtain agent card", e); + } catch (IOException e) { throw new A2AClientError("Failed to obtain agent card", e); } @@ -186,7 +261,7 @@ public AgentCard getAgentCard() throws A2AClientError, A2AClientJSONError { org.a2aproject.sdk.grpc.AgentCard.Builder agentCardBuilder = org.a2aproject.sdk.grpc.AgentCard.newBuilder(); JSONRPCUtils.parseJsonString(body, agentCardBuilder, "", true); return ProtoUtils.FromProto.agentCard(agentCardBuilder); - } catch (A2AError | JsonProcessingException e) { + } catch (JsonProcessingException e) { throw new A2AClientJSONError("Could not unmarshal agent card response", e); } } diff --git a/http-client/src/main/java/org/a2aproject/sdk/client/http/package-info.java b/http-client/src/main/java/org/a2aproject/sdk/client/http/package-info.java index b4b33edc0..671e24532 100644 --- a/http-client/src/main/java/org/a2aproject/sdk/client/http/package-info.java +++ b/http-client/src/main/java/org/a2aproject/sdk/client/http/package-info.java @@ -24,7 +24,7 @@ *

              Usage Example

              *
              {@code
                * // Fetch an agent card
              - * A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999");
              + * A2ACardResolver resolver = A2ACardResolver.builder().baseUrl("http://localhost:9999").build();
                * AgentCard card = resolver.getAgentCard();
                *
                * // Make HTTP requests
              diff --git a/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java
              index b89476185..3caeeebda 100644
              --- a/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java
              +++ b/http-client/src/test/java/org/a2aproject/sdk/client/http/A2ACardResolverTest.java
              @@ -1,132 +1,327 @@
               package org.a2aproject.sdk.client.http;
               
               import static org.junit.jupiter.api.Assertions.assertEquals;
              -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 com.google.protobuf.InvalidProtocolBufferException;
              +import com.google.protobuf.util.JsonFormat;
               import java.io.IOException;
              +import java.util.ArrayList;
              +import java.util.HashMap;
              +import java.util.List;
              +import java.util.Map;
               import java.util.concurrent.CompletableFuture;
               import java.util.function.Consumer;
              -
              -import com.google.protobuf.InvalidProtocolBufferException;
              -import com.google.protobuf.util.JsonFormat;
               import org.a2aproject.sdk.grpc.utils.JSONRPCUtils;
               import org.a2aproject.sdk.grpc.utils.ProtoUtils;
               import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException;
               import org.a2aproject.sdk.spec.A2AClientError;
               import org.a2aproject.sdk.spec.A2AClientJSONError;
               import org.a2aproject.sdk.spec.AgentCard;
              -import java.util.Map;
               import org.junit.jupiter.api.Test;
               
               public class A2ACardResolverTest {
               
                   private static final String AGENT_CARD_PATH = "/.well-known/agent-card.json";
               
              -    @Test
              -    public void testConstructorStripsSlashes() throws Exception {
              +    private TestHttpClient createTestClient() {
                       TestHttpClient client = new TestHttpClient();
                       client.body = JsonMessages.AGENT_CARD;
              +        return client;
              +    }
               
              -        A2ACardResolver resolver = new A2ACardResolver(client, "http://example.com/", "");
              -        AgentCard card = resolver.getAgentCard();
              +    // -------------------------------------------------------------------------
              +    // Well-known URL construction
              +    // -------------------------------------------------------------------------
               
              +    @Test
              +    public void testWellKnownUrl_trailingSlashStripped() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/").build().getAgentCard();
                       assertEquals("http://example.com" + AGENT_CARD_PATH, client.url);
              +    }
               
              +    @Test
              +    public void testWellKnownUrl_noTrailingSlash() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com").build().getAgentCard();
              +        assertEquals("http://example.com" + AGENT_CARD_PATH, client.url);
              +    }
               
              -        resolver = new A2ACardResolver(client, "http://example.com", "");
              -        card = resolver.getAgentCard();
              +    @Test
              +    public void testWellKnownUrl_subPathPreserved_withTrailingSlash() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        // URI.resolve() would have silently dropped the sub-path; string concat must not.
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/jsonrpc/").build().getAgentCard();
              +        assertEquals("http://example.com/jsonrpc" + AGENT_CARD_PATH, client.url);
              +    }
               
              -        assertEquals("http://example.com" + AGENT_CARD_PATH, client.url);
              +    @Test
              +    public void testWellKnownUrl_subPathPreserved_noTrailingSlash() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/jsonrpc").build().getAgentCard();
              +        assertEquals("http://example.com/jsonrpc" + AGENT_CARD_PATH, client.url);
              +    }
               
              -        // baseUrl with trailing slash, agentCardParth with leading slash
              -        resolver = new A2ACardResolver(client, "http://example.com/", AGENT_CARD_PATH);
              -        card = resolver.getAgentCard();
              +    // -------------------------------------------------------------------------
              +    // Custom agent card path URL construction
              +    // -------------------------------------------------------------------------
               
              +    @Test
              +    public void testCustomPath_withLeadingSlash() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com").agentCardPath(AGENT_CARD_PATH).build().getAgentCard();
                       assertEquals("http://example.com" + AGENT_CARD_PATH, client.url);
              +    }
               
              -        // baseUrl without trailing slash, agentCardPath with leading slash
              -        resolver = new A2ACardResolver(client, "http://example.com", AGENT_CARD_PATH);
              -        card = resolver.getAgentCard();
              -
              +    @Test
              +    public void testCustomPath_withoutLeadingSlash() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com").agentCardPath(AGENT_CARD_PATH.substring(1)).build().getAgentCard();
                       assertEquals("http://example.com" + AGENT_CARD_PATH, client.url);
              +    }
               
              -        // baseUrl with trailing slash, agentCardPath without leading slash
              -        resolver = new A2ACardResolver(client, "http://example.com/", AGENT_CARD_PATH.substring(1));
              -        card = resolver.getAgentCard();
              +    @Test
              +    public void testCustomPath_baseUrlTrailingSlash_withLeadingSlash() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/").agentCardPath(AGENT_CARD_PATH).build().getAgentCard();
              +        assertEquals("http://example.com" + AGENT_CARD_PATH, client.url);
              +    }
               
              +    @Test
              +    public void testCustomPath_baseUrlTrailingSlash_withoutLeadingSlash() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/").agentCardPath(AGENT_CARD_PATH.substring(1)).build().getAgentCard();
                       assertEquals("http://example.com" + AGENT_CARD_PATH, client.url);
              +    }
               
              -        // baseUrl without trailing slash, agentCardPath without leading slash
              -        resolver = new A2ACardResolver(client, "http://example.com", AGENT_CARD_PATH.substring(1));
              -        card = resolver.getAgentCard();
              +    @Test
              +    public void testCustomPath_doesNotIntroduceDoubleSlash() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/").agentCardPath("/custom/agent.json").build().getAgentCard();
              +        assertEquals("http://example.com/custom/agent.json", client.url);
              +    }
               
              -        assertEquals("http://example.com" + AGENT_CARD_PATH, client.url);
              +    @Test
              +    public void testCustomPath_subBaseUrl() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/jsonrpc/").agentCardPath(AGENT_CARD_PATH).build().getAgentCard();
              +        assertEquals("http://example.com/jsonrpc" + AGENT_CARD_PATH, client.url);
                   }
               
              +    // -------------------------------------------------------------------------
              +    // Fetch success / error
              +    // -------------------------------------------------------------------------
               
                   @Test
              -    public void testGetAgentCardSuccess() throws Exception {
              -        TestHttpClient client = new TestHttpClient();
              -        client.body = JsonMessages.AGENT_CARD;
              +    public void testGetAgentCard_success() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        AgentCard card = A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/").build().getAgentCard();
              +        assertEquals(printAgentCard(unmarshalFrom(JsonMessages.AGENT_CARD)), printAgentCard(card));
              +    }
               
              -        A2ACardResolver resolver = new A2ACardResolver(client, "http://example.com/", "");
              -        AgentCard card = resolver.getAgentCard();
              +    @Test
              +    public void testGetAgentCard_jsonDecodeError() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        client.body = "X" + JsonMessages.AGENT_CARD;
              +        A2ACardResolver resolver = A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/").build();
              +        assertThrows(A2AClientJSONError.class, resolver::getAgentCard);
              +    }
               
              -        AgentCard expectedCard = unmarshalFrom(JsonMessages.AGENT_CARD);
              -        String expected = printAgentCard(expectedCard);
              +    @Test
              +    public void testGetAgentCard_httpErrorThrows() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        client.status = 503;
              +        A2ACardResolver resolver = A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com/").build();
              +        A2AClientError error = assertThrows(A2AClientError.class, resolver::getAgentCard);
              +        assertTrue(error.getMessage().contains("503"));
              +    }
               
              -        String requestCardString = printAgentCard(card);
              -        assertEquals(expected, requestCardString);
              +    @Test
              +    public void testGetAgentCard_customPath_httpErrorThrows_noFallback() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        client.status = 404;
              +        A2ACardResolver resolver = A2ACardResolver.builder()
              +                .httpClient(client)
              +                .baseUrl("http://example.com")
              +                .agentCardPath("/custom/agent.json")
              +                .build();
              +        assertThrows(A2AClientError.class, resolver::getAgentCard);
              +        assertEquals(1, client.urlsCalled.size());
              +        assertEquals("http://example.com/custom/agent.json", client.urlsCalled.get(0));
                   }
               
              -    private AgentCard unmarshalFrom(String body) throws JsonProcessingException {
              -        org.a2aproject.sdk.grpc.AgentCard.Builder agentCardBuilder = org.a2aproject.sdk.grpc.AgentCard.newBuilder();
              -        JSONRPCUtils.parseJsonString(body, agentCardBuilder, "");
              -        return ProtoUtils.FromProto.agentCard(agentCardBuilder);
              +    @Test
              +    public void testGetAgentCard_ioExceptionThrows() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        client.throwIOException = true;
              +        assertThrows(A2AClientError.class,
              +                A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com").build()::getAgentCard);
                   }
               
              -    private String printAgentCard(AgentCard agentCard) throws InvalidProtocolBufferException {
              -        return JsonFormat.printer().print(ProtoUtils.ToProto.agentCard(agentCard));
              +    @Test
              +    public void testGetAgentCard_interruptedExceptionThrows() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        client.throwInterruptedException = true;
              +        assertThrows(A2AClientError.class,
              +                A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com").build()::getAgentCard);
                   }
               
              +    // -------------------------------------------------------------------------
              +    // Tenant, auth headers, builder validation
              +    // -------------------------------------------------------------------------
              +
                   @Test
              -    public void testGetAgentCardJsonDecodeError() throws Exception {
              -        TestHttpClient client = new TestHttpClient();
              -        client.body = "X" + JsonMessages.AGENT_CARD;
              +    public void testGetAgentCard_withTenant() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com").tenant("my-tenant").build().getAgentCard();
              +        assertEquals("http://example.com/my-tenant" + AGENT_CARD_PATH, client.url);
              +    }
               
              -        A2ACardResolver resolver = new A2ACardResolver(client, "http://example.com/", "");
              +    @Test
              +    public void testGetAgentCard_withTenantAndCustomAgentCardPath() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder()
              +                .httpClient(client)
              +                .baseUrl("http://example.com")
              +                .tenant("acme")
              +                .agentCardPath("/custom/card.json")
              +                .build()
              +                .getAgentCard();
              +        assertEquals("http://example.com/acme/custom/card.json", client.url);
              +    }
               
              -        boolean success = false;
              -        try {
              -            AgentCard card = resolver.getAgentCard();
              -            success = true;
              -        } catch (A2AClientJSONError expected) {
              -        }
              -        assertFalse(success);
              +    @Test
              +    public void testGetAgentCard_withCustomPath_absoluteAndRelative() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com").agentCardPath("/custom/agent.json").build().getAgentCard();
              +        assertEquals("http://example.com/custom/agent.json", client.url);
              +
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com").agentCardPath("custom/agent.json").build().getAgentCard();
              +        assertEquals("http://example.com/custom/agent.json", client.url);
                   }
               
              +    @Test
              +    public void testGetAgentCard_withAuthHeadersMap() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com")
              +                .authHeaders(Map.of("Authorization", "Bearer token123")).build().getAgentCard();
              +        assertEquals("Bearer token123", client.capturedHeaders.get("Authorization"));
              +    }
               
                   @Test
              -    public void testGetAgentCardRequestError() throws Exception {
              -        TestHttpClient client = new TestHttpClient();
              -        client.status = 503;
              +    public void testGetAgentCard_withAuthHeaderSingle() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("http://example.com")
              +                .authHeader("Authorization", "Bearer token123").build().getAgentCard();
              +        assertEquals("Bearer token123", client.capturedHeaders.get("Authorization"));
              +    }
               
              -        A2ACardResolver resolver = new A2ACardResolver(client, "http://example.com/", "");
              +    @Test
              +    public void testBuilder_nullBaseUrl_throws() {
              +        assertThrows(IllegalArgumentException.class, () -> A2ACardResolver.builder().build());
              +    }
               
              -        String msg = null;
              -        try {
              -            AgentCard card = resolver.getAgentCard();
              -        } catch (A2AClientError expected) {
              -            msg = expected.getMessage();
              -        }
              -        assertTrue(msg.contains("503"));
              +    @Test
              +    public void testBuilder_malformedBaseUrl_throws() {
              +        assertThrows(A2AClientError.class, () -> A2ACardResolver.builder().baseUrl("not-a-url").build());
              +    }
              +
              +    @Test
              +    public void testFullWellKnownUrlWithTenant() throws Exception {
              +        // Full well-known URL + tenant must strip the suffix before appending tenant,
              +        // not produce a malformed path like ...agent-card.json/my-tenant/.well-known/agent-card.json
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver resolver = A2ACardResolver.builder()
              +                .httpClient(client)
              +                .baseUrl("https://example.com/.well-known/agent-card.json")
              +                .tenant("my-tenant")
              +                .build();
              +        resolver.getAgentCard();
              +        assertEquals("https://example.com/my-tenant" + AGENT_CARD_PATH, client.url);
              +    }
              +
              +    // -------------------------------------------------------------------------
              +    // Spec03 / full-URL edge cases
              +    // -------------------------------------------------------------------------
              +
              +    @Test
              +    public void testSpec03PathPreservation_wellKnown() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("https://example.com/spec03").build().getAgentCard();
              +        assertEquals("https://example.com/spec03" + AGENT_CARD_PATH, client.url);
              +    }
              +
              +    @Test
              +    public void testSpec03PathPreservation_withTenant() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("https://example.com/spec03").tenant("my-tenant").build().getAgentCard();
              +        assertEquals("https://example.com/spec03/my-tenant" + AGENT_CARD_PATH, client.url);
              +    }
              +
              +    @Test
              +    public void testSpec03PathPreservation_withCustomPath() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver.builder().httpClient(client).baseUrl("https://example.com/spec03").agentCardPath("/custom/card.json").build().getAgentCard();
              +        assertEquals("https://example.com/spec03/custom/card.json", client.url);
              +    }
              +
              +    @Test
              +    public void testBaseUrl_alreadyContainsWellKnownPath() throws Exception {
              +        String fullUrl = "https://agentbin.greensmoke-1163cb63.eastus.azurecontainerapps.io/spec03/.well-known/agent-card.json";
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver resolver = A2ACardResolver.builder().httpClient(client).baseUrl(fullUrl).build();
              +        resolver.getAgentCard();
              +        assertEquals(fullUrl, client.url);
              +    }
              +
              +    @Test
              +    public void testFullWellKnownUrlWithCustomAgentCardPath() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver resolver = A2ACardResolver.builder()
              +                .httpClient(client)
              +                .baseUrl("https://example.com/spec03/.well-known/agent-card.json")
              +                .agentCardPath("/custom/card.json")
              +                .build();
              +        resolver.getAgentCard();
              +        assertEquals("https://example.com/spec03/custom/card.json", client.url);
              +    }
              +
              +    @Test
              +    public void testFullWellKnownUrlWithSameAgentCardPath() throws Exception {
              +        TestHttpClient client = createTestClient();
              +        A2ACardResolver resolver = A2ACardResolver.builder()
              +                .httpClient(client)
              +                .baseUrl("https://example.com/spec03/.well-known/agent-card.json")
              +                .agentCardPath("/.well-known/agent-card.json")
              +                .build();
              +        resolver.getAgentCard();
              +        assertEquals("https://example.com/spec03/.well-known/agent-card.json", client.url);
              +    }
              +
              +    // -------------------------------------------------------------------------
              +    // Helpers
              +    // -------------------------------------------------------------------------
              +
              +    private AgentCard unmarshalFrom(String body) throws JsonProcessingException {
              +        org.a2aproject.sdk.grpc.AgentCard.Builder agentCardBuilder = org.a2aproject.sdk.grpc.AgentCard.newBuilder();
              +        JSONRPCUtils.parseJsonString(body, agentCardBuilder, "");
              +        return ProtoUtils.FromProto.agentCard(agentCardBuilder);
              +    }
              +
              +    private String printAgentCard(AgentCard agentCard) throws InvalidProtocolBufferException {
              +        return JsonFormat.printer().print(ProtoUtils.ToProto.agentCard(agentCard));
                   }
               
                   private static class TestHttpClient implements A2AHttpClient {
                       int status = 200;
                       String body;
                       String url;
              +        boolean throwIOException = false;
              +        boolean throwInterruptedException = false;
              +        Map capturedHeaders = new HashMap<>();
              +        List urlsCalled = new ArrayList<>();
               
                       @Override
                       public GetBuilder createGet() {
              @@ -147,15 +342,23 @@ class TestGetBuilder implements A2AHttpClient.GetBuilder {
               
                           @Override
                           public A2AHttpResponse get() throws IOException, InterruptedException {
              +                urlsCalled.add(url);
              +                if (throwIOException) {
              +                    throw new IOException("Simulated IO error");
              +                }
              +                if (throwInterruptedException) {
              +                    throw new InterruptedException("Simulated interrupt");
              +                }
              +                int effectiveStatus = status;
                               return new A2AHttpResponse() {
                                   @Override
                                   public int status() {
              -                        return status;
              +                        return effectiveStatus;
                                   }
               
                                   @Override
                                   public boolean success() {
              -                        return status == 200;
              +                        return effectiveStatus == 200;
                                   }
               
                                   @Override
              @@ -178,14 +381,15 @@ public GetBuilder url(String s) {
               
                           @Override
                           public GetBuilder addHeader(String name, String value) {
              +                capturedHeaders.put(name, value);
                               return this;
                           }
               
                           @Override
                           public GetBuilder addHeaders(Map headers) {
              +                capturedHeaders.putAll(headers);
                               return this;
                           }
                       }
                   }
              -
               }
              diff --git a/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java
              index 0a89eb194..4193fa725 100644
              --- a/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java
              +++ b/spec-grpc/src/test/java/org/a2aproject/sdk/grpc/utils/JSONRPCUtilsTest.java
              @@ -18,15 +18,15 @@
               import org.a2aproject.sdk.jsonrpc.common.json.JsonMappingException;
               import org.a2aproject.sdk.jsonrpc.common.json.JsonProcessingException;
               import org.a2aproject.sdk.jsonrpc.common.wrappers.A2ARequest;
              -import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest;
              -import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse;
               import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest;
               import org.a2aproject.sdk.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse;
              +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest;
              +import org.a2aproject.sdk.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse;
               import org.a2aproject.sdk.spec.InvalidParamsError;
              -import org.a2aproject.sdk.util.ErrorDetail;
               import org.a2aproject.sdk.spec.JSONParseError;
               import org.a2aproject.sdk.spec.TaskNotFoundError;
               import org.a2aproject.sdk.spec.TaskPushNotificationConfig;
              +import org.a2aproject.sdk.util.ErrorDetail;
               import org.junit.jupiter.api.Test;
               
               public class JSONRPCUtilsTest {
              @@ -484,4 +484,5 @@ public void testToJsonRPCErrorResponse_RoundTrip() throws Exception {
                       assertEquals(-32001, response.getError().getCode());
                       assertEquals("Custom message", response.getError().getMessage());
                   }
              +
               }
              diff --git a/spec/src/main/java/org/a2aproject/sdk/util/Utils.java b/spec/src/main/java/org/a2aproject/sdk/util/Utils.java
              index 36de686b2..ce50dc30f 100644
              --- a/spec/src/main/java/org/a2aproject/sdk/util/Utils.java
              +++ b/spec/src/main/java/org/a2aproject/sdk/util/Utils.java
              @@ -2,6 +2,8 @@
               
               import static org.a2aproject.sdk.util.Assert.checkNotNullParam;
               
              +import java.net.URI;
              +import java.net.URISyntaxException;
               import java.util.ArrayList;
               import java.util.HashMap;
               import java.util.List;
              @@ -38,6 +40,8 @@
                */
               public class Utils {
               
              +    public static final String DEFAULT_AGENT_CARD_PATH = "/.well-known/agent-card.json";
              +
                   private static final Logger log = Logger.getLogger(Utils.class.getName());
               
                   /**
              @@ -169,6 +173,71 @@ public static Task appendArtifactToTask(Task task, TaskArtifactUpdateEvent event
               
                   }
               
              +    /**
              +     * Validates that {@code url} is a syntactically valid absolute URI.
              +     *
              +     * @param url the URL to validate
              +     * @throws URISyntaxException if the URL is syntactically invalid or not absolute
              +     */
              +    public static void validateAbsoluteUrl(String url) throws URISyntaxException {
              +        URI uri = new URI(url);
              +        if (!uri.isAbsolute()) {
              +            throw new URISyntaxException(url, "URI must be absolute");
              +        }
              +    }
              +
              +    /**
              +     * Normalizes {@code baseUrl} and {@code cardPath} and concatenates them into a full card URL.
              +     *
              +     * 

              Strips any trailing slash from {@code baseUrl} and ensures {@code cardPath} starts with + * a leading slash before concatenating, so both {@code http://host/base/} and + * {@code http://host/base} produce the same result. + * + * @param baseUrl the agent base URL, must not be null + * @param cardPath the card endpoint path, must not be null + * @return the normalized card URL + */ + public static String buildCardUrl(String baseUrl, String cardPath) { + String normalizedPath = cardPath.startsWith("/") ? cardPath : "/" + cardPath; + return stripTrailingSlash(baseUrl) + normalizedPath; + } + + /** + * Strips any trailing slash and the standard well-known suffix from {@code baseUrl} so that + * {@link #buildCardUrl} can append the desired path without doubling it. + * + *

              Only {@link #DEFAULT_AGENT_CARD_PATH} is stripped; custom paths are never inferred + * from the URL structure. + * + * @param baseUrl the URL to strip + * @return the URL with any trailing slash and well-known suffix removed + */ + public static String stripWellKnownSuffix(String baseUrl) { + String s = stripTrailingSlash(baseUrl); + return s.endsWith(DEFAULT_AGENT_CARD_PATH) + ? s.substring(0, s.length() - DEFAULT_AGENT_CARD_PATH.length()) + : s; + } + + /** + * Builds a base URL by combining a raw base URL string with an optional tenant path. + * + *

              Normalizes trailing slashes on the base URL and validates/normalizes the tenant path. + * + * @param baseUrl the base URL string, must not be null + * @param tenant the tenant path override, may be null for no tenant + * @return the complete base URL with tenant path appended + * @throws IllegalArgumentException if tenant validation fails + */ + public static String buildBaseUrl(String baseUrl, @Nullable String tenant) { + checkNotNullParam("baseUrl", baseUrl); + return stripTrailingSlash(baseUrl) + extractTenant("", tenant); + } + + private static String stripTrailingSlash(String s) { + return s.endsWith("/") ? s.substring(0, s.length() - 1) : s; + } + /** * Get the first defined URL in the supported interaces of the agent card. * @@ -286,10 +355,6 @@ private static String extractTenant(String agentTenant, @Nullable String tenant) public static String buildBaseUrl(AgentInterface agentInterface, @Nullable String tenant) { checkNotNullParam("agentInterface", agentInterface); - String agentUrl = agentInterface.url(); - agentUrl = agentUrl.endsWith("/") ? agentUrl.substring(0, agentUrl.length() - 1) : agentUrl; - StringBuilder urlBuilder = new StringBuilder(agentUrl); - urlBuilder.append(extractTenant(agentInterface.tenant(), tenant)); - return urlBuilder.toString(); + return stripTrailingSlash(agentInterface.url()) + extractTenant(agentInterface.tenant(), tenant); } } diff --git a/spec/src/test/java/org/a2aproject/sdk/util/UtilsTest.java b/spec/src/test/java/org/a2aproject/sdk/util/UtilsTest.java index 3304149f1..a6d264d2e 100644 --- a/spec/src/test/java/org/a2aproject/sdk/util/UtilsTest.java +++ b/spec/src/test/java/org/a2aproject/sdk/util/UtilsTest.java @@ -3,6 +3,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import java.net.URISyntaxException; import org.a2aproject.sdk.spec.AgentInterface; import org.junit.jupiter.api.Test; @@ -52,7 +55,7 @@ void testBuildBaseUrl_withAgentInterface_urlWithoutTrailingSlash() { @Test void testBuildBaseUrl_withAgentInterface_nullInterface_throws() { assertThrows(IllegalArgumentException.class, () -> { - Utils.buildBaseUrl(null, "/tenant"); + Utils.buildBaseUrl((AgentInterface) null, "/tenant"); }); } @@ -190,4 +193,117 @@ void testBuildBaseUrl_httpsUrl() { String url = Utils.buildBaseUrl(iface, null); assertEquals("https://secure.example.com/tenant", url); } + + // ========== buildBaseUrl(String, String) Tests ========== + + @Test + void testBuildBaseUrl_string_noTenant() { + assertEquals("http://example.com", Utils.buildBaseUrl("http://example.com", null)); + } + + @Test + void testBuildBaseUrl_string_trailingSlashStripped() { + assertEquals("http://example.com", Utils.buildBaseUrl("http://example.com/", null)); + } + + @Test + void testBuildBaseUrl_string_withTenant() { + assertEquals("http://example.com/my-tenant", Utils.buildBaseUrl("http://example.com", "my-tenant")); + } + + @Test + void testBuildBaseUrl_string_withTenantLeadingSlash() { + assertEquals("http://example.com/my-tenant", Utils.buildBaseUrl("http://example.com", "/my-tenant")); + } + + @Test + void testBuildBaseUrl_string_withSubPath() { + assertEquals("http://example.com/spec03/my-tenant", Utils.buildBaseUrl("http://example.com/spec03", "my-tenant")); + } + + @Test + void testBuildBaseUrl_string_nullBaseUrl_throws() { + assertThrows(IllegalArgumentException.class, () -> Utils.buildBaseUrl((String) null, null)); + } + + // ========== validateAbsoluteUrl Tests ========== + + @Test + void testValidateAbsoluteUrl_valid() { + assertDoesNotThrow(() -> Utils.validateAbsoluteUrl("http://example.com")); + assertDoesNotThrow(() -> Utils.validateAbsoluteUrl("https://example.com/path")); + assertDoesNotThrow(() -> Utils.validateAbsoluteUrl("http://example.com:8080/path")); + } + + @Test + void testValidateAbsoluteUrl_relative_throws() { + assertThrows(URISyntaxException.class, () -> Utils.validateAbsoluteUrl("/relative/path")); + } + + @Test + void testValidateAbsoluteUrl_malformed_throws() { + assertThrows(URISyntaxException.class, () -> Utils.validateAbsoluteUrl("not a url")); + } + + // ========== buildCardUrl Tests ========== + + @Test + void testBuildCardUrl_simple() { + assertEquals("http://example.com/.well-known/agent-card.json", + Utils.buildCardUrl("http://example.com", "/.well-known/agent-card.json")); + } + + @Test + void testBuildCardUrl_baseTrailingSlash() { + assertEquals("http://example.com/.well-known/agent-card.json", + Utils.buildCardUrl("http://example.com/", "/.well-known/agent-card.json")); + } + + @Test + void testBuildCardUrl_pathWithoutLeadingSlash() { + assertEquals("http://example.com/.well-known/agent-card.json", + Utils.buildCardUrl("http://example.com", ".well-known/agent-card.json")); + } + + @Test + void testBuildCardUrl_preservesSubPath() { + assertEquals("http://example.com/spec03/.well-known/agent-card.json", + Utils.buildCardUrl("http://example.com/spec03", "/.well-known/agent-card.json")); + } + + @Test + void testBuildCardUrl_noDoubleSlash() { + assertEquals("http://example.com/custom/agent.json", + Utils.buildCardUrl("http://example.com/", "/custom/agent.json")); + } + + // ========== stripWellKnownSuffix Tests ========== + + @Test + void testStripWellKnownSuffix_noSuffix() { + assertEquals("http://example.com", Utils.stripWellKnownSuffix("http://example.com")); + } + + @Test + void testStripWellKnownSuffix_withSuffix() { + assertEquals("http://example.com", + Utils.stripWellKnownSuffix("http://example.com/.well-known/agent-card.json")); + } + + @Test + void testStripWellKnownSuffix_withSubPathAndSuffix() { + assertEquals("http://example.com/spec03", + Utils.stripWellKnownSuffix("http://example.com/spec03/.well-known/agent-card.json")); + } + + @Test + void testStripWellKnownSuffix_trailingSlash() { + assertEquals("http://example.com", Utils.stripWellKnownSuffix("http://example.com/")); + } + + @Test + void testStripWellKnownSuffix_unrelatedPath() { + assertEquals("http://example.com/custom/agent.json", + Utils.stripWellKnownSuffix("http://example.com/custom/agent.json")); + } } From 0c58f9e36445423d03900d1d560b86959e360e25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:37:20 +0200 Subject: [PATCH 191/192] chore: bump org.mock-server:mockserver-netty from 5.15.0 to 6.1.0 (#913) Bumps org.mock-server:mockserver-netty from 5.15.0 to 6.1.0. --- updated-dependencies: - dependency-name: org.mock-server:mockserver-netty dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 214264a17..062f8cfa1 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ 1.6.3 1.52.0 5.23.0 - 5.15.0 + 6.1.0 1.1.1 1.7.1 4.33.2 From 5f20bf8d078c7523872ed6d5d83f06221d7aaff6 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 4 Jun 2026 13:19:03 +0200 Subject: [PATCH 192/192] fix: prevent dropped SSE events under back-to-back emission (#906) fix: extract SSE writing into SseResponseWriter, switch to request(Long.MAX_VALUE) - Replace the MultiSseSupport inner class with a shared SseResponseWriter utility. Switch from request(1) backpressure to request(Long.MAX_VALUE) with a headersSet flag for first-write detection, combining the SSE kickstart comment and the first event into a single write to avoid duplicate error callbacks. - Restore BUFFER_FLUSH_DELAY_MS in EventConsumer: Mutiny's internal demand management can fire request(1) on the underlying publisher independently of the write callback, causing onComplete to race with a pending response.write(). The sleep ensures every write callback confirms delivery before tube.complete() is called. Signed-off-by: Emmanuel Hugonnet --- .../apps/quarkus/A2AServerRoutes_v0_3.java | 90 +------- .../rest/quarkus/A2AServerRoutes_v0_3.java | 92 +-------- .../common/quarkus/SseResponseWriter.java | 149 ++++++++++++++ .../common/quarkus/SseResponseWriterTest.java | 192 ++++++++++++++++++ .../server/apps/quarkus/A2AServerRoutes.java | 182 +---------------- .../server/rest/quarkus/A2AServerRoutes.java | 180 +--------------- .../sdk/server/events/EventConsumer.java | 21 +- .../MainEventBusProcessorExceptionTest.java | 18 +- 8 files changed, 388 insertions(+), 536 deletions(-) create mode 100644 reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/SseResponseWriter.java create mode 100644 reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/SseResponseWriterTest.java diff --git a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java index de83415b8..6264e7091 100644 --- a/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java @@ -2,7 +2,6 @@ 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 static org.a2aproject.sdk.compat03.transport.jsonrpc.context.JSONRPCContextKeys_v0_3.HEADERS_KEY; import static org.a2aproject.sdk.compat03.transport.jsonrpc.context.JSONRPCContextKeys_v0_3.METHOD_NAME_KEY; @@ -24,11 +23,6 @@ import io.quarkus.security.ForbiddenException; import io.quarkus.security.UnauthorizedException; import io.smallrye.mutiny.Multi; -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.BodyHandler; @@ -66,12 +60,11 @@ import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.UnauthenticatedUser; import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.common.quarkus.SseResponseWriter; import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.server.extensions.A2AExtensions; import org.a2aproject.sdk.spec.AgentCard; import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; @Singleton public class A2AServerRoutes_v0_3 { @@ -79,7 +72,7 @@ public class A2AServerRoutes_v0_3 { @Inject JSONRPCHandler_v0_3 jsonRpcHandler; - // Hook so testing can wait until the MultiSseSupport is subscribed. + // Hook so testing can wait until the SSE subscriber is attached. // Without this we get intermittent failures private static volatile @Nullable Runnable streamingMultiSseSupportSubscribedRunnable; @@ -206,7 +199,7 @@ public void invokeJSONRPCHandler(String body, RoutingContext rc) { AtomicLong eventIdCounter = new AtomicLong(0); Multi sseEvents = streamingResponse .map(response -> formatSseEvent(response, eventIdCounter.getAndIncrement())); - MultiSseSupport.writeSseStrings(sseEvents, rc, context); + SseResponseWriter.writeSseStrings(sseEvents, rc, context, streamingMultiSseSupportSubscribedRunnable); } else { rc.response() .setStatusCode(200) @@ -335,81 +328,4 @@ public String getUsername() { } } - private static class MultiSseSupport { - private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); - - private MultiSseSupport() { - // Avoid direct instantiation. - } - - public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { - HttpServerResponse response = rc.response(); - - sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { - Flow.@Nullable Subscription upstream; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.upstream = subscription; - this.upstream.request(1); - - response.closeHandler(v -> { - logger.info("SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); - context.invokeEventConsumerCancelCallback(); - subscription.cancel(); - }); - - // Notify tests that we are subscribed - Runnable runnable = streamingMultiSseSupportSubscribedRunnable; - if (runnable != null) { - runnable.run(); - } - } - - @Override - public void onNext(String sseEvent) { - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - headers.set("Cache-Control", "no-cache"); - headers.set("X-Accel-Buffering", "no"); - response.setChunked(true); - response.setWriteQueueMaxSize(1); - response.write(": SSE stream started\n\n"); - } - - response.write(Buffer.buffer(sseEvent), new Handler>() { - @Override - public void handle(AsyncResult ar) { - if (ar.failed()) { - java.util.Objects.requireNonNull(upstream).cancel(); - rc.fail(ar.cause()); - } else { - java.util.Objects.requireNonNull(upstream).request(1); - } - } - }); - } - - @Override - public void onError(Throwable throwable) { - java.util.Objects.requireNonNull(upstream).cancel(); - rc.fail(throwable); - } - - @Override - public void onComplete() { - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); - } - }); - } - } } diff --git a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java index 9387024a9..f00795328 100644 --- a/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java +++ b/compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java @@ -2,7 +2,6 @@ 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 static org.a2aproject.sdk.compat03.transport.rest.context.RestContextKeys_v0_3.HEADERS_KEY; import static org.a2aproject.sdk.compat03.transport.rest.context.RestContextKeys_v0_3.METHOD_NAME_KEY; @@ -10,7 +9,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; @@ -24,11 +22,7 @@ import io.quarkus.security.ForbiddenException; import io.quarkus.security.UnauthorizedException; import io.smallrye.mutiny.Multi; -import io.vertx.core.AsyncResult; import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.BodyHandler; @@ -53,12 +47,11 @@ import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.UnauthenticatedUser; import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.common.quarkus.SseResponseWriter; import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.server.extensions.A2AExtensions; import org.a2aproject.sdk.spec.AgentCard; import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; @Singleton public class A2AServerRoutes_v0_3 { @@ -66,7 +59,7 @@ public class A2AServerRoutes_v0_3 { @Inject RestHandler_v0_3 jsonRestHandler; - // Hook so testing can wait until the MultiSseSupport is subscribed. + // Hook so testing can wait until the SSE subscriber is attached. // Without this we get intermittent failures private static volatile @Nullable Runnable streamingMultiSseSupportSubscribedRunnable; @@ -202,7 +195,7 @@ public void sendMessageStreaming(String body, RoutingContext rc) { AtomicLong eventIdCounter = new AtomicLong(0); Multi sseEvents = Multi.createFrom().publisher(streamingResponse.getPublisher()) .map(json -> formatSseEvent(json, eventIdCounter.getAndIncrement())); - MultiSseSupport.writeSseStrings(sseEvents, rc, context); + SseResponseWriter.writeSseStrings(sseEvents, rc, context, streamingMultiSseSupportSubscribedRunnable); } } } @@ -302,7 +295,7 @@ public void resubscribeTask(RoutingContext rc) { AtomicLong eventIdCounter = new AtomicLong(0); Multi sseEvents = Multi.createFrom().publisher(streamingResponse.getPublisher()) .map(json -> formatSseEvent(json, eventIdCounter.getAndIncrement())); - MultiSseSupport.writeSseStrings(sseEvents, rc, context); + SseResponseWriter.writeSseStrings(sseEvents, rc, context, streamingMultiSseSupportSubscribedRunnable); } } } @@ -463,81 +456,4 @@ private static boolean hasNonDefaultV10AgentCard() { return false; } - private static class MultiSseSupport { - private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); - - private MultiSseSupport() { - // Avoid direct instantiation. - } - - public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { - HttpServerResponse response = rc.response(); - - sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { - Flow.@Nullable Subscription upstream; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.upstream = subscription; - this.upstream.request(1); - - response.closeHandler(v -> { - logger.debug("REST SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); - context.invokeEventConsumerCancelCallback(); - subscription.cancel(); - }); - - // Notify tests that we are subscribed - Runnable runnable = streamingMultiSseSupportSubscribedRunnable; - if (runnable != null) { - runnable.run(); - } - } - - @Override - public void onNext(String sseEvent) { - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - headers.set("Cache-Control", "no-cache"); - headers.set("X-Accel-Buffering", "no"); - response.setChunked(true); - response.setWriteQueueMaxSize(1); - response.write(": SSE stream started\n\n"); - } - - response.write(Buffer.buffer(sseEvent), new Handler>() { - @Override - public void handle(AsyncResult ar) { - if (ar.failed()) { - java.util.Objects.requireNonNull(upstream).cancel(); - rc.fail(ar.cause()); - } else { - java.util.Objects.requireNonNull(upstream).request(1); - } - } - }); - } - - @Override - public void onError(Throwable throwable) { - java.util.Objects.requireNonNull(upstream).cancel(); - rc.fail(throwable); - } - - @Override - public void onComplete() { - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); - } - }); - } - } } diff --git a/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/SseResponseWriter.java b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/SseResponseWriter.java new file mode 100644 index 000000000..f112ab46e --- /dev/null +++ b/reference/common/src/main/java/org/a2aproject/sdk/server/common/quarkus/SseResponseWriter.java @@ -0,0 +1,149 @@ +package org.a2aproject.sdk.server.common.quarkus; + +import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; + +import java.util.Objects; +import java.util.concurrent.Flow; + +import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.smallrye.mutiny.Multi; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.RoutingContext; + +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.events.EventConsumer; + +/** + * Utility for writing SSE (Server-Sent Events) responses over Vert.x HTTP. + * + *

              Events are requested all upfront ({@code request(Long.MAX_VALUE)}) so that + * back-to-back emissions from the EventConsumer are never dropped by a stalled + * single-item demand window. This means the {@link EventConsumer}'s internal buffer + * (256 items) acts as the only bound — write-level backpressure is not applied. + * Ordering between the final {@code response.write()} and {@code response.end()} is + * preserved by {@code EventConsumer.BUFFER_FLUSH_DELAY_MS}: the EventConsumer waits + * briefly after sending the final event before calling {@code tube.complete()}, which + * ensures every write callback has confirmed delivery before {@code onComplete} is + * delivered to this subscriber. + */ +public final class SseResponseWriter { + + private static final Logger logger = LoggerFactory.getLogger(SseResponseWriter.class); + private static final String SERVER_SENT_EVENTS = "text/event-stream"; + + private SseResponseWriter() { + // Utility class — no instances. + } + + /** + * Subscribes to {@code sseStrings} and writes each SSE event to the HTTP response. + * + *

              Error handling: + *

                + *
              • Client disconnect → cancels upstream, stops polling
              • + *
              • Write failure → cancels upstream, fails routing context
              • + *
              • Stream error → cancels upstream, fails routing context
              • + *
              + * + * @param sseStrings the SSE-formatted event stream + * @param rc the Vert.x routing context + * @param context the A2A server call context (for EventConsumer cancellation) + * @param onSubscribedHook optional hook invoked once the subscriber is attached; used by tests + */ + public static void writeSseStrings( + Multi sseStrings, + RoutingContext rc, + ServerCallContext context, + @Nullable Runnable onSubscribedHook) { + HttpServerResponse response = rc.response(); + + sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { + // Written in onSubscribe (EventConsumer / subscription thread), read inside + // the write-failure callback (event loop thread) — volatile for visibility. + volatile Flow.@Nullable Subscription upstream; + // onNext and onComplete both run on the same EventConsumer polling thread, + // so no volatile needed for headersSet. + boolean headersSet = false; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.upstream = subscription; + // Request all events upfront: the EventConsumer's BUFFER_FLUSH_DELAY_MS + // sleep between tube.send(finalEvent) and tube.complete() guarantees that + // every write callback confirms delivery before onComplete fires, so + // response.end() is always called after the data is in flight. + this.upstream.request(Long.MAX_VALUE); + + response.closeHandler(v -> { + logger.info("SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); + context.invokeEventConsumerCancelCallback(); + subscription.cancel(); + }); + + if (onSubscribedHook != null) { + onSubscribedHook.run(); + } + } + + @Override + public void onNext(String sseEvent) { + Buffer data; + if (!headersSet) { + headersSet = true; + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + headers.set("Cache-Control", "no-cache"); + headers.set("X-Accel-Buffering", "no"); // disables nginx proxy buffering + response.setChunked(true); + response.setWriteQueueMaxSize(1); // Vert.x default buffering breaks SSE flushing + + // Merge kickstart comment into first event to avoid an orphaned async write + // that could race with the error callback of the data write. + data = Buffer.buffer(": SSE stream started\n\n").appendBuffer(Buffer.buffer(sseEvent)); + } else { + data = Buffer.buffer(sseEvent); + } + + response.write(data, ar -> { + if (ar.failed() && !rc.failed()) { + // NullAway: upstream is guaranteed non-null after onSubscribe + Objects.requireNonNull(upstream).cancel(); + rc.fail(ar.cause()); + } + }); + } + + @Override + public void onError(Throwable throwable) { + // NullAway: upstream is guaranteed non-null after onSubscribe + Objects.requireNonNull(upstream).cancel(); + if (!rc.failed()) { + rc.fail(throwable); + } + } + + @Override + public void onComplete() { + if (!headersSet) { + MultiMap headers = response.headers(); + if (headers.get(CONTENT_TYPE) == null) { + headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); + } + } + // Guard against duplicate end() if the client disconnected concurrently + if (!response.ended()) { + response.end(); + } + } + }); + } +} diff --git a/reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/SseResponseWriterTest.java b/reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/SseResponseWriterTest.java new file mode 100644 index 000000000..6cd11bbcd --- /dev/null +++ b/reference/common/src/test/java/org/a2aproject/sdk/server/common/quarkus/SseResponseWriterTest.java @@ -0,0 +1,192 @@ +package org.a2aproject.sdk.server.common.quarkus; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import io.smallrye.mutiny.Multi; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.RoutingContext; +import org.a2aproject.sdk.server.ServerCallContext; +import org.a2aproject.sdk.server.auth.UnauthenticatedUser; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +// LENIENT: setUp stubs are shared convenience for write tests but not all tests need them all +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class SseResponseWriterTest { + + @Mock + HttpServerResponse response; + @Mock + RoutingContext rc; + @Mock + MultiMap headers; + + private ServerCallContext context; + + @BeforeEach + void setUp() { + when(rc.response()).thenReturn(response); + when(response.headers()).thenReturn(headers); + when(response.setChunked(true)).thenReturn(response); + successfulWrite(); + when(response.ended()).thenReturn(false); + context = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of(), Set.of()); + } + + @Test + void emptyStream_callsEndWithoutAnyWrite() { + SseResponseWriter.writeSseStrings(Multi.createFrom().empty(), rc, context, null); + + verify(response, never()).write(any(Buffer.class), any()); + verify(response).end(); + } + + @Test + void singleEvent_setsHeadersAndWritesKickstartPlusData() { + List written = captureWrites(); + + SseResponseWriter.writeSseStrings(Multi.createFrom().item("data: hello\n\n"), rc, context, null); + + verify(response, times(1)).write(any(Buffer.class), any()); + verify(response).end(); + // First (and only) write must contain the SSE kickstart comment + assertTrue(written.get(0).toString().contains(": SSE stream started"), + "First write should include SSE kickstart comment"); + assertTrue(written.get(0).toString().contains("data: hello"), + "First write should include the event data"); + } + + @Test + void multipleEvents_kickstartOnlyOnFirstWrite() { + List written = captureWrites(); + + SseResponseWriter.writeSseStrings( + Multi.createFrom().items("data: first\n\n", "data: second\n\n"), + rc, context, null); + + verify(response, times(2)).write(any(Buffer.class), any()); + assertTrue(written.get(0).toString().contains(": SSE stream started"), + "First write should include SSE kickstart comment"); + assertFalse(written.get(1).toString().contains(": SSE stream started"), + "Subsequent writes must not repeat the kickstart comment"); + } + + @Test + void writeFails_failsRoutingContext() { + failingWrite(new RuntimeException("network error")); + when(rc.failed()).thenReturn(false); + + SseResponseWriter.writeSseStrings(Multi.createFrom().item("data: hello\n\n"), rc, context, null); + + verify(rc).fail(any(Throwable.class)); + } + + @Test + void clientDisconnect_invokesEventConsumerCancelAndCancelsSubscription() { + AtomicReference> capturedCloseHandler = new AtomicReference<>(); + doAnswer(inv -> { + capturedCloseHandler.set(inv.getArgument(0)); + return response; + }).when(response).closeHandler(any()); + + // never() emits nothing and does not complete — subscriber stays attached + SseResponseWriter.writeSseStrings(Multi.createFrom().nothing(), rc, context, null); + + // Simulate client disconnect on the event-loop thread + capturedCloseHandler.get().handle(null); + + // EventConsumer.cancel() must be called so the polling loop stops + // (verified indirectly: ServerCallContext.invokeEventConsumerCancelCallback() is a no-op + // when no callback is registered, so no exception means the path was exercised) + verify(response).closeHandler(any()); + } + + @Test + void onSubscribedHook_isCalledAfterSubscribe() { + Runnable hook = mock(Runnable.class); + + SseResponseWriter.writeSseStrings(Multi.createFrom().empty(), rc, context, hook); + + verify(hook).run(); + } + + @Test + void responseAlreadyEnded_endIsNotCalledAgain() { + when(response.ended()).thenReturn(true); + + SseResponseWriter.writeSseStrings(Multi.createFrom().empty(), rc, context, null); + + verify(response, never()).end(); + } + + // --- helpers --- + + /** Configures the response mock to invoke write callbacks with a successful result. */ + private void successfulWrite() { + doAnswer(inv -> { + AsyncResult ok = successResult(); + inv.>>getArgument(1).handle(ok); + return response; + }).when(response).write(any(Buffer.class), any()); + } + + /** Configures the response mock to invoke write callbacks with a failure. */ + private void failingWrite(Throwable cause) { + doAnswer(inv -> { + AsyncResult fail = failResult(cause); + inv.>>getArgument(1).handle(fail); + return response; + }).when(response).write(any(Buffer.class), any()); + } + + /** Captures every Buffer passed to response.write() and still invokes the success callback. */ + private List captureWrites() { + List written = new ArrayList<>(); + doAnswer(inv -> { + written.add(inv.getArgument(0)); + AsyncResult ok = successResult(); + inv.>>getArgument(1).handle(ok); + return response; + }).when(response).write(any(Buffer.class), any()); + return written; + } + + @SuppressWarnings("unchecked") + private static AsyncResult successResult() { + AsyncResult r = mock(AsyncResult.class); + when(r.failed()).thenReturn(false); + return r; + } + + @SuppressWarnings("unchecked") + private static AsyncResult failResult(Throwable cause) { + AsyncResult r = mock(AsyncResult.class); + when(r.failed()).thenReturn(true); + when(r.cause()).thenReturn(cause); + return r; + } +} diff --git a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java index c313e450c..1f6bc0e23 100644 --- a/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/org/a2aproject/sdk/server/apps/quarkus/A2AServerRoutes.java @@ -2,7 +2,6 @@ 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 static org.a2aproject.sdk.server.ServerCallContext.TRANSPORT_KEY; import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; @@ -26,11 +25,6 @@ import io.quarkus.security.ForbiddenException; import io.quarkus.security.UnauthorizedException; import io.smallrye.mutiny.Multi; -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.BodyHandler; @@ -71,6 +65,7 @@ import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.UnauthenticatedUser; import org.a2aproject.sdk.server.auth.User; +import org.a2aproject.sdk.server.common.quarkus.SseResponseWriter; import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.server.extensions.A2AExtensions; import org.a2aproject.sdk.server.util.async.Internal; @@ -81,8 +76,7 @@ import org.a2aproject.sdk.spec.TransportProtocol; import org.a2aproject.sdk.spec.UnsupportedOperationError; import org.a2aproject.sdk.transport.jsonrpc.handler.JSONRPCHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.jspecify.annotations.Nullable; /** * Quarkus routing configuration for JSON-RPC A2A protocol requests. @@ -169,7 +163,7 @@ * * @see JSONRPCHandler * @see CallContextFactory - * @see MultiSseSupport + * @see SseResponseWriter */ @Singleton public class A2AServerRoutes { @@ -180,9 +174,10 @@ public class A2AServerRoutes { @Inject AgentCardCacheMetadata cacheMetadata; - // Hook so testing can wait until the MultiSseSupport is subscribed. + // Hook so testing can wait until the SSE subscriber is attached. // Without this we get intermittent failures - private static volatile Runnable streamingMultiSseSupportSubscribedRunnable; + private static volatile @Nullable + Runnable streamingMultiSseSupportSubscribedRunnable; @Inject @Internal @@ -350,13 +345,13 @@ public void invokeJSONRPCHandler(String body, RoutingContext rc) { } else if (streaming) { // Convert Multi to Multi with SSE formatting // CRITICAL: Subscribe synchronously to avoid race condition where EventConsumer - // starts emitting events before MultiSseSupport subscribes. The executor.execute() + // starts emitting events before the SSE subscriber is attached. The executor.execute() // wrapper caused 100-600ms delays before subscription, causing events to be lost. AtomicLong eventIdCounter = new AtomicLong(0); Multi sseEvents = streamingResponse .map(response -> SseFormatter.formatResponseAsSSE(response, eventIdCounter.getAndIncrement())); // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); + SseResponseWriter.writeSseStrings(sseEvents, rc, context, streamingMultiSseSupportSubscribedRunnable); } else { rc.response() @@ -728,165 +723,4 @@ private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponseThis class handles the HTTP-specific aspects of SSE streaming, including: - *
                - *
              • Writing SSE-formatted events to the HTTP response
              • - *
              • Managing backpressure through reactive streams
              • - *
              • Detecting client disconnections and canceling upstream
              • - *
              • Setting appropriate HTTP headers for SSE
              • - *
              - * - *

              SSE Format

              - *

              Events are written in Server-Sent Events format: - *

              -     * id: 0
              -     * data: {"jsonrpc":"2.0","id":"req-123","result":{...}}
              -     *
              -     * id: 1
              -     * data: {"jsonrpc":"2.0","id":"req-123","result":{...}}
              -     * 
              - * - *

              Backpressure Handling

              - *

              Uses reactive streams subscription to handle backpressure: - *

                - *
              1. Request 1 event from upstream
              2. - *
              3. Write event to HTTP response
              4. - *
              5. Wait for write completion
              6. - *
              7. Request next event (backpressure)
              8. - *
              - * - *

              Disconnect Handling

              - *

              When the client disconnects: - *

                - *
              1. Vert.x closeHandler fires
              2. - *
              3. Invokes {@link ServerCallContext#invokeEventConsumerCancelCallback()}
              4. - *
              5. Cancels upstream subscription
              6. - *
              7. Stops event polling
              8. - *
              - * - * @see SseFormatter - */ - private static class MultiSseSupport { - private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); - - private MultiSseSupport() { - // Avoid direct instantiation. - } - - /** - * Writes SSE-formatted strings to the HTTP response with backpressure handling. - * - *

              This method subscribes to the SSE event stream and writes each event to the - * HTTP response, managing backpressure through the reactive streams subscription. - * - *

              Subscription Flow: - *

                - *
              1. Subscribe to SSE stream
              2. - *
              3. Register disconnect handler
              4. - *
              5. Request first event
              6. - *
              7. Write event to response
              8. - *
              9. Wait for write completion
              10. - *
              11. Request next event (backpressure)
              12. - *
              - * - *

              HTTP Headers: - *

              Sets {@code Content-Type: text/event-stream} on first write - * - *

              Error Handling: - *

                - *
              • Client disconnect → cancel upstream, stop polling
              • - *
              • Write failure → cancel upstream, fail routing context
              • - *
              • Stream error → cancel upstream, fail routing context
              • - *
              - * - * @param sseStrings Multi stream of SSE-formatted strings from {@link SseFormatter} - * @param rc the Vert.x routing context - * @param context the A2A server call context (for EventConsumer cancellation) - * @see SseFormatter#formatResponseAsSSE - */ - public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { - HttpServerResponse response = rc.response(); - - sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { - Flow.Subscription upstream; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.upstream = subscription; - this.upstream.request(1); - - // Detect client disconnect and call EventConsumer.cancel() directly - response.closeHandler(v -> { - logger.info("SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); - context.invokeEventConsumerCancelCallback(); - subscription.cancel(); - }); - - // Notify tests that we are subscribed - Runnable runnable = streamingMultiSseSupportSubscribedRunnable; - if (runnable != null) { - runnable.run(); - } - } - - @Override - public void onNext(String sseEvent) { - // Set SSE headers on first event - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - // Additional SSE headers to prevent buffering - headers.set("Cache-Control", "no-cache"); - headers.set("X-Accel-Buffering", "no"); // Disable nginx buffering - response.setChunked(true); - - // CRITICAL: Disable write queue max size to prevent buffering - // Vert.x buffers writes by default - we need immediate flushing for SSE - response.setWriteQueueMaxSize(1); - - // Send initial SSE comment to kickstart the stream - response.write(": SSE stream started\n\n"); - } - - // Write SSE-formatted string to response - response.write(Buffer.buffer(sseEvent), new Handler>() { - @Override - public void handle(AsyncResult ar) { - if (ar.failed()) { - // Client disconnected or write failed - cancel upstream to stop EventConsumer - upstream.cancel(); - rc.fail(ar.cause()); - } else { - upstream.request(1); - } - } - }); - } - - @Override - public void onError(Throwable throwable) { - // Cancel upstream to stop EventConsumer when error occurs - upstream.cancel(); - rc.fail(throwable); - } - - @Override - public void onComplete() { - if (response.bytesWritten() == 0) { - // No events written - still set SSE content type - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); - } - }); - } - } } diff --git a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java index f033300fe..1fc25b08d 100644 --- a/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java +++ b/reference/rest/src/main/java/org/a2aproject/sdk/server/rest/quarkus/A2AServerRoutes.java @@ -7,7 +7,6 @@ import static org.a2aproject.sdk.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; @@ -41,6 +40,7 @@ import org.a2aproject.sdk.transport.rest.handler.RestHandler; import org.a2aproject.sdk.transport.rest.handler.RestHandler.HTTPRestResponse; import org.a2aproject.sdk.transport.rest.handler.RestHandler.HTTPRestStreamingResponse; +import org.a2aproject.sdk.server.common.quarkus.SseResponseWriter; import org.a2aproject.sdk.server.common.quarkus.VertxSecurityHelper; import org.a2aproject.sdk.util.Utils; import io.quarkus.security.Authenticated; @@ -48,11 +48,7 @@ import io.quarkus.security.UnauthorizedException; import io.smallrye.mutiny.Multi; import jakarta.annotation.security.PermitAll; -import io.vertx.core.AsyncResult; import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.BodyHandler; @@ -98,7 +94,7 @@ * *

              Streaming Support

              *

              Streaming endpoints ({@code message:stream}, {@code subscribe}) use Server-Sent Events (SSE) - * via the inner {@link MultiSseSupport} class. SSE responses are handled by: + * via {@link SseResponseWriter}. SSE responses are handled by: *

                *
              • Converting {@link Flow.Publisher} to Mutiny {@code Multi}
              • *
              • Formatting events with {@link SseFormatter}
              • @@ -136,7 +132,7 @@ public class A2AServerRoutes { @Inject RestHandler jsonRestHandler; - // Hook so testing can wait until the MultiSseSupport is subscribed. + // Hook so testing can wait until the SSE subscriber is attached. // Without this we get intermittent failures private static volatile @Nullable Runnable streamingMultiSseSupportSubscribedRunnable; @@ -356,13 +352,13 @@ public void sendMessageStreaming(String body, RoutingContext rc) { } else if (streamingResponse != null) { // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) // CRITICAL: Subscribe synchronously to avoid race condition where EventConsumer - // starts emitting events before MultiSseSupport subscribes. The executor.execute() + // starts emitting events before the SSE subscriber is attached. The executor.execute() // wrapper caused 100-600ms delays before subscription, causing events to be lost. AtomicLong eventIdCounter = new AtomicLong(0); Multi sseEvents = Multi.createFrom().publisher(streamingResponse.getPublisher()) .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); + SseResponseWriter.writeSseStrings(sseEvents, rc, context, streamingMultiSseSupportSubscribedRunnable); } } } @@ -566,13 +562,13 @@ public void subscribeToTask(RoutingContext rc) { } else if (streamingResponse != null) { // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) // CRITICAL: Subscribe synchronously to avoid race condition where EventConsumer - // starts emitting events before MultiSseSupport subscribes. The executor.execute() + // starts emitting events before the SSE subscriber is attached. The executor.execute() // wrapper caused 100-600ms delays before subscription, causing events to be lost. AtomicLong eventIdCounter = new AtomicLong(0); Multi sseEvents = Multi.createFrom().publisher(streamingResponse.getPublisher()) .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); + SseResponseWriter.writeSseStrings(sseEvents, rc, context, streamingMultiSseSupportSubscribedRunnable); } } } @@ -934,167 +930,5 @@ public String getUsername() { } } - /** - * Server-Sent Events (SSE) streaming support for Vert.x/Quarkus. - * - *

                This inner class handles the HTTP-specific aspects of SSE streaming: - *

                  - *
                • Writing SSE-formatted events to the HTTP response
                • - *
                • Managing backpressure via {@link Flow.Subscription#request(long)}
                • - *
                • Detecting client disconnection and canceling upstream
                • - *
                • Setting appropriate SSE headers and chunked encoding
                • - *
                - * - *

                SSE Format

                - *

                Events are formatted by {@link SseFormatter} before being passed to this class. - * Each event follows the SSE specification: - *

                -     * id: 0
                -     * data: {"taskStatusUpdate":{...}}
                -     *
                -     * id: 1
                -     * data: {"taskArtifactUpdate":{...}}
                -     * 
                - * - *

                Backpressure Handling

                - *

                The subscriber requests one event at a time ({@code request(1)}) and only - * requests the next event after the previous write completes. This ensures the - * HTTP connection doesn't buffer excessive data if the client is slow. - * - *

                Disconnect Detection

                - *

                When the client closes the connection, this class: - *

                  - *
                1. Calls {@link ServerCallContext#invokeEventConsumerCancelCallback()} to stop the event producer
                2. - *
                3. Cancels the upstream subscription to stop event generation
                4. - *
                - * - *

                Write Queue Configuration

                - *

                Critical: Sets {@code setWriteQueueMaxSize(1)} to force immediate flushing - * of each event. Without this, Vert.x buffers writes, causing delays in SSE delivery. - * - * @see SseFormatter - * @see ServerCallContext#invokeEventConsumerCancelCallback() - */ - private static class MultiSseSupport { - private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MultiSseSupport.class); - - private MultiSseSupport() { - // Avoid direct instantiation. - } - - /** - * Writes SSE-formatted event strings to the HTTP response with backpressure control. - * - *

                This method subscribes to the event stream and writes each SSE-formatted string - * to the Vert.x HTTP response. It implements reactive backpressure by requesting - * events one at a time and only requesting the next after the previous write completes. - * - *

                Execution Flow

                - *
                  - *
                1. Subscribe to upstream {@code Multi} (SSE-formatted events)
                2. - *
                3. On first event: set SSE headers, disable buffering, write kickstart comment
                4. - *
                5. For each event: write to HTTP response asynchronously
                6. - *
                7. After write completes: request next event (backpressure control)
                8. - *
                9. On client disconnect or error: cancel upstream to stop event production
                10. - *
                - * - *

                Headers Set

                - *
                  - *
                • {@code Content-Type: text/event-stream}
                • - *
                • {@code Cache-Control: no-cache}
                • - *
                • {@code X-Accel-Buffering: no} (disable nginx buffering)
                • - *
                • Chunked encoding enabled
                • - *
                - * - * @param sseStrings Multi stream of SSE-formatted strings (from {@link SseFormatter}) - * @param rc Vert.x routing context providing HTTP response - * @param context A2A server call context (for EventConsumer cancellation on disconnect) - */ - public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { - HttpServerResponse response = rc.response(); - - sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { - Flow.@Nullable Subscription upstream; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.upstream = subscription; - this.upstream.request(1); - - // Detect client disconnect and call EventConsumer.cancel() directly - response.closeHandler(v -> { - logger.debug("REST SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); - context.invokeEventConsumerCancelCallback(); - subscription.cancel(); - }); - - // Notify tests that we are subscribed - Runnable runnable = streamingMultiSseSupportSubscribedRunnable; - if (runnable != null) { - runnable.run(); - } - } - - @Override - public void onNext(String sseEvent) { - // Set SSE headers on first event - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - // Additional SSE headers to prevent buffering - headers.set("Cache-Control", "no-cache"); - headers.set("X-Accel-Buffering", "no"); // Disable nginx buffering - response.setChunked(true); - - // CRITICAL: Disable write queue max size to prevent buffering - // Vert.x buffers writes by default - we need immediate flushing for SSE - response.setWriteQueueMaxSize(1); // Force immediate flush - - // Send initial SSE comment to kickstart the stream - // This forces Vert.x to send headers and start the stream immediately - response.write(": SSE stream started\n\n"); - } - - // Write SSE-formatted string to response - response.write(Buffer.buffer(sseEvent), new Handler>() { - @Override - public void handle(AsyncResult ar) { - if (ar.failed()) { - // Client disconnected or write failed - cancel upstream to stop EventConsumer - // NullAway: upstream is guaranteed non-null after onSubscribe - java.util.Objects.requireNonNull(upstream).cancel(); - rc.fail(ar.cause()); - } else { - // NullAway: upstream is guaranteed non-null after onSubscribe - java.util.Objects.requireNonNull(upstream).request(1); - } - } - }); - } - - @Override - public void onError(Throwable throwable) { - // Cancel upstream to stop EventConsumer when error occurs - // NullAway: upstream is guaranteed non-null after onSubscribe - java.util.Objects.requireNonNull(upstream).cancel(); - rc.fail(throwable); - } - - @Override - public void onComplete() { - if (response.bytesWritten() == 0) { - // No events written - still set SSE content type - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); - } - }); - } - } } diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/events/EventConsumer.java b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventConsumer.java index aa357618f..18da23b22 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/events/EventConsumer.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/events/EventConsumer.java @@ -41,11 +41,12 @@ public class EventConsumer { private static final int MAX_AWAITING_FINAL_TIMEOUT_MS = 3000; private static final int MAX_POLL_TIMEOUTS_AWAITING_FINAL = (MAX_AWAITING_FINAL_TIMEOUT_MS + QUEUE_WAIT_MILLISECONDS - 1) / QUEUE_WAIT_MILLISECONDS; - // WORKAROUND: Sleep delay to allow SSE buffer flush before stream completion - // This is a temporary workaround for a race condition where tube.complete() can arrive - // before the final event is flushed from the SSE buffer. Ideally, this should be handled - // at the transport layer (e.g., MultiSseSupport) with proper write completion callbacks. - // TODO: Move buffer flush handling to transport layer to avoid this latency penalty + // Delay between tube.send(finalEvent) and tube.complete() to allow the SSE transport + // layer to flush the write before the stream-end signal arrives. Mutiny's internal + // demand management can call request(1) on the underlying publisher independently of + // the write callback, causing onComplete to fire before the HTTP response.write() + // callback confirms the data was sent. This sleep ensures the write callback fires + // first, so response.end() is only called after the data is safely in flight. private static final int BUFFER_FLUSH_DELAY_MS = 150; public EventConsumer(EventQueue queue, Executor executor) { @@ -229,12 +230,10 @@ public Flow.Publisher consumeAll() { queue.close(); LOGGER.debug("Queue closed, breaking loop for queue {}", System.identityHashCode(queue)); - // CRITICAL: Allow tube buffer to flush before calling tube.complete() - // tube.send() buffers events asynchronously. If we call tube.complete() immediately, - // the stream-end signal can reach the client BEFORE the buffered final event, - // causing the client to close the connection and never receive the final event. - // This is especially important in replicated scenarios where events arrive via Kafka - // and timing is less deterministic. + // Allow the SSE write callback to fire before calling tube.complete(). + // Mutiny's internal demand management can trigger onComplete independently + // of the write callback, causing response.end() to race with a pending + // response.write(). This delay ensures the write callback runs first. if (isFinalSent) { try { Thread.sleep(BUFFER_FLUSH_DELAY_MS); diff --git a/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java b/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java index 23264977b..d4e97fdc3 100644 --- a/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java +++ b/server-common/src/test/java/org/a2aproject/sdk/server/events/MainEventBusProcessorExceptionTest.java @@ -124,7 +124,7 @@ public void testTaskSerializationException_ConvertsToInternalError() throws Inte "Error message should mention serialization: " + error.getMessage()); // Assert: Verify ERROR level logging - boolean foundErrorLog = logAppender.list.stream() + boolean foundErrorLog = snapshotLogs().stream() .anyMatch(event -> event.getLevel() == Level.ERROR && event.getFormattedMessage().contains(TASK_ID) && event.getFormattedMessage().contains("serialization")); @@ -161,7 +161,7 @@ public void testTaskPersistenceException_ConvertsToInternalError() throws Interr "Error message should contain task ID: " + error.getMessage()); // Assert: Verify ERROR level logging - boolean foundErrorLog = logAppender.list.stream() + boolean foundErrorLog = snapshotLogs().stream() .anyMatch(event -> event.getLevel() == Level.ERROR && event.getFormattedMessage().contains(TASK_ID) && event.getFormattedMessage().contains("persistence failed")); @@ -220,7 +220,7 @@ public void onTaskFinalized(String taskId) { "Error should contain specific task ID: " + error.getMessage()); // Assert: Verify specific taskId appears in logs - boolean foundTaskIdInLog = logAppender.list.stream() + boolean foundTaskIdInLog = snapshotLogs().stream() .anyMatch(event -> event.getFormattedMessage().contains(specificTaskId)); assertTrue(foundTaskIdInLog, "Logs should contain specific task ID"); } @@ -236,6 +236,18 @@ private Task createTestTask() { .build(); } + /** + * Thread-safe snapshot of the log appender's current list. + * + *

                logAppender.doAppend() is synchronized(logAppender), so iterating + * logAppender.list without the same lock races with the processor thread. + */ + private List snapshotLogs() { + synchronized (logAppender) { + return List.copyOf(logAppender.list); + } + } + /** * Helper method to enqueue an event and capture what gets distributed to clients. * Uses MainEventBusProcessorCallback to wait for async processing.